Added threads and callbacks to GIB, as well as several QW callbacks dealing

with player status.
This commit is contained in:
Brian Koropoff 2002-08-27 04:47:49 +00:00
parent 070aee9a0c
commit 98fc04e041
12 changed files with 299 additions and 35 deletions

View file

@ -3,10 +3,10 @@ SUBDIRS = GL plugin
includedir = $(prefix)/include/QF
include_HEADERS = bspfile.h cbuf.h cdaudio.h checksum.h clip_hull.h cmd.h \
console.h crc.h csqc.h cvar.h dstring.h draw.h gcc_attr.h gib_buffer.h \
gib_builtin.h gib_function.h gib_parse.h gib_process.h gib_vars.h hash.h hl.h \
idparse.h in_event.h info.h input.h joystick.h keys.h link.h locs.h \
mathlib.h mdfour.h model.h modelgen.h msg.h pak.h pakfile.h pcx.h \
plugin.h pr_comp.h pr_debug.h pr_obj.h progs.h qargs.h qdefs.h qendian.h \
qfplist.h qtypes.h render.h screen.h sizebuf.h skin.h sound.h \
spritegn.h sys.h teamplay.h texture.h tga.h uint32.h va.h ver_check.h \
vfile.h vfs.h vid.h wad.h zone.h
gib_builtin.h gib_function.h gib_parse.h gib_process.h gib_thread.h \
gib_vars.h hash.h hl.h idparse.h in_event.h info.h input.h joystick.h \
keys.h link.h locs.h mathlib.h mdfour.h model.h modelgen.h msg.h pak.h \
pakfile.h pcx.h plugin.h pr_comp.h pr_debug.h pr_obj.h progs.h qargs.h \
qdefs.h qendian.h qfplist.h qtypes.h render.h screen.h sizebuf.h skin.h \
sound.h spritegn.h sys.h teamplay.h texture.h tga.h uint32.h va.h \
ver_check.h vfile.h vfs.h vid.h wad.h zone.h

View file

@ -36,4 +36,4 @@ typedef struct gib_function_s {
void GIB_Function_Define (const char *name, const char *program);
gib_function_t *GIB_Function_Find (const char *name);
void GIB_Function_Execute (gib_function_t *func);
void GIB_Function_Execute (cbuf_t *cbuf, gib_function_t *func, cbuf_args_t *args);

43
include/QF/gib_thread.h Normal file
View file

@ -0,0 +1,43 @@
/*
#FILENAME#
#DESCRIPTION#
Copyright (C) 2002 #AUTHOR#
Author: #AUTHOR#
Date: #DATE#
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to:
Free Software Foundation, Inc.
59 Temple Place - Suite 330
Boston, MA 02111-1307, USA
$Id$
*/
typedef struct gib_thread_s {
unsigned long int id;
struct cbuf_s *cbuf;
struct gib_thread_s *next,*prev;
} gib_thread_t;
void GIB_Thread_Add (gib_thread_t *thread);
void GIB_Thread_Remove (gib_thread_t *thread);
gib_thread_t *GIB_Thread_Find (unsigned long int id);
gib_thread_t *GIB_Thread_New (void);
void GIB_Thread_Execute (void);
void GIB_Thread_Callback (const char *func, unsigned int argc, ...);

View file

@ -28,9 +28,9 @@ libQFutil_la_DEPENDENCIES= libasm.la
libQFutil_la_SOURCES= \
bspfile.c buildnum.c cbuf.c checksum.c cmd.c crc.c cvar.c dstring.c \
exp.c fendian.c getopt.c getopt1.c gib_buffer.c gib_builtin.c \
gib_function.c gib_parse.c gib_process.c gib_vars.c hash.c idparse.c \
info.c link.c mathlib.c mdfour.c msg.c ops.c pakfile.c pcx.c plugin.c \
qargs.c qendian.c qfplist.c quakefs.c quakeio.c sizebuf.c string.c \
gib_function.c gib_parse.c gib_process.c gib_thread.c gib_vars.c hash.c \
idparse.c info.c link.c mathlib.c mdfour.c msg.c ops.c pakfile.c pcx.c \
plugin.c qargs.c qendian.c qfplist.c quakefs.c quakeio.c sizebuf.c string.c \
sys.c tga.c va.c ver_check.c wad.c zone.c \
$(fnmatch)

View file

@ -49,6 +49,7 @@ static const char rcsid[] =
#include "QF/gib_buffer.h"
#include "QF/gib_function.h"
#include "QF/gib_vars.h"
#include "QF/gib_thread.h"
hashtab_t *gib_builtins;
@ -334,8 +335,13 @@ GIB_Runexported_f (void)
Sys_Printf ("Error: No function found for exported command \"%s\".\n"
"This is most likely a bug, please report it to"
"The QuakeForge developers.", Cmd_Argv(0));
else
GIB_Function_Execute (f);
else {
cbuf_t *sub = Cbuf_New (&gib_interp);
GIB_Function_Execute (sub, f, cbuf_active->args);
cbuf_active->down = sub;
sub->up = cbuf_active;
cbuf_active->state = CBUF_STATE_STACK;
}
}
void
@ -377,6 +383,45 @@ GIB_String_Equal_f (void)
GIB_Return (va("%i", !strcmp(GIB_Argv(1), GIB_Argv(2))));
}
void
GIB_Thread_Create_f (void)
{
if (GIB_Argc() != 2)
Cbuf_Error ("syntax",
"thread.create: invalid syntax\n"
"usage: thread.create program");
else {
gib_thread_t *thread = GIB_Thread_New ();
Cbuf_AddText (thread->cbuf, GIB_Argv(1));
GIB_Thread_Add (thread);
GIB_Return (va("%lu", thread->id));
}
}
void
GIB_Thread_Kill_f (void)
{
if (GIB_Argc() != 2)
Cbuf_Error ("syntax",
"thread.kill: invalid syntax\n"
"usage: thread.kill id");
else {
gib_thread_t *thread;
cbuf_t *cur;
unsigned long int id = strtoul (GIB_Argv(1), 0, 10);
thread = GIB_Thread_Find (id);
if (!thread) {
Cbuf_Error ("thread", "thread.kill: thread %ul does not exist.", id);
return;
}
for (cur = thread->cbuf; cur; cur = cur->down) {
GIB_DATA(cur)->type = GIB_BUFFER_NORMAL;
dstring_clearstr (cur->line);
dstring_clearstr (cur->buf);
}
}
}
void
GIB_Builtin_Init (void)
{
@ -394,4 +439,6 @@ GIB_Builtin_Init (void)
GIB_Builtin_Add ("break", GIB_Break_f, GIB_BUILTIN_NORMAL);
GIB_Builtin_Add ("string.length", GIB_String_Length_f, GIB_BUILTIN_NORMAL);
GIB_Builtin_Add ("string.equal", GIB_String_Equal_f, GIB_BUILTIN_NORMAL);
GIB_Builtin_Add ("thread.create", GIB_Thread_Create_f, GIB_BUILTIN_NORMAL);
GIB_Builtin_Add ("thread.kill", GIB_Thread_Kill_f, GIB_BUILTIN_NORMAL);
}

View file

@ -37,6 +37,7 @@ static const char rcsid[] =
#include <stdlib.h>
#include "QF/sys.h"
#include "QF/dstring.h"
#include "QF/hash.h"
#include "QF/cbuf.h"
@ -123,26 +124,16 @@ GIB_Function_Find (const char *name)
/*
GIB_Function_Execute
Creates a new buffer on the current stack
and copies the program text of a function
into it. Also sets local variables on the
buffer for all arguments passed to the
function
Prepares a buffer to execute
a GIB function with certain arguments
*/
void
GIB_Function_Execute (gib_function_t *func)
GIB_Function_Execute (cbuf_t *cbuf, gib_function_t *func, cbuf_args_t *args)
{
cbuf_t *sub = Cbuf_New (&gib_interp);
int i;
Cbuf_AddText (sub, func->program->str);
if (cbuf_active->down)
Cbuf_DeleteStack (cbuf_active->down);
cbuf_active->down = sub;
sub->up = cbuf_active;
cbuf_active->state = CBUF_STATE_STACK;
for (i = 0; i < cbuf_active->args->argc; i++)
GIB_Var_Set_Local (sub, va("%i", i), cbuf_active->args->argv[i]->str);
GIB_Var_Set_Local (sub, "argc", va("%i", cbuf_active->args->argc));
Cbuf_AddText (cbuf, func->program->str);
for (i = 0; i < args->argc; i++)
GIB_Var_Set_Local (cbuf, va("%i", i), args->argv[i]->str);
GIB_Var_Set_Local (cbuf, "argc", va("%i", args->argc));
}

View file

@ -466,9 +466,13 @@ void GIB_Parse_Execute_Line (cbuf_t *cbuf)
if ((b = GIB_Builtin_Find (args->argv[0]->str)))
b->func ();
else if ((f = GIB_Function_Find (args->argv[0]->str)))
GIB_Function_Execute (f);
else if (args->argc == 3 && !strcmp (args->argv[1]->str, "=")) {
else if ((f = GIB_Function_Find (args->argv[0]->str))) {
cbuf_t *sub = Cbuf_New (&gib_interp);
GIB_Function_Execute (sub, f, cbuf_active->args);
cbuf_active->down = sub;
sub->up = cbuf_active;
cbuf_active->state = CBUF_STATE_STACK;
} else if (args->argc == 3 && !strcmp (args->argv[1]->str, "=")) {
// First, determine global versus local
int glob = 0;
char *c = 0;

143
libs/util/gib_thread.c Normal file
View file

@ -0,0 +1,143 @@
/*
#FILENAME#
#DESCRIPTION#
Copyright (C) 2002 #AUTHOR#
Author: #AUTHOR#
Date: #DATE#
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to:
Free Software Foundation, Inc.
59 Temple Place - Suite 330
Boston, MA 02111-1307, USA
*/
static const char rcsid[] =
"$Id$";
#include <stdlib.h>
#include <stdarg.h>
#include "QF/sys.h"
#include "QF/cbuf.h"
#include "QF/gib_parse.h"
#include "QF/gib_thread.h"
#include "QF/gib_function.h"
#include "QF/dstring.h"
gib_thread_t *gib_threads;
static unsigned long int nextid = 0;
void
GIB_Thread_Add (gib_thread_t *thread)
{
thread->prev = 0;
thread->next = gib_threads;
if (gib_threads)
gib_threads->prev = thread;
gib_threads = thread;
}
void
GIB_Thread_Remove (gib_thread_t *thread)
{
if (thread == gib_threads) {
gib_threads = gib_threads->next;
if (gib_threads)
gib_threads->prev = 0;
} else {
thread->prev->next = thread->next;
if (thread->next)
thread->next->prev = thread->prev;
}
}
gib_thread_t *
GIB_Thread_Find (unsigned long int id)
{
gib_thread_t *cur;
for (cur = gib_threads; cur; cur=cur->next)
if (cur->id == id)
return cur;
return 0;
}
gib_thread_t *
GIB_Thread_New (void)
{
gib_thread_t *new = calloc (1, sizeof(gib_thread_t));
new->cbuf = Cbuf_New (&gib_interp);
new->id = nextid;
nextid++;
return new;
}
void
GIB_Thread_Delete (gib_thread_t *thread)
{
Cbuf_DeleteStack (thread->cbuf);
free (thread);
}
void
GIB_Thread_Execute (void)
{
gib_thread_t *cur, *tmp;
if (!gib_threads)
return;
for (cur = gib_threads; cur->next; cur = cur->next);
for (; cur; cur = tmp) {
tmp = cur->prev;
if (!cur->cbuf->buf->str[0] && !cur->cbuf->down) {
GIB_Thread_Remove (cur);
GIB_Thread_Delete (cur);
} else
Cbuf_Execute_Stack (cur->cbuf);
}
}
void
GIB_Thread_Callback (const char *func, unsigned int argc, ...)
{
gib_function_t *f = GIB_Function_Find (func);
gib_thread_t *thread;
cbuf_args_t *args;
va_list ap;
unsigned int i;
if (!f)
return;
thread = GIB_Thread_New ();
args = Cbuf_ArgsNew ();
va_start (ap, argc);
Cbuf_ArgsAdd (args, func);
for (i = 0; i < argc; i++)
Cbuf_ArgsAdd (args, va_arg (ap, const char *));
va_end (ap);
GIB_Function_Execute (thread->cbuf, f, args);
GIB_Thread_Add (thread);
Cbuf_ArgsDelete (args);
}

View file

@ -50,6 +50,7 @@ static const char rcsid[] =
#include "QF/sys.h"
#include "QF/va.h"
#include "QF/vid.h"
#include "QF/gib_thread.h"
#include "buildnum.h"
#include "chase.h"
@ -605,6 +606,10 @@ _Host_Frame (float time)
IN_Commands ();
}
// process gib threads
GIB_Thread_Execute ();
// process console commands
cmd_source = src_command;
Cbuf_Execute_Stack (host_cbuf);

View file

@ -79,6 +79,7 @@ static const char rcsid[] =
#include "QF/va.h"
#include "QF/vfs.h"
#include "QF/vid.h"
#include "QF/gib_thread.h"
#include "bothdefs.h"
#include "buildnum.h"
@ -1531,6 +1532,10 @@ Host_Frame (float time)
// allow mouses or other external controllers to add commands
IN_Commands ();
// process gib threads
GIB_Thread_Execute ();
// process console commands
Cbuf_Execute_Stack (cl_cbuf);

View file

@ -57,6 +57,7 @@ static const char rcsid[] =
#include "QF/vfile.h"
#include "QF/dstring.h"
#include "QF/gib_vars.h"
#include "QF/gib_thread.h"
#include "bothdefs.h"
#include "cl_ents.h"
@ -775,7 +776,7 @@ CL_ParseModellist (void)
cl_playerindex = nummodels;
else if (!strcmp (cl.model_name[nummodels], "progs/flag.mdl"))
cl_flagindex = nummodels;
// for deadbodyfilter & gibfilter
// for deadbodyfilter & gib filter
else if (!strcmp (cl.model_name[nummodels], "progs/h_player.mdl"))
cl_h_playerindex = nummodels;
else if (!strcmp (cl.model_name[nummodels], "progs/gib1.mdl"))
@ -1055,7 +1056,8 @@ void
CL_SetStat (int stat, int value)
{
int j;
const char *arm;
unsigned int changed;
const char *arm, *cb;
if (stat < 0 || stat >= MAX_CL_STATS)
Host_Error ("CL_SetStat: %i is invalid", stat);
@ -1064,7 +1066,11 @@ CL_SetStat (int stat, int value)
switch (stat) {
case STAT_ITEMS:
changed = cl.stats[STAT_ITEMS] ^ value;
Sbar_Changed ();
if ((changed & IT_KEY1 || changed & IT_KEY2) &&
(cb = GIB_Var_Get_Global ("player.key.callback")))
GIB_Thread_Callback (cb, 0);
GIB_Var_Set_Global ("player.key.1", value & IT_KEY1 ? "1" : "0");
GIB_Var_Set_Global ("player.key.2", value & IT_KEY2 ? "1" : "0");
if (value & IT_ARMOR1)
@ -1076,6 +1082,9 @@ CL_SetStat (int stat, int value)
else
arm = "none";
GIB_Var_Set_Global ("player.armor.type", arm);
if ((changed & 127 || changed & IT_AXE) &&
(cb = GIB_Var_Get_Global ("player.weapon.callback")))
GIB_Thread_Callback (cb, 0);
GIB_Var_Set_Global ("player.weapon.1", value & IT_AXE ? "1" : "0");
for (j = 0; j < 7; j++)
GIB_Var_Set_Global (va("player.weapon.%i", j+2),
@ -1085,23 +1094,35 @@ CL_SetStat (int stat, int value)
cl.item_gettime[j] = cl.time;
break;
case STAT_HEALTH:
if ((cb = GIB_Var_Get_Global ("player.health.callback")))
GIB_Thread_Callback (cb, 1, va("%i", value));
GIB_Var_Set_Global ("player.health", va("%i", value));
if (value <= 0)
Team_Dead ();
break;
case STAT_ARMOR:
if ((cb = GIB_Var_Get_Global ("player.armor.callback")))
GIB_Thread_Callback (cb, 1, va("%i", value));
GIB_Var_Set_Global ("player.armor", va("%i", value));
break;
case STAT_SHELLS:
if ((cb = GIB_Var_Get_Global ("player.ammo.shells.callback")))
GIB_Thread_Callback (cb, 1, va("%i", value));
GIB_Var_Set_Global ("player.ammo.shells", va("%i", value));
break;
case STAT_NAILS:
if ((cb = GIB_Var_Get_Global ("player.ammo.nails.callback")))
GIB_Thread_Callback (cb, 1, va("%i", value));
GIB_Var_Set_Global ("player.ammo.nails", va("%i", value));
break;
case STAT_ROCKETS:
if ((cb = GIB_Var_Get_Global ("player.ammo.rockets.callback")))
GIB_Thread_Callback (cb, 1, va("%i", value));
GIB_Var_Set_Global ("player.ammo.rockets", va("%i", value));
break;
case STAT_CELLS:
if ((cb = GIB_Var_Get_Global ("player.ammo.cells.callback")))
GIB_Thread_Callback (cb, 1, va("%i", value));
GIB_Var_Set_Global ("player.ammo.cells", va("%i", value));
break;
}

View file

@ -63,6 +63,7 @@ static const char rcsid[] =
#include "QF/idparse.h"
#include "QF/gib_parse.h"
#include "QF/gib_buffer.h"
#include "QF/gib_thread.h"
#include "QF/cmd.h"
#include "QF/console.h"
#include "QF/cvar.h"
@ -1902,6 +1903,10 @@ SV_Frame (float time)
// check for commands typed to the host
SV_GetConsoleCommands ();
// process gib threads
GIB_Thread_Execute ();
// process console commands
Cbuf_Execute_Stack (sv_cbuf);