From 66fda1fddb5579bc3d46be9ea5e161d99659ea95 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 17 Jan 2013 14:11:54 +0900 Subject: [PATCH] Rewrite edict access. The server edict arrays are now stored outside of progs memory, only the entity data itself (ie data accessible to progs via ent.fld) is stored in progs memory. Many of the changes were due to code accessing edicts and entity fields directly rather than through the provided macros. --- include/QF/progs.h | 45 +++++++++++++++--------- libs/gamecode/pr_debug.c | 8 ++--- libs/gamecode/pr_edict.c | 20 +++++------ libs/gamecode/pr_exec.c | 62 +++++++++++++++++++++------------- libs/gamecode/pr_load.c | 34 ++++++++----------- libs/gamecode/pr_parse.c | 6 ++-- libs/ruamoko/pr_cmds.c | 6 ++-- nq/source/host_cmd.c | 4 +-- nq/source/sv_main.c | 2 +- nq/source/sv_progs.c | 38 ++++++++++++++------- qw/source/sv_progs.c | 58 +++++++++++++++++++------------ qw/source/sv_user.c | 2 +- tools/qfcc/source/qfprogs.c | 6 ++-- tools/qfcc/test/test-harness.c | 2 +- tools/qwaq/main.c | 2 +- tools/qwaq/qwaq.c | 2 +- 16 files changed, 173 insertions(+), 124 deletions(-) diff --git a/include/QF/progs.h b/include/QF/progs.h index 7c8bb3341..5f8661341 100644 --- a/include/QF/progs.h +++ b/include/QF/progs.h @@ -218,10 +218,11 @@ void PR_BoundsCheck (progs_t *pr, int addr, etype_t type); struct edict_s { qboolean free; + progs_t *pr; ///< progs owning this edict int entnum; ///< number of this entity + int edict; ///< offset of this entity in pr_edict_area float freetime; ///< sv.time when the object was freed void *edata; ///< external per-edict data - pr_type_t v[1]; ///< fields from progs }; // pr_edict.c @@ -252,18 +253,18 @@ struct plitem_s *ED_Parse (progs_t *pr, const char *data); void ED_LoadFromFile (progs_t *pr, const char *data); void ED_EntityParseFunction (progs_t *pr); -#define PR_edicts(p) ((byte *) *(p)->edicts) +#define PR_edicts(p) (*(p)->pr_edicts) -#define NEXT_EDICT(p,e) ((edict_t *) ((byte *) e + (p)->pr_edict_size)) -#define EDICT_TO_PROG(p,e) ((pr_int_t)(intptr_t)((byte *)(e) - PR_edicts (p))) -#define PROG_TO_EDICT(p,e) ((edict_t *) (PR_edicts (p) + (e))) +#define NEXT_EDICT(p,e) ((e) + 1) +#define EDICT_TO_PROG(p,e) ((e)->entnum * (p)->pr_edict_size) +#define PROG_TO_EDICT(p,e) (&PR_edicts(p)[(e) / (p)->pr_edict_size]) #define NUM_FOR_BAD_EDICT(p,e) ((e)->entnum) #ifndef PR_PARANOID_PROGS -# define EDICT_NUM(p,n) (PROG_TO_EDICT (p, (n) * (p)->pr_edict_size)) -# define NUM_FOR_EDICT(p,e) NUM_FOR_BAD_EDICT (p, e) +# define EDICT_NUM(p,n) (PR_edicts (p) + (n)) +# define NUM_FOR_EDICT(p,e) NUM_FOR_BAD_EDICT ((p), (e)) #else -# define EDICT_NUM(p,n) ED_EdictNum (p, n) -# define NUM_FOR_EDICT(p,e) ED_NumForEdict (p, e) +# define EDICT_NUM(p,n) ED_EdictNum ((p), (n)) +# define NUM_FOR_EDICT(p,e) ED_NumForEdict ((p), (e)) #endif //@} @@ -420,7 +421,7 @@ void PR_Undefined (progs_t *pr, const char *type, const char *name) __attribute_ \hideinitializer */ -#define G_EDICT(p,o) ((edict_t *)(PR_edicts (p) + G_INT (p, o))) +#define G_EDICT(p,o) PROG_TO_EDICT ((p), G_INT (p, o)) /** Access an entity global. @@ -610,7 +611,7 @@ void PR_Undefined (progs_t *pr, const char *type, const char *name) __attribute_ \hideinitializer */ -#define P_EDICT(p,n) ((edict_t *)(PR_edicts (p) + P_INT (p, n))) +#define P_EDICT(p,n) PROG_TO_EDICT ((p), P_INT (p, n)) /** Access an entity parameter. @@ -807,7 +808,7 @@ void PR_Undefined (progs_t *pr, const char *type, const char *name) __attribute_ \hideinitializer */ -#define RETURN_EDICT(p,e) (R_STRING (p) = EDICT_TO_PROG(p, e)) +#define RETURN_EDICT(p,e) (R_INT (p) = EDICT_TO_PROG(p, e)) /** Set the return value to the given C pointer. NULL is converted to 0. @@ -858,7 +859,18 @@ void PR_Undefined (progs_t *pr, const char *type, const char *name) __attribute_ \hideinitializer */ -#define E_var(e,o,t) ((e)->v[o].t##_var) +#define E_fld(e,o) ((e)->pr->pr_edict_area[(e)->edict + (o)]) + + +/** \internal + \param e pointer to the entity + \param o field offset into entity data space + \param t typename prefix (see pr_type_u) + \return lvalue of the appropriate type + + \hideinitializer +*/ +#define E_var(e,o,t) (E_fld (e,o).t##_var) /** Access a float entity field. Can be assigned to. @@ -1592,7 +1604,7 @@ struct progs_s { /// \name edicts //@{ - edict_t **edicts; + edict_t **pr_edicts; int max_edicts; int *num_edicts; int *reserved_edicts; ///< alloc will start at reserved_edicts+1 @@ -1600,8 +1612,9 @@ struct progs_s { void (*flush) (void); int (*prune_edict) (progs_t *pr, edict_t *ent); void (*free_edict) (progs_t *pr, edict_t *ent); - int pr_edict_size; ///< in bytes - int pr_edictareasize; ///< for bounds checking, starts at 0 + pr_type_t *pr_edict_area; + int pr_edict_size; ///< # of pr_type_t slots + int pr_edict_area_size; ///< for bounds checking, starts at 0 func_t edict_parse; //@} diff --git a/libs/gamecode/pr_debug.c b/libs/gamecode/pr_debug.c index 602a2cc15..3656c2d0f 100644 --- a/libs/gamecode/pr_debug.c +++ b/libs/gamecode/pr_debug.c @@ -160,7 +160,7 @@ parse_expression (progs_t *pr, const char *expr, int conditional) if (!field) goto error; d = *field; - expr_ptr = &ent->v[field->ofs]; + expr_ptr = &E_fld (ent, field->ofs); d.ofs = PR_SetPointer (pr, expr_ptr); } else if (isdigit ((byte) es->token->str[0])) { expr_ptr = PR_GetPointer (pr, strtol (es->token->str, 0, 0)); @@ -924,9 +924,9 @@ PR_PrintStatement (progs_t *pr, dstatement_t *s, int contents) parm_ind = pr->pr_globals[s->b].uinteger_var; if (parm_ind < pr->progs->entityfields && opval >= 0 - && opval < pr->pr_edictareasize) { + && opval < pr->pr_edict_area_size) { ed = PROG_TO_EDICT (pr, opval); - opval = &ed->v[parm_ind] - pr->pr_globals; + opval = &E_fld(ed, parm_ind) - pr->pr_globals; } if (!ed) { str = "bad entity.field"; @@ -1064,7 +1064,7 @@ ED_Print (progs_t *pr, edict_t *ed) && strchr ("xyz", name[strlen (name) -1])) continue; // skip _x, _y, _z vars - v = ed->v + d->ofs; + v = &E_fld(ed, d->ofs); // if the value is still all 0, skip the field type = d->type & ~DEF_SAVEGLOBAL; diff --git a/libs/gamecode/pr_edict.c b/libs/gamecode/pr_edict.c index 2241e3e9f..1e77dee66 100644 --- a/libs/gamecode/pr_edict.c +++ b/libs/gamecode/pr_edict.c @@ -66,13 +66,11 @@ ED_ClearEdict (progs_t *pr, edict_t *e, int val) if (NUM_FOR_EDICT (pr, e) < *pr->reserved_edicts) Sys_Printf ("clearing reserved edict %d\n", NUM_FOR_EDICT (pr, e)); for (i=0; i < pr->progs->entityfields; i++) - e->v[i].integer_var = val; + E_INT (e, i) = val; e->free = false; } /* - ED_Alloc - Either finds a free edict, or allocates a new one. Try to avoid reusing an entity that was recently freed, because it can cause the client to think the entity morphed into something else @@ -203,9 +201,9 @@ ED_Count (progs_t *pr) continue; } active++; - if (solid_def && ent->v[solid_def->ofs].float_var) + if (solid_def && E_FLOAT (ent, solid_def->ofs)) solid++; - if (model_def && ent->v[model_def->ofs].float_var) + if (model_def && E_FLOAT (ent, model_def->ofs)) models++; } @@ -219,12 +217,10 @@ ED_Count (progs_t *pr) edict_t * ED_EdictNum (progs_t *pr, pr_int_t n) { - pr_int_t offs = n * pr->pr_edict_size; - - if (offs < 0 || n >= pr->pr_edictareasize) + if (n < 0 || n >= *pr->num_edicts) PR_RunError (pr, "EDICT_NUM: bad number %d", n); - return PROG_TO_EDICT (pr, offs); + return PR_edicts(pr) + n; } pr_int_t @@ -234,9 +230,9 @@ ED_NumForEdict (progs_t *pr, edict_t *e) b = NUM_FOR_BAD_EDICT (pr, e); - if (b && (b < 0 || b >= *(pr)->num_edicts)) + if (b && (b < 0 || b >= *pr->num_edicts)) PR_RunError (pr, "NUM_FOR_EDICT: bad pointer %d %p %p", b, e, - *(pr)->edicts); + pr->pr_edicts); return b; } @@ -244,7 +240,7 @@ ED_NumForEdict (progs_t *pr, edict_t *e) qboolean PR_EdictValid (progs_t *pr, pr_int_t e) { - if (e < 0 || e >= pr->pr_edictareasize) + if (e < 0 || e >= pr->pr_edict_area_size) return false; if (e % pr->pr_edict_size) return false; diff --git a/libs/gamecode/pr_exec.c b/libs/gamecode/pr_exec.c index 24778dd74..1e995170b 100644 --- a/libs/gamecode/pr_exec.c +++ b/libs/gamecode/pr_exec.c @@ -355,9 +355,9 @@ VISIBLE void PR_ExecuteProgram (progs_t * pr, func_t fnum) { int exitdepth, profile, startprofile; + int fldofs; pr_uint_t pointer; dstatement_t *st; - edict_t *ed; pr_type_t *ptr; pr_type_t old_val = {0}, *watch = 0; @@ -642,7 +642,7 @@ PR_ExecuteProgram (progs_t * pr, func_t fnum) case OP_ADDRESS: if (pr_boundscheck->int_val) { if (OPA.entity_var < 0 - || OPA.entity_var >= pr->pr_edictareasize) + || OPA.entity_var >= pr->pr_edict_area_size) PR_RunError (pr, "Progs attempted to address an out " "of bounds edict"); if (OPA.entity_var == 0 && pr->null_bad) @@ -651,8 +651,8 @@ PR_ExecuteProgram (progs_t * pr, func_t fnum) PR_RunError (pr, "Progs attempted to address an " "invalid field in an edict"); } - ed = PROG_TO_EDICT (pr, OPA.entity_var); - OPC.integer_var = &ed->v[OPB.integer_var] - pr->pr_globals; + fldofs = OPA.entity_var + OPB.integer_var; + OPC.integer_var = &pr->pr_edict_area[fldofs] - pr->pr_globals; break; case OP_ADDRESS_VOID: case OP_ADDRESS_F: @@ -676,41 +676,41 @@ PR_ExecuteProgram (progs_t * pr, func_t fnum) case OP_LOAD_P: if (pr_boundscheck->int_val) { if (OPA.entity_var < 0 - || OPA.entity_var >= pr->pr_edictareasize) + || OPA.entity_var >= pr->pr_edict_area_size) PR_RunError (pr, "Progs attempted to read an out of " "bounds edict number"); if (OPB.uinteger_var >= pr->progs->entityfields) PR_RunError (pr, "Progs attempted to read an invalid " "field in an edict"); } - ed = PROG_TO_EDICT (pr, OPA.entity_var); - OPC.integer_var = ed->v[OPB.integer_var].integer_var; + fldofs = OPA.entity_var + OPB.integer_var; + OPC.integer_var = pr->pr_edict_area[fldofs].integer_var; break; case OP_LOAD_V: if (pr_boundscheck->int_val) { if (OPA.entity_var < 0 - || OPA.entity_var >= pr->pr_edictareasize) + || OPA.entity_var >= pr->pr_edict_area_size) PR_RunError (pr, "Progs attempted to read an out of " "bounds edict number"); if (OPB.uinteger_var + 2 >= pr->progs->entityfields) PR_RunError (pr, "Progs attempted to read an invalid " "field in an edict"); } - ed = PROG_TO_EDICT (pr, OPA.entity_var); - memcpy (&OPC, &ed->v[OPB.integer_var], 3 * sizeof (OPC)); + fldofs = OPA.entity_var + OPB.integer_var; + memcpy (&OPC, &pr->pr_edict_area[fldofs], 3 * sizeof (OPC)); break; case OP_LOAD_Q: if (pr_boundscheck->int_val) { if (OPA.entity_var < 0 - || OPA.entity_var >= pr->pr_edictareasize) + || OPA.entity_var >= pr->pr_edict_area_size) PR_RunError (pr, "Progs attempted to read an out of " "bounds edict number"); if (OPB.uinteger_var + 3 >= pr->progs->entityfields) PR_RunError (pr, "Progs attempted to read an invalid " "field in an edict"); } - ed = PROG_TO_EDICT (pr, OPA.entity_var); - memcpy (&OPC, &ed->v[OPB.integer_var], 3 * sizeof (OPC)); + fldofs = OPA.entity_var + OPB.integer_var; + memcpy (&OPC, &pr->pr_edict_area[fldofs], 4 * sizeof (OPC)); break; case OP_LOADB_F: @@ -965,18 +965,34 @@ op_call: } break; case OP_STATE: - ed = PROG_TO_EDICT (pr, *pr->globals.self); - ed->v[pr->fields.nextthink].float_var = *pr->globals.time + - 0.1; - ed->v[pr->fields.frame].float_var = OPA.float_var; - ed->v[pr->fields.think].func_var = OPB.func_var; + { + int self = *pr->globals.self; + int nextthink = pr->fields.nextthink; + int frame = pr->fields.frame; + int think = pr->fields.think; + fldofs = self + nextthink; + pr->pr_edict_area[fldofs].float_var = *pr->globals.time + + 0.1; + fldofs = self + frame; + pr->pr_edict_area[fldofs].float_var = OPA.float_var; + fldofs = self + think; + pr->pr_edict_area[fldofs].func_var = OPB.func_var; + } break; case OP_STATE_F: - ed = PROG_TO_EDICT (pr, *pr->globals.self); - ed->v[pr->fields.nextthink].float_var = *pr->globals.time + - OPC.float_var; - ed->v[pr->fields.frame].float_var = OPA.float_var; - ed->v[pr->fields.think].func_var = OPB.func_var; + { + int self = *pr->globals.self; + int nextthink = pr->fields.nextthink; + int frame = pr->fields.frame; + int think = pr->fields.think; + fldofs = self + nextthink; + pr->pr_edict_area[fldofs].float_var = *pr->globals.time + + OPC.float_var; + fldofs = self + frame; + pr->pr_edict_area[fldofs].float_var = OPA.float_var; + fldofs = self + think; + pr->pr_edict_area[fldofs].func_var = OPB.func_var; + } break; case OP_ADD_I: OPC.integer_var = OPA.integer_var + OPB.integer_var; diff --git a/libs/gamecode/pr_load.c b/libs/gamecode/pr_load.c index b32cf71c3..76a84e2a2 100644 --- a/libs/gamecode/pr_load.c +++ b/libs/gamecode/pr_load.c @@ -166,6 +166,16 @@ PR_LoadProgsFile (progs_t *pr, QFile *file, int size, int max_edicts, int zone) pr->progs_size += sizeof (void*) - 1; pr->progs_size &= ~(sizeof (void*) - 1); + // size of edict asked for by progs, but at least 1 + pr->pr_edict_size = max (1, progs.entityfields); + // round off to next highest multiple of 4 words + // this ensures that progs that try to align vectors and quaternions + // get what they want + pr->pr_edict_size += (4 - 1); + pr->pr_edict_size &= ~(4 - 1); + pr->pr_edict_area_size = max_edicts * pr->pr_edict_size; + pr->max_edicts = max_edicts; + // size of heap asked for by vm-subsystem pr->zone_size = zone; // round off to next highest whole word address (esp for Alpha) @@ -174,19 +184,8 @@ PR_LoadProgsFile (progs_t *pr, QFile *file, int size, int max_edicts, int zone) pr->zone_size += sizeof (void*) - 1; pr->zone_size &= ~(sizeof (void*) - 1); - // size of edict asked for by progs - pr->pr_edict_size = max (1, progs.entityfields) * 4; - // size of engine data - pr->pr_edict_size += sizeof (edict_t) - sizeof (pr_type_t); - // round off to next highest whole word address (esp for Alpha) - // this ensures that pointers in the engine data area are always - // properly aligned - pr->pr_edict_size += sizeof (void*) - 1; - pr->pr_edict_size &= ~(sizeof (void*) - 1); - pr->pr_edictareasize = max_edicts * pr->pr_edict_size; - pr->max_edicts = max_edicts; - - mem_size = pr->progs_size + pr->zone_size + pr->pr_edictareasize; + mem_size = pr->pr_edict_area_size * sizeof (pr_type_t); + mem_size += pr->progs_size + pr->zone_size; pr->progs = pr->allocate_progs_mem (pr, mem_size + 1); if (!pr->progs) return; @@ -198,13 +197,10 @@ PR_LoadProgsFile (progs_t *pr, QFile *file, int size, int max_edicts, int zone) CRC_ProcessBlock (base, &pr->crc, size - sizeof (progs)); base -= sizeof (progs); // offsets are from file start - if (pr->edicts) - *pr->edicts = (edict_t *)((byte *) pr->progs + pr->progs_size); - pr->zone = (memzone_t *)((byte *) pr->progs + pr->progs_size - + pr->pr_edictareasize); + pr->pr_edict_area = (pr_type_t *)((byte *) pr->progs + pr->progs_size); + pr->zone = (memzone_t *)(&pr->pr_edict_area[pr->pr_edict_area_size]); - pr->pr_functions = - (dfunction_t *) (base + pr->progs->ofs_functions); + pr->pr_functions = (dfunction_t *) (base + pr->progs->ofs_functions); pr->pr_strings = (char *) base + pr->progs->ofs_strings; pr->pr_stringsize = (char *) pr->zone + pr->zone_size - (char *) base; pr->pr_globaldefs = (ddef_t *) (base + pr->progs->ofs_globaldefs); diff --git a/libs/gamecode/pr_parse.c b/libs/gamecode/pr_parse.c index 758e2c4cc..e6900fce9 100644 --- a/libs/gamecode/pr_parse.c +++ b/libs/gamecode/pr_parse.c @@ -139,7 +139,7 @@ ED_EntityDict (progs_t *pr, edict_t *ed) if (name[strlen (name) - 2] == '_') continue; // skip _x, _y, _z vars - v = &ed->v[d->ofs]; + v = &E_fld (ed, d->ofs); // if the value is still all 0, skip the field type = d->type & ~DEF_SAVEGLOBAL; @@ -418,7 +418,7 @@ ED_InitEntity (progs_t *pr, plitem_t *entity, edict_t *ent) continue; } } else { - if (!ED_ParseEpair (pr, ent->v, field, value)) + if (!ED_ParseEpair (pr, &E_fld (ent, 0), field, value)) PR_Error (pr, "ED_InitEntity: parse error"); } init = 1; @@ -439,7 +439,7 @@ ED_SpawnEntities (progs_t *pr, plitem_t *entity_list) int count; const char *classname; dfunction_t *func; - pr_int_t max_edicts = pr->pr_edictareasize / pr->pr_edict_size; + pr_int_t max_edicts = pr->pr_edict_area_size / pr->pr_edict_size; max_edicts -= *pr->num_edicts; count = PL_A_NumObjects (entity_list); diff --git a/libs/ruamoko/pr_cmds.c b/libs/ruamoko/pr_cmds.c index 8352228d4..1ce9560d1 100644 --- a/libs/ruamoko/pr_cmds.c +++ b/libs/ruamoko/pr_cmds.c @@ -306,7 +306,7 @@ PF_Find (progs_t *pr) } } - RETURN_EDICT (pr, *pr->edicts); + RETURN_EDICT (pr, EDICT_NUM (pr, 0)); } /* @@ -401,7 +401,7 @@ PF_nextent (progs_t *pr) while (1) { i++; if (i == *pr->num_edicts) { - RETURN_EDICT (pr, *pr->edicts); + RETURN_EDICT (pr, EDICT_NUM (pr, 0)); return; } ent = EDICT_NUM (pr, i); @@ -601,7 +601,7 @@ PF_PR_SetField (progs_t *pr) R_INT (pr) = 0; if (field) - R_INT (pr) = ED_ParseEpair (pr, ent->v, field, value); + R_INT (pr) = ED_ParseEpair (pr, &E_fld (ent, 0), field, value); } static void diff --git a/nq/source/host_cmd.c b/nq/source/host_cmd.c index 4a819d66c..76e13fe0e 100644 --- a/nq/source/host_cmd.c +++ b/nq/source/host_cmd.c @@ -700,7 +700,7 @@ Host_Loadgame_f (void) plitem_t *entity = PL_ObjectAtIndex (list, entnum); edict_t *ent = EDICT_NUM (&sv_pr_state, entnum); - memset (&ent->v, 0, sv_pr_state.progs->entityfields * 4); + memset (&E_fld (ent, 0), 0, sv_pr_state.progs->entityfields * 4); ent->free = false; ED_InitEntity (&sv_pr_state, entity, ent); @@ -989,7 +989,7 @@ Host_Spawn_f (void) } else { // set up the edict ent = host_client->edict; - memset (&ent->v, 0, sv_pr_state.progs->entityfields * 4); + memset (&E_fld (ent, 0), 0, sv_pr_state.progs->entityfields * 4); SVfloat (ent, colormap) = NUM_FOR_EDICT (&sv_pr_state, ent); SVfloat (ent, team) = (host_client->colors & 15) + 1; SVstring (ent, netname) = PR_SetString (&sv_pr_state, diff --git a/nq/source/sv_main.c b/nq/source/sv_main.c index d06ec4543..acaccd765 100644 --- a/nq/source/sv_main.c +++ b/nq/source/sv_main.c @@ -1193,7 +1193,7 @@ SV_SpawnServer (const char *server) // load the rest of the entities ent = EDICT_NUM (&sv_pr_state, 0); - memset (&ent->v, 0, sv_pr_state.progs->entityfields * 4); + memset (&E_fld (ent, 0), 0, sv_pr_state.progs->entityfields * 4); ent->free = false; SVstring (ent, model) = PR_SetString (&sv_pr_state, sv.worldmodel->name); SVfloat (ent, modelindex) = 1; // world model diff --git a/nq/source/sv_progs.c b/nq/source/sv_progs.c index ca80ae190..6e0b5f7d1 100644 --- a/nq/source/sv_progs.c +++ b/nq/source/sv_progs.c @@ -51,6 +51,7 @@ sv_globals_t sv_globals; sv_funcs_t sv_funcs; sv_fields_t sv_fields; +edict_t sv_edicts[MAX_EDICTS]; sv_data_t sv_data[MAX_EDICTS]; cvar_t *sv_progs; @@ -448,12 +449,32 @@ resolve (progs_t *pr) return ret; } +static int +sv_init_edicts (progs_t *pr) +{ + int i; + + memset (sv_edicts, 0, sizeof (sv_edicts)); + memset (sv_data, 0, sizeof (sv_data)); + + // init the data field of the edicts + for (i = 0; i < sv.max_edicts; i++) { + edict_t *ent = EDICT_NUM (&sv_pr_state, i); + ent->pr = &sv_pr_state; + ent->entnum = i; + ent->edict = EDICT_TO_PROG (&sv_pr_state, ent); + ent->edata = &sv_data[i]; + SVdata (ent)->edict = ent; + } + + return 1; +} + void SV_LoadProgs (void) { const char *progs_name = "progs.dat"; const char *range; - int i; if (strequal (sv_progs_ext->string, "qf")) { sv_range = PR_RANGE_QF; @@ -475,27 +496,18 @@ SV_LoadProgs (void) if (*sv_progs->string) progs_name = sv_progs->string; + sv.edicts = sv_edicts; PR_LoadProgs (&sv_pr_state, progs_name, sv.max_edicts, sv_progs_zone->int_val * 1024); if (!sv_pr_state.progs) Host_Error ("SV_LoadProgs: couldn't load %s", progs_name); - - memset (sv_data, 0, sizeof (sv_data)); - - // init the data field of the edicts - for (i = 0; i < sv.max_edicts; i++) { - edict_t *ent = EDICT_NUM (&sv_pr_state, i); - ent->entnum = i; - ent->edata = &sv_data[i]; - SVdata (ent)->edict = ent; - } } void SV_Progs_Init (void) { pr_gametype = "netquake"; - sv_pr_state.edicts = &sv.edicts; + sv_pr_state.pr_edicts = &sv.edicts; sv_pr_state.num_edicts = &sv.num_edicts; sv_pr_state.reserved_edicts = &svs.maxclients; sv_pr_state.unlink = SV_UnlinkEdict; @@ -504,6 +516,8 @@ SV_Progs_Init (void) sv_pr_state.bi_map = bi_map; sv_pr_state.resolve = resolve; + PR_AddLoadFunc (&sv_pr_state, sv_init_edicts); + SV_PR_Cmds_Init (); Cmd_AddCommand ("edict", ED_PrintEdict_f, "Report information on a given " diff --git a/qw/source/sv_progs.c b/qw/source/sv_progs.c index e11805c17..048961186 100644 --- a/qw/source/sv_progs.c +++ b/qw/source/sv_progs.c @@ -53,6 +53,7 @@ sv_globals_t sv_globals; sv_funcs_t sv_funcs; sv_fields_t sv_fields; +edict_t sv_edicts[MAX_EDICTS]; sv_data_t sv_data[MAX_EDICTS]; cvar_t *r_skyname; @@ -92,16 +93,16 @@ static void free_edict (progs_t *pr, edict_t *ent) { if (sv_old_entity_free->int_val) { - ent->v[sv_fields.model].entity_var = 0; - ent->v[sv_fields.takedamage].float_var = 0; - ent->v[sv_fields.modelindex].float_var = 0; - ent->v[sv_fields.colormap].float_var = 0; - ent->v[sv_fields.skin].float_var = 0; - ent->v[sv_fields.frame].float_var = 0; - ent->v[sv_fields.nextthink].float_var = -1; - ent->v[sv_fields.solid].float_var = 0; - memset (ent->v[sv_fields.origin].vector_var, 0, 3*sizeof (float)); - memset (ent->v[sv_fields.angles].vector_var, 0, 3*sizeof (float)); + E_fld (ent, sv_fields.model).entity_var = 0; + E_fld (ent, sv_fields.takedamage).float_var = 0; + E_fld (ent, sv_fields.modelindex).float_var = 0; + E_fld (ent, sv_fields.colormap).float_var = 0; + E_fld (ent, sv_fields.skin).float_var = 0; + E_fld (ent, sv_fields.frame).float_var = 0; + E_fld (ent, sv_fields.nextthink).float_var = -1; + E_fld (ent, sv_fields.solid).float_var = 0; + memset (E_fld (ent, sv_fields.origin).vector_var, 0, 3*sizeof (float)); + memset (E_fld (ent, sv_fields.angles).vector_var, 0, 3*sizeof (float)); } else { ED_ClearEdict (pr, ent, 0); } @@ -481,12 +482,32 @@ resolve (progs_t *pr) return ret; } +static int +sv_init_edicts (progs_t *pr) +{ + int i; + + memset (sv_edicts, 0, sizeof (sv_edicts)); + memset (sv_data, 0, sizeof (sv_data)); + + // init the data field of the edicts + for (i = 0; i < MAX_EDICTS; i++) { + edict_t *ent = EDICT_NUM (&sv_pr_state, i); + ent->pr = &sv_pr_state; + ent->entnum = i; + ent->edict = EDICT_TO_PROG (&sv_pr_state, ent); + ent->edata = &sv_data[i]; + SVdata (ent)->edict = ent; + } + + return 1; +} + void SV_LoadProgs (void) { const char *progs_name = "qwprogs.dat"; const char *range; - int i; if (strequal (sv_progs_ext->string, "qf")) { sv_range = PR_RANGE_QF; @@ -521,27 +542,18 @@ SV_LoadProgs (void) if (*sv_progs->string) progs_name = sv_progs->string; + sv.edicts = sv_edicts; PR_LoadProgs (&sv_pr_state, progs_name, MAX_EDICTS, sv_progs_zone->int_val * 1024); if (!sv_pr_state.progs) Sys_Error ("SV_LoadProgs: couldn't load %s", progs_name); - - memset (sv_data, 0, sizeof (sv_data)); - - // init the data field of the edicts - for (i = 0; i < MAX_EDICTS; i++) { - edict_t *ent = EDICT_NUM (&sv_pr_state, i); - ent->entnum = i; - ent->edata = &sv_data[i]; - SVdata (ent)->edict = ent; - } } void SV_Progs_Init (void) { pr_gametype = "quakeworld"; - sv_pr_state.edicts = &sv.edicts; + sv_pr_state.pr_edicts = &sv.edicts; sv_pr_state.num_edicts = &sv.num_edicts; sv_pr_state.reserved_edicts = &reserved_edicts; sv_pr_state.unlink = SV_UnlinkEdict; @@ -552,6 +564,8 @@ SV_Progs_Init (void) sv_pr_state.bi_map = bi_map; sv_pr_state.resolve = resolve; + PR_AddLoadFunc (&sv_pr_state, sv_init_edicts); + SV_PR_Cmds_Init (); SV_PR_QWE_Init (&sv_pr_state); SV_PR_CPQW_Init (&sv_pr_state); diff --git a/qw/source/sv_user.c b/qw/source/sv_user.c index 608b44480..4505b3921 100644 --- a/qw/source/sv_user.c +++ b/qw/source/sv_user.c @@ -376,7 +376,7 @@ SV_Spawn (client_t *client) // set up the edict ent = client->edict; - memset (&ent->v, 0, sv_pr_state.progs->entityfields * 4); + memset (&E_fld (ent, 0), 0, sv_pr_state.progs->entityfields * 4); SVfloat (ent, colormap) = NUM_FOR_EDICT (&sv_pr_state, ent); SVfloat (ent, team) = 0; // FIXME SVstring (ent, netname) = PR_SetString (&sv_pr_state, client->name); diff --git a/tools/qfcc/source/qfprogs.c b/tools/qfcc/source/qfprogs.c index d6bf84927..7063d1805 100644 --- a/tools/qfcc/source/qfprogs.c +++ b/tools/qfcc/source/qfprogs.c @@ -238,7 +238,7 @@ init_qf (void) PR_Init_Cvars (); PR_Init (); - pr.edicts = &edicts; + pr.pr_edicts = &edicts; pr.num_edicts = &num_edicts; pr.reserved_edicts = &reserved_edicts; pr.file_error = file_error; @@ -267,8 +267,8 @@ convert_qfo (void) pr.pr_fielddefs = P (ddef_t, ofs_fielddefs); pr.pr_globals = P (pr_type_t, ofs_globals); pr.globals_size = pr.progs->numglobals; - pr.pr_edict_size = max (1, pr.progs->entityfields) * 4; - pr.pr_edictareasize = 1 * pr.pr_edict_size; + pr.pr_edict_size = max (1, pr.progs->entityfields); + pr.pr_edict_area_size = 1 * pr.pr_edict_size; #undef P if (verbosity) { diff --git a/tools/qfcc/test/test-harness.c b/tools/qfcc/test/test-harness.c index eff3ff9a4..061b03d4c 100644 --- a/tools/qfcc/test/test-harness.c +++ b/tools/qfcc/test/test-harness.c @@ -138,7 +138,7 @@ init_qf (void) Cvar_Get ("pr_debug", "2", 0, 0, 0); Cvar_Get ("pr_boundscheck", "2", 0, 0, 0); - pr.edicts = &edicts; + pr.pr_edicts = &edicts; pr.num_edicts = &num_edicts; pr.reserved_edicts = &reserved_edicts; pr.load_file = load_file; diff --git a/tools/qwaq/main.c b/tools/qwaq/main.c index edb7c0229..78788dded 100644 --- a/tools/qwaq/main.c +++ b/tools/qwaq/main.c @@ -107,7 +107,7 @@ init_qf (void) Cvar_Get ("pr_debug", "2", 0, 0, 0); Cvar_Get ("pr_boundscheck", "0", 0, 0, 0); - pr.edicts = &edicts; + pr.pr_edicts = &edicts; pr.num_edicts = &num_edicts; pr.reserved_edicts = &reserved_edicts; pr.load_file = load_file; diff --git a/tools/qwaq/qwaq.c b/tools/qwaq/qwaq.c index f1197ccfb..a69c393ae 100644 --- a/tools/qwaq/qwaq.c +++ b/tools/qwaq/qwaq.c @@ -118,7 +118,7 @@ init_qf (void) Cvar_Get ("pr_debug", "2", 0, 0, 0); Cvar_Get ("pr_boundscheck", "0", 0, 0, 0); - pr.edicts = &edicts; + pr.pr_edicts = &edicts; pr.num_edicts = &num_edicts; pr.reserved_edicts = &reserved_edicts; pr.load_file = load_file;