// 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)"};
+extern sizebuf_t vm_tempstringsbuf;
+
//============================================================================
// mempool handling
return true;
}
+/*
+=============
+PRVM_GameCommand_f
+
+Console command to send a string to QC function GameCommand of the
+indicated progs
+
+Usage:
+ sv_cmd adminmsg 3 "do not teamkill"
+ cl_cmd someclientcommand
+ menu_cmd somemenucommand
+
+All progs can support this extension; sg calls it in server QC, cg in client
+QC, mg in menu QC.
+=============
+*/
+void PRVM_GameCommand(const char *whichprogs, const char *whichcmd)
+{
+ if(Cmd_Argc() < 1)
+ {
+ Con_Printf("%s text...\n", whichcmd);
+ return;
+ }
+
+ PRVM_Begin;
+ if(!PRVM_SetProgFromString(whichprogs))
+ // note: this is not PRVM_SetProg because that one aborts "hard" using PRVM_Error
+ // also, it makes printing error messages easier!
+ {
+ Con_Printf("%s program not loaded.\n", whichprogs);
+ return;
+ }
+
+ if(!prog->funcoffsets.GameCommand)
+ {
+ Con_Printf("%s program do not support GameCommand!\n", whichprogs);
+ }
+ else
+ {
+ int restorevm_tempstringsbuf_cursize;
+ const char *s;
+
+ s = Cmd_Args();
+
+ restorevm_tempstringsbuf_cursize = vm_tempstringsbuf.cursize;
+ PRVM_G_INT(OFS_PARM0) = PRVM_SetTempString(s ? s : "");
+ PRVM_ExecuteProgram (prog->funcoffsets.GameCommand, "QC function GameCommand is missing");
+ vm_tempstringsbuf.cursize = restorevm_tempstringsbuf_cursize;
+ }
+
+ PRVM_End;
+}
+void PRVM_GameCommand_Server_f(void)
+{
+ PRVM_GameCommand("server", "sv_cmd");
+}
+void PRVM_GameCommand_Client_f(void)
+{
+ PRVM_GameCommand("client", "cl_cmd");
+}
+void PRVM_GameCommand_Menu_f(void)
+{
+ PRVM_GameCommand("menu", "menu_cmd");
+}
+
/*
=============
PRVM_ED_EdictSet_f
prog->fieldoffsets.customizeentityforclient = PRVM_ED_FindFieldOffset("customizeentityforclient");
prog->fieldoffsets.dimension_hit = PRVM_ED_FindFieldOffset("dimension_hit");
prog->fieldoffsets.dimension_solid = PRVM_ED_FindFieldOffset("dimension_solid");
+ prog->fieldoffsets.disableclientprediction = PRVM_ED_FindFieldOffset("disableclientprediction");
prog->fieldoffsets.dphitcontentsmask = PRVM_ED_FindFieldOffset("dphitcontentsmask");
prog->fieldoffsets.drawonlytoclient = PRVM_ED_FindFieldOffset("drawonlytoclient");
prog->fieldoffsets.exteriormodeltoclient = PRVM_ED_FindFieldOffset("exteriormodeltoclient");
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.modelflags = PRVM_ED_FindFieldOffset("modelflags");
prog->fieldoffsets.movement = PRVM_ED_FindFieldOffset("movement");
+ prog->fieldoffsets.netaddress = PRVM_ED_FindFieldOffset("netaddress");
prog->fieldoffsets.nextthink = PRVM_ED_FindFieldOffset("nextthink");
prog->fieldoffsets.nodrawtoclient = PRVM_ED_FindFieldOffset("nodrawtoclient");
prog->fieldoffsets.pflags = PRVM_ED_FindFieldOffset("pflags");
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.GameCommand = PRVM_ED_FindFunctionOffset("GameCommand");
prog->globaloffsets.SV_InitCmd = PRVM_ED_FindGlobalOffset("SV_InitCmd");
prog->globaloffsets.self = PRVM_ED_FindGlobalOffset("self");
prog->globaloffsets.time = PRVM_ED_FindGlobalOffset("time");
PRVM_FindOffsets();
- // check if OP_STATE animation is possible in this dat file
- if (prog->fieldoffsets.nextthink >= 0 && prog->fieldoffsets.frame >= 0 && prog->fieldoffsets.think >= 0 && prog->globaloffsets.self >= 0)
- prog->flag |= PRVM_OP_STATE;
-
PRVM_GCALL(init_cmd)();
// init mempools
void PRVM_Init (void)
{
Cmd_AddCommand ("prvm_edict", PRVM_ED_PrintEdict_f, "print all data about an entity number in the selected VM (server, client, menu)");
- Cmd_AddCommand ("prvm_edicts", PRVM_ED_PrintEdicts_f, "set a property on an entity number in the selected VM (server, client, menu)");
+ 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_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_globalset", PRVM_GlobalSet_f, "sets value of a specified global variable in the selected VM (server, client, menu)");
Cmd_AddCommand ("prvm_edictset", PRVM_ED_EdictSet_f, "changes value of a specified property of a specified entity in the selected VM (server, client, menu)");
Cmd_AddCommand ("prvm_printfunction", PRVM_PrintFunction_f, "prints a disassembly (QuakeC instructions) of the specified function in the selected VM (server, client, menu)");
+ Cmd_AddCommand ("cl_cmd", PRVM_GameCommand_Client_f, "calls the client QC function GameCommand with the supplied string as argument");
+ 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))
Cvar_RegisterVariable (&prvm_boundscheck);
Cvar_RegisterVariable (&prvm_traceqc);
if (prog->knownstrings[i] == s)
return -1 - i;
// new unknown engine string
- if (developer.integer >= 100)
- Con_Printf("new engine string %p\n", s);
+ if (developer.integer >= 200)
+ Con_Printf("new engine string %p = \"%s\"\n", s, s);
for (i = prog->firstfreeknownstring;i < prog->numknownstrings;i++)
if (!prog->knownstrings[i])
break;