X-Git-Url: http://git.xonotic.org/?a=blobdiff_plain;f=host.c;h=3cf4f493900412ecf165a4a1148e323a43bea777;hb=919633c14ce3da61012042b62a517b015d7ca761;hp=180bb66c4b298d17493f7f5d96b87004a0d61ccd;hpb=9cc276c2e36a6fc6cfafd8a0fb6df85e2f644c07;p=xonotic%2Fdarkplaces.git diff --git a/host.c b/host.c index 180bb66c..3cf4f493 100644 --- a/host.c +++ b/host.c @@ -122,6 +122,9 @@ void Host_Error (const char *error, ...) static qboolean hosterror = false; va_list argptr; + // turn off rcon redirect if it was active when the crash occurred + rcon_redirect = false; + va_start (argptr,error); dpvsnprintf (hosterrorstring1,sizeof(hosterrorstring1),error,argptr); va_end (argptr); @@ -141,13 +144,15 @@ void Host_Error (const char *error, ...) CL_Parse_DumpPacket(); + CL_Parse_ErrorCleanUp(); + //PR_Crash(); // print out where the crash happened, if it was caused by QC (and do a cleanup) PRVM_Crash(); - Host_ShutdownServer (false); + Host_ShutdownServer (); if (cls.state == ca_dedicated) Sys_Error ("Host_Error: %s",hosterrorstring2); // dedicated servers exit @@ -416,9 +421,9 @@ void SV_DropClient(qboolean crash) buf.data = bufdata; buf.maxsize = sizeof(bufdata); MSG_WriteByte(&buf, svc_disconnect); - NetConn_SendUnreliableMessage(host_client->netconnection, &buf); - NetConn_SendUnreliableMessage(host_client->netconnection, &buf); - NetConn_SendUnreliableMessage(host_client->netconnection, &buf); + NetConn_SendUnreliableMessage(host_client->netconnection, &buf, sv.protocol); + NetConn_SendUnreliableMessage(host_client->netconnection, &buf, sv.protocol); + NetConn_SendUnreliableMessage(host_client->netconnection, &buf, sv.protocol); } // break the net connection NetConn_Close(host_client->netconnection); @@ -489,11 +494,9 @@ Host_ShutdownServer This only happens at the end of a game, not between levels ================== */ -void Host_ShutdownServer(qboolean crash) +void Host_ShutdownServer(void) { - int i, count; - sizebuf_t buf; - unsigned char message[4]; + int i; Con_DPrintf("Host_ShutdownServer\n"); @@ -504,18 +507,10 @@ void Host_ShutdownServer(qboolean crash) NetConn_Heartbeat(2); // make sure all the clients know we're disconnecting - buf.data = message; - buf.maxsize = 4; - buf.cursize = 0; - MSG_WriteByte(&buf, svc_disconnect); - count = NetConn_SendToAll(&buf, 5); - if (count) - Con_Printf("Host_ShutdownServer: NetConn_SendToAll failed for %u clients\n", count); - SV_VM_Begin(); for (i = 0, host_client = svs.clients;i < svs.maxclients;i++, host_client++) if (host_client->active) - SV_DropClient(crash); // server shutdown + SV_DropClient(false); // server shutdown SV_VM_End(); NetConn_CloseServerPorts(); @@ -665,12 +660,12 @@ Host_ServerFrame */ void Host_ServerFrame (void) { - // never run more than 1 frame per call because multiple frames per call it - // does not handle overload gracefully, slowing down is better than a - // sudden significant drop in framerate (or worse, freezing until the - // problem goes away) - int framecount, framelimit = 1; - double advancetime; + // execute one or more server frames, with an upper limit on how much + // execution time to spend on server frames to avoid freezing the game if + // the server is overloaded, this execution time limit means the game will + // slow down if the server is taking too long. + int framecount, framelimit = 100; + double advancetime, aborttime; if (!sv.active) { sv.timer = 0; @@ -678,18 +673,22 @@ void Host_ServerFrame (void) } sv.timer += host_realframetime; - // run the world state // don't allow simulation to run too fast or too slow or logic glitches can occur + + // setup the VM frame + SV_VM_Begin(); + // stop running server frames if the wall time reaches this value + aborttime = Sys_DoubleTime() + 0.05; for (framecount = 0;framecount < framelimit && sv.timer > 0;framecount++) { - // setup the VM frame - SV_VM_Begin(); - - if (cl.islocalgame && !sv_fixedframeratesingleplayer.integer) + if (sys_ticrate.value <= 0) + advancetime = sv.timer; + else if (cl.islocalgame && !sv_fixedframeratesingleplayer.integer) advancetime = min(sv.timer, sys_ticrate.value); else advancetime = sys_ticrate.value; + advancetime = min(advancetime, 0.1); sv.timer -= advancetime; // only advance time if not paused @@ -700,12 +699,6 @@ void Host_ServerFrame (void) if (sv.paused || (cl.islocalgame && (key_dest != key_game || key_consoleactive))) sv.frametime = 0; - // set the time and clear the general datagram - SV_ClearDatagram(); - - // check for network packets to the server each world step incase they - // come in midframe (particularly if host is running really slow) - NetConn_ServerFrame(); // move things around and think unless paused if (sv.frametime) @@ -714,13 +707,19 @@ void Host_ServerFrame (void) // send all messages to the clients SV_SendClientMessages(); - // send an heartbeat if enough time has passed since the last one - NetConn_Heartbeat(0); + // clear the general datagram + SV_ClearDatagram(); - // end the server VM frame - SV_VM_End(); + // if this server frame took too long, break out of the loop + if (Sys_DoubleTime() >= aborttime) + break; } + // end the server VM frame + SV_VM_End(); + + // send an heartbeat if enough time has passed since the last one + NetConn_Heartbeat(0); // if we fell behind too many frames just don't worry about it if (sv.timer > 0) @@ -764,8 +763,8 @@ void _Host_Frame (float time) Cbuf_Execute(); // if running the server locally, make intentions now - if (cls.state == ca_connected && sv.active) - CL_SendCmd(); + //if (cl.islocalgame) + // CL_SendCmd(); //------------------- // @@ -773,6 +772,11 @@ void _Host_Frame (float time) // //------------------- + // receive server packets now, which might contain rcon commands, which + // may change level or other such things we don't want to have happen in + // the middle of Host_Frame + NetConn_ServerFrame(); + // check for commands typed to the host Host_GetConsoleCommands(); @@ -792,11 +796,11 @@ void _Host_Frame (float time) if (cls.state == ca_connected) { + CL_ReadFromServer(); // if running the server remotely, send intentions now after // the incoming messages have been read - if (!sv.active) - CL_SendCmd(); - CL_ReadFromServer(); + //if (!cl.islocalgame) + // CL_SendCmd(); } //ui_update(); @@ -943,6 +947,8 @@ void Host_Init (void) os = "OpenBSD"; #elif defined(MACOSX) os = "Mac OS X"; +#elif defined(__MORPHOS__) + os = "MorphOS"; #else os = "Unknown"; #endif @@ -1011,8 +1017,6 @@ void Host_Init (void) Cbuf_AddText("alias startmap_sp \"map nehstart\"\nalias startmap_dm \"map nehstart\"\nexec quake.rc\n"); else if (gamemode == GAME_TRANSFUSION) Cbuf_AddText("alias startmap_sp \"map e1m1\"\n""alias startmap_dm \"map bb1\"\nexec quake.rc\n"); - else if (gamemode == GAME_NEXUIZ) - Cbuf_AddText("alias startmap_sp \"map nexdm01\"\nalias startmap_dm \"map nexdm01\"\nexec quake.rc\n"); else if (gamemode == GAME_TEU) Cbuf_AddText("alias startmap_sp \"map start\"\nalias startmap_dm \"map start\"\nexec teu.rc\n"); else @@ -1029,9 +1033,11 @@ void Host_Init (void) // save console log up to this point to log_file if it was set by configs Log_Start(); + // put up the loading image so the user doesn't stare at a black screen... + SCR_BeginLoadingPlaque(); + // FIXME: put this into some neat design, but the menu should be allowed to crash // without crashing the whole game, so this should just be a short-time solution - Host_StartVideo(); // here comes the not so critical stuff if (setjmp(host_abortframe)) { @@ -1091,7 +1097,7 @@ void Host_Init (void) Con_DPrint("========Initialized=========\n"); - Host_StartVideo(); + //Host_StartVideo(); } @@ -1121,7 +1127,7 @@ void Host_Shutdown(void) CL_Disconnect(); // shut down local server if active - Host_ShutdownServer (false); + Host_ShutdownServer (); // Shutdown menu if(MR_Shutdown)