cvar_t gamecfg = {0, "gamecfg", "0", "unused cvar in quake, can be used by mods"};
cvar_t noexit = {CVAR_NOTIFY, "noexit","0", "kills anyone attempting to use an exit"};
cvar_t nomonsters = {0, "nomonsters", "0", "unused cvar in quake, can be used by mods"};
-cvar_t pausable = {0, "pausable","1", "allow players to pause or not"};
+cvar_t pausable = {0, "pausable","1", "allow players to pause or not (otherwise, only the server admin can)"};
cvar_t pr_checkextension = {CVAR_READONLY, "pr_checkextension", "1", "indicates to QuakeC that the standard quakec extensions system is available (if 0, quakec should not attempt to use extensions)"};
cvar_t samelevel = {CVAR_NOTIFY, "samelevel","0", "repeats same level if level ends (due to timelimit or someone hitting an exit)"};
cvar_t skill = {0, "skill","1", "difficulty level of game, affects monster layouts in levels, 0 = easy, 1 = normal, 2 = hard, 3 = nightmare (same layout as hard but monsters fire twice)"};
MSG_WriteByte (&client->netconnection->message, svc_signonnum);
MSG_WriteByte (&client->netconnection->message, 1);
+ client->prespawned = false; // need prespawn, spawn, etc
client->spawned = false; // need prespawn, spawn, etc
+ client->begun = false; // need prespawn, spawn, etc
client->sendsignon = 1; // send this message, and increment to 2, 2 will be set to 0 by the prespawn command
// clear movement info until client enters the new level properly
strlcpy(client->name, "unconnected", sizeof(client->name));
strlcpy(client->old_name, "unconnected", sizeof(client->old_name));
+ client->prespawned = false;
client->spawned = false;
+ client->begun = false;
client->edict = PRVM_EDICT_NUM(clientnum+1);
if (client->netconnection)
client->netconnection->message.allowoverflow = true; // we can catch it
if (client->netconnection)
SV_SendServerinfo (client);
else
- client->spawned = true;
+ client->prespawned = client->spawned = client->begun = true;
}
unsigned int customizeentityforclient;
unsigned int sendentity;
float f;
- float *v;
+ prvm_vec_t *v;
vec3_t cullmins, cullmaxs;
dp_model_t *model;
cs->framegroupblend[2].lerp = PRVM_serveredictfloat(ent, lerpfrac3);
cs->framegroupblend[3].lerp = PRVM_serveredictfloat(ent, lerpfrac4);
cs->framegroupblend[0].lerp = 1.0f - cs->framegroupblend[1].lerp - cs->framegroupblend[2].lerp - cs->framegroupblend[3].lerp;
+ cs->frame = 0; // don't need the legacy frame
}
cs->light[0] = light[0];
else
EntityFrameCSQC_WriteFrame(msg, maxsize, numcsqcsendstates, sv.writeentitiestoclient_csqcsendstates, 0);
- if(client->num_skippedentityframes >= 10)
- need_empty = true; // force every 10th frame to be not empty (or cl_movement replay takes too long)
+ // force every 16th frame to be not empty (or cl_movement replay takes
+ // too long)
+ // BTW, this should normally not kick in any more due to the check
+ // below, except if the client stopped sending movement frames
+ if(client->num_skippedentityframes >= 16)
+ need_empty = true;
+
+ // help cl_movement a bit more
+ if(client->movesequence != client->lastmovesequence)
+ need_empty = true;
+ client->lastmovesequence = client->movesequence;
if (client->entitydatabase5)
success = EntityFrame5_WriteFrame(msg, maxsize, client->entitydatabase5, numsendstates, sv.writeentitiestoclient_sendstates, client - svs.clients + 1, client->movesequence, need_empty);
{
// angle fixing was requested by global thinking code...
// so store the current angles for later use
- memcpy(host_client->fixangle_angles, PRVM_serveredictvector(ent, angles), sizeof(host_client->fixangle_angles));
+ VectorCopy(PRVM_serveredictvector(ent, angles), host_client->fixangle_angles);
host_client->fixangle_angles_set = TRUE;
// and clear fixangle for the next frame
host_client->fixangle_angles_set = FALSE;
}
- // stuff the sigil bits into the high bits of items for sbar, or else
- // mix in items2
- // LordHavoc: detecting items2 turned out to be tricky, check if the field
- // was forcefully declared, we want to override serverflags if it was
- // declared by the qc intentionally, but not if we added it in the engine.
- if (prog->fieldoffsets.items2 < (int)(prog->numfielddefs - SV_REQGLOBALS))
- items = (int)PRVM_serveredictfloat(ent, items) | ((int)PRVM_serveredictfloat(ent, items2) << 23);
- else
- items = (int)PRVM_serveredictfloat(ent, items) | ((int)PRVM_serverglobalfloat(serverflags) << 28);
+ // the runes are in serverflags, pack them into the items value, also pack
+ // in the items2 value for mission pack huds
+ // (used only in the mission packs, which do not use serverflags)
+ items = (int)PRVM_serveredictfloat(ent, items) | ((int)PRVM_serveredictfloat(ent, items2) << 23) | ((int)PRVM_serverglobalfloat(serverflags) << 28);
VectorCopy(PRVM_serveredictvector(ent, punchvector), punchvector);
MSG_WriteByte (msg, stats[STAT_NAILS]);
MSG_WriteByte (msg, stats[STAT_ROCKETS]);
MSG_WriteByte (msg, stats[STAT_CELLS]);
- if (gamemode == GAME_HIPNOTIC || gamemode == GAME_ROGUE || gamemode == GAME_NEXUIZ)
+ if (gamemode == GAME_HIPNOTIC || gamemode == GAME_ROGUE || gamemode == GAME_QUOTH || gamemode == GAME_NEXUIZ)
{
for (i = 0;i < 32;i++)
if (stats[STAT_ACTIVEWEAPON] & (1<<i))
return;
for (i = 0, client = svs.clients;i < svs.maxclients;i++, client++)
{
- if (!client->spawned || !client->netconnection || client->unreliablemsg.cursize + sv.datagram.cursize > client->unreliablemsg.maxsize || client->unreliablemsg_splitpoints >= (int)(sizeof(client->unreliablemsg_splitpoint)/sizeof(client->unreliablemsg_splitpoint[0])))
+ if (!client->begun || !client->netconnection || client->unreliablemsg.cursize + sv.datagram.cursize > client->unreliablemsg.maxsize || client->unreliablemsg_splitpoints >= (int)(sizeof(client->unreliablemsg_splitpoint)/sizeof(client->unreliablemsg_splitpoint[0])))
continue;
SZ_Write(&client->unreliablemsg, sv.datagram.data, sv.datagram.cursize);
client->unreliablemsg_splitpoint[client->unreliablemsg_splitpoints++] = client->unreliablemsg.cursize;
msg.cursize = 0;
msg.allowoverflow = false;
- if (host_client->spawned)
+ if (host_client->begun)
{
// the player is in the game
MSG_WriteByte (&msg, svc_time);
PRVM_serveredictstring(host_client->edict, netname) = PRVM_SetEngineString(prog, host_client->name);
if (strcmp(host_client->old_name, host_client->name))
{
- if (host_client->spawned)
+ if (host_client->begun)
SV_BroadcastPrintf("%s ^7changed name to %s\n", host_client->old_name, host_client->name);
strlcpy(host_client->old_name, host_client->name, sizeof(host_client->old_name));
// send notification to all clients
// frags
host_client->frags = (int)PRVM_serveredictfloat(host_client->edict, frags);
if(gamemode == GAME_NEXUIZ || gamemode == GAME_XONOTIC)
- if(!host_client->spawned && host_client->netconnection)
+ if(!host_client->begun && host_client->netconnection)
host_client->frags = -666;
if (host_client->old_frags != host_client->frags)
{
}
for (j = 0, client = svs.clients;j < svs.maxclients;j++, client++)
- if (client->netconnection && (client->spawned || client->clientconnectcalled)) // also send MSG_ALL to people who are past ClientConnect, but not spawned yet
+ if (client->netconnection && (client->begun || client->clientconnectcalled)) // also send MSG_ALL to people who are past ClientConnect, but not spawned yet
SZ_Write (&client->netconnection->message, sv.reliable_datagram.data, sv.reliable_datagram.cursize);
SZ_Clear (&sv.reliable_datagram);
argc = 0;
for (;;)
{
- if (!COM_ParseToken_Simple(&text, true, false) || !strcmp(com_token, "\n"))
+ if (!COM_ParseToken_Simple(&text, true, false, true) || !strcmp(com_token, "\n"))
break;
if (argc < 16)
{
if (cls.state != ca_dedicated)
{
- SCR_BeginLoadingPlaque();
+ SCR_BeginLoadingPlaque(false);
S_StopAllSounds();
}
//
// AK possible hack since num_edicts is still 0
ent = PRVM_EDICT_NUM(0);
- memset (ent->fields.vp, 0, prog->entityfields * 4);
+ memset (ent->fields.fp, 0, prog->entityfields * sizeof(prvm_vec_t));
ent->priv.server->free = false;
PRVM_serveredictstring(ent, model) = PRVM_SetEngineString(prog, sv.worldname);
PRVM_serveredictfloat(ent, modelindex) = 1; // world model
// and we need to set the ->edict pointers to point into the progs edicts
for (i = 0, host_client = svs.clients;i < svs.maxclients;i++, host_client++)
{
- host_client->spawned = false;
+ host_client->begun = false;
host_client->edict = PRVM_EDICT_NUM(i + 1);
PRVM_ED_ClearEdict(prog, host_client->edict);
}
PRVM_serverglobaledict(self) = PRVM_EDICT_TO_PROG(host_client->edict);
prog->ExecuteProgram(prog, PRVM_serverfunction(ClientConnect), "QC function ClientConnect is missing");
prog->ExecuteProgram(prog, PRVM_serverfunction(PutClientInServer), "QC function PutClientInServer is missing");
- host_client->spawned = true;
+ host_client->begun = true;
}
}
prog->error_cmd = Host_Error;
prog->ExecuteProgram = SVVM_ExecuteProgram;
- PRVM_Prog_Load(prog, sv_progs.string, SV_REQFUNCS, sv_reqfuncs, SV_REQFIELDS, sv_reqfields, SV_REQGLOBALS, sv_reqglobals);
+ PRVM_Prog_Load(prog, sv_progs.string, NULL, 0, SV_REQFUNCS, sv_reqfuncs, SV_REQFIELDS, sv_reqfields, SV_REQGLOBALS, sv_reqglobals);
// some mods compiled with scrambling compilers lack certain critical
// global names and field names such as "self" and "time" and "nextthink"
playing = false;
if (sv.active)
for (i = 0, host_client = svs.clients;i < svs.maxclients;i++, host_client++)
- if(host_client->spawned)
+ if(host_client->begun)
if(host_client->netconnection)
playing = true;
- if(!playing)
+ if(sv.time < 10)
{
- // Nobody is looking? Then we won't do timing...
- // Instead, reset it to zero
+ // don't accumulate time for the first 10 seconds of a match
+ // so things can settle
svs.perf_acc_realtime = svs.perf_acc_sleeptime = svs.perf_acc_lost = svs.perf_acc_offset = svs.perf_acc_offset_squared = svs.perf_acc_offset_max = svs.perf_acc_offset_samples = 0;
}
else if(svs.perf_acc_realtime > 5)
svs.perf_offset_sdev = sqrt(svs.perf_acc_offset_squared / svs.perf_acc_offset_samples - svs.perf_offset_avg * svs.perf_offset_avg);
}
if(svs.perf_lost > 0 && developer_extra.integer)
- Con_DPrintf("Server can't keep up: %s\n", Host_TimingReport(vabuf, sizeof(vabuf)));
+ if(playing)
+ Con_DPrintf("Server can't keep up: %s\n", Host_TimingReport(vabuf, sizeof(vabuf)));
svs.perf_acc_realtime = svs.perf_acc_sleeptime = svs.perf_acc_lost = svs.perf_acc_offset = svs.perf_acc_offset_squared = svs.perf_acc_offset_max = svs.perf_acc_offset_samples = 0;
}
if (sv.paused == 1 && sv_realtime > sv.pausedstart && sv.pausedstart > 0)
{
PRVM_serverglobalfloat(time) = sv.time;
- prog->globals.generic[OFS_PARM0] = sv_realtime - sv.pausedstart;
+ prog->globals.fp[OFS_PARM0] = sv_realtime - sv.pausedstart;
prog->ExecuteProgram(prog, PRVM_serverfunction(SV_PausedTic), "QC function SV_PausedTic is missing");
}