add hud_miniscores_show cvar to hide the mini deathmatch overlay
fix some issues with ezhud. ownfrags, text alphas, RGB player colours. tweak gamecontroller input a little, to make axis slightly more usable. fix issue with menuqc/csqc not being able to query binds reliably. fix csqc gravitydir. bump r_particle_tracelimit so that its no longer a limitation by default. tweak fog to allow far-clip-plane culling on entities (but still not on world, due to issues with glClear). fix performance issue with q1bspx BRUSHLIST lump. fix mvd recording bug. fix limitation that becomes apparent on maps with lots of ents visible at once. will now use more bandwidth in such cases, however. git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@4994 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
parent
e03a8d9d41
commit
71319a8852
60 changed files with 1342 additions and 407 deletions
|
@ -1804,7 +1804,7 @@ void NPP_QWFlush(void)
|
|||
org[0] = (*(short*)&buffer[multicastpos])/8.0f;
|
||||
org[1] = (*(short*)&buffer[multicastpos+2])/8.0f;
|
||||
org[2] = (*(short*)&buffer[multicastpos+4])/8.0f;
|
||||
count = bound(0, buffer[2]*20, 255);
|
||||
count = bound(0, buffer[2]*20, 254); //255 is taken to mean an explosion, for some reason.
|
||||
if (minortype == TEQW_LIGHTNINGBLOOD)
|
||||
colour = 225;
|
||||
else
|
||||
|
|
|
@ -693,7 +693,7 @@ void PR_LoadGlabalStruct(qboolean muted)
|
|||
static float input_impulse_default;
|
||||
static vec3_t input_angles_default;
|
||||
static vec3_t input_movevalues_default;
|
||||
static vec3_t global_gravitydir_default;
|
||||
static vec3_t global_gravitydir_default = {0,0,-1};
|
||||
int i;
|
||||
int *v;
|
||||
globalptrs_t *pr_globals = pr_global_ptrs;
|
||||
|
@ -1115,7 +1115,8 @@ void PR_ApplyCompilation_f (void)
|
|||
{
|
||||
edict_t *ent;
|
||||
char *s;
|
||||
int len, i;
|
||||
size_t len;
|
||||
int i;
|
||||
if (sv.state < ss_active)
|
||||
{
|
||||
Con_Printf("Can't apply: Server isn't running or is still loading\n");
|
||||
|
@ -1248,7 +1249,7 @@ void PR_SSCoreDump_f(void)
|
|||
}
|
||||
|
||||
{
|
||||
int size = 1024*1024*8;
|
||||
size_t size = 1024*1024*8;
|
||||
char *buffer = BZ_Malloc(size);
|
||||
svprogfuncs->save_ents(svprogfuncs, buffer, &size, size, 3);
|
||||
COM_WriteFile("ssqccore.txt", FS_GAMEONLY, buffer, size);
|
||||
|
@ -3959,12 +3960,7 @@ void QCBUILTIN PF_precache_vwep_model (pubprogfuncs_t *prinst, struct globalvars
|
|||
G_FLOAT(OFS_RETURN) = 0;
|
||||
return;
|
||||
}
|
||||
#ifdef VM_Q1
|
||||
if (svs.gametype == GT_Q1QVM)
|
||||
sv.strings.vw_model_precache[i] = s;
|
||||
else
|
||||
#endif
|
||||
sv.strings.vw_model_precache[i] = PR_AddString(prinst, s, 0, false);
|
||||
sv.strings.vw_model_precache[i] = PR_AddString(prinst, s, 0, false);
|
||||
return;
|
||||
}
|
||||
if (!strcmp(sv.strings.vw_model_precache[i], s))
|
||||
|
@ -8532,16 +8528,31 @@ int PF_ForceInfoKey_Internal(unsigned int entnum, const char *key, const char *v
|
|||
MSG_WriteString (&sv.reliable_datagram, key);
|
||||
MSG_WriteString (&sv.reliable_datagram, Info_ValueForKey(svs.clients[entnum-1].userinfo, key));
|
||||
|
||||
#ifdef NQPROT
|
||||
if (!strcmp(key, "name"))
|
||||
{
|
||||
MSG_WriteByte(&sv.nqreliable_datagram, svc_updatename);
|
||||
MSG_WriteByte(&sv.nqreliable_datagram, entnum-1);
|
||||
MSG_WriteString (&sv.nqreliable_datagram, Info_ValueForKey(svs.clients[entnum-1].userinfo, key));
|
||||
}
|
||||
else if (!strcmp(key, "topcolor") || !strcmp(key, "bottomcolor"))
|
||||
{
|
||||
int c;
|
||||
//this sucks, but whatever.
|
||||
c = (atoi(Info_ValueForKey(svs.clients[entnum-1].userinfo, "topcolor" )) & 0xf)<<4;
|
||||
c|= (atoi(Info_ValueForKey(svs.clients[entnum-1].userinfo, "bottomcolor")) & 0xf);
|
||||
MSG_WriteByte(&sv.nqreliable_datagram, svc_updatecolors);
|
||||
MSG_WriteByte(&sv.nqreliable_datagram, entnum-1);
|
||||
MSG_WriteByte (&sv.nqreliable_datagram, c);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!strcmp(key, "*spectator"))
|
||||
svs.clients[entnum-1].spectator = !!atoi(value);
|
||||
#ifdef _DEBUG
|
||||
if (!strcmp(key, "*transfer"))
|
||||
{
|
||||
#ifdef SUBSERVERS
|
||||
SSV_InitiatePlayerTransfer(&svs.clients[entnum-1], value);
|
||||
#else
|
||||
PF_ForceInfoKey_Internal(entnum, key, "");
|
||||
Con_Printf("WARNING: *transfer is no longer supported\n");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
@ -9205,6 +9216,42 @@ static void QCBUILTIN PF_clusterevent(pubprogfuncs_t *prinst, struct globalvars_
|
|||
SSV_Send(dest, src, cmd, info);
|
||||
#endif
|
||||
}
|
||||
static void QCBUILTIN PF_clustertransfer(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
|
||||
{
|
||||
#ifdef SUBSERVERS
|
||||
int p = G_EDICT(prinst, OFS_PARM0)->entnum - 1;
|
||||
const char *dest = (prinst->callargc >= 2)?PR_GetStringOfs(prinst, OFS_PARM1):NULL;
|
||||
|
||||
G_INT(OFS_RETURN) = 0;
|
||||
|
||||
if (p < 0 || p >= sv.allocated_client_slots)
|
||||
{
|
||||
PR_BIError (prinst, "PF_clustertransfer: not a player\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (dest)
|
||||
{
|
||||
if (!SSV_IsSubServer())
|
||||
{
|
||||
Con_DPrintf("PF_clustertransfer: not running in mapcluster mode\n", svs.clients[p].transfer, dest);
|
||||
return;
|
||||
}
|
||||
if (svs.clients[p].transfer)
|
||||
{
|
||||
Con_DPrintf("PF_clustertransfer: Already transferring to %s, ignoring transfer to %s\n", svs.clients[p].transfer, dest);
|
||||
return;
|
||||
}
|
||||
svs.clients[p].transfer = Z_StrDup(svs.clients[p].transfer);
|
||||
SSV_InitiatePlayerTransfer(&svs.clients[p], svs.clients[p].transfer);
|
||||
}
|
||||
|
||||
if (svs.clients[p].transfer)
|
||||
RETURN_TSTRING(svs.clients[p].transfer);
|
||||
#else
|
||||
G_INT(OFS_RETURN) = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@ -9749,7 +9796,8 @@ BuiltinList_t BuiltinList[] = { //nq qw h2 ebfs
|
|||
{"checkcommand", PF_checkcommand, 0, 0, 0, 294, D("float(string name)", "Checks to see if the supplied name is a valid command, cvar, or alias. Returns 0 if it does not exist.")},
|
||||
{"argescape", PF_argescape, 0, 0, 0, 295, D("string(string s)", "Marks up a string so that it can be reliably tokenized as a single argument later.")},
|
||||
// {"cvar_setlatch", PF_cvar_setlatch, 0, 0, 0, ???, "void(string cvarname, optional string value)"},
|
||||
{"clusterevent", PF_clusterevent, 0, 0, 0, 296, D("void(string dest, string from, string cmd, string info)", "Only functions in mapcluster mode. Sends an event to whichever server the named player is on. The destination server can then dispatch the event to the client or handle it itself via the SV_ParseClusterEvent entrypoint. If dest is empty, the event is broadcast to ALL servers. If the named player can't be found, the event will be returned to this server with the cmd prefixed with 'error:'.")},
|
||||
{"clusterevent", PF_clusterevent, 0, 0, 0, 0, D("void(string dest, string from, string cmd, string info)", "Only functions in mapcluster mode. Sends an event to whichever server the named player is on. The destination server can then dispatch the event to the client or handle it itself via the SV_ParseClusterEvent entrypoint. If dest is empty, the event is broadcast to ALL servers. If the named player can't be found, the event will be returned to this server with the cmd prefixed with 'error:'.")},
|
||||
{"clustertransfer", PF_clustertransfer, 0, 0, 0, 0, D("string(entity player, optional string newnode)", "Only functions in mapcluster mode. Initiate transfer of the player to a different node. Can take some time. If dest is specified, returns null on error. Otherwise returns the current/new target node (or null if not transferring).")},
|
||||
|
||||
|
||||
{"clearscene", PF_Fixme, 0, 0, 0, 300, D("void()", "Forgets all rentities, polygons, and temporary dlights. Resets all view properties to their default values.")},// (EXT_CSQC)
|
||||
|
@ -9797,7 +9845,8 @@ BuiltinList_t BuiltinList[] = { //nq qw h2 ebfs
|
|||
//330
|
||||
{"getstati", PF_Fixme, 0, 0, 0, 330, D("float(float stnum)", "Retrieves the numerical value of the given EV_INTEGER or EV_ENTITY stat (converted to a float).")},// (EXT_CSQC)
|
||||
{"getstatf", PF_Fixme, 0, 0, 0, 331, D("#define getstatbits getstatf\nfloat(float stnum, optional float firstbit, optional float bitcount)", "Retrieves the numerical value of the given EV_FLOAT stat. If firstbit and bitcount are specified, retrieves the upper bits of the STAT_ITEMS stat.")},// (EXT_CSQC)
|
||||
{"getstats", PF_Fixme, 0, 0, 0, 332, D("string(float firststnum)", "Retrieves the value of the given EV_STRING stat, as a tempstring.\nOlder engines may use 4 consecutive integer stats, with a limit of 15 chars (yes, really. 15.), but "FULLENGINENAME" uses a separate namespace for string stats and has a much higher length limit.")},
|
||||
{"getstats", PF_Fixme, 0, 0, 0, 332, D("string(float stnum)", "Retrieves the value of the given EV_STRING stat, as a tempstring.\nOlder engines may use 4 consecutive integer stats, with a limit of 15 chars (yes, really. 15.), but "FULLENGINENAME" uses a separate namespace for string stats and has a much higher length limit.")},
|
||||
{"getplayerstat", PF_Fixme, 0, 0, 0, 0, D("__variant(float playernum, float statnum, float stattype)", "Retrieves a specific player's stat, matching the type specified on the server. This builtin is primarily intended for mvd playback where ALL players are known. For EV_ENTITY, world will be returned if the entity is not in the pvs, use type-punning with EV_INTEGER to get the entity number if you just want to see if its set. STAT_ITEMS should be queried as an EV_INTEGER on account of runes and items2 being packed into the upper bits.")},
|
||||
|
||||
//EXT_CSQC
|
||||
{"setmodelindex", PF_Fixme, 0, 0, 0, 333, D("void(entity e, float mdlindex)", "Sets a model by precache index instead of by name. Otherwise identical to setmodel.")},//
|
||||
|
@ -10757,6 +10806,7 @@ void PR_DumpPlatform_f(void)
|
|||
{"trace_brush_id", "int", QW|NQ|CS},
|
||||
{"trace_brush_faceid", "int", QW|NQ|CS},
|
||||
|
||||
{"global_gravitydir", "vector", QW|NQ|CS, "The direction gravity should act in if not otherwise specified per entity.", 0,"'0 0 -1'"},
|
||||
{"serverid", "int", QW|NQ|CS, "The unique id of this server within the server cluster."},
|
||||
|
||||
#define comfieldfloat(name,desc) {#name, ".float", FL, desc},
|
||||
|
@ -10928,6 +10978,25 @@ void PR_DumpPlatform_f(void)
|
|||
{"GE_ABSMAX", "const float", CS, "Valid for getentity. Guesses the entity's .absmax vector.", GE_ABSMAX},
|
||||
// {"GE_LIGHT", "const float", CS, NULL, GE_LIGHT},
|
||||
|
||||
{"GE_MODELINDEX", "const float", CS, "Valid for getentity. Guesses the entity's .modelindex float.", GE_MODELINDEX},
|
||||
{"GE_MODELINDEX2", "const float", CS, "Valid for getentity. Guesses the entity's .vw_index float.", GE_MODELINDEX2},
|
||||
{"GE_EFFECTS", "const float", CS, "Valid for getentity. Guesses the entity's .effects float.", GE_EFFECTS},
|
||||
{"GE_FRAME", "const float", CS, "Valid for getentity. Guesses the entity's .frame float.", GE_FRAME},
|
||||
{"GE_ANGLES", "const float", CS, "Valid for getentity. Guesses the entity's .angles vector.", GE_ANGLES},
|
||||
{"GE_FATNESS", "const float", CS, "Valid for getentity. Guesses the entity's .fatness float.", GE_FATNESS},
|
||||
{"GE_DRAWFLAGS", "const float", CS, "Valid for getentity. Guesses the entity's .drawflags float.", GE_DRAWFLAGS},
|
||||
{"GE_ABSLIGHT", "const float", CS, "Valid for getentity. Guesses the entity's .abslight float.", GE_ABSLIGHT},
|
||||
{"GE_GLOWMOD", "const float", CS, "Valid for getentity. Guesses the entity's .glowmod vector.", GE_GLOWMOD},
|
||||
{"GE_GLOWSIZE", "const float", CS, "Valid for getentity. Guesses the entity's .glowsize float.", GE_GLOWSIZE},
|
||||
{"GE_GLOWCOLOUR", "const float", CS, "Valid for getentity. Guesses the entity's .glowcolor float.", GE_GLOWCOLOUR},
|
||||
{"GE_RTSTYLE", "const float", CS, "Valid for getentity. Guesses the entity's .style float.", GE_RTSTYLE},
|
||||
{"GE_RTPFLAGS", "const float", CS, "Valid for getentity. Guesses the entity's .pflags float.", GE_RTPFLAGS},
|
||||
{"GE_RTCOLOUR", "const float", CS, "Valid for getentity. Guesses the entity's .color vector.", GE_RTCOLOUR},
|
||||
{"GE_RTRADIUS", "const float", CS, "Valid for getentity. Guesses the entity's .light_lev float.", GE_RTRADIUS},
|
||||
{"GE_TAGENTITY", "const float", CS, "Valid for getentity. Guesses the entity's .tag_entity float.", GE_TAGENTITY},
|
||||
{"GE_TAGINDEX", "const float", CS, "Valid for getentity. Guesses the entity's .tag_index float.", GE_TAGINDEX},
|
||||
{"GE_GRAVITYDIR", "const float", CS, "Valid for getentity. Guesses the entity's .gravitydir vector.", GE_GRAVITYDIR},
|
||||
{"GE_TRAILEFFECTNUM","const float",CS, "Valid for getentity. Guesses the entity's .traileffectnum float.", GE_TRAILEFFECTNUM},
|
||||
|
||||
{"DAMAGE_NO", "const float", QW|NQ, NULL, DAMAGE_NO},
|
||||
{"DAMAGE_YES", "const float", QW|NQ, NULL, DAMAGE_YES},
|
||||
|
|
|
@ -228,11 +228,19 @@ typedef enum
|
|||
|
||||
typedef struct
|
||||
{
|
||||
string_t name;
|
||||
quintptr_t name;
|
||||
int ofs;
|
||||
fieldtype_t type;
|
||||
// int flags;
|
||||
} field_t;
|
||||
} fieldN_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned int name;
|
||||
int ofs;
|
||||
fieldtype_t type;
|
||||
// int flags;
|
||||
} field32_t;
|
||||
|
||||
|
||||
|
||||
|
@ -296,22 +304,33 @@ typedef struct {
|
|||
//this is not directly usable in 64bit to refer to a 32bit qvm (hence why we have two versions).
|
||||
typedef struct
|
||||
{
|
||||
struct vmedict_s *ents;
|
||||
int sizeofent;
|
||||
q1qvmglobalvars_t *global;
|
||||
field_t *fields;
|
||||
int APIversion;
|
||||
} gameDataN_t;
|
||||
unsigned int APIversion;
|
||||
unsigned int sizeofent;
|
||||
unsigned int maxedicts;
|
||||
|
||||
quintptr_t global;
|
||||
quintptr_t fields;
|
||||
quintptr_t ents;
|
||||
} gameDataPrivate_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned int ents;
|
||||
int sizeofent;
|
||||
int sizeofent;
|
||||
unsigned int global;
|
||||
unsigned int fields;
|
||||
int APIversion;
|
||||
int APIversion;
|
||||
} gameData32_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
quintptr_t ents;
|
||||
int sizeofent;
|
||||
quintptr_t global;
|
||||
quintptr_t fields;
|
||||
int APIversion;
|
||||
} gameDataN_t;
|
||||
|
||||
typedef enum {
|
||||
FS_READ_BIN,
|
||||
FS_READ_TXT,
|
||||
|
@ -354,7 +373,7 @@ static pubprogfuncs_t q1qvmprogfuncs;
|
|||
|
||||
|
||||
static void *evars; //pointer to the gamecodes idea of an edict_t
|
||||
static qintptr_t vevars; //offset into the vm base of evars
|
||||
static quintptr_t vevars; //offset into the vm base of evars
|
||||
|
||||
/*
|
||||
static char *Q1QVMPF_AddString(pubprogfuncs_t *pf, char *base, int minlength)
|
||||
|
@ -485,8 +504,22 @@ static int QDECL Q1QVMPF_LoadEnts(pubprogfuncs_t *pf, const char *mapstring, flo
|
|||
return sv.world.edict_size;
|
||||
}
|
||||
|
||||
static int QDECL Q1QVMPF_QueryField(pubprogfuncs_t *prinst, unsigned int fieldoffset, etype_t *type, char **name, evalc_t *fieldcache)
|
||||
{
|
||||
*type = ev_void;
|
||||
*name = "?";
|
||||
|
||||
fieldcache->varname = NULL;
|
||||
fieldcache->spare[0] = fieldoffset;
|
||||
return true;
|
||||
}
|
||||
|
||||
static eval_t *QDECL Q1QVMPF_GetEdictFieldValue(pubprogfuncs_t *pf, edict_t *e, char *fieldname, evalc_t *cache)
|
||||
{
|
||||
if (cache && !cache->varname)
|
||||
{
|
||||
return (eval_t*)((char*)e->v + cache->spare[0]-WASTED_EDICT_T_SIZE);
|
||||
}
|
||||
if (!strcmp(fieldname, "message"))
|
||||
{
|
||||
return (eval_t*)&e->v->message;
|
||||
|
@ -506,17 +539,31 @@ static globalvars_t *QDECL Q1QVMPF_Globals(pubprogfuncs_t *prinst, int prnum)
|
|||
|
||||
static string_t QDECL Q1QVMPF_StringToProgs(pubprogfuncs_t *prinst, const char *str)
|
||||
{
|
||||
string_t ret = (string_t)(str - (char*)VM_MemoryBase(q1qvm));
|
||||
quintptr_t ret = (str - (char*)VM_MemoryBase(q1qvm));
|
||||
if (ret >= VM_MemoryMask(q1qvm))
|
||||
return 0;
|
||||
if (ret >= 0xffffffff)
|
||||
return 0; //invalid string! blame 64bit.
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void *ASMCALL QDECL Q1QVMPF_PointerToNative(pubprogfuncs_t *prinst, quintptr_t str)
|
||||
{
|
||||
void *ret;
|
||||
if (!str || (quintptr_t)str >= VM_MemoryMask(q1qvm))
|
||||
return NULL; //null or invalid pointers.
|
||||
ret = (char*)VM_MemoryBase(q1qvm) + str;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const char *ASMCALL QDECL Q1QVMPF_StringToNative(pubprogfuncs_t *prinst, string_t str)
|
||||
{
|
||||
char *ret = (char*)VM_MemoryBase(q1qvm) + str;
|
||||
if (!ret) //qvms can never return a null. make sure native code can't crash things either.
|
||||
return "";
|
||||
char *ret;
|
||||
if (str == ~0)
|
||||
return " "; //models are weird. yes, this is a hack.
|
||||
if (!str || (quintptr_t)str >= VM_MemoryMask(q1qvm))
|
||||
return ""; //null or invalid pointers.
|
||||
ret = (char*)VM_MemoryBase(q1qvm) + str;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -851,13 +898,25 @@ static qintptr_t QVM_SetSpawnParams (void *offset, quintptr_t mask, const qintpt
|
|||
}
|
||||
static qintptr_t QVM_ChangeLevel (void *offset, quintptr_t mask, const qintptr_t *arg)
|
||||
{
|
||||
WrapQCBuiltin(PF_changelevel, offset, mask, arg, "s");
|
||||
return 0;
|
||||
char newmap[MAX_QPATH];
|
||||
if (sv.mapchangelocked)
|
||||
return 0;
|
||||
sv.mapchangelocked = true;
|
||||
COM_QuotedString(VM_POINTER(arg[0]), newmap, sizeof(newmap), false);
|
||||
Cbuf_AddText (va("\nchangelevel %s\n", newmap), RESTRICT_LOCAL);
|
||||
return 1;
|
||||
}
|
||||
static qintptr_t QVM_ChangeLevel2 (void *offset, quintptr_t mask, const qintptr_t *arg)
|
||||
{
|
||||
WrapQCBuiltin(PF_changelevel, offset, mask, arg, "ss");
|
||||
return 0;
|
||||
char newmap[MAX_QPATH];
|
||||
char startspot[MAX_QPATH];
|
||||
if (sv.mapchangelocked)
|
||||
return 0;
|
||||
sv.mapchangelocked = true;
|
||||
COM_QuotedString(VM_POINTER(arg[0]), newmap, sizeof(newmap), false);
|
||||
COM_QuotedString(VM_POINTER(arg[1]), startspot, sizeof(startspot), false);
|
||||
Cbuf_AddText (va("\nchangelevel %s %s\n", newmap, startspot), RESTRICT_LOCAL);
|
||||
return 1;
|
||||
}
|
||||
static qintptr_t QVM_LogFrag (void *offset, quintptr_t mask, const qintptr_t *arg)
|
||||
{
|
||||
|
@ -866,9 +925,31 @@ static qintptr_t QVM_LogFrag (void *offset, quintptr_t mask, const qintptr_t *ar
|
|||
}
|
||||
static qintptr_t QVM_Precache_VWep_Model (void *offset, quintptr_t mask, const qintptr_t *arg)
|
||||
{
|
||||
int i = WrapQCBuiltin(PF_precache_vwep_model, offset, mask, arg, "s");
|
||||
float f = *(float*)&i;
|
||||
return f;
|
||||
const char *s = VM_POINTER(arg[0]);
|
||||
int i;
|
||||
|
||||
if (!*s || strchr(s, '\"') || strchr(s, ';') || strchr(s, '\t') || strchr(s, '\n'))
|
||||
Con_Printf("QVM_Precache_VWep_Model: bad string\n");
|
||||
else
|
||||
{
|
||||
for (i = 0; i < sizeof(sv.strings.vw_model_precache)/sizeof(sv.strings.vw_model_precache[0]); i++)
|
||||
{
|
||||
if (!sv.strings.vw_model_precache[i])
|
||||
{
|
||||
if (sv.state != ss_loading)
|
||||
{
|
||||
Con_Printf("QVM_Precache_VWep_Model: not spawning\n");
|
||||
return 0;
|
||||
}
|
||||
sv.strings.vw_model_precache[i] = s;
|
||||
return i;
|
||||
}
|
||||
if (!strcmp(sv.strings.vw_model_precache[i], s))
|
||||
return i;
|
||||
}
|
||||
Con_Printf("QVM_Precache_VWep_Model: overflow\n");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
static qintptr_t QVM_GetInfoKey (void *offset, quintptr_t mask, const qintptr_t *arg)
|
||||
{
|
||||
|
@ -1492,6 +1573,27 @@ static qintptr_t QVM_pointparticles (void *offset, quintptr_t mask, const qintpt
|
|||
return WrapQCBuiltin(PF_sv_pointparticles, offset, mask, arg, "ivvi");
|
||||
}
|
||||
|
||||
static qintptr_t QVM_clientstat (void *offset, quintptr_t mask, const qintptr_t *arg)
|
||||
{
|
||||
int num = VM_LONG(arg[0]);
|
||||
int type = VM_LONG(arg[1]);
|
||||
int fieldofs = VM_LONG(arg[2]);
|
||||
|
||||
|
||||
// SV_QCStatEval(type, "", &cache, NULL, num);
|
||||
|
||||
SV_QCStatFieldIdx(type, fieldofs, num);
|
||||
return 0;
|
||||
}
|
||||
static qintptr_t QVM_pointerstat (void *offset, quintptr_t mask, const qintptr_t *arg)
|
||||
{
|
||||
int num = VM_LONG(arg[0]);
|
||||
int type = VM_LONG(arg[1]);
|
||||
void *ptr = VM_POINTER(arg[2]);
|
||||
SV_QCStatPtr(type, ptr, num);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static qintptr_t QVM_Map_Extension (void *offset, quintptr_t mask, const qintptr_t *arg);
|
||||
|
||||
typedef qintptr_t (*traps_t) (void *offset, quintptr_t mask, const qintptr_t *arg);
|
||||
|
@ -1607,6 +1709,8 @@ struct
|
|||
{"particleeffectnum", QVM_particleeffectnum},
|
||||
{"trailparticles", QVM_trailparticles},
|
||||
{"pointparticles", QVM_pointparticles},
|
||||
{"clientstat", QVM_clientstat}, //csqc extension
|
||||
{"pointerstat", QVM_pointerstat}, //csqc extension
|
||||
|
||||
//sql?
|
||||
//model querying?
|
||||
|
@ -1717,6 +1821,7 @@ void Q1QVM_Shutdown(void)
|
|||
Z_Free(q1qvmprogfuncs.edicttable);
|
||||
q1qvmprogfuncs.edicttable = NULL;
|
||||
}
|
||||
vevars = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1751,8 +1856,13 @@ void QDECL Q1QVMPF_SetStringField(pubprogfuncs_t *progfuncs, struct edict_s *ed,
|
|||
string_t newval = progfuncs->StringToProgs(progfuncs, str);
|
||||
if (newval || !str)
|
||||
*fld = newval;
|
||||
else if (!str)
|
||||
*fld = 0;
|
||||
else
|
||||
Con_DPrintf("Ignoring string set outside of progs VM\n");
|
||||
{
|
||||
*fld = ~0;
|
||||
// Con_DPrintf("Ignoring string set outside of progs VM\n");
|
||||
}
|
||||
}
|
||||
|
||||
qboolean PR_LoadQ1QVM(void)
|
||||
|
@ -1764,8 +1874,10 @@ qboolean PR_LoadQ1QVM(void)
|
|||
static float physics_mode = 2;
|
||||
static vec3_t defaultgravity = {0,0,-1};
|
||||
int i;
|
||||
gameDataN_t *gd, gdm;
|
||||
gameDataPrivate_t gd;
|
||||
gameDataN_t *gdn;
|
||||
gameData32_t *gd32;
|
||||
q1qvmglobalvars_t *global;
|
||||
qintptr_t ret;
|
||||
qintptr_t limit;
|
||||
extern cvar_t pr_maxedicts;
|
||||
|
@ -1807,6 +1919,7 @@ qboolean PR_LoadQ1QVM(void)
|
|||
q1qvmprogfuncs.load_ents = Q1QVMPF_LoadEnts;
|
||||
q1qvmprogfuncs.globals = Q1QVMPF_Globals;
|
||||
q1qvmprogfuncs.GetEdictFieldValue = Q1QVMPF_GetEdictFieldValue;
|
||||
q1qvmprogfuncs.QueryField = Q1QVMPF_QueryField;
|
||||
q1qvmprogfuncs.StringToProgs = Q1QVMPF_StringToProgs;
|
||||
q1qvmprogfuncs.StringToNative = Q1QVMPF_StringToNative;
|
||||
q1qvmprogfuncs.SetStringField = Q1QVMPF_SetStringField;
|
||||
|
@ -1834,48 +1947,63 @@ qboolean PR_LoadQ1QVM(void)
|
|||
}
|
||||
|
||||
if (VM_NonNative(q1qvm))
|
||||
{
|
||||
{ //when non native, this can only be a 32bit qvm in a 64bit server.
|
||||
gd32 = (gameData32_t*)((char*)VM_MemoryBase(q1qvm) + ret); //qvm is 32bit
|
||||
|
||||
//when running native64, we need to convert these to real types, so we can use em below
|
||||
//double casts to silence warnings
|
||||
gd = &gdm;
|
||||
gd->ents = (struct vmedict_s *)(qintptr_t)gd32->ents;
|
||||
gd->sizeofent = gd32->sizeofent;
|
||||
gd->global = (q1qvmglobalvars_t *)(qintptr_t)gd32->global;
|
||||
gd->fields = (field_t *)(qintptr_t)gd32->fields;
|
||||
gd->APIversion = gd32->APIversion;
|
||||
gd.APIversion = gd32->APIversion;
|
||||
gd.sizeofent = gd32->sizeofent;
|
||||
|
||||
gd.ents = gd32->ents;
|
||||
gd.global = gd32->global;
|
||||
gd.fields = gd32->fields;
|
||||
|
||||
gd.maxedicts = pr_maxedicts.ival; //FIXME
|
||||
}
|
||||
else
|
||||
{
|
||||
gd = (gameDataN_t*)((char*)VM_MemoryBase(q1qvm) + ret); //qvm is 32bit
|
||||
gdn = (gameDataN_t*)((char*)VM_MemoryBase(q1qvm) + ret);
|
||||
gd.APIversion = gdn->APIversion;
|
||||
gd.sizeofent = gdn->sizeofent;
|
||||
|
||||
gd.ents = gdn->ents;
|
||||
gd.global = gdn->global;
|
||||
gd.fields = gdn->fields;
|
||||
|
||||
gd.maxedicts = pr_maxedicts.ival; //FIXME
|
||||
}
|
||||
|
||||
sv.world.num_edicts = 1;
|
||||
sv.world.max_edicts = bound(64, pr_maxedicts.ival, MAX_EDICTS);
|
||||
sv.world.max_edicts = bound(64, gd.maxedicts, MAX_EDICTS);
|
||||
q1qvmprogfuncs.edicttable = Z_Malloc(sizeof(*q1qvmprogfuncs.edicttable) * sv.world.max_edicts);
|
||||
|
||||
limit = VM_MemoryMask(q1qvm);
|
||||
if (gd->sizeofent < 0 || gd->sizeofent > (0xffffffff-(qintptr_t)gd->ents) / sv.world.max_edicts)
|
||||
gd->sizeofent = 0xffffffff / MAX_EDICTS;
|
||||
if ((quintptr_t)gd->ents+(gd->sizeofent*MAX_Q1QVM_EDICTS) < (quintptr_t)gd->ents || (quintptr_t)gd->ents > (quintptr_t)limit)
|
||||
gd->ents = NULL;
|
||||
if ((quintptr_t)(gd->global+1) < (quintptr_t)gd->global || (quintptr_t)gd->global > (quintptr_t)limit)
|
||||
gd->global = NULL;
|
||||
if (/*(quintptr_t)gd->fields < (quintptr_t)gd->fields ||*/ (quintptr_t)gd->fields > limit)
|
||||
gd->fields = NULL;
|
||||
if (gd.sizeofent < 0 || gd.sizeofent > 0xffffffff / gd.maxedicts)
|
||||
gd.sizeofent = 0xffffffff / gd.maxedicts;
|
||||
if ((quintptr_t)gd.ents+(gd.sizeofent*gd.maxedicts) < (quintptr_t)gd.ents || (quintptr_t)gd.ents > (quintptr_t)limit)
|
||||
gd.ents = 0;
|
||||
if ((quintptr_t)(gd.global+1) < (quintptr_t)gd.global || (quintptr_t)gd.global > (quintptr_t)limit)
|
||||
gd.global = 0;
|
||||
if (/*(quintptr_t)gd.fields < (quintptr_t)gd.fields ||*/ (quintptr_t)gd.fields > limit)
|
||||
gd.fields = 0;
|
||||
|
||||
sv.world.edict_size = gd->sizeofent;
|
||||
vevars = (qintptr_t)gd->ents;
|
||||
evars = ((char*)VM_MemoryBase(q1qvm) + vevars);
|
||||
sv.world.edict_size = gd.sizeofent;
|
||||
vevars = gd.ents;
|
||||
evars = Q1QVMPF_PointerToNative(&q1qvmprogfuncs, vevars);
|
||||
global = Q1QVMPF_PointerToNative(&q1qvmprogfuncs, gd.global);
|
||||
|
||||
if (!evars || !global)
|
||||
{
|
||||
Q1QVM_Shutdown();
|
||||
return false;
|
||||
}
|
||||
|
||||
//WARNING: global is not remapped yet...
|
||||
//This code is written evilly, but works well enough
|
||||
#define globalint(required, name) pr_global_ptrs->name = (int*)((char*)VM_MemoryBase(q1qvm)+(qintptr_t)&gd->global->name) //the logic of this is somewhat crazy
|
||||
#define globalfloat(required, name) pr_global_ptrs->name = (float*)((char*)VM_MemoryBase(q1qvm)+(qintptr_t)&gd->global->name)
|
||||
#define globalstring(required, name) pr_global_ptrs->name = (string_t*)((char*)VM_MemoryBase(q1qvm)+(qintptr_t)&gd->global->name)
|
||||
#define globalvec(required, name) pr_global_ptrs->name = (vec3_t*)((char*)VM_MemoryBase(q1qvm)+(qintptr_t)&gd->global->name)
|
||||
#define globalfunc(required, name) pr_global_ptrs->name = (int*)((char*)VM_MemoryBase(q1qvm)+(qintptr_t)&gd->global->name)
|
||||
#define globalint(required, name) pr_global_ptrs->name = Q1QVMPF_PointerToNative(&q1qvmprogfuncs, (qintptr_t)&global->name) //the logic of this is somewhat crazy
|
||||
#define globalfloat(required, name) pr_global_ptrs->name = Q1QVMPF_PointerToNative(&q1qvmprogfuncs, (qintptr_t)&global->name)
|
||||
#define globalstring(required, name) pr_global_ptrs->name = Q1QVMPF_PointerToNative(&q1qvmprogfuncs, (qintptr_t)&global->name)
|
||||
#define globalvec(required, name) pr_global_ptrs->name = Q1QVMPF_PointerToNative(&q1qvmprogfuncs, (qintptr_t)&global->name)
|
||||
#define globalfunc(required, name) pr_global_ptrs->name = Q1QVMPF_PointerToNative(&q1qvmprogfuncs, (qintptr_t)&global->name)
|
||||
#define globalfloatnull(required, name) pr_global_ptrs->name = NULL
|
||||
globalint (true, self); //we need the qw ones, but any in standard quake and not quakeworld, we don't really care about.
|
||||
globalint (true, other);
|
||||
|
@ -1937,27 +2065,42 @@ qboolean PR_LoadQ1QVM(void)
|
|||
|
||||
dimensionsend = dimensiondefault = 255;
|
||||
for (i = 0; i < 16; i++)
|
||||
pr_global_ptrs->spawnparamglobals[i] = (float*)((char*)VM_MemoryBase(q1qvm)+(qintptr_t)(&gd->global->parm1 + i));
|
||||
pr_global_ptrs->spawnparamglobals[i] = (float*)((char*)VM_MemoryBase(q1qvm)+(qintptr_t)(&global->parm1 + i));
|
||||
for (; i < NUM_SPAWN_PARMS; i++)
|
||||
pr_global_ptrs->spawnparamglobals[i] = NULL;
|
||||
|
||||
for (i = 0; gd->fields[i].name; i++)
|
||||
#define emufield(n,t) if (field[i].type == t && !strcmp(#n, fname)) {fofs.n = (field[i].ofs - WASTED_EDICT_T_SIZE)/sizeof(float); continue;}
|
||||
if (VM_NonNative(q1qvm))
|
||||
{
|
||||
const char *fname = Q1QVMPF_StringToNative(&q1qvmprogfuncs, gd->fields[i].name);
|
||||
#define emufield(n,t) if (gd->fields[i].type == t && !strcmp(#n, fname)) {fofs.n = (gd->fields[i].ofs - WASTED_EDICT_T_SIZE)/sizeof(float); continue;}
|
||||
emufields
|
||||
#undef emufield
|
||||
field32_t *field = Q1QVMPF_PointerToNative(&q1qvmprogfuncs, gd.fields);
|
||||
if (field)
|
||||
for (i = 0; field[i].name; i++)
|
||||
{
|
||||
const char *fname = Q1QVMPF_PointerToNative(&q1qvmprogfuncs, field[i].name);
|
||||
emufields
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fieldN_t *field = Q1QVMPF_PointerToNative(&q1qvmprogfuncs, gd.fields);
|
||||
if (field)
|
||||
for (i = 0; field[i].name; i++)
|
||||
{
|
||||
const char *fname = Q1QVMPF_PointerToNative(&q1qvmprogfuncs, field[i].name);
|
||||
emufields
|
||||
}
|
||||
}
|
||||
#undef emufield
|
||||
|
||||
|
||||
sv.world.progs = &q1qvmprogfuncs;
|
||||
sv.world.edicts = (wedict_t*)Q1QVMPF_EdictNum(svprogfuncs, 0);
|
||||
sv.world.usesolidcorpse = true;
|
||||
|
||||
if ((unsigned)gd->global->mapname && (unsigned)gd->global->mapname+MAPNAME_LEN < VM_MemoryMask(q1qvm))
|
||||
Q_strncpyz((char*)VM_MemoryBase(q1qvm) + gd->global->mapname, svs.name, MAPNAME_LEN);
|
||||
if ((quintptr_t)global->mapname && (quintptr_t)global->mapname+MAPNAME_LEN < VM_MemoryMask(q1qvm))
|
||||
Q_strncpyz((char*)VM_MemoryBase(q1qvm) + global->mapname, svs.name, MAPNAME_LEN);
|
||||
else
|
||||
gd->global->mapname = Q1QVMPF_StringToProgs(sv.world.progs, svs.name);
|
||||
global->mapname = Q1QVMPF_StringToProgs(sv.world.progs, svs.name);
|
||||
|
||||
PR_SV_FillWorldGlobals(&sv.world);
|
||||
return true;
|
||||
|
@ -1981,7 +2124,7 @@ void Q1QVM_ClientConnect(client_t *cl)
|
|||
cl->name = cl->namebuf;
|
||||
cl->edict->v->netname = Q1QVMPF_StringToProgs(svprogfuncs, cl->namebuf);
|
||||
|
||||
Con_DPrintf("WARNING: Mod provided no netname buffer and will not function correctly when compiled as a qvm.\n");
|
||||
// Con_DPrintf("WARNING: Mod provided no netname buffer and will not function correctly when compiled as a qvm.\n");
|
||||
}
|
||||
else
|
||||
Con_Printf("WARNING: Mod provided no netname buffer. Player names will not be set properly.\n");
|
||||
|
|
|
@ -350,7 +350,7 @@ void SV_Loadgame_Legacy(char *filename, vfsfile_t *f, int version)
|
|||
|
||||
void SV_LegacySavegame_f (void)
|
||||
{
|
||||
int len;
|
||||
size_t len;
|
||||
char *s = NULL;
|
||||
client_t *cl;
|
||||
int clnum;
|
||||
|
@ -550,7 +550,8 @@ qboolean SV_LoadLevelCache(char *savename, char *level, char *startspot, qboolea
|
|||
char mapname[MAX_QPATH];
|
||||
float time;
|
||||
char str[32768];
|
||||
int i,j;
|
||||
int i;
|
||||
size_t j;
|
||||
edict_t *ent;
|
||||
int version;
|
||||
|
||||
|
@ -848,7 +849,7 @@ qboolean SV_LoadLevelCache(char *savename, char *level, char *startspot, qboolea
|
|||
|
||||
void SV_SaveLevelCache(char *savedir, qboolean dontharmgame)
|
||||
{
|
||||
int len;
|
||||
size_t len;
|
||||
char *s;
|
||||
client_t *cl;
|
||||
int clnum;
|
||||
|
|
|
@ -407,6 +407,7 @@ typedef struct client_s
|
|||
int challenge;
|
||||
int userid; // identifying number
|
||||
char userinfo[EXTENDED_INFO_STRING]; // infostring
|
||||
char *transfer;
|
||||
|
||||
usercmd_t lastcmd; // for filling in big drops and partial predictions
|
||||
double localtime; // of last message
|
||||
|
@ -1057,6 +1058,12 @@ void SV_FixupName(char *in, char *out, unsigned int outlen);
|
|||
//cluster stuff
|
||||
typedef struct pubsubserver_s
|
||||
{
|
||||
struct
|
||||
{
|
||||
void (*InstructSlave)(struct pubsubserver_s *ps, sizebuf_t *cmd); //send to
|
||||
int (*SubServerRead)(struct pubsubserver_s *ps); //read from. fills up net_message
|
||||
} funcs;
|
||||
|
||||
struct pubsubserver_s *next;
|
||||
unsigned int id;
|
||||
char name[64];
|
||||
|
@ -1073,8 +1080,6 @@ void SSV_ReadFromControlServer(void);
|
|||
void SSV_SavePlayerStats(client_t *cl, int reason); //initial, periodic (in case of node crashes), part
|
||||
void SSV_RequestShutdown(void); //asks the cluster to not send us new players
|
||||
|
||||
void Sys_InstructSlave(pubsubserver_t *s, sizebuf_t *cmd);
|
||||
int Sys_SubServerRead(pubsubserver_t *s); //1: yes. 0: no. -1: error
|
||||
pubsubserver_t *Sys_ForkServer(void);
|
||||
|
||||
#define SSV_IsSubServer() isClusterSlave
|
||||
|
|
|
@ -736,7 +736,7 @@ void SV_Map_f (void)
|
|||
|
||||
if (preserveplayers && svprogfuncs && host_client->state == cs_spawned && host_client->spawninfo)
|
||||
{
|
||||
int j = 0;
|
||||
size_t j = 0;
|
||||
svprogfuncs->restoreent(svprogfuncs, host_client->spawninfo, &j, host_client->edict);
|
||||
host_client->istobeloaded = true;
|
||||
host_client->state=cs_connected;
|
||||
|
@ -871,7 +871,7 @@ void SV_EvaluatePenalties(client_t *cl)
|
|||
{
|
||||
bannedips_t *banip;
|
||||
unsigned int penalties = 0, delta, p;
|
||||
char *penaltyreason[countof(banflags)];
|
||||
char *penaltyreason[countof(banflags)] = {NULL};
|
||||
const char *activepenalties[countof(banflags)];
|
||||
char *reasons[countof(banflags)] = {NULL};
|
||||
int numpenalties = 0;
|
||||
|
@ -923,8 +923,8 @@ void SV_EvaluatePenalties(client_t *cl)
|
|||
if ((penalties & (BAN_BAN | BAN_PERMIT)) == BAN_BAN)
|
||||
{
|
||||
//we should only reach here by a player getting banned mid-game.
|
||||
if (penaltyreason[0])
|
||||
SV_BroadcastPrintf(PRINT_HIGH, "%s was banned: %s\n", cl->name, penaltyreason[0]);
|
||||
if (penaltyreason[BAN_BAN])
|
||||
SV_BroadcastPrintf(PRINT_HIGH, "%s was banned: %s\n", cl->name, penaltyreason[BAN_BAN]);
|
||||
else
|
||||
SV_BroadcastPrintf(PRINT_HIGH, "%s was banned\n", cl->name);
|
||||
cl->drop = true;
|
||||
|
|
|
@ -101,7 +101,7 @@ pubsubserver_t *MSV_StartSubServer(unsigned int id, const char *mapname)
|
|||
MSG_WriteByte(&send, ccmd_acceptserver);
|
||||
MSG_WriteLong(&send, s->id);
|
||||
MSG_WriteString(&send, s->name);
|
||||
Sys_InstructSlave(s, &send);
|
||||
s->funcs.InstructSlave(s, &send);
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
@ -185,13 +185,13 @@ void MSV_InstructSlave(unsigned int id, sizebuf_t *cmd)
|
|||
if (!id)
|
||||
{
|
||||
for (s = subservers; s; s = s->next)
|
||||
Sys_InstructSlave(s, cmd);
|
||||
s->funcs.InstructSlave(s, cmd);
|
||||
}
|
||||
else
|
||||
{
|
||||
s = MSV_FindSubServer(id);
|
||||
if (s)
|
||||
Sys_InstructSlave(s, cmd);
|
||||
s->funcs.InstructSlave(s, cmd);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -381,7 +381,7 @@ void MSV_ReadFromSubServer(pubsubserver_t *s)
|
|||
MSG_WriteByte(&send, ccmd_transferedplayer);
|
||||
MSG_WriteLong(&send, s->id);
|
||||
MSG_WriteLong(&send, plid);
|
||||
Sys_InstructSlave(pl->server, &send);
|
||||
pl->server->funcs.InstructSlave(pl->server, &send);
|
||||
}
|
||||
pl->server = s;
|
||||
break;
|
||||
|
@ -431,7 +431,7 @@ void MSV_ReadFromSubServer(pubsubserver_t *s)
|
|||
while(c--)
|
||||
MSG_WriteFloat(&send, MSG_ReadFloat());
|
||||
|
||||
Sys_InstructSlave(toptr, &send);
|
||||
toptr->funcs.InstructSlave(toptr, &send);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -447,7 +447,7 @@ void MSV_ReadFromSubServer(pubsubserver_t *s)
|
|||
MSG_WriteLong(&send, plid);
|
||||
MSG_WriteString(&send, "");
|
||||
|
||||
Sys_InstructSlave(s, &send);
|
||||
s->funcs.InstructSlave(s, &send);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -534,21 +534,21 @@ void MSV_ReadFromSubServer(pubsubserver_t *s)
|
|||
if (!*dest) //broadcast if no dest
|
||||
{
|
||||
for (s = subservers; s; s = s->next)
|
||||
Sys_InstructSlave(s, &send);
|
||||
s->funcs.InstructSlave(s, &send);
|
||||
}
|
||||
else if (*dest == '\\')
|
||||
{
|
||||
//send to a specific server (backslashes should not be valid in infostrings, and thus not in names.
|
||||
//FIXME: broadcasting for now.
|
||||
for (s = subservers; s; s = s->next)
|
||||
Sys_InstructSlave(s, &send);
|
||||
s->funcs.InstructSlave(s, &send);
|
||||
}
|
||||
else
|
||||
{
|
||||
//send it to the server that the player is currently on.
|
||||
clusterplayer_t *pl = MSV_FindPlayerName(dest);
|
||||
if (pl)
|
||||
Sys_InstructSlave(pl->server, &send);
|
||||
pl->server->funcs.InstructSlave(pl->server, &send);
|
||||
else if (!pl && strncmp(cmd, "error:", 6))
|
||||
{
|
||||
//player not found. send it back to the sender, but add an error prefix.
|
||||
|
@ -559,7 +559,7 @@ void MSV_ReadFromSubServer(pubsubserver_t *s)
|
|||
SZ_Write(&send, "error:", 6);
|
||||
MSG_WriteString(&send, cmd);
|
||||
MSG_WriteString(&send, info);
|
||||
Sys_InstructSlave(s, &send);
|
||||
s->funcs.InstructSlave(s, &send);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -574,7 +574,7 @@ void MSV_PollSlaves(void)
|
|||
pubsubserver_t **link, *s;
|
||||
for (link = &subservers; (s=*link); )
|
||||
{
|
||||
switch(Sys_SubServerRead(s))
|
||||
switch(s->funcs.SubServerRead(s))
|
||||
{
|
||||
case -1:
|
||||
//error - server is dead and needs to be freed.
|
||||
|
@ -644,7 +644,8 @@ void SSV_ReadFromControlServer(void)
|
|||
if (!*addr)
|
||||
{
|
||||
Con_Printf("%s: tookplayer: failed\n", sv.modelname);
|
||||
Info_SetValueForStarKey(cl->userinfo, "*transfer", "", sizeof(cl->userinfo));
|
||||
Z_Free(cl->transfer);
|
||||
cl->transfer = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -662,7 +663,6 @@ void SSV_ReadFromControlServer(void)
|
|||
case ccmd_transferedplayer:
|
||||
{
|
||||
client_t *cl;
|
||||
char *to;
|
||||
int toserver = MSG_ReadLong();
|
||||
int playerid = MSG_ReadLong();
|
||||
int i;
|
||||
|
@ -673,8 +673,7 @@ void SSV_ReadFromControlServer(void)
|
|||
{
|
||||
cl = &svs.clients[i];
|
||||
cl->drop = true;
|
||||
to = Info_ValueForKey(cl->userinfo, "*transfer");
|
||||
Con_Printf("%s transfered to %s\n", cl->name, to);
|
||||
Con_Printf("%s transfered to %s\n", cl->name, cl->transfer);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -850,7 +849,6 @@ void SSV_UpdateAddresses(void)
|
|||
|
||||
void SSV_SavePlayerStats(client_t *cl, int reason)
|
||||
{
|
||||
//called when the *transfer userinfo gets set to the new map
|
||||
sizebuf_t send;
|
||||
qbyte send_buf[MAX_QWMSGLEN];
|
||||
int i;
|
||||
|
@ -878,7 +876,6 @@ void SSV_SavePlayerStats(client_t *cl, int reason)
|
|||
}
|
||||
void SSV_Send(const char *dest, const char *src, const char *cmd, const char *msg)
|
||||
{
|
||||
//called when the *transfer userinfo gets set to the new map
|
||||
sizebuf_t send;
|
||||
qbyte send_buf[MAX_QWMSGLEN];
|
||||
if (!SSV_IsSubServer())
|
||||
|
@ -899,7 +896,6 @@ void SSV_Send(const char *dest, const char *src, const char *cmd, const char *ms
|
|||
}
|
||||
void SSV_InitiatePlayerTransfer(client_t *cl, const char *newserver)
|
||||
{
|
||||
//called when the *transfer userinfo gets set to the new map
|
||||
sizebuf_t send;
|
||||
qbyte send_buf[MAX_QWMSGLEN];
|
||||
int i;
|
||||
|
@ -1005,7 +1001,7 @@ qboolean MSV_ClusterLoginReply(netadr_t *legacyclientredirect, unsigned int serv
|
|||
|
||||
MSG_WriteByte(&send, statsblobsize/4);
|
||||
SZ_Write(&send, statsblob, statsblobsize&~3);
|
||||
Sys_InstructSlave(s, &send);
|
||||
s->funcs.InstructSlave(s, &send);
|
||||
|
||||
if (serveraddr.type == NA_INVALID)
|
||||
{
|
||||
|
|
|
@ -1328,7 +1328,37 @@ void SVFTE_EmitPacketEntities(client_t *client, packet_entities_t *to, sizebuf_t
|
|||
if (msg->cursize + 50 > msg->maxsize)
|
||||
break; /*give up if it gets full*/
|
||||
if (outno >= outmax)
|
||||
{ //expand the frames. may need some copying...
|
||||
client_frame_t *newframes;
|
||||
char *ptr;
|
||||
int maxents = outmax * 2; /*this is the max number of ents updated per frame. we can't track more, so...*/
|
||||
if (maxents > client->max_net_ents)
|
||||
maxents = client->max_net_ents;
|
||||
ptr = Z_Malloc( sizeof(client_frame_t)*UPDATE_BACKUP+
|
||||
sizeof(*client->pendingentbits)*client->max_net_ents+
|
||||
sizeof(unsigned int)*maxents*UPDATE_BACKUP+
|
||||
sizeof(unsigned int)*maxents*UPDATE_BACKUP);
|
||||
newframes = (void*)ptr;
|
||||
memcpy(newframes, client->frameunion.frames, sizeof(client_frame_t)*UPDATE_BACKUP);
|
||||
ptr += sizeof(client_frame_t)*UPDATE_BACKUP;
|
||||
memcpy(ptr, client->pendingentbits, sizeof(*client->pendingentbits)*client->max_net_ents);
|
||||
client->pendingentbits = (void*)ptr;
|
||||
ptr += sizeof(*client->pendingentbits)*client->max_net_ents;
|
||||
for (i = 0; i < UPDATE_BACKUP; i++)
|
||||
{
|
||||
newframes[i].entities.max_entities = maxents;
|
||||
newframes[i].resendentnum = (void*)ptr;
|
||||
memcpy(newframes[i].resendentnum, client->frameunion.frames[i].resendentnum, sizeof(unsigned int)*client->frameunion.frames[i].entities.num_entities);
|
||||
ptr += sizeof(*newframes[i].resendentnum)*maxents;
|
||||
newframes[i].resendentbits = (void*)ptr;
|
||||
memcpy(newframes[i].resendentbits, client->frameunion.frames[i].resendentbits, sizeof(unsigned int)*client->frameunion.frames[i].entities.num_entities);
|
||||
ptr += sizeof(*newframes[i].resendentbits)*maxents;
|
||||
newframes[i].senttime = realtime;
|
||||
}
|
||||
Z_Free(client->frameunion.frames);
|
||||
client->frameunion.frames = newframes;
|
||||
break;
|
||||
}
|
||||
client->pendingentbits[j] = 0;
|
||||
|
||||
if (bits & UF_REMOVE)
|
||||
|
|
|
@ -326,7 +326,7 @@ void SV_SaveSpawnparmsClient(client_t *client, float *transferparms)
|
|||
if (PR_FindGlobal(svprogfuncs, "ClientReEnter", 0, NULL))
|
||||
{//oooh, evil.
|
||||
char buffer[65536*4];
|
||||
int bufsize = 0;
|
||||
size_t bufsize = 0;
|
||||
char *buf;
|
||||
for (j=0 ; j<NUM_SPAWN_PARMS ; j++)
|
||||
client->spawn_parms[j] = 0;
|
||||
|
@ -1081,6 +1081,7 @@ void SV_SpawnServer (char *server, char *startspot, qboolean noents, qboolean us
|
|||
#ifdef VM_Q1
|
||||
if (PR_LoadQ1QVM())
|
||||
newgametype = GT_Q1QVM;
|
||||
|
||||
else
|
||||
#endif
|
||||
{
|
||||
|
|
|
@ -306,7 +306,7 @@ void VARGS SV_Error (char *error, ...)
|
|||
|
||||
if (svprogfuncs && pr_ssqc_coreonerror.value && svprogfuncs->save_ents)
|
||||
{
|
||||
int size = 1024*1024*8;
|
||||
size_t size = 1024*1024*8;
|
||||
char *buffer = BZ_Malloc(size);
|
||||
svprogfuncs->save_ents(svprogfuncs, buffer, &size, size, 3);
|
||||
COM_WriteFile("ssqccore.txt", FS_GAMEONLY, buffer, size);
|
||||
|
@ -1842,7 +1842,9 @@ void SV_ClientProtocolExtensionsChanged(client_t *client)
|
|||
if ((client->fteprotocolextensions2 & PEXT2_REPLACEMENTDELTAS))// || ISDPCLIENT(&temp))
|
||||
{
|
||||
char *ptr;
|
||||
int maxents = /*client->max_net_ents;//*/maxpacketentities; /*this is the max number of ents updated per frame. we can't track more, so...*/
|
||||
int maxents = maxpacketentities*4; /*this is the max number of ents updated per frame. we can't track more, so...*/
|
||||
if (maxents > client->max_net_ents)
|
||||
maxents = client->max_net_ents;
|
||||
ptr = Z_Malloc( sizeof(client_frame_t)*UPDATE_BACKUP+
|
||||
sizeof(*client->pendingentbits)*client->max_net_ents+
|
||||
sizeof(unsigned int)*maxents*UPDATE_BACKUP+
|
||||
|
|
|
@ -1013,6 +1013,14 @@ void SV_WriteMVDMessage (sizebuf_t *msg, int type, int to, float time)
|
|||
void SV_MVD_WriteReliables(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
//chuck in the broadcast reliables
|
||||
ClientReliableCheckBlock(&demo.recorder, sv.reliable_datagram.cursize);
|
||||
ClientReliableWrite_SZ(&demo.recorder, sv.reliable_datagram.data, sv.reliable_datagram.cursize);
|
||||
//and the broadcast unreliables. everything is reliables when it comes to mvds
|
||||
ClientReliableCheckBlock(&demo.recorder, sv.datagram.cursize);
|
||||
ClientReliableWrite_SZ(&demo.recorder, sv.datagram.data, sv.datagram.cursize);
|
||||
|
||||
if (demo.recorder.netchan.message.cursize)
|
||||
{
|
||||
SV_WriteMVDMessage(&demo.recorder.netchan.message, dem_all, 0, sv.time);
|
||||
|
@ -1022,7 +1030,8 @@ void SV_MVD_WriteReliables(void)
|
|||
{
|
||||
demo.recorder.backbuf.data = demo.recorder.backbuf_data[i];
|
||||
demo.recorder.backbuf.cursize = demo.recorder.backbuf_size[i];
|
||||
SV_WriteMVDMessage(&demo.recorder.backbuf, dem_all, 0, sv.time);
|
||||
if (demo.recorder.backbuf.cursize)
|
||||
SV_WriteMVDMessage(&demo.recorder.backbuf, dem_all, 0, sv.time);
|
||||
demo.recorder.backbuf_size[i] = 0;
|
||||
}
|
||||
demo.recorder.num_backbuf = 0;
|
||||
|
|
|
@ -2282,14 +2282,6 @@ void World_Physics_Frame(world_t *w)
|
|||
wedict_t *ent;
|
||||
extern cvar_t sv_nqplayerphysics;
|
||||
|
||||
if (w->g.defaultgravitydir)
|
||||
{
|
||||
w->g.defaultgravitydir[0] = 0;
|
||||
w->g.defaultgravitydir[1] = 0;
|
||||
w->g.defaultgravitydir[2] = -1;
|
||||
VectorNormalize(w->g.defaultgravitydir);
|
||||
}
|
||||
|
||||
w->framenum++;
|
||||
|
||||
i = *w->g.physics_mode;
|
||||
|
|
|
@ -1648,7 +1648,7 @@ typedef struct {
|
|||
} eval;
|
||||
int statnum;
|
||||
} qcstat_t;
|
||||
qcstat_t qcstats[MAX_CL_STATS-32];
|
||||
qcstat_t qcstats[MAX_CL_STATS];
|
||||
int numqcstats;
|
||||
void SV_QCStatEval(int type, char *name, evalc_t *field, eval_t *global, int statnum)
|
||||
{
|
||||
|
@ -2205,11 +2205,10 @@ qboolean SV_SendClientDatagram (client_t *client)
|
|||
qbyte buf[MAX_OVERALLMSGLEN];
|
||||
sizebuf_t msg;
|
||||
unsigned int sentbytes;
|
||||
client_frame_t *frame = NULL;
|
||||
|
||||
if (ISQWCLIENT(client) || ISNQCLIENT(client))
|
||||
{
|
||||
frame = &client->frameunion.frames[client->netchan.outgoing_sequence & UPDATE_MASK];
|
||||
client_frame_t *frame = &client->frameunion.frames[client->netchan.outgoing_sequence & UPDATE_MASK];
|
||||
frame->numresendstats = 0;
|
||||
}
|
||||
|
||||
|
@ -2248,6 +2247,7 @@ qboolean SV_SendClientDatagram (client_t *client)
|
|||
{
|
||||
int pnum=1;
|
||||
client_t *c;
|
||||
client_frame_t *frame = &client->frameunion.frames[client->netchan.outgoing_sequence & UPDATE_MASK];
|
||||
SV_UpdateClientStats (client, 0, &msg, frame);
|
||||
|
||||
for (c = client->controlled; c; c = c->controlled,pnum++)
|
||||
|
@ -2286,8 +2286,11 @@ qboolean SV_SendClientDatagram (client_t *client)
|
|||
// send the datagram
|
||||
sentbytes = Netchan_Transmit (&client->netchan, msg.cursize, buf, SV_RateForClient(client));
|
||||
|
||||
if (frame)
|
||||
if (ISQWCLIENT(client) || ISNQCLIENT(client))
|
||||
{
|
||||
client_frame_t *frame = &client->frameunion.frames[client->netchan.outgoing_sequence & UPDATE_MASK];
|
||||
frame->packetsizeout += sentbytes;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -1804,7 +1804,7 @@ void SV_Begin_Core(client_t *split)
|
|||
if (eval && eval->function && split->spawninfo)
|
||||
{
|
||||
globalvars_t *pr_globals = PR_globals(svprogfuncs, PR_CURRENT);
|
||||
int j;
|
||||
size_t j;
|
||||
edict_t *ent;
|
||||
ent = split->edict;
|
||||
j = strlen(split->spawninfo);
|
||||
|
@ -3745,7 +3745,7 @@ void SV_Drop_f (void)
|
|||
if (!host_client->drop)
|
||||
{
|
||||
if (host_client->redirect == 2)
|
||||
SV_BroadcastPrintf (PRINT_HIGH, "%s transfered to %s\n", host_client->name, Info_ValueForKey(host_client->userinfo, "*transfer"));
|
||||
SV_BroadcastPrintf (PRINT_HIGH, "%s transfered to %s\n", host_client->name, host_client->transfer);
|
||||
else if (host_client->redirect)
|
||||
SV_BroadcastPrintf (PRINT_HIGH, "%s redirected to %s\n", host_client->name, sv_fullredirect.string);
|
||||
else
|
||||
|
@ -5680,6 +5680,9 @@ void SV_ExecuteUserCommand (char *s, qboolean fromQC)
|
|||
client_t *oldhost = host_client;
|
||||
char adr[MAX_ADR_SIZE];
|
||||
|
||||
if (host_client->state < cs_connected)
|
||||
return;
|
||||
|
||||
Con_DPrintf("Client command: %s\n", s);
|
||||
|
||||
Cmd_TokenizeString (s, false, false);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue