]> git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - sv_main.c
added PRVM_64 define which upgrades the QC VM to double precision
[xonotic/darkplaces.git] / sv_main.c
index c99273b1add0f9a448ba8e24f3a3c7de40d58be9..d94bb0321ec868dcd887d062bb05f54571071a7b 100644 (file)
--- a/sv_main.c
+++ b/sv_main.c
@@ -43,7 +43,7 @@ cvar_t fraglimit = {CVAR_NOTIFY, "fraglimit","0", "ends level if this many frags
 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)"};
@@ -1160,7 +1160,7 @@ static qboolean SV_PrepareEntityForSending (prvm_edict_t *ent, entity_state_t *c
        unsigned int customizeentityforclient;
        unsigned int sendentity;
        float f;
-       float *v;
+       prvm_vec_t *v;
        vec3_t cullmins, cullmaxs;
        dp_model_t *model;
 
@@ -1362,6 +1362,7 @@ static qboolean SV_PrepareEntityForSending (prvm_edict_t *ent, entity_state_t *c
                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];
@@ -1894,8 +1895,17 @@ static void SV_WriteEntitiesToClient(client_t *client, prvm_edict_t *clent, size
        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);
@@ -1983,7 +1993,7 @@ void SV_WriteClientdataToMessage (client_t *client, prvm_edict_t *ent, sizebuf_t
        {
                // 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
@@ -1998,15 +2008,10 @@ void SV_WriteClientdataToMessage (client_t *client, prvm_edict_t *ent, sizebuf_t
                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);
 
@@ -2973,7 +2978,7 @@ int SV_ParticleEffectIndex(const char *name)
                                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)
                                        {
@@ -3231,9 +3236,12 @@ void SV_SpawnServer (const char *server)
 
 //     SV_LockThreadMutex();
 
+       if(cls.state == ca_dedicated)
+               Sys_MakeProcessNice();
+
        if (cls.state != ca_dedicated)
        {
-               SCR_BeginLoadingPlaque();
+               SCR_BeginLoadingPlaque(false);
                S_StopAllSounds();
        }
 
@@ -3256,7 +3264,12 @@ void SV_SpawnServer (const char *server)
        if (!worldmodel || !worldmodel->TraceBox)
        {
                Con_Printf("Couldn't load map %s\n", modelname);
+
+               if(cls.state == ca_dedicated)
+                       Sys_MakeProcessMean();
+
 //             SV_UnlockThreadMutex();
+
                return;
        }
 
@@ -3396,7 +3409,7 @@ void SV_SpawnServer (const char *server)
 //
        // 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
@@ -3498,6 +3511,9 @@ void SV_SpawnServer (const char *server)
        Con_DPrint("Server spawned.\n");
        NetConn_Heartbeat (2);
 
+       if(cls.state == ca_dedicated)
+               Sys_MakeProcessMean();
+
 //     SV_UnlockThreadMutex();
 }
 
@@ -3883,10 +3899,10 @@ static int SV_ThreadFunc(void *voiddata)
                                if(host_client->spawned)
                                        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)
@@ -3900,7 +3916,8 @@ static int SV_ThreadFunc(void *voiddata)
                                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;
                }
 
@@ -3968,7 +3985,7 @@ static int SV_ThreadFunc(void *voiddata)
                        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");
                        }