More formulaic registration of various qc extension fields+funcs, including some that are still unused in this revision.

This commit is contained in:
Shpoike 2020-09-03 11:08:13 +01:00
parent 2e92fbf1d4
commit e04c097eb8
5 changed files with 178 additions and 137 deletions

View file

@ -34,13 +34,6 @@ char *PR_GetTempString (void)
#define RETURN_EDICT(e) (((int *)qcvm->globals)[OFS_RETURN] = EDICT_TO_PROG(e))
#define MSG_BROADCAST 0 // unreliable to all
#define MSG_ONE 1 // reliable to one (msg_entity)
#define MSG_ALL 2 // reliable to all
#define MSG_INIT 3 // write to the init string
#define MSG_EXT_MULTICAST 4 // temporary buffer that can be splurged more reliably / with more control.
#define MSG_EXT_ENTITY 5 // for csqc networking. we don't actually support this. I'm just defining it for completeness.
/*
===============================================================================

View file

@ -1273,26 +1273,13 @@ qboolean PR_LoadProgs (const char *filename, qboolean fatal, unsigned int needcr
qcvm->numbuiltins = numbuiltins;
//spike: detect extended fields from progs
qcvm->extfields.items2 = ED_FindFieldOffset("items2");
qcvm->extfields.gravity = ED_FindFieldOffset("gravity");
qcvm->extfields.alpha = ED_FindFieldOffset("alpha");
qcvm->extfields.movement = ED_FindFieldOffset("movement");
qcvm->extfields.traileffectnum = ED_FindFieldOffset("traileffectnum");
qcvm->extfields.emiteffectnum = ED_FindFieldOffset("emiteffectnum");
qcvm->extfields.viewmodelforclient = ED_FindFieldOffset("viewmodelforclient");
qcvm->extfields.exteriormodeltoclient = ED_FindFieldOffset("exteriormodeltoclient");
qcvm->extfields.scale = ED_FindFieldOffset("scale");
qcvm->extfields.colormod = ED_FindFieldOffset("colormod");
qcvm->extfields.tag_entity = ED_FindFieldOffset("tag_entity");
qcvm->extfields.tag_index = ED_FindFieldOffset("tag_index");
qcvm->extfields.button3 = ED_FindFieldOffset("button3");
qcvm->extfields.button4 = ED_FindFieldOffset("button4");
qcvm->extfields.button5 = ED_FindFieldOffset("button5");
qcvm->extfields.button6 = ED_FindFieldOffset("button6");
qcvm->extfields.button7 = ED_FindFieldOffset("button7");
qcvm->extfields.button8 = ED_FindFieldOffset("button8");
qcvm->extfields.viewzoom = ED_FindFieldOffset("viewzoom");
qcvm->extfields.modelflags = ED_FindFieldOffset("modelflags");
#define QCEXTFIELD(n,t) qcvm->extfields.n = ED_FindFieldOffset(#n);
QCEXTFIELDS_ALL
QCEXTFIELDS_GAME
QCEXTFIELDS_CL
QCEXTFIELDS_CS
QCEXTFIELDS_SS
#undef QCEXTFIELD
i = qcvm->progs->entityfields;
if (qcvm->extfields.emiteffectnum < 0)

View file

@ -5535,19 +5535,19 @@ static size_t hostCacheSortCount;
static size_t hostCacheSort[HOSTCACHESIZE];
static enum hostfield_e serversort_field;
static int serversort_descending;
static void PF_gethostcachevalue(void)
{
enum{
enum hostcacheprop_e {
SLIST_HOSTCACHEVIEWCOUNT,
SLIST_HOSTCACHETOTALCOUNT,
SLIST_MASTERQUERYCOUNT,
SLIST_MASTERREPLYCOUNT,
SLIST_SERVERQUERYCOUNT,
SLIST_SERVERREPLYCOUNT,
SLIST_MASTERQUERYCOUNT_DP,
SLIST_MASTERREPLYCOUNT_DP,
SLIST_SERVERQUERYCOUNT_DP,
SLIST_SERVERREPLYCOUNT_DP,
SLIST_SORTFIELD,
SLIST_SORTDESCENDING
} fld = G_FLOAT(OFS_PARM0);
switch(fld)
};
static void PF_gethostcachevalue(void)
{
switch((enum hostcacheprop_e)G_FLOAT(OFS_PARM0))
{
case SLIST_HOSTCACHEVIEWCOUNT:
G_FLOAT(OFS_RETURN) = hostCacheSortCount?hostCacheSortCount:hostCacheCount;
@ -5555,10 +5555,10 @@ static void PF_gethostcachevalue(void)
case SLIST_HOSTCACHETOTALCOUNT:
G_FLOAT(OFS_RETURN) = hostCacheCount;
break;
case SLIST_MASTERQUERYCOUNT:
case SLIST_MASTERREPLYCOUNT:
case SLIST_SERVERQUERYCOUNT:
case SLIST_SERVERREPLYCOUNT:
case SLIST_MASTERQUERYCOUNT_DP:
case SLIST_MASTERREPLYCOUNT_DP:
case SLIST_SERVERQUERYCOUNT_DP:
case SLIST_SERVERREPLYCOUNT_DP:
G_FLOAT(OFS_RETURN) = 0;
break;
case SLIST_SORTFIELD:
@ -6758,9 +6758,12 @@ void PR_EnableExtensions(ddef_t *pr_globaldefs)
return;
}
//replace standard builtins with new replacement extended ones.
#define QCEXTFUNC(n,t) qcvm->extfuncs.n = PR_FindExtFunction(#n);
QCEXTFUNCS_COMMON
//replace standard builtins with new replacement extended ones and selectively populate references to module-specific entrypoints.
if (qcvm == &cl.qcvm)
{
{ //csqc
for (i = 0; i < sizeof(extensionbuiltins) / sizeof(extensionbuiltins[0]); i++)
{
int num = (extensionbuiltins[i].documentednumber);
@ -6768,17 +6771,11 @@ void PR_EnableExtensions(ddef_t *pr_globaldefs)
qcvm->builtins[num] = extensionbuiltins[i].csqcfunc;
}
//csqc entrypoints
qcvm->extfuncs.CSQC_Init = PR_FindExtFunction("CSQC_Init");
qcvm->extfuncs.CSQC_DrawHud = PR_FindExtFunction("CSQC_DrawHud");
qcvm->extfuncs.CSQC_DrawScores = PR_FindExtFunction("CSQC_DrawScores");
qcvm->extfuncs.CSQC_InputEvent = PR_FindExtFunction("CSQC_InputEvent");
qcvm->extfuncs.CSQC_ConsoleCommand = PR_FindExtFunction("CSQC_ConsoleCommand");
qcvm->extfuncs.CSQC_Parse_Event = PR_FindExtFunction("CSQC_Parse_Event");
qcvm->extfuncs.CSQC_Parse_Damage = PR_FindExtFunction("CSQC_Parse_Damage");
QCEXTFUNCS_GAME
QCEXTFUNCS_CS
}
else if (qcvm == &sv.qcvm)
{
{ //ssqc
for (i = 0; i < sizeof(extensionbuiltins) / sizeof(extensionbuiltins[0]); i++)
{
int num = (extensionbuiltins[i].documentednumber);
@ -6786,12 +6783,11 @@ void PR_EnableExtensions(ddef_t *pr_globaldefs)
qcvm->builtins[num] = extensionbuiltins[i].ssqcfunc;
}
//ssqc entrypoints
qcvm->extfuncs.SV_ParseClientCommand = PR_FindExtFunction("SV_ParseClientCommand");
qcvm->extfuncs.EndFrame = PR_FindExtFunction("EndFrame");
QCEXTFUNCS_GAME
QCEXTFUNCS_SV
}
else if (qcvm == &cls.menu_qcvm)
{
{ //menuqc
for (i = 0; i < sizeof(extensionbuiltins) / sizeof(extensionbuiltins[0]); i++)
{
int num = (extensionbuiltins[i].documentednumber_menuqc);
@ -6799,27 +6795,16 @@ void PR_EnableExtensions(ddef_t *pr_globaldefs)
qcvm->builtins[num] = extensionbuiltins[i].menufunc;
}
//menuqc entrypoints
qcvm->extfuncs.m_init = PR_FindExtFunction("m_init");
qcvm->extfuncs.m_toggle = PR_FindExtFunction("m_toggle");
qcvm->extfuncs.m_draw = PR_FindExtFunction("m_draw");
qcvm->extfuncs.m_keydown = PR_FindExtFunction("m_keydown");
qcvm->extfuncs.m_keyup = PR_FindExtFunction("m_keyup");
qcvm->extfuncs.m_consolecommand = PR_FindExtFunction("m_consolecommand");
qcvm->extfuncs.Menu_InputEvent = PR_FindExtFunction("Menu_InputEvent");
QCEXTFUNCS_MENU
}
#undef QCEXTFUNC
//general entrypoints
qcvm->extfuncs.GameCommand = PR_FindExtFunction("GameCommand");
qcvm->extglobals.time = PR_FindExtGlobal(ev_float, "time");
qcvm->extglobals.frametime = PR_FindExtGlobal(ev_float, "frametime");
qcvm->extglobals.cltime = PR_FindExtGlobal(ev_float, "cltime");
qcvm->extglobals.maxclients = PR_FindExtGlobal(ev_float, "maxclients");
qcvm->extglobals.intermission = PR_FindExtGlobal(ev_float, "intermission");
qcvm->extglobals.intermission_time = PR_FindExtGlobal(ev_float, "intermission_time");
qcvm->extglobals.player_localnum = PR_FindExtGlobal(ev_float, "player_localnum");
qcvm->extglobals.player_localentnum = PR_FindExtGlobal(ev_float, "player_localentnum");
#define QCEXTGLOBAL_FLOAT(n) qcvm->extglobals.n = PR_FindExtGlobal(ev_float, #n);
QCEXTGLOBALS_COMMON
QCEXTGLOBALS_GAME
QCEXTGLOBALS_CSQC
#undef QCEXTGLOBAL_FLOAT
//any #0 functions are remapped to their builtins here, so we don't have to tweak the VM in an obscure potentially-breaking way.
for (i = 0; i < (unsigned int)qcvm->progs->numfunctions; i++)

View file

@ -149,6 +149,8 @@ void ED_PrintNum (int ent);
eval_t *GetEdictFieldValue(edict_t *ed, int fldofs); //handles invalid offsets with a null
int ED_FindFieldOffset (const char *name);
#define GetEdictFieldValid(fld) (qcvm->extfields.fld>=0)
#define GetEdictFieldEval(ed,fld) ((eval_t *)((char *)&ed->v + qcvm->extfields.fld*4)) //caller must validate the field first
//from pr_cmds, no longer static so that pr_ext can use them.
sizebuf_t *WriteDest (void);
@ -160,80 +162,147 @@ char *PF_VarString (int first);
void PF_Fixme(void); //the 'unimplemented' builtin. woot.
struct pr_extfuncs_s
{ //various global ssqc entry points that might be called by the engine, if set.
func_t EndFrame;
func_t SV_ParseClientCommand;
{
/*all vms*/
#define QCEXTFUNCS_COMMON \
QCEXTFUNC(GameCommand, "void(string cmdtext)") /*obsoleted by m_consolecommand, included for dp compat.*/ \
/*csqc+ssqc*/
#define QCEXTFUNCS_GAME \
QCEXTFUNC(EndFrame, "void()") \
/*ssqc*/
#define QCEXTFUNCS_SV \
QCEXTFUNC(SV_ParseClientCommand, "void(string cmd)") \
QCEXTFUNC(SV_RunClientCommand, "void()") \
/*csqc*/
#define QCEXTFUNCS_CS \
QCEXTFUNC(CSQC_Init, "void(float apilevel, string enginename, float engineversion)") \
QCEXTFUNC(CSQC_Shutdown, "void()") \
QCEXTFUNC(CSQC_DrawHud, "void(vector virtsize, float showscores)") /*simple: for the simple(+limited) hud-only csqc interface.*/ \
QCEXTFUNC(CSQC_DrawScores, "void(vector virtsize, float showscores)") /*simple: (optional) for the simple hud-only csqc interface.*/ \
QCEXTFUNC(CSQC_InputEvent, "float(float evtype, float scanx, float chary, float devid)") \
QCEXTFUNC(CSQC_ConsoleCommand, "float(string cmdstr)") \
QCEXTFUNC(CSQC_Parse_Event, "void()") \
QCEXTFUNC(CSQC_Parse_Damage, "float(float save, float take, vector dir)") \
QCEXTFUNC(CSQC_UpdateView, "void(float vwidth, float vheight, float notmenu)") /*full only: for the full csqc-draws-entire-screen interface*/ \
QCEXTFUNC(CSQC_Input_Frame, "void()") /*full only: input angles stuff.*/ \
QCEXTFUNC(CSQC_Parse_CenterPrint, "float(string msg)") \
QCEXTFUNC(CSQC_Parse_Print, "void(string printmsg, float printlvl)") \
QCEXTFUNC(CSQC_Ent_Update, "void(float isnew)") /*full: lots of reads needed to interpret the bytestream*/ \
QCEXTFUNC(CSQC_Ent_Remove, "void()") /*full: basically just remove(self)*/\
QCEXTFUNC(CSQC_Parse_TempEntity, "float()") /*full: evil... This is the bane of all protocol compatibility. Die.*/ \
QCEXTFUNC(CSQC_Parse_StuffCmd, "void(string msg)") /*full only: not in simple. Too easy to make cheats by ignoring server messages.*/ \
/*menucsqc*/
#define QCEXTFUNCS_MENU \
QCEXTFUNC(m_init, "void()") \
QCEXTFUNC(m_toggle, "void(float wantmode)") /*-1: toggle, 0: clear, 1: force*/ \
QCEXTFUNC(m_draw, "void(vector screensize)") \
QCEXTFUNC(m_keydown, "void(float scan, float chr)") /*obsoleted by Menu_InputEvent, included for dp compat.*/ \
QCEXTFUNC(m_keyup, "void(float scan, float chr)") /*obsoleted by Menu_InputEvent, included for dp compat.*/ \
QCEXTFUNC(m_consolecommand, "float(string cmd)") \
QCEXTFUNC(Menu_InputEvent, "float(float evtype, float scanx, float chary, float devid)") \
//csqc-specific entry points
func_t CSQC_Init;
func_t CSQC_DrawHud; //for the simple hud-only csqc interface.
func_t CSQC_DrawScores; //(optional) for the simple hud-only csqc interface.
func_t CSQC_InputEvent;
func_t CSQC_ConsoleCommand;
func_t CSQC_Parse_Event;
func_t CSQC_Parse_Damage;
//todo...
// func_t CSQC_Parse_CenterPrint;
// func_t CSQC_Parse_Print;
// func_t CSQC_Parse_TempEntity; //evil... This is the bane of all protocol compatibility. Die.
// func_t CSQC_Parse_StuffCmd; //not in simple. Too easy to make cheats by ignoring server messages.
//menuqc-specific entry points
func_t m_init;
func_t m_toggle; //-1: toggle, 0: clear, 1: force
func_t m_draw;
func_t m_keydown; //obsoleted by Menu_InputEvent, included for dp compat.
func_t m_keyup; //obsoleted by Menu_InputEvent, included for dp compat.
func_t m_consolecommand;
func_t Menu_InputEvent;
//generic entry points, albeit not necessarily implemented for more than one module.
func_t GameCommand;//obsoleted by m_consolecommand, included for dp compat.
#define QCEXTFUNC(n,t) func_t n;
QCEXTFUNCS_COMMON
QCEXTFUNCS_GAME
QCEXTFUNCS_SV
QCEXTFUNCS_CS
QCEXTFUNCS_MENU
#undef QCEXTFUNC
};
extern cvar_t pr_checkextension; //if 0, extensions are disabled (unless they'd be fatal, but they're still spammy)
struct pr_extglobals_s
{
//menuqc things...
float *time;
float *frametime;
//csqc-specific globals...
float *cltime;
float *maxclients;
float *intermission;
float *intermission_time;
float *player_localnum;
float *player_localentnum;
//float *clientcommandframe; //we don't have prediction.
//float *servercommandframe; //we don't have prediction.
#define QCEXTGLOBALS_COMMON \
QCEXTGLOBAL_FLOAT(time)\
QCEXTGLOBAL_FLOAT(frametime)\
//end
#define QCEXTGLOBALS_GAME \
QCEXTGLOBAL_FLOAT(input_timelength)\
QCEXTGLOBAL_FLOAT(input_movevalues)\
QCEXTGLOBAL_FLOAT(input_angles)\
QCEXTGLOBAL_FLOAT(input_buttons)\
QCEXTGLOBAL_FLOAT(input_impulse)\
QCEXTGLOBAL_FLOAT(physics_mode)\
//end
#define QCEXTGLOBALS_CSQC \
QCEXTGLOBAL_FLOAT(cltime)\
QCEXTGLOBAL_FLOAT(maxclients)\
QCEXTGLOBAL_FLOAT(intermission)\
QCEXTGLOBAL_FLOAT(intermission_time)\
QCEXTGLOBAL_FLOAT(player_localnum)\
QCEXTGLOBAL_FLOAT(player_localentnum)\
QCEXTGLOBAL_FLOAT(view_angles)\
QCEXTGLOBAL_FLOAT(clientcommandframe)\
QCEXTGLOBAL_FLOAT(servercommandframe)\
//end
#define QCEXTGLOBAL_FLOAT(n) float *n;
QCEXTGLOBALS_COMMON
QCEXTGLOBALS_GAME
QCEXTGLOBALS_CSQC
#undef QCEXTGLOBAL_FLOAT
};
struct pr_extfields_s
{ //various fields that might be wanted by the engine. -1 == invalid
//I should probably use preprocessor magic for this list or something
int items2; //float
int gravity; //float
int alpha; //float
int movement; //vector
int viewmodelforclient; //entity
int exteriormodeltoclient; //entity
int traileffectnum; //float
int emiteffectnum; //float
int scale; //float
int colormod; //vector
int tag_entity; //entity
int tag_index; //float
int button3; //float
int button4; //float
int button5; //float
int button6; //float
int button7; //float
int button8; //float
int viewzoom; //float
int modelflags; //float, the upper 8 bits of .effects
//REMEMBER TO ADD THESE TO qsextensions.qc AND pr_edict.c
#define QCEXTFIELDS_ALL \
/*renderscene means we need a number of fields here*/ \
QCEXTFIELD(alpha, ".float") /*float*/ \
QCEXTFIELD(scale, ".float") /*float*/ \
QCEXTFIELD(colormod, ".vector") /*vector*/ \
QCEXTFIELD(tag_entity, ".entity") /*entity*/ \
QCEXTFIELD(tag_index, ".float") /*float*/ \
QCEXTFIELD(modelflags, ".float") /*float, the upper 8 bits of .effects*/ \
QCEXTFIELD(origin, ".vector") /*for menuqc's addentity builtin.*/ \
QCEXTFIELD(angles, ".vector") /*for menuqc's addentity builtin.*/ \
QCEXTFIELD(frame, ".float") /*for menuqc's addentity builtin.*/ \
QCEXTFIELD(skin, ".float") /*for menuqc's addentity builtin.*/ \
/*end of list*/
#define QCEXTFIELDS_GAME \
/*stuff used by csqc+ssqc, but not menu*/ \
QCEXTFIELD(customphysics, ".void()")/*function*/ \
QCEXTFIELD(gravity, ".float") /*float*/ \
//end of list
#define QCEXTFIELDS_CL \
QCEXTFIELD(frame2, ".float") /*for csqc's addentity builtin.*/ \
QCEXTFIELD(lerpfrac, ".float") /*for csqc's addentity builtin.*/ \
QCEXTFIELD(frame1time, ".float") /*for csqc's addentity builtin.*/ \
QCEXTFIELD(frame2time, ".float") /*for csqc's addentity builtin.*/ \
QCEXTFIELD(renderflags, ".float") /*for csqc's addentity builtin.*/ \
//end of list
#define QCEXTFIELDS_CS \
/*csqc-only*/ \
QCEXTFIELD(entnum, ".float") /*for csqc.*/ \
QCEXTFIELD(drawmask, ".float") /*for csqc's addentities builtin.*/ \
QCEXTFIELD(predraw, ".float()") /*for csqc's addentities builtin.*/ \
//end of list
#define QCEXTFIELDS_SS \
/*ssqc-only*/ \
QCEXTFIELD(items2, "//.float") /*float*/ \
QCEXTFIELD(movement, ".vector") /*vector*/ \
QCEXTFIELD(viewmodelforclient, ".entity") /*entity*/ \
QCEXTFIELD(exteriormodeltoclient, ".entity") /*entity*/ \
QCEXTFIELD(traileffectnum, ".float") /*float*/ \
QCEXTFIELD(emiteffectnum, ".float") /*float*/ \
QCEXTFIELD(button3, ".float") /*float*/ \
QCEXTFIELD(button4, ".float") /*float*/ \
QCEXTFIELD(button5, ".float") /*float*/ \
QCEXTFIELD(button6, ".float") /*float*/ \
QCEXTFIELD(button7, ".float") /*float*/ \
QCEXTFIELD(button8, ".float") /*float*/ \
QCEXTFIELD(viewzoom, ".float") /*float*/ \
QCEXTFIELD(SendEntity, ".float(entity to, float changedflags)") /*function*/ \
QCEXTFIELD(SendFlags, ".float") /*float. :( */ \
//end of list
#define QCEXTFIELD(n,t) int n;
QCEXTFIELDS_ALL
QCEXTFIELDS_GAME
QCEXTFIELDS_CL
QCEXTFIELDS_CS
QCEXTFIELDS_SS
#undef QCEXTFIELD
};
typedef struct

View file

@ -258,6 +258,13 @@ typedef struct client_s
#define SPAWNFLAG_NOT_HARD 1024
#define SPAWNFLAG_NOT_DEATHMATCH 2048
#define MSG_BROADCAST 0 // unreliable to all
#define MSG_ONE 1 // reliable to one (msg_entity)
#define MSG_ALL 2 // reliable to all
#define MSG_INIT 3 // write to the init string
#define MSG_EXT_MULTICAST 4 // temporary buffer that can be splurged more reliably / with more control.
#define MSG_EXT_ENTITY 5 // for csqc networking. we don't actually support this. I'm just defining it for completeness.
//============================================================================
extern cvar_t teamplay;