cvar_t host_speeds = {0, "host_speeds","0", "reports how much time is used in server/graphics/sound"};
cvar_t host_maxwait = {0, "host_maxwait","1000", "maximum sleep time requested from the operating system in millisecond. Larger sleeps will be done using multiple host_maxwait length sleeps. Lowering this value will increase CPU load, but may help working around problems with accuracy of sleep times."};
cvar_t cl_minfps = {CVAR_SAVE, "cl_minfps", "40", "minimum fps target - while the rendering performance is below this, it will drift toward lower quality"};
-cvar_t cl_minfps_fade = {CVAR_SAVE, "cl_minfps_fade", "0.2", "how fast the quality adapts to varying framerate"};
+cvar_t cl_minfps_fade = {CVAR_SAVE, "cl_minfps_fade", "1", "how fast the quality adapts to varying framerate"};
cvar_t cl_minfps_qualitymax = {CVAR_SAVE, "cl_minfps_qualitymax", "1", "highest allowed drawdistance multiplier"};
cvar_t cl_minfps_qualitymin = {CVAR_SAVE, "cl_minfps_qualitymin", "0.25", "lowest allowed drawdistance multiplier"};
-cvar_t cl_minfps_qualitypower = {CVAR_SAVE, "cl_minfps_qualitypower", "4", "raises quality value to a power of itself, higher values make quality drop more sharply in relation to framerate"};
-cvar_t cl_minfps_qualityscale = {CVAR_SAVE, "cl_minfps_qualityscale", "0.5", "multiplier for quality"};
+cvar_t cl_minfps_qualitymultiply = {CVAR_SAVE, "cl_minfps_qualitymultiply", "0.2", "multiplier for quality changes in quality change per second render time (1 assumes linearity of quality and render time)"};
+cvar_t cl_minfps_qualityhysteresis = {CVAR_SAVE, "cl_minfps_qualityhysteresis", "0.05", "reduce all quality increments by this to reduce flickering"};
+cvar_t cl_minfps_qualitystepmax = {CVAR_SAVE, "cl_minfps_qualitystepmax", "0.1", "maximum quality change in a single frame"};
+cvar_t cl_minfps_force = {0, "cl_minfps_force", "0", "also apply quality reductions in timedemo/capturevideo"};
cvar_t cl_maxfps = {CVAR_SAVE, "cl_maxfps", "0", "maximum fps cap, 0 = unlimited, if game is running faster than this it will wait before running another frame (useful to make cpu time available to other programs)"};
cvar_t cl_maxfps_alwayssleep = {0, "cl_maxfps_alwayssleep","1", "gives up some processing time to other applications each frame, value in milliseconds, disabled if cl_maxfps is 0"};
cvar_t cl_maxidlefps = {CVAR_SAVE, "cl_maxidlefps", "20", "maximum fps cap when the game is not the active window (makes cpu time available to other programs"};
cvar_t timestamps = {CVAR_SAVE, "timestamps", "0", "prints timestamps on console messages"};
cvar_t timeformat = {CVAR_SAVE, "timeformat", "[%Y-%m-%d %H:%M:%S] ", "time format to use on timestamped console messages"};
+cvar_t sessionid = {CVAR_READONLY, "sessionid", "", "ID of the current session (use the -sessionid parameter to set it); this is always either empty or begins with a dot (.)"};
+cvar_t locksession = {0, "locksession", "0", "Lock the session? 0 = no, 1 = yes and abort on failure, 2 = yes and continue on failure"};
+
/*
================
Host_AbortCurrentFrame
*/
void Host_AbortCurrentFrame(void)
{
+ // in case we were previously nice, make us mean again
+ Sys_MakeProcessMean();
+
longjmp (host_abortframe, 1);
}
Cvar_RegisterVariable (&cl_minfps_fade);
Cvar_RegisterVariable (&cl_minfps_qualitymax);
Cvar_RegisterVariable (&cl_minfps_qualitymin);
- Cvar_RegisterVariable (&cl_minfps_qualitypower);
- Cvar_RegisterVariable (&cl_minfps_qualityscale);
+ Cvar_RegisterVariable (&cl_minfps_qualitystepmax);
+ Cvar_RegisterVariable (&cl_minfps_qualityhysteresis);
+ Cvar_RegisterVariable (&cl_minfps_qualitymultiply);
+ Cvar_RegisterVariable (&cl_minfps_force);
Cvar_RegisterVariable (&cl_maxfps);
Cvar_RegisterVariable (&cl_maxfps_alwayssleep);
Cvar_RegisterVariable (&cl_maxidlefps);
// process console commands
// R_TimeReport("preconsole");
CL_VM_PreventInformationLeaks();
- Cbuf_Execute();
+ Cbuf_Frame();
// R_TimeReport("console");
}
advancetime = sv_timer;
else if (cl.islocalgame && !sv_fixedframeratesingleplayer.integer)
{
- // synchronize to the client frametime, but no less than 10ms and no more than sys_ticrate
- advancetime = bound(0.01, cl_timer, sys_ticrate.value);
- framelimit = cl_maxphysicsframesperserverframe.integer;
- aborttime = realtime + 0.1;
+ // synchronize to the client frametime, but no less than 10ms and no more than 100ms
+ advancetime = bound(0.01, cl_timer, 0.1);
}
else
{
advancetime = sys_ticrate.value;
// listen servers can run multiple server frames per client frame
- if (cls.state == ca_connected)
- {
- framelimit = cl_maxphysicsframesperserverframe.integer;
- aborttime = realtime + 0.1;
- }
+ framelimit = cl_maxphysicsframesperserverframe.integer;
+ aborttime = Sys_DirtyTime() + 0.1;
}
if(slowmo.value > 0 && slowmo.value < 1)
advancetime = min(advancetime, 0.1 / slowmo.value);
if(advancetime > 0)
{
- offset = Sys_DirtyTime() - realtime;if (offset < 0 || offset >= 1800) offset = 0;
+ offset = Sys_DirtyTime() - dirtytime;if (offset < 0 || offset >= 1800) offset = 0;
offset += sv_timer;
++svs.perf_acc_offset_samples;
svs.perf_acc_offset += offset;
extern qboolean host_stuffcmdsrun;
+static qfile_t *locksession_fh = NULL;
+static qboolean locksession_run = false;
+static void Host_InitSession(void)
+{
+ int i;
+ Cvar_RegisterVariable(&sessionid);
+ Cvar_RegisterVariable(&locksession);
+
+ // load the session ID into the read-only cvar
+ if ((i = COM_CheckParm("-sessionid")) && (i + 1 < com_argc))
+ {
+ char vabuf[1024];
+ if(com_argv[i+1][0] == '.')
+ Cvar_SetQuick(&sessionid, com_argv[i+1]);
+ else
+ Cvar_SetQuick(&sessionid, va(vabuf, sizeof(vabuf), ".%s", com_argv[i+1]));
+ }
+}
+void Host_LockSession(void)
+{
+ if(locksession_run)
+ return;
+ locksession_run = true;
+ if(locksession.integer != 0)
+ {
+ char vabuf[1024];
+ char *p = va(vabuf, sizeof(vabuf), "%slock%s", *fs_userdir ? fs_userdir : fs_basedir, sessionid.string);
+ FS_CreatePath(p);
+ locksession_fh = FS_SysOpen(p, "wl", false);
+ // TODO maybe write the pid into the lockfile, while we are at it? may help server management tools
+ if(!locksession_fh)
+ {
+ if(locksession.integer == 2)
+ {
+ Con_Printf("WARNING: session lock %s could not be acquired. Please run with -sessionid and an unique session name. Continuing anyway.\n", p);
+ }
+ else
+ {
+ Sys_Error("session lock %s could not be acquired. Please run with -sessionid and an unique session name.\n", p);
+ }
+ }
+ }
+}
+void Host_UnlockSession(void)
+{
+ if(!locksession_run)
+ return;
+ locksession_run = false;
+
+ if(locksession_fh)
+ {
+ FS_Close(locksession_fh);
+ // NOTE: we can NOT unlink the lock here, as doing so would
+ // create a race condition if another process created it
+ // between our close and our unlink
+ locksession_fh = NULL;
+ }
+}
+
/*
====================
Host_Init
dpsnprintf (engineversion, sizeof (engineversion), "%s %s %s", gamename, os, buildstring);
Con_Printf("%s\n", engineversion);
+ // initialize process nice level
+ Sys_InitProcessNice();
+
// initialize ixtable
Mathlib_Init();
// initialize filesystem (including fs_basedir, fs_gamedir, -game, scr_screenshot_name)
FS_Init();
+ // register the cvars for session locking
+ Host_InitSession();
+
// must be after FS_Init
Crypto_Init();
Crypto_Init_Commands();
if (!sv.active && !cls.demoplayback && !cls.connect_trying)
{
- Cbuf_AddText("togglemenu\n");
+ Cbuf_AddText("togglemenu 1\n");
Cbuf_Execute();
}
// be quiet while shutting down
S_StopAllSounds();
+ // end the server thread
+ if (svs.threaded)
+ SV_StopThread();
+
// disconnect client from server if active
CL_Disconnect();
Host_ShutdownServer ();
SV_UnlockThreadMutex();
- // end the server thread
- if (svs.threaded)
- SV_StopThread();
-
// Shutdown menu
if(MR_Shutdown)
MR_Shutdown();
Sys_Shutdown();
Log_Close();
Crypto_Shutdown();
- FS_Shutdown();
+
+ Host_UnlockSession();
+
+ S_Shutdown();
Con_Shutdown();
Memory_Shutdown();
}