libqfgamecode now builds. Now for the fun part: getting qw and nq to work using

the new setup.
This commit is contained in:
Bill Currie 2001-02-28 09:12:01 +00:00
parent b5d86d522d
commit dfaf767890
6 changed files with 88 additions and 57 deletions

View file

@ -30,6 +30,7 @@
#define _PROGS_H
#include "link.h"
#include "quakeio.h"
#include "pr_comp.h"
typedef union eval_s
@ -45,8 +46,10 @@ typedef union eval_s
typedef union pr_type_u {
float float_var;
int int_var;
string_t string_t_var;
func_t func_t_var;
string_t string_var;
func_t func_var;
int edict_var;
float vector_var[1]; // really 3, but this structure must be 32 bits
} pr_type_t;
#define MAX_ENT_LEAFS 16
@ -135,7 +138,9 @@ typedef void (*builtin_t) (progs_t *pr);
extern builtin_t *pr_builtins;
extern int pr_numbuiltins;
ddef_t *PR_FindGlobal (progs_t *pr, const char *name);
int FindFieldOffset (progs_t *pr, char *field);
eval_t *GETEDICTFIELDVALUE (edict_t *ed, int fieldoffset);
extern func_t EndFrame; // 2000-01-02 EndFrame function by Maddes/FrikaC
@ -210,7 +215,7 @@ struct progs_s {
edict_t **edicts;
int *num_edicts;
int *max_edicts;
int *reserved_edicts;
double *time;
int null_bad;
@ -218,6 +223,14 @@ struct progs_s {
void (*unlink)(edict_t *ent);
void (*flush)(void);
// required globals
float *g_time;
int *g_self;
// required fields (offsets into the edict)
int f_nextthink;
int f_frame;
int f_think;
};
#endif // _PROGS_H

View file

@ -61,7 +61,7 @@ int type_size[8] = {
};
ddef_t *ED_FieldAtOfs (progs_t * pr, int ofs);
qboolean ED_ParseEpair (progs_t * pr, void *base, ddef_t *key, char *s);
qboolean ED_ParseEpair (progs_t * pr, pr_type_t *base, ddef_t *key, char *s);
#define MAX_FIELD_LEN 64
#define GEFV_CACHESIZE 2
@ -99,8 +99,9 @@ ED_Alloc (progs_t * pr)
{
int i;
edict_t *e;
int start = pr->reserved_edicts ? *pr->reserved_edicts : 0;
for (i = MAX_CLIENTS + 1; i < *(pr)->num_edicts; i++) {
for (i = start + 1; i < *(pr)->num_edicts; i++) {
e = EDICT_NUM (pr, i);
// the first couple seconds of server time can involve a lot of
// freeing and allocating, so relax the replacement policy
@ -196,10 +197,10 @@ ED_FindField (progs_t * pr, char *name)
/*
ED_FindGlobal
PR_FindGlobal
*/
ddef_t *
ED_FindGlobal (progs_t * pr, char *name)
PR_FindGlobal (progs_t * pr, const char *name)
{
ddef_t *def;
int i;
@ -545,26 +546,27 @@ ED_Count (progs_t * pr)
int i;
edict_t *ent;
int active, models, solid, step;
ddef_t *solid_def;
ddef_t *model_def;
solid_def = ED_FindField (pr, "solid");
model_def = ED_FindField (pr, "model");
active = models = solid = step = 0;
for (i = 0; i < *(pr)->num_edicts; i++) {
ent = EDICT_NUM (pr, i);
if (ent->free)
continue;
active++;
if (ent->v.v.solid)
if (solid_def && ent->v[solid_def->ofs].float_var)
solid++;
if (ent->v.v.model)
if (model_def && ent->v[model_def->ofs].float_var)
models++;
if (ent->v.v.movetype == MOVETYPE_STEP)
step++;
}
Con_Printf ("num_edicts:%3i\n", *(pr)->num_edicts);
Con_Printf ("active :%3i\n", active);
Con_Printf ("view :%3i\n", models);
Con_Printf ("touch :%3i\n", solid);
Con_Printf ("step :%3i\n", step);
}
@ -632,13 +634,13 @@ ED_ParseGlobals (progs_t * pr, char *data)
if (com_token[0] == '}')
PR_Error (pr, "ED_ParseEntity: closing brace without data");
key = ED_FindGlobal (pr, keyname);
key = PR_FindGlobal (pr, keyname);
if (!key) {
Con_Printf ("'%s' is not a global\n", keyname);
continue;
}
if (!ED_ParseEpair (pr, (void *) pr->pr_globals, key, com_token))
if (!ED_ParseEpair (pr, pr->pr_globals, key, com_token))
PR_Error (pr, "ED_ParseGlobals: parse error");
}
}
@ -681,24 +683,24 @@ ED_NewString (progs_t * pr, char *string)
returns false if error
*/
qboolean
ED_ParseEpair (progs_t * pr, void *base, ddef_t *key, char *s)
ED_ParseEpair (progs_t * pr, pr_type_t *base, ddef_t *key, char *s)
{
int i;
char string[128];
ddef_t *def;
char *v, *w;
void *d;
eval_t *d;
dfunction_t *func;
d = (void *) ((int *) base + key->ofs);
d = (eval_t*)&base[key->ofs];
switch (key->type & ~DEF_SAVEGLOBAL) {
case ev_string:
*(string_t *) d = PR_SetString (pr, ED_NewString (pr, s));
d->string = PR_SetString (pr, ED_NewString (pr, s));
break;
case ev_float:
*(float *) d = atof (s);
d->_float = atof (s);
break;
case ev_vector:
@ -709,13 +711,13 @@ ED_ParseEpair (progs_t * pr, void *base, ddef_t *key, char *s)
while (*v && *v != ' ')
v++;
*v = 0;
((float *) d)[i] = atof (w);
d->vector[i] = atof (w);
w = v = v + 1;
}
break;
case ev_entity:
*(int *) d = EDICT_TO_PROG (pr, EDICT_NUM (pr, atoi (s)));
d->edict = EDICT_TO_PROG (pr, EDICT_NUM (pr, atoi (s)));
break;
case ev_field:
@ -724,7 +726,7 @@ ED_ParseEpair (progs_t * pr, void *base, ddef_t *key, char *s)
Con_Printf ("Can't find field %s\n", s);
return false;
}
*(int *) d = G_INT (pr, def->ofs);
d->_int = G_INT (pr, def->ofs);
break;
case ev_function:
@ -733,7 +735,7 @@ ED_ParseEpair (progs_t * pr, void *base, ddef_t *key, char *s)
Con_Printf ("Can't find function %s\n", s);
return false;
}
*(func_t *) d = func - pr->pr_functions;
d->function = func - pr->pr_functions;
break;
default:
@ -819,10 +821,9 @@ ED_ParseEdict (progs_t * pr, char *data, edict_t *ent)
int ret;
if (anglehack) {
ret = ED_ParseEpair (pr, (void *) &ent->v, key,
va ("0 %s 0", com_token));
ret = ED_ParseEpair (pr, ent->v, key, va ("0 %s 0", com_token));
} else {
ret = ED_ParseEpair (pr, (void *) &ent->v, key, com_token);
ret = ED_ParseEpair (pr, ent->v, key, com_token);
}
if (!ret)
PR_Error (pr, "ED_ParseEdict: parse error");
@ -855,14 +856,16 @@ ED_LoadFromFile (progs_t * pr, char *data)
edict_t *ent;
int inhibit;
dfunction_t *func;
eval_t *classname;
ent = NULL;
inhibit = 0;
pr->pr_global_struct->time = *(pr)->time;
// parse ents
*pr->g_time = *(pr)->time;
// parse ents
while (1) {
// parse the opening brace
// parse the opening brace
data = COM_Parse (data);
if (!data)
break;
@ -875,23 +878,24 @@ ED_LoadFromFile (progs_t * pr, char *data)
ent = ED_Alloc (pr);
data = ED_ParseEdict (pr, data, ent);
// remove things from different skill levels or deathmatch
// remove things from different skill levels or deathmatch
if (ED_Prune_Edict (pr, ent)) {
ED_Free (pr, ent);
inhibit++;
continue;
}
//
// immediately call spawn function
//
if (!ent->v.v.classname) {
//
// immediately call spawn function
//
classname = GETEDICTFIELDVALUE (ent, FindFieldOffset (pr, "classname"));
if (classname) {
Con_Printf ("No classname for:\n");
ED_Print (pr, ent);
ED_Free (pr, ent);
continue;
}
// look for the spawn function
func = ED_FindFunction (pr, PR_GetString (pr, ent->v.v.classname));
func = ED_FindFunction (pr, PR_GetString (pr, classname->string));
if (!func) {
Con_Printf ("No spawn function for:\n");
@ -900,7 +904,7 @@ ED_LoadFromFile (progs_t * pr, char *data)
continue;
}
pr->pr_global_struct->self = EDICT_TO_PROG (pr, ent);
*pr->g_self = EDICT_TO_PROG (pr, ent);
PR_ExecuteProgram (pr, func - pr->pr_functions);
if (pr->flush)
pr->flush ();
@ -917,6 +921,7 @@ PR_LoadProgs (progs_t * pr, char *progsname)
{
int i;
dstatement_t *st;
ddef_t *def;
// flush the non-C variable lookup cache
for (i = 0; i < GEFV_CACHESIZE; i++)
@ -928,18 +933,16 @@ PR_LoadProgs (progs_t * pr, char *progsname)
Con_DPrintf ("Programs occupy %iK.\n", com_filesize / 1024);
// store prog crc
// store prog crc
pr->crc = CRC_Block ((byte *) pr->progs, com_filesize);
// byte swap the header
// byte swap the header
for (i = 0; i < sizeof (*pr->progs) / 4; i++)
((int *) pr->progs)[i] = LittleLong (((int *) pr->progs)[i]);
if (pr->progs->version != PROG_VERSION)
PR_Error (pr, "progs.dat has wrong version number (%i should be %i)",
pr->progs->version, PROG_VERSION);
if (pr->progs->crc != PROGHEADER_CRC)
PR_Error (pr, "You must have the qwprogs.dat from QuakeWorld installed");
PR_Error (pr, "%s has wrong version number (%i should be %i)",
progsname, pr->progs->version, PROG_VERSION);
pr->pr_functions =
(dfunction_t *) ((byte *) pr->progs + pr->progs->ofs_functions);
@ -999,6 +1002,21 @@ PR_LoadProgs (progs_t * pr, char *progsname)
for (i = 0; i < pr->progs->numglobals; i++)
((int *) pr->pr_globals)[i] = LittleLong (((int *) pr->pr_globals)[i]);
def = PR_FindGlobal (pr, "time");
if (!def)
PR_Error (pr, "%s: undefined symbol: time", progsname);
pr->g_time = &pr->pr_globals[def->ofs].float_var;
def = PR_FindGlobal (pr, "self");
if (!def)
PR_Error (pr, "%s: undefined symbol: self", progsname);
pr->g_self = &pr->pr_globals[def->ofs].edict_var;
if (!(pr->f_nextthink = FindFieldOffset (pr, "nextthink")))
PR_Error (pr, "%s: undefined field: nextthink", progsname);
if (!(pr->f_frame = FindFieldOffset (pr, "frame")))
PR_Error (pr, "%s: undefined field: frame", progsname);
if (!(pr->f_think = FindFieldOffset (pr, "function")))
PR_Error (pr, "%s: undefined field: function", progsname);
// LordHavoc: Ender added this
FindEdictFieldOffsets (pr);

View file

@ -40,9 +40,7 @@
#include "console.h"
#include "cvar.h"
#include "host.h"
#include "progs.h"
#include "server.h"
#include "sys.h"
char *pr_opnames[] = {
@ -249,10 +247,10 @@ PR_RunError (progs_t * pr, char *error, ...)
PR_StackTrace (pr);
Con_Printf ("%s\n", string);
pr->pr_depth = 0; // dump the stack so SV_Error can
pr->pr_depth = 0; // dump the stack so PR_Error can
// shutdown functions
SV_Error ("Program error");
PR_Error (pr, "Program error");
}
/*
@ -311,7 +309,7 @@ PR_LeaveFunction (progs_t * pr)
int i, c;
if (pr->pr_depth <= 0)
SV_Error ("prog stack underflow");
PR_Error (pr, "prog stack underflow");
// restore locals from the stack
c = pr->pr_xfunction->locals;
@ -354,9 +352,9 @@ PR_ExecuteProgram (progs_t * pr, func_t fnum)
int profile, startprofile;
if (!fnum || fnum >= pr->progs->numfunctions) {
if (pr->pr_global_struct->self)
ED_Print (pr, PROG_TO_EDICT (pr, pr->pr_global_struct->self));
SV_Error ("PR_ExecuteProgram: NULL function");
if (*pr->g_self)
ED_Print (pr, PROG_TO_EDICT (pr, *pr->g_self));
PR_Error (pr, "PR_ExecuteProgram: NULL function");
}
f = &pr->pr_functions[fnum];
@ -677,10 +675,10 @@ PR_ExecuteProgram (progs_t * pr, func_t fnum)
return; // all done
break;
case OP_STATE:
ed = PROG_TO_EDICT (pr, pr->pr_global_struct->self);
ed->v.v.nextthink = pr->pr_global_struct->time + 0.1;
ed->v.v.frame = E_OPA->_float;
ed->v.v.think = E_OPB->function;
ed = PROG_TO_EDICT (pr, *pr->g_self);
ed->v[pr->f_nextthink].float_var = *pr->time + 0.1;
ed->v[pr->f_frame].float_var = E_OPA->_float;
ed->v[pr->f_think].func_var = E_OPB->function;
break;
// LordHavoc: to be enabled when Progs version 7 (or whatever it will be numbered) is finalized
/*

View file

@ -175,6 +175,7 @@ SV_Progs_Init (void)
sv_pr_state.edicts = &sv.edicts;
sv_pr_state.num_edicts = &sv.num_edicts;
sv_pr_state.time = &sv.time;
sv_pr_state.reserved_edicts = &svs.maxclients;
sv_pr_state.unlink = SV_UnlinkEdict;
Cmd_AddCommand ("edict", ED_PrintEdict_f,

View file

@ -46,8 +46,6 @@
extern int eval_alpha, eval_scale, eval_glowsize, eval_glowcolor,
eval_colormod;
// Ender Extends (QSG - End)
extern eval_t *GETEDICTFIELDVALUE (edict_t *ed, int fieldoffset);
/*
The PVS must include a small area around the client to allow head

View file

@ -52,6 +52,8 @@ func_t SpectatorConnect;
func_t SpectatorDisconnect;
func_t SpectatorThink;
static reserved_edicts = MAX_CLIENTS;
void
FindEdictFieldOffsets (progs_t *pr)
{
@ -154,6 +156,7 @@ SV_Progs_Init (void)
sv_pr_state.edicts = &sv.edicts;
sv_pr_state.num_edicts = &sv.num_edicts;
sv_pr_state.time = &sv.time;
sv_pr_state.reserved_edicts = &reserved_edicts;
sv_pr_state.unlink = SV_UnlinkEdict;
sv_pr_state.flush = SV_FlushSignon;