Beispiel #1
0
/*
 * ================
 * SV_Shutdown
 *
 * Called when each game quits,
 * before Sys_Quit or Sys_Error
 * ================
 */
void SV_Shutdown(char *finalmsg, qboolean reconnect)
{
    if (svs.clients)
    {
        SV_FinalMessage(finalmsg, reconnect);
    }

    Master_Shutdown();
    SV_ShutdownGameProgs();

    // free current level
    if (sv.demofile)
    {
        FS_FCloseFile(sv.demofile);
    }
    memset(&sv, 0, sizeof(sv));
    Com_SetServerState(sv.state);

    // free server static data
    if (svs.clients)
    {
        Z_Free(svs.clients);
    }
    if (svs.client_entities)
    {
        Z_Free(svs.client_entities);
    }
    if (svs.demofile)
    {
        fclose(svs.demofile);
    }
    memset(&svs, 0, sizeof(svs));
}
Beispiel #2
0
/**
 * @brief Called when either the entire server is being killed, or it is changing to a different game directory.
 * @sa G_Shutdown
 * @sa SV_InitGameProgs
 */
void SV_ShutdownGameProgs (void)
{
	uint32_t size;

	if (!svs.ge)
		return;

	Com_SetServerState(ss_game_shutdown);

	if (svs.gameThread) {
		Com_Printf("Shutdown the game thread\n");
		SDL_CondSignal(svs.gameFrameCond);
		SDL_WaitThread(svs.gameThread, NULL);
		SDL_DestroyCond(svs.gameFrameCond);
		svs.gameFrameCond = NULL;
		svs.gameThread = NULL;
	}

	svs.ge->Shutdown();

	size = Mem_PoolSize(sv->gameSysPool);
	if (size > 0) {
		Com_Printf("WARNING: Game memory leak (%u bytes)\n", size);
		Cmd_ExecuteString(va("mem_stats %s", sv->gameSysPool->name));
	}

	Mem_DeletePool(sv->gameSysPool);
	sv->gameSysPool = NULL;

	SV_UnloadGame();

	svs.ge = NULL;
}
Beispiel #3
0
/*
================
SV_Shutdown

Called when each game quits, and before exitting application
================
*/
void SV_Shutdown(const char *finalmsg, bool reconnect)
{
	guard(SV_Shutdown);

	if (svs.clients)
	// NOTE: this required even for attractloop: if disable, when demo finishes, client will not be automatically disconnected
	{
		int			i;
		client_t	*cl;

		// Send a final message to all connected clients before the server goes down.
		//  The messages are sent immediately, not just stuck on the outgoing message
		// list, because the server is going to totally exit after returning from this function.
		for (i = 0, cl = svs.clients; i < sv_maxclients->integer; i++, cl++)
		{
			if (cl->state < cs_connected)
				continue;

			net_message.Clear();
			MSG_WriteByte(&net_message, svc_print);
			MSG_WriteByte(&net_message, PRINT_HIGH);
			if (cl->newprotocol && !reconnect)	// colorize exit message
				MSG_WriteString(&net_message, va(S_RED"%s", finalmsg));
			else
				MSG_WriteString(&net_message, finalmsg);
			MSG_WriteByte(&net_message, reconnect ? svc_reconnect : svc_disconnect);

			cl->netchan.Transmit(net_message.data, net_message.cursize);
		}
	}

	Master_Shutdown();
	SV_ShutdownGameLibrary();

	// free current level
	if (sv.rdemofile)
		delete sv.rdemofile;
	memset(&sv, 0, sizeof(sv));
	Com_SetServerState(ss_dead);	// == 0

	// free server static data
	sv_client = NULL;
	if (svs.clients) delete svs.clients;
	if (svs.client_entities) delete svs.client_entities;
	if (svs.wdemofile)
		fclose(svs.wdemofile);
	memset(&svs, 0, sizeof(svs));

	SV_InitVars();	// called for unlocking latched vars
	Cvar_ForceSet("nointro", "1");

	unguard;
}
Beispiel #4
0
/**
 * @brief Change the server to a new map, taking all connected clients along with it.
 * @note the full syntax is: @code map [day|night] [+]<map> [<assembly>] @endcode
 * @sa SV_AssembleMap
 * @sa CM_LoadMap
 * @sa Com_SetServerState
 */
void SV_Map (qboolean day, const char *levelstring, const char *assembly)
{
	int i;
	unsigned checksum = 0;
	char * map = SV_GetConfigString(CS_TILES);
	char * pos = SV_GetConfigString(CS_POSITIONS);
	mapInfo_t *randomMap = NULL;
	client_t *cl;

	/* any partially connected client will be restarted */
	Com_SetServerState(ss_restart);

	/* the game is just starting */
	SV_InitGame();

	if (!svs.initialized) {
		Com_Printf("Could not spawn the server\n");
		return;
	}

	assert(levelstring[0] != '\0');

	Com_DPrintf(DEBUG_SERVER, "SpawnServer: %s\n", levelstring);

	/* save name for levels that don't set message */
	SV_SetConfigString(CS_NAME, levelstring);
	SV_SetConfigString(CS_LIGHTMAP, day);

	Q_strncpyz(sv->name, levelstring, sizeof(sv->name));

	/* set serverinfo variable */
	sv_mapname = Cvar_FullSet("sv_mapname", sv->name, CVAR_SERVERINFO | CVAR_NOSET);

	/* notify the client in case of a listening server */
	SCR_BeginLoadingPlaque();

	if (assembly)
		Q_strncpyz(sv->assembly, assembly, sizeof(sv->assembly));
	else
		sv->assembly[0] = '\0';

	/* leave slots at start for clients only */
	cl = NULL;
	while ((cl = SV_GetNextClient(cl)) != NULL) {
		/* needs to reconnect */
		if (cl->state >= cs_spawning)
			SV_SetClientState(cl, cs_connected);
	}

	/* assemble and load the map */
	if (levelstring[0] == '+') {
		randomMap = SV_AssembleMap(levelstring + 1, assembly, map, pos, 0);
		if (!randomMap) {
			Com_Printf("Could not load assembly for map '%s'\n", levelstring);
			return;
		}
	} else {
		SV_SetConfigString(CS_TILES, levelstring);
		SV_SetConfigString(CS_POSITIONS, assembly ? assembly : "");
	}

	CM_LoadMap(map, day, pos, &sv->mapData, &sv->mapTiles);

	Com_Printf("checksum for the map '%s': %u\n", levelstring, sv->mapData.mapChecksum);
	SV_SetConfigString(CS_MAPCHECKSUM, sv->mapData.mapChecksum);

	checksum = Com_GetScriptChecksum();

	Com_Printf("ufo script checksum %u\n", checksum);
	SV_SetConfigString(CS_UFOCHECKSUM, checksum);
	SV_SetConfigString(CS_OBJECTAMOUNT, csi.numODs);
	SV_SetConfigString(CS_VERSION, UFO_VERSION);
	SV_SetConfigString(CS_MAPTITLE, SV_GetMapTitle(randomMap, levelstring));
	if (Q_strstart(SV_GetConfigString(CS_MAPTITLE), "b/")) {
		/* For base attack, CS_MAPTITLE contains too many chars */
		SV_SetConfigString(CS_MAPTITLE, "Base attack");
		SV_SetConfigString(CS_NAME, ".baseattack");
	}

	/* clear random-map assembly data */
	Mem_Free(randomMap);
	randomMap = NULL;

	/* clear physics interaction links */
	SV_ClearWorld();

	/* fix this! */
	for (i = 1; i <= sv->mapData.numInline; i++)
		sv->models[i] = CM_InlineModel(&sv->mapTiles, va("*%i", i));

	/* precache and static commands can be issued during map initialization */
	Com_SetServerState(ss_loading);

	TH_MutexLock(svs.serverMutex);
	/* load and spawn all other entities */
	svs.ge->SpawnEntities(sv->name, SV_GetConfigStringInteger(CS_LIGHTMAP), sv->mapData.mapEntityString);
	TH_MutexUnlock(svs.serverMutex);

	/* all precaches are complete */
	Com_SetServerState(ss_game);

	Com_Printf("-------------------------------------\n");

	Cbuf_CopyToDefer();
}
Beispiel #5
0
/*
================
SV_SpawnServer

Change the server to a new map, taking all connected
clients along with it.

================
*/
void SV_SpawnServer (char *server, char *spawnpoint, server_state_t serverstate, qboolean attractloop, qboolean loadgame)
{
	int			i;
	unsigned	checksum;

	if (attractloop)
		Cvar_Set ("paused", "0");

	Com_Printf ("------- Server Initialization -------\n");

	Com_DPrintf ("SpawnServer: %s\n",server);
	if (sv.demofile)
		fclose (sv.demofile);

	svs.spawncount++;		// any partially connected client will be
							// restarted
	sv.state = ss_dead;
	Com_SetServerState (sv.state);

	// wipe the entire per-level structure
	memset (&sv, 0, sizeof(sv));
	svs.realtime = 0;
	sv.loadgame = loadgame;
	sv.attractloop = attractloop;

	// save name for levels that don't set message
	strcpy (sv.configstrings[CS_NAME], server);
	if (Cvar_VariableValue ("deathmatch"))
	{
		sprintf(sv.configstrings[CS_AIRACCEL], "%g", sv_airaccelerate->value);
		pm_airaccelerate = sv_airaccelerate->value;
	}
	else
	{
		strcpy(sv.configstrings[CS_AIRACCEL], "0");
		pm_airaccelerate = 0;
	}

	SZ_Init (&sv.multicast, sv.multicast_buf, sizeof(sv.multicast_buf));

	strcpy (sv.name, server);

	// leave slots at start for clients only
	for (i=0 ; i<maxclients->value ; i++)
	{
		// needs to reconnect
		if (svs.clients[i].state > cs_connected)
			svs.clients[i].state = cs_connected;
		svs.clients[i].lastframe = -1;
	}

	sv.time = 1000;
	
	strcpy (sv.name, server);
	strcpy (sv.configstrings[CS_NAME], server);

	if (serverstate != ss_game)
	{
		sv.models[1] = CM_LoadMap ("", false, &checksum);	// no real map
	}
	else
	{
		Com_sprintf (sv.configstrings[CS_MODELS+1],sizeof(sv.configstrings[CS_MODELS+1]),
			"maps/%s.bsp", server);
		sv.models[1] = CM_LoadMap (sv.configstrings[CS_MODELS+1], false, &checksum);
	}
	Com_sprintf (sv.configstrings[CS_MAPCHECKSUM],sizeof(sv.configstrings[CS_MAPCHECKSUM]),
		"%i", checksum);

	//
	// clear physics interaction links
	//
	SV_ClearWorld ();
	
	for (i=1 ; i< CM_NumInlineModels() ; i++)
	{
		Com_sprintf (sv.configstrings[CS_MODELS+1+i], sizeof(sv.configstrings[CS_MODELS+1+i]),
			"*%i", i);
		sv.models[i+1] = CM_InlineModel (sv.configstrings[CS_MODELS+1+i]);
	}

	//
	// spawn the rest of the entities on the map
	//	

	// precache and static commands can be issued during
	// map initialization
	sv.state = ss_loading;
	Com_SetServerState (sv.state);

	// load and spawn all other entities
	ge->SpawnEntities ( sv.name, CM_EntityString(), spawnpoint );

	// run two frames to allow everything to settle
	ge->RunFrame ();
	ge->RunFrame ();

	// all precaches are complete
	sv.state = serverstate;
	Com_SetServerState (sv.state);
	
	// create a baseline for more efficient communications
	SV_CreateBaseline ();

	// check for a savegame
	SV_CheckForSavegame ();

	// set serverinfo variable
	Cvar_FullSet ("mapname", sv.name, CVAR_SERVERINFO | CVAR_NOSET);

	Com_Printf ("-------------------------------------\n");
}
Beispiel #6
0
/*
* SV_ShutdownGame
* 
* Called when each game quits
*/
void SV_ShutdownGame( const char *finalmsg, qboolean reconnect )
{
	if( !svs.initialized )
		return;

	if( svs.demo.file )
		SV_Demo_Stop_f();

	if( svs.clients )
		SV_FinalMessage( finalmsg, reconnect );

	SV_ShutdownGameProgs();

	// SV_MM_Shutdown();

	NET_CloseSocket( &svs.socket_loopback );
	NET_CloseSocket( &svs.socket_udp );
	NET_CloseSocket( &svs.socket_udp6 );
#ifdef TCP_ALLOW_CONNECT
	if( sv_tcp->integer )
		NET_CloseSocket( &svs.socket_tcp );
#endif

	// get any latched variable changes (sv_maxclients, etc)
	Cvar_GetLatchedVars( CVAR_LATCH );

	if( svs.clients )
	{
		Mem_Free( svs.clients );
		svs.clients = NULL;
	}

	if( svs.client_entities.entities )
	{
		Mem_Free( svs.client_entities.entities );
		memset( &svs.client_entities, 0, sizeof( svs.client_entities ) );
	}

	if( svs.cms )
	{
		CM_Free( svs.cms );
		svs.cms = NULL;
	}

	memset( &sv, 0, sizeof( sv ) );
	Com_SetServerState( sv.state );

	Com_FreePureList( &svs.purelist );

	if( svs.motd )
	{
		Mem_Free( svs.motd );
		svs.motd = NULL;
	}

	if( sv_mempool )
		Mem_EmptyPool( sv_mempool );

	memset( &svs, 0, sizeof( svs ) );

	svs.initialized = qfalse;
}
Beispiel #7
0
/*
* SV_SpawnServer
* Change the server to a new map, taking all connected clients along with it.
*/
static void SV_SpawnServer( const char *server, qboolean devmap )
{
	unsigned checksum;
	int i;

	if( devmap )
		Cvar_ForceSet( "sv_cheats", "1" );
	Cvar_FixCheatVars();

	Com_Printf( "------- Server Initialization -------\n" );
	Com_Printf( "SpawnServer: %s\n", server );

	svs.spawncount++;   // any partially connected client will be restarted

	Com_SetServerState( ss_dead );

	// wipe the entire per-level structure
	memset( &sv, 0, sizeof( sv ) );
	SV_ResetClientFrameCounters();
	svs.realtime = 0;
	svs.gametime = 0;
	SV_UpdateActivity();

	Q_strncpyz( sv.mapname, server, sizeof( sv.mapname ) );

	SV_SetServerConfigStrings();

	sv.nextSnapTime = 1000;

	Q_snprintfz( sv.configstrings[CS_WORLDMODEL], sizeof( sv.configstrings[CS_WORLDMODEL] ), "maps/%s.bsp", server );
	CM_LoadMap( svs.cms, sv.configstrings[CS_WORLDMODEL], qfalse, &checksum );

	Q_snprintfz( sv.configstrings[CS_MAPCHECKSUM], sizeof( sv.configstrings[CS_MAPCHECKSUM] ), "%i", checksum );

	// reserve the first modelIndexes for inline models
	for( i = 1; i < CM_NumInlineModels( svs.cms ); i++ )
		Q_snprintfz( sv.configstrings[CS_MODELS + i], sizeof( sv.configstrings[CS_MODELS + i] ), "*%i", i );

	// set serverinfo variable
	Cvar_FullSet( "mapname", sv.mapname, CVAR_SERVERINFO | CVAR_READONLY, qtrue );

	//
	// spawn the rest of the entities on the map
	//

	// precache and static commands can be issued during
	// map initialization
	sv.state = ss_loading;
	Com_SetServerState( sv.state );

	// set purelist
	SV_ReloadPureList();

	// load and spawn all other entities
	ge->InitLevel( sv.mapname, CM_EntityString( svs.cms ), CM_EntityStringLen( svs.cms ), 0, svs.gametime, svs.realtime );

	// run two frames to allow everything to settle
	ge->RunFrame( svc.snapFrameTime, svs.gametime );
	ge->RunFrame( svc.snapFrameTime, svs.gametime );

	SV_CreateBaseline(); // create a baseline for more efficient communications

	// all precaches are complete
	sv.state = ss_game;
	Com_SetServerState( sv.state );

	Com_Printf( "-------------------------------------\n" );
}
Beispiel #8
0
/*
 * Change the server to a new map, taking all connected
 * clients along with it.
 */
void SV_SpawnServer(char *server, char *spawnpoint, server_state_t serverstate, qboolean attractloop, qboolean loadgame)
{
  int i;
  unsigned checksum;

  if (attractloop) {
    Cvar_Set("paused", "0");
  }

  Com_Printf("Server init\n");
  Com_DPrintf("SpawnServer: %s\n", server);

  svs.spawncount++; /* any partially connected client will be restarted */
  sv.state = ss_dead;
  Com_SetServerState(sv.state);

  /* wipe the entire per-level structure */
  memset(&sv, 0, sizeof(sv));
  svs.realtime = 0;
  sv.loadgame = loadgame;
  sv.attractloop = attractloop;

  /* save name for levels that don't set message */
  strcpy(sv.configstrings[CS_NAME], server);

  if (Cvar_VariableValue("deathmatch")) {
    sprintf(sv.configstrings[CS_AIRACCEL], "%g", sv_airaccelerate->value);
    pm_airaccelerate = sv_airaccelerate->value;
  } else {
    strcpy(sv.configstrings[CS_AIRACCEL], "0");
    pm_airaccelerate = 0;
  }

  SZ_Init(&sv.multicast, sv.multicast_buf, sizeof(sv.multicast_buf));

  strcpy(sv.name, server);

  /* leave slots at start for clients only */
  for (i = 0; i < maxclients->value; i++) {
    /* needs to reconnect */
    if (svs.clients[i].state > cs_connected) {
      svs.clients[i].state = cs_connected;
    }

    svs.clients[i].lastframe = -1;
  }

  sv.time = 1000;

  strcpy(sv.name, server);
  strcpy(sv.configstrings[CS_NAME], server);

  if (serverstate != ss_game) {
    sv.models[1] = CM_LoadMap("", false, &checksum); /* no real map */
  } else {
    Com_sprintf(sv.configstrings[CS_MODELS + 1], sizeof(sv.configstrings[CS_MODELS + 1]), "maps/%s.bsp", server);
    sv.models[1] = CM_LoadMap(sv.configstrings[CS_MODELS + 1], false, &checksum);
  }

  Com_sprintf(sv.configstrings[CS_MAPCHECKSUM], sizeof(sv.configstrings[CS_MAPCHECKSUM]), "%i", checksum);

  /* clear physics interaction links */
  SV_ClearWorld();

  for (i = 1; i < CM_NumInlineModels(); i++) {
    Com_sprintf(sv.configstrings[CS_MODELS + 1 + i], sizeof(sv.configstrings[CS_MODELS + 1 + i]), "*%i", i);
    sv.models[i + 1] = CM_InlineModel(sv.configstrings[CS_MODELS + 1 + i]);
  }

  /* spawn the rest of the entities on the map */
  sv.state = ss_loading;
  Com_SetServerState(sv.state);

  /* load and spawn all other entities */
  SpawnEntities(sv.name, CM_EntityString(), spawnpoint);

  /* run two frames to allow everything to settle */
  G_RunFrame();
  G_RunFrame();

  /* verify game didn't clobber important stuff */
  if ((int) checksum != (int) strtol(sv.configstrings[CS_MAPCHECKSUM], (char **) NULL, 10)) {
    Com_Error(ERR_DROP, "Game DLL corrupted server configstrings");
  }

  /* all precaches are complete */
  sv.state = serverstate;
  Com_SetServerState(sv.state);

  /* create a baseline for more efficient communications */
  SV_CreateBaseline();

  /* set serverinfo variable */
  Cvar_FullSet("mapname", sv.name, CVAR_SERVERINFO | CVAR_NOSET);
}
Beispiel #9
0
/**
 * @brief Will eventually shutdown the server once all clients have disconnected
 * @sa SV_CountPlayers
 */
void SV_ShutdownWhenEmpty (void)
{
	svs.abandon = true;
	/* pretend server is already dead, otherwise clients may try and reconnect */
	Com_SetServerState(ss_dead);
}
Beispiel #10
0
/*
* SV_ShutdownGame
*
* Called when each game quits
*/
void SV_ShutdownGame( const char *finalmsg, bool reconnect ) {
	if( !svs.initialized ) {
		return;
	}

	if( svs.demo.file ) {
		SV_Demo_Stop_f();
	}

	if( svs.clients ) {
		SV_FinalMessage( finalmsg, reconnect );
	}

	SV_ShutdownGameProgs();

	// SV_MM_Shutdown();

	SV_MasterSendQuit();

	NET_CloseSocket( &svs.socket_loopback );
	NET_CloseSocket( &svs.socket_udp );
	NET_CloseSocket( &svs.socket_udp6 );
#ifdef TCP_ALLOW_CONNECT
	if( sv_tcp->integer ) {
		NET_CloseSocket( &svs.socket_tcp );
		NET_CloseSocket( &svs.socket_tcp6 );
	}
#endif

	// get any latched variable changes (sv_maxclients, etc)
	Cvar_GetLatchedVars( CVAR_LATCH );

	if( svs.clients ) {
		Mem_Free( svs.clients );
		svs.clients = NULL;
	}

	if( svs.client_entities.entities ) {
		Mem_Free( svs.client_entities.entities );
		memset( &svs.client_entities, 0, sizeof( svs.client_entities ) );
	}

	if( svs.cms ) {
		// CM_ReleaseReference will take care of freeing up the memory
		// if there are no other modules referencing the collision model
		CM_ReleaseReference( svs.cms );
		svs.cms = NULL;
	}

	Com_SetServerCM( NULL, 0 );

	memset( &sv, 0, sizeof( sv ) );
	Com_SetServerState( sv.state );

	Com_FreePureList( &svs.purelist );

	if( svs.motd ) {
		Mem_Free( svs.motd );
		svs.motd = NULL;
	}

	if( sv_mempool ) {
		Mem_EmptyPool( sv_mempool );
	}

	if( svs.wakelock ) {
		Sys_ReleaseWakeLock( svs.wakelock );
		svs.wakelock = NULL;
	}

	memset( &svs, 0, sizeof( svs ) );

	svs.initialized = false;
}
Beispiel #11
0
/*
================
SV_SpawnServer

Change the server to a new map, taking all connected
clients along with it.

================
*/
void SV_SpawnServer (char *server, char *spawnpoint, server_state_t serverstate, 
					 qboolean attractloop, qboolean loadgame)
{
	int			i;
	unsigned	checksum;
	float		cer_public;
	float		cer_sv_login;
	float		cer_sv_forcesky;
	float		cer_guntemp_inc;
	float		cer_guntemp_dec;
	float		cer_elim;
	float		cer_fraglimit;
	float		cer_timelimit;

	if (attractloop)
		Cvar_Set("paused", "0");

	Com_Printf("------- Server Initialization -------\n");
	Com_DPrintf("SpawnServer: %s\n", server);

	if (sv.demofile)
		fclose(sv.demofile);

	svs.spawncount++;		// any partially connected client will be restarted
	sv.state = ss_dead;
	Com_SetServerState(sv.state);

	// wipe the entire per-level structure
	memset(&sv, 0, sizeof(sv));
	svs.realtime = 0;
	sv.loadgame = loadgame;
	sv.attractloop = attractloop;

	// save name for levels that don't set message
	strcpy(sv.configstrings[CS_NAME], server);

	sprintf(sv.configstrings[CS_AIRACCEL], "%g", sv_airaccelerate->value);
	pm_airaccelerate = sv_airaccelerate->value;

	SV_ReplicatePhysicsSettings(); // jitmovephysics

	sprintf(sv.configstrings[CS_SERVEREVERSION], "Enginever: %g Enginebuild: %d", VERSION, BUILD);
	SZ_Init(&sv.multicast, sv.multicast_buf, sizeof(sv.multicast_buf));
	strcpy(sv.name, server);

	// leave slots at start for clients only
	for (i = 0; i < maxclients->value; i++)
	{
		// needs to reconnect
		if (svs.clients[i].state > cs_connected)
			svs.clients[i].state = cs_connected;

		svs.clients[i].lastframe = -1;
	}

	sv.time = 1000;
	strcpy(sv.name, server);
	strcpy(sv.configstrings[CS_NAME], server);

	if (serverstate != ss_game)
	{
		sv.models[1] = CM_LoadMap("", false, &checksum);	// no real map
	}
	else
	{
		Com_sprintf(sv.configstrings[CS_MODELS + 1], sizeof(sv.configstrings[CS_MODELS + 1]), "maps/%s.bsp", server);
		sv.models[1] = CM_LoadMap(sv.configstrings[CS_MODELS + 1], false, &checksum);
	}

	Com_sprintf(sv.configstrings[CS_MAPCHECKSUM], sizeof(sv.configstrings[CS_MAPCHECKSUM]), "%i", checksum);

	// clear physics interaction links
	SV_ClearWorld();
	
	for (i = 1; i < CM_NumInlineModels(); i++)
	{
		Com_sprintf (sv.configstrings[CS_MODELS + 1 + i], sizeof(sv.configstrings[CS_MODELS + 1 + i]), "*%i", i);
		sv.models[i + 1] = CM_InlineModel(sv.configstrings[CS_MODELS + 1 + i]);
	}

	//
	// spawn the rest of the entities on the map
	//	

	// precache and static commands can be issued during
	// map initialization
	sv.state = ss_loading;
	Com_SetServerState(sv.state);

	//if(!sv.attractloop) // jitdemo -- don't spawn game stuff while demo is playing!
	{
		// load and spawn all other entities
		ge->SpawnEntities(sv.name, CM_EntityString(), spawnpoint);

		// run two frames to allow everything to settle
		ge->RunFrame();
		ge->RunFrame();
	}

	// all precaches are complete
	sv.state = serverstate;
	Com_SetServerState(sv.state);
	
	// create a baseline for more efficient communications
	SV_CreateBaseline();

	// check for a savegame
	SV_CheckForSavegame();

	// set serverinfo variable
	Cvar_FullSet("mapname", sv.name, CVAR_SERVERINFO | CVAR_NOSET, true);

	// T3RR0R15T: certificated server info (default settings atm)
	//cer_maxclients			= Cvar_VariableValue("maxclients");
	cer_elim				= Cvar_VariableValue("elim");
	cer_fraglimit			= Cvar_VariableValue("fraglimit");
	cer_timelimit			= Cvar_VariableValue("timelimit");
	//cer_sv_minclientbuild   = Cvar_VariableValue("sv_minclientbuild");
	cer_guntemp_inc			= Cvar_VariableValue("guntemp_inc");
	cer_guntemp_dec			= Cvar_VariableValue("guntemp_dec");
	cer_sv_forcesky			= Cvar_VariableValue("sv_forcesky");
	cer_sv_login			= Cvar_VariableValue("sv_login");
	cer_public				= Cvar_VariableValue("public");

	// Don't forget to change the SV_Certificatedinfo_f (sv_ccmds.c), if you change something here !
	if (//cer_maxclients->value == 16 &&
		(cer_elim >= 60.0f || cer_elim == 0.0f) &&
		cer_fraglimit == 50.0f &&
		cer_timelimit == 20.0f &&
		//cer_sv_minclientbuild >= 28.0f &&
		cer_guntemp_inc >= 10.5f && // 11 + some leeway
		cer_guntemp_dec <= 4.2f && // 4 + some leeway
		cer_sv_forcesky &&
		cer_sv_login &&
		cer_public)
	{
		Cvar_FullSet("sv_certificated", "1", CVAR_SERVERINFO | CVAR_NOSET, true);
	} else {
		Cvar_FullSet("sv_certificated", "0", CVAR_SERVERINFO | CVAR_NOSET, true);
	}

	Com_Printf("-------------------------------------\n");
}