/* ================== 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_InitGame A brand new game has been started ============== */ void SV_InitGame( void ) { edict_t *ent; int i; if( svs.initialized ) { // cause any connected clients to reconnect Q_strncpy( host.finalmsg, "Server restarted", MAX_STRING ); SV_Shutdown( true ); } else { // init game after host error if( !svgame.hInstance ) { if( !SV_LoadProgs( GI->game_dll )) { MsgDev( D_ERROR, "SV_InitGame: can't initialize %s\n", GI->game_dll ); return; // can't load } MsgDev( D_INFO, "Server loaded\n" ); } // make sure the client is down CL_Drop(); } // now apply latched commands Cmd_ExecuteString( "latch\n", src_command ); if( Cvar_VariableValue( "coop" ) && Cvar_VariableValue ( "deathmatch" ) && Cvar_VariableValue( "teamplay" )) { MsgDev( D_WARN, "Deathmatch, Teamplay and Coop set, defaulting to Deathmatch\n"); Cvar_FullSet( "coop", "0", CVAR_LATCH ); Cvar_FullSet( "teamplay", "0", CVAR_LATCH ); } // dedicated servers are can't be single player and are usually DM // so unless they explicity set coop, force it to deathmatch if( host.type == HOST_DEDICATED ) { if( !Cvar_VariableValue( "coop" ) && !Cvar_VariableValue( "teamplay" )) Cvar_FullSet( "deathmatch", "1", CVAR_LATCH ); } // init clients if( Cvar_VariableValue( "deathmatch" ) || Cvar_VariableValue( "teamplay" )) { if( sv_maxclients->integer <= 1 ) Cvar_FullSet( "maxplayers", "8", CVAR_LATCH ); else if( sv_maxclients->integer > MAX_CLIENTS ) Cvar_FullSet( "maxplayers", "32", CVAR_LATCH ); } else if( Cvar_VariableValue( "coop" )) { if( sv_maxclients->integer <= 1 || sv_maxclients->integer > 4 ) Cvar_FullSet( "maxplayers", "4", CVAR_LATCH ); } else { // non-deathmatch, non-coop is one player Cvar_FullSet( "maxplayers", "1", CVAR_LATCH ); } svgame.globals->maxClients = sv_maxclients->integer; SV_UPDATE_BACKUP = ( svgame.globals->maxClients == 1 ) ? SINGLEPLAYER_BACKUP : MULTIPLAYER_BACKUP; svs.clients = Z_Malloc( sizeof( sv_client_t ) * sv_maxclients->integer ); svs.num_client_entities = sv_maxclients->integer * SV_UPDATE_BACKUP * 64; svs.packet_entities = Z_Malloc( sizeof( entity_state_t ) * svs.num_client_entities ); svs.baselines = Z_Malloc( sizeof( entity_state_t ) * GI->max_edicts ); // client frames will be allocated in SV_DirectConnect // init network stuff NET_Config(( sv_maxclients->integer > 1 )); // copy gamemode into svgame.globals svgame.globals->deathmatch = Cvar_VariableInteger( "deathmatch" ); svgame.globals->teamplay = Cvar_VariableInteger( "teamplay" ); svgame.globals->coop = Cvar_VariableInteger( "coop" ); // heartbeats will always be sent to the id master svs.last_heartbeat = MAX_HEARTBEAT; // send immediately // set client fields on player ents for( i = 0; i < svgame.globals->maxClients; i++ ) { // setup all the clients ent = EDICT_NUM( i + 1 ); SV_InitEdict( ent ); svs.clients[i].edict = ent; } // get actual movevars SV_UpdateMovevars( true ); svgame.numEntities = svgame.globals->maxClients + 1; // clients + world svs.initialized = true; }