while not 100% complete (sv is still referred to as well as r_skyname), the

progs engine no longer refers to any global vars. This alows for multiple progs
being loaded (NOTE: NOT multiple mods, but (eg) for various protocol
extensions) and, once the last couple of issues are taken care of, CSQC.
This commit is contained in:
Bill Currie 2000-12-31 07:43:09 +00:00
parent 76a11bd74a
commit b6c832d900
17 changed files with 1106 additions and 1200 deletions

View file

@ -63,83 +63,69 @@ typedef struct edict_s
} edict_t;
#define EDICT_FROM_AREA(l) STRUCT_FROM_LINK(l,edict_t,area)
//============================================================================
extern dprograms_t *progs;
extern dfunction_t *pr_functions;
extern char *pr_strings;
extern ddef_t *pr_globaldefs;
extern ddef_t *pr_fielddefs;
extern dstatement_t *pr_statements;
extern globalvars_t *pr_global_struct;
extern float *pr_globals; // same as pr_global_struct
extern int pr_edict_size; // in bytes
extern int pr_edictareasize; // LordHavoc: for bounds checking
struct progs_s;
//============================================================================
void PR_Init (void);
void PR_ExecuteProgram (func_t fnum);
void PR_LoadProgs (void);
void PR_ExecuteProgram (struct progs_s *pr, func_t fnum);
void PR_LoadProgs (struct progs_s *pr);
void PR_Profile_f (void);
edict_t *ED_Alloc (void);
void ED_Free (edict_t *ed);
edict_t *ED_Alloc (struct progs_s *pr);
void ED_Free (struct progs_s *pr, edict_t *ed);
char *ED_NewString (char *string);
char *ED_NewString (struct progs_s *pr, char *string);
// returns a copy of the string allocated from the server's string heap
void ED_Print (edict_t *ed);
void ED_Write (QFile *f, edict_t *ed);
char *ED_ParseEdict (char *data, edict_t *ent);
void ED_Print (struct progs_s *pr, edict_t *ed);
void ED_Write (struct progs_s *pr, QFile *f, edict_t *ed);
char *ED_ParseEdict (struct progs_s *pr, char *data, edict_t *ent);
void ED_WriteGlobals (QFile *f);
void ED_ParseGlobals (char *data);
void ED_WriteGlobals (struct progs_s *pr, QFile *f);
void ED_ParseGlobals (struct progs_s *pr, char *data);
void ED_LoadFromFile (char *data);
void ED_LoadFromFile (struct progs_s *pr, char *data);
ddef_t *ED_FindField (char *name);
ddef_t *ED_FindField (struct progs_s *pr, char *name);
dfunction_t *ED_FindFunction (struct progs_s *pr, char *name);
//define EDICT_NUM(n) ((edict_t *)(sv.edicts+ (n)*pr_edict_size))
//define NUM_FOR_EDICT(e) (((byte *)(e) - sv.edicts)/pr_edict_size)
edict_t *EDICT_NUM(int n);
int NUM_FOR_EDICT(edict_t *e);
//define EDICT_NUM(p,n) ((edict_t *)(sv.edicts+ (n)*(p)->pr_edict_size))
//define NUM_FOR_EDICT(p,e) (((byte *)(e) - sv.edicts)/(p)->pr_edict_size)
#define NEXT_EDICT(e) ((edict_t *)( (byte *)e + pr_edict_size))
edict_t *EDICT_NUM(struct progs_s *pr, int n);
int NUM_FOR_EDICT(struct progs_s *pr, edict_t *e);
#define NEXT_EDICT(p,e) ((edict_t *)( (byte *)e + (p)->pr_edict_size))
#define EDICT_TO_PROG(e) ((byte *)e - (byte *)sv.edicts)
#define PROG_TO_EDICT(e) ((edict_t *)((byte *)sv.edicts + e))
//============================================================================
#define G_FLOAT(o) (pr_globals[o])
#define G_INT(o) (*(int *)&pr_globals[o])
#define G_EDICT(o) ((edict_t *)((byte *)sv.edicts+ *(int *)&pr_globals[o]))
#define G_EDICTNUM(o) NUM_FOR_EDICT(G_EDICT(o))
#define G_VECTOR(o) (&pr_globals[o])
#define G_STRING(o) (PR_GetString(*(string_t *)&pr_globals[o]))
#define G_FUNCTION(o) (*(func_t *)&pr_globals[o])
#define G_FLOAT(p,o) ((p)->pr_globals[o])
#define G_INT(p,o) (*(int *)&(p)->pr_globals[o])
#define G_EDICT(p,o) ((edict_t *)((byte *)sv.edicts+ *(int *)&(p)->pr_globals[o]))
#define G_EDICTNUM(p,o) NUM_FOR_EDICT(p,G_EDICT(p, o))
#define G_VECTOR(p,o) (&(p)->pr_globals[o])
#define G_STRING(p,o) (PR_GetString(pr,*(string_t *)&(p)->pr_globals[o]))
#define G_FUNCTION(p,o) (*(func_t *)&(p)->pr_globals[o])
#define E_FLOAT(e,o) (((float*)&e->v)[o])
#define E_INT(e,o) (*(int *)&((float*)&e->v)[o])
#define E_VECTOR(e,o) (&((float*)&e->v)[o])
#define E_STRING(e,o) (PR_GetString(*(string_t *)&((float*)&e->v)[o]))
#define E_STRING(e,o) (PR_GetString(pr,*(string_t *)&((float*)&e->v)[o]))
extern int type_size[8];
typedef void (*builtin_t) (void);
typedef void (*builtin_t) (struct progs_s *pr);
extern builtin_t *pr_builtins;
extern int pr_numbuiltins;
extern int pr_argc;
extern qboolean pr_trace;
extern dfunction_t *pr_xfunction;
extern int pr_xstatement;
int FindFieldOffset (struct progs_s *pr, char *field);
extern func_t EndFrame; // 2000-01-02 EndFrame function by Maddes/FrikaC
@ -147,22 +133,58 @@ extern func_t SpectatorConnect;
extern func_t SpectatorThink;
extern func_t SpectatorDisconnect;
void PR_RunError (char *error, ...) __attribute__((format(printf,1,2)));
void PR_RunError (struct progs_s *pr, char *error, ...) __attribute__((format(printf,2,3)));
void ED_PrintEdicts (void);
void ED_PrintNum (int ent);
void ED_PrintEdicts (struct progs_s *pr);
void ED_PrintNum (struct progs_s *pr, int ent);
eval_t *GetEdictFieldValue(edict_t *ed, char *field);
eval_t *GetEdictFieldValue(struct progs_s *pr, edict_t *ed, char *field);
//
// PR STrings stuff
//
#define MAX_PRSTR 1024
extern char *pr_strtbl[MAX_PRSTR];
extern int num_prstr;
char *PR_GetString(struct progs_s *pr, int num);
int PR_SetString(struct progs_s *pr, char *s);
char *PR_GetString(int num);
int PR_SetString(char *s);
//============================================================================
#define MAX_STACK_DEPTH 32
#define LOCALSTACK_SIZE 2048
typedef struct {
int s;
dfunction_t *f;
} prstack_t;
typedef struct progs_s {
dprograms_t *progs;
dfunction_t *pr_functions;
char *pr_strings;
ddef_t *pr_globaldefs;
ddef_t *pr_fielddefs;
dstatement_t *pr_statements;
globalvars_t *pr_global_struct;
float *pr_globals; // same as pr_global_struct
int pr_edict_size; // in bytes
int pr_edictareasize; // LordHavoc: for bounds checking
int pr_argc;
qboolean pr_trace;
dfunction_t *pr_xfunction;
int pr_xstatement;
char *pr_strtbl[MAX_PRSTR];
int num_prstr;
prstack_t pr_stack[MAX_STACK_DEPTH];
int pr_depth;
int localstack[LOCALSTACK_SIZE];
int localstack_used;
} progs_t;
#endif // _PROGS_H

View file

@ -397,6 +397,8 @@ extern QFile *sv_fraglogfile;
extern double sv_frametime;
extern progs_t sv_progs;
//===========================================================
// FIXME: declare exported functions in their own relevant .h
@ -423,7 +425,8 @@ qboolean SV_movestep (edict_t *ent, vec3_t move, qboolean relink);
void SV_WriteClientdataToMessage (client_t *client, sizebuf_t *msg);
void SV_MoveToGoal (void);
struct progs_s;
void SV_MoveToGoal (struct progs_s *pr);
void SV_SaveSpawnparms (void);

View file

@ -69,7 +69,7 @@ endif
server_SOURCES= pr_cmds.c pr_edict.c pr_exec.c pr_offs.c sv_ccmds.c sv_cvar.c \
sv_ents.c sv_init.c sv_main.c sv_misc.c sv_model.c \
sv_move.c sv_nchan.c sv_phys.c sv_send.c sv_user.c \
sv_move.c sv_nchan.c sv_phys.c sv_progs.c sv_send.c sv_user.c \
ver_check.c world.c $(world_ASM)
qf_server_SOURCES= $(common_SOURCES) $(server_SOURCES)

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -38,27 +38,6 @@
#include "server.h"
#include "sys.h"
typedef struct {
int s;
dfunction_t *f;
} prstack_t;
#define MAX_STACK_DEPTH 32
prstack_t pr_stack[MAX_STACK_DEPTH];
int pr_depth;
#define LOCALSTACK_SIZE 2048
int localstack[LOCALSTACK_SIZE];
int localstack_used;
qboolean pr_trace;
dfunction_t *pr_xfunction;
int pr_xstatement;
int pr_argc;
char *pr_opnames[] = {
"DONE",
@ -157,7 +136,7 @@ char *PR_GlobalStringNoContents (int ofs);
PR_PrintStatement
*/
void
PR_PrintStatement (dstatement_t *s)
PR_PrintStatement (progs_t *pr, dstatement_t *s)
{
int i;
@ -192,34 +171,34 @@ PR_PrintStatement (dstatement_t *s)
PR_StackTrace
*/
void
PR_StackTrace (void)
PR_StackTrace (progs_t *pr)
{
dfunction_t *f;
int i;
if (pr_depth == 0) {
if (pr->pr_depth == 0) {
Con_Printf ("<NO STACK>\n");
return;
}
pr_stack[pr_depth].f = pr_xfunction;
for (i = pr_depth; i >= 0; i--) {
f = pr_stack[i].f;
pr->pr_stack[pr->pr_depth].f = pr->pr_xfunction;
for (i = pr->pr_depth; i >= 0; i--) {
f = pr->pr_stack[i].f;
if (!f) {
Con_Printf ("<NO FUNCTION>\n");
} else
Con_Printf ("%12s : %s\n", PR_GetString (f->s_file),
PR_GetString (f->s_name));
Con_Printf ("%12s : %s\n", PR_GetString (pr, f->s_file),
PR_GetString (pr, f->s_name));
}
}
/*
PR_Profile_f
PR_Profile
*/
void
PR_Profile_f (void)
PR_Profile (progs_t *pr)
{
dfunction_t *f, *best;
int max;
@ -230,8 +209,8 @@ PR_Profile_f (void)
do {
max = 0;
best = NULL;
for (i = 0; i < progs->numfunctions; i++) {
f = &pr_functions[i];
for (i = 0; i < pr->progs->numfunctions; i++) {
f = &pr->pr_functions[i];
if (f->profile > max) {
max = f->profile;
best = f;
@ -240,13 +219,18 @@ PR_Profile_f (void)
if (best) {
if (num < 10)
Con_Printf ("%7i %s\n", best->profile,
PR_GetString (best->s_name));
PR_GetString (pr, best->s_name));
num++;
best->profile = 0;
}
} while (best);
}
void
PR_Profile_f (void)
{
}
/*
PR_RunError
@ -254,7 +238,7 @@ PR_Profile_f (void)
Aborts the currently executing function
*/
void
PR_RunError (char *error, ...)
PR_RunError (progs_t *pr, char *error, ...)
{
va_list argptr;
char string[1024];
@ -263,11 +247,11 @@ PR_RunError (char *error, ...)
vsnprintf (string, sizeof (string), error, argptr);
va_end (argptr);
PR_PrintStatement (pr_statements + pr_xstatement);
PR_StackTrace ();
PR_PrintStatement (pr, pr->pr_statements + pr->pr_xstatement);
PR_StackTrace (pr);
Con_Printf ("%s\n", string);
pr_depth = 0; // dump the stack so SV_Error can
pr->pr_depth = 0; // dump the stack so SV_Error can
// shutdown functions
SV_Error ("Program error");
@ -285,36 +269,36 @@ PR_RunError (char *error, ...)
Returns the new program statement counter
*/
int
PR_EnterFunction (dfunction_t *f)
PR_EnterFunction (progs_t *pr, dfunction_t *f)
{
int i, j, c, o;
pr_stack[pr_depth].s = pr_xstatement;
pr_stack[pr_depth].f = pr_xfunction;
pr_depth++;
if (pr_depth >= MAX_STACK_DEPTH)
PR_RunError ("stack overflow");
pr->pr_stack[pr->pr_depth].s = pr->pr_xstatement;
pr->pr_stack[pr->pr_depth].f = pr->pr_xfunction;
pr->pr_depth++;
if (pr->pr_depth >= MAX_STACK_DEPTH)
PR_RunError (pr, "stack overflow");
// save off any locals that the new function steps on
c = f->locals;
if (localstack_used + c > LOCALSTACK_SIZE)
PR_RunError ("PR_ExecuteProgram: locals stack overflow\n");
if (pr->localstack_used + c > LOCALSTACK_SIZE)
PR_RunError (pr, "PR_ExecuteProgram: locals stack overflow\n");
for (i = 0; i < c; i++)
localstack[localstack_used + i] =
((int *) pr_globals)[f->parm_start + i];
localstack_used += c;
pr->localstack[pr->localstack_used + i] =
((int *) pr->pr_globals)[f->parm_start + i];
pr->localstack_used += c;
// copy parameters
o = f->parm_start;
for (i = 0; i < f->numparms; i++) {
for (j = 0; j < f->parm_size[i]; j++) {
((int *) pr_globals)[o] = ((int *) pr_globals)[OFS_PARM0 + i * 3 + j];
((int *) pr->pr_globals)[o] = ((int *) pr->pr_globals)[OFS_PARM0 + i * 3 + j];
o++;
}
}
pr_xfunction = f;
pr->pr_xfunction = f;
return f->first_statement - 1; // offset the s++
}
@ -322,28 +306,28 @@ PR_EnterFunction (dfunction_t *f)
PR_LeaveFunction
*/
int
PR_LeaveFunction (void)
PR_LeaveFunction (progs_t *pr)
{
int i, c;
if (pr_depth <= 0)
if (pr->pr_depth <= 0)
SV_Error ("prog stack underflow");
// restore locals from the stack
c = pr_xfunction->locals;
localstack_used -= c;
if (localstack_used < 0)
PR_RunError ("PR_ExecuteProgram: locals stack underflow\n");
c = pr->pr_xfunction->locals;
pr->localstack_used -= c;
if (pr->localstack_used < 0)
PR_RunError (pr, "PR_ExecuteProgram: locals stack underflow\n");
for (i = 0; i < c; i++)
((int *) pr_globals)[pr_xfunction->parm_start + i] =
localstack[localstack_used + i];
((int *) pr->pr_globals)[pr->pr_xfunction->parm_start + i] =
pr->localstack[pr->localstack_used + i];
// up stack
pr_depth--;
pr_xfunction = pr_stack[pr_depth].f;
return pr_stack[pr_depth].s;
pr->pr_depth--;
pr->pr_xfunction = pr->pr_stack[pr->pr_depth].f;
return pr->pr_stack[pr->pr_depth].s;
}
@ -351,14 +335,14 @@ PR_LeaveFunction (void)
PR_ExecuteProgram
*/
// LordHavoc: optimized
#define OPA ((eval_t *)&pr_globals[(unsigned short) st->a])
#define OPB ((eval_t *)&pr_globals[(unsigned short) st->b])
#define OPC ((eval_t *)&pr_globals[(unsigned short) st->c])
#define OPA ((eval_t *)&pr->pr_globals[(unsigned short) st->a])
#define OPB ((eval_t *)&pr->pr_globals[(unsigned short) st->b])
#define OPC ((eval_t *)&pr->pr_globals[(unsigned short) st->c])
extern cvar_t *pr_boundscheck;
void
PR_ExecuteProgram (func_t fnum)
PR_ExecuteProgram (progs_t *pr, func_t fnum)
{
dstatement_t *st;
dfunction_t *f, *newf;
@ -367,20 +351,20 @@ PR_ExecuteProgram (func_t fnum)
eval_t *ptr;
int profile, startprofile;
if (!fnum || fnum >= progs->numfunctions) {
if (pr_global_struct->self)
ED_Print (PROG_TO_EDICT (pr_global_struct->self));
if (!fnum || fnum >= pr->progs->numfunctions) {
if (pr->pr_global_struct->self)
ED_Print (pr, PROG_TO_EDICT (pr->pr_global_struct->self));
SV_Error ("PR_ExecuteProgram: NULL function");
}
f = &pr_functions[fnum];
f = &pr->pr_functions[fnum];
pr_trace = false;
pr->pr_trace = false;
// make a stack frame
exitdepth = pr_depth;
exitdepth = pr->pr_depth;
st = &pr_statements[PR_EnterFunction (f)];
st = &pr->pr_statements[PR_EnterFunction (pr, f)];
startprofile = profile = 0;
while (1) {
@ -388,12 +372,12 @@ PR_ExecuteProgram (func_t fnum)
if (++profile > 1000000) // LordHavoc: increased runaway loop
// limit 10x
{
pr_xstatement = st - pr_statements;
PR_RunError ("runaway loop error");
pr->pr_xstatement = st - pr->pr_statements;
PR_RunError (pr, "runaway loop error");
}
if (pr_trace)
PR_PrintStatement (st);
if (pr->pr_trace)
PR_PrintStatement (pr, st);
switch (st->op) {
case OP_ADD_F:
@ -466,7 +450,7 @@ PR_ExecuteProgram (func_t fnum)
&& !OPA->vector[2];
break;
case OP_NOT_S:
OPC->_float = !OPA->string || !*PR_GetString (OPA->string);
OPC->_float = !OPA->string || !*PR_GetString (pr, OPA->string);
break;
case OP_NOT_FNC:
OPC->_float = !OPA->function;
@ -484,8 +468,8 @@ PR_ExecuteProgram (func_t fnum)
break;
case OP_EQ_S:
OPC->_float =
!strcmp (PR_GetString (OPA->string),
PR_GetString (OPB->string));
!strcmp (PR_GetString (pr, OPA->string),
PR_GetString (pr, OPB->string));
break;
case OP_EQ_E:
OPC->_float = OPA->_int == OPB->_int;
@ -503,8 +487,8 @@ PR_ExecuteProgram (func_t fnum)
break;
case OP_NE_S:
OPC->_float =
strcmp (PR_GetString (OPA->string),
PR_GetString (OPB->string));
strcmp (PR_GetString (pr, OPA->string),
PR_GetString (pr, OPB->string));
break;
case OP_NE_E:
OPC->_float = OPA->_int != OPB->_int;
@ -533,18 +517,18 @@ PR_ExecuteProgram (func_t fnum)
case OP_STOREP_S:
case OP_STOREP_FNC: // pointers
if (pr_boundscheck->int_val
&& (OPB->_int < 0 || OPB->_int + 4 > pr_edictareasize)) {
pr_xstatement = st - pr_statements;
&& (OPB->_int < 0 || OPB->_int + 4 > pr->pr_edictareasize)) {
pr->pr_xstatement = st - pr->pr_statements;
PR_RunError
("Progs attempted to write to an out of bounds edict\n");
(pr, "Progs attempted to write to an out of bounds edict\n");
return;
}
if (pr_boundscheck->int_val && (OPB->_int % pr_edict_size <
if (pr_boundscheck->int_val && (OPB->_int % pr->pr_edict_size <
((byte *) & sv.edicts->v -
(byte *) sv.edicts))) {
pr_xstatement = st - pr_statements;
pr->pr_xstatement = st - pr->pr_statements;
PR_RunError
("Progs attempted to write to an engine edict field\n");
(pr, "Progs attempted to write to an engine edict field\n");
return;
}
ptr = (eval_t *) ((byte *) sv.edicts + OPB->_int);
@ -552,10 +536,10 @@ PR_ExecuteProgram (func_t fnum)
break;
case OP_STOREP_V:
if (pr_boundscheck->int_val
&& (OPB->_int < 0 || OPB->_int + 12 > pr_edictareasize)) {
pr_xstatement = st - pr_statements;
&& (OPB->_int < 0 || OPB->_int + 12 > pr->pr_edictareasize)) {
pr->pr_xstatement = st - pr->pr_statements;
PR_RunError
("Progs attempted to write to an out of bounds edict\n");
(pr, "Progs attempted to write to an out of bounds edict\n");
return;
}
ptr = (eval_t *) ((byte *) sv.edicts + OPB->_int);
@ -565,23 +549,23 @@ PR_ExecuteProgram (func_t fnum)
break;
case OP_ADDRESS:
if (pr_boundscheck->int_val
&& (OPA->edict < 0 || OPA->edict >= pr_edictareasize)) {
pr_xstatement = st - pr_statements;
&& (OPA->edict < 0 || OPA->edict >= pr->pr_edictareasize)) {
pr->pr_xstatement = st - pr->pr_statements;
PR_RunError
("Progs attempted to address an out of bounds edict\n");
(pr, "Progs attempted to address an out of bounds edict\n");
return;
}
if (pr_boundscheck->int_val
&& (OPA->edict == 0 && sv.state == ss_active)) {
pr_xstatement = st - pr_statements;
PR_RunError ("assignment to world entity");
pr->pr_xstatement = st - pr->pr_statements;
PR_RunError (pr, "assignment to world entity");
return;
}
if (pr_boundscheck->int_val
&& (OPB->_int < 0 || OPB->_int >= progs->entityfields)) {
pr_xstatement = st - pr_statements;
&& (OPB->_int < 0 || OPB->_int >= pr->progs->entityfields)) {
pr->pr_xstatement = st - pr->pr_statements;
PR_RunError
("Progs attempted to address an invalid field in an edict\n");
(pr, "Progs attempted to address an invalid field in an edict\n");
return;
}
ed = PROG_TO_EDICT (OPA->edict);
@ -594,17 +578,17 @@ PR_ExecuteProgram (func_t fnum)
case OP_LOAD_S:
case OP_LOAD_FNC:
if (pr_boundscheck->int_val
&& (OPA->edict < 0 || OPA->edict >= pr_edictareasize)) {
pr_xstatement = st - pr_statements;
&& (OPA->edict < 0 || OPA->edict >= pr->pr_edictareasize)) {
pr->pr_xstatement = st - pr->pr_statements;
PR_RunError
("Progs attempted to read an out of bounds edict number\n");
(pr, "Progs attempted to read an out of bounds edict number\n");
return;
}
if (pr_boundscheck->int_val
&& (OPB->_int < 0 || OPB->_int >= progs->entityfields)) {
pr_xstatement = st - pr_statements;
&& (OPB->_int < 0 || OPB->_int >= pr->progs->entityfields)) {
pr->pr_xstatement = st - pr->pr_statements;
PR_RunError
("Progs attempted to read an invalid field in an edict\n");
(pr, "Progs attempted to read an invalid field in an edict\n");
return;
}
ed = PROG_TO_EDICT (OPA->edict);
@ -612,17 +596,17 @@ PR_ExecuteProgram (func_t fnum)
break;
case OP_LOAD_V:
if (pr_boundscheck->int_val
&& (OPA->edict < 0 || OPA->edict >= pr_edictareasize)) {
pr_xstatement = st - pr_statements;
&& (OPA->edict < 0 || OPA->edict >= pr->pr_edictareasize)) {
pr->pr_xstatement = st - pr->pr_statements;
PR_RunError
("Progs attempted to read an out of bounds edict number\n");
(pr, "Progs attempted to read an out of bounds edict number\n");
return;
}
if (pr_boundscheck->int_val
&& (OPB->_int < 0 || OPB->_int + 2 >= progs->entityfields)) {
pr_xstatement = st - pr_statements;
&& (OPB->_int < 0 || OPB->_int + 2 >= pr->progs->entityfields)) {
pr->pr_xstatement = st - pr->pr_statements;
PR_RunError
("Progs attempted to read an invalid field in an edict\n");
(pr, "Progs attempted to read an invalid field in an edict\n");
return;
}
ed = PROG_TO_EDICT (OPA->edict);
@ -654,40 +638,40 @@ PR_ExecuteProgram (func_t fnum)
case OP_CALL6:
case OP_CALL7:
case OP_CALL8:
pr_xfunction->profile += profile - startprofile;
pr->pr_xfunction->profile += profile - startprofile;
startprofile = profile;
pr_xstatement = st - pr_statements;
pr_argc = st->op - OP_CALL0;
pr->pr_xstatement = st - pr->pr_statements;
pr->pr_argc = st->op - OP_CALL0;
if (!OPA->function)
PR_RunError ("NULL function");
newf = &pr_functions[OPA->function];
PR_RunError (pr, "NULL function");
newf = &pr->pr_functions[OPA->function];
if (newf->first_statement < 0) { // negative
// statements are
// built in functions
int i = -newf->first_statement;
if (i >= pr_numbuiltins)
PR_RunError ("Bad builtin call number");
pr_builtins[i] ();
PR_RunError (pr, "Bad builtin call number");
pr_builtins[i] (pr);
break;
}
st = &pr_statements[PR_EnterFunction (newf)];
st = &pr->pr_statements[PR_EnterFunction (pr, newf)];
break;
case OP_DONE:
case OP_RETURN:
pr_globals[OFS_RETURN] = pr_globals[(unsigned short) st->a];
pr_globals[OFS_RETURN + 1] =
pr_globals[(unsigned short) st->a + 1];
pr_globals[OFS_RETURN + 2] =
pr_globals[(unsigned short) st->a + 2];
st = &pr_statements[PR_LeaveFunction ()];
if (pr_depth == exitdepth)
pr->pr_globals[OFS_RETURN] = pr->pr_globals[(unsigned short) st->a];
pr->pr_globals[OFS_RETURN + 1] =
pr->pr_globals[(unsigned short) st->a + 1];
pr->pr_globals[OFS_RETURN + 2] =
pr->pr_globals[(unsigned short) st->a + 2];
st = &pr->pr_statements[PR_LeaveFunction (pr)];
if (pr->pr_depth == exitdepth)
return; // all done
break;
case OP_STATE:
ed = PROG_TO_EDICT (pr_global_struct->self);
ed->v.nextthink = pr_global_struct->time + 0.1;
ed = PROG_TO_EDICT (pr->pr_global_struct->self);
ed->v.nextthink = pr->pr_global_struct->time + 0.1;
ed->v.frame = OPA->_float;
ed->v.think = OPB->function;
break;
@ -847,18 +831,18 @@ PR_ExecuteProgram (func_t fnum)
break;
case OP_STOREP_I:
if (pr_boundscheck->int_val
&& (OPB->_int < 0 || OPB->_int + 4 > pr_edictareasize)) {
pr_xstatement = st - pr_statements;
&& (OPB->_int < 0 || OPB->_int + 4 > pr->pr_edictareasize)) {
pr->pr_xstatement = st - pr->pr_statements;
PR_RunError
("Progs attempted to write to an out of bounds edict\n");
(pr, "Progs attempted to write to an out of bounds edict\n");
return;
}
if (pr_boundscheck->int_val
&& (OPB->_int % pr_edict_size <
&& (OPB->_int % pr->pr_edict_size <
((byte *) & sv.edicts->v - (byte *) sv.edicts))) {
pr_xstatement = st - pr_statements;
pr->pr_xstatement = st - pr->pr_statements;
PR_RunError
("Progs attempted to write to an engine edict field\n");
(pr, "Progs attempted to write to an engine edict field\n");
return;
}
ptr = (eval_t *) ((byte *) sv.edicts + OPB->_int);
@ -866,17 +850,17 @@ PR_ExecuteProgram (func_t fnum)
break;
case OP_LOAD_I:
if (pr_boundscheck->int_val
&& (OPA->edict < 0 || OPA->edict >= pr_edictareasize)) {
pr_xstatement = st - pr_statements;
&& (OPA->edict < 0 || OPA->edict >= pr->pr_edictareasize)) {
pr->pr_xstatement = st - pr->pr_statements;
PR_RunError
("Progs attempted to read an out of bounds edict number\n");
(pr, "Progs attempted to read an out of bounds edict number\n");
return;
}
if (pr_boundscheck->int_val
&& (OPB->_int < 0 || OPB->_int >= progs->entityfields)) {
pr_xstatement = st - pr_statements;
&& (OPB->_int < 0 || OPB->_int >= pr->progs->entityfields)) {
pr->pr_xstatement = st - pr->pr_statements;
PR_RunError
("Progs attempted to read an invalid field in an edict\n");
(pr, "Progs attempted to read an invalid field in an edict\n");
return;
}
ed = PROG_TO_EDICT (OPA->edict);
@ -890,37 +874,37 @@ PR_ExecuteProgram (func_t fnum)
case OP_GSTOREP_S:
case OP_GSTOREP_FNC: // pointers
if (pr_boundscheck->int_val
&& (OPB->_int < 0 || OPB->_int >= pr_globaldefs)) {
pr_xstatement = st - pr_statements;
&& (OPB->_int < 0 || OPB->_int >= pr->pr_globaldefs)) {
pr->pr_xstatement = st - pr->pr_statements;
PR_RunError
("Progs attempted to write to an invalid indexed global\n");
(pr, "Progs attempted to write to an invalid indexed global\n");
return;
}
pr_globals[OPB->_int] = OPA->_float;
pr->pr_globals[OPB->_int] = OPA->_float;
break;
case OP_GSTOREP_V:
if (pr_boundscheck->int_val
&& (OPB->_int < 0 || OPB->_int + 2 >= pr_globaldefs)) {
pr_xstatement = st - pr_statements;
&& (OPB->_int < 0 || OPB->_int + 2 >= pr->pr_globaldefs)) {
pr->pr_xstatement = st - pr->pr_statements;
PR_RunError
("Progs attempted to write to an invalid indexed global\n");
(pr, "Progs attempted to write to an invalid indexed global\n");
return;
}
pr_globals[OPB->_int] = OPA->vector[0];
pr_globals[OPB->_int + 1] = OPA->vector[1];
pr_globals[OPB->_int + 2] = OPA->vector[2];
pr->pr_globals[OPB->_int] = OPA->vector[0];
pr->pr_globals[OPB->_int + 1] = OPA->vector[1];
pr->pr_globals[OPB->_int + 2] = OPA->vector[2];
break;
case OP_GADDRESS:
i = OPA->_int + (int) OPB->_float;
if (pr_boundscheck->int_val
&& (i < 0 || i >= pr_globaldefs)) {
pr_xstatement = st - pr_statements;
&& (i < 0 || i >= pr->pr_globaldefs)) {
pr->pr_xstatement = st - pr->pr_statements;
PR_RunError
("Progs attempted to address an out of bounds global\n");
(pr, "Progs attempted to address an out of bounds global\n");
return;
}
OPC->_float = pr_globals[i];
OPC->_float = pr->pr_globals[i];
break;
case OP_GLOAD_I:
@ -930,33 +914,33 @@ PR_ExecuteProgram (func_t fnum)
case OP_GLOAD_S:
case OP_GLOAD_FNC:
if (pr_boundscheck->int_val
&& (OPA->_int < 0 || OPA->_int >= pr_globaldefs)) {
pr_xstatement = st - pr_statements;
&& (OPA->_int < 0 || OPA->_int >= pr->pr_globaldefs)) {
pr->pr_xstatement = st - pr->pr_statements;
PR_RunError
("Progs attempted to read an invalid indexed global\n");
(pr, "Progs attempted to read an invalid indexed global\n");
return;
}
OPC->_float = pr_globals[OPA->_int];
OPC->_float = pr->pr_globals[OPA->_int];
break;
case OP_GLOAD_V:
if (pr_boundscheck->int_val
&& (OPA->_int < 0 || OPA->_int + 2 >= pr_globaldefs)) {
pr_xstatement = st - pr_statements;
&& (OPA->_int < 0 || OPA->_int + 2 >= pr->pr_globaldefs)) {
pr->pr_xstatement = st - pr->pr_statements;
PR_RunError
("Progs attempted to read an invalid indexed global\n");
(pr, "Progs attempted to read an invalid indexed global\n");
return;
}
OPC->vector[0] = pr_globals[OPA->_int];
OPC->vector[1] = pr_globals[OPA->_int + 1];
OPC->vector[2] = pr_globals[OPA->_int + 2];
OPC->vector[0] = pr->pr_globals[OPA->_int];
OPC->vector[1] = pr->pr_globals[OPA->_int + 1];
OPC->vector[2] = pr->pr_globals[OPA->_int + 2];
break;
case OP_BOUNDCHECK:
if (OPA->_int < 0 || OPA->_int >= st->b) {
pr_xstatement = st - pr_statements;
pr->pr_xstatement = st - pr->pr_statements;
PR_RunError
("Progs boundcheck failed at line number %d, value is < 0 or >= %d\n",
(pr, "Progs boundcheck failed at line number %d, value is < 0 or >= %d\n",
st->b, st->c);
return;
}
@ -964,41 +948,39 @@ PR_ExecuteProgram (func_t fnum)
*/
default:
pr_xstatement = st - pr_statements;
PR_RunError ("Bad opcode %i", st->op);
pr->pr_xstatement = st - pr->pr_statements;
PR_RunError (pr, "Bad opcode %i", st->op);
}
}
}
char *pr_strtbl[MAX_PRSTR];
int num_prstr;
char *
PR_GetString (int num)
PR_GetString (progs_t *pr, int num)
{
if (num < 0) {
// Con_DPrintf("GET:%d == %s\n", num, pr_strtbl[-num]);
return pr_strtbl[-num];
// Con_DPrintf("GET:%d == %s\n", num, pr->pr_strtbl[-num]);
return pr->pr_strtbl[-num];
}
return pr_strings + num;
return pr->pr_strings + num;
}
int
PR_SetString (char *s)
PR_SetString (progs_t *pr, char *s)
{
int i;
if (s - pr_strings < 0) {
for (i = 0; i <= num_prstr; i++)
if (pr_strtbl[i] == s)
if (s - pr->pr_strings < 0) {
for (i = 0; i <= pr->num_prstr; i++)
if (pr->pr_strtbl[i] == s)
break;
if (i < num_prstr)
if (i < pr->num_prstr)
return -i;
if (num_prstr == MAX_PRSTR - 1)
if (pr->num_prstr == MAX_PRSTR - 1)
Sys_Error ("MAX_PRSTR");
num_prstr++;
pr_strtbl[num_prstr] = s;
// Con_DPrintf("SET:%d == %s\n", -num_prstr, s);
return -num_prstr;
pr->num_prstr++;
pr->pr_strtbl[pr->num_prstr] = s;
// Con_DPrintf("SET:%d == %s\n", -pr->num_prstr, s);
return -pr->num_prstr;
}
return (int) (s - pr_strings);
return (int) (s - pr->pr_strings);
}

View file

@ -32,14 +32,12 @@
#include "progs.h"
int eval_alpha, eval_scale, eval_glowsize, eval_glowcolor, eval_colormod;
int
FindFieldOffset (char *field)
FindFieldOffset (progs_t *pr, char *field)
{
ddef_t *d;
d = ED_FindField (field);
d = ED_FindField (pr, field);
if (!d)
return 0;
@ -54,13 +52,3 @@ GETEDICTFIELDVALUE (edict_t *ed, int fieldoffset)
return (eval_t *) ((char *) &ed->v + fieldoffset);
}
void
FindEdictFieldOffsets (void)
{
eval_alpha = FindFieldOffset ("alpha");
eval_scale = FindFieldOffset ("scale");
eval_glowsize = FindFieldOffset ("glow_size");
eval_glowcolor = FindFieldOffset ("glow_color");
eval_colormod = FindFieldOffset ("colormod");
};

View file

@ -419,7 +419,7 @@ SV_Status_f (void)
Con_Printf ("net address : %s\n", NET_AdrToString (net_local_adr));
Con_Printf ("cpu utilization : %3i%%\n", (int) cpu);
Con_Printf ("avg response time: %i ms\n", (int) avg);
Con_Printf ("packets/frame : %5.2f (%d)\n", pak, num_prstr);
Con_Printf ("packets/frame : %5.2f (%d)\n", pak, sv_progs.num_prstr);
// min fps lat drp
if (sv_redirected != RD_NONE) {

View file

@ -373,7 +373,7 @@ SV_EmitPacketEntities (client_t *client, packet_entities_t *to, sizebuf_t *msg)
if (newnum < oldnum) { // this is a new entity, send it from
// the baseline
ent = EDICT_NUM (newnum);
ent = EDICT_NUM (&sv_progs, newnum);
//Con_Printf ("baseline %i\n", newnum);
SV_WriteDelta (&ent->baseline, &to->entities[newindex], msg, true,
client->stdver);
@ -550,10 +550,10 @@ SV_WriteEntitiesToClient (client_t *client, sizebuf_t *msg)
numnails = 0;
for (e = MAX_CLIENTS + 1, ent = EDICT_NUM (e); e < sv.num_edicts;
e++, ent = NEXT_EDICT (ent)) {
for (e = MAX_CLIENTS + 1, ent = EDICT_NUM (&sv_progs, e); e < sv.num_edicts;
e++, ent = NEXT_EDICT (&sv_progs, ent)) {
// ignore ents without visible models
if (!ent->v.modelindex || !*PR_GetString (ent->v.model))
if (!ent->v.modelindex || !*PR_GetString (&sv_progs, ent->v.model))
continue;
// ignore if not touching a PV leaf

View file

@ -110,7 +110,7 @@ SV_CreateBaseline (void)
int entnum;
for (entnum = 0; entnum < sv.num_edicts; entnum++) {
svent = EDICT_NUM (entnum);
svent = EDICT_NUM (&sv_progs, entnum);
if (svent->free)
continue;
// create baselines for all player slots,
@ -131,7 +131,7 @@ SV_CreateBaseline (void)
} else {
svent->baseline.colormap = 0;
svent->baseline.modelindex =
SV_ModelIndex (PR_GetString (svent->v.model));
SV_ModelIndex (PR_GetString (&sv_progs, svent->v.model));
}
// LordHavoc: setup baseline to include new effects
svent->baseline.alpha = 255;
@ -182,7 +182,7 @@ SV_SaveSpawnparms (void)
return; // no progs loaded yet
// serverflags is the only game related thing maintained
svs.serverflags = pr_global_struct->serverflags;
svs.serverflags = sv_progs.pr_global_struct->serverflags;
for (i = 0, host_client = svs.clients; i < MAX_CLIENTS; i++, host_client++) {
if (host_client->state != cs_spawned)
@ -192,10 +192,10 @@ SV_SaveSpawnparms (void)
host_client->state = cs_connected;
// call the progs to get default spawn parms for the new client
pr_global_struct->self = EDICT_TO_PROG (host_client->edict);
PR_ExecuteProgram (pr_global_struct->SetChangeParms);
sv_progs.pr_global_struct->self = EDICT_TO_PROG (host_client->edict);
PR_ExecuteProgram (&sv_progs, sv_progs.pr_global_struct->SetChangeParms);
for (j = 0; j < NUM_SPAWN_PARMS; j++)
host_client->spawn_parms[j] = (&pr_global_struct->parm1)[j];
host_client->spawn_parms[j] = (&sv_progs.pr_global_struct->parm1)[j];
}
}
@ -344,15 +344,15 @@ SV_SpawnServer (char *server)
// load progs to get entity field count
// which determines how big each edict is
PR_LoadProgs ();
PR_LoadProgs (&sv_progs);
// allocate edicts
sv.edicts = Hunk_AllocName (MAX_EDICTS * pr_edict_size, "edicts");
sv.edicts = Hunk_AllocName (MAX_EDICTS * sv_progs.pr_edict_size, "edicts");
// leave slots at start for clients only
sv.num_edicts = MAX_CLIENTS + 1;
for (i = 0; i < MAX_CLIENTS; i++) {
ent = EDICT_NUM (i + 1);
ent = EDICT_NUM (&sv_progs, i + 1);
svs.clients[i].edict = ent;
//ZOID - make sure we update frags right
svs.clients[i].old_frags = 0;
@ -370,9 +370,9 @@ SV_SpawnServer (char *server)
//
SV_ClearWorld ();
sv.sound_precache[0] = pr_strings;
sv.sound_precache[0] = sv_progs.pr_strings;
sv.model_precache[0] = pr_strings;
sv.model_precache[0] = sv_progs.pr_strings;
sv.model_precache[1] = sv.modelname;
sv.models[1] = sv.worldmodel;
for (i = 1; i < sv.worldmodel->numsubmodels; i++) {
@ -392,22 +392,22 @@ SV_SpawnServer (char *server)
// map initialization
sv.state = ss_loading;
ent = EDICT_NUM (0);
ent = EDICT_NUM (&sv_progs, 0);
ent->free = false;
ent->v.model = PR_SetString (sv.worldmodel->name);
ent->v.model = PR_SetString (&sv_progs, sv.worldmodel->name);
ent->v.modelindex = 1; // world model
ent->v.solid = SOLID_BSP;
ent->v.movetype = MOVETYPE_PUSH;
pr_global_struct->mapname = PR_SetString (sv.name);
sv_progs.pr_global_struct->mapname = PR_SetString (&sv_progs, sv.name);
// serverflags are for cross level information (sigils)
pr_global_struct->serverflags = svs.serverflags;
sv_progs.pr_global_struct->serverflags = svs.serverflags;
// run the frame start qc function to let progs check cvars
SV_ProgStartFrame ();
// load and spawn all other entities
ED_LoadFromFile (sv.worldmodel->entities);
ED_LoadFromFile (&sv_progs, sv.worldmodel->entities);
// look up some model indexes for specialized message compression
SV_FindModelNumbers ();

View file

@ -250,13 +250,13 @@ SV_DropClient (client_t *drop)
if (!drop->spectator) {
// call the prog function for removing a client
// this will set the body to a dead frame, among other things
pr_global_struct->self = EDICT_TO_PROG (drop->edict);
PR_ExecuteProgram (pr_global_struct->ClientDisconnect);
sv_progs.pr_global_struct->self = EDICT_TO_PROG (drop->edict);
PR_ExecuteProgram (&sv_progs, sv_progs.pr_global_struct->ClientDisconnect);
} else if (SpectatorDisconnect) {
// call the prog function for removing a client
// this will set the body to a dead frame, among other things
pr_global_struct->self = EDICT_TO_PROG (drop->edict);
PR_ExecuteProgram (SpectatorDisconnect);
sv_progs.pr_global_struct->self = EDICT_TO_PROG (drop->edict);
PR_ExecuteProgram (&sv_progs, SpectatorDisconnect);
}
}
if (drop->spectator)
@ -823,7 +823,7 @@ SVC_DirectConnect (void)
// spectator mode can ONLY be set at join time
newcl->spectator = spectator;
ent = EDICT_NUM (edictnum);
ent = EDICT_NUM (&sv_progs, edictnum);
newcl->edict = ent;
// parse some info from the info strings
@ -836,9 +836,9 @@ SVC_DirectConnect (void)
newcl->lockedtill = 0;
// call the progs to get default spawn parms for the new client
PR_ExecuteProgram (pr_global_struct->SetNewParms);
PR_ExecuteProgram (&sv_progs, sv_progs.pr_global_struct->SetNewParms);
for (i = 0; i < NUM_SPAWN_PARMS; i++)
newcl->spawn_parms[i] = (&pr_global_struct->parm1)[i];
newcl->spawn_parms[i] = (&sv_progs.pr_global_struct->parm1)[i];
if (newcl->spectator)
Con_Printf ("Spectator %s connected\n", newcl->name);

View file

@ -397,17 +397,17 @@ SV_MoveToGoal
======================
*/
void
SV_MoveToGoal (void)
SV_MoveToGoal (progs_t *pr)
{
edict_t *ent, *goal;
float dist;
ent = PROG_TO_EDICT (pr_global_struct->self);
ent = PROG_TO_EDICT (sv_progs.pr_global_struct->self);
goal = PROG_TO_EDICT (ent->v.goalentity);
dist = G_FLOAT (OFS_PARM0);
dist = G_FLOAT (&sv_progs, OFS_PARM0);
if (!((int) ent->v.flags & (FL_ONGROUND | FL_FLY | FL_SWIM))) {
G_FLOAT (OFS_RETURN) = 0;
G_FLOAT (&sv_progs, OFS_RETURN) = 0;
return;
}
// if the next step hits the enemy, return immediately

View file

@ -84,8 +84,8 @@ SV_CheckAllEnts (void)
edict_t *check;
// see if any solid entities are inside the final position
check = NEXT_EDICT (sv.edicts);
for (e = 1; e < sv.num_edicts; e++, check = NEXT_EDICT (check)) {
check = NEXT_EDICT (&sv_progs, sv.edicts);
for (e = 1; e < sv.num_edicts; e++, check = NEXT_EDICT (&sv_progs, check)) {
if (check->free)
continue;
if (check->v.movetype == MOVETYPE_PUSH
@ -116,12 +116,12 @@ SV_CheckVelocity (edict_t *ent)
for (i = 0; i < 3; i++) {
if (IS_NAN (ent->v.velocity[i])) {
Con_Printf ("Got a NaN velocity on %s\n",
PR_GetString (ent->v.classname));
PR_GetString (&sv_progs, ent->v.classname));
ent->v.velocity[i] = 0;
}
if (IS_NAN (ent->v.origin[i])) {
Con_Printf ("Got a NaN origin on %s\n",
PR_GetString (ent->v.classname));
PR_GetString (&sv_progs, ent->v.classname));
ent->v.origin[i] = 0;
}
}
@ -162,10 +162,10 @@ SV_RunThink (edict_t *ent)
// it is possible to start that way
// by a trigger with a local time.
ent->v.nextthink = 0;
pr_global_struct->time = thinktime;
pr_global_struct->self = EDICT_TO_PROG (ent);
pr_global_struct->other = EDICT_TO_PROG (sv.edicts);
PR_ExecuteProgram (ent->v.think);
sv_progs.pr_global_struct->time = thinktime;
sv_progs.pr_global_struct->self = EDICT_TO_PROG (ent);
sv_progs.pr_global_struct->other = EDICT_TO_PROG (sv.edicts);
PR_ExecuteProgram (&sv_progs, ent->v.think);
if (ent->free)
return false;
@ -186,24 +186,24 @@ SV_Impact (edict_t *e1, edict_t *e2)
{
int old_self, old_other;
old_self = pr_global_struct->self;
old_other = pr_global_struct->other;
old_self = sv_progs.pr_global_struct->self;
old_other = sv_progs.pr_global_struct->other;
pr_global_struct->time = sv.time;
sv_progs.pr_global_struct->time = sv.time;
if (e1->v.touch && e1->v.solid != SOLID_NOT) {
pr_global_struct->self = EDICT_TO_PROG (e1);
pr_global_struct->other = EDICT_TO_PROG (e2);
PR_ExecuteProgram (e1->v.touch);
sv_progs.pr_global_struct->self = EDICT_TO_PROG (e1);
sv_progs.pr_global_struct->other = EDICT_TO_PROG (e2);
PR_ExecuteProgram (&sv_progs, e1->v.touch);
}
if (e2->v.touch && e2->v.solid != SOLID_NOT) {
pr_global_struct->self = EDICT_TO_PROG (e2);
pr_global_struct->other = EDICT_TO_PROG (e1);
PR_ExecuteProgram (e2->v.touch);
sv_progs.pr_global_struct->self = EDICT_TO_PROG (e2);
sv_progs.pr_global_struct->other = EDICT_TO_PROG (e1);
PR_ExecuteProgram (&sv_progs, e2->v.touch);
}
pr_global_struct->self = old_self;
pr_global_struct->other = old_other;
sv_progs.pr_global_struct->self = old_self;
sv_progs.pr_global_struct->other = old_other;
}
@ -470,8 +470,8 @@ SV_Push (edict_t *pusher, vec3_t move)
// see if any solid entities are inside the final position
num_moved = 0;
check = NEXT_EDICT (sv.edicts);
for (e = 1; e < sv.num_edicts; e++, check = NEXT_EDICT (check)) {
check = NEXT_EDICT (&sv_progs, sv.edicts);
for (e = 1; e < sv.num_edicts; e++, check = NEXT_EDICT (&sv_progs, check)) {
if (check->free)
continue;
if (check->v.movetype == MOVETYPE_PUSH
@ -541,9 +541,9 @@ SV_Push (edict_t *pusher, vec3_t move)
// if the pusher has a "blocked" function, call it
// otherwise, just stay in place until the obstacle is gone
if (pusher->v.blocked) {
pr_global_struct->self = EDICT_TO_PROG (pusher);
pr_global_struct->other = EDICT_TO_PROG (check);
PR_ExecuteProgram (pusher->v.blocked);
sv_progs.pr_global_struct->self = EDICT_TO_PROG (pusher);
sv_progs.pr_global_struct->other = EDICT_TO_PROG (check);
PR_ExecuteProgram (&sv_progs, pusher->v.blocked);
}
// move back any entities we already moved
for (i = 0; i < num_moved; i++) {
@ -615,10 +615,10 @@ SV_Physics_Pusher (edict_t *ent)
if (thinktime > oldltime && thinktime <= ent->v.ltime) {
VectorCopy (ent->v.origin, oldorg);
ent->v.nextthink = 0;
pr_global_struct->time = sv.time;
pr_global_struct->self = EDICT_TO_PROG (ent);
pr_global_struct->other = EDICT_TO_PROG (sv.edicts);
PR_ExecuteProgram (ent->v.think);
sv_progs.pr_global_struct->time = sv.time;
sv_progs.pr_global_struct->self = EDICT_TO_PROG (ent);
sv_progs.pr_global_struct->other = EDICT_TO_PROG (sv.edicts);
PR_ExecuteProgram (&sv_progs, ent->v.think);
if (ent->free)
return;
VectorSubtract (ent->v.origin, oldorg, move);
@ -855,8 +855,8 @@ SV_PPushMove (edict_t *pusher, float movetime) // player push
oldsolid = pusher->v.solid;
check = NEXT_EDICT (sv.edicts);
for (e = 1; e < sv.num_edicts; e++, check = NEXT_EDICT (check)) {
check = NEXT_EDICT (&sv_progs, sv.edicts);
for (e = 1; e < sv.num_edicts; e++, check = NEXT_EDICT (&sv_progs, check)) {
if (check->free) // What entity?
continue;
@ -881,9 +881,9 @@ SV_PPushMove (edict_t *pusher, float movetime) // player push
// Stage 4: Yes, it must be. Fail the move.
VectorCopy (pusher->v.origin, pusher->v.oldorigin); // Revert
if (pusher->v.blocked) { // Blocked func?
pr_global_struct->self = EDICT_TO_PROG (pusher);
pr_global_struct->other = EDICT_TO_PROG (check);
PR_ExecuteProgram (pusher->v.blocked);
sv_progs.pr_global_struct->self = EDICT_TO_PROG (pusher);
sv_progs.pr_global_struct->other = EDICT_TO_PROG (check);
PR_ExecuteProgram (&sv_progs, pusher->v.blocked);
}
return;
@ -917,10 +917,10 @@ SV_Physics_PPusher (edict_t *ent)
if (thinktime > oldltime && thinktime <= ent->v.ltime) {
ent->v.nextthink = 0;
pr_global_struct->time = sv.time;
pr_global_struct->self = EDICT_TO_PROG (ent);
pr_global_struct->other = EDICT_TO_PROG (sv.edicts);
PR_ExecuteProgram (ent->v.think);
sv_progs.pr_global_struct->time = sv.time;
sv_progs.pr_global_struct->self = EDICT_TO_PROG (ent);
sv_progs.pr_global_struct->other = EDICT_TO_PROG (sv.edicts);
PR_ExecuteProgram (&sv_progs, ent->v.think);
if (ent->free)
return;
}
@ -932,10 +932,10 @@ void
SV_ProgStartFrame (void)
{
// let the progs know that a new frame has started
pr_global_struct->self = EDICT_TO_PROG (sv.edicts);
pr_global_struct->other = EDICT_TO_PROG (sv.edicts);
pr_global_struct->time = sv.time;
PR_ExecuteProgram (pr_global_struct->StartFrame);
sv_progs.pr_global_struct->self = EDICT_TO_PROG (sv.edicts);
sv_progs.pr_global_struct->other = EDICT_TO_PROG (sv.edicts);
sv_progs.pr_global_struct->time = sv.time;
PR_ExecuteProgram (&sv_progs, sv_progs.pr_global_struct->StartFrame);
}
/*
@ -989,11 +989,11 @@ SV_RunNewmis (void)
{
edict_t *ent;
if (!pr_global_struct->newmis)
if (!sv_progs.pr_global_struct->newmis)
return;
ent = PROG_TO_EDICT (pr_global_struct->newmis);
ent = PROG_TO_EDICT (sv_progs.pr_global_struct->newmis);
sv_frametime = 0.05;
pr_global_struct->newmis = 0;
sv_progs.pr_global_struct->newmis = 0;
SV_RunEntity (ent);
}
@ -1019,7 +1019,7 @@ SV_Physics (void)
sv_frametime = sv_maxtic->value;
old_time = realtime;
pr_global_struct->frametime = sv_frametime;
sv_progs.pr_global_struct->frametime = sv_frametime;
SV_ProgStartFrame ();
@ -1028,11 +1028,11 @@ SV_Physics (void)
// even the world gets a chance to think
//
ent = sv.edicts;
for (i = 0; i < sv.num_edicts; i++, ent = NEXT_EDICT (ent)) {
for (i = 0; i < sv.num_edicts; i++, ent = NEXT_EDICT (&sv_progs, ent)) {
if (ent->free)
continue;
if (pr_global_struct->force_retouch)
if (sv_progs.pr_global_struct->force_retouch)
SV_LinkEdict (ent, true); // force retouch even for stationary
if (i > 0 && i <= MAX_CLIENTS)
@ -1043,16 +1043,16 @@ SV_Physics (void)
SV_RunNewmis ();
}
if (pr_global_struct->force_retouch)
pr_global_struct->force_retouch--;
if (sv_progs.pr_global_struct->force_retouch)
sv_progs.pr_global_struct->force_retouch--;
// 2000-01-02 EndFrame function by Maddes/FrikaC start
if (EndFrame) {
// let the progs know that the frame has ended
pr_global_struct->self = EDICT_TO_PROG (sv.edicts);
pr_global_struct->other = EDICT_TO_PROG (sv.edicts);
pr_global_struct->time = sv.time;
PR_ExecuteProgram (EndFrame);
sv_progs.pr_global_struct->self = EDICT_TO_PROG (sv.edicts);
sv_progs.pr_global_struct->other = EDICT_TO_PROG (sv.edicts);
sv_progs.pr_global_struct->time = sv.time;
PR_ExecuteProgram (&sv_progs, EndFrame);
}
// 2000-01-02 EndFrame function by Maddes/FrikaC end
}

70
source/sv_progs.c Normal file
View file

@ -0,0 +1,70 @@
/*
sv_progs.c
Quick QuakeC server code
Copyright (C) 1996-1997 Id Software, Inc.
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$
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include "progs.h"
int eval_alpha, eval_scale, eval_glowsize, eval_glowcolor, eval_colormod;
progs_t sv_progs;
func_t EndFrame;
func_t SpectatorConnect;
func_t SpectatorDisconnect;
func_t SpectatorThink;
void
FindEdictFieldOffsets (progs_t *pr)
{
dfunction_t *f;
if (pr == &sv_progs) {
// Zoid, find the spectator functions
SpectatorConnect = SpectatorThink = SpectatorDisconnect = 0;
if ((f = ED_FindFunction (&sv_progs, "SpectatorConnect")) != NULL)
SpectatorConnect = (func_t) (f - sv_progs.pr_functions);
if ((f = ED_FindFunction (&sv_progs, "SpectatorThink")) != NULL)
SpectatorThink = (func_t) (f - sv_progs.pr_functions);
if ((f = ED_FindFunction (&sv_progs, "SpectatorDisconnect")) != NULL)
SpectatorDisconnect = (func_t) (f - sv_progs.pr_functions);
// 2000-01-02 EndFrame function by Maddes/FrikaC
EndFrame = 0;
if ((f = ED_FindFunction (&sv_progs, "EndFrame")) != NULL)
EndFrame = (func_t) (f - sv_progs.pr_functions);
eval_alpha = FindFieldOffset (&sv_progs, "alpha");
eval_scale = FindFieldOffset (&sv_progs, "scale");
eval_glowsize = FindFieldOffset (&sv_progs, "glow_size");
eval_glowcolor = FindFieldOffset (&sv_progs, "glow_color");
eval_colormod = FindFieldOffset (&sv_progs, "colormod");
}
};

View file

@ -422,7 +422,7 @@ SV_StartSound (edict_t *entity, int channel, char *sample, int volume,
return;
}
ent = NUM_FOR_EDICT (entity);
ent = NUM_FOR_EDICT (&sv_progs, entity);
if ((channel & 8) || !sv_phs->int_val) // no PHS flag
{
@ -572,7 +572,7 @@ SV_UpdateClientStats (client_t *client)
ent = svs.clients[client->spec_track - 1].edict;
stats[STAT_HEALTH] = ent->v.health;
stats[STAT_WEAPON] = SV_ModelIndex (PR_GetString (ent->v.weaponmodel));
stats[STAT_WEAPON] = SV_ModelIndex (PR_GetString (&sv_progs, ent->v.weaponmodel));
stats[STAT_AMMO] = ent->v.currentammo;
stats[STAT_ARMOR] = ent->v.armorvalue;
stats[STAT_SHELLS] = ent->v.ammo_shells;
@ -583,7 +583,7 @@ SV_UpdateClientStats (client_t *client)
stats[STAT_ACTIVEWEAPON] = ent->v.weapon;
// stuff the sigil bits into the high bits of items for sbar
stats[STAT_ITEMS] =
(int) ent->v.items | ((int) pr_global_struct->serverflags << 28);
(int) ent->v.items | ((int) sv_progs.pr_global_struct->serverflags << 28);
// Extensions to the QW 2.40 protocol for Mega2k --KB
stats[STAT_VIEWHEIGHT] = (int) ent->v.view_ofs[2];
@ -693,13 +693,13 @@ SV_UpdateToReliableMessages (void)
// maxspeed/entgravity changes
ent = host_client->edict;
val = GetEdictFieldValue (ent, "gravity");
val = GetEdictFieldValue (&sv_progs, ent, "gravity");
if (val && host_client->entgravity != val->_float) {
host_client->entgravity = val->_float;
ClientReliableWrite_Begin (host_client, svc_entgravity, 5);
ClientReliableWrite_Float (host_client, host_client->entgravity);
}
val = GetEdictFieldValue (ent, "maxspeed");
val = GetEdictFieldValue (&sv_progs, ent, "maxspeed");
if (val && host_client->maxspeed != val->_float) {
host_client->maxspeed = val->_float;
ClientReliableWrite_Begin (host_client, svc_maxspeed, 5);

View file

@ -129,14 +129,14 @@ SV_New_f (void)
MSG_WriteLong (&host_client->netchan.message, svs.spawncount);
MSG_WriteString (&host_client->netchan.message, gamedir);
playernum = NUM_FOR_EDICT (host_client->edict) - 1;
playernum = NUM_FOR_EDICT (&sv_progs, host_client->edict) - 1;
if (host_client->spectator)
playernum |= 128;
MSG_WriteByte (&host_client->netchan.message, playernum);
// send full levelname
MSG_WriteString (&host_client->netchan.message,
PR_GetString (sv.edicts->v.message));
PR_GetString (&sv_progs, sv.edicts->v.message));
// send the movevars
MSG_WriteFloat (&host_client->netchan.message, movevars.gravity);
@ -398,17 +398,17 @@ SV_Spawn_f (void)
// set up the edict
ent = host_client->edict;
memset (&ent->v, 0, progs->entityfields * 4);
ent->v.colormap = NUM_FOR_EDICT (ent);
memset (&ent->v, 0, sv_progs.progs->entityfields * 4);
ent->v.colormap = NUM_FOR_EDICT (&sv_progs, ent);
ent->v.team = 0; // FIXME
ent->v.netname = PR_SetString (host_client->name);
ent->v.netname = PR_SetString (&sv_progs, host_client->name);
host_client->entgravity = 1.0;
val = GetEdictFieldValue (ent, "gravity");
val = GetEdictFieldValue (&sv_progs, ent, "gravity");
if (val)
val->_float = 1.0;
host_client->maxspeed = sv_maxspeed->value;
val = GetEdictFieldValue (ent, "maxspeed");
val = GetEdictFieldValue (&sv_progs, ent, "maxspeed");
if (val)
val->_float = sv_maxspeed->value;
@ -419,19 +419,19 @@ SV_Spawn_f (void)
ClientReliableWrite_Begin (host_client, svc_updatestatlong, 6);
ClientReliableWrite_Byte (host_client, STAT_TOTALSECRETS);
ClientReliableWrite_Long (host_client, pr_global_struct->total_secrets);
ClientReliableWrite_Long (host_client, sv_progs.pr_global_struct->total_secrets);
ClientReliableWrite_Begin (host_client, svc_updatestatlong, 6);
ClientReliableWrite_Byte (host_client, STAT_TOTALMONSTERS);
ClientReliableWrite_Long (host_client, pr_global_struct->total_monsters);
ClientReliableWrite_Long (host_client, sv_progs.pr_global_struct->total_monsters);
ClientReliableWrite_Begin (host_client, svc_updatestatlong, 6);
ClientReliableWrite_Byte (host_client, STAT_SECRETS);
ClientReliableWrite_Long (host_client, pr_global_struct->found_secrets);
ClientReliableWrite_Long (host_client, sv_progs.pr_global_struct->found_secrets);
ClientReliableWrite_Begin (host_client, svc_updatestatlong, 6);
ClientReliableWrite_Byte (host_client, STAT_MONSTERS);
ClientReliableWrite_Long (host_client, pr_global_struct->killed_monsters);
ClientReliableWrite_Long (host_client, sv_progs.pr_global_struct->killed_monsters);
// get the client to check and download skins
// when that is completed, a begin command will be issued
@ -456,8 +456,8 @@ SV_SpawnSpectator (void)
// search for an info_playerstart to spawn the spectator at
for (i = MAX_CLIENTS - 1; i < sv.num_edicts; i++) {
e = EDICT_NUM (i);
if (!strcmp (PR_GetString (e->v.classname), "info_player_start")) {
e = EDICT_NUM (&sv_progs, i);
if (!strcmp (PR_GetString (&sv_progs, e->v.classname), "info_player_start")) {
VectorCopy (e->v.origin, sv_player->v.origin);
return;
}
@ -494,27 +494,27 @@ SV_Begin_f (void)
if (SpectatorConnect) {
// copy spawn parms out of the client_t
for (i = 0; i < NUM_SPAWN_PARMS; i++)
(&pr_global_struct->parm1)[i] = host_client->spawn_parms[i];
(&sv_progs.pr_global_struct->parm1)[i] = host_client->spawn_parms[i];
// call the spawn function
pr_global_struct->time = sv.time;
pr_global_struct->self = EDICT_TO_PROG (sv_player);
PR_ExecuteProgram (SpectatorConnect);
sv_progs.pr_global_struct->time = sv.time;
sv_progs.pr_global_struct->self = EDICT_TO_PROG (sv_player);
PR_ExecuteProgram (&sv_progs, SpectatorConnect);
}
} else {
// copy spawn parms out of the client_t
for (i = 0; i < NUM_SPAWN_PARMS; i++)
(&pr_global_struct->parm1)[i] = host_client->spawn_parms[i];
(&sv_progs.pr_global_struct->parm1)[i] = host_client->spawn_parms[i];
// call the spawn function
pr_global_struct->time = sv.time;
pr_global_struct->self = EDICT_TO_PROG (sv_player);
PR_ExecuteProgram (pr_global_struct->ClientConnect);
sv_progs.pr_global_struct->time = sv.time;
sv_progs.pr_global_struct->self = EDICT_TO_PROG (sv_player);
PR_ExecuteProgram (&sv_progs, sv_progs.pr_global_struct->ClientConnect);
// actually spawn the player
pr_global_struct->time = sv.time;
pr_global_struct->self = EDICT_TO_PROG (sv_player);
PR_ExecuteProgram (pr_global_struct->PutClientInServer);
sv_progs.pr_global_struct->time = sv.time;
sv_progs.pr_global_struct->self = EDICT_TO_PROG (sv_player);
PR_ExecuteProgram (&sv_progs, sv_progs.pr_global_struct->PutClientInServer);
}
// clear the net statistics, because connecting gives a bogus picture
@ -546,7 +546,7 @@ SV_Begin_f (void)
// in a state where it is expecting the client to correct the angle
// and it won't happen if the game was just loaded, so you wind up
// with a permanent head tilt
ent = EDICT_NUM (1 + (host_client - svs.clients));
ent = EDICT_NUM (&sv_progs, 1 + (host_client - svs.clients));
MSG_WriteByte (&host_client->netchan.message, svc_setangle);
for (i = 0; i < 2; i++)
MSG_WriteAngle (&host_client->netchan.message, ent->v.angles[i]);
@ -945,9 +945,9 @@ SV_Kill_f (void)
return;
}
pr_global_struct->time = sv.time;
pr_global_struct->self = EDICT_TO_PROG (sv_player);
PR_ExecuteProgram (pr_global_struct->ClientKill);
sv_progs.pr_global_struct->time = sv.time;
sv_progs.pr_global_struct->self = EDICT_TO_PROG (sv_player);
PR_ExecuteProgram (&sv_progs, sv_progs.pr_global_struct->ClientKill);
}
/*
@ -1052,8 +1052,8 @@ SV_PTrack_f (void)
if (Cmd_Argc () != 2) {
// turn off tracking
host_client->spec_track = 0;
ent = EDICT_NUM (host_client - svs.clients + 1);
tent = EDICT_NUM (0);
ent = EDICT_NUM (&sv_progs, host_client - svs.clients + 1);
tent = EDICT_NUM (&sv_progs, 0);
ent->v.goalentity = EDICT_TO_PROG (tent);
return;
}
@ -1063,15 +1063,15 @@ SV_PTrack_f (void)
svs.clients[i].spectator) {
SV_ClientPrintf (host_client, PRINT_HIGH, "Invalid client to track\n");
host_client->spec_track = 0;
ent = EDICT_NUM (host_client - svs.clients + 1);
tent = EDICT_NUM (0);
ent = EDICT_NUM (&sv_progs, host_client - svs.clients + 1);
tent = EDICT_NUM (&sv_progs, 0);
ent->v.goalentity = EDICT_TO_PROG (tent);
return;
}
host_client->spec_track = i + 1; // now tracking
ent = EDICT_NUM (host_client - svs.clients + 1);
tent = EDICT_NUM (i + 1);
ent = EDICT_NUM (&sv_progs, host_client - svs.clients + 1);
tent = EDICT_NUM (&sv_progs, i + 1);
ent->v.goalentity = EDICT_TO_PROG (tent);
}
@ -1350,7 +1350,7 @@ AddLinksToPmove (areanode_t *node)
pmove.numphysent++;
VectorCopy (check->v.origin, pe->origin);
pe->info = NUM_FOR_EDICT (check);
pe->info = NUM_FOR_EDICT (&sv_progs, check);
if (check->v.solid == SOLID_BSP) {
pe->model = sv.models[(int) (check->v.modelindex)];
@ -1391,8 +1391,8 @@ AddAllEntsToPmove (void)
int pl;
pl = EDICT_TO_PROG (sv_player);
check = NEXT_EDICT (sv.edicts);
for (e = 1; e < sv.num_edicts; e++, check = NEXT_EDICT (check)) {
check = NEXT_EDICT (&sv_progs, sv.edicts);
for (e = 1; e < sv.num_edicts; e++, check = NEXT_EDICT (&sv_progs, check)) {
if (check->free)
continue;
if (check->v.owner == pl)
@ -1531,11 +1531,11 @@ SV_RunCmd (usercmd_t *ucmd, qboolean inside)
sv_frametime = min (0.1, ucmd->msec * 0.001);
if (!host_client->spectator) {
pr_global_struct->frametime = sv_frametime;
sv_progs.pr_global_struct->frametime = sv_frametime;
pr_global_struct->time = sv.time;
pr_global_struct->self = EDICT_TO_PROG (sv_player);
PR_ExecuteProgram (pr_global_struct->PlayerPreThink);
sv_progs.pr_global_struct->time = sv.time;
sv_progs.pr_global_struct->self = EDICT_TO_PROG (sv_player);
PR_ExecuteProgram (&sv_progs, sv_progs.pr_global_struct->PlayerPreThink);
SV_RunThink (sv_player);
}
@ -1591,7 +1591,7 @@ SV_RunCmd (usercmd_t *ucmd, qboolean inside)
if (onground != -1) {
sv_player->v.flags = (int) sv_player->v.flags | FL_ONGROUND;
sv_player->v.groundentity =
EDICT_TO_PROG (EDICT_NUM (pmove.physents[onground].info));
EDICT_TO_PROG (EDICT_NUM (&sv_progs, pmove.physents[onground].info));
} else {
sv_player->v.flags = (int) sv_player->v.flags & ~FL_ONGROUND;
}
@ -1616,12 +1616,12 @@ SV_RunCmd (usercmd_t *ucmd, qboolean inside)
// touch other objects
for (i = 0; i < pmove.numtouch; i++) {
n = pmove.physents[pmove.touchindex[i]].info;
ent = EDICT_NUM (n);
ent = EDICT_NUM (&sv_progs, n);
if (!ent->v.touch || (playertouch[n / 8] & (1 << (n % 8))))
continue;
pr_global_struct->self = EDICT_TO_PROG (ent);
pr_global_struct->other = EDICT_TO_PROG (sv_player);
PR_ExecuteProgram (ent->v.touch);
sv_progs.pr_global_struct->self = EDICT_TO_PROG (ent);
sv_progs.pr_global_struct->other = EDICT_TO_PROG (sv_player);
PR_ExecuteProgram (&sv_progs, ent->v.touch);
playertouch[n / 8] |= 1 << (n % 8);
}
}
@ -1639,14 +1639,14 @@ SV_PostRunCmd (void)
// run post-think
if (!host_client->spectator) {
pr_global_struct->time = sv.time;
pr_global_struct->self = EDICT_TO_PROG (sv_player);
PR_ExecuteProgram (pr_global_struct->PlayerPostThink);
sv_progs.pr_global_struct->time = sv.time;
sv_progs.pr_global_struct->self = EDICT_TO_PROG (sv_player);
PR_ExecuteProgram (&sv_progs, sv_progs.pr_global_struct->PlayerPostThink);
SV_RunNewmis ();
} else if (SpectatorThink) {
pr_global_struct->time = sv.time;
pr_global_struct->self = EDICT_TO_PROG (sv_player);
PR_ExecuteProgram (SpectatorThink);
sv_progs.pr_global_struct->time = sv.time;
sv_progs.pr_global_struct->self = EDICT_TO_PROG (sv_player);
PR_ExecuteProgram (&sv_progs, SpectatorThink);
}
}

View file

@ -313,16 +313,16 @@ SV_TouchLinks (edict_t *ent, areanode_t *node)
|| ent->v.absmax[2] < touch->v.absmin[2])
continue;
old_self = pr_global_struct->self;
old_other = pr_global_struct->other;
old_self = sv_progs.pr_global_struct->self;
old_other = sv_progs.pr_global_struct->other;
pr_global_struct->self = EDICT_TO_PROG (touch);
pr_global_struct->other = EDICT_TO_PROG (ent);
pr_global_struct->time = sv.time;
PR_ExecuteProgram (touch->v.touch);
sv_progs.pr_global_struct->self = EDICT_TO_PROG (touch);
sv_progs.pr_global_struct->other = EDICT_TO_PROG (ent);
sv_progs.pr_global_struct->time = sv.time;
PR_ExecuteProgram (&sv_progs, touch->v.touch);
pr_global_struct->self = old_self;
pr_global_struct->other = old_other;
sv_progs.pr_global_struct->self = old_self;
sv_progs.pr_global_struct->other = old_other;
}
// recurse down both sides
@ -912,8 +912,8 @@ SV_TestPlayerPosition (edict_t *ent, vec3_t origin)
VectorAdd (origin, ent->v.mins, boxmins);
VectorAdd (origin, ent->v.maxs, boxmaxs);
check = NEXT_EDICT (sv.edicts);
for (e = 1; e < sv.num_edicts; e++, check = NEXT_EDICT (check)) {
check = NEXT_EDICT (&sv_progs, sv.edicts);
for (e = 1; e < sv.num_edicts; e++, check = NEXT_EDICT (&sv_progs, check)) {
if (check->free)
continue;
if (check->v.solid != SOLID_BSP &&