Exemple #1
0
/**
* @brief Called when all downloading has been completed
* Initiates update process after an update has been downloaded.
*/
static void Com_DownloadsComplete(void)
{
	if (Com_CheckUpdateDownloads())
	{
		return;
	}

	// if we downloaded files we need to restart the file system
	if (dld.downloadRestart)
	{
		dld.downloadRestart = qfalse;

#ifdef DEDICATED
		FS_Restart(sv.checksumFeed);
#else
		FS_Restart(clc.checksumFeed);    // We possibly downloaded a pak, restart the file system to load it

		if (!dld.bWWWDlDisconnected)
		{
			// inform the server so we get new gamestate info
			Com_AddReliableCommand("donedl");
		}
#endif
		// we can reset that now
		dld.bWWWDlDisconnected = qfalse;
		Com_ClearStaticDownload();

		// by sending the donedl command we request a new gamestate
		// so we don't want to load stuff yet
		return;
	}

	// I wonder if that happens - it should not but I suspect it could happen if a download fails in the middle or is aborted
	assert(!dld.bWWWDlDisconnected);

#ifndef DEDICATED
	CL_DownloadsComplete();
#endif
}
/*
 ==================
 UI_Mods_Callback
 ==================
*/
static void UI_Mods_Callback (void *self, int event){

	menuCommon_t	*item = (menuCommon_t *)self;

	if (event == QM_CHANGED){
		// See if the load button should be grayed
		if (!Str_ICompare(CVar_GetVariableString("fs_game"), uiMods.modsDir[uiMods.modList.curItem]))
			uiMods.load.generic.flags |= QMF_GRAYED;
		else
			uiMods.load.generic.flags &= ~QMF_GRAYED;

		return;
	}

	if (event != QM_ACTIVATED)
		return;

	switch (item->id){
	case ID_BACK:
		UI_PopMenu();
		break;
	case ID_LOAD:
		if (cls.state == CA_ACTIVE)
			break;		// Don't f**k up the game

		// Update fs_game
		CVar_ForceSet("fs_game", uiMods.modsDir[uiMods.modList.curItem]);

		// Restart file system
		FS_Restart();

		// Flush all data so it will be forced to reload
		Cmd_ExecuteText(CMD_EXEC_APPEND, "restartVideo\n");

		break;
	}
}
Exemple #3
0
void CL_cURL_PerformDownload(void)
{
	CURLMcode res;
	CURLMsg *msg;
	int c;
	int i = 0;

	res = qcurl_multi_perform(clc.downloadCURLM, &c);
	while(res == CURLM_CALL_MULTI_PERFORM && i < 100) {
		res = qcurl_multi_perform(clc.downloadCURLM, &c);
		i++;
	}
	if(res == CURLM_CALL_MULTI_PERFORM)
		return;
	msg = qcurl_multi_info_read(clc.downloadCURLM, &c);
	if(msg == NULL) {
		return;
	}
	FS_FCloseFile(clc.download);
	if(msg->msg == CURLMSG_DONE && msg->data.result == CURLE_OK) {
		FS_SV_Rename(clc.downloadTempName, clc.downloadName);
	}
	else {
		long code;

		qcurl_easy_getinfo(msg->easy_handle, CURLINFO_RESPONSE_CODE,
			&code);	
		Com_Error(ERR_DROP, "Download Error: %s Code: %d",
			qcurl_easy_strerror(msg->data.result),
			code);
	}
	*clc.downloadTempName = *clc.downloadName = 0;
	Cvar_Set( "cl_downloadName", "" );
	CL_cURL_Cleanup();
	FS_Restart(clc.checksumFeed);
	CL_Reconnect_f();
}
/*
================
SV_SpawnServer

Change the server to a new map, taking all connected
clients along with it.
This is NOT called for map_restart
================
*/
void SV_SpawnServer( char *server, qboolean killBots ) {
    int			i;
    int			checksum;
    qboolean	isBot;
    char		systemInfo[16384];
    const char	*p;

    // shut down the existing game if it is running
    SV_ShutdownGameProgs();

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

    // if not running a dedicated server CL_MapLoading will connect the client to the server
    // also print some status stuff
    CL_MapLoading();

    // make sure all the client stuff is unloaded
    CL_ShutdownAll();

    // clear the whole hunk because we're (re)loading the server
    Hunk_Clear();

    // clear collision map data
    CM_ClearMap();

    // init client structures and svs.numSnapshotEntities
    if ( !Cvar_VariableValue("sv_running") ) {
        SV_Startup();
    } else {
        // check for maxclients change
        if ( sv_maxclients->modified ) {
            SV_ChangeMaxClients();
        }
    }

    // clear pak references
    FS_ClearPakReferences(0);

    // allocate the snapshot entities on the hunk
    svs.snapshotEntities = Hunk_Alloc( sizeof(entityState_t)*svs.numSnapshotEntities, h_high );
    svs.nextSnapshotEntities = 0;

    // toggle the server bit so clients can detect that a
    // server has changed
    svs.snapFlagServerBit ^= SNAPFLAG_SERVERCOUNT;

    // set nextmap to the same map, but it may be overriden
    // by the game startup or another console command
    Cvar_Set( "nextmap", "map_restart 0");
//	Cvar_Set( "nextmap", va("map %s", server) );

    // wipe the entire per-level structure
    SV_ClearServer();
    for ( i = 0 ; i < MAX_CONFIGSTRINGS ; i++ ) {
        sv.configstrings[i] = CopyString("");
    }

    // make sure we are not paused
    Cvar_Set("cl_paused", "0");

    // get a new checksum feed and restart the file system
    srand(Com_Milliseconds());
    sv.checksumFeed = ( ((int) rand() << 16) ^ rand() ) ^ Com_Milliseconds();
    FS_Restart( sv.checksumFeed );

    CM_LoadMap( va("maps/%s.bsp", server), qfalse, &checksum );

    // set serverinfo visible name
    Cvar_Set( "mapname", server );

    Cvar_Set( "sv_mapChecksum", va("%i",checksum) );

    // serverid should be different each time
    sv.serverId = com_frameTime;
    sv.restartedServerId = sv.serverId; // I suppose the init here is just to be safe
    sv.checksumFeedServerId = sv.serverId;
    Cvar_Set( "sv_serverid", va("%i", sv.serverId ) );

    // clear physics interaction links
    SV_ClearWorld ();

    // media configstring setting should be done during
    // the loading stage, so connected clients don't have
    // to load during actual gameplay
    sv.state = SS_LOADING;

    // load and spawn all other entities
    SV_InitGameProgs();

    // don't allow a map_restart if game is modified
    sv_gametype->modified = qfalse;

    // run a few frames to allow everything to settle
    for ( i = 0 ; i < 3 ; i++ ) {
        VM_Call( gvm, GAME_RUN_FRAME, svs.time );
        SV_BotFrame( svs.time );
        svs.time += 100;
    }

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

    for (i=0 ; i<sv_maxclients->integer ; i++) {
        // send the new gamestate to all connected clients
        if (svs.clients[i].state >= CS_CONNECTED) {
            char	*denied;

            if ( svs.clients[i].netchan.remoteAddress.type == NA_BOT ) {
                if ( killBots ) {
                    SV_DropClient( &svs.clients[i], "" );
                    continue;
                }
                isBot = qtrue;
            }
            else {
                isBot = qfalse;
            }

            // connect the client again
            denied = VM_ExplicitArgPtr( gvm, VM_Call( gvm, GAME_CLIENT_CONNECT, i, qfalse, isBot ) );	// firstTime = qfalse
            if ( denied ) {
                // this generally shouldn't happen, because the client
                // was connected before the level change
                SV_DropClient( &svs.clients[i], denied );
            } else {
                if( !isBot ) {
                    // when we get the next packet from a connected client,
                    // the new gamestate will be sent
                    svs.clients[i].state = CS_CONNECTED;
                }
                else {
                    client_t		*client;
                    sharedEntity_t	*ent;

                    client = &svs.clients[i];
                    client->state = CS_ACTIVE;
                    ent = SV_GentityNum( i );
                    ent->s.number = i;
                    client->gentity = ent;

                    client->deltaMessage = -1;
                    client->nextSnapshotTime = svs.time;	// generate a snapshot immediately

                    VM_Call( gvm, GAME_CLIENT_BEGIN, i );
                }
            }
        }
    }

    // run another frame to allow things to look at all the players
    VM_Call( gvm, GAME_RUN_FRAME, svs.time );
    SV_BotFrame( svs.time );
    svs.time += 100;

    if ( sv_pure->integer ) {
        // the server sends these to the clients so they will only
        // load pk3s also loaded at the server
        p = FS_LoadedPakChecksums();
        Cvar_Set( "sv_paks", p );
        if (strlen(p) == 0) {
            Com_Printf( "WARNING: sv_pure set but no PK3 files loaded\n" );
        }
        p = FS_LoadedPakNames();
        Cvar_Set( "sv_pakNames", p );

        // if a dedicated pure server we need to touch the cgame because it could be in a
        // seperate pk3 file and the client will need to load the latest cgame.qvm
        if ( com_dedicated->integer ) {
            SV_TouchCGame();
        }
    }
    else {
        Cvar_Set( "sv_paks", "" );
        Cvar_Set( "sv_pakNames", "" );
    }
    // the server sends these to the clients so they can figure
    // out which pk3s should be auto-downloaded
    p = FS_ReferencedPakChecksums();
    Cvar_Set( "sv_referencedPaks", p );
    p = FS_ReferencedPakNames();
    Cvar_Set( "sv_referencedPakNames", p );

    // save systeminfo and serverinfo strings
    Q_strncpyz( systemInfo, Cvar_InfoString_Big( CVAR_SYSTEMINFO ), sizeof( systemInfo ) );
    cvar_modifiedFlags &= ~CVAR_SYSTEMINFO;
    SV_SetConfigstring( CS_SYSTEMINFO, systemInfo );

    SV_SetConfigstring( CS_SERVERINFO, Cvar_InfoString( CVAR_SERVERINFO ) );
    cvar_modifiedFlags &= ~CVAR_SERVERINFO;

    // any media configstring setting now should issue a warning
    // and any configstring changes should be reliably transmitted
    // to all clients
    sv.state = SS_GAME;

    // send a heartbeat now so the master will get up to date info
    SV_Heartbeat_f();

    Hunk_SetMark();

    Com_Printf ("-----------------------------------\n");
}
Exemple #5
0
/*
================
SV_SpawnServer

Change the server to a new map, taking all connected
clients along with it.
This is NOT called for map_restart
================
*/
void SV_SpawnServer( char *server, qboolean killBots )
{
	int        i;
	int        checksum;
	qboolean   isBot;
	const char *p;

	// shut down the existing game if it is running
	SV_ShutdownGameProgs();

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

	// if not running a dedicated server CL_MapLoading will connect the client to the server
	// also print some status stuff
	CL_MapLoading();

	// make sure all the client stuff is unloaded
	CL_ShutdownAll();

	// clear the whole hunk because we're (re)loading the server
	Hunk_Clear();

	// clear collision map data     // (SA) NOTE: TODO: used in missionpack
	CM_ClearMap();

	// wipe the entire per-level structure
	SV_ClearServer();

	// MrE: main zone should be pretty much emtpy at this point
	// except for file system data and cached renderer data
	Z_LogHeap();

	// allocate empty config strings
	for ( i = 0; i < MAX_CONFIGSTRINGS; i++ )
	{
		sv.configstrings[ i ] = CopyString( "" );
		sv.configstringsmodified[ i ] = qfalse;
	}

	// init client structures and svs.numSnapshotEntities
	if ( !Cvar_VariableValue( "sv_running" ) )
	{
		SV_Startup();
	}
	else
	{
		// check for maxclients change
		if ( sv_maxclients->modified )
		{
			SV_ChangeMaxClients();
		}

#ifdef USE_HUB_SERVER

		// if sv_owHubHost was changed, resolve the address again
		if ( sv_owHubHost->modified )
		{
			sv_owHubHost->modified = qfalse;
			SV_ResolveowHubHost();
		}

#endif
	}

	// clear pak references
	FS_ClearPakReferences( 0 );

	// allocate the snapshot entities on the hunk
	svs.snapshotEntities = Hunk_Alloc( sizeof( entityState_t ) * svs.numSnapshotEntities, h_high );
	svs.nextSnapshotEntities = 0;

	// toggle the server bit so clients can detect that a
	// server has changed
	svs.snapFlagServerBit ^= SNAPFLAG_SERVERCOUNT;

	// set nextmap to the same map, but it may be overriden
	// by the game startup or another console command
	Cvar_Set( "nextmap", "map_restart 0" );
//  Cvar_Set( "nextmap", va("map %s", server) );

	// Ridah
	// DHM - Nerve :: We want to use the completion bar in multiplayer as well
	// Arnout: just always use it
//  if( !SV_GameIsSinglePlayer() ) {
	SV_SetExpectedHunkUsage( va( "maps/%s.bsp", server ) );
//  } else {
	// just set it to a negative number,so the cgame knows not to draw the percent bar
//      Cvar_Set( "com_expectedhunkusage", "-1" );
//  }

	// make sure we are not paused
	Cvar_Set( "cl_paused", "0" );

#if !defined( DO_LIGHT_DEDICATED )
	// get a new checksum feed and restart the file system
	srand( Sys_Milliseconds() );
	sv.checksumFeed = ( ( ( int ) rand() << 16 ) ^ rand() ) ^ Sys_Milliseconds();

	// DO_LIGHT_DEDICATED
	// only comment out when you need a new pure checksum string and it's associated random feed
	//Com_DPrintf("SV_SpawnServer checksum feed: %p\n", sv.checksumFeed);

#else // DO_LIGHT_DEDICATED implementation below
	// we are not able to randomize the checksum feed since the feed is used as key for pure_checksum computations
	// files.c 1776 : pack->pure_checksum = Com_BlockChecksumKey( fs_headerLongs, 4 * fs_numHeaderLongs, LittleLong(fs_checksumFeed) );
	// we request a fake randomized feed, files.c knows the answer
	srand( Sys_Milliseconds() );
	sv.checksumFeed = FS_RandChecksumFeed();
#endif
	FS_Restart( sv.checksumFeed );

	CM_LoadMap( va( "maps/%s.bsp", server ), qfalse, &checksum );

	// set serverinfo visible name
	Cvar_Set( "mapname", server );

	Cvar_Set( "sv_mapChecksum", va( "%i", checksum ) );

	sv_newGameShlib = Cvar_Get( "sv_newGameShlib", "", CVAR_TEMP );

	// serverid should be different each time
	sv.serverId = com_frameTime;
	sv.restartedServerId = sv.serverId;
	sv.checksumFeedServerId = sv.serverId;
	Cvar_Set( "sv_serverid", va( "%i", sv.serverId ) );

	// clear physics interaction links
	SV_ClearWorld();

	// media configstring setting should be done during
	// the loading stage, so connected clients don't have
	// to load during actual gameplay
	sv.state = SS_LOADING;

	Cvar_Set( "sv_serverRestarting", "1" );

	// load and spawn all other entities
	SV_InitGameProgs();

	// don't allow a map_restart if game is modified
	// Arnout: there isn't any check done against this, obsolete
//  sv_gametype->modified = qfalse;

	// run a few frames to allow everything to settle
	for ( i = 0; i < GAME_INIT_FRAMES; i++ )
	{
		VM_Call( gvm, GAME_RUN_FRAME, svs.time );
		SV_BotFrame( svs.time );
		svs.time += FRAMETIME;
	}

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

	for ( i = 0; i < sv_maxclients->integer; i++ )
	{
		// send the new gamestate to all connected clients
		if ( svs.clients[ i ].state >= CS_CONNECTED )
		{
			char *denied;

			if ( svs.clients[ i ].netchan.remoteAddress.type == NA_BOT )
			{
				if ( killBots || SV_GameIsSinglePlayer() || SV_GameIsCoop() )
				{
					SV_DropClient( &svs.clients[ i ], "" );
					continue;
				}

				isBot = qtrue;
			}
			else
			{
				isBot = qfalse;
			}

			// connect the client again
			denied = VM_ExplicitArgPtr( gvm, VM_Call( gvm, GAME_CLIENT_CONNECT, i, qfalse, isBot ) );   // firstTime = qfalse

			if ( denied )
			{
				// this generally shouldn't happen, because the client
				// was connected before the level change
				SV_DropClient( &svs.clients[ i ], denied );
			}
			else
			{
				if ( !isBot )
				{
					// when we get the next packet from a connected client,
					// the new gamestate will be sent
					svs.clients[ i ].state = CS_CONNECTED;
				}
				else
				{
					client_t       *client;
					sharedEntity_t *ent;

					client = &svs.clients[ i ];
					client->state = CS_ACTIVE;
					ent = SV_GentityNum( i );
					ent->s.number = i;
					client->gentity = ent;

					client->deltaMessage = -1;
					client->nextSnapshotTime = svs.time; // generate a snapshot immediately

					VM_Call( gvm, GAME_CLIENT_BEGIN, i );
				}
			}
		}
	}

	// run another frame to allow things to look at all the players
	VM_Call( gvm, GAME_RUN_FRAME, svs.time );
	SV_BotFrame( svs.time );
	svs.time += FRAMETIME;

	if ( sv_pure->integer )
	{
		// the server sends these to the clients so they will only
		// load pk3s also loaded at the server
		p = FS_LoadedPakChecksums();
		Cvar_Set( "sv_paks", p );

		if ( strlen( p ) == 0 )
		{
			Com_Printf( "WARNING: sv_pure set but no PK3 files loaded\n" );
		}

		p = FS_LoadedPakNames();
		Cvar_Set( "sv_pakNames", p );

		// if a dedicated pure server we need to touch the cgame because it could be in a
		// seperate pk3 file and the client will need to load the latest cgame.qvm
		if ( com_dedicated->integer )
		{
			SV_TouchCGame();
		}
	}
	else
	{
		Cvar_Set( "sv_paks", "" );
		Cvar_Set( "sv_pakNames", "" );
	}

	// the server sends these to the clients so they can figure
	// out which pk3s should be auto-downloaded
	// NOTE: we consider the referencedPaks as 'required for operation'

	// we want the server to reference the mp_bin pk3 that the client is expected to load from
	SV_TouchCGameDLL();

	p = FS_ReferencedPakChecksums();
	Cvar_Set( "sv_referencedPaks", p );
	p = FS_ReferencedPakNames();
	Cvar_Set( "sv_referencedPakNames", p );

	// save systeminfo and serverinfo strings
	cvar_modifiedFlags &= ~CVAR_SYSTEMINFO;
	SV_SetConfigstring( CS_SYSTEMINFO, Cvar_InfoString_Big( CVAR_SYSTEMINFO ) );

	SV_SetConfigstring( CS_SERVERINFO, Cvar_InfoString( CVAR_SERVERINFO | CVAR_SERVERINFO_NOUPDATE ) );
	cvar_modifiedFlags &= ~CVAR_SERVERINFO;

	// any media configstring setting now should issue a warning
	// and any configstring changes should be reliably transmitted
	// to all clients
	sv.state = SS_GAME;

	// send a heartbeat now so the master will get up to date info
	SV_Heartbeat_f();

	Hunk_SetMark();

	SV_UpdateConfigStrings();

	Cvar_Set( "sv_serverRestarting", "0" );

	Com_Printf( "-----------------------------------\n" );
}
Exemple #6
0
/*
================
SV_SpawnServer

Change the server to a new map, taking all connected
clients along with it.
This is NOT called for map_restart
================
*/
void SV_SpawnServer( char *server, qboolean killBots, ForceReload_e eForceReload ) {
	int			i;
	int			checksum;
	qboolean	isBot;
	char		systemInfo[16384];
	const char	*p;

	SV_StopAutoRecordDemos();

	SV_SendMapChange();

	re->RegisterMedia_LevelLoadBegin(server, eForceReload);

	// shut down the existing game if it is running
	SV_ShutdownGameProgs();
	svs.gameStarted = qfalse;

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

/*
Ghoul2 Insert Start
*/
 	// de allocate the snapshot entities
	if (svs.snapshotEntities)
	{
		delete[] svs.snapshotEntities;
		svs.snapshotEntities = NULL;
	}
/*
Ghoul2 Insert End
*/

	SV_SendMapChange();

	// if not running a dedicated server CL_MapLoading will connect the client to the server
	// also print some status stuff
	CL_MapLoading();

#ifndef DEDICATED
	// make sure all the client stuff is unloaded
	CL_ShutdownAll( qfalse );
#endif

	CM_ClearMap();

	// clear the whole hunk because we're (re)loading the server
	Hunk_Clear();

	re->InitSkins();
	re->InitShaders(qtrue);

	// init client structures and svs.numSnapshotEntities
	if ( !Cvar_VariableValue("sv_running") ) {
		SV_Startup();
	} else {
		// check for maxclients change
		if ( sv_maxclients->modified ) {
			SV_ChangeMaxClients();
		}
	}

	SV_SendMapChange();

/*
Ghoul2 Insert Start
*/
 	// clear out those shaders, images and Models as long as this
	// isnt a dedicated server.
	/*
	if ( !com_dedicated->integer )
	{
#ifndef DEDICATED
		R_InitImages();

		R_InitShaders();

		R_ModelInit();
#endif
	}
	else
	*/
	if (com_dedicated->integer)
	{
		re->SVModelInit();
	}

	SV_SendMapChange();

	// clear pak references
	FS_ClearPakReferences(0);

/*
Ghoul2 Insert Start
*/
	// allocate the snapshot entities on the hunk
//	svs.snapshotEntities = (struct entityState_s *)Hunk_Alloc( sizeof(entityState_t)*svs.numSnapshotEntities, h_high );
	svs.nextSnapshotEntities = 0;

	// allocate the snapshot entities
	svs.snapshotEntities = new entityState_s[svs.numSnapshotEntities];
	// we CAN afford to do this here, since we know the STL vectors in Ghoul2 are empty
	memset(svs.snapshotEntities, 0, sizeof(entityState_t)*svs.numSnapshotEntities);

/*
Ghoul2 Insert End
*/

	// toggle the server bit so clients can detect that a
	// server has changed
	svs.snapFlagServerBit ^= SNAPFLAG_SERVERCOUNT;

	// set nextmap to the same map, but it may be overriden
	// by the game startup or another console command
	Cvar_Set( "nextmap", "map_restart 0");
//	Cvar_Set( "nextmap", va("map %s", server) );

	for (i=0 ; i<sv_maxclients->integer ; i++) {
		// save when the server started for each client already connected
		if (svs.clients[i].state >= CS_CONNECTED) {
			svs.clients[i].oldServerTime = svs.time;
		}
	}

	// wipe the entire per-level structure
	SV_ClearServer();
	for ( i = 0 ; i < MAX_CONFIGSTRINGS ; i++ ) {
		sv.configstrings[i] = CopyString("");
	}

	//rww - RAGDOLL_BEGIN
	re->G2API_SetTime(sv.time,0);
	//rww - RAGDOLL_END

	// make sure we are not paused
	Cvar_Set("cl_paused", "0");

	// get a new checksum feed and restart the file system
	srand(Com_Milliseconds());
	sv.checksumFeed = ( ((int) rand() << 16) ^ rand() ) ^ Com_Milliseconds();
	FS_Restart( sv.checksumFeed );

	CM_LoadMap( va("maps/%s.bsp", server), qfalse, &checksum );

	SV_SendMapChange();

	// set serverinfo visible name
	Cvar_Set( "mapname", server );

	Cvar_Set( "sv_mapChecksum", va("%i",checksum) );

	// serverid should be different each time
	sv.serverId = com_frameTime;
	sv.restartedServerId = sv.serverId; // I suppose the init here is just to be safe
	Cvar_Set( "sv_serverid", va("%i", sv.serverId ) );

	time( &sv.realMapTimeStarted );
	sv.demosPruned = qfalse;

	// clear physics interaction links
	SV_ClearWorld ();

	// media configstring setting should be done during
	// the loading stage, so connected clients don't have
	// to load during actual gameplay
	sv.state = SS_LOADING;

	// load and spawn all other entities
	SV_InitGameProgs();

	// don't allow a map_restart if game is modified
	sv_gametype->modified = qfalse;

	// run a few frames to allow everything to settle
	for ( i = 0 ;i < 3 ; i++ ) {
		//rww - RAGDOLL_BEGIN
		re->G2API_SetTime(sv.time,0);
		//rww - RAGDOLL_END
		GVM_RunFrame( sv.time );
		SV_BotFrame( sv.time );
		sv.time += 100;
		svs.time += 100;
	}
	//rww - RAGDOLL_BEGIN
	re->G2API_SetTime(sv.time,0);
	//rww - RAGDOLL_END

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

	for (i=0 ; i<sv_maxclients->integer ; i++) {
		// send the new gamestate to all connected clients
		if (svs.clients[i].state >= CS_CONNECTED) {
			char	*denied;

			if ( svs.clients[i].netchan.remoteAddress.type == NA_BOT ) {
				if ( killBots ) {
					SV_DropClient( &svs.clients[i], "" );
					continue;
				}
				isBot = qtrue;
			}
			else {
				isBot = qfalse;
			}

			// connect the client again
			denied = GVM_ClientConnect( i, qfalse, isBot );	// firstTime = qfalse
			if ( denied ) {
				// this generally shouldn't happen, because the client
				// was connected before the level change
				SV_DropClient( &svs.clients[i], denied );
			} else {
				if( !isBot ) {
					// when we get the next packet from a connected client,
					// the new gamestate will be sent
					svs.clients[i].state = CS_CONNECTED;
				}
				else {
					client_t		*client;
					sharedEntity_t	*ent;

					client = &svs.clients[i];
					client->state = CS_ACTIVE;
					ent = SV_GentityNum( i );
					ent->s.number = i;
					client->gentity = ent;

					client->deltaMessage = -1;
					client->nextSnapshotTime = svs.time;	// generate a snapshot immediately

					GVM_ClientBegin( i );
				}
			}
		}
	}

	// run another frame to allow things to look at all the players
	GVM_RunFrame( sv.time );
	SV_BotFrame( sv.time );
	sv.time += 100;
	svs.time += 100;
	//rww - RAGDOLL_BEGIN
	re->G2API_SetTime(sv.time,0);
	//rww - RAGDOLL_END

	if ( sv_pure->integer ) {
		// the server sends these to the clients so they will only
		// load pk3s also loaded at the server
		p = FS_LoadedPakChecksums();
		Cvar_Set( "sv_paks", p );
		if (strlen(p) == 0) {
			Com_Printf( "WARNING: sv_pure set but no PK3 files loaded\n" );
		}
		p = FS_LoadedPakNames();
		Cvar_Set( "sv_pakNames", p );

		// if a dedicated pure server we need to touch the cgame because it could be in a
		// seperate pk3 file and the client will need to load the latest cgame.qvm
		if ( com_dedicated->integer ) {
			SV_TouchCGame();
		}
	}
	else {
		Cvar_Set( "sv_paks", "" );
		Cvar_Set( "sv_pakNames", "" );
	}
	// the server sends these to the clients so they can figure
	// out which pk3s should be auto-downloaded
	p = FS_ReferencedPakChecksums();
	Cvar_Set( "sv_referencedPaks", p );
	p = FS_ReferencedPakNames();
	Cvar_Set( "sv_referencedPakNames", p );

	// save systeminfo and serverinfo strings
	Q_strncpyz( systemInfo, Cvar_InfoString_Big( CVAR_SYSTEMINFO ), sizeof( systemInfo ) );
	cvar_modifiedFlags &= ~CVAR_SYSTEMINFO;
	SV_SetConfigstring( CS_SYSTEMINFO, systemInfo );

	SV_SetConfigstring( CS_SERVERINFO, Cvar_InfoString( CVAR_SERVERINFO ) );
	cvar_modifiedFlags &= ~CVAR_SERVERINFO;

	// any media configstring setting now should issue a warning
	// and any configstring changes should be reliably transmitted
	// to all clients
	sv.state = SS_GAME;

	// send a heartbeat now so the master will get up to date info
	SV_Heartbeat_f();

	Hunk_SetMark();

	/* MrE: 2000-09-13: now called in CL_DownloadsComplete
	// don't call when running dedicated
	if ( !com_dedicated->integer ) {
		// note that this is called after setting the hunk mark with Hunk_SetMark
		CL_StartHunkUsers();
	}
	*/

	for ( client_t *client = svs.clients; client - svs.clients < sv_maxclients->integer; client++) {
		// bots will not request gamestate, so it must be manually sent
		// cannot do this above where it says it will because mapname is not set at that time
		if ( client->netchan.remoteAddress.type == NA_BOT && client->demo.demorecording ) {
			SV_SendClientGameState( client );
		}
	}

	SV_BeginAutoRecordDemos();
}
Exemple #7
0
/**
 * @brief Change the server to a new map, taking all connected
 * clients along with it.
 * This is NOT called for map_restart
 */
void SV_SpawnServer(char *server)
{
	int        i;
	int        checksum;
	qboolean   isBot;
	const char *p;

	// broadcast a level change to all connected clients
	if (svs.clients && !com_errorEntered)
	{
		SV_FinalCommand("spawnserver", qfalse);
	}

	// shut down the existing game if it is running
	SV_ShutdownGameProgs();

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

	// if not running a dedicated server CL_MapLoading will connect the client to the server
	// also print some status stuff
	CL_MapLoading();

	// make sure all the client stuff is unloaded
	CL_ShutdownAll();

	// clear the whole hunk because we're (re)loading the server
	Hunk_Clear();

	// clear collision map data
	CM_ClearMap();

	// wipe the entire per-level structure
	SV_ClearServer();

	// main zone should be pretty much emtpy at this point
	// except for file system data and cached renderer data
	Z_LogHeap();

	// allocate empty config strings
	for (i = 0 ; i < MAX_CONFIGSTRINGS ; i++)
	{
		sv.configstrings[i]         = CopyString("");
		sv.configstringsmodified[i] = qfalse;
	}

	// init client structures and svs.numSnapshotEntities
	if (!Cvar_VariableValue("sv_running"))
	{
		SV_Startup();
	}
	else
	{
		// check for maxclients change
		if (sv_maxclients->modified)
		{
			// If we are playing/waiting to play/waiting to stop a demo, we use a specialized function that will move real clients slots (so that democlients will be put to their original slots they were affected at the time of the real game)
			if (sv.demoState == DS_WAITINGPLAYBACK || sv.demoState == DS_PLAYBACK || sv.demoState == DS_WAITINGSTOP)
			{
				SV_DemoChangeMaxClients();
			}
			else
			{
				SV_ChangeMaxClients();
			}
		}
	}

	// clear pak references
	FS_ClearPakReferences(0);

	// allocate the snapshot entities on the hunk
	svs.snapshotEntities     = Hunk_Alloc(sizeof(entityState_t) * svs.numSnapshotEntities, h_high);
	svs.nextSnapshotEntities = 0;

	// toggle the server bit so clients can detect that a
	// server has changed
	svs.snapFlagServerBit ^= SNAPFLAG_SERVERCOUNT;

	// set nextmap to the same map, but it may be overriden
	// by the game startup or another console command
	Cvar_Set("nextmap", "map_restart 0");

	SV_SetExpectedHunkUsage(va("maps/%s.bsp", server));

	// make sure we are not paused
	Cvar_Set("cl_paused", "0");

	// get a new checksum feed and restart the file system
	srand(Sys_Milliseconds());
	sv.checksumFeed = (((int) rand() << 16) ^ rand()) ^ Sys_Milliseconds();

	// only comment out when you need a new pure checksum string and it's associated random feed
	// Com_DPrintf("SV_SpawnServer checksum feed: %p\n", sv.checksumFeed);

	FS_Restart(sv.checksumFeed);

	CM_LoadMap(va("maps/%s.bsp", server), qfalse, &checksum);

	// set serverinfo visible name
	Cvar_Set("mapname", server);

	Cvar_Set("sv_mapChecksum", va("%i", checksum));

	// serverid should be different each time
	sv.serverId             = com_frameTime;
	sv.restartedServerId    = sv.serverId;
	sv.checksumFeedServerId = sv.serverId;
	Cvar_Set("sv_serverid", va("%i", sv.serverId));

	// clear physics interaction links
	SV_ClearWorld();

	// media configstring setting should be done during
	// the loading stage, so connected clients don't have
	// to load during actual gameplay
	sv.state = SS_LOADING;

	// load and spawn all other entities
	SV_InitGameProgs();

	// run a few frames to allow everything to settle
	for (i = 0 ; i < GAME_INIT_FRAMES ; i++)
	{
		VM_Call(gvm, GAME_RUN_FRAME, svs.time);
		svs.time += FRAMETIME;
	}

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

	for (i = 0 ; i < sv_maxclients->integer ; i++)
	{
		// send the new gamestate to all connected clients
		if (svs.clients[i].state >= CS_CONNECTED)
		{
			char *denied;

			if (svs.clients[i].netchan.remoteAddress.type == NA_BOT)
			{
				isBot = qtrue;
			}
			else
			{
				isBot = qfalse;
			}

			// connect the client again
			denied = VM_ExplicitArgPtr(gvm, VM_Call(gvm, GAME_CLIENT_CONNECT, i, qfalse, isBot));       // firstTime = qfalse
			if (denied)
			{
				// this generally shouldn't happen, because the client
				// was connected before the level change
				SV_DropClient(&svs.clients[i], denied);
			}
			else
			{
				if (!isBot)
				{
					// when we get the next packet from a connected client,
					// the new gamestate will be sent
					svs.clients[i].state = CS_CONNECTED;
				}
				else
				{
					client_t       *client;
					sharedEntity_t *ent;

					client          = &svs.clients[i];
					client->state   = CS_ACTIVE;
					ent             = SV_GentityNum(i);
					ent->s.number   = i;
					client->gentity = ent;

					client->deltaMessage     = -1;
					client->nextSnapshotTime = svs.time;    // generate a snapshot immediately

					VM_Call(gvm, GAME_CLIENT_BEGIN, i);
				}
			}
		}
	}

	// run another frame to allow things to look at all the players
	VM_Call(gvm, GAME_RUN_FRAME, svs.time);

	svs.time += FRAMETIME;

	if (sv_pure->integer)
	{
		// the server sends these to the clients so they will only
		// load pk3s also loaded at the server
		p = FS_LoadedPakChecksums();
		Cvar_Set("sv_paks", p);
		if (strlen(p) == 0)
		{
			Com_Printf("WARNING: sv_pure set but no PK3 files loaded\n");
		}
		p = FS_LoadedPakNames();
		Cvar_Set("sv_pakNames", p);
	}
	else
	{
		Cvar_Set("sv_paks", "");
		Cvar_Set("sv_pakNames", "");
	}
	// the server sends these to the clients so they can figure
	// out which pk3s should be auto-downloaded
	// NOTE: we consider the referencedPaks as 'required for operation'

	// we want the server to reference the mod_bin pk3 that the client is expected to load from
	SV_TouchCGameDLL();

	p = FS_ReferencedPakChecksums();
	Cvar_Set("sv_referencedPaks", p);
	p = FS_ReferencedPakNames();
	Cvar_Set("sv_referencedPakNames", p);

	// save systeminfo and serverinfo strings
	cvar_modifiedFlags &= ~CVAR_SYSTEMINFO;
	SV_SetConfigstring(CS_SYSTEMINFO, Cvar_InfoString_Big(CVAR_SYSTEMINFO));

	SV_SetConfigstring(CS_SERVERINFO, Cvar_InfoString(CVAR_SERVERINFO | CVAR_SERVERINFO_NOUPDATE));
	cvar_modifiedFlags &= ~CVAR_SERVERINFO;

	SV_SetConfigstring(CS_WOLFINFO, Cvar_InfoString(CVAR_WOLFINFO));
	cvar_modifiedFlags &= ~CVAR_WOLFINFO;

	// any media configstring setting now should issue a warning
	// and any configstring changes should be reliably transmitted
	// to all clients
	sv.state = SS_GAME;

	// send a heartbeat now so the master will get up to date info
	if (sv_advert->integer & SVA_MASTER)
	{
		SV_Heartbeat_f();
	}
	else // let admin's know it's disabled
	{
		Com_Printf("Not sending heartbeats to master servers - disabled by sv_advert.\n");
	}

	Hunk_SetMark();

	SV_UpdateConfigStrings();

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

	// start recording a demo
	if (sv_autoDemo->integer)
	{
		SV_DemoAutoDemoRecord();
	}
}
Exemple #8
0
/*
================
SV_SpawnServer

Change the server to a new map, taking all connected
clients along with it.
This is NOT called for map_restart
================
*/
void SV_SpawnServer( char *server, qboolean killBots ) {
	int			i;
	int			checksum;
	char		systemInfo[16384];
	const char	*p;

	// shut down the existing game if it is running
	SV_ShutdownGameProgs();

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

	// if not running a dedicated server CL_MapLoading will connect the client to the server
	// also print some status stuff
	CL_MapLoading();

	// make sure all the client stuff is unloaded
	CL_ShutdownAll();

	// clear the whole hunk because we're (re)loading the server
	Hunk_Clear();

#ifndef DEDICATED
	// Restart renderer
	CL_StartHunkUsers( qtrue );
#endif

	// clear collision map data
	CM_ClearMap();

	// init client structures and svs.numSnapshotEntities 
	if ( !Cvar_VariableValue("sv_running") ) {
		SV_Startup();
	} else {
		// check for maxclients or democlients change
		if ( sv_maxclients->modified || sv_democlients->modified ) {
			SV_ChangeMaxClients();
		}
	}

	// clear pak references
	FS_ClearPakReferences(0);

	// allocate the snapshot entities on the hunk
	svs.snapshotEntities = Hunk_Alloc( sizeof(entityState_t)*svs.numSnapshotEntities, h_high );
	svs.nextSnapshotEntities = 0;

	// toggle the server bit so clients can detect that a
	// server has changed
	svs.snapFlagServerBit ^= SNAPFLAG_SERVERCOUNT;

	for (i=0 ; i<sv_maxclients->integer ; i++) {
		// save when the server started for each client already connected
		if (svs.clients[i].state >= CS_CONNECTED) {
			svs.clients[i].oldServerTime = sv.time;
		}
	}

	// wipe the entire per-level structure
	SV_ClearServer();
	for ( i = 0 ; i < MAX_CONFIGSTRINGS ; i++ ) {
		sv.configstrings[i] = CopyString("");
	}

	// make sure we are not paused
	Cvar_Set("cl_paused", "0");

	// get a new checksum feed and restart the file system
	sv.checksumFeed = ( ((int) rand() << 16) ^ rand() ) ^ Com_Milliseconds();
	FS_Restart( sv.checksumFeed );

	CM_LoadMap( va("maps/%s.bsp", server), qfalse, &checksum );

	// set serverinfo visible name
	Cvar_Set( "mapname", server );

	Cvar_Set( "sv_mapChecksum", va("%i",checksum) );

	// serverid should be different each time
	sv.serverId = com_frameTime;
	sv.restartedServerId = sv.serverId; // I suppose the init here is just to be safe
	sv.checksumFeedServerId = sv.serverId;
	Cvar_Set( "sv_serverid", va("%i", sv.serverId ) );

	// clear physics interaction links
	SV_ClearWorld ();
	
	// media configstring setting should be done during
	// the loading stage, so connected clients don't have
	// to load during actual gameplay
	sv.state = SS_LOADING;

	// load and spawn all other entities
	SV_InitGameProgs();

	// run a few frames to allow everything to settle
	for (i = 0;i < 3; i++)
	{
		VM_Call (gvm, GAME_RUN_FRAME, sv.time);
		sv.time += 100;
		svs.time += 100;
	}

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

	for (i=0 ; i<sv_maxclients->integer ; i++) {
		// send the new gamestate to all connected clients
		if (svs.clients[i].state >= CS_CONNECTED) {
			char	*denied;

			// connect the client again
			denied = VM_ExplicitArgPtr( gvm, VM_Call( gvm, GAME_CLIENT_CONNECT, i, qfalse ) );	// firstTime = qfalse
			if ( denied ) {
				// this generally shouldn't happen, because the client
				// was connected before the level change
				SV_DropClient( &svs.clients[i], denied );
			} else {
				// when we get the next packet from a connected client,
				// the new gamestate will be sent
				svs.clients[i].state = CS_CONNECTED;
			}
		}
	}	

	// run another frame to allow things to look at all the players
	VM_Call (gvm, GAME_RUN_FRAME, sv.time);
	sv.time += 100;
	svs.time += 100;

	// if a dedicated server we need to touch the cgame because it could be in a
	// seperate pk3 file and the client will need to load the latest cgame.qvm
	if ( com_dedicated->integer ) {
		SV_TouchCGame();
	}

	// the server sends these to the clients so they will only
	// load pk3s also loaded at the server
	Cvar_Set( "sv_paks", sv_pure->integer ? FS_LoadedPakChecksums() : "" );
	Cvar_Set( "sv_pakNames", sv_pure->integer ? FS_LoadedPakNames() : "" );

	// the server sends these to the clients so they can figure
	// out which pk3s should be auto-downloaded
	p = FS_ReferencedPakChecksums();
	Cvar_Set( "sv_referencedPaks", p );
	p = FS_ReferencedPakNames();
	Cvar_Set( "sv_referencedPakNames", p );

	// save systeminfo and serverinfo strings
	Q_strncpyz( systemInfo, Cvar_InfoString_Big( CVAR_SYSTEMINFO ), sizeof( systemInfo ) );
	cvar_modifiedFlags &= ~CVAR_SYSTEMINFO;
	SV_SetConfigstring( CS_SYSTEMINFO, systemInfo );

	SV_SetConfigstring( CS_SERVERINFO, Cvar_InfoString( CVAR_SERVERINFO ) );
	cvar_modifiedFlags &= ~CVAR_SERVERINFO;

	// any media configstring setting now should issue a warning
	// and any configstring changes should be reliably transmitted
	// to all clients
	sv.state = SS_GAME;

	// send a heartbeat now so the master will get up to date info
	SV_Heartbeat_f();

	Hunk_SetMark();

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

	// start recording a demo
	if ( sv_autoDemo->integer ) {
		qtime_t	now;
		Com_RealTime( &now );
		Cbuf_AddText( va( "demo_record %04d%02d%02d%02d%02d%02d-%s\n",
			1900 + now.tm_year,
			1 + now.tm_mon,
			now.tm_mday,
			now.tm_hour,
			now.tm_min,
			now.tm_sec,
			server ) );
	}
}
Exemple #9
0
void DL_End( CURLcode res, CURLMcode resm )
{
	CURLMsg *msg;
	int msgs;

	if( dl_verbose->integer == 0 && dl_showprogress->integer == 2 && !curlm )
		Com_Printf( "\n" );
	
	if( curlm )
	{	
		// res = final download result
		while( ( msg = curl_multi_info_read( curlm, &msgs ) ) )
		{
			if( msg->msg != CURLMSG_DONE )
			{
				if( dl_error[0] == '\0' )
					Q_strncpyz( dl_error, "Download Interrupted.", sizeof(dl_error) );
			}
			else if( msg->easy_handle == curl )
			{
				if( msg->data.result != CURLE_OK );
					res = msg->data.result;
			}
			else
			{
				Com_Printf( "Invalid cURL handle.\n" );
			}
		}

		curl_multi_cleanup( curlm );
		curlm = NULL;		
	}

	if( curl )
	{
		curl_easy_cleanup( curl );
		curl = NULL;
	}

	// get possible error messages
	if( !*dl_error && res != CURLE_OK )
		Q_strncpyz( dl_error, curl_easy_strerror(res), sizeof(dl_error) );
	if( !*dl_error && resm != CURLM_OK )
		Q_strncpyz( dl_error, curl_multi_strerror(resm), sizeof(dl_error) );
	if( !*dl_error && !f )
		Q_strncpyz( dl_error, "File is not opened.", sizeof(dl_error) );

	if (f) {
		FS_FCloseFile(f);
		f = 0;
		if (!*dl_error) {	// download succeeded
			char dest[MAX_OSPATH];
			Com_Printf("Download complete, restarting filesystem.\n");
			Q_strncpyz(dest, path, strlen(path)-3);	// -4 +1 for the trailing \0
			Q_strcat(dest, sizeof(dest), ".pk3");
			if (!FS_FileExists(dest)) {
				FS_SV_Rename(path, dest);
				FS_Restart(clc.checksumFeed);
				if (dl_showmotd->integer && *motd) {
					Com_Printf("Server motd: %s\n", motd);
				}
			} else {
				// normally such errors should be caught upon starting the transfer. Anyway better do
				// it here again - the filesystem might have changed, plus this may help contain some
				// bugs / exploitable flaws in the code.
				Com_Printf("Failed to copy downloaded file to its location - file already exists.\n");
				FS_HomeRemove(path);
			}
		} else {
			FS_HomeRemove(path);
		}
	}

	Cvar_Set( "cl_downloadName", "" );  // hide the ui downloading screen
	Cvar_SetValue( "cl_downloadSize", 0 );
	Cvar_SetValue( "cl_downloadCount", 0 );
	Cvar_SetValue( "cl_downloadTime", 0 );
	Cvar_Set( "cl_downloadMotd", "" );

	if( *dl_error )
	{
		if( clc.state == CA_CONNECTED )
			Com_Error( ERR_DROP, "%s\n", dl_error ); // download error while connecting, can not continue loading
		else
			Com_Printf( "%s\n", dl_error ); // download error while in game, do not disconnect

		*dl_error = '\0';
	}
	else
	{
		if (strlen(Cvar_VariableString("cl_downloadDemo"))) {
			Cbuf_AddText( va("demo %s\n", Cvar_VariableString("cl_downloadDemo") ) );
		// download completed, request new gamestate to check possible new map if we are not already in game
		} else if( clc.state == CA_CONNECTED)
			CL_AddReliableCommand( "donedl", qfalse); // get new gamestate info from server
	}
}
Exemple #10
0
void SV_SpawnServer( char *server, qboolean killBots, ForceReload_e eForceReload ) {
	int			i;
	int			checksum;
	qboolean	isBot;
	char		systemInfo[16384];
	const char	*p;

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

	SV_SendMapChange();

	RE_RegisterMedia_LevelLoadBegin(server, eForceReload);

	// shut down the existing game if it is running
	SV_ShutdownGameProgs();

	FixGhoul2InfoLeaks(false,true);

/*
Ghoul2 Insert Start
*/
 	// de allocate the snapshot entities
	if (svs.snapshotEntities)
	{
		delete[] svs.snapshotEntities;
		svs.snapshotEntities = NULL;
	}
/*
Ghoul2 Insert End
*/

	SV_SendMapChange();

	// if not running a dedicated server CL_MapLoading will connect the client to the server
	// also print some status stuff
	CL_MapLoading();

#ifndef DEDICATED
	// make sure all the client stuff is unloaded
	CL_ShutdownAll();
#endif

	CM_ClearMap();

	// clear the whole hunk because we're (re)loading the server
	Hunk_Clear();

/*
Ghoul2 Insert Start
*/
	// clear out those shaders, images and Models as long as this
	// isnt a dedicated server.
	if ( !com_dedicated->integer )
	{
#ifndef DEDICATED
		R_InitImages();

		R_InitShaders();

		R_ModelInit();
#endif
	}
	else
	{
		R_SVModelInit();

#ifdef G2_COLLISION_ENABLED
		if (!G2VertSpaceServer)
		{
			G2VertSpaceServer = new CMiniHeap(G2_VERT_SPACE_SERVER_SIZE * 1024);
		}
#endif
	}

	SV_SendMapChange();

	// init client structures and svs.numSnapshotEntities
	if ( !Cvar_VariableValue("sv_running") ) {
		SV_Startup();
	} else {
		// check for maxclients change
		if ( sv_maxclients->modified ) {
			SV_ChangeMaxClients();
		}
	}

	SV_SendMapChange();

	// clear pak references
	FS_ClearPakReferences(0);

/*
Ghoul2 Insert Start
*/
	// allocate the snapshot entities on the hunk
//	svs.snapshotEntities = (struct entityState_s *)Hunk_Alloc( sizeof(entityState_t)*svs.numSnapshotEntities, h_high );
	svs.nextSnapshotEntities = 0;

	// allocate the snapshot entities
	svs.snapshotEntities = new entityState_s[svs.numSnapshotEntities];
	// we CAN afford to do this here, since we know the STL vectors in Ghoul2 are empty
	memset(svs.snapshotEntities, 0, sizeof(entityState_t)*svs.numSnapshotEntities);

/*
Ghoul2 Insert End
*/

	// toggle the server bit so clients can detect that a
	// server has changed
	svs.snapFlagServerBit ^= SNAPFLAG_SERVERCOUNT;

	// set nextmap to the same map, but it may be overriden
	// by the game startup or another console command
	Cvar_Set( "nextmap", "map_restart 0");
//	Cvar_Set( "nextmap", va("map %s", server) );

	// wipe the entire per-level structure
	SV_ClearServer();
	for ( i = 0 ; i < MAX_CONFIGSTRINGS ; i++ ) {
		sv.configstrings[i] = CopyString("");
	}

	// decide which serverversion to host
	mv_serverversion = Cvar_Get("mv_serverversion", "1.04", CVAR_ARCHIVE | CVAR_LATCH | CVAR_GLOBAL);
	if (FS_AllPath_Base_FileExists("assets5.pk3") && (!strcmp(mv_serverversion->string, "auto") || !strcmp(mv_serverversion->string, "1.04"))) {
		Com_Printf("serverversion set to 1.04\n");
		MV_SetCurrentGameversion(VERSION_1_04);
	}
	else if (FS_AllPath_Base_FileExists("assets2.pk3") && (!strcmp(mv_serverversion->string, "auto") || !strcmp(mv_serverversion->string, "1.03"))) {
		Com_Printf("serverversion set to 1.03\n");
		MV_SetCurrentGameversion(VERSION_1_03);
	} else {
		Com_Printf("serverversion set to 1.02\n");
		MV_SetCurrentGameversion(VERSION_1_02);
	}

	Cvar_Set("protocol", va("%i", MV_GetCurrentProtocol()));

	// make sure we are not paused
	Cvar_Set("cl_paused", "0");

	// get a new checksum feed and restart the file system
	srand(Com_Milliseconds());
	sv.checksumFeed = ( ((int) rand() << 16) ^ rand() ) ^ Com_Milliseconds();

	FS_PureServerSetReferencedPaks("", "");
	FS_Restart( sv.checksumFeed );

	CM_LoadMap( va("maps/%s.bsp", server), qfalse, &checksum );

	SV_SendMapChange();

	// set serverinfo visible name
	Cvar_Set( "mapname", server );

	Cvar_Set( "sv_mapChecksum", va("%i",checksum) );

	// serverid should be different each time
	sv.serverId = com_frameTime;
	sv.restartedServerId = sv.serverId;
	Cvar_Set( "sv_serverid", va("%i", sv.serverId ) );

	// clear physics interaction links
	SV_ClearWorld ();

	// media configstring setting should be done during
	// the loading stage, so connected clients don't have
	// to load during actual gameplay
	sv.state = SS_LOADING;

	// load and spawn all other entities
	SV_InitGameProgs();

	// don't allow a map_restart if game is modified
	sv_gametype->modified = qfalse;

	// run a few frames to allow everything to settle
	for ( i = 0 ;i < 3 ; i++ ) {
		VM_Call( gvm, GAME_RUN_FRAME, svs.time );
		SV_BotFrame( svs.time );
		svs.time += 100;
	}

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

	for (i=0 ; i<sv_maxclients->integer ; i++) {
		// send the new gamestate to all connected clients
		if (svs.clients[i].state >= CS_CONNECTED) {
			char	*denied;

			if ( svs.clients[i].netchan.remoteAddress.type == NA_BOT ) {
				if ( killBots ) {
					SV_DropClient( &svs.clients[i], "" );
					continue;
				}
				isBot = qtrue;
			}
			else {
				isBot = qfalse;
			}

			// connect the client again
			denied = (char *)VM_ExplicitArgPtr( gvm, VM_Call( gvm, GAME_CLIENT_CONNECT, i, qfalse, isBot ) );	// firstTime = qfalse
			if ( denied ) {
				// this generally shouldn't happen, because the client
				// was connected before the level change
				SV_DropClient( &svs.clients[i], denied );
			} else {
				if( !isBot ) {
					// when we get the next packet from a connected client,
					// the new gamestate will be sent
					svs.clients[i].state = CS_CONNECTED;
				}
				else {
					client_t		*client;
					sharedEntity_t	*ent;

					client = &svs.clients[i];
					client->state = CS_ACTIVE;
					ent = SV_GentityNum( i );
					ent->s.number = i;
					client->gentity = ent;

					client->deltaMessage = -1;
					client->nextSnapshotTime = svs.time;	// generate a snapshot immediately

					VM_Call( gvm, GAME_CLIENT_BEGIN, i );
				}
			}
		}
	}

	// run another frame to allow things to look at all the players
	VM_Call( gvm, GAME_RUN_FRAME, svs.time );
	SV_BotFrame( svs.time );
	svs.time += 100;

	if ( sv_pure->integer ) {
		// the server sends these to the clients so they will only
		// load pk3s also loaded at the server
		p = FS_LoadedPakChecksums();
		Cvar_Set( "sv_paks", p );
		if (strlen(p) == 0) {
			Com_Printf( "WARNING: sv_pure set but no PK3 files loaded\n" );
		}
		p = FS_LoadedPakNames();
		Cvar_Set( "sv_pakNames", p );

		// if a dedicated pure server we need to touch the cgame because it could be in a
		// seperate pk3 file and the client will need to load the latest cgame.qvm
		if ( com_dedicated->integer ) {
			SV_TouchCGame();
		}
	}
	else {
		Cvar_Set( "sv_paks", "" );
		Cvar_Set( "sv_pakNames", "" );
	}
	// the server sends these to the clients so they can figure
	// out which pk3s should be auto-downloaded
	p = FS_ReferencedPakChecksums();
	Cvar_Set( "sv_referencedPaks", p );
	p = FS_ReferencedPakNames();
	Cvar_Set( "sv_referencedPakNames", p );

	// save systeminfo and serverinfo strings
	Q_strncpyz( systemInfo, Cvar_InfoString_Big( CVAR_SYSTEMINFO ), sizeof( systemInfo ) );
	cvar_modifiedFlags &= ~CVAR_SYSTEMINFO;
	SV_SetConfigstring( CS_SYSTEMINFO, systemInfo );

	SV_SetConfigstring( CS_SERVERINFO, Cvar_InfoString( CVAR_SERVERINFO ) );
	cvar_modifiedFlags &= ~CVAR_SERVERINFO;

	// any media configstring setting now should issue a warning
	// and any configstring changes should be reliably transmitted
	// to all clients
	sv.state = SS_GAME;

	// send a heartbeat now so the master will get up to date info
	SV_Heartbeat_f();

	Hunk_SetMark();

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

	/* MrE: 2000-09-13: now called in CL_DownloadsComplete
	// don't call when running dedicated
	if ( !com_dedicated->integer ) {
		// note that this is called after setting the hunk mark with Hunk_SetMark
		CL_StartHunkUsers();
	}
	*/

	// shutdown webserver
	if (mgsrv && ((mv_httpdownloads->latchedString && !atoi(mv_httpdownloads->latchedString)) || mv_httpserverport->latchedString)) {
		SV_MV_Websrv_Shutdown();
	}

	// here because latched
	mv_httpdownloads = Cvar_Get("mv_httpdownloads", "0", CVAR_SERVERINFO | CVAR_ARCHIVE | CVAR_LATCH);
	mv_httpserverport = Cvar_Get("mv_httpserverport", "0", CVAR_ARCHIVE | CVAR_LATCH);

	// start webserver
	if (mv_httpdownloads->integer) {
		if (Q_stristr(mv_httpserverport->string, "http://")) {
			Com_Printf("HTTP Downloads: redirecting to %s\n", mv_httpserverport->string);
		} else if (!mgsrv) {
			const char *err = NULL;
			int port;

			mgsrv = mg_create_server(NULL, SV_MV_Websrv_Request_ExtThread);
			mg_set_option(mgsrv, "document_root", Cvar_Get("fs_basepath", "", 0)->string);

			if (mv_httpserverport->integer) {
				port = mv_httpserverport->integer;
				err = mg_set_option(mgsrv, "listening_port", va("%i", port));
			} else {
				for (port = HTTPSRV_STDPORT; port <= HTTPSRV_STDPORT + 15; port++) {
					err = mg_set_option(mgsrv, "listening_port", va("%i", port));
					if (!err) {
						break;
					}
				}
			}

			if (!err) {
				sv.http_port = port;
				Com_Printf("HTTP Downloads: webserver running on port %i...\n", port);
			} else {
				Com_Error(ERR_DROP, "HTTP Downloads: webserver startup failed: %s", err);
			}

			mg_start_thread(SV_MV_Websrv_Loop_ExtThread, mgsrv);
		}
	}
}
Exemple #11
0
void SV_SpawnServer( char *mapname, qboolean killBots, cb_context_t *after ) {
	int                i;
	cb_context_t       *context;
	spawnserver_data_t *data;

	// shut down the existing game if it is running
	SV_ShutdownGameProgs();

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

	// if not running a dedicated server CL_MapLoading will connect the client to the server
	// also print some status stuff
	CL_MapLoading();

	// make sure all the client stuff is unloaded
	CL_ShutdownAll(qfalse);

	// clear the whole hunk because we're (re)loading the server
	Hunk_Clear();

	// clear collision map data
	CM_ClearMap();

	// init client structures and svs.numSnapshotEntities 
	if ( !Cvar_VariableValue("sv_running") ) {
		SV_Startup();
	} else {
		// check for maxclients change
		if ( sv_maxclients->modified ) {
			SV_ChangeMaxClients();
		}
	}

	// clear pak references
	FS_ClearPakReferences(0);

	// allocate the snapshot entities on the hunk
	svs.snapshotEntities = Hunk_Alloc( sizeof(entityState_t)*svs.numSnapshotEntities, h_high );
	svs.nextSnapshotEntities = 0;

	// toggle the server bit so clients can detect that a
	// server has changed
	svs.snapFlagServerBit ^= SNAPFLAG_SERVERCOUNT;

	// set nextmap to the same map, but it may be overriden
	// by the game startup or another console command
	Cvar_Set( "nextmap", "map_restart 0");
//	Cvar_Set( "nextmap", va("map %s", server) );

	for (i=0 ; i<sv_maxclients->integer ; i++) {
		// save when the server started for each client already connected
		if (svs.clients[i].state >= CS_CONNECTED) {
			svs.clients[i].oldServerTime = sv.time;
		}
	}

	// wipe the entire per-level structure
	SV_ClearServer();
	for ( i = 0 ; i < MAX_CONFIGSTRINGS ; i++ ) {
		sv.configstrings[i] = CopyString("");
	}

	// make sure we are not paused
	Cvar_Set("cl_paused", "0");

	// set serverinfo visible name
	Cvar_Set("mapname", mapname);

	// get a new checksum feed and restart the file system
	sv.checksumFeed = ( ((int) rand() << 16) ^ rand() ) ^ Com_Milliseconds();

	// Setup callback context.
	context = cb_create_context( SV_SpawnServer_after_FS_Restart, spawnserver_data_t );
	data = (spawnserver_data_t *)context->data;
	Q_strncpyz(data->mapname, mapname, MAX_QPATH);
	data->killBots = killBots;
	data->after = after;

	FS_Restart( sv.checksumFeed, context );
}
void Sec_Update( qboolean getbasefiles ){
    char buff[SEC_UPDATE_INITIALBUFFSIZE];
    char *ptr,*ptr2, *testfile;
	char filepathbuf[MAX_OSPATH];
    char baseurl[1024];
    char name1[256],name2[256];
    sec_file_t files, *currFile = &files;
    qboolean dlExec = qfalse;
    int len;
    char hash[128];
    long unsigned size;
	ftRequest_t* filetransferobj;
	ftRequest_t* curfileobj;
	int transret;
	mvabuf;

	
    if(!Sec_Initialized()){
	return;
    }
    
#ifdef CAN_UPDATE
    Com_Printf("\n-----------------------------\n");
    Com_Printf(" CoD4X Auto Update\n");
    Com_Printf(" Current version: %g\n",SEC_VERSION);
    Com_Printf(" Current build: %d\n",BUILD_NUMBER);
    Com_Printf(" Current type: %s\n",SEC_TYPE == 's' ? "stable      " : "experimental");
    Com_Printf("-----------------------------\n\n");

    canupdate = Cvar_RegisterBool("allowupdating", qtrue, 0, "This enables autoupdating of CoD4 server with new versions.");

    if(getbasefiles == qtrue)
    {

        Com_sprintf(buff, sizeof(buff), "http://" SEC_UPDATE_HOST SEC_UPDATE_GETGROUNDVERSION);

    }else{

        if(canupdate->boolean == qfalse)
            return;

        Com_sprintf(buff, sizeof(buff), "http://" SEC_UPDATE_HOST SEC_UPDATE_GETVERSION);
    }
#else
    if(getbasefiles == qtrue)
    {
        Com_sprintf(buff, sizeof(buff), "http://" SEC_UPDATE_HOST SEC_UPDATE_GETGROUNDVERSION);
    }else{
        return;
    }
#endif
	
	filetransferobj = FileDownloadRequest( buff );

    if(filetransferobj == NULL){
		return;
    }

	do {
		transret = FileDownloadSendReceive( filetransferobj );
		usleep(20000);
	} while (transret == 0);

    if(transret < 0)
	{
		FileDownloadFreeRequest(filetransferobj);
		return;
    }
    /* Need to catch errors */
 //   FS_WriteFile("tmp.txt", va("%d", status), 1);

    // TODO: Do something with the status?

//    FS_WriteFile("tmp2.txt", packet.header, packet.headerLength);
//    FS_WriteFile("tmp3.txt", packet.content, packet.contentLength);
    if(filetransferobj->code <= 0){
		Com_PrintError("Receiving data. Error code: %d.\n", filetransferobj->code);
		FileDownloadFreeRequest(filetransferobj);
		return;
    }
    if(filetransferobj->code == 204){
		Com_Printf("\nServer is up to date.\n\n");
		FileDownloadFreeRequest(filetransferobj);
		return;
    }
    else if(filetransferobj->code != 200){
		Com_PrintWarning("The update server's malfunction.\nStatus code: %d.\n", filetransferobj->code);
		FileDownloadFreeRequest(filetransferobj);
		return;
    }

    Com_Memset(&files, 0, sizeof(files));

    /* We need to parse filenames etc */
    ptr = Sec_StrTok((char*)(filetransferobj->recvmsg.data + filetransferobj->headerLength),"\n",42); // Yes, 42.
    if(ptr == NULL || Q_stricmpn("baseurl: ", ptr, 9))
    {
	    Com_PrintWarning("Sec_Update: Corrupt data from update server. Update aborted.\n");
		FileDownloadFreeRequest(filetransferobj);
		return;
    }
    Q_strncpyz(baseurl, ptr +9, sizeof(baseurl));

    ptr = Sec_StrTok(NULL,"\n",42); // Yes, 42 again.

	while(ptr != NULL){
		
		currFile->next = Sec_GMalloc(sec_file_t,1);
		currFile = currFile->next;
		Com_Memset(currFile,0,sizeof(sec_file_t));
		ptr2 = strchr(ptr,' ');
		if(ptr2 == NULL){
			Com_PrintWarning("Sec_Update: Corrupt data from update server. Update aborted.\nDebug:\"%s\"\n",ptr);
			FileDownloadFreeRequest(filetransferobj);
			return;
		}
		*ptr2++ = 0;
		Q_strncpyz(currFile->path,ptr,sizeof(currFile->path));
		ptr = ptr2;
		ptr2 = strchr(ptr,' ');
		if(ptr2 == NULL){
			Com_PrintWarning("Sec_Update: Corrupt data from update server. Update aborted.\nDebug:\"%s\"\n",ptr);
			FileDownloadFreeRequest(filetransferobj);
			return;
		}
		*ptr2++ = 0;
		if(!isInteger(ptr, 0)){
			Com_PrintWarning("Sec_Update: Corrupt data from update server - size is not a number. Update aborted.\nDebug:\"%s\"\n",ptr);
			FileDownloadFreeRequest(filetransferobj);
			return;
		}
		currFile->size = atoi(ptr);
		Q_strncpyz(currFile->hash,ptr2,sizeof(currFile->hash));
		Q_strncpyz(currFile->name,currFile->path, sizeof(currFile->name));
		//printf("DEBUG: File to download: link: \"%s\", name: \"%s\", size: %d, hash: \"%s\"\n\n",file.path,file.name,file.size,file.hash);

		Com_sprintf(buff, sizeof(buff), SEC_UPDATE_DOWNLOAD(baseurl, currFile->path));
		
		curfileobj = FileDownloadRequest(buff);
		if(curfileobj == NULL)
		{
			FileDownloadFreeRequest(filetransferobj);
			return;	
		}

		Com_Printf("Downloading file: \"%s\"\n\n",currFile->name);

		do {
			transret = FileDownloadSendReceive( curfileobj );
			Com_Printf("%s", FileDownloadGenerateProgress( curfileobj ));
			usleep(20000);
		} while (transret == 0);
		
		Com_Printf("\n");

		if(transret < 0)
		{
			FileDownloadFreeRequest(curfileobj);
			FileDownloadFreeRequest(filetransferobj);
			return;
		}

		Q_strncpyz(buff,currFile->name, sizeof(buff));
		Q_strcat(buff, sizeof(buff),".new");

		if(curfileobj->code != 200){
			Com_PrintError("Downloading has failed! Error code: %d. Update aborted.\n", curfileobj->code);
			FileDownloadFreeRequest(filetransferobj);
			FileDownloadFreeRequest(curfileobj);
			return;
		}

		len = FS_SV_BaseWriteFile(buff, curfileobj->recvmsg.data + curfileobj->headerLength, curfileobj->contentLength);
		if(len != curfileobj->contentLength){

			len = FS_SV_HomeWriteFile(buff, curfileobj->recvmsg.data + curfileobj->headerLength, curfileobj->contentLength);
			if(len != curfileobj->contentLength)
			{
				Com_PrintError("Opening \"%s\" for writing! Update aborted.\n",buff);
				FileDownloadFreeRequest(filetransferobj);
				FileDownloadFreeRequest(curfileobj);
				return;
			}
		}

		ptr = Sec_StrTok(NULL,"\n",42); // Yes, 42 again.

		size = sizeof(hash);
		
		if(!Sec_HashMemory(SEC_HASH_SHA256, curfileobj->recvmsg.data + curfileobj->headerLength, curfileobj->contentLength, hash, &size,qfalse)){
			Com_PrintError("Hashing the file \"%s\". Error code: %s.\nUpdate aborted.\n",currFile->name,Sec_CryptErrStr(SecCryptErr));
			FileDownloadFreeRequest(filetransferobj);
			FileDownloadFreeRequest(curfileobj);
			return;
		}

		FileDownloadFreeRequest(curfileobj);
		
		if(!Q_strncmp(hash, currFile->hash, size)){
			Com_Printf("Successfully downloaded file \"%s\".\n", currFile->name);
		}
		else{
			Com_PrintError("File \"%s\" is corrupt!\nUpdate aborted.\n",currFile->name);
			Com_DPrintf("Hash: \"%s\", correct hash: \"%s\".\n",hash,currFile->hash);
			FileDownloadFreeRequest(filetransferobj);
			return;
		}
		
	}

	FileDownloadFreeRequest(filetransferobj);

    Com_Printf("All files downloaded successfully. Applying update...\n");

    currFile = files.next;
    do{
		Com_Printf("Updating file %s...\n", currFile->name);
		Q_strncpyz(name1, currFile->name, sizeof(name1));

		Q_strcat(name1, sizeof(name1), ".old");

		Q_strncpyz(name2, currFile->name, sizeof(name2));

		Q_strcat(name2, sizeof(name2), ".new");

		testfile = FS_SV_GetFilepath(name1, filepathbuf, sizeof(filepathbuf));
		if(testfile != NULL)
		{ // Old file exists, back it up
			FS_SV_BaseRemove( name1 );
			FS_SV_HomeRemove( name1 );
			testfile = FS_SV_GetFilepath(name1, filepathbuf, sizeof(filepathbuf));
			if(testfile != NULL)
			{
				Com_PrintWarning("Couldn't remove backup file: %s\n", testfile);
			}
			if(FS_SV_HomeFileExists(name1) == qtrue)
			{
				Com_PrintError("Couldn't remove backup file from fs_homepath: %s\n", name1);
			}
		}
		// Check if an old file exists with this name
		testfile = FS_SV_GetFilepath(currFile->name, filepathbuf, sizeof(filepathbuf));
		if(testfile != NULL)
		{ // Old file exists, back it up
			FS_SV_Rename(currFile->name, name1);
		}
		testfile = FS_SV_GetFilepath(currFile->name, filepathbuf, sizeof(filepathbuf));
		// We couldn't back it up. Now we try to just delete it.
		if(testfile != NULL)
		{
			FS_SV_BaseRemove( currFile->name );
			FS_SV_HomeRemove( currFile->name );
			testfile = FS_SV_GetFilepath( currFile->name, filepathbuf, sizeof(filepathbuf) );
			if(testfile != NULL)
			{
				Com_PrintWarning("Couldn't remove file: %s\n", testfile);
			}
			if(FS_SV_HomeFileExists(currFile->name) == qtrue)
			{
				Com_PrintError("Couldn't remove file from fs_homepath: %s\n", currFile->name);
				Com_PrintError("Update has failed!\n");
				return;
			}
		}

		if(Q_strncmp(currFile->name, EXECUTABLE_NAME, 15)){
			/* This is not the executable file */
			FS_SV_Rename(name2, currFile->name);
			testfile = FS_SV_GetFilepath(currFile->name, filepathbuf, sizeof(filepathbuf));
			if(testfile == NULL)
			{
				Com_PrintError("Failed to rename file %s to %s\n", name2,currFile->name);
				Com_PrintError("Update has failed!\n");
				return;
			}
			Com_Printf("Update on file %s successfully applied.\n",currFile->name);

		}else{
			/* This is the executable file */
			testfile = FS_SV_GetFilepath(name2, filepathbuf, sizeof(filepathbuf));
			if(testfile == NULL)
			{
				Com_PrintError("Can not find file %s\n", name2);
				Com_PrintError("Update has failed!\n");
				return;
			}
			if(FS_SetPermissionsExec(name2) == qfalse)
			{
				Com_PrintError("CRITICAL ERROR: failed to change mode of the file \"%s\"! Aborting, manual installation might be required.\n", name2);
				return;
			}
			FS_RenameOSPath(Sys_ExeFile(), va("%s.dead", Sys_ExeFile()));
			FS_RemoveOSPath(va("%s.dead", Sys_ExeFile()));
			FS_RemoveOSPath(Sys_ExeFile());
			if(FS_FileExistsOSPath(Sys_ExeFile()))
			{
				Com_PrintError("Failed to delete file %s\n", Sys_ExeFile());
				Com_PrintError("Update has failed!\n");
				return;
			}
			FS_RenameOSPath(testfile, Sys_ExeFile());
			if(!FS_FileExistsOSPath(Sys_ExeFile()))
			{
				Com_PrintError("Failed to rename file %s\n", testfile);
				Com_PrintError("Update has failed! Manual reinstallation of file %s is required. This server is now broken!\n", Sys_ExeFile());
				return;
			}
			Com_Printf("Update on file %s successfully applied.\n", Sys_ExeFile());
			dlExec = qtrue;
		}
		currFile = currFile->next;

    }while(currFile != NULL);

    Sec_FreeFileStruct(files.next);
    Com_Printf("Finalizing update...\n");


    if(dlExec == qtrue)
    {
		Sys_Restart("System has been updated and will restart now.");
    }else{
        FS_Restart( 0 );
    }
}
Exemple #13
0
void SV_SpawnServer( char *server, qboolean killBots, ForceReload_e eForceReload ) {
	int			i;
	int			checksum;
	qboolean	isBot;
	char		systemInfo[16384];
	const char	*p;

	SV_SendMapChange();

	RE_RegisterMedia_LevelLoadBegin(server, eForceReload);

	// shut down the existing game if it is running
	SV_ShutdownGameProgs();

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

/*
Ghoul2 Insert Start
*/
 	// de allocate the snapshot entities 
	if (svs.snapshotEntities)
	{
		delete[] svs.snapshotEntities;
		svs.snapshotEntities = NULL;
	}
/*
Ghoul2 Insert End
*/

	SV_SendMapChange();

#ifdef _XBOX
	// disable vsync during load for speed
	qglDisable(GL_VSYNC);
#endif

	// if not running a dedicated server CL_MapLoading will connect the client to the server
	// also print some status stuff
	CL_MapLoading();

#ifndef DEDICATED
	// make sure all the client stuff is unloaded
	CL_ShutdownAll();
#endif

	CM_ClearMap();

#ifdef _XBOX
	R_DeleteTextures();
#endif

	// clear the whole hunk because we're (re)loading the server
	Hunk_Clear();

#ifdef _XBOX
	SV_ClearLastLevel();
	ClientManager::ActivateClient(0);
#endif

	R_InitSkins();
	R_InitShaders(qtrue);

	// This was in SV_DedicatedSpawn, but it gets in the way of my memory maps:
	if( com_dedicated->integer )
	{
		// Textures have been blown away - need to kill font system so it
		// will re-register shaders when UI re-scans menu files below:
		extern void R_ShutdownFonts( void );
		R_ShutdownFonts();
	}

	ClientManager::ClientActiveRelocate( !com_dedicated->integer && !ClientManager::splitScreenMode );

#if defined(_XBOX) && !defined(FINAL_BUILD)
	//Useful for memory debugging.  Please don't delete.  Comment out if
	//necessary.
	extern void Z_DisplayLevelMemory(int, int, int);
	extern void Z_Details_f(void);
	extern void Z_TagPointers(memtag_t);
	Z_DisplayLevelMemory(0, 0, 0);
	Z_TagPointers( TAG_ALL );
	Z_Details_f();
#endif

	// init client structures and svs.numSnapshotEntities 
	if ( !Cvar_VariableValue("sv_running") ) {
		SV_Startup();
	} else {
		// check for maxclients change
		if ( sv_maxclients->modified ) {
			SV_ChangeMaxClients();
		}
	}

	// Do dedicated server-specific startup
	if ( com_dedicated->integer )
	{
		SV_DedicatedSpawn(server);
	}

	// Xbox - Correct various problems with broken rules settings when people
	// change gametype in-game, etc...
	SV_FixBrokenRules();

	SV_SendMapChange();

/*
Ghoul2 Insert Start
*/
 	// clear out those shaders, images and Models as long as this 
	// isnt a dedicated server.
	/*
	if ( !com_dedicated->integer )
	{
#ifndef DEDICATED
		R_InitImages();

		R_InitShaders();

		R_ModelInit();
#endif
	}
	else
	*/
	if (com_dedicated->integer)
	{
		R_SVModelInit();
	}

	SV_SendMapChange();

	// clear pak references
	FS_ClearPakReferences(0);

/*
Ghoul2 Insert Start
*/
	// allocate the snapshot entities on the hunk
//	svs.snapshotEntities = (struct entityState_s *)Hunk_Alloc( sizeof(entityState_t)*svs.numSnapshotEntities, h_high );
	svs.nextSnapshotEntities = 0;

	// allocate the snapshot entities 
	svs.snapshotEntities = new entityState_s[svs.numSnapshotEntities];
	// we CAN afford to do this here, since we know the STL vectors in Ghoul2 are empty
	memset(svs.snapshotEntities, 0, sizeof(entityState_t)*svs.numSnapshotEntities);

/*
Ghoul2 Insert End
*/

	// toggle the server bit so clients can detect that a
	// server has changed
	svs.snapFlagServerBit ^= SNAPFLAG_SERVERCOUNT;

	// set nextmap to the same map, but it may be overriden
	// by the game startup or another console command
	Cvar_Set( "nextmap", "map_restart 0");
//	Cvar_Set( "nextmap", va("map %s", server) );

	// wipe the entire per-level structure
	SV_ClearServer();
	for ( i = 0 ; i < MAX_CONFIGSTRINGS ; i++ ) {
		sv.configstrings[i] = CopyString("");
	}

	//rww - RAGDOLL_BEGIN
	G2API_SetTime(svs.time,0);
	//rww - RAGDOLL_END

	// make sure we are not paused
	Cvar_Set("cl_paused", "0");

	// get a new checksum feed and restart the file system
	srand(Com_Milliseconds());
	sv.checksumFeed = ( ((int) rand() << 16) ^ rand() ) ^ Com_Milliseconds();
	FS_Restart( sv.checksumFeed );

#ifdef _XBOX
	CL_StartHunkUsers();
	CM_LoadMap( va("maps/%s.bsp", server), qfalse, &checksum );
//	RE_LoadWorldMap(va("maps/%s.bsp", server));

	// Start up voice system if it isn't running yet. (ie, if we're on syslink)
	if( !logged_on )
		g_Voice.Initialize();
#else
	CM_LoadMap( va("maps/%s.bsp", server), qfalse, &checksum );
#endif

	SV_SendMapChange();

	// set serverinfo visible name
	Cvar_Set( "mapname", server );

	Cvar_Set( "sv_mapChecksum", va("%i",checksum) );

	// serverid should be different each time
	sv.serverId = com_frameTime;
	sv.restartedServerId = sv.serverId;
	Cvar_Set( "sv_serverid", va("%i", sv.serverId ) );

	// clear physics interaction links
	SV_ClearWorld ();
	
	// media configstring setting should be done during
	// the loading stage, so connected clients don't have
	// to load during actual gameplay
	sv.state = SS_LOADING;

	// load and spawn all other entities
	SV_InitGameProgs();

	// don't allow a map_restart if game is modified
	sv_gametype->modified = qfalse;

	// run a few frames to allow everything to settle
	for ( i = 0 ;i < 3 ; i++ ) {
		//rww - RAGDOLL_BEGIN
		G2API_SetTime(svs.time,0);
		//rww - RAGDOLL_END
		VM_Call( gvm, GAME_RUN_FRAME, svs.time );
		SV_BotFrame( svs.time );
		svs.time += 100;
	}
	//rww - RAGDOLL_BEGIN
	G2API_SetTime(svs.time,0);
	//rww - RAGDOLL_END

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

	for (i=0 ; i<sv_maxclients->integer ; i++) {
		// send the new gamestate to all connected clients
		if (svs.clients[i].state >= CS_CONNECTED) {
			char	*denied;

			if ( svs.clients[i].netchan.remoteAddress.type == NA_BOT ) {
				if ( killBots ) {
					SV_DropClient( &svs.clients[i], "" );
					continue;
				}
				isBot = qtrue;
			}
			else {
				isBot = qfalse;
			}

			// connect the client again
			denied = (char *)VM_ExplicitArgPtr( gvm, VM_Call( gvm, GAME_CLIENT_CONNECT, i, qfalse, isBot ) );	// firstTime = qfalse
			if ( denied ) {
				// this generally shouldn't happen, because the client
				// was connected before the level change
//				SV_DropClient( &svs.clients[i], denied );
				SV_DropClient( &svs.clients[i], "@MENUS_LOST_CONNECTION" );
			} else {
				if( !isBot ) {
					// when we get the next packet from a connected client,
					// the new gamestate will be sent
					svs.clients[i].state = CS_CONNECTED;
				}
				else {
					client_t		*client;
					sharedEntity_t	*ent;

					client = &svs.clients[i];
					client->state = CS_ACTIVE;
					ent = SV_GentityNum( i );
					ent->s.number = i;
					client->gentity = ent;

					client->deltaMessage = -1;
					client->nextSnapshotTime = svs.time;	// generate a snapshot immediately

					VM_Call( gvm, GAME_CLIENT_BEGIN, i );
				}
			}
		}
	}	

	// run another frame to allow things to look at all the players
	VM_Call( gvm, GAME_RUN_FRAME, svs.time );
	SV_BotFrame( svs.time );
	svs.time += 100;
	//rww - RAGDOLL_BEGIN
	G2API_SetTime(svs.time,0);
	//rww - RAGDOLL_END

	if ( sv_pure->integer ) {
		// the server sends these to the clients so they will only
		// load pk3s also loaded at the server
		p = FS_LoadedPakChecksums();
		Cvar_Set( "sv_paks", p );
		if (strlen(p) == 0) {
			Com_Printf( "WARNING: sv_pure set but no PK3 files loaded\n" );
		}
		p = FS_LoadedPakNames();
		Cvar_Set( "sv_pakNames", p );

		// if a dedicated pure server we need to touch the cgame because it could be in a
		// seperate pk3 file and the client will need to load the latest cgame.qvm
		if ( com_dedicated->integer ) {
			SV_TouchCGame();
		}
	}
	else {
		Cvar_Set( "sv_paks", "" );
		Cvar_Set( "sv_pakNames", "" );
	}
	// the server sends these to the clients so they can figure
	// out which pk3s should be auto-downloaded
	p = FS_ReferencedPakChecksums();
	Cvar_Set( "sv_referencedPaks", p );
	p = FS_ReferencedPakNames();
	Cvar_Set( "sv_referencedPakNames", p );

	// save systeminfo and serverinfo strings
	Q_strncpyz( systemInfo, Cvar_InfoString_Big( CVAR_SYSTEMINFO ), sizeof( systemInfo ) );
	cvar_modifiedFlags &= ~CVAR_SYSTEMINFO;
	SV_SetConfigstring( CS_SYSTEMINFO, systemInfo );

	SV_SetConfigstring( CS_SERVERINFO, Cvar_InfoString( CVAR_SERVERINFO ) );
	cvar_modifiedFlags &= ~CVAR_SERVERINFO;

	// any media configstring setting now should issue a warning
	// and any configstring changes should be reliably transmitted
	// to all clients
	sv.state = SS_GAME;

	// send a heartbeat now so the master will get up to date info
	SV_Heartbeat_f();

	Hunk_SetMark();

	/* MrE: 2000-09-13: now called in CL_DownloadsComplete
	// don't call when running dedicated
	if ( !com_dedicated->integer ) {
		// note that this is called after setting the hunk mark with Hunk_SetMark
		CL_StartHunkUsers();
	}
	*/

	// Xbox - Dedicated servers need to do extra work here. Most of this is done in
	// cl_parse normally, but that never runs in this case:
	if ( com_dedicated->integer )
	{
		// Normally, we start advertising when we get the first snapshot.
		// Do it now. This is also necessary so that Net_GetXNKID works below.
		XBL_MM_Advertise();

		// We need to put ourselves into the playerlist.
		xbOnlineInfo.localIndex = DEDICATED_SERVER_INDEX;

		XBPlayerInfo *plyrInfo = &xbOnlineInfo.xbPlayerList[DEDICATED_SERVER_INDEX];
		memset( plyrInfo, 0, sizeof(XBPlayerInfo) );

		// We get the first refIndex
		plyrInfo->refIndex = svs.clientRefNum++;

		// Address information
		plyrInfo->xbAddr = *Net_GetXNADDR( NULL );
		XNetXnAddrToInAddr( &plyrInfo->xbAddr, Net_GetXNKID(), &plyrInfo->inAddr );

		// Gamertag and XUID
		Q_strncpyz( plyrInfo->name, Cvar_VariableString("name"), sizeof(plyrInfo->name) );
		XONLINE_USER *pUser;
		if (logged_on && (pUser = &XBLLoggedOnUsers[ IN_GetMainController() ]) && (pUser->hr == S_OK))
			plyrInfo->xuid = pUser->xuid;
		else
			plyrInfo->xuid.qwUserID = plyrInfo->refIndex;

		plyrInfo->isActive = true;

		// Start up the voice chat session
		g_Voice.JoinSession();

		// And mark ourselves as playing, so that others can join our game:
		XBL_F_SetState( XONLINE_FRIENDSTATE_FLAG_PLAYING, true );
	}
}