X-Git-Url: http://git.xonotic.org/?p=xonotic%2Fdarkplaces.git;a=blobdiff_plain;f=sv_main.c;h=8750bac1ebbd7e72beff2be32ec688202a234e32;hp=c4168d2e5d41f0d264695d084a69311104fa1e33;hb=HEAD;hpb=4a705e0b274fb1a5489d32dd67a8c36418402e08 diff --git a/sv_main.c b/sv_main.c index c4168d2e..21a2e8db 100644 --- a/sv_main.c +++ b/sv_main.c @@ -110,10 +110,11 @@ cvar_t sv_gameplayfix_easierwaterjump = {CF_SERVER, "sv_gameplayfix_easierwaterj cvar_t sv_gameplayfix_findradiusdistancetobox = {CF_SERVER, "sv_gameplayfix_findradiusdistancetobox", "1", "causes findradius to check the distance to the corner of a box rather than the center of the box, makes findradius detect bmodels such as very large doors that would otherwise be unaffected by splash damage"}; cvar_t sv_gameplayfix_gravityunaffectedbyticrate = {CF_SERVER, "sv_gameplayfix_gravityunaffectedbyticrate", "0", "fix some ticrate issues in physics."}; cvar_t sv_gameplayfix_grenadebouncedownslopes = {CF_SERVER, "sv_gameplayfix_grenadebouncedownslopes", "1", "prevents MOVETYPE_BOUNCE (grenades) from getting stuck when fired down a downward sloping surface"}; +cvar_t sv_gameplayfix_impactbeforeonground = {CF_SERVER, "sv_gameplayfix_impactbeforeonground", "0", "enables a bug from old DP versions in which entity .touch functions are called before FL_ONGROUND is set when a collision is detected in SV_FlyMove() (used by MOVETYPE_WALK and MOVETYPE_STEP), Quake 1.5 and Combat+ mods require this, it breaks id1 fiends"}; cvar_t sv_gameplayfix_multiplethinksperframe = {CF_SERVER, "sv_gameplayfix_multiplethinksperframe", "1", "allows entities to think more often than the server framerate, primarily useful for very high fire rate weapons"}; cvar_t sv_gameplayfix_noairborncorpse = {CF_SERVER, "sv_gameplayfix_noairborncorpse", "1", "causes entities (corpses, items, etc) sitting ontop of moving entities (players) to fall when the moving entity (player) is no longer supporting them"}; cvar_t sv_gameplayfix_noairborncorpse_allowsuspendeditems = {CF_SERVER, "sv_gameplayfix_noairborncorpse_allowsuspendeditems", "1", "causes entities sitting ontop of objects that are instantaneously remove to float in midair (special hack to allow a common level design trick for floating items)"}; -cvar_t sv_gameplayfix_nudgeoutofsolid = {CF_SERVER, "sv_gameplayfix_nudgeoutofsolid", "1", "attempts to fix physics errors where an object ended up in solid for some reason, supersedes sv_gameplayfix_unstickentities"}; +cvar_t sv_gameplayfix_nudgeoutofsolid = {CF_SERVER, "sv_gameplayfix_nudgeoutofsolid", "0", "attempts to fix physics errors where an object ended up in solid for some reason, better than sv_gameplayfix_unstick* but currently has no effect on Q1BSP (unless mod_q1bsp_polygoncollisions is enabled)"}; cvar_t sv_gameplayfix_nudgeoutofsolid_separation = {CF_SERVER, "sv_gameplayfix_nudgeoutofsolid_separation", "0.03125", "keep objects this distance apart to prevent collision issues on seams"}; cvar_t sv_gameplayfix_q2airaccelerate = {CF_SERVER, "sv_gameplayfix_q2airaccelerate", "0", "Quake2-style air acceleration"}; cvar_t sv_gameplayfix_nogravityonground = {CF_SERVER, "sv_gameplayfix_nogravityonground", "0", "turn off gravity when on ground (to get rid of sliding)"}; @@ -126,10 +127,9 @@ cvar_t sv_gameplayfix_swiminbmodels = {CF_SERVER, "sv_gameplayfix_swiminbmodels" cvar_t sv_gameplayfix_upwardvelocityclearsongroundflag = {CF_SERVER, "sv_gameplayfix_upwardvelocityclearsongroundflag", "1", "prevents monsters, items, and most other objects from being stuck to the floor when pushed around by damage, and other situations in mods"}; cvar_t sv_gameplayfix_downtracesupportsongroundflag = {CF_SERVER, "sv_gameplayfix_downtracesupportsongroundflag", "1", "prevents very short moves from clearing onground (which may make the player stick to the floor at high netfps), fixes groundentity not being set when walking onto a mover with sv_gameplayfix_nogravityonground"}; cvar_t sv_gameplayfix_q1bsptracelinereportstexture = {CF_SERVER, "sv_gameplayfix_q1bsptracelinereportstexture", "1", "enables mods to get accurate trace_texture results on q1bsp by using a surface-hitting traceline implementation rather than the standard solidbsp method, q3bsp always reports texture accurately"}; -cvar_t sv_gameplayfix_unstickplayers = {CF_SERVER, "sv_gameplayfix_unstickplayers", "0", "big hack to try and fix the rare case of MOVETYPE_WALK entities getting stuck in the world clipping hull."}; -cvar_t sv_gameplayfix_unstickentities = {CF_SERVER, "sv_gameplayfix_unstickentities", "1", "hack to check if entities are crossing world collision hull and try to move them to the right position, superseded by sv_gameplayfix_nudgeoutofsolid"}; +cvar_t sv_gameplayfix_unstickplayers = {CF_SERVER, "sv_gameplayfix_unstickplayers", "1", "big hack to try and fix the rare case of MOVETYPE_WALK entities getting stuck in the world clipping hull. Quake did something similar."}; +cvar_t sv_gameplayfix_unstickentities = {CF_SERVER, "sv_gameplayfix_unstickentities", "0", "hack to check if entities are crossing world collision hull and try to move them to the right position. Quake didn't do this so maps shouldn't depend on it."}; cvar_t sv_gameplayfix_fixedcheckwatertransition = {CF_SERVER, "sv_gameplayfix_fixedcheckwatertransition", "1", "fix two very stupid bugs in SV_CheckWaterTransition when watertype is CONTENTS_EMPTY (the bugs causes waterlevel to be 1 on first frame, -1 on second frame - the fix makes it 0 on both frames)"}; -cvar_t sv_gameplayfix_customstats = {CF_SERVER, "sv_gameplayfix_customstats", "0", "Disable stats higher than 220, for use by certain games such as Xonotic"}; cvar_t sv_gravity = {CF_SERVER | CF_NOTIFY, "sv_gravity","800", "how fast you fall (512 = roughly earth gravity)"}; cvar_t sv_init_frame_count = {CF_SERVER, "sv_init_frame_count", "2", "number of frames to run to allow everything to settle before letting clients connect"}; cvar_t sv_idealpitchscale = {CF_SERVER, "sv_idealpitchscale","0.8", "how much to look up/down slopes and stairs when not using freelook"}; @@ -144,6 +144,7 @@ cvar_t sv_nostep = {CF_SERVER | CF_NOTIFY, "sv_nostep","0", "prevents MOVETYPE_S cvar_t sv_playerphysicsqc = {CF_SERVER | CF_NOTIFY, "sv_playerphysicsqc", "1", "enables QuakeC function to override player physics"}; cvar_t sv_progs = {CF_SERVER, "sv_progs", "progs.dat", "selects which quakec progs.dat file to run" }; cvar_t sv_protocolname = {CF_SERVER, "sv_protocolname", "DP7", "selects network protocol to host for (values include QUAKE, QUAKEDP, NEHAHRAMOVIE, DP1 and up)"}; +cvar_t sv_qcstats = {CF_SERVER, "sv_qcstats", "0", "Disables engine sending of stats 220 and above, for use by certain games such as Xonotic, NOTE: it's strongly recommended that SVQC send correct STAT_MOVEVARS_TICRATE and STAT_MOVEVARS_TIMESCALE"}; cvar_t sv_random_seed = {CF_SERVER, "sv_random_seed", "", "random seed; when set, on every map start this random seed is used to initialize the random number generator. Don't touch it unless for benchmarking or debugging"}; cvar_t host_limitlocal = {CF_SERVER, "host_limitlocal", "0", "whether to apply rate limiting to the local player in a listen server (only useful for testing)"}; cvar_t sv_sound_land = {CF_SERVER, "sv_sound_land", "demon/dland2.wav", "sound to play when MOVETYPE_STEP entity hits the ground at high speed (empty cvar disables the sound)"}; @@ -265,12 +266,11 @@ static const char *standardeffectnames[EFFECT_TOTAL] = "SVC_PARTICLE" }; -#define SV_REQFUNCS 0 -#define sv_reqfuncs NULL -//#define SV_REQFUNCS (sizeof(sv_reqfuncs) / sizeof(const char *)) -//static const char *sv_reqfuncs[] = { -//}; +static void SV_CheckRequiredFuncs(prvm_prog_t *prog, const char *filename) +{ + // no required funcs?! +} #define SV_REQFIELDS (sizeof(sv_reqfields) / sizeof(prvm_required_field_t)) @@ -594,6 +594,7 @@ void SV_Init (void) Cvar_RegisterVariable (&sv_gameplayfix_findradiusdistancetobox); Cvar_RegisterVariable (&sv_gameplayfix_gravityunaffectedbyticrate); Cvar_RegisterVariable (&sv_gameplayfix_grenadebouncedownslopes); + Cvar_RegisterVariable (&sv_gameplayfix_impactbeforeonground); Cvar_RegisterVariable (&sv_gameplayfix_multiplethinksperframe); Cvar_RegisterVariable (&sv_gameplayfix_noairborncorpse); Cvar_RegisterVariable (&sv_gameplayfix_noairborncorpse_allowsuspendeditems); @@ -613,7 +614,7 @@ void SV_Init (void) Cvar_RegisterVariable (&sv_gameplayfix_unstickplayers); Cvar_RegisterVariable (&sv_gameplayfix_unstickentities); Cvar_RegisterVariable (&sv_gameplayfix_fixedcheckwatertransition); - Cvar_RegisterVariable (&sv_gameplayfix_customstats); + Cvar_RegisterVariable (&sv_qcstats); Cvar_RegisterVariable (&sv_gravity); Cvar_RegisterVariable (&sv_init_frame_count); Cvar_RegisterVariable (&sv_idealpitchscale); @@ -796,7 +797,7 @@ void SV_SendServerinfo (client_t *client) SZ_Clear (&client->netconnection->message); MSG_WriteByte (&client->netconnection->message, svc_print); - dpsnprintf (message, sizeof (message), "\nServer: %s build %s (progs %i crc)\n", gamename, buildstring, prog->filecrc); + dpsnprintf (message, sizeof (message), "\nServer: %s (progs %i crc)\n", engineversion, prog->filecrc); MSG_WriteString (&client->netconnection->message,message); SV_StopDemoRecording(client); // to split up demos into different files @@ -959,8 +960,8 @@ void SV_ConnectClient (int clientnum, netconn_t *netconnection) ); } - strlcpy(client->name, "unconnected", sizeof(client->name)); - strlcpy(client->old_name, "unconnected", sizeof(client->old_name)); + dp_strlcpy(client->name, "unconnected", sizeof(client->name)); + dp_strlcpy(client->old_name, "unconnected", sizeof(client->old_name)); client->prespawned = false; client->spawned = false; client->begun = false; @@ -1237,7 +1238,7 @@ static void SV_Download_f(cmd_state_t *cmd) Download_CheckExtensions(cmd); - strlcpy(host_client->download_name, Cmd_Argv(cmd, 1), sizeof(host_client->download_name)); + dp_strlcpy(host_client->download_name, Cmd_Argv(cmd, 1), sizeof(host_client->download_name)); extension = FS_FileExtension(host_client->download_name); // host_client is asking to download a specified file @@ -1250,7 +1251,7 @@ static void SV_Download_f(cmd_state_t *cmd) extensions[0] = '\0'; if(host_client->download_deflate) - strlcat(extensions, " deflate", sizeof(extensions)); + dp_strlcat(extensions, " deflate", sizeof(extensions)); Con_DPrintf("Downloading %s to %s\n", host_client->download_name, host_client->name); @@ -1405,7 +1406,7 @@ int SV_ModelIndex(const char *s, int precachemode) // testing //if (precachemode == 2) // return 0; - strlcpy(filename, s, sizeof(filename)); + dp_strlcpy(filename, s, sizeof(filename)); for (i = 2;i < limit;i++) { if (!sv.model_precache[i][0]) @@ -1419,7 +1420,7 @@ int SV_ModelIndex(const char *s, int precachemode) } if (precachemode == 1) Con_Printf("SV_ModelIndex(\"%s\"): not precached (fix your code), precaching anyway\n", filename); - strlcpy(sv.model_precache[i], filename, sizeof(sv.model_precache[i])); + dp_strlcpy(sv.model_precache[i], filename, sizeof(sv.model_precache[i])); if (sv.state == ss_loading) { // running from SV_SpawnServer which is launched from the client console command interpreter @@ -1468,7 +1469,7 @@ int SV_SoundIndex(const char *s, int precachemode) // testing //if (precachemode == 2) // return 0; - strlcpy(filename, s, sizeof(filename)); + dp_strlcpy(filename, s, sizeof(filename)); for (i = 1;i < limit;i++) { if (!sv.sound_precache[i][0]) @@ -1482,7 +1483,7 @@ int SV_SoundIndex(const char *s, int precachemode) } if (precachemode == 1) Con_Printf("SV_SoundIndex(\"%s\"): not precached (fix your code), precaching anyway\n", filename); - strlcpy(sv.sound_precache[i], filename, sizeof(sv.sound_precache[i])); + dp_strlcpy(sv.sound_precache[i], filename, sizeof(sv.sound_precache[i])); if (sv.state != ss_loading) { MSG_WriteByte(&sv.reliable_datagram, svc_precache); @@ -1523,7 +1524,7 @@ int SV_ParticleEffectIndex(const char *name) sv.particleeffectnamesloaded = true; memset(sv.particleeffectname, 0, sizeof(sv.particleeffectname)); for (i = 0;i < EFFECT_TOTAL;i++) - strlcpy(sv.particleeffectname[i], standardeffectnames[i], sizeof(sv.particleeffectname[i])); + dp_strlcpy(sv.particleeffectname[i], standardeffectnames[i], sizeof(sv.particleeffectname[i])); for (filepass = 0;;filepass++) { if (filepass == 0) @@ -1547,7 +1548,7 @@ int SV_ParticleEffectIndex(const char *name) break; if (argc < 16) { - strlcpy(argv[argc], com_token, sizeof(argv[argc])); + dp_strlcpy(argv[argc], com_token, sizeof(argv[argc])); argc++; } } @@ -1568,7 +1569,7 @@ int SV_ParticleEffectIndex(const char *name) } else { - strlcpy(sv.particleeffectname[effectnameindex], argv[1], sizeof(sv.particleeffectname[effectnameindex])); + dp_strlcpy(sv.particleeffectname[effectnameindex], argv[1], sizeof(sv.particleeffectname[effectnameindex])); break; } } @@ -1721,7 +1722,7 @@ static void SV_Prepare_CSQC(void) sv.csqc_progsize = (int)progsize; sv.csqc_progcrc = CRC_Block(svs.csqc_progdata, progsize); - strlcpy(sv.csqc_progname, csqc_progname.string, sizeof(sv.csqc_progname)); + dp_strlcpy(sv.csqc_progname, csqc_progname.string, sizeof(sv.csqc_progname)); Con_DPrintf("server detected csqc progs file \"%s\" with size %i and crc %i\n", sv.csqc_progname, sv.csqc_progsize, sv.csqc_progcrc); Con_DPrint("Compressing csprogs.dat\n"); @@ -1773,6 +1774,21 @@ int SV_IsLocalServer(void) return (host_isclient.integer && sv.active ? svs.maxclients : 0); } +static void SV_VM_Shutdown(qbool prog_reset) +{ + prvm_prog_t *prog = SVVM_prog; + + if(prog->loaded && PRVM_serverfunction(SV_Shutdown)) + { + func_t s = PRVM_serverfunction(SV_Shutdown); + PRVM_serverglobalfloat(time) = sv.time; + PRVM_serverfunction(SV_Shutdown) = 0; // prevent it from getting called again + prog->ExecuteProgram(prog, s,"SV_Shutdown() required"); + } + if (prog_reset) + PRVM_Prog_Reset(prog); +} + /* ================ SV_SpawnServer @@ -1789,21 +1805,26 @@ void SV_SpawnServer (const char *map) char *entities; model_t *worldmodel; char modelname[sizeof(sv.worldname)]; + const char *canonicalname; char vabuf[1024]; Con_Printf("SpawnServer: %s\n", map); dpsnprintf (modelname, sizeof(modelname), "maps/%s.bsp", map); - if (!FS_FileExists(modelname)) + if (!(canonicalname = FS_FileExists(modelname))) { dpsnprintf (modelname, sizeof(modelname), "maps/%s", map); - if (!FS_FileExists(modelname)) + if (!(canonicalname = FS_FileExists(modelname))) { - Con_Printf("SpawnServer: no map file named %s\n", modelname); + Con_Printf(CON_ERROR "SpawnServer: no map file named %s.bsp\n", modelname); return; } } + // if it's not in a pak canonicalname will be the same pointer as modelname + // if it's in a pak canonicalname may differ by case + if (modelname != canonicalname) + dp_strlcpy(modelname, canonicalname, sizeof(modelname)); // SV_LockThreadMutex(); @@ -1816,16 +1837,7 @@ void SV_SpawnServer (const char *map) } if(sv.active) - { - World_End(&sv.world); - if(PRVM_serverfunction(SV_Shutdown)) - { - func_t s = PRVM_serverfunction(SV_Shutdown); - PRVM_serverglobalfloat(time) = sv.time; - PRVM_serverfunction(SV_Shutdown) = 0; // prevent it from getting called again - prog->ExecuteProgram(prog, s,"SV_Shutdown() required"); - } - } + SV_VM_Shutdown(false); // free q3 shaders so that any newly downloaded shaders will be active Mod_FreeQ3Shaders(); @@ -1833,7 +1845,7 @@ void SV_SpawnServer (const char *map) worldmodel = Mod_ForName(modelname, false, developer.integer > 0, NULL); if (!worldmodel || !worldmodel->TraceBox) { - Con_Printf("Couldn't load map %s\n", modelname); + Con_Printf(CON_ERROR "Couldn't load map %s\n", modelname); if(!host_isclient.integer) Sys_MakeProcessMean(); @@ -1922,10 +1934,10 @@ void SV_SpawnServer (const char *map) sv.active = true; // set level base name variables for later use - strlcpy (sv.name, map, sizeof (sv.name)); - strlcpy(sv.worldname, modelname, sizeof(sv.worldname)); + dp_strlcpy(sv.worldname, modelname, sizeof(sv.worldname)); FS_StripExtension(sv.worldname, sv.worldnamenoextension, sizeof(sv.worldnamenoextension)); - strlcpy(sv.worldbasename, !strncmp(sv.worldnamenoextension, "maps/", 5) ? sv.worldnamenoextension + 5 : sv.worldnamenoextension, sizeof(sv.worldbasename)); + dp_strlcpy(sv.worldbasename, !strncasecmp(sv.worldnamenoextension, "maps/", 5) ? sv.worldnamenoextension + 5 : sv.worldnamenoextension, sizeof(sv.worldbasename)); +// dp_strlcpy(sv.name, sv.worldbasename, sizeof (sv.name)); // TODO can we just remove this now? //Cvar_SetQuick(&sv_worldmessage, sv.worldmessage); // set later after QC is spawned Cvar_SetQuick(&sv_worldname, sv.worldname); Cvar_SetQuick(&sv_worldnamenoextension, sv.worldnamenoextension); @@ -1976,17 +1988,17 @@ void SV_SpawnServer (const char *map) World_SetSize(&sv.world, sv.worldname, sv.worldmodel->normalmins, sv.worldmodel->normalmaxs, prog); World_Start(&sv.world); - strlcpy(sv.sound_precache[0], "", sizeof(sv.sound_precache[0])); + dp_strlcpy(sv.sound_precache[0], "", sizeof(sv.sound_precache[0])); - strlcpy(sv.model_precache[0], "", sizeof(sv.model_precache[0])); - strlcpy(sv.model_precache[1], sv.worldname, sizeof(sv.model_precache[1])); + dp_strlcpy(sv.model_precache[0], "", sizeof(sv.model_precache[0])); + dp_strlcpy(sv.model_precache[1], sv.worldname, sizeof(sv.model_precache[1])); for (i = 1;i < sv.worldmodel->brush.numsubmodels && i+1 < MAX_MODELS;i++) { dpsnprintf(sv.model_precache[i+1], sizeof(sv.model_precache[i+1]), "*%i", i); sv.models[i+1] = Mod_ForName (sv.model_precache[i+1], false, false, sv.worldname); } if(i < sv.worldmodel->brush.numsubmodels) - Con_Printf("Too many submodels (MAX_MODELS is %i)\n", MAX_MODELS); + Con_Printf(CON_WARN "Too many submodels (MAX_MODELS is %i)\n", MAX_MODELS); // // load the rest of the entities @@ -2009,7 +2021,7 @@ void SV_SpawnServer (const char *map) else PRVM_serverglobalfloat(deathmatch) = deathmatch.integer; - PRVM_serverglobalstring(mapname) = PRVM_SetEngineString(prog, sv.name); + PRVM_serverglobalstring(mapname) = PRVM_SetEngineString(prog, sv.worldbasename); // serverflags are for cross level information (sigils) PRVM_serverglobalfloat(serverflags) = svs.serverflags; @@ -2091,9 +2103,8 @@ void SV_SpawnServer (const char *map) } } - // update the map title cvar - strlcpy(sv.worldmessage, PRVM_GetString(prog, PRVM_serveredictstring(prog->edicts, message)), sizeof(sv.worldmessage)); // map title (not related to filename) - Cvar_SetQuick(&sv_worldmessage, sv.worldmessage); + // update the map title cvar (not related to filename) + Cvar_SetQuick(&sv_worldmessage, PRVM_GetString(prog, PRVM_serveredictstring(prog->edicts, message))); Con_Printf("Server spawned.\n"); NetConn_Heartbeat (2); @@ -2113,7 +2124,6 @@ This only happens at the end of a game, not between levels */ void SV_Shutdown(void) { - prvm_prog_t *prog = SVVM_prog; int i; SV_LockThreadMutex(); @@ -2126,22 +2136,13 @@ void SV_Shutdown(void) NetConn_Heartbeat(2); NetConn_Heartbeat(2); -// make sure all the clients know we're disconnecting - World_End(&sv.world); - if(prog->loaded) - { - if(PRVM_serverfunction(SV_Shutdown)) - { - func_t s = PRVM_serverfunction(SV_Shutdown); - PRVM_serverglobalfloat(time) = sv.time; - PRVM_serverfunction(SV_Shutdown) = 0; // prevent it from getting called again - prog->ExecuteProgram(prog, s,"SV_Shutdown() required"); - } - } + // make sure all the clients know we're disconnecting for (i = 0, host_client = svs.clients;i < svs.maxclients;i++, host_client++) if (host_client->active) SV_DropClient(false, "Server shutting down"); // server shutdown + SV_VM_Shutdown(true); + NetConn_CloseServerPorts(); sv.active = false; @@ -2346,7 +2347,7 @@ static void SV_VM_Setup(void) prog->error_cmd = Host_Error; prog->ExecuteProgram = SVVM_ExecuteProgram; - PRVM_Prog_Load(prog, sv_progs.string, NULL, 0, SV_REQFUNCS, sv_reqfuncs, SV_REQFIELDS, sv_reqfields, SV_REQGLOBALS, sv_reqglobals); + PRVM_Prog_Load(prog, sv_progs.string, NULL, 0, SV_CheckRequiredFuncs, 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" @@ -2519,7 +2520,6 @@ const char *SV_TimingReport(char *buf, size_t buflen) return va(buf, buflen, "%.1f%% CPU, %.2f%% lost, offset avg %.1fms, max %.1fms, sdev %.1fms", sv.perf_cpuload * 100, sv.perf_lost * 100, sv.perf_offset_avg * 1000, sv.perf_offset_max * 1000, sv.perf_offset_sdev * 1000); } -extern cvar_t host_maxwait; extern cvar_t host_framerate; double SV_Frame(double time) { @@ -2712,7 +2712,6 @@ static int SV_ThreadFunc(void *voiddata) qbool playing = false; double sv_timer = 0; double sv_deltarealtime, sv_oldrealtime, sv_realtime; - double wait; int i; char vabuf[1024]; sv_realtime = Sys_DirtyTime(); @@ -2771,21 +2770,10 @@ static int SV_ThreadFunc(void *voiddata) } // if the accumulators haven't become positive yet, wait a while - wait = sv_timer * -1000000.0; - if (wait >= 1) + if (sv_timer < 0) { - double time0, delta; SV_UnlockThreadMutex(); // don't keep mutex locked while sleeping - if (host_maxwait.value <= 0) - wait = min(wait, 1000000.0); - else - wait = min(wait, host_maxwait.value * 1000.0); - if(wait < 1) - wait = 1; // because we cast to int - time0 = Sys_DirtyTime(); - Sys_Sleep((int)wait); - delta = Sys_DirtyTime() - time0;if (delta < 0 || delta >= 1800) delta = 0; - sv.perf_acc_sleeptime += delta; + sv.perf_acc_sleeptime += Sys_Sleep(-sv_timer); continue; }