/* ================ SV_SpawnServer Change the server to a new map, taking all connected clients along with it. ================ */ void SV_SpawnServer( cm_t *cm, const char *server, const char *spawnpoint ) { int i; client_t *client; #if USE_CLIENT SCR_BeginLoadingPlaque(); // for local system #endif Com_Printf( "------- Server Initialization -------\n" ); Com_Printf( "SpawnServer: %s\n", server ); // everyone needs to reconnect FOR_EACH_CLIENT( client ) { SV_ClientReset( client ); } SV_BroadcastCommand( "changing map=%s\n", server ); SV_SendClientMessages(); SV_SendAsyncPackets(); // free current level CM_FreeMap( &sv.cm ); SV_FreeFile( sv.entitystring ); // wipe the entire per-level structure memset( &sv, 0, sizeof( sv ) ); sv.spawncount = ( rand() | ( rand() << 16 ) ) ^ Sys_Milliseconds(); sv.spawncount &= 0x7FFFFFFF; // set legacy spawncounts FOR_EACH_CLIENT( client ) { client->spawncount = sv.spawncount; } // reset entity counter svs.next_entity = 0; #if USE_FPS // set framerate parameters set_frame_time(); #endif // save name for levels that don't set message Q_strlcpy( sv.configstrings[CS_NAME], server, MAX_QPATH ); Q_strlcpy( sv.name, server, sizeof( sv.name ) ); if( Cvar_VariableInteger( "deathmatch" ) ) { sprintf( sv.configstrings[CS_AIRACCEL], "%d", sv_airaccelerate->integer ); } else { strcpy( sv.configstrings[CS_AIRACCEL], "0" ); } #if !USE_CLIENT resolve_masters(); #endif override_entity_string( server ); sv.cm = *cm; sprintf( sv.configstrings[CS_MAPCHECKSUM], "%d", ( int )cm->cache->checksum ); // set inline model names Q_concat( sv.configstrings[CS_MODELS + 1], MAX_QPATH, "maps/", server, ".bsp", NULL ); for( i = 1; i < cm->cache->nummodels; i++ ) { sprintf( sv.configstrings[ CS_MODELS + 1 + i ], "*%d", i ); } // // clear physics interaction links // SV_ClearWorld(); // // spawn the rest of the entities on the map // // precache and static commands can be issued during // map initialization sv.state = ss_loading; X86_PUSH_FPCW; X86_SINGLE_FPCW; // load and spawn all other entities ge->SpawnEntities ( sv.name, sv.entitystring ? sv.entitystring : cm->cache->entitystring, spawnpoint ); // run two frames to allow everything to settle ge->RunFrame (); sv.framenum++; ge->RunFrame (); sv.framenum++; X86_POP_FPCW; // make sure maxclients string is correct sprintf( sv.configstrings[CS_MAXCLIENTS], "%d", sv_maxclients->integer ); // all precaches are complete sv.state = ss_game; #if USE_MVD_SERVER // respawn dummy MVD client, set base states, etc SV_MvdMapChanged(); #endif // set serverinfo variable SV_InfoSet( "mapname", sv.name ); SV_InfoSet( "port", net_port->string ); Cvar_SetInteger( sv_running, ss_game, FROM_CODE ); Cvar_Set( "sv_paused", "0" ); Cvar_Set( "timedemo", "0" ); EXEC_TRIGGER( sv_changemapcmd ); #if USE_SYSCON SV_SetConsoleTitle(); #endif SV_BroadcastCommand( "reconnect\n" ); Com_Printf ("-------------------------------------\n"); }
/* ============== SV_InitGame A brand new game has been started. If mvd_spawn is non-zero, load the built-in MVD game module. ============== */ void SV_InitGame( unsigned mvd_spawn ) { int i, entnum; edict_t *ent; client_t *client; if( svs.initialized ) { // cause any connected clients to reconnect SV_Shutdown( "Server restarted\n", ERR_RECONNECT | mvd_spawn ); } else { #if USE_CLIENT // make sure the client is down CL_Disconnect( ERR_RECONNECT ); SCR_BeginLoadingPlaque(); #endif CM_FreeMap( &sv.cm ); SV_FreeFile( sv.entitystring ); memset( &sv, 0, sizeof( sv ) ); #if USE_FPS // set up default frametime for main loop sv.frametime = BASE_FRAMETIME; #endif } // get any latched variable changes (maxclients, etc) Cvar_GetLatchedVars (); #if !USE_CLIENT Cvar_Reset( sv_recycle ); #endif if( mvd_spawn ) { Cvar_Set( "deathmatch", "1" ); Cvar_Set( "coop", "0" ); } else { if( Cvar_VariableInteger( "coop" ) && Cvar_VariableInteger( "deathmatch" ) ) { Com_Printf( "Deathmatch and Coop both set, disabling Coop\n" ); Cvar_Set( "coop", "0" ); } // dedicated servers can't be single player and are usually DM // so unless they explicity set coop, force it to deathmatch if( Com_IsDedicated() ) { if( !Cvar_VariableInteger( "coop" ) ) Cvar_Set( "deathmatch", "1" ); } } // init clients if( Cvar_VariableInteger( "deathmatch" ) ) { if( sv_maxclients->integer <= 1 ) { Cvar_SetInteger( sv_maxclients, 8, FROM_CODE ); } else if( sv_maxclients->integer > CLIENTNUM_RESERVED ) { Cvar_SetInteger( sv_maxclients, CLIENTNUM_RESERVED, FROM_CODE ); } } else if( Cvar_VariableInteger( "coop" ) ) { if( sv_maxclients->integer <= 1 || sv_maxclients->integer > 4 ) Cvar_Set( "maxclients", "4" ); } else { // non-deathmatch, non-coop is one player Cvar_FullSet( "maxclients", "1", CVAR_SERVERINFO|CVAR_LATCH, FROM_CODE ); } // enable networking if( sv_maxclients->integer > 1 ) { NET_Config( NET_SERVER ); } svs.client_pool = SV_Mallocz( sizeof( client_t ) * sv_maxclients->integer ); svs.num_entities = sv_maxclients->integer * UPDATE_BACKUP * MAX_PACKET_ENTITIES; svs.entities = SV_Mallocz( sizeof( entity_state_t ) * svs.num_entities ); #if USE_MVD_SERVER // initialize MVD server if( !mvd_spawn ) { SV_MvdInit(); } #endif Cvar_ClampInteger( sv_reserved_slots, 0, sv_maxclients->integer - 1 ); #if USE_ZLIB svs.z.zalloc = SV_Zalloc; svs.z.zfree = SV_Zfree; if( deflateInit2( &svs.z, Z_DEFAULT_COMPRESSION, Z_DEFLATED, -MAX_WBITS, 9, Z_DEFAULT_STRATEGY ) != Z_OK ) { Com_Error( ERR_FATAL, "%s: deflateInit2() failed", __func__ ); } #endif // init game #if USE_MVD_CLIENT if( mvd_spawn ) { if( ge ) { SV_ShutdownGameProgs(); } ge = &mvd_ge; ge->Init(); } else #endif SV_InitGameProgs(); // send heartbeat very soon svs.last_heartbeat = -(HEARTBEAT_SECONDS-5)*1000; for( i = 0; i < sv_maxclients->integer; i++ ) { client = svs.client_pool + i; entnum = i + 1; ent = EDICT_NUM( entnum ); ent->s.number = entnum; client->edict = ent; client->number = i; } #if USE_AC_SERVER AC_Connect( mvd_spawn ); #endif svs.initialized = qtrue; }
static void abort_func(void *arg) { CM_FreeMap(arg); }