progs: hack around the remaining differences in pr_edict.c

PR_LoadProgs got a bit messy, but there's still plenty of common code to
make this worthwhile.

Signed-off-by: Kevin Shanahan <kmshanah@disenchant.net>
This commit is contained in:
Kevin Shanahan 2012-11-12 16:30:01 +10:30
parent c139514d85
commit 4afe9347b6
2 changed files with 210 additions and 16 deletions

View File

@ -29,12 +29,17 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "world.h"
#include "zone.h"
#ifdef NQ_HACK
#include "host.h"
#include "quakedef.h"
#include "sys.h"
/* FIXME - quick hack to enable merging of NQ/QWSV shared code */
#define SV_Error Sys_Error
#endif
#if defined(QW_HACK) && defined(SERVERONLY)
#include "qwsvdef.h"
#endif
dprograms_t *progs;
dfunction_t *pr_functions;
@ -48,8 +53,6 @@ int pr_edict_size; // in bytes
static ddef_t *pr_fielddefs;
static ddef_t *pr_globaldefs;
unsigned short pr_crc;
/*
* These are the sizes of the types enumerated in etype_t (pr_comp.h)
*/
@ -76,6 +79,8 @@ typedef struct {
static gefv_cache gefvCache[GEFV_CACHESIZE] = { {NULL, ""}, {NULL, ""} };
#ifdef NQ_HACK
unsigned short pr_crc;
cvar_t nomonsters = { "nomonsters", "0" };
static cvar_t gamecfg = { "gamecfg", "0" };
static cvar_t scratch1 = { "scratch1", "0" };
@ -87,6 +92,12 @@ static cvar_t saved1 = { "saved1", "0", true };
static cvar_t saved2 = { "saved2", "0", true };
static cvar_t saved3 = { "saved3", "0", true };
static cvar_t saved4 = { "saved4", "0", true };
#endif
#if defined(QW_HACK) && defined(SERVERONLY)
func_t SpectatorConnect;
func_t SpectatorThink;
func_t SpectatorDisconnect;
#endif
/*
=================
@ -119,7 +130,12 @@ ED_Alloc(void)
int i;
edict_t *e;
#ifdef NQ_HACK
for (i = svs.maxclients + 1; i < sv.num_edicts; i++) {
#endif
#if defined(QW_HACK) && defined(SERVERONLY)
for (i = MAX_CLIENTS + 1; i < sv.num_edicts; i++) {
#endif
e = EDICT_NUM(i);
// the first couple seconds of server time can involve a lot of
// freeing and allocating, so relax the replacement policy
@ -129,10 +145,21 @@ ED_Alloc(void)
}
}
#ifdef NQ_HACK
if (i == MAX_EDICTS)
SV_Error("%s: no free edicts", __func__);
sv.num_edicts++;
#endif
#if defined(QW_HACK) && defined(SERVERONLY)
if (i == MAX_EDICTS) {
Con_Printf("WARNING: ED_Alloc: no free edicts\n");
i--; // step on whatever is the last edict
e = EDICT_NUM(i);
SV_UnlinkEdict(e);
} else
sv.num_edicts++;
#endif
e = EDICT_NUM(i);
ED_ClearEdict(e);
@ -266,7 +293,6 @@ ED_FindFunction(char *name)
return NULL;
}
eval_t *
GetEdictFieldValue(edict_t *ed, char *field)
{
@ -296,7 +322,6 @@ GetEdictFieldValue(edict_t *ed, char *field)
return (eval_t *)((char *)&ed->v + def->ofs * 4);
}
/*
============
PR_ValueString
@ -705,7 +730,12 @@ ED_ParseGlobals(char *data)
}
if (!ED_ParseEpair((void *)pr_globals, key, com_token))
#ifdef NQ_HACK
Host_Error("%s: parse error", __func__);
#endif
#if defined(QW_HACK) && defined(SERVERONLY)
SV_Error("%s: parse error", __func__);
#endif
}
}
@ -895,7 +925,12 @@ ED_ParseEdict(char *data, edict_t *ent)
}
if (!ED_ParseEpair((void *)&ent->v, key, com_token))
#ifdef NQ_HACK
Host_Error("%s: parse error", __func__);
#endif
#if defined(QW_HACK) && defined(SERVERONLY)
SV_Error("%s: parse error", __func__);
#endif
}
if (!init)
@ -947,12 +982,15 @@ ED_LoadFromFile(char *data)
data = ED_ParseEdict(data, ent);
// remove things from different skill levels or deathmatch
#ifdef NQ_HACK
if (deathmatch.value) {
#endif
if (((int)ent->v.spawnflags & SPAWNFLAG_NOT_DEATHMATCH)) {
ED_Free(ent);
inhibit++;
continue;
}
#ifdef NQ_HACK
} else
if ((current_skill == 0
&& ((int)ent->v.spawnflags & SPAWNFLAG_NOT_EASY))
@ -964,6 +1002,8 @@ ED_LoadFromFile(char *data)
inhibit++;
continue;
}
#endif
//
// immediately call spawn function
//
@ -985,6 +1025,9 @@ ED_LoadFromFile(char *data)
pr_global_struct->self = EDICT_TO_PROG(ent);
PR_ExecuteProgram(func - pr_functions);
#if defined(QW_HACK) && defined(SERVERONLY)
SV_FlushSignon();
#endif
}
Con_DPrintf("%i entities inhibited\n", inhibit);
@ -1000,20 +1043,35 @@ void
PR_LoadProgs(void)
{
int i;
#if defined(QW_HACK) && defined(SERVERONLY)
char num[32];
dfunction_t *f;
#endif
// flush the non-C variable lookup cache
for (i = 0; i < GEFV_CACHESIZE; i++)
gefvCache[i].field[0] = 0;
CRC_Init(&pr_crc);
#ifdef NQ_HACK
progs = (dprograms_t *)COM_LoadHunkFile("progs.dat");
#endif
#if defined(QW_HACK) && defined(SERVERONLY)
progs = (dprograms_t *)COM_LoadHunkFile("qwprogs.dat");
if (!progs)
progs = (dprograms_t *)COM_LoadHunkFile("progs.dat");
#endif
if (!progs)
SV_Error("%s: couldn't load progs.dat", __func__);
Con_DPrintf("Programs occupy %iK.\n", com_filesize / 1024);
for (i = 0; i < com_filesize; i++)
CRC_ProcessByte(&pr_crc, ((byte *)progs)[i]);
#ifdef NQ_HACK
pr_crc = CRC_Block((byte *)progs, com_filesize);
#endif
#if defined(QW_HACK) && defined(SERVERONLY)
// add prog crc to the serverinfo
sprintf(num, "%i", CRC_Block((byte *)progs, com_filesize));
Info_SetValueForStarKey(svs.info, "*progs", num, MAX_SERVERINFO_STRING);
#endif
// byte swap the header
for (i = 0; i < sizeof(*progs) / 4; i++)
@ -1023,14 +1081,24 @@ PR_LoadProgs(void)
SV_Error("progs.dat has wrong version number (%i should be %i)",
progs->version, PROG_VERSION);
if (progs->crc != PROGHEADER_CRC)
#ifdef NQ_HACK
SV_Error("progs.dat system vars have been modified, "
"progdefs.h is out of date");
#endif
#if defined(QW_HACK) && defined(SERVERONLY)
SV_Error("You must have the progs.dat from QuakeWorld installed");
#endif
pr_functions = (dfunction_t *)((byte *)progs + progs->ofs_functions);
pr_strings = (char *)progs + progs->ofs_strings;
pr_strings_size = progs->strings_size;
if (progs->ofs_strings + pr_strings_size >= com_filesize)
#ifdef NQ_HACK
Host_Error("progs.dat strings extend past end of file\n");
#endif
#if defined(QW_HACK) && defined(SERVERONLY)
SV_Error("progs.dat strings extend past end of file\n");
#endif
PR_InitStringTable();
pr_globaldefs = (ddef_t *)((byte *)progs + progs->ofs_globaldefs);
@ -1077,6 +1145,18 @@ PR_LoadProgs(void)
for (i = 0; i < progs->numglobals; i++)
((int *)pr_globals)[i] = LittleLong(((int *)pr_globals)[i]);
#if defined(QW_HACK) && defined(SERVERONLY)
// Zoid, find the spectator functions
SpectatorConnect = SpectatorThink = SpectatorDisconnect = 0;
if ((f = ED_FindFunction("SpectatorConnect")) != NULL)
SpectatorConnect = (func_t)(f - pr_functions);
if ((f = ED_FindFunction("SpectatorThink")) != NULL)
SpectatorThink = (func_t)(f - pr_functions);
if ((f = ED_FindFunction("SpectatorDisconnect")) != NULL)
SpectatorDisconnect = (func_t)(f - pr_functions);
#endif
}
@ -1092,6 +1172,7 @@ PR_Init(void)
Cmd_AddCommand("edicts", ED_PrintEdicts);
Cmd_AddCommand("edictcount", ED_Count);
Cmd_AddCommand("profile", PR_Profile_f);
#ifdef NQ_HACK
Cvar_RegisterVariable(&nomonsters);
Cvar_RegisterVariable(&gamecfg);
Cvar_RegisterVariable(&scratch1);
@ -1103,13 +1184,18 @@ PR_Init(void)
Cvar_RegisterVariable(&saved2);
Cvar_RegisterVariable(&saved3);
Cvar_RegisterVariable(&saved4);
#endif
}
edict_t *
EDICT_NUM(int n)
{
#ifdef NQ_HACK
if (n < 0 || n >= sv.max_edicts)
#endif
#if defined(QW_HACK) && defined(SERVERONLY)
if (n < 0 || n >= MAX_EDICTS)
#endif
SV_Error("%s: bad number %i", __func__, n);
return (edict_t *)((byte *)sv.edicts + (n) * pr_edict_size);
}

View File

@ -29,7 +29,17 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "world.h"
#include "zone.h"
#ifdef NQ_HACK
#include "host.h"
#include "quakedef.h"
#include "sys.h"
/* FIXME - quick hack to enable merging of NQ/QWSV shared code */
#define SV_Error Sys_Error
#endif
#if defined(QW_HACK) && defined(SERVERONLY)
#include "qwsvdef.h"
#endif
dprograms_t *progs;
dfunction_t *pr_functions;
@ -69,10 +79,25 @@ typedef struct {
static gefv_cache gefvCache[GEFV_CACHESIZE] = { {NULL, ""}, {NULL, ""} };
#ifdef NQ_HACK
unsigned short pr_crc;
cvar_t nomonsters = { "nomonsters", "0" };
static cvar_t gamecfg = { "gamecfg", "0" };
static cvar_t scratch1 = { "scratch1", "0" };
static cvar_t scratch2 = { "scratch2", "0" };
static cvar_t scratch3 = { "scratch3", "0" };
static cvar_t scratch4 = { "scratch4", "0" };
static cvar_t savedgamecfg = { "savedgamecfg", "0", true };
static cvar_t saved1 = { "saved1", "0", true };
static cvar_t saved2 = { "saved2", "0", true };
static cvar_t saved3 = { "saved3", "0", true };
static cvar_t saved4 = { "saved4", "0", true };
#endif
#if defined(QW_HACK) && defined(SERVERONLY)
func_t SpectatorConnect;
func_t SpectatorThink;
func_t SpectatorDisconnect;
#endif
/*
=================
@ -105,7 +130,12 @@ ED_Alloc(void)
int i;
edict_t *e;
#ifdef NQ_HACK
for (i = svs.maxclients + 1; i < sv.num_edicts; i++) {
#endif
#if defined(QW_HACK) && defined(SERVERONLY)
for (i = MAX_CLIENTS + 1; i < sv.num_edicts; i++) {
#endif
e = EDICT_NUM(i);
// the first couple seconds of server time can involve a lot of
// freeing and allocating, so relax the replacement policy
@ -115,6 +145,12 @@ ED_Alloc(void)
}
}
#ifdef NQ_HACK
if (i == MAX_EDICTS)
SV_Error("%s: no free edicts", __func__);
sv.num_edicts++;
#endif
#if defined(QW_HACK) && defined(SERVERONLY)
if (i == MAX_EDICTS) {
Con_Printf("WARNING: ED_Alloc: no free edicts\n");
i--; // step on whatever is the last edict
@ -122,6 +158,8 @@ ED_Alloc(void)
SV_UnlinkEdict(e);
} else
sv.num_edicts++;
#endif
e = EDICT_NUM(i);
ED_ClearEdict(e);
@ -618,7 +656,7 @@ ED_Count(void)
/*
==============================================================================
ARCHIVING GLOBALS
ARCHIVING GLOBALS
FIXME: need to tag constants, doesn't really work
==============================================================================
@ -692,7 +730,12 @@ ED_ParseGlobals(char *data)
}
if (!ED_ParseEpair((void *)pr_globals, key, com_token))
#ifdef NQ_HACK
Host_Error("%s: parse error", __func__);
#endif
#if defined(QW_HACK) && defined(SERVERONLY)
SV_Error("%s: parse error", __func__);
#endif
}
}
@ -870,7 +913,7 @@ ED_ParseEdict(char *data, edict_t *ent)
key = ED_FindField(keyname);
if (!key) {
Con_Printf("%s is not a field\n", keyname);
Con_Printf("'%s' is not a field\n", keyname);
continue;
}
@ -882,7 +925,12 @@ ED_ParseEdict(char *data, edict_t *ent)
}
if (!ED_ParseEpair((void *)&ent->v, key, com_token))
#ifdef NQ_HACK
Host_Error("%s: parse error", __func__);
#endif
#if defined(QW_HACK) && defined(SERVERONLY)
SV_Error("%s: parse error", __func__);
#endif
}
if (!init)
@ -934,11 +982,28 @@ ED_LoadFromFile(char *data)
data = ED_ParseEdict(data, ent);
// remove things from different skill levels or deathmatch
if (((int)ent->v.spawnflags & SPAWNFLAG_NOT_DEATHMATCH)) {
#ifdef NQ_HACK
if (deathmatch.value) {
#endif
if (((int)ent->v.spawnflags & SPAWNFLAG_NOT_DEATHMATCH)) {
ED_Free(ent);
inhibit++;
continue;
}
#ifdef NQ_HACK
} else
if ((current_skill == 0
&& ((int)ent->v.spawnflags & SPAWNFLAG_NOT_EASY))
|| (current_skill == 1
&& ((int)ent->v.spawnflags & SPAWNFLAG_NOT_MEDIUM))
|| (current_skill >= 2
&& ((int)ent->v.spawnflags & SPAWNFLAG_NOT_HARD))) {
ED_Free(ent);
inhibit++;
continue;
}
#endif
//
// immediately call spawn function
//
@ -960,7 +1025,9 @@ ED_LoadFromFile(char *data)
pr_global_struct->self = EDICT_TO_PROG(ent);
PR_ExecuteProgram(func - pr_functions);
#if defined(QW_HACK) && defined(SERVERONLY)
SV_FlushSignon();
#endif
}
Con_DPrintf("%i entities inhibited\n", inhibit);
@ -976,23 +1043,35 @@ void
PR_LoadProgs(void)
{
int i;
#if defined(QW_HACK) && defined(SERVERONLY)
char num[32];
dfunction_t *f;
#endif
// flush the non-C variable lookup cache
for (i = 0; i < GEFV_CACHESIZE; i++)
gefvCache[i].field[0] = 0;
#ifdef NQ_HACK
progs = (dprograms_t *)COM_LoadHunkFile("progs.dat");
#endif
#if defined(QW_HACK) && defined(SERVERONLY)
progs = (dprograms_t *)COM_LoadHunkFile("qwprogs.dat");
if (!progs)
progs = (dprograms_t *)COM_LoadHunkFile("progs.dat");
#endif
if (!progs)
SV_Error("%s: couldn't load progs.dat", __func__);
Con_DPrintf("Programs occupy %iK.\n", com_filesize / 1024);
#ifdef NQ_HACK
pr_crc = CRC_Block((byte *)progs, com_filesize);
#endif
#if defined(QW_HACK) && defined(SERVERONLY)
// add prog crc to the serverinfo
sprintf(num, "%i", CRC_Block((byte *)progs, com_filesize));
Info_SetValueForStarKey(svs.info, "*progs", num, MAX_SERVERINFO_STRING);
#endif
// byte swap the header
for (i = 0; i < sizeof(*progs) / 4; i++)
@ -1002,13 +1081,24 @@ PR_LoadProgs(void)
SV_Error("progs.dat has wrong version number (%i should be %i)",
progs->version, PROG_VERSION);
if (progs->crc != PROGHEADER_CRC)
#ifdef NQ_HACK
SV_Error("progs.dat system vars have been modified, "
"progdefs.h is out of date");
#endif
#if defined(QW_HACK) && defined(SERVERONLY)
SV_Error("You must have the progs.dat from QuakeWorld installed");
#endif
pr_functions = (dfunction_t *)((byte *)progs + progs->ofs_functions);
pr_strings = (char *)progs + progs->ofs_strings;
pr_strings_size = progs->strings_size;
if (progs->ofs_strings + pr_strings_size >= com_filesize)
#ifdef NQ_HACK
Host_Error("progs.dat strings extend past end of file\n");
#endif
#if defined(QW_HACK) && defined(SERVERONLY)
SV_Error("progs.dat strings extend past end of file\n");
#endif
PR_InitStringTable();
pr_globaldefs = (ddef_t *)((byte *)progs + progs->ofs_globaldefs);
@ -1056,6 +1146,7 @@ PR_LoadProgs(void)
for (i = 0; i < progs->numglobals; i++)
((int *)pr_globals)[i] = LittleLong(((int *)pr_globals)[i]);
#if defined(QW_HACK) && defined(SERVERONLY)
// Zoid, find the spectator functions
SpectatorConnect = SpectatorThink = SpectatorDisconnect = 0;
@ -1065,6 +1156,7 @@ PR_LoadProgs(void)
SpectatorThink = (func_t)(f - pr_functions);
if ((f = ED_FindFunction("SpectatorDisconnect")) != NULL)
SpectatorDisconnect = (func_t)(f - pr_functions);
#endif
}
@ -1080,14 +1172,30 @@ PR_Init(void)
Cmd_AddCommand("edicts", ED_PrintEdicts);
Cmd_AddCommand("edictcount", ED_Count);
Cmd_AddCommand("profile", PR_Profile_f);
#ifdef NQ_HACK
Cvar_RegisterVariable(&nomonsters);
Cvar_RegisterVariable(&gamecfg);
Cvar_RegisterVariable(&scratch1);
Cvar_RegisterVariable(&scratch2);
Cvar_RegisterVariable(&scratch3);
Cvar_RegisterVariable(&scratch4);
Cvar_RegisterVariable(&savedgamecfg);
Cvar_RegisterVariable(&saved1);
Cvar_RegisterVariable(&saved2);
Cvar_RegisterVariable(&saved3);
Cvar_RegisterVariable(&saved4);
#endif
}
edict_t *
EDICT_NUM(int n)
{
#ifdef NQ_HACK
if (n < 0 || n >= sv.max_edicts)
#endif
#if defined(QW_HACK) && defined(SERVERONLY)
if (n < 0 || n >= MAX_EDICTS)
#endif
SV_Error("%s: bad number %i", __func__, n);
return (edict_t *)((byte *)sv.edicts + (n) * pr_edict_size);
}