X-Git-Url: https://de.git.xonotic.org/?a=blobdiff_plain;f=pr_edict.c;h=8520ede01ac44f24623ef63cf23292e506ce6f5e;hb=59e91e85a8f84adf31e1c3e69b7089b77098b24e;hp=bf351309ad331e3b39617e44ffb227ea7fb9e128;hpb=444342309adca329b3483ee873c14c874c9442e5;p=xonotic%2Fdarkplaces.git diff --git a/pr_edict.c b/pr_edict.c index bf351309..8520ede0 100644 --- a/pr_edict.c +++ b/pr_edict.c @@ -40,7 +40,7 @@ mempool_t *edictstring_mempool; int type_size[8] = {1,sizeof(string_t)/4,1,3,1,1,sizeof(func_t)/4,sizeof(void *)/4}; ddef_t *ED_FieldAtOfs (int ofs); -qboolean ED_ParseEpair (void *base, ddef_t *key, char *s); +qboolean ED_ParseEpair (void *base, ddef_t *key, const char *s); cvar_t pr_checkextension = {0, "pr_checkextension", "1"}; cvar_t nomonsters = {0, "nomonsters", "0"}; @@ -68,6 +68,8 @@ cvar_t nehx18 = {0, "nehx18", "0"};cvar_t nehx19 = {0, "nehx19", "0"}; cvar_t cutscene = {0, "cutscene", "1"}; // LordHavoc: optional runtime bounds checking (speed drain, but worth it for security, on by default - breaks most QCCX features (used by CRMod and others)) cvar_t pr_boundscheck = {0, "pr_boundscheck", "1"}; +// LordHavoc: prints every opcode as it executes - warning: this is significant spew +cvar_t pr_traceqc = {0, "pr_traceqc", "0"}; #define MAX_FIELD_LEN 64 #define GEFV_CACHESIZE 2 @@ -79,8 +81,8 @@ typedef struct { static gefv_cache gefvCache[GEFV_CACHESIZE] = {{NULL, ""}, {NULL, ""}}; -ddef_t *ED_FindField (char *name); -dfunction_t *ED_FindFunction (char *name); +ddef_t *ED_FindField (const char *name); +dfunction_t *ED_FindFunction (const char *name); // LordHavoc: in an effort to eliminate time wasted on GetEdictFieldValue... these are defined as externs in progs.h int eval_gravity; @@ -121,7 +123,7 @@ int eval_viewzoom; dfunction_t *SV_PlayerPhysicsQC; dfunction_t *EndFrameQC; -int FindFieldOffset(char *field) +int FindFieldOffset(const char *field) { ddef_t *d; d = ED_FindField(field); @@ -296,10 +298,10 @@ ddef_t *ED_FieldAtOfs (int ofs) ED_FindField ============ */ -ddef_t *ED_FindField (char *name) +ddef_t *ED_FindField (const char *name) { - ddef_t *def; - int i; + ddef_t *def; + int i; for (i=0 ; inumfielddefs ; i++) { @@ -315,11 +317,11 @@ ddef_t *ED_FindField (char *name) ED_FindGlobal ============ */ -ddef_t *ED_FindGlobal (char *name) +ddef_t *ED_FindGlobal (const char *name) { - ddef_t *def; - int i; - + ddef_t *def; + int i; + for (i=0 ; inumglobaldefs ; i++) { def = &pr_globaldefs[i]; @@ -335,11 +337,11 @@ ddef_t *ED_FindGlobal (char *name) ED_FindFunction ============ */ -dfunction_t *ED_FindFunction (char *name) +dfunction_t *ED_FindFunction (const char *name) { dfunction_t *func; int i; - + for (i=0 ; inumfunctions ; i++) { func = &pr_functions[i]; @@ -405,7 +407,7 @@ char *PR_ValueString (etype_t type, eval_t *val) sprintf (line, "bad type %i", type); break; } - + return line; } @@ -685,7 +687,7 @@ void ED_PrintEdicts (void) ============= ED_PrintEdict_f -For debugging, prints a single edicy +For debugging, prints a single edict ============= */ void ED_PrintEdict_f (void) @@ -782,25 +784,23 @@ void ED_WriteGlobals (QFile *f) ED_ParseGlobals ============= */ -void ED_ParseGlobals (char *data) +void ED_ParseGlobals (const char *data) { - char keyname[1024]; // LordHavoc: good idea? bad idea? was 64 - ddef_t *key; + char keyname[1024]; // LordHavoc: good idea? bad idea? was 64 + ddef_t *key; while (1) - { - // parse key - data = COM_Parse (data); + { + // parse key + if (!COM_ParseToken (&data)) + Host_Error ("ED_ParseEntity: EOF without closing brace"); if (com_token[0] == '}') break; - if (!data) - Host_Error ("ED_ParseEntity: EOF without closing brace"); strcpy (keyname, com_token); - // parse value - data = COM_Parse (data); - if (!data) + // parse value + if (!COM_ParseToken (&data)) Host_Error ("ED_ParseEntity: EOF without closing brace"); if (com_token[0] == '}') @@ -826,10 +826,10 @@ void ED_ParseGlobals (char *data) ED_NewString ============= */ -char *ED_NewString (char *string) +char *ED_NewString (const char *string) { - char *new, *new_p; - int i,l; + char *new, *new_p; + int i,l; l = strlen(string) + 1; new = Mem_Alloc(edictstring_mempool, l); @@ -861,7 +861,7 @@ Can parse either fields or globals returns false if error ============= */ -qboolean ED_ParseEpair (void *base, ddef_t *key, char *s) +qboolean ED_ParseEpair (void *base, ddef_t *key, const char *s) { int i; char string[128]; @@ -899,7 +899,7 @@ qboolean ED_ParseEpair (void *base, ddef_t *key, char *s) case ev_entity: *(int *)d = EDICT_TO_PROG(EDICT_NUM(atoi (s))); break; - + case ev_field: def = ED_FindField (s); if (!def) @@ -937,13 +937,13 @@ ed should be a properly initialized empty edict. Used for initial level load and for savegames. ==================== */ -char *ED_ParseEdict (char *data, edict_t *ent) +const char *ED_ParseEdict (const char *data, edict_t *ent) { - ddef_t *key; - qboolean anglehack; - qboolean init; - char keyname[256]; - int n; + ddef_t *key; + qboolean anglehack; + qboolean init; + char keyname[256]; + int n; init = false; @@ -955,11 +955,10 @@ char *ED_ParseEdict (char *data, edict_t *ent) while (1) { // parse key - data = COM_Parse (data); + if (!COM_ParseToken (&data)) + Host_Error ("ED_ParseEntity: EOF without closing brace"); if (com_token[0] == '}') break; - if (!data) - Host_Error ("ED_ParseEntity: EOF without closing brace"); // anglehack is to allow QuakeEd to write single scalar angles // and allow them to be turned into vectors. (FIXME...) @@ -986,8 +985,7 @@ char *ED_ParseEdict (char *data, edict_t *ent) } // parse value - data = COM_Parse (data); - if (!data) + if (!COM_ParseToken (&data)) Host_Error ("ED_ParseEntity: EOF without closing brace"); if (com_token[0] == '}') @@ -1040,11 +1038,11 @@ Used for both fresh maps and savegame loads. A fresh map would also need to call ED_CallSpawnFunctions () to let the objects initialize themselves. ================ */ -void ED_LoadFromFile (char *data) -{ - edict_t *ent; - int inhibit; - dfunction_t *func; +void ED_LoadFromFile (const char *data) +{ + edict_t *ent; + int inhibit; + dfunction_t *func; ent = NULL; inhibit = 0; @@ -1053,9 +1051,8 @@ void ED_LoadFromFile (char *data) // parse ents while (1) { -// parse the opening brace - data = COM_Parse (data); - if (!data) +// parse the opening brace + if (!COM_ParseToken (&data)) break; if (com_token[0] != '{') Host_Error ("ED_LoadFromFile: found %s when expecting {",com_token); @@ -1378,20 +1375,113 @@ void PR_LoadProgs (void) } FindEdictFieldOffsets(); // LordHavoc: update field offset list + PR_Execute_ProgsLoaded(); } void PR_Fields_f (void) { - int i; + int i, j, ednum, used, usedamount; + int *counts; + char tempstring[5000], tempstring2[260], *name; + edict_t *ed; + ddef_t *d; + int *v; if (!sv.active) { Con_Printf("no progs loaded\n"); return; } + counts = Mem_Alloc(tempmempool, progs->numfielddefs * sizeof(int)); + for (ednum = 0;ednum < MAX_EDICTS;ednum++) + { + ed = EDICT_NUM(ednum); + if (ed->free) + continue; + for (i = 1;i < progs->numfielddefs;i++) + { + d = &pr_fielddefs[i]; + name = pr_strings + d->s_name; + if (name[strlen(name)-2] == '_') + continue; // skip _x, _y, _z vars + v = (int *)((char *)&ed->v + d->ofs*4); + // if the value is still all 0, skip the field + for (j = 0;j < type_size[d->type & ~DEF_SAVEGLOBAL];j++) + { + if (v[j]) + { + counts[i]++; + break; + } + } + } + } + used = 0; + usedamount = 0; + tempstring[0] = 0; for (i = 0;i < progs->numfielddefs;i++) - Con_Printf("%s\n", (pr_strings + pr_fielddefs[i].s_name)); - Con_Printf("%i entity fields, totalling %i bytes per edict, %i edicts, %i bytes total spent on edict fields\n", progs->entityfields, progs->entityfields * 4, MAX_EDICTS, progs->entityfields * 4 * MAX_EDICTS); + { + d = &pr_fielddefs[i]; + name = pr_strings + d->s_name; + if (name[strlen(name)-2] == '_') + continue; // skip _x, _y, _z vars + switch(d->type & ~DEF_SAVEGLOBAL) + { + case ev_string: + strcat(tempstring, "string "); + break; + case ev_entity: + strcat(tempstring, "entity "); + break; + case ev_function: + strcat(tempstring, "function "); + break; + case ev_field: + strcat(tempstring, "field "); + break; + case ev_void: + strcat(tempstring, "void "); + break; + case ev_float: + strcat(tempstring, "float "); + break; + case ev_vector: + strcat(tempstring, "vector "); + break; + case ev_pointer: + strcat(tempstring, "pointer "); + break; + default: + sprintf (tempstring2, "bad type %i ", d->type & ~DEF_SAVEGLOBAL); + strcat(tempstring, tempstring2); + break; + } + if (strlen(name) > 256) + { + strncpy(tempstring2, name, 256); + tempstring2[256] = tempstring2[257] = tempstring2[258] = '.'; + tempstring2[259] = 0; + name = tempstring2; + } + strcat(tempstring, name); + for (j = strlen(name);j < 25;j++) + strcat(tempstring, " "); + sprintf(tempstring2, "%5d", counts[i]); + strcat(tempstring, tempstring2); + strcat(tempstring, "\n"); + if (strlen(tempstring) >= 4096) + { + Con_Printf("%s", tempstring); + tempstring[0] = 0; + } + if (counts[i]) + { + used++; + usedamount += type_size[d->type & ~DEF_SAVEGLOBAL]; + } + } + Mem_Free(counts); + Con_Printf("%i entity fields (%i in use), totalling %i bytes per edict (%i in use), %i edicts, %i bytes total spent on edict fields (%i needed)\n", progs->entityfields, used, progs->entityfields * 4, usedamount * 4, MAX_EDICTS, progs->entityfields * 4 * MAX_EDICTS, usedamount * 4 * MAX_EDICTS); } void PR_Globals_f (void) @@ -1451,6 +1541,7 @@ void PR_Init (void) Cvar_RegisterVariable (&cutscene); // for Nehahra but useful to other mods as well // LordHavoc: optional runtime bounds checking (speed drain, but worth it for security, on by default - breaks most QCCX features (used by CRMod and others)) Cvar_RegisterVariable (&pr_boundscheck); + Cvar_RegisterVariable (&pr_traceqc); progs_mempool = Mem_AllocPool("progs.dat"); edictstring_mempool = Mem_AllocPool("edict strings");