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);
PRVM_Crash();
- Host_ShutdownServer (false);
+ Host_ShutdownServer ();
if (cls.state == ca_dedicated)
Sys_Error ("Host_Error: %s",hosterrorstring2); // dedicated servers exit
*/
void SV_ClientPrint(const char *msg)
{
- MSG_WriteByte(&host_client->message, svc_print);
- MSG_WriteString(&host_client->message, msg);
+ if (host_client->netconnection)
+ {
+ MSG_WriteByte(&host_client->netconnection->message, svc_print);
+ MSG_WriteString(&host_client->netconnection->message, msg);
+ }
}
/*
for (i = 0, client = svs.clients;i < svs.maxclients;i++, client++)
{
- if (client->spawned)
+ if (client->spawned && client->netconnection)
{
- MSG_WriteByte(&client->message, svc_print);
- MSG_WriteString(&client->message, msg);
+ MSG_WriteByte(&client->netconnection->message, svc_print);
+ MSG_WriteString(&client->netconnection->message, msg);
}
}
va_list argptr;
char string[MAX_INPUTLINE];
+ if (!host_client->netconnection)
+ return;
+
va_start(argptr,fmt);
dpvsnprintf(string, sizeof(string), fmt, argptr);
va_end(argptr);
- MSG_WriteByte(&host_client->message, svc_stufftext);
- MSG_WriteString(&host_client->message, string);
+ MSG_WriteByte(&host_client->netconnection->message, svc_stufftext);
+ MSG_WriteString(&host_client->netconnection->message, string);
}
/*
if (!crash)
{
// LordHavoc: no opportunity for resending, so use unreliable 3 times
- MSG_WriteByte(&host_client->message, svc_disconnect);
- NetConn_SendUnreliableMessage(host_client->netconnection, &host_client->message);
- NetConn_SendUnreliableMessage(host_client->netconnection, &host_client->message);
- NetConn_SendUnreliableMessage(host_client->netconnection, &host_client->message);
+ unsigned char bufdata[8];
+ sizebuf_t buf;
+ memset(&buf, 0, sizeof(buf));
+ 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);
}
// break the net connection
NetConn_Close(host_client->netconnection);
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");
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();
*/
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;
}
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
// 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)
SV_Physics();
// send all messages to the clients
SV_SendClientMessages();
- // send an heartbeat if enough time has passed since the last one
- NetConn_Heartbeat(0);
-
- // 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)
Cbuf_Execute();
// if running the server locally, make intentions now
- if (cls.state == ca_connected && sv.active)
- CL_SendCmd();
+ //if (cl.islocalgame)
+ // CL_SendCmd();
//-------------------
//
//
//-------------------
+ // 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();
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();
CL_Disconnect();
// shut down local server if active
- Host_ShutdownServer (false);
+ Host_ShutdownServer ();
// Shutdown menu
if(MR_Shutdown)