/* * ================== * SV_Frame * * ================== */ void SV_Frame(int msec) { time_before_game = time_after_game = 0; // if server is not active, do nothing if (!svs.initialized) { return; } svs.realtime += msec; // keep the random time dependent rand(); // check timeouts SV_CheckTimeouts(); // get packets from clients SV_ReadPackets(); // move autonomous things around if enough time has passed if (!sv_timedemo->value && (svs.realtime < sv.time)) { // never let the time get too far off if (sv.time - svs.realtime > 100) { if (sv_showclamp->value) { Com_Printf("sv lowclamp\n"); } svs.realtime = sv.time - 100; } NET_Sleep(sv.time - svs.realtime); return; } // update ping based on the last known frame from all clients SV_CalcPings(); // give the clients some timeslices SV_GiveMsec(); // let everything in the world think and move SV_RunGameFrame(); // send messages back to the clients that had packets read this frame SV_SendClientMessages(); // save the entire world state if recording a serverdemo SV_RecordDemoMessage(); // send a heartbeat to the master if needed Master_Heartbeat(); // clear teleport flags, etc for next frame SV_PrepWorldFrame(); }
/** * @sa Qcommon_Frame */ void SV_Frame (int now, void *data) { Com_ReadFromPipe(); /* change the gametype even if no server is running (e.g. the first time) */ if (sv_dedicated->integer && sv_gametype->modified) { Com_SetGameType(); sv_gametype->modified = false; } if (sv_dedicated->integer) { const char *s; do { s = Sys_ConsoleInput(); if (s) Cbuf_AddText(va("%s\n", s)); } while (s); } /* if server is not active, do nothing */ if (!svs.initialized) { #ifdef DEDICATED_ONLY Com_Printf("Starting next map from the mapcycle\n"); SV_NextMapcycle(); #endif return; } svs.realtime = now; /* keep the random time dependent */ rand(); SV_CheckSpawnSoldiers(); SV_CheckStartMatch(); SV_CheckTimeouts(); if (!sv_threads->integer) SV_RunGameFrame(); else /* signal the game frame thread to wake up */ SDL_CondSignal(svs.gameFrameCond); SV_LogHandleOutput(); /* next map in the cycle */ if (sv->endgame && sv_maxclients->integer > 1) SV_NextMapcycle(); /* send a heartbeat to the master if needed */ Master_Heartbeat(); SV_PingPlayers(); /* server is empty - so shutdown */ if (svs.abandon && svs.killserver) SV_Shutdown("Server disconnected.", false); }
/* ================== SV_Frame ================== */ void SV_Frame (float time) { static double start, end; start = Sys_DoubleTime (); svs.stats.idle += start - end; // keep the random time dependent rand (); // decide the simulation time realtime += time; sv.time += time; // check timeouts SV_CheckTimeouts (); // toggle the log buffer if full SV_CheckLog (); // move autonomous things around if enough time has passed SV_Physics (); // get packets SV_ReadPackets (); // check for commands typed to the host SV_GetConsoleCommands (); // process console commands Cbuf_Execute (); SV_CheckVars (); // send messages back to the clients that had packets read this frame SV_SendClientMessages (); // send a heartbeat to the master if needed Master_Heartbeat (); // collect timing statistics end = Sys_DoubleTime (); svs.stats.active += end-start; if (++svs.stats.count == STATFRAMES) { svs.stats.latched_active = svs.stats.active; svs.stats.latched_idle = svs.stats.idle; svs.stats.latched_packets = svs.stats.packets; svs.stats.active = 0; svs.stats.idle = 0; svs.stats.packets = 0; svs.stats.count = 0; } }
/* * SV_Frame */ void SV_Frame( int realmsec, int gamemsec ) { const unsigned int wrappingPoint = 0x70000000; time_before_game = time_after_game = 0; // if server is not active, do nothing if( !svs.initialized ) { SV_CheckDefaultMap(); return; } svs.realtime += realmsec; svs.gametime += gamemsec; // advance to next map if the server is running for too long (numbers taken from q3 src) if( svs.realtime > wrappingPoint || svs.gametime > wrappingPoint || sv.framenum >= wrappingPoint ) { Cbuf_AddText( "wait; vstr nextmap\n" ); SV_ShutdownGame( "Restarting server due to time wrapping", qtrue ); return; } // check timeouts SV_CheckTimeouts(); // get packets from clients SV_ReadPackets(); // let everything in the world think and move if( SV_RunGameFrame( gamemsec ) ) { // send messages back to the clients that had packets read this frame SV_SendClientMessages(); // write snap to server demo file SV_Demo_WriteSnap(); // run matchmaker stuff SV_CheckMatchUUID(); SV_MM_Frame(); // send a heartbeat to the master if needed SV_MasterHeartbeat(); // clear teleport flags, etc for next frame ge->ClearSnap(); } SV_CheckAutoUpdate(); }
/* ================== Host_ServerFrame ================== */ void Host_ServerFrame( void ) { // if server is not active, do nothing if( !svs.initialized ) return; svgame.globals->frametime = host.frametime; // check timeouts SV_CheckTimeouts (); // check clients timewindow SV_CheckCmdTimes (); // read packets from clients SV_ReadPackets (); // update ping based on the last known frame from all clients SV_CalcPings (); // refresh serverinfo on the client side SV_UpdateServerInfo (); // refresh physic movevars on the client side SV_UpdateMovevars ( false ); // let everything in the world think and move SV_RunGameFrame (); // send messages back to the clients that had packets read this frame SV_SendClientMessages (); // clear edict flags for next frame SV_PrepWorldFrame (); // send a heartbeat to the master if needed Master_Heartbeat (); }
/* ================== SV_Frame Player movement occurs as a result of packet events, which happen before SV_Frame is called ================== */ void SV_Frame( int msec ) { int frameMsec; int startTime; // the menu kills the server with this cvar if ( sv_killserver->integer ) { SV_Shutdown ("Server was killed"); Cvar_Set( "sv_killserver", "0" ); return; } if (!com_sv_running->integer) { if(com_dedicated->integer) { // Block indefinitely until something interesting happens // on STDIN. NET_Sleep(-1); } return; } // allow pause if only the local client is connected if ( SV_CheckPaused() ) { return; } // if it isn't time for the next frame, do nothing if ( sv_fps->integer < 1 ) { Cvar_Set( "sv_fps", "10" ); } frameMsec = 1000 / sv_fps->integer * com_timescale->value; // don't let it scale below 1ms if(frameMsec < 1) { Cvar_Set("timescale", va("%f", sv_fps->integer / 1000.0f)); frameMsec = 1; } sv.timeResidual += msec; if (!com_dedicated->integer) SV_BotFrame (sv.time + sv.timeResidual); if ( com_dedicated->integer && sv.timeResidual < frameMsec ) { // NET_Sleep will give the OS time slices until either get a packet // or time enough for a server frame has gone by NET_Sleep(frameMsec - sv.timeResidual); return; } // if time is about to hit the 32nd bit, kick all clients // and clear sv.time, rather // than checking for negative time wraparound everywhere. // 2giga-milliseconds = 23 days, so it won't be too often if ( svs.time > 0x70000000 ) { SV_Shutdown( "Restarting server due to time wrapping" ); Cbuf_AddText( va( "map %s\n", Cvar_VariableString( "mapname" ) ) ); return; } // this can happen considerably earlier when lots of clients play and the map doesn't change if ( svs.nextSnapshotEntities >= 0x7FFFFFFE - svs.numSnapshotEntities ) { SV_Shutdown( "Restarting server due to numSnapshotEntities wrapping" ); Cbuf_AddText( va( "map %s\n", Cvar_VariableString( "mapname" ) ) ); return; } if( sv.restartTime && sv.time >= sv.restartTime ) { sv.restartTime = 0; Cbuf_AddText( "map_restart 0\n" ); return; } // update infostrings if anything has been changed if ( cvar_modifiedFlags & CVAR_SERVERINFO ) { SV_SetConfigstring( CS_SERVERINFO, Cvar_InfoString( CVAR_SERVERINFO ) ); cvar_modifiedFlags &= ~CVAR_SERVERINFO; } if ( cvar_modifiedFlags & CVAR_SYSTEMINFO ) { SV_SetConfigstring( CS_SYSTEMINFO, Cvar_InfoString_Big( CVAR_SYSTEMINFO ) ); cvar_modifiedFlags &= ~CVAR_SYSTEMINFO; } if ( com_speeds->integer ) { startTime = Sys_Milliseconds (); } else { startTime = 0; // quite a compiler warning } // update ping based on the all received frames SV_CalcPings(); if (com_dedicated->integer) SV_BotFrame (sv.time); // run the game simulation in chunks while ( sv.timeResidual >= frameMsec ) { sv.timeResidual -= frameMsec; svs.time += frameMsec; sv.time += frameMsec; // let everything in the world think and move VM_Call (gvm, GAME_RUN_FRAME, sv.time); } if ( com_speeds->integer ) { time_game = Sys_Milliseconds () - startTime; } // check timeouts SV_CheckTimeouts(); // check user info buffer thingy SV_CheckClientUserinfoTimer(); // send messages back to the clients SV_SendClientMessages(); // send a heartbeat to the master if needed SV_MasterHeartbeat(); }
void SV_Frame( int msec,float fractionMsec ) { int frameMsec; int startTime=0; // the menu kills the server with this cvar if ( sv_killserver->integer ) { SV_Shutdown ("Server was killed.\n"); Cvar_Set( "sv_killserver", "0" ); return; } if ( !com_sv_running->integer ) { return; } extern void SE_CheckForLanguageUpdates(void); SE_CheckForLanguageUpdates(); // will fast-return else load different language if menu changed it // allow pause if only the local client is connected if ( SV_CheckPaused() ) { return; } // go ahead and let time slip if the server really hitched badly if ( msec > 1000 ) { Com_DPrintf( "SV_Frame: Truncating msec of %i to 1000\n", msec ); msec = 1000; } // if it isn't time for the next frame, do nothing if ( sv_fps->integer < 1 ) { Cvar_Set( "sv_fps", "10" ); } frameMsec = 1000 / sv_fps->integer ; sv.timeResidual += msec; sv.timeResidualFraction+=fractionMsec; if (sv.timeResidualFraction>=1.0f) { sv.timeResidualFraction-=1.0f; if (cl_newClock&&cl_newClock->integer) { sv.timeResidual++; } } if ( sv.timeResidual < frameMsec ) { return; } // if time is about to hit the 32nd bit, restart the // level, which will force the time back to zero, rather // than checking for negative time wraparound everywhere. // 2giga-milliseconds = 23 days, so it won't be too often if ( sv.time > 0x70000000 ) { SV_Shutdown( "Restarting server due to time wrapping" ); Com_Printf("You win. if you can play this long and not die, you deserve to win.\n"); return; } // update infostrings if anything has been changed if ( cvar_modifiedFlags & CVAR_SERVERINFO ) { SV_SetConfigstring( CS_SERVERINFO, Cvar_InfoString( CVAR_SERVERINFO ) ); cvar_modifiedFlags &= ~CVAR_SERVERINFO; } if ( cvar_modifiedFlags & CVAR_SYSTEMINFO ) { SV_SetConfigstring( CS_SYSTEMINFO, Cvar_InfoString( CVAR_SYSTEMINFO ) ); cvar_modifiedFlags &= ~CVAR_SYSTEMINFO; } if ( com_speeds->integer ) { startTime = Sys_Milliseconds (); } // SV_BotFrame( sv.time ); // run the game simulation in chunks while ( sv.timeResidual >= frameMsec ) { sv.timeResidual -= frameMsec; sv.time += frameMsec; G2API_SetTime(sv.time,G2T_SV_TIME); // let everything in the world think and move ge->RunFrame( sv.time ); } if ( com_speeds->integer ) { time_game = Sys_Milliseconds () - startTime; } SG_TestSave(); // returns immediately if not active, used for fake-save-every-cycle to test (mainly) Icarus disk code // check timeouts SV_CheckTimeouts (); // update ping based on the last known frame from all clients SV_CalcPings (); // send messages back to the clients SV_SendClientMessages (); }
/* ================== SV_Frame Player movement occurs as a result of packet events, which happen before SV_Frame is called ================== */ void SV_Frame( int msec ) { int frameMsec; int startTime; #if !defined RTCW_SP char mapname[MAX_QPATH]; #endif // RTCW_XX #if defined RTCW_ET int frameStartTime = 0, frameEndTime; #endif // RTCW_XX // the menu kills the server with this cvar if ( sv_killserver->integer ) { SV_Shutdown( "Server was killed.\n" ); Cvar_Set( "sv_killserver", "0" ); return; } if ( !com_sv_running->integer ) { return; } // allow pause if only the local client is connected if ( SV_CheckPaused() ) { return; } #if defined RTCW_ET if ( com_dedicated->integer ) { frameStartTime = Sys_Milliseconds(); } #endif // RTCW_XX // if it isn't time for the next frame, do nothing if ( sv_fps->integer < 1 ) { Cvar_Set( "sv_fps", "10" ); } frameMsec = 1000 / sv_fps->integer ; sv.timeResidual += msec; if ( !com_dedicated->integer ) { SV_BotFrame( svs.time + sv.timeResidual ); } if ( com_dedicated->integer && sv.timeResidual < frameMsec ) { // NET_Sleep will give the OS time slices until either get a packet // or time enough for a server frame has gone by NET_Sleep( frameMsec - sv.timeResidual ); return; } // if time is about to hit the 32nd bit, kick all clients // and clear sv.time, rather // than checking for negative time wraparound everywhere. // 2giga-milliseconds = 23 days, so it won't be too often if ( svs.time > 0x70000000 ) { #if defined RTCW_SP SV_Shutdown( "Restarting server due to time wrapping" ); Cbuf_AddText( "vstr nextmap\n" ); #else Q_strncpyz( mapname, sv_mapname->string, MAX_QPATH ); SV_Shutdown( "Restarting server due to time wrapping" ); // TTimo // show_bug.cgi?id=388 // there won't be a map_restart if you have shut down the server // since it doesn't restart a non-running server // instead, re-run the current map Cbuf_AddText( va( "map %s\n", mapname ) ); #endif // RTCW_XX return; } // this can happen considerably earlier when lots of clients play and the map doesn't change if ( svs.nextSnapshotEntities >= 0x7FFFFFFE - svs.numSnapshotEntities ) { #if defined RTCW_SP SV_Shutdown( "Restarting server due to numSnapshotEntities wrapping" ); Cbuf_AddText( "vstr nextmap\n" ); #else Q_strncpyz( mapname, sv_mapname->string, MAX_QPATH ); SV_Shutdown( "Restarting server due to numSnapshotEntities wrapping" ); // TTimo see above Cbuf_AddText( va( "map %s\n", mapname ) ); #endif // RTCW_XX return; } if ( sv.restartTime && svs.time >= sv.restartTime ) { sv.restartTime = 0; Cbuf_AddText( "map_restart 0\n" ); return; } // update infostrings if anything has been changed if ( cvar_modifiedFlags & CVAR_SERVERINFO ) { #if !defined RTCW_ET SV_SetConfigstring( CS_SERVERINFO, Cvar_InfoString( CVAR_SERVERINFO ) ); #else SV_SetConfigstring( CS_SERVERINFO, Cvar_InfoString( CVAR_SERVERINFO | CVAR_SERVERINFO_NOUPDATE ) ); #endif // RTCW_XX cvar_modifiedFlags &= ~CVAR_SERVERINFO; } #if defined RTCW_ET if ( cvar_modifiedFlags & CVAR_SERVERINFO_NOUPDATE ) { SV_SetConfigstringNoUpdate( CS_SERVERINFO, Cvar_InfoString( CVAR_SERVERINFO | CVAR_SERVERINFO_NOUPDATE ) ); cvar_modifiedFlags &= ~CVAR_SERVERINFO_NOUPDATE; } #endif // RTCW_XX if ( cvar_modifiedFlags & CVAR_SYSTEMINFO ) { SV_SetConfigstring( CS_SYSTEMINFO, Cvar_InfoString_Big( CVAR_SYSTEMINFO ) ); cvar_modifiedFlags &= ~CVAR_SYSTEMINFO; } #if !defined RTCW_SP // NERVE - SMF if ( cvar_modifiedFlags & CVAR_WOLFINFO ) { SV_SetConfigstring( CS_WOLFINFO, Cvar_InfoString( CVAR_WOLFINFO ) ); cvar_modifiedFlags &= ~CVAR_WOLFINFO; } #endif // RTCW_XX if ( com_speeds->integer ) { startTime = Sys_Milliseconds(); } else { startTime = 0; // quite a compiler warning } // update ping based on the all received frames SV_CalcPings(); if ( com_dedicated->integer ) { SV_BotFrame( svs.time ); } // run the game simulation in chunks while ( sv.timeResidual >= frameMsec ) { sv.timeResidual -= frameMsec; svs.time += frameMsec; // let everything in the world think and move #if !defined RTCW_MP || (defined RTCW_MP && !UPDATE_SERVER) VM_Call( gvm, GAME_RUN_FRAME, svs.time ); #endif // RTCW_XX } if ( com_speeds->integer ) { time_game = Sys_Milliseconds() - startTime; } // check timeouts SV_CheckTimeouts(); // send messages back to the clients SV_SendClientMessages(); // send a heartbeat to the master if needed #if defined RTCW_SP SV_MasterHeartbeat(); #else SV_MasterHeartbeat( HEARTBEAT_GAME ); #endif // RTCW_XX #if defined RTCW_ET if ( com_dedicated->integer ) { frameEndTime = Sys_Milliseconds(); svs.totalFrameTime += ( frameEndTime - frameStartTime ); svs.currentFrameIndex++; //if( svs.currentFrameIndex % 50 == 0 ) // Com_Printf( "currentFrameIndex: %i\n", svs.currentFrameIndex ); if ( svs.currentFrameIndex == SERVER_PERFORMANCECOUNTER_FRAMES ) { int averageFrameTime; averageFrameTime = svs.totalFrameTime / SERVER_PERFORMANCECOUNTER_FRAMES; svs.sampleTimes[svs.currentSampleIndex % SERVER_PERFORMANCECOUNTER_SAMPLES] = averageFrameTime; svs.currentSampleIndex++; if ( svs.currentSampleIndex > SERVER_PERFORMANCECOUNTER_SAMPLES ) { int totalTime, i; totalTime = 0; for ( i = 0; i < SERVER_PERFORMANCECOUNTER_SAMPLES; i++ ) { totalTime += svs.sampleTimes[i]; } if ( !totalTime ) { totalTime = 1; } averageFrameTime = totalTime / SERVER_PERFORMANCECOUNTER_SAMPLES; svs.serverLoad = ( averageFrameTime / (float)frameMsec ) * 100; } //Com_Printf( "serverload: %i (%i/%i)\n", svs.serverLoad, averageFrameTime, frameMsec ); svs.totalFrameTime = 0; svs.currentFrameIndex = 0; } } else { svs.serverLoad = -1; } #endif // RTCW_XX }
/* ================== SV_Frame Player movement occurs as a result of packet events, which happen before SV_Frame is called ================== */ void SV_Frame( int msec ) { int frameMsec; int startTime; char mapname[MAX_QPATH]; // the menu kills the server with this cvar if ( sv_killserver->integer ) { SV_Shutdown( "Server was killed.\n" ); Cvar_Set( "sv_killserver", "0" ); return; } if ( !com_sv_running->integer ) { return; } // allow pause if only the local client is connected if ( SV_CheckPaused() ) { return; } // if it isn't time for the next frame, do nothing if ( sv_fps->integer < 1 ) { Cvar_Set( "sv_fps", "10" ); } frameMsec = 1000 / sv_fps->integer ; sv.timeResidual += msec; if ( !com_dedicated->integer ) { SV_BotFrame( svs.time + sv.timeResidual ); } if ( com_dedicated->integer && sv.timeResidual < frameMsec ) { // NET_Sleep will give the OS time slices until either get a packet // or time enough for a server frame has gone by NET_Sleep( frameMsec - sv.timeResidual ); return; } // if time is about to hit the 32nd bit, kick all clients // and clear sv.time, rather // than checking for negative time wraparound everywhere. // 2giga-milliseconds = 23 days, so it won't be too often if ( svs.time > 0x70000000 ) { Q_strncpyz( mapname, sv_mapname->string, MAX_QPATH ); SV_Shutdown( "Restarting server due to time wrapping" ); // TTimo // show_bug.cgi?id=388 // there won't be a map_restart if you have shut down the server // since it doesn't restart a non-running server // instead, re-run the current map Cbuf_AddText( va( "map %s\n", mapname ) ); return; } // this can happen considerably earlier when lots of clients play and the map doesn't change if ( svs.nextSnapshotEntities >= 0x7FFFFFFE - svs.numSnapshotEntities ) { Q_strncpyz( mapname, sv_mapname->string, MAX_QPATH ); SV_Shutdown( "Restarting server due to numSnapshotEntities wrapping" ); // TTimo see above Cbuf_AddText( va( "map %s\n", mapname ) ); return; } if ( sv.restartTime && svs.time >= sv.restartTime ) { sv.restartTime = 0; Cbuf_AddText( "map_restart 0\n" ); return; } // update infostrings if anything has been changed if ( cvar_modifiedFlags & CVAR_SERVERINFO ) { SV_SetConfigstring( CS_SERVERINFO, Cvar_InfoString( CVAR_SERVERINFO ) ); cvar_modifiedFlags &= ~CVAR_SERVERINFO; } if ( cvar_modifiedFlags & CVAR_SYSTEMINFO ) { SV_SetConfigstring( CS_SYSTEMINFO, Cvar_InfoString_Big( CVAR_SYSTEMINFO ) ); cvar_modifiedFlags &= ~CVAR_SYSTEMINFO; } // NERVE - SMF if ( cvar_modifiedFlags & CVAR_WOLFINFO ) { SV_SetConfigstring( CS_WOLFINFO, Cvar_InfoString( CVAR_WOLFINFO ) ); cvar_modifiedFlags &= ~CVAR_WOLFINFO; } if ( com_speeds->integer ) { startTime = Sys_Milliseconds(); } else { startTime = 0; // quite a compiler warning } // update ping based on the all received frames SV_CalcPings(); if ( com_dedicated->integer ) { SV_BotFrame( svs.time ); } // run the game simulation in chunks while ( sv.timeResidual >= frameMsec ) { sv.timeResidual -= frameMsec; svs.time += frameMsec; // let everything in the world think and move #ifndef UPDATE_SERVER VM_Call( gvm, GAME_RUN_FRAME, svs.time ); #endif } if ( com_speeds->integer ) { time_game = Sys_Milliseconds() - startTime; } // check timeouts SV_CheckTimeouts(); // send messages back to the clients SV_SendClientMessages(); // send a heartbeat to the master if needed SV_MasterHeartbeat( HEARTBEAT_GAME ); }
/** * @sa Qcommon_Frame */ void SV_Frame (int now, void* data) { Com_ReadFromPipe(); /* change the gametype even if no server is running (e.g. the first time) */ if (sv_dedicated->integer && sv_gametype->modified) { Com_SetGameType(); sv_gametype->modified = false; } if (sv_dedicated->integer) { const char* s; do { s = Sys_ConsoleInput(); if (s) Cbuf_AddText("%s\n", s); } while (s); } /* if server is not active, do nothing */ if (!svs.initialized) { #ifdef DEDICATED_ONLY Com_Printf("Starting next map from the mapcycle\n"); SV_NextMapcycle(); #endif return; } svs.realtime = now; /* if time is about to hit the 32nd bit, kick all clients * and clear sv.time, rather * than checking for negative time wraparound everywhere. * 2giga-milliseconds = 23 days, so it won't be too often */ if (svs.realtime > 0x70000000) { SV_Map(true, sv->name, sv->assembly); return; } /* keep the random time dependent */ rand(); SV_CheckSpawnSoldiers(); SV_CheckStartMatch(); SV_CheckTimeouts(); if (!sv_threads->integer) SV_RunGameFrame(); else /* signal the game frame thread to wake up */ SDL_CondSignal(svs.gameFrameCond); SV_LogHandleOutput(); /* next map in the cycle */ if (sv->endgame && sv_maxclients->integer > 1) SV_NextMapcycle(); /* send a heartbeat to the master if needed */ Master_Heartbeat(); SV_PingPlayers(); /* server is empty - so shutdown */ if (svs.abandon && svs.killserver) SV_Shutdown("Server disconnected.", false); }
void SV_Frame(float msec) { guard(SV_Frame); time_before_game = time_after_game = 0; // if server is not active, do nothing if (!svs.initialized) return; // SV_DrawTextLeft(va("time: %10d rf: %10.5f d: %10.4f ri:%10d", sv.time, svs.realtimef, msec, svs.realtime));//!! svs.realtimef += msec; svs.realtime = appFloor(svs.realtimef); if (!sv.attractloop) { // check timeouts SV_CheckTimeouts(); } // get packets from clients SV_ReadPackets(); if (sv.state == ss_dead) return; // server was killed from one of packet (e.g. "rcon killserver") int frameTime = 100; // (sv_fps->integer > 10) ? (1000 / sv_fps->integer) : 100; // move autonomous things around if enough time has passed if (svs.realtime < sv.time) { // never let the time get too far off if (sv.time - svs.realtime > frameTime) { if (sv_showclamp->integer) appPrintf("sv lowclamp s:%d -- r:%d -> %d\n", sv.time, svs.realtime, sv.time - frameTime); svs.realtime = sv.time - frameTime; svs.realtimef = svs.realtime; } return; } SV_ClearTexts(); if (!sv.attractloop) { // update ping based on the last known frame from all clients SV_CalcPings(); // give the clients some timeslices SV_GiveMsec(); } // let everything in the world think and move /*-------- SV_RunGameFrame() ---------------*/ // we always need to bump framenum, even if we // don't run the world, otherwise the delta // compression can get confused when a client // has the "current" frame sv.framenum++; sv.time += frameTime; // = sv.framenum*100; ?? // don't run if paused if (!sv_paused->integer || sv_maxclients->integer > 1) { time_before_game = appCycles(); guardGame(ge.RunFrame); ge->RunFrame(); unguardGame; // never get more than one tic behind if (sv.time < svs.realtime) { if (sv_showclamp->integer) appPrintf("sv highclamp s:%d r:%d -> %d\n", sv.time, svs.realtime, sv.time); svs.realtime = sv.time; svs.realtimef = sv.time; } time_after_game = appCycles(); } // if extended protocol used, recalculate footstep sounds, mdx/mdl/md3 frames etc. if (sv_extProtocol->integer && !sv.attractloop) SV_PostprocessFrame(); // send messages back to the clients that had packets read this frame SV_SendClientMessages(); // save the entire world state if recording a serverdemo SV_RecordDemoMessage(); // send a heartbeat to the master if needed Master_Heartbeat(); // clear teleport flags, etc for next frame SV_PrepWorldFrame(); unguard; }