X-Git-Url: https://git.xonotic.org/?a=blobdiff_plain;f=host.c;h=fa64cf64e16bb35ec03d5bd21e8afe6382706188;hb=79e0d29501f9ee5965da7b310266bcad1a5a8dbe;hp=aea36ef34baa8c75ec845f99f4faf83bf820c491;hpb=39ffc8f99e2ea7bed0b477ce5b9220821f93adc1;p=xonotic%2Fdarkplaces.git diff --git a/host.c b/host.c index aea36ef3..fa64cf64 100644 --- a/host.c +++ b/host.c @@ -52,47 +52,19 @@ client_t *host_client; jmp_buf host_abortframe; -// random seed -cvar_t sv_random_seed = {0, "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"}; - // pretend frames take this amount of time (in seconds), 0 = realtime cvar_t host_framerate = {0, "host_framerate","0", "locks frame timing to this value in seconds, 0.05 is 20fps for example, note that this can easily run too fast, use cl_maxfps if you want to limit your framerate instead, or sys_ticrate to limit server speed"}; // shows time used by certain subsystems cvar_t host_speeds = {0, "host_speeds","0", "reports how much time is used in server/graphics/sound"}; -// LordHavoc: framerate independent slowmo -cvar_t slowmo = {0, "slowmo", "1.0", "controls game speed, 0.5 is half speed, 2 is double speed"}; // LordHavoc: framerate upper cap cvar_t cl_maxfps = {CVAR_SAVE, "cl_maxfps", "1000", "maximum fps cap, if game is running faster than this it will wait before running another frame (useful to make cpu time available to other programs)"}; -// print broadcast messages in dedicated mode -cvar_t sv_echobprint = {CVAR_SAVE, "sv_echobprint", "1", "prints gamecode bprint() calls to server console"}; - -cvar_t sys_ticrate = {CVAR_SAVE, "sys_ticrate","0.05", "how long a server frame is in seconds, 0.05 is 20fps server rate, 0.1 is 10fps (can not be set higher than 0.1), 0 runs as many server frames as possible (makes games against bots a little smoother, overwhelms network players)"}; -cvar_t sv_fixedframeratesingleplayer = {0, "sv_fixedframeratesingleplayer", "0", "allows you to use server-style timing system in singleplayer (don't run faster than sys_ticrate)"}; - -cvar_t fraglimit = {CVAR_NOTIFY, "fraglimit","0", "ends level if this many frags is reached by any player"}; -cvar_t timelimit = {CVAR_NOTIFY, "timelimit","0", "ends level at this time (in minutes)"}; -cvar_t teamplay = {CVAR_NOTIFY, "teamplay","0", "teamplay mode, values depend on mod but typically 0 = no teams, 1 = no team damage no self damage, 2 = team damage and self damage, some mods support 3 = no team damage but can damage self"}; - -cvar_t samelevel = {CVAR_NOTIFY, "samelevel","0", "repeats same level if level ends (due to timelimit or someone hitting an exit)"}; -cvar_t noexit = {CVAR_NOTIFY, "noexit","0", "kills anyone attempting to use an exit"}; - cvar_t developer = {0, "developer","0", "prints additional debugging messages and information (recommended for modders and level designers)"}; cvar_t developer_entityparsing = {0, "developer_entityparsing", "0", "prints detailed network entities information each time a packet is received"}; -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)"}; -cvar_t deathmatch = {0, "deathmatch","0", "deathmatch mode, values depend on mod but typically 0 = no deathmatch, 1 = normal deathmatch with respawning weapons, 2 = weapons stay (players can only pick up new weapons)"}; -cvar_t coop = {0, "coop","0", "coop mode, 0 = no coop, 1 = coop mode, multiple players playing through the singleplayer game (coop mode also shuts off deathmatch)"}; - -cvar_t pausable = {0, "pausable","1", "allow players to pause or not"}; - -cvar_t temp1 = {0, "temp1","0", "general cvar for mods to use, in stock id1 this selects which death animation to use on players (0 = random death, other values select specific death scenes)"}; - 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 sv_checkforpacketsduringsleep = {0, "sv_checkforpacketsduringsleep", "0", "uses select() function to wait between frames which can be interrupted by packets being received, instead of Sleep()/usleep()/SDL_Sleep() functions which do not check for packets"}; - /* ================ Host_AbortCurrentFrame @@ -224,36 +196,15 @@ static void Host_InitLocal (void) Cmd_AddCommand("saveconfig", Host_SaveConfig_f, "save settings to config.cfg immediately (also automatic when quitting)"); Cmd_AddCommand("loadconfig", Host_LoadConfig_f, "reset everything and reload configs"); - Cvar_RegisterVariable (&sv_random_seed); Cvar_RegisterVariable (&host_framerate); Cvar_RegisterVariable (&host_speeds); - Cvar_RegisterVariable (&slowmo); Cvar_RegisterVariable (&cl_maxfps); - Cvar_RegisterVariable (&sv_echobprint); - - Cvar_RegisterVariable (&sys_ticrate); - Cvar_RegisterVariable (&sv_fixedframeratesingleplayer); - - Cvar_RegisterVariable (&fraglimit); - Cvar_RegisterVariable (&timelimit); - Cvar_RegisterVariable (&teamplay); - Cvar_RegisterVariable (&samelevel); - Cvar_RegisterVariable (&noexit); - Cvar_RegisterVariable (&skill); Cvar_RegisterVariable (&developer); Cvar_RegisterVariable (&developer_entityparsing); - Cvar_RegisterVariable (&deathmatch); - Cvar_RegisterVariable (&coop); - - Cvar_RegisterVariable (&pausable); - - Cvar_RegisterVariable (&temp1); Cvar_RegisterVariable (×tamps); Cvar_RegisterVariable (&timeformat); - - Cvar_RegisterVariable (&sv_checkforpacketsduringsleep); } @@ -271,7 +222,7 @@ void Host_SaveConfig_f(void) // dedicated servers initialize the host but don't parse and set the // config.cfg cvars // LordHavoc: don't save a config if it crashed in startup - if (host_framecount >= 3 && cls.state != ca_dedicated && !COM_CheckParm("-benchmark")) + if (host_framecount >= 3 && cls.state != ca_dedicated && !COM_CheckParm("-benchmark") && !COM_CheckParm("-capturedemo")) { f = FS_Open ("config.cfg", "wb", false, false); if (!f) @@ -435,9 +386,9 @@ void SV_DropClient(qboolean crash) buf.data = bufdata; buf.maxsize = sizeof(bufdata); MSG_WriteByte(&buf, svc_disconnect); - NetConn_SendUnreliableMessage(host_client->netconnection, &buf, sv.protocol); - NetConn_SendUnreliableMessage(host_client->netconnection, &buf, sv.protocol); - NetConn_SendUnreliableMessage(host_client->netconnection, &buf, sv.protocol); + NetConn_SendUnreliableMessage(host_client->netconnection, &buf, sv.protocol, 10000, false); + NetConn_SendUnreliableMessage(host_client->netconnection, &buf, sv.protocol, 10000, false); + NetConn_SendUnreliableMessage(host_client->netconnection, &buf, sv.protocol, 10000, false); } // break the net connection NetConn_Close(host_client->netconnection); @@ -577,12 +528,11 @@ Runs all active servers static void Host_Init(void); void Host_Main(void) { - static double time1 = 0; - static double time2 = 0; - static double time3 = 0; - // these are static because of setjmp/longjmp warnings in mingw32 gcc 2.95.3 - static double frameoldtime, framenewtime, framedeltatime, cl_timer, sv_timer; - double clframetime; + double time1 = 0; + double time2 = 0; + double time3 = 0; + double cl_timer, sv_timer; + double clframetime, deltarealtime, oldrealtime; double wait; int pass1, pass2, pass3; @@ -591,20 +541,18 @@ void Host_Main(void) cl_timer = 0; sv_timer = 0; - framenewtime = Sys_DoubleTime(); + realtime = Sys_DoubleTime(); for (;;) { if (setjmp(host_abortframe)) continue; // something bad happened, or the server disconnected - frameoldtime = framenewtime; - framenewtime = Sys_DoubleTime(); - framedeltatime = framenewtime - frameoldtime; - realtime += framedeltatime; + oldrealtime = realtime; + realtime = Sys_DoubleTime(); - // accumulate the new frametime into the timers - cl_timer += framedeltatime; - sv_timer += framedeltatime; + deltarealtime = realtime - oldrealtime; + cl_timer += deltarealtime; + sv_timer += deltarealtime; if (slowmo.value < 0) Cvar_SetValue("slowmo", 0); @@ -613,8 +561,8 @@ void Host_Main(void) if (cl_maxfps.value < 1) Cvar_SetValue("cl_maxfps", 1); - // keep the random time dependent - if(!*sv_random_seed.string) + // keep the random time dependent, but not when playing demos/benchmarking + if(!*sv_random_seed.string && !cls.demoplayback) rand(); cl.islocalgame = NetConn_IsLocalGame(); @@ -701,7 +649,7 @@ void Host_Main(void) // 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 = 10; - aborttime = Sys_DoubleTime() + 0.1; + aborttime = realtime + 0.1; } else { @@ -710,7 +658,7 @@ void Host_Main(void) if (cls.state == ca_connected) { framelimit = 10; - aborttime = Sys_DoubleTime() + 0.1; + aborttime = realtime + 0.1; } } advancetime = min(advancetime, 0.1); @@ -734,17 +682,14 @@ void Host_Main(void) if (sv.frametime) SV_Physics(); - // send all messages to the clients - SV_SendClientMessages(); - - // clear the general datagram - SV_ClearDatagram(); - // if this server frame took too long, break out of the loop if (framelimit > 1 && Sys_DoubleTime() >= aborttime) break; } + // send all messages to the clients + SV_SendClientMessages(); + // end the server VM frame SV_VM_End(); @@ -777,7 +722,15 @@ void Host_Main(void) clframetime = cl.realframetime = 0.1; // apply slowmo scaling - clframetime *= slowmo.value; + clframetime *= cl.movevars_timescale; + // scale playback speed of demos by slowmo cvar + if (cls.demoplayback) + { + clframetime *= slowmo.value; + // if demo playback is paused, don't advance time at all + if (cls.demopaused) + clframetime = 0; + } // host_framerate overrides all else if (host_framerate.value) @@ -795,16 +748,17 @@ void Host_Main(void) // Collect input into cmd CL_Input(); + // check for new packets NetConn_ClientFrame(); - if (cls.state == ca_connected) - { - CL_ReadFromServer(); - // if running the server remotely, send intentions now after - // the incoming messages have been read - //if (!cl.islocalgame) - // CL_SendCmd(); - } + // read a new frame from a demo if needed + CL_ReadDemoMessage(); + + // now that packets have been read, send input to server + CL_SendMove(); + + // update client world (interpolate entities, create trails, etc) + CL_UpdateWorld(); // update video if (host_speeds.integer) @@ -820,10 +774,10 @@ void Host_Main(void) time2 = Sys_DoubleTime(); // update audio - if(csqc_usecsqclistener) + if(cl.csqc_usecsqclistener) { - S_Update(&csqc_listenermatrix); - csqc_usecsqclistener = false; + S_Update(&cl.csqc_listenermatrix); + cl.csqc_usecsqclistener = false; } else S_Update(&r_view.matrix); @@ -888,7 +842,10 @@ static void Host_Init (void) const char* os; // LordHavoc: quake never seeded the random number generator before... heh - srand(time(NULL)); + if (COM_CheckParm("-benchmark")) + srand(0); // predictable random sequence for -benchmark + else + srand(time(NULL)); // FIXME: this is evil, but possibly temporary // COMMANDLINEOPTION: Console: -developer enables warnings and other notices (RECOMMENDED for mod developers) @@ -1048,6 +1005,15 @@ static void Host_Init (void) Cbuf_Execute(); } +// COMMANDLINEOPTION: Client: -capturedemo captures a playdemo and quits + i = COM_CheckParm("-capturedemo"); + if (i && i + 1 < com_argc) + if (!sv.active && !cls.demoplayback && !cls.connect_trying) + { + Cbuf_AddText(va("playdemo %s\ncl_capturevideo 1\n", com_argv[i + 1])); + Cbuf_Execute(); + } + if (cls.state == ca_dedicated || COM_CheckParm("-listen")) if (!sv.active && !cls.demoplayback && !cls.connect_trying) { @@ -1087,6 +1053,11 @@ void Host_Shutdown(void) Con_Print("recursive shutdown\n"); return; } + if (setjmp(host_abortframe)) + { + Con_Print("aborted the quitting frame?!?\n"); + return; + } isdown = true; // be quiet while shutting down