X-Git-Url: http://de.git.xonotic.org/?p=xonotic%2Fdarkplaces.git;a=blobdiff_plain;f=prvm_edict.c;h=9e85cfc7dac516f735d56f1bc77a29ae73790782;hp=4b59235656d4bb0c05c81e1e95a075cd21101f9d;hb=9fb9f7ec19abcbd8caa7b2c61a0c990d03d674a3;hpb=df96a719a2e77a0fc8175c003bf261b0016cefae diff --git a/prvm_edict.c b/prvm_edict.c index 4b592356..9e85cfc7 100644 --- a/prvm_edict.c +++ b/prvm_edict.c @@ -32,11 +32,14 @@ ddef_t *PRVM_ED_FieldAtOfs(int ofs); qboolean PRVM_ED_ParseEpair(prvm_edict_t *ent, ddef_t *key, const char *s); // LordHavoc: optional runtime bounds checking (speed drain, but worth it for security, on by default - breaks most QCCX features (used by CRMod and others)) +#ifdef PRVM_BOUNDSCHECK_CVAR cvar_t prvm_boundscheck = {0, "prvm_boundscheck", "1", "enables detection of out of bounds memory access in the QuakeC code being run (in other words, prevents really exceedingly bad QuakeC code from doing nasty things to your computer)"}; +#endif // LordHavoc: prints every opcode as it executes - warning: this is significant spew cvar_t prvm_traceqc = {0, "prvm_traceqc", "0", "prints every QuakeC statement as it is executed (only for really thorough debugging!)"}; // LordHavoc: counts usage of each QuakeC statement cvar_t prvm_statementprofiling = {0, "prvm_statementprofiling", "0", "counts how many times each QuakeC statement has been executed, these counts are displayed in prvm_printfunction output (if enabled)"}; +cvar_t prvm_backtraceforwarnings = {0, "prvm_backtraceforwarnings", "0", "print a backtrace for warnings too"}; extern sizebuf_t vm_tempstringsbuf; @@ -574,7 +577,7 @@ For debugging */ // LordHavoc: optimized this to print out much more quickly (tempstring) // LordHavoc: changed to print out every 4096 characters (incase there are a lot of fields to print) -void PRVM_ED_Print(prvm_edict_t *ed) +void PRVM_ED_Print(prvm_edict_t *ed, const char *wildcard_fieldname) { size_t l; ddef_t *d; @@ -599,6 +602,12 @@ void PRVM_ED_Print(prvm_edict_t *ed) if (name[strlen(name)-2] == '_') continue; // skip _x, _y, _z vars + // Check Field Name Wildcard + if(wildcard_fieldname) + if( !matchpattern(name, wildcard_fieldname, 1) ) + // Didn't match; skip + continue; + v = (int *)((char *)ed->fields.vp + d->ofs*4); // if the value is still all 0, skip the field @@ -689,9 +698,9 @@ void PRVM_ED_Write (qfile_t *f, prvm_edict_t *ed) FS_Print(f, "}\n"); } -void PRVM_ED_PrintNum (int ent) +void PRVM_ED_PrintNum (int ent, const char *wildcard_fieldname) { - PRVM_ED_Print(PRVM_EDICT_NUM(ent)); + PRVM_ED_Print(PRVM_EDICT_NUM(ent), wildcard_fieldname); } /* @@ -704,10 +713,11 @@ For debugging, prints all the entities in the current server void PRVM_ED_PrintEdicts_f (void) { int i; + const char *wildcard_fieldname; - if(Cmd_Argc() != 2) + if(Cmd_Argc() < 2 || Cmd_Argc() > 3) { - Con_Print("prvm_edicts \n"); + Con_Print("prvm_edicts \n"); return; } @@ -715,9 +725,14 @@ void PRVM_ED_PrintEdicts_f (void) if(!PRVM_SetProgFromString(Cmd_Argv(1))) return; + if( Cmd_Argc() == 3) + wildcard_fieldname = Cmd_Argv(2); + else + wildcard_fieldname = NULL; + Con_Printf("%s: %i entities\n", PRVM_NAME, prog->num_edicts); for (i=0 ; inum_edicts ; i++) - PRVM_ED_PrintNum (i); + PRVM_ED_PrintNum (i, wildcard_fieldname); PRVM_End; } @@ -732,10 +747,11 @@ For debugging, prints a single edict void PRVM_ED_PrintEdict_f (void) { int i; + const char *wildcard_fieldname; - if(Cmd_Argc() != 3) + if(Cmd_Argc() < 3 || Cmd_Argc() > 4) { - Con_Print("prvm_edict \n"); + Con_Print("prvm_edict \n"); return; } @@ -750,7 +766,13 @@ void PRVM_ED_PrintEdict_f (void) PRVM_End; return; } - PRVM_ED_PrintNum (i); + if( Cmd_Argc() == 4) + // Optional Wildcard Provided + wildcard_fieldname = Cmd_Argv(3); + else + // Use All + wildcard_fieldname = NULL; + PRVM_ED_PrintNum (i, wildcard_fieldname); PRVM_End; } @@ -853,7 +875,7 @@ void PRVM_ED_ParseGlobals (const char *data) while (1) { // parse key - if (!COM_ParseToken_Simple(&data, false)) + if (!COM_ParseToken_Simple(&data, false, false)) PRVM_ERROR ("PRVM_ED_ParseGlobals: EOF without closing brace"); if (com_token[0] == '}') break; @@ -861,7 +883,7 @@ void PRVM_ED_ParseGlobals (const char *data) strlcpy (keyname, com_token, sizeof(keyname)); // parse value - if (!COM_ParseToken_Simple(&data, false)) + if (!COM_ParseToken_Simple(&data, false, true)) PRVM_ERROR ("PRVM_ED_ParseGlobals: EOF without closing brace"); if (com_token[0] == '}') @@ -1110,7 +1132,7 @@ const char *PRVM_ED_ParseEdict (const char *data, prvm_edict_t *ent) while (1) { // parse key - if (!COM_ParseToken_Simple(&data, false)) + if (!COM_ParseToken_Simple(&data, false, false)) PRVM_ERROR ("PRVM_ED_ParseEdict: EOF without closing brace"); if (developer_entityparsing.integer) Con_Printf("Key: \"%s\"", com_token); @@ -1142,7 +1164,7 @@ const char *PRVM_ED_ParseEdict (const char *data, prvm_edict_t *ent) } // parse value - if (!COM_ParseToken_Simple(&data, false)) + if (!COM_ParseToken_Simple(&data, false, true)) PRVM_ERROR ("PRVM_ED_ParseEdict: EOF without closing brace"); if (developer_entityparsing.integer) Con_Printf(" \"%s\"\n", com_token); @@ -1205,6 +1227,7 @@ void PRVM_ED_LoadFromFile (const char *data) { prvm_edict_t *ent; int parsed, inhibited, spawned, died; + const char *funcname; mfunction_t *func; parsed = 0; @@ -1217,7 +1240,7 @@ void PRVM_ED_LoadFromFile (const char *data) while (1) { // parse the opening brace - if (!COM_ParseToken_Simple(&data, false)) + if (!COM_ParseToken_Simple(&data, false, false)) break; if (com_token[0] != '{') PRVM_ERROR ("PRVM_ED_LoadFromFile: %s: found %s when expecting {", PRVM_NAME, com_token); @@ -1255,28 +1278,43 @@ void PRVM_ED_LoadFromFile (const char *data) if (!handle) { Con_Print("No classname for:\n"); - PRVM_ED_Print(ent); + PRVM_ED_Print(ent, NULL); PRVM_ED_Free (ent); continue; } // look for the spawn function - func = PRVM_ED_FindFunction (PRVM_GetString(handle)); + funcname = PRVM_GetString(handle); + func = PRVM_ED_FindFunction (va("spawnfunc_%s", funcname)); + if(!func) + func = PRVM_ED_FindFunction (funcname); if (!func) { - if (developer.integer) // don't confuse non-developers with errors + // check for OnEntityNoSpawnFunction + if (prog->funcoffsets.SV_OnEntityNoSpawnFunction) { - Con_Print("No spawn function for:\n"); - PRVM_ED_Print(ent); + // self = ent + PRVM_GLOBALFIELDVALUE(prog->globaloffsets.self)->edict = PRVM_EDICT_TO_PROG(ent); + PRVM_ExecuteProgram (prog->funcoffsets.SV_OnEntityNoSpawnFunction, "QC function SV_OnEntityNoSpawnFunction is missing"); + } + else + { + if (developer.integer) // don't confuse non-developers with errors + { + Con_Print("No spawn function for:\n"); + PRVM_ED_Print(ent, NULL); + } + PRVM_ED_Free (ent); + continue; } - PRVM_ED_Free (ent); - continue; } - - // self = ent - PRVM_GLOBALFIELDVALUE(prog->globaloffsets.self)->edict = PRVM_EDICT_TO_PROG(ent); - PRVM_ExecuteProgram (func - prog->functions, ""); + else + { + // self = ent + PRVM_GLOBALFIELDVALUE(prog->globaloffsets.self)->edict = PRVM_EDICT_TO_PROG(ent); + PRVM_ExecuteProgram (func - prog->functions, ""); + } } spawned++; @@ -1359,6 +1397,7 @@ void PRVM_FindOffsets(void) prog->fieldoffsets.items2 = PRVM_ED_FindFieldOffset("items2"); prog->fieldoffsets.lerpfrac = PRVM_ED_FindFieldOffset("lerpfrac"); prog->fieldoffsets.light_lev = PRVM_ED_FindFieldOffset("light_lev"); + prog->fieldoffsets.message = PRVM_ED_FindFieldOffset("message"); prog->fieldoffsets.modelflags = PRVM_ED_FindFieldOffset("modelflags"); prog->fieldoffsets.movement = PRVM_ED_FindFieldOffset("movement"); prog->fieldoffsets.netaddress = PRVM_ED_FindFieldOffset("netaddress"); @@ -1382,10 +1421,12 @@ void PRVM_FindOffsets(void) prog->fieldoffsets.viewmodelforclient = PRVM_ED_FindFieldOffset("viewmodelforclient"); prog->fieldoffsets.viewzoom = PRVM_ED_FindFieldOffset("viewzoom"); prog->fieldoffsets.yaw_speed = PRVM_ED_FindFieldOffset("yaw_speed"); + prog->fieldoffsets.clientcamera = PRVM_ED_FindFieldOffset("clientcamera"); prog->funcoffsets.CSQC_ConsoleCommand = PRVM_ED_FindFunctionOffset("CSQC_ConsoleCommand"); prog->funcoffsets.CSQC_Ent_Remove = PRVM_ED_FindFunctionOffset("CSQC_Ent_Remove"); prog->funcoffsets.CSQC_Ent_Update = PRVM_ED_FindFunctionOffset("CSQC_Ent_Update"); prog->funcoffsets.CSQC_Event = PRVM_ED_FindFunctionOffset("CSQC_Event"); + prog->funcoffsets.CSQC_Event_Sound = PRVM_ED_FindFunctionOffset("CSQC_Event_Sound"); prog->funcoffsets.CSQC_Init = PRVM_ED_FindFunctionOffset("CSQC_Init"); prog->funcoffsets.CSQC_InputEvent = PRVM_ED_FindFunctionOffset("CSQC_InputEvent"); prog->funcoffsets.CSQC_Parse_CenterPrint = PRVM_ED_FindFunctionOffset("CSQC_Parse_CenterPrint"); @@ -1394,18 +1435,22 @@ void PRVM_FindOffsets(void) prog->funcoffsets.CSQC_Parse_TempEntity = PRVM_ED_FindFunctionOffset("CSQC_Parse_TempEntity"); prog->funcoffsets.CSQC_Shutdown = PRVM_ED_FindFunctionOffset("CSQC_Shutdown"); prog->funcoffsets.CSQC_UpdateView = PRVM_ED_FindFunctionOffset("CSQC_UpdateView"); + prog->funcoffsets.Gecko_Query = PRVM_ED_FindFunctionOffset("Gecko_Query"); prog->funcoffsets.EndFrame = PRVM_ED_FindFunctionOffset("EndFrame"); prog->funcoffsets.RestoreGame = PRVM_ED_FindFunctionOffset("RestoreGame"); prog->funcoffsets.SV_ChangeTeam = PRVM_ED_FindFunctionOffset("SV_ChangeTeam"); prog->funcoffsets.SV_ParseClientCommand = PRVM_ED_FindFunctionOffset("SV_ParseClientCommand"); prog->funcoffsets.SV_PlayerPhysics = PRVM_ED_FindFunctionOffset("SV_PlayerPhysics"); + prog->funcoffsets.SV_OnEntityNoSpawnFunction = PRVM_ED_FindFunctionOffset("SV_OnEntityNoSpawnFunction"); prog->funcoffsets.GameCommand = PRVM_ED_FindFunctionOffset("GameCommand"); + prog->funcoffsets.SV_Shutdown = PRVM_ED_FindFunctionOffset("SV_Shutdown"); prog->globaloffsets.SV_InitCmd = PRVM_ED_FindGlobalOffset("SV_InitCmd"); prog->globaloffsets.self = PRVM_ED_FindGlobalOffset("self"); prog->globaloffsets.time = PRVM_ED_FindGlobalOffset("time"); prog->globaloffsets.v_forward = PRVM_ED_FindGlobalOffset("v_forward"); prog->globaloffsets.v_right = PRVM_ED_FindGlobalOffset("v_right"); prog->globaloffsets.v_up = PRVM_ED_FindGlobalOffset("v_up"); + prog->globaloffsets.view_angles = PRVM_ED_FindGlobalOffset("view_angles"); prog->globaloffsets.trace_allsolid = PRVM_ED_FindGlobalOffset("trace_allsolid"); prog->globaloffsets.trace_startsolid = PRVM_ED_FindGlobalOffset("trace_startsolid"); prog->globaloffsets.trace_fraction = PRVM_ED_FindGlobalOffset("trace_fraction"); @@ -1419,11 +1464,17 @@ void PRVM_FindOffsets(void) prog->globaloffsets.trace_dphitq3surfaceflags = PRVM_ED_FindGlobalOffset("trace_dphitq3surfaceflags"); prog->globaloffsets.trace_dphittexturename = PRVM_ED_FindGlobalOffset("trace_dphittexturename"); prog->globaloffsets.trace_dpstartcontents = PRVM_ED_FindGlobalOffset("trace_dpstartcontents"); + prog->globaloffsets.intermission = PRVM_ED_FindGlobalOffset("intermission"); + prog->globaloffsets.coop = PRVM_ED_FindGlobalOffset("coop"); + prog->globaloffsets.deathmatch = PRVM_ED_FindGlobalOffset("deathmatch"); + prog->globaloffsets.dmg_take = PRVM_ED_FindGlobalOffset("dmg_take"); + prog->globaloffsets.dmg_save = PRVM_ED_FindGlobalOffset("dmg_save"); + prog->globaloffsets.dmg_origin = PRVM_ED_FindGlobalOffset("dmg_origin"); + prog->globaloffsets.sb_showscores = PRVM_ED_FindGlobalOffset("sb_showscores"); + prog->globaloffsets.drawfont = PRVM_ED_FindGlobalOffset("drawfont"); // menu qc only uses some functions, nothing else - prog->funcoffsets.m_display = PRVM_ED_FindFunctionOffset("m_display"); prog->funcoffsets.m_draw = PRVM_ED_FindFunctionOffset("m_draw"); - prog->funcoffsets.m_hide = PRVM_ED_FindFunctionOffset("m_hide"); prog->funcoffsets.m_init = PRVM_ED_FindFunctionOffset("m_init"); prog->funcoffsets.m_keydown = PRVM_ED_FindFunctionOffset("m_keydown"); prog->funcoffsets.m_keyup = PRVM_ED_FindFunctionOffset("m_keyup"); @@ -1458,6 +1509,7 @@ void PRVM_ResetProg() PRVM_GCALL(reset_cmd)(); Mem_FreePool(&prog->progs_mempool); memset(prog,0,sizeof(prvm_prog_t)); + prog->starttime = Sys_DoubleTime(); } /* @@ -1538,25 +1590,24 @@ void PRVM_LoadProgs (const char * filename, int numrequiredfunc, char **required if (prog->progs->version != PROG_VERSION) PRVM_ERROR ("%s: %s has wrong version number (%i should be %i)", PRVM_NAME, filename, prog->progs->version, PROG_VERSION); - if (prog->progs->crc != prog->headercrc) - PRVM_ERROR ("%s: %s system vars have been modified, progdefs.h is out of date", PRVM_NAME, filename); + if (prog->progs->crc != prog->headercrc && prog->progs->crc != prog->headercrc2) + PRVM_ERROR ("%s: %s system vars have been modified (CRC of progs.dat systemvars %i != engine %i), progdefs.h is out of date", PRVM_NAME, filename, prog->progs->crc, prog->headercrc); //prog->functions = (dfunction_t *)((unsigned char *)progs + progs->ofs_functions); dfunctions = (dfunction_t *)((unsigned char *)prog->progs + prog->progs->ofs_functions); + if (prog->progs->ofs_strings + prog->progs->numstrings >= (int)filesize) + PRVM_ERROR ("%s: %s strings go past end of file", PRVM_NAME, filename); prog->strings = (char *)prog->progs + prog->progs->ofs_strings; - prog->stringssize = 0; - for (i = 0;i < prog->progs->numstrings;i++) - { - if (prog->progs->ofs_strings + prog->stringssize >= (int)filesize) - PRVM_ERROR ("%s: %s strings go past end of file", PRVM_NAME, filename); - prog->stringssize += (int)strlen (prog->strings + prog->stringssize) + 1; - } + prog->stringssize = prog->progs->numstrings; + prog->numknownstrings = 0; prog->maxknownstrings = 0; prog->knownstrings = NULL; prog->knownstrings_freeable = NULL; + Mem_ExpandableArray_NewArray(&prog->stringbuffersarray, prog->progs_mempool, sizeof(prvm_stringbuffer_t), 64); + prog->globaldefs = (ddef_t *)((unsigned char *)prog->progs + prog->progs->ofs_globaldefs); // we need to expand the fielddefs list to include all the engine fields, @@ -1887,15 +1938,18 @@ void PRVM_Fields_f (void) void PRVM_Globals_f (void) { int i; + const char *wildcard; + int numculled; + numculled = 0; // TODO /*if (!sv.active) { Con_Print("no progs loaded\n"); return; }*/ - if(Cmd_Argc () != 2) + if(Cmd_Argc () < 2 || Cmd_Argc() > 3) { - Con_Print("prvm_globals \n"); + Con_Print("prvm_globals \n"); return; } @@ -1903,11 +1957,24 @@ void PRVM_Globals_f (void) if(!PRVM_SetProgFromString (Cmd_Argv (1))) return; + if( Cmd_Argc() == 3) + wildcard = Cmd_Argv(2); + else + wildcard = NULL; + Con_Printf("%s :", PRVM_NAME); for (i = 0;i < prog->progs->numglobaldefs;i++) + { + if(wildcard) + if( !matchpattern( PRVM_GetString(prog->globaldefs[i].s_name), wildcard, 1) ) + { + numculled++; + continue; + } Con_Printf("%s\n", PRVM_GetString(prog->globaldefs[i].s_name)); - Con_Printf("%i global variables, totalling %i bytes\n", prog->progs->numglobals, prog->progs->numglobals * 4); + } + Con_Printf("%i global variables, %i culled, totalling %i bytes\n", prog->progs->numglobals, numculled, prog->progs->numglobals * 4); PRVM_End; } @@ -1973,6 +2040,7 @@ void PRVM_Init (void) Cmd_AddCommand ("prvm_edicts", PRVM_ED_PrintEdicts_f, "prints all data about all entities in the selected VM (server, client, menu)"); Cmd_AddCommand ("prvm_edictcount", PRVM_ED_Count_f, "prints number of active entities in the selected VM (server, client, menu)"); Cmd_AddCommand ("prvm_profile", PRVM_Profile_f, "prints execution statistics about the most used QuakeC functions in the selected VM (server, client, menu)"); + Cmd_AddCommand ("prvm_callprofile", PRVM_CallProfile_f, "prints execution statistics about the most time consuming QuakeC calls from the engine in the selected VM (server, client, menu)"); Cmd_AddCommand ("prvm_fields", PRVM_Fields_f, "prints usage statistics on properties (how many entities have non-zero values) in the selected VM (server, client, menu)"); Cmd_AddCommand ("prvm_globals", PRVM_Globals_f, "prints all global variables in the selected VM (server, client, menu)"); Cmd_AddCommand ("prvm_global", PRVM_Global_f, "prints value of a specified global variable in the selected VM (server, client, menu)"); @@ -1983,9 +2051,12 @@ void PRVM_Init (void) Cmd_AddCommand ("menu_cmd", PRVM_GameCommand_Menu_f, "calls the menu QC function GameCommand with the supplied string as argument"); Cmd_AddCommand ("sv_cmd", PRVM_GameCommand_Server_f, "calls the server QC function GameCommand with the supplied string as argument"); // LordHavoc: optional runtime bounds checking (speed drain, but worth it for security, on by default - breaks most QCCX features (used by CRMod and others)) +#ifdef PRVM_BOUNDSCHECK_CVAR Cvar_RegisterVariable (&prvm_boundscheck); +#endif Cvar_RegisterVariable (&prvm_traceqc); Cvar_RegisterVariable (&prvm_statementprofiling); + Cvar_RegisterVariable (&prvm_backtraceforwarnings); //VM_Cmd_Init(); } @@ -2006,6 +2077,7 @@ void PRVM_InitProg(int prognr) PRVM_ResetProg(); memset(prog, 0, sizeof(prvm_prog_t)); + prog->starttime = Sys_DoubleTime(); prog->error_cmd = Host_Error; } @@ -2099,14 +2171,14 @@ const char *PRVM_GetString(int num) return (char *)vm_tempstringsbuf.data + num; else { - VM_Warning("PRVM_GetString: Invalid temp-string offset (%i >= %i vm_tempstringsbuf.cursize)", num, vm_tempstringsbuf.cursize); + VM_Warning("PRVM_GetString: Invalid temp-string offset (%i >= %i vm_tempstringsbuf.cursize)\n", num, vm_tempstringsbuf.cursize); return ""; } } else #endif { - VM_Warning("PRVM_GetString: Invalid constant-string offset (%i >= %i prog->stringssize)", num, prog->stringssize); + VM_Warning("PRVM_GetString: Invalid constant-string offset (%i >= %i prog->stringssize)\n", num, prog->stringssize); return ""; } } @@ -2122,7 +2194,7 @@ const char *PRVM_GetString(int num) return (char *)vm_tempstringsbuf.data + num; else { - VM_Warning("PRVM_GetString: Invalid temp-string offset (%i >= %i vm_tempstringsbuf.cursize)", num, vm_tempstringsbuf.cursize); + VM_Warning("PRVM_GetString: Invalid temp-string offset (%i >= %i vm_tempstringsbuf.cursize)\n", num, vm_tempstringsbuf.cursize); return ""; } } @@ -2131,12 +2203,12 @@ const char *PRVM_GetString(int num) if (num < prog->numknownstrings) { if (!prog->knownstrings[num]) - VM_Warning("PRVM_GetString: Invalid zone-string offset (%i has been freed)", num); + VM_Warning("PRVM_GetString: Invalid zone-string offset (%i has been freed)\n", num); return prog->knownstrings[num]; } else { - VM_Warning("PRVM_GetString: Invalid zone-string offset (%i >= %i)", num, prog->numknownstrings); + VM_Warning("PRVM_GetString: Invalid zone-string offset (%i >= %i)\n", num, prog->numknownstrings); return ""; } }