return NULL;
}
+/*
+============
+PRVM_ED_FindGlobalEval
+============
+*/
+prvm_eval_t *PRVM_ED_FindGlobalEval(prvm_prog_t *prog, const char *name)
+{
+ ddef_t *def = PRVM_ED_FindGlobal(prog, name);
+ return def ? (prvm_eval_t *) &prog->globals.fp[def->ofs] : NULL;
+}
/*
============
dpsnprintf (line, linelength, "%s()", PRVM_GetString(prog, f->s_name));
}
else
- dpsnprintf (line, linelength, "function%lli() (invalid!)", val->function);
+ dpsnprintf (line, linelength, "function %" PRVM_PRIi "() (invalid!)", val->function);
break;
case ev_field:
def = PRVM_ED_FieldAtOfs ( prog, val->_int );
if (def != NULL)
dpsnprintf (line, linelength, ".%s", PRVM_GetString(prog, def->s_name));
else
- dpsnprintf (line, linelength, "field%lli (invalid!)", val->_int );
+ dpsnprintf (line, linelength, "field %" PRVM_PRIi " (invalid!)", val->_int );
break;
case ev_void:
dpsnprintf (line, linelength, "void");
strlcpy (line, PRVM_GetString (prog, f->s_name), linelength);
}
else
- dpsnprintf (line, linelength, "bad function %lli (invalid!)", val->function);
+ dpsnprintf (line, linelength, "bad function %" PRVM_PRIi " (invalid!)", val->function);
break;
case ev_field:
def = PRVM_ED_FieldAtOfs ( prog, val->_int );
if (def != NULL)
dpsnprintf (line, linelength, ".%s", PRVM_GetString(prog, def->s_name));
else
- dpsnprintf (line, linelength, "field%lli (invalid!)", val->_int );
+ dpsnprintf (line, linelength, "field %" PRVM_PRIi "(invalid!)", val->_int );
break;
case ev_void:
dpsnprintf (line, linelength, "void");
For savegames
=============
*/
-extern cvar_t developer_entityparsing;
void PRVM_ED_Write (prvm_prog_t *prog, qfile_t *f, prvm_edict_t *ed)
{
ddef_t *d;
ed = PRVM_EDICT_NUM(atoi(Cmd_Argv(cmd, 2)));
if((key = PRVM_ED_FindField(prog, Cmd_Argv(cmd, 3))) == 0)
- Con_Printf("Key %s not found !\n", Cmd_Argv(cmd, 3));
+ Con_Printf("Key %s not found!\n", Cmd_Argv(cmd, 3));
else
PRVM_ED_ParseEpair(prog, ed, key, Cmd_Argv(cmd, 4), true);
}
return data;
}
+void PRVM_ED_CallPrespawnFunction(prvm_prog_t *prog, prvm_edict_t *ent)
+{
+ if (PRVM_serverfunction(SV_OnEntityPreSpawnFunction))
+ {
+ // self = ent
+ PRVM_serverglobalfloat(time) = sv.time;
+ PRVM_serverglobaledict(self) = PRVM_EDICT_TO_PROG(ent);
+ prog->ExecuteProgram(prog, PRVM_serverfunction(SV_OnEntityPreSpawnFunction), "QC function SV_OnEntityPreSpawnFunction is missing");
+ }
+}
+
+qboolean PRVM_ED_CallSpawnFunction(prvm_prog_t *prog, prvm_edict_t *ent, const char *data, const char *start)
+{
+ const char *funcname;
+ mfunction_t *func;
+ prvm_eval_t *fulldata = NULL;
+ char vabuf[1024];
+
+//
+// immediately call spawn function, but only if there is a self global and a classname
+//
+ if (!ent->priv.required->free)
+ {
+ if (!PRVM_alledictstring(ent, classname))
+ {
+ Con_Print("No classname for:\n");
+ PRVM_ED_Print(prog, ent, NULL);
+ PRVM_ED_Free (prog, ent);
+ return false;
+ }
+ /*
+ * This is required for FTE compatibility (FreeCS).
+ * It copies the key/value pairs themselves into a
+ * global for QC to parse on its own.
+ */
+ else if (data && start)
+ {
+ if((fulldata = PRVM_ED_FindGlobalEval(prog, "__fullspawndata")))
+ {
+ const char *in;
+ char *spawndata;
+ fulldata->string = PRVM_AllocString(prog, data - start + 1, &spawndata);
+ for(in = start; in < data; )
+ {
+ char c = *in++;
+ if(c == '\n')
+ *spawndata++ = '\t';
+ else
+ *spawndata++ = c;
+ }
+ *spawndata = 0;
+ }
+ }
+
+ // look for the spawn function
+ funcname = PRVM_GetString(prog, PRVM_alledictstring(ent, classname));
+ func = PRVM_ED_FindFunction (prog, va(vabuf, sizeof(vabuf), "spawnfunc_%s", funcname));
+ if(!func)
+ if(!PRVM_allglobalfloat(require_spawnfunc_prefix))
+ func = PRVM_ED_FindFunction (prog, funcname);
+
+ if (!func)
+ {
+ // check for OnEntityNoSpawnFunction
+ if (PRVM_serverfunction(SV_OnEntityNoSpawnFunction))
+ {
+ // self = ent
+ PRVM_serverglobalfloat(time) = sv.time;
+ PRVM_serverglobaledict(self) = PRVM_EDICT_TO_PROG(ent);
+ prog->ExecuteProgram(prog, PRVM_serverfunction(SV_OnEntityNoSpawnFunction), "QC function SV_OnEntityNoSpawnFunction is missing");
+ }
+ else
+ {
+
+ Con_DPrint("No spawn function for:\n");
+ if (developer.integer > 0) // don't confuse non-developers with errors
+ PRVM_ED_Print(prog, ent, NULL);
+
+ PRVM_ED_Free (prog, ent);
+ return false; // not included in "inhibited" count
+ }
+ }
+ else
+ {
+ // self = ent
+ PRVM_serverglobalfloat(time) = sv.time;
+ PRVM_allglobaledict(self) = PRVM_EDICT_TO_PROG(ent);
+ prog->ExecuteProgram(prog, func - prog->functions, "");
+ }
+ return true;
+ }
+ PRVM_ED_Free(prog, ent);
+ return false;
+}
+
+void PRVM_ED_CallPostspawnFunction (prvm_prog_t *prog, prvm_edict_t *ent)
+{
+ if(!ent->priv.required->free)
+ if (PRVM_serverfunction(SV_OnEntityPostSpawnFunction))
+ {
+ // self = ent
+ PRVM_serverglobalfloat(time) = sv.time;
+ PRVM_serverglobaledict(self) = PRVM_EDICT_TO_PROG(ent);
+ prog->ExecuteProgram(prog, PRVM_serverfunction(SV_OnEntityPostSpawnFunction), "QC function SV_OnEntityPostSpawnFunction is missing");
+ }
+}
/*
================
void PRVM_ED_LoadFromFile (prvm_prog_t *prog, const char *data)
{
prvm_edict_t *ent;
+ const char *start;
int parsed, inhibited, spawned, died;
- const char *funcname;
- mfunction_t *func;
- char vabuf[1024];
parsed = 0;
inhibited = 0;
prvm_reuseedicts_always_allow = host.realtime;
-// parse ents
+ // parse ents
while (1)
{
-// parse the opening brace
+ start = data;
+
+ // parse the opening brace
if (!COM_ParseToken_Simple(&data, false, false, true))
break;
if (com_token[0] != '{')
continue;
}
- if (PRVM_serverfunction(SV_OnEntityPreSpawnFunction))
- {
- // self = ent
- PRVM_serverglobalfloat(time) = sv.time;
- PRVM_serverglobaledict(self) = PRVM_EDICT_TO_PROG(ent);
- prog->ExecuteProgram(prog, PRVM_serverfunction(SV_OnEntityPreSpawnFunction), "QC function SV_OnEntityPreSpawnFunction is missing");
- }
+ PRVM_ED_CallPrespawnFunction(prog, ent);
if(ent->priv.required->free)
{
continue;
}
-//
-// immediately call spawn function, but only if there is a self global and a classname
-//
- if(!ent->priv.required->free)
- {
- if (!PRVM_alledictstring(ent, classname))
- {
- Con_Print("No classname for:\n");
- PRVM_ED_Print(prog, ent, NULL);
- PRVM_ED_Free (prog, ent);
- continue;
- }
-
- // look for the spawn function
- funcname = PRVM_GetString(prog, PRVM_alledictstring(ent, classname));
- func = PRVM_ED_FindFunction (prog, va(vabuf, sizeof(vabuf), "spawnfunc_%s", funcname));
- if(!func)
- if(!PRVM_allglobalfloat(require_spawnfunc_prefix))
- func = PRVM_ED_FindFunction (prog, funcname);
-
- if (!func)
- {
- // check for OnEntityNoSpawnFunction
- if (PRVM_serverfunction(SV_OnEntityNoSpawnFunction))
- {
- // self = ent
- PRVM_serverglobalfloat(time) = sv.time;
- PRVM_serverglobaledict(self) = PRVM_EDICT_TO_PROG(ent);
- prog->ExecuteProgram(prog, PRVM_serverfunction(SV_OnEntityNoSpawnFunction), "QC function SV_OnEntityNoSpawnFunction is missing");
- }
- else
- {
- if (developer.integer > 0) // don't confuse non-developers with errors
- {
- Con_Print("No spawn function for:\n");
- PRVM_ED_Print(prog, ent, NULL);
- }
- PRVM_ED_Free (prog, ent);
- continue; // not included in "inhibited" count
- }
- }
- else
- {
- // self = ent
- PRVM_serverglobalfloat(time) = sv.time;
- PRVM_allglobaledict(self) = PRVM_EDICT_TO_PROG(ent);
- prog->ExecuteProgram(prog, func - prog->functions, "");
- }
- }
-
- if(!ent->priv.required->free)
- if (PRVM_serverfunction(SV_OnEntityPostSpawnFunction))
- {
- // self = ent
- PRVM_serverglobalfloat(time) = sv.time;
- PRVM_serverglobaledict(self) = PRVM_EDICT_TO_PROG(ent);
- prog->ExecuteProgram(prog, PRVM_serverfunction(SV_OnEntityPostSpawnFunction), "QC function SV_OnEntityPostSpawnFunction is missing");
- }
+ if(!PRVM_ED_CallSpawnFunction(prog, ent, data, start))
+ continue;
+
+ PRVM_ED_CallPostspawnFunction(prog, ent);
spawned++;
if (ent->priv.required->free)
{
if (prog->loaded)
{
+ if(prog->tempstringsbuf.cursize)
+ Mem_Free(prog->tempstringsbuf.data);
+ prog->tempstringsbuf.cursize = 0;
PRVM_LeakTest(prog);
prog->reset_cmd(prog);
Mem_FreePool(&prog->progs_mempool);
prog->profiletime = Sys_DirtyTime();
prog->starttime = host.realtime;
- Con_DPrintf("%s programs occupy %iK.\n", prog->name, (int)(filesize/1024));
-
requiredglobalspace = 0;
for (i = 0;i < numrequiredglobals;i++)
requiredglobalspace += required_global[i].type == ev_vector ? 3 : 1;
if(!cvar)
{
const char *value;
- char buf[64];
+ char buf[128];
+ int prec[3];
+ float f;
Con_DPrintf("PRVM_LoadProgs: no cvar for autocvar global %s in %s, creating...\n", name, prog->name);
switch(prog->globaldefs[i].type & ~DEF_SAVEGLOBAL)
{
if((float)((int)(val->_float)) == val->_float)
dpsnprintf(buf, sizeof(buf), "%i", (int)(val->_float));
else
- dpsnprintf(buf, sizeof(buf), "%.9g", val->_float);
+ {
+ // ftos_slow
+ f = val->_float;
+ for (int precision = 7; precision <= 9; ++precision) {
+ dpsnprintf(buf, sizeof(buf), "%.*g", precision, f);
+ if ((float)atof(buf) == f) {
+ break;
+ }
+ }
+ }
value = buf;
break;
case ev_vector:
- dpsnprintf(buf, sizeof(buf), "%.9g %.9g %.9g", val->vector[0], val->vector[1], val->vector[2]); value = buf;
+ for (i = 0; i < 3; ++i)
+ {
+ prec[i] = 9;
+ f = val->vector[i];
+ for (int precision = 7; precision <= 9; ++precision) {
+ dpsnprintf(buf, sizeof(buf), "%.*g", precision, f);
+ if ((float)atof(buf) == f) {
+ prec[i] = precision;
+ break;
+ }
+ }
+ }
+ dpsnprintf(buf, sizeof(buf), "%.*g %.*g %.*g", prec[0], val->vector[0], prec[1], val->vector[1], prec[2], val->vector[2]);
+ value = buf;
break;
case ev_string:
value = PRVM_GetString(prog, val->string);
// init mempools
PRVM_MEM_Alloc(prog);
+ Con_Printf("%s: program loaded (crc %i, size %iK)\n", prog->name, prog->filecrc, (int)(filesize/1024));
+
// Inittime is at least the time when this function finished. However,
// later events may bump it.
prog->inittime = host.realtime;
return PRVM_KNOWNSTRINGBASE + i;
// new unknown engine string
if (developer_insane.integer)
- Con_DPrintf("new engine string %p = \"%s\"\n", s, s);
+ Con_DPrintf("new engine string %p = \"%s\"\n", (void *)s, s);
for (i = prog->firstfreeknownstring;i < prog->numknownstrings;i++)
if (!prog->knownstrings[i])
break;