Exemple #1
0
void SV_Frame( int msec,float fractionMsec ) {
	int		frameMsec;
	int		startTime=0;

	// the menu kills the server with this cvar
	if ( sv_killserver->integer ) {
		SV_Shutdown ("Server was killed.\n");
		Cvar_Set( "sv_killserver", "0" );
		return;
	}

	if ( !com_sv_running->integer ) {
		return;
	}

 	extern void SE_CheckForLanguageUpdates(void);
	SE_CheckForLanguageUpdates();	// will fast-return else load different language if menu changed it

	// allow pause if only the local client is connected
	if ( SV_CheckPaused() ) {
		return;
	}

	// go ahead and let time slip if the server really hitched badly
	if ( msec > 1000 ) {
		Com_DPrintf( "SV_Frame: Truncating msec of %i to 1000\n", msec );
		msec = 1000;
	}

	// if it isn't time for the next frame, do nothing
	if ( sv_fps->integer < 1 ) {
		Cvar_Set( "sv_fps", "10" );
	}
	frameMsec = 1000 / sv_fps->integer ;

	sv.timeResidual += msec;
	sv.timeResidualFraction+=fractionMsec;
	if (sv.timeResidualFraction>=1.0f)
	{
		sv.timeResidualFraction-=1.0f;
		if (cl_newClock&&cl_newClock->integer)
		{
			sv.timeResidual++;
		}
	}
	if ( sv.timeResidual < frameMsec ) {
		return;
	}

	// if time is about to hit the 32nd bit, restart the
	// level, which will force the time back to zero, rather
	// than checking for negative time wraparound everywhere.
	// 2giga-milliseconds = 23 days, so it won't be too often
	if ( sv.time > 0x70000000 ) {
		SV_Shutdown( "Restarting server due to time wrapping" );
		Com_Printf("You win.  if you can play this long and not die, you deserve to win.\n");
		return;
	}

	// update infostrings if anything has been changed
	if ( cvar_modifiedFlags & CVAR_SERVERINFO ) {
		SV_SetConfigstring( CS_SERVERINFO, Cvar_InfoString( CVAR_SERVERINFO ) );
		cvar_modifiedFlags &= ~CVAR_SERVERINFO;
	}
	if ( cvar_modifiedFlags & CVAR_SYSTEMINFO ) {
		SV_SetConfigstring( CS_SYSTEMINFO, Cvar_InfoString( CVAR_SYSTEMINFO ) );
		cvar_modifiedFlags &= ~CVAR_SYSTEMINFO;
	}

	if ( com_speeds->integer ) {
		startTime = Sys_Milliseconds ();
	}

//	SV_BotFrame( sv.time );

	// run the game simulation in chunks
	while ( sv.timeResidual >= frameMsec ) {
		sv.timeResidual -= frameMsec;
		sv.time += frameMsec;
		re.G2API_SetTime(sv.time,G2T_SV_TIME);

		// let everything in the world think and move
		ge->RunFrame( sv.time );
	}

	if ( com_speeds->integer ) {
		time_game = Sys_Milliseconds () - startTime;
	}

	SG_TestSave();	// returns immediately if not active, used for fake-save-every-cycle to test (mainly) Icarus disk code

	// check timeouts
	SV_CheckTimeouts ();

	// update ping based on the last known frame from all clients
	SV_CalcPings ();

	// send messages back to the clients
	SV_SendClientMessages ();
}
/*
==================
Cmd_CallVote_f
==================
*/
__cdecl void Cmd_CallVote_f( gentity_t *ent ) {
    int i, activePlayers;
    char arg1[MAX_STRING_TOKENS];
    char arg2[MAX_STRING_TOKENS];
    char arg3[MAX_STRING_TOKENS];
    char cleanName[64];    // JPW NERVE
    int mask = 0;
    mvabuf;


    if ( !g_allowVote->boolean ) {
        SV_GameSendServerCommand( ent - g_entities, 0, va("%c \"GAME_VOTINGNOTENABLED\"\0", 0x65));
        return;
    }
    if ( level.voteTime ) {
        SV_GameSendServerCommand( ent - g_entities, 0, va("%c \"GAME_VOTEALLREADYINPROGRESS\"\0", 0x65));
        return;
    }
    if ( ent->client->pers.voteCount >= g_voteMaxVotes->integer ) {
        SV_GameSendServerCommand( ent - g_entities, 0, va("%c \"You have called too many votes\"\0", 0x65));
        return;
    }
    if ( ent->client->sess.sessionTeam == TEAM_SPECTATOR ) {
        SV_GameSendServerCommand( ent - g_entities, 0, va("%c \"GAME_NOSPECTATORCALLVOTE\"\0", 0x65));
        return;
    }

    // make sure it is a valid command to vote on
    SV_Cmd_ArgvBuffer( 1, arg1, sizeof( arg1 ) );
    SV_Cmd_ArgvBuffer( 2, arg2, sizeof( arg2 ) );
    SV_Cmd_ArgvBuffer( 3, arg3, sizeof( arg3 ) );

    if ( strchr( arg1, ';' ) || strchr( arg2, ';' ) || strchr( arg3, ';' ) ) {
        SV_GameSendServerCommand( ent - g_entities, 0, va("%c \"GAME_INVALIDVOTESTRING\"\0", 0x65));
        return;
    }

    if ( !Q_stricmp( arg1, "map_restart" ) ) {
        mask = VOTEFLAGS_RESTART;
    } else if ( !Q_stricmp( arg1, "map_rotate" ) ) {
        mask = VOTEFLAGS_NEXTMAP;
    } else if ( !Q_stricmp( arg1, "map" ) ) {
        mask = VOTEFLAGS_MAP;
    } else if ( !Q_stricmp( arg1, "typemap" ) ) {
        mask = VOTEFLAGS_TYPE;
    } else if ( !Q_stricmp( arg1, "kick" ) ) {
        mask = VOTEFLAGS_KICK;
    } else if ( !Q_stricmp( arg1, "tempbanuser" ) ) {
        mask = VOTEFLAGS_KICK;
    } else if ( !Q_stricmp( arg1, "g_gametype" ) ) {        // NERVE - SMF
        mask = VOTEFLAGS_GAMETYPE;
// jpw
    } else {
        SV_GameSendServerCommand( ent - g_entities, 0, va("%c \"GAME_INVALIDVOTESTRING\"\0", 0x65));
        SV_GameSendServerCommand( ent - g_entities, 0, va("%c \"GAME_VOTECOMMANDSARE\x15 map_restart, map_rotate, map <mapname>, g_gametype <gametype>, kick <player or clientnum>, typemap <gametype> <map>\"\0", 0x65));
        return;
    }

    if ( !( g_voteFlags & mask ) ) {
        SV_GameSendServerCommand( ent - g_entities, 0, va("%c \"Voting for %s is disabled on this server\"\0", 0x65, arg1 ) );
        return;
    }

    // if there is still a vote to be executed
    if ( level.voteExecuteTime ) {
        level.voteExecuteTime = 0;
        Cbuf_AddText( va( "%s\n", level.voteString ) );
    }

    // special case for g_gametype, check for bad values
    if ( !Q_stricmp( arg1, "typemap" ) ) {

        if(*g_voteVoteGametypes->string) {
            if(!strstr(g_voteVoteGametypes->string, arg2)) {
                SV_GameSendServerCommand( ent - g_entities, 0, va("%c \"Voting for gametype %s is disabled on this server\"\0", 0x65, arg2));
                return;
            }
        }

        for( i = 0; i < g_gametypes->numGametypes; i++) {
            if(!Q_stricmp( arg2, g_gametypes->gametype[i].gametypename) )
                break;
        }
        if ( i == g_gametypes->numGametypes) {
            SV_GameSendServerCommand( ent - g_entities, 0, va("%c \"GAME_INVALIDGAMETYPE\"\0", 0x65));
            return;
        }

        if( !(g_voteFlags & VOTEFLAGS_ANYMAP) ) {
            if(!strstr(SV_GetMapRotation(), va("map %s",arg3))) {
                SV_GameSendServerCommand( ent - g_entities, 0, va("%c \"Voting for map %s is disabled on this server\"\0", 0x65, arg3));
                return;
            }
        }
        Com_sprintf( level.voteString, sizeof( level.voteString ), "set g_votedGametype %s; set g_votedMapName %s\n", arg2, arg3);
        Com_sprintf( level.voteDisplayString, sizeof( level.voteDisplayString ), "Set next map to: %s and gametype to: \x14%s", arg3, g_gametypes->gametype[i].gametypereadable);

    } else if ( !Q_stricmp( arg1, "g_gametype" ) ) {

        if(*g_voteVoteGametypes->string) {
            if(!strstr(g_voteVoteGametypes->string, arg2)) {
                SV_GameSendServerCommand( ent - g_entities, 0, va("%c \"Voting for gametype %s is disabled on this server\"\0", 0x65, arg2));
                return;
            }
        }

        for( i = 0; i < g_gametypes->numGametypes; i++) {
            if(!Q_stricmp( arg2, g_gametypes->gametype[i].gametypename) )
                break;
        }
        if ( i == g_gametypes->numGametypes) {
            SV_GameSendServerCommand( ent - g_entities, 0, va("%c \"GAME_INVALIDGAMETYPE\"\0", 0x65));
            return;
        }

        Com_sprintf( level.voteString, sizeof( level.voteString ), "set g_gametype %s; map_restart\n", arg2);
        Com_sprintf( level.voteDisplayString, sizeof( level.voteDisplayString ), "Set gametype to: \x15%s and restart", g_gametypes->gametype[i].gametypename);

    } else if ( !Q_stricmp( arg1, "map_restart" ) ) {
        // NERVE - SMF - do a warmup when we restart maps
        Com_sprintf( level.voteString, sizeof( level.voteString ), "map_restart\n");
        Com_sprintf( level.voteDisplayString, sizeof( level.voteDisplayString ), "Restart current game" );
    } else if ( !Q_stricmp( arg1, "map" ) ) {

        if( !(g_voteFlags & VOTEFLAGS_ANYMAP) ) {
            if(!strstr(SV_GetMapRotation(), va("map %s", arg2))) {
                SV_GameSendServerCommand( ent - g_entities, 0, va("%c \"This server does not allow voting for maps which aren't part of map-rotation\"\0", 0x65));
                return;
            }
        }
        Com_sprintf( level.voteString, sizeof( level.voteString ), "set g_votedMapName %s\n", arg2 );
        Com_sprintf( level.voteDisplayString, sizeof( level.voteDisplayString ), "Set next map to: %s", arg2 );
    } else if ( !Q_stricmp( arg1, "map_rotate" ) ) {

        if(*g_votedMapName->string) {
            if(*g_votedGametype->string)
                Com_sprintf( level.voteString, sizeof( level.voteString ), "set g_gametype %s; map %s; set g_votedGametype \"\"; set g_votedMapName \"\"\n", g_votedGametype->string, g_votedMapName->string);
            else
                Com_sprintf( level.voteString, sizeof( level.voteString ), "map %s; set g_votedMapName \"\"\n", g_votedMapName->string);
            //Com_sprintf( s, sizeof( s ), g_votedMapName->string);
        } else {
            Com_sprintf( level.voteString, sizeof( level.voteString ), "map_rotate\n" );
            //Com_sprintf( s, sizeof( s ), g_votedMapName->string);
        }
        Com_sprintf( level.voteDisplayString, sizeof( level.voteDisplayString ), "Switch to next map now");
// JPW NERVE
    } else if ( !Q_stricmp( arg1,"tempbanuser") || !Q_stricmp( arg1,"kick")) {

        int i, kicknum = MAX_CLIENTS;

        for ( i = 0, activePlayers = 0; i < level.maxclients; i++ ) {
            if ( level.clients[i].pers.connected != CON_CONNECTED || level.clients[i].sess.sessionTeam == TEAM_SPECTATOR) {
                continue;
            }
            activePlayers++;
        }
        if(activePlayers < g_voteKickMinPlayers->integer) {
            SV_GameSendServerCommand( ent - g_entities, 0, va("%c \"GAME_VOTINGNOTENOUGHPLAYERS\"\0", 0x65));
            return;
        }
        for ( i = 0; i < MAX_CLIENTS; i++ ) {
            if ( level.clients[i].pers.connected != CON_CONNECTED ) {
                continue;
            }
            // strip the color crap out
            Q_strncpyz( cleanName, level.clients[i].pers.netname, sizeof( cleanName ) );
            Q_CleanStr( cleanName );
            if ( !Q_stricmp( cleanName, arg2 ) ) {
                kicknum = i;
            }
        }

        if ( kicknum != MAX_CLIENTS ) { // found a client # to kick, so override votestring with better one

            Com_sprintf( level.voteDisplayString, sizeof( level.voteDisplayString ), "%s wants to kick and tempban: %s", ent->client->pers.netname ,level.clients[kicknum].pers.netname );

            if(svs.clients[kicknum].power > 5)
            {
                SV_GameSendServerCommand( ent - g_entities, 0, va("%c \"Can not call a vote against a protected player\"\0", 0x65));
                level.voteDisplayString[0] = 0;
                return;
            } else {
                Com_sprintf( level.voteString, sizeof( level.voteString ),"tempban \"%d\" %im Vote kick; kick \"%d\" Vote kick\n", kicknum, g_voteBanTime->integer, kicknum);
            }

        } else { // if it can't do a name match, don't allow kick (to prevent votekick text spam wars)
            SV_GameSendServerCommand( ent - g_entities, 0, va("%c \"GAME_CLIENTNOTONSERVER\"\0", 0x65));
            level.voteDisplayString[0] = 0;
            return;
        }
// jpw
    } else {
//		Com_sprintf( level.voteString, sizeof( level.voteString ), "%s \"%s\"", arg1, arg2 );
//		Com_sprintf( level.voteDisplayString, sizeof( level.voteDisplayString ), "%s", level.voteString );
    }

    SV_GameSendServerCommand( -1, 0, va("%c \"GAME_CALLEDAVOTE\x15%s\"\0", 0x65, ent->client->pers.netname));
    ent->client->pers.voteCount++;

    // start the voting, the caller autoamtically votes yes
    level.voteTime = level.time + 1000*g_voteTime->integer;
    level.voteYes = 1;
    level.voteNo = 0;

    for ( i = 0 ; i < level.maxclients ; i++ ) {
        level.clients[i].ps.eFlags &= ~EF_VOTED;
    }
    ent->client->ps.eFlags |= EF_VOTED;

    SV_SetConfigstring( CS_VOTE_TIME, va( "%i %i", level.voteTime, sv_serverid->integer) );
    SV_SetConfigstring( CS_VOTE_STRING, level.voteDisplayString );
    SV_SetConfigstring( CS_VOTE_YES, va( "%i", level.voteYes ) );
    SV_SetConfigstring( CS_VOTE_NO, va( "%i", level.voteNo ) );
}
Exemple #3
0
/*
================
SV_MapRestart_f

Completely restarts a level, but doesn't send a new gamestate to the clients.
This allows fair starts with variable load times.
================
*/
static void SV_MapRestart_f( void ) {
	int			i;
	client_t	*client;
	char		*denied;
	qboolean	isBot;
	int			delay;

	// make sure we aren't restarting twice in the same frame
	if ( com_frameTime == sv.serverId ) {
		return;
	}

	// make sure server is running
	if ( !com_sv_running->integer ) {
		Com_Printf( "Server is not running.\n" );
		return;
	}

	if ( sv.restartTime ) {
		return;
	}

	if (Cmd_Argc() > 1 ) {
		delay = atoi( Cmd_Argv(1) );
	}
	else {
		delay = 5;
	}
	if( delay ) {
		sv.restartTime = sv.time + delay * 1000;
		SV_SetConfigstring( CS_WARMUP, va("%i", sv.restartTime) );
		return;
	}

	// check for changes in variables that can't just be restarted
	// check for maxclients change
	if ( sv_maxclients->modified || sv_gametype->modified ) {
		char	mapname[MAX_QPATH];

		Com_Printf( "variable change -- restarting.\n" );
		// restart the map the slow way
		Q_strncpyz( mapname, Cvar_VariableString( "mapname" ), sizeof( mapname ) );

		SV_SpawnServer( mapname, qfalse, eForceReload_NOTHING );
		return;
	}

	SV_StopAutoRecordDemos();

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

	// generate a new serverid
	// TTimo - don't update restartedserverId there, otherwise we won't deal correctly with multiple map_restart
	sv.serverId = com_frameTime;
	Cvar_Set( "sv_serverid", va("%i", sv.serverId ) );

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

	// if a map_restart occurs while a client is changing maps, we need
	// to give them the correct time so that when they finish loading
	// they don't violate the backwards time check in cl_cgame.c
	for (i=0 ; i<sv_maxclients->integer ; i++) {
		if (svs.clients[i].state == CS_PRIMED) {
			svs.clients[i].oldServerTime = sv.restartTime;
		}
	}

	// reset all the vm data in place without changing memory allocation
	// note that we do NOT set sv.state = SS_LOADING, so configstrings that
	// had been changed from their default values will generate broadcast updates
	sv.state = SS_LOADING;
	sv.restarting = qtrue;

	SV_RestartGame();

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

	sv.state = SS_GAME;
	sv.restarting = qfalse;

	// connect and begin all the clients
	for (i=0 ; i<sv_maxclients->integer ; i++) {
		client = &svs.clients[i];

		// send the new gamestate to all connected clients
		if ( client->state < CS_CONNECTED) {
			continue;
		}

		if ( client->netchan.remoteAddress.type == NA_BOT ) {
			isBot = qtrue;
		} else {
			isBot = qfalse;
		}

		// add the map_restart command
		SV_AddServerCommand( client, "map_restart\n" );

		// connect the client again, without the firstTime flag
		denied = GVM_ClientConnect( i, qfalse, isBot );
		if ( denied ) {
			// this generally shouldn't happen, because the client
			// was connected before the level change
			SV_DropClient( client, denied );
			Com_Printf( "SV_MapRestart_f(%d): dropped client %i - denied!\n", delay, i );
			continue;
		}

		if(client->state == CS_ACTIVE)
			SV_ClientEnterWorld(client, &client->lastUsercmd);
		else
		{
			// If we don't reset client->lastUsercmd and are restarting during map load,
			// the client will hang because we'll use the last Usercmd from the previous map,
			// which is wrong obviously.
			SV_ClientEnterWorld(client, NULL);
		}
	}

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

	SV_BeginAutoRecordDemos();
}
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 );
	}
}
/**
 * @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)
		{
			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 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;

	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();

#ifdef FEATURE_MYSQL
        if (Com_DB_Ready()) {
                Com_DB_SetMap(server);
        }
#endif /* FEATURE_MYSQL */

	Com_Printf("-----------------------------------\n");
}
/*
================
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( const char *server )
{
	int        i;
	bool   isBot;

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

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

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

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

	// clear collision map data
	CM_ClearMap();

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

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

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

	// allocate the snapshot entities on the hunk
	svs.snapshotEntities = ( entityState_t * ) 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 sv_nextmap to the same map, but it may be overridden
	// by the game startup or another console command
	Cvar_Set( "sv_nextmap", "map_restart 0" );

	// 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 = ( ( rand() << 16 ) ^ rand() ) ^ Sys_Milliseconds();

	FS::PakPath::ClearPaks();
	FS_LoadBasePak();
	if (!FS_LoadPak(va("map-%s", server)))
		Com_Error(ERR_DROP, "Could not load map pak\n");

	CM_LoadMap(server);

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

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

	// 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++ )
	{
		gvm.GameRunFrame( sv.time );
		svs.time += FRAMETIME;
		sv.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 )
		{
			bool denied;
			char reason[ MAX_STRING_CHARS ];

			isBot = SV_IsBot(&svs.clients[i]);

			// connect the client again
			denied = gvm.GameClientConnect( reason, sizeof( reason ), i, false, isBot );   // firstTime = false

			if ( denied )
			{
				// this generally shouldn't happen, because the client
				// was connected before the level change
				SV_DropClient( &svs.clients[ i ], reason );
			}
			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.GameClientBegin( i );
				}
			}
		}
	}

	// run another frame to allow things to look at all the players
	gvm.GameRunFrame( sv.time );
	svs.time += FRAMETIME;
	sv.time += FRAMETIME;

	// the server sends these to the clients so they can figure
	// out which pk3s should be auto-downloaded

	Cvar_Set( "sv_paks", FS_LoadedPaks() );

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

	SV_SetConfigstring( CS_SERVERINFO, Cvar_InfoString( CVAR_SERVERINFO, false ) );
	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();

	SV_AddOperatorCommands();

	Com_Printf( "-----------------------------------\n" );
}
Exemple #7
0
/*
====================
SV_GameSystemCalls

The module is making a system call
====================
*/
intptr_t SV_GameSystemCalls(intptr_t * args) {
	switch (args[0]) {
		case G_PRINT:
			Com_Printf("%s", (char *)VMA(1));
			return 0;
		case G_ERROR:
			Com_Error(ERR_DROP, "%s", (char *)VMA(1));
			return 0;
		case G_MILLISECONDS:
			return Sys_Milliseconds();
		case G_CVAR_REGISTER:
			Cvar_Register((vmCvar_t*)VMA(1), (char*)VMA(2), (char*)VMA(3), args[4]);
			return 0;
		case G_CVAR_UPDATE:
			Cvar_Update((vmCvar_t*)VMA(1));
			return 0;
		case G_CVAR_SET:
			Cvar_Set((const char *)VMA(1), (const char *)VMA(2));
			return 0;
		case G_CVAR_VARIABLE_INTEGER_VALUE:
			return Cvar_VariableIntegerValue((const char *)VMA(1));
		case G_CVAR_VARIABLE_STRING_BUFFER:
			Cvar_VariableStringBuffer((char *)VMA(1), (char*)VMA(2), args[3]);
			return 0;
		case G_CVAR_LATCHEDVARIABLESTRINGBUFFER:
			Cvar_LatchedVariableStringBuffer((char *)VMA(1), (char*)VMA(2), args[3]);
			return 0;
		case G_ARGC:
			return Cmd_Argc();
		case G_ARGV:
			Cmd_ArgvBuffer(args[1], (char*)VMA(2), args[3]);
			return 0;
		case G_SEND_CONSOLE_COMMAND:
			Cbuf_ExecuteText(args[1], (char *)VMA(2));
			return 0;
		case G_FS_FOPEN_FILE:
			return FS_FOpenFileByMode((char *)VMA(1), (fileHandle_t*)VMA(2), (fsMode_t)args[3]);
		case G_FS_READ:
			FS_Read2(VMA(1), args[2], args[3]);
			return 0;
		case G_FS_WRITE:
			return FS_Write(VMA(1), args[2], args[3]);
		case G_FS_RENAME:
			FS_Rename((char *)VMA(1), (char *)VMA(2));
			return 0;
		case G_FS_FCLOSE_FILE:
			FS_FCloseFile(args[1]);
			return 0;
		case G_FS_GETFILELIST:
			return FS_GetFileList((char *)VMA(1), (char *)VMA(2), (char*)VMA(3), args[4]);
		case G_LOCATE_GAME_DATA:
			SV_LocateGameData((sharedEntity_t*)VMA(1), args[2], args[3], (playerState_t*)VMA(4), args[5]);
			return 0;
		case G_DROP_CLIENT:
			SV_GameDropClient(args[1], (char*)VMA(2), args[3]);
			return 0;
		case G_SEND_SERVER_COMMAND:
			SV_GameSendServerCommand(args[1], (char*)VMA(2));
			return 0;
		case G_LINKENTITY:
			SV_LinkEntity((sharedEntity_t*)VMA(1));
			return 0;
		case G_UNLINKENTITY:
			SV_UnlinkEntity((sharedEntity_t*)VMA(1));
			return 0;
		case G_ENTITIES_IN_BOX:
			return SV_AreaEntities((float*)VMA(1), (float*)VMA(2), (int*)VMA(3), args[4]);
		case G_ENTITY_CONTACT:
			return SV_EntityContact((float*)VMA(1), (float*)VMA(2), (sharedEntity_t*)VMA(3), TT_AABB);
		case G_ENTITY_CONTACTCAPSULE:
			return SV_EntityContact((float*)VMA(1), (float*)VMA(2), (sharedEntity_t*)VMA(3), TT_CAPSULE);
		case G_TRACE:
			SV_Trace((trace_t*)VMA(1), (float*)VMA(2), (float*)VMA(3), (float*)VMA(4), (float*)VMA(5), args[6], args[7], TT_AABB);
			return 0;
		case G_TRACECAPSULE:
			SV_Trace((trace_t*)VMA(1), (float*)VMA(2), (float*)VMA(3), (float*)VMA(4), (float*)VMA(5), args[6], args[7], TT_CAPSULE);
			return 0;
		case G_POINT_CONTENTS:
			return SV_PointContents((float*)VMA(1), args[2]);
		case G_SET_BRUSH_MODEL:
			SV_SetBrushModel((sharedEntity_t*)VMA(1), (char*)VMA(2));
			return 0;
		case G_IN_PVS:
			return SV_inPVS((float*)VMA(1), (float*)VMA(2));
		case G_IN_PVS_IGNORE_PORTALS:
			return SV_inPVSIgnorePortals((float*)VMA(1), (float*)VMA(2));
		case G_SET_CONFIGSTRING:
			SV_SetConfigstring(args[1], (char*)VMA(2));
			return 0;
		case G_GET_CONFIGSTRING:
			SV_GetConfigstring(args[1], (char*)VMA(2), args[3]);
			return 0;
		case G_SET_CONFIGSTRING_RESTRICTIONS:
			SV_SetConfigstringRestrictions( args[1], (clientList_t*)VMA(2) );
			return 0;
		case G_SET_USERINFO:
			SV_SetUserinfo(args[1], (char*)VMA(2));
			return 0;
		case G_GET_USERINFO:
			SV_GetUserinfo(args[1], (char*)VMA(2), args[3]);
			return 0;
		case G_GET_SERVERINFO:
			SV_GetServerinfo((char*)VMA(1), args[2]);
			return 0;
		case G_ADJUST_AREA_PORTAL_STATE:
			SV_AdjustAreaPortalState((sharedEntity_t*)VMA(1),(qboolean)args[2]);
			return 0;
		case G_AREAS_CONNECTED:
			return CM_AreasConnected(args[1], args[2]);
		case G_UPDATE_SHARED_CONFIG:
			SV_UpdateSharedConfig( args[1], (char*)VMA(2) );
			return 0;
		case G_BOT_ALLOCATE_CLIENT:
			return SV_BotAllocateClient(args[1]);
		case G_BOT_FREE_CLIENT:
			SV_BotFreeClient(args[1]);
			return 0;
		case G_GET_USERCMD:
			SV_GetUsercmd(args[1], (usercmd_t*)VMA(2));
			return 0;
		case G_GET_ENTITY_TOKEN: {
			const char     *s;

			s = COM_Parse(&sv.entityParsePoint);
			Q_strncpyz((char*)VMA(1), s, args[2]);
			if(!sv.entityParsePoint && !s[0]) {
				return qfalse;
			} else {
				return qtrue;
			}
		}
		case G_DEBUG_POLYGON_CREATE:
			return BotImport_DebugPolygonCreate(args[1], args[2], (vec3_t*)VMA(3));
		case G_DEBUG_POLYGON_DELETE:
			BotImport_DebugPolygonDelete(args[1]);
			return 0;
		case G_REAL_TIME:
			return Com_RealTime((qtime_t*)VMA(1));
		case G_SNAPVECTOR:
			Q_SnapVector((float*)VMA(1));
			return 0;
		case G_SEND_GAMESTAT:
			SV_MasterGameStat( (char*)VMA(1) );
			return 0;
		case G_ADDCOMMAND:
			Cmd_AddCommand( (char*)VMA(1), NULL, (char*)VMA(3) );
			return 0;
		case G_REMOVECOMMAND:
			Cmd_RemoveCommand( (char*)VMA(1) );
			return 0;
		case G_GETTAG:
			return SV_GetTag(args[1], args[2], (char*)VMA(3), (orientation_t*)VMA(4));
		case G_REGISTERTAG:
			return SV_LoadTag((char*)VMA(1));
		case G_REGISTERSOUND:
			return S_RegisterSound((char*)VMA(1), (qboolean)args[2]);
		case G_GET_SOUND_LENGTH:
			return S_GetSoundLength(args[1]);
		case G_PARSE_ADD_GLOBAL_DEFINE:
			return Parse_AddGlobalDefine( (char*)VMA(1) );
		case G_PARSE_LOAD_SOURCE:
			return Parse_LoadSourceHandle( (char*)VMA(1) );
		case G_PARSE_FREE_SOURCE:
			return Parse_FreeSourceHandle( args[1] );
		case G_PARSE_READ_TOKEN:
			return Parse_ReadTokenHandle( args[1], (pc_token_t*)VMA(2) );
		case G_PARSE_SOURCE_FILE_AND_LINE:
			return Parse_SourceFileAndLine( args[1], (char*)VMA(2), (int*)VMA(3) );
		case BOTLIB_SETUP:
			return SV_BotLibSetup();
		case BOTLIB_SHUTDOWN:
			return SV_BotLibShutdown();
		case BOTLIB_LIBVAR_SET:
			return botlib_export->BotLibVarSet((char*)VMA(1), (char*)VMA(2));
		case BOTLIB_LIBVAR_GET:
			return botlib_export->BotLibVarGet((char*)VMA(1), (char*)VMA(2), args[3]);
		case BOTLIB_PC_ADD_GLOBAL_DEFINE:
			return Parse_AddGlobalDefine( (char*)VMA(1) );
		case BOTLIB_PC_LOAD_SOURCE:
			return Parse_LoadSourceHandle((char*)VMA(1));
		case BOTLIB_PC_FREE_SOURCE:
			return Parse_FreeSourceHandle(args[1]);
		case BOTLIB_PC_READ_TOKEN:
			return Parse_ReadTokenHandle(args[1], (pc_token_t*)VMA(2));
		case BOTLIB_PC_SOURCE_FILE_AND_LINE:
			return Parse_SourceFileAndLine(args[1], (char*)VMA(2), (int*)VMA(3));
		case BOTLIB_PC_UNREAD_TOKEN:
			Parse_UnreadLastTokenHandle(args[1]);
			return 0;
		case BOTLIB_START_FRAME:
			return botlib_export->BotLibStartFrame(VMF(1));
		case BOTLIB_LOAD_MAP:
			return botlib_export->BotLibLoadMap((char*)VMA(1));
		case BOTLIB_UPDATENTITY:
			return botlib_export->BotLibUpdateEntity(args[1], (bot_entitystate_t*)VMA(2));
		case BOTLIB_TEST:
			return botlib_export->Test( args[1], (char*)VMA(2), (float*)VMA(3), (float*)VMA(4) );
		case BOTLIB_GET_SNAPSHOT_ENTITY:
			return SV_BotGetSnapshotEntity(args[1], args[2]);
		case BOTLIB_GET_CONSOLE_MESSAGE:
			return SV_BotGetConsoleMessage(args[1], (char*)VMA(2), args[3]);
		case BOTLIB_USER_COMMAND:
			SV_ClientThink(&svs.clients[args[1]], (usercmd_t*)VMA(2));
			return 0;
		case BOTLIB_AAS_ENTITY_INFO:
			botlib_export->aas.AAS_EntityInfo(args[1], (aas_entityinfo_s*)VMA(2));
			return 0;
		case BOTLIB_AAS_INITIALIZED:
			return botlib_export->aas.AAS_Initialized();
		case BOTLIB_AAS_PRESENCE_TYPE_BOUNDING_BOX:
			botlib_export->aas.AAS_PresenceTypeBoundingBox( args[1], (float*)VMA(2), (float*)VMA(3) );
			return 0;
		case BOTLIB_AAS_TIME:
			return FloatAsInt(botlib_export->aas.AAS_Time());
		case BOTLIB_AAS_SETCURRENTWORLD:
			botlib_export->aas.AAS_SetCurrentWorld(args[1]);
			return 0;
		case BOTLIB_AAS_POINT_AREA_NUM:
			return botlib_export->aas.AAS_PointAreaNum( (float*)VMA(1) );
		case BOTLIB_AAS_TRACE_AREAS:
			return botlib_export->aas.AAS_TraceAreas( (float*)VMA(1), (float*)VMA(2), (int*)VMA(3), (vec3_t*)VMA(4), args[5] );
		case BOTLIB_AAS_BBOX_AREAS:
			return botlib_export->aas.AAS_BBoxAreas( (float*)VMA(1), (float*)VMA(2), (int*)VMA(3), args[4] );
		case BOTLIB_AAS_AREA_CENTER:
			botlib_export->aas.AAS_AreaCenter(args[1], (float*)VMA(2));
			return 0;
		case BOTLIB_AAS_AREA_WAYPOINT:
			return botlib_export->aas.AAS_AreaWaypoint(args[1], (float*)VMA(2));
		case BOTLIB_AAS_POINT_CONTENTS:
			return botlib_export->aas.AAS_PointContents((float*)VMA(1));
		case BOTLIB_AAS_NEXT_BSP_ENTITY:
			return botlib_export->aas.AAS_NextBSPEntity(args[1]);
		case BOTLIB_AAS_VALUE_FOR_BSP_EPAIR_KEY:
			return botlib_export->aas.AAS_ValueForBSPEpairKey(args[1], (char*)VMA(2), (char*)VMA(3), args[4]);
		case BOTLIB_AAS_VECTOR_FOR_BSP_EPAIR_KEY:
			return botlib_export->aas.AAS_VectorForBSPEpairKey(args[1], (char*)VMA(2), (float*)VMA(3));
		case BOTLIB_AAS_FLOAT_FOR_BSP_EPAIR_KEY:
			return botlib_export->aas.AAS_FloatForBSPEpairKey(args[1], (char*)VMA(2), (float*)VMA(3));
		case BOTLIB_AAS_INT_FOR_BSP_EPAIR_KEY:
			return botlib_export->aas.AAS_IntForBSPEpairKey(args[1], (char*)VMA(2), (int*)VMA(3));
		case BOTLIB_AAS_AREA_REACHABILITY:
			return botlib_export->aas.AAS_AreaReachability(args[1]);
		case BOTLIB_AAS_AREA_LADDER:
			return botlib_export->aas.AAS_AreaLadder(args[1]);
		case BOTLIB_AAS_AREA_TRAVEL_TIME_TO_GOAL_AREA:
			return botlib_export->aas.AAS_AreaTravelTimeToGoalArea(args[1], (float*)VMA(2), args[3], args[4]);
		case BOTLIB_AAS_SWIMMING:
			return botlib_export->aas.AAS_Swimming((float*)VMA(1));
		case BOTLIB_AAS_PREDICT_CLIENT_MOVEMENT:
			return botlib_export->aas.AAS_PredictClientMovement((aas_clientmove_s*)VMA(1), args[2], (float*)VMA(3), args[4], args[5], (float*)VMA(6), (float*)VMA(7), args[8], args[9], VMF(10), args[11], args[12], args[13]);
		case BOTLIB_AAS_RT_SHOWROUTE:
			botlib_export->aas.AAS_RT_ShowRoute((float*)VMA(1), args[2], args[3]);
			return 0;
		case BOTLIB_AAS_NEARESTHIDEAREA:
			return botlib_export->aas.AAS_NearestHideArea(args[1], (float*)VMA(2), args[3], args[4], (float*)VMA(5), args[6], args[7], VMF(8), (float*)VMA(9));
		case BOTLIB_AAS_LISTAREASINRANGE:
			return botlib_export->aas.AAS_ListAreasInRange((float*)VMA(1), args[2], VMF(3), args[4], (vec3_t*)VMA(5), args[6]);
		case BOTLIB_AAS_AVOIDDANGERAREA:
			return botlib_export->aas.AAS_AvoidDangerArea((float*)VMA(1), args[2], (float*)VMA(3), args[4], VMF(5), args[6]);
		case BOTLIB_AAS_RETREAT:
			return botlib_export->aas.AAS_Retreat((int*)VMA(1), args[2], (float*)VMA(3), args[4], (float*)VMA(5), args[6], VMF(7), VMF(8), args[9]);
		case BOTLIB_AAS_ALTROUTEGOALS:
			return botlib_export->aas.AAS_AlternativeRouteGoals((float*)VMA(1), (float*)VMA(2), args[3], (aas_altroutegoal_t*)VMA(4), args[5], args[6]);
		case BOTLIB_AAS_SETAASBLOCKINGENTITY:
			botlib_export->aas.AAS_SetAASBlockingEntity((float*)VMA(1), (float*)VMA(2), args[3]);
			return 0;
		case BOTLIB_AAS_RECORDTEAMDEATHAREA:
			botlib_export->aas.AAS_RecordTeamDeathArea((float*)VMA(1), args[2], args[3], args[4], args[5]);
			return 0;
		case BOTLIB_EA_SAY:
			botlib_export->ea.EA_Say(args[1], (char*)VMA(2));
			return 0;
		case BOTLIB_EA_SAY_TEAM:
			botlib_export->ea.EA_SayTeam(args[1], (char*)VMA(2));
			return 0;
		case BOTLIB_EA_USE_ITEM:
			botlib_export->ea.EA_UseItem(args[1], (char*)VMA(2));
			return 0;
		case BOTLIB_EA_DROP_ITEM:
			botlib_export->ea.EA_DropItem(args[1], (char*)VMA(2));
			return 0;
		case BOTLIB_EA_USE_INV:
			botlib_export->ea.EA_UseInv(args[1], (char*)VMA(2));
			return 0;
		case BOTLIB_EA_DROP_INV:
			botlib_export->ea.EA_DropInv(args[1], (char*)VMA(2));
			return 0;
		case BOTLIB_EA_GESTURE:
			botlib_export->ea.EA_Gesture(args[1]);
			return 0;
		case BOTLIB_EA_COMMAND:
			botlib_export->ea.EA_Command(args[1], (char*)VMA(2));
			return 0;
		case BOTLIB_EA_SELECT_WEAPON:
			botlib_export->ea.EA_SelectWeapon(args[1], args[2]);
			return 0;
		case BOTLIB_EA_TALK:
			botlib_export->ea.EA_Talk(args[1]);
			return 0;
		case BOTLIB_EA_ATTACK:
			botlib_export->ea.EA_Attack(args[1]);
			return 0;
		case BOTLIB_EA_RELOAD:
			botlib_export->ea.EA_Reload(args[1]);
			return 0;
		case BOTLIB_EA_USE:
			botlib_export->ea.EA_Use(args[1]);
			return 0;
		case BOTLIB_EA_RESPAWN:
			botlib_export->ea.EA_Respawn(args[1]);
			return 0;
		case BOTLIB_EA_JUMP:
			botlib_export->ea.EA_Jump(args[1]);
			return 0;
		case BOTLIB_EA_DELAYED_JUMP:
			botlib_export->ea.EA_DelayedJump(args[1]);
			return 0;
		case BOTLIB_EA_CROUCH:
			botlib_export->ea.EA_Crouch(args[1]);
			return 0;
		case BOTLIB_EA_WALK:
			botlib_export->ea.EA_Walk(args[1]);
			return 0;
		case BOTLIB_EA_MOVE_UP:
			botlib_export->ea.EA_MoveUp(args[1]);
			return 0;
		case BOTLIB_EA_MOVE_DOWN:
			botlib_export->ea.EA_MoveDown(args[1]);
			return 0;
		case BOTLIB_EA_MOVE_FORWARD:
			botlib_export->ea.EA_MoveForward(args[1]);
			return 0;
		case BOTLIB_EA_MOVE_BACK:
			botlib_export->ea.EA_MoveBack(args[1]);
			return 0;
		case BOTLIB_EA_MOVE_LEFT:
			botlib_export->ea.EA_MoveLeft(args[1]);
			return 0;
		case BOTLIB_EA_MOVE_RIGHT:
			botlib_export->ea.EA_MoveRight(args[1]);
			return 0;
		case BOTLIB_EA_MOVE:
			botlib_export->ea.EA_Move(args[1], (float*)VMA(2), VMF(3));
			return 0;
		case BOTLIB_EA_VIEW:
			botlib_export->ea.EA_View(args[1], (float*)VMA(2));
			return 0;
		case BOTLIB_EA_PRONE:
			botlib_export->ea.EA_Prone(args[1]);
			return 0;
		case BOTLIB_EA_END_REGULAR:
			botlib_export->ea.EA_EndRegular(args[1], VMF(2));
			return 0;
		case BOTLIB_EA_GET_INPUT:
			botlib_export->ea.EA_GetInput(args[1], VMF(2), (bot_input_t*)VMA(3));
			return 0;
		case BOTLIB_EA_RESET_INPUT:
			botlib_export->ea.EA_ResetInput(args[1], (bot_input_t*)VMA(2));
			return 0;
		case BOTLIB_AI_LOAD_CHARACTER:
			return botlib_export->ai.BotLoadCharacter((char*)VMA(1), args[2]);
		case BOTLIB_AI_FREE_CHARACTER:
			botlib_export->ai.BotFreeCharacter(args[1]);
			return 0;
		case BOTLIB_AI_CHARACTERISTIC_FLOAT:
			return FloatAsInt(botlib_export->ai.Characteristic_Float(args[1], args[2]));
		case BOTLIB_AI_CHARACTERISTIC_BFLOAT:
			return FloatAsInt(botlib_export->ai.Characteristic_BFloat(args[1], args[2], VMF(3), VMF(4)));
		case BOTLIB_AI_CHARACTERISTIC_INTEGER:
			return botlib_export->ai.Characteristic_Integer(args[1], args[2]);
		case BOTLIB_AI_CHARACTERISTIC_BINTEGER:
			return botlib_export->ai.Characteristic_BInteger(args[1], args[2], args[3], args[4]);
		case BOTLIB_AI_CHARACTERISTIC_STRING:
			botlib_export->ai.Characteristic_String(args[1], args[2], (char*)VMA(3), args[4]);
			return 0;
		case BOTLIB_AI_ALLOC_CHAT_STATE:
			return botlib_export->ai.BotAllocChatState();
		case BOTLIB_AI_FREE_CHAT_STATE:
			botlib_export->ai.BotFreeChatState(args[1]);
			return 0;
		case BOTLIB_AI_QUEUE_CONSOLE_MESSAGE:
			botlib_export->ai.BotQueueConsoleMessage(args[1], args[2], (char*)VMA(3));
			return 0;
		case BOTLIB_AI_REMOVE_CONSOLE_MESSAGE:
			botlib_export->ai.BotRemoveConsoleMessage(args[1], args[2]);
			return 0;
		case BOTLIB_AI_NEXT_CONSOLE_MESSAGE:
			return botlib_export->ai.BotNextConsoleMessage(args[1], (bot_consolemessage_s*)VMA(2));
		case BOTLIB_AI_NUM_CONSOLE_MESSAGE:
			return botlib_export->ai.BotNumConsoleMessages(args[1]);
		case BOTLIB_AI_INITIAL_CHAT:
			botlib_export->ai.BotInitialChat(args[1], (char*)VMA(2), args[3], (char*)VMA(4), (char*)VMA(5), (char*)VMA(6), (char*)VMA(7), (char*)VMA(8), (char*)VMA(9), (char*)VMA(10), (char*)VMA(11));
			return 0;
		case BOTLIB_AI_NUM_INITIAL_CHATS:
			return botlib_export->ai.BotNumInitialChats(args[1], (char*)VMA(2));
		case BOTLIB_AI_REPLY_CHAT:
			return botlib_export->ai.BotReplyChat(args[1], (char*)VMA(2), args[3], args[4], (char*)VMA(5), (char*)VMA(6), (char*)VMA(7), (char*)VMA(8), (char*)VMA(9), (char*)VMA(10), (char*)VMA(11), (char*)VMA(12));
		case BOTLIB_AI_CHAT_LENGTH:
			return botlib_export->ai.BotChatLength(args[1]);
		case BOTLIB_AI_ENTER_CHAT:
			botlib_export->ai.BotEnterChat(args[1], args[2], args[3]);
			return 0;
		case BOTLIB_AI_GET_CHAT_MESSAGE:
			botlib_export->ai.BotGetChatMessage(args[1], (char*)VMA(2), args[3]);
			return 0;
		case BOTLIB_AI_STRING_CONTAINS:
			return botlib_export->ai.StringContains((char*)VMA(1), (char*)VMA(2), args[3]);
		case BOTLIB_AI_FIND_MATCH:
			return botlib_export->ai.BotFindMatch((char*)VMA(1), (bot_match_s*)VMA(2), args[3]);
		case BOTLIB_AI_MATCH_VARIABLE:
			botlib_export->ai.BotMatchVariable((bot_match_s*)VMA(1), args[2], (char*)VMA(3), args[4]);
			return 0;
		case BOTLIB_AI_UNIFY_WHITE_SPACES:
			botlib_export->ai.UnifyWhiteSpaces((char*)VMA(1));
			return 0;
		case BOTLIB_AI_REPLACE_SYNONYMS:
			botlib_export->ai.BotReplaceSynonyms((char*)VMA(1), args[2]);
			return 0;
		case BOTLIB_AI_LOAD_CHAT_FILE:
			return botlib_export->ai.BotLoadChatFile(args[1], (char*)VMA(2), (char*)VMA(3));
		case BOTLIB_AI_SET_CHAT_GENDER:
			botlib_export->ai.BotSetChatGender(args[1], args[2]);
			return 0;
		case BOTLIB_AI_SET_CHAT_NAME:
			botlib_export->ai.BotSetChatName(args[1], (char*)VMA(2));
			return 0;
		case BOTLIB_AI_RESET_GOAL_STATE:
			botlib_export->ai.BotResetGoalState(args[1]);
			return 0;
		case BOTLIB_AI_RESET_AVOID_GOALS:
			botlib_export->ai.BotResetAvoidGoals(args[1]);
			return 0;
		case BOTLIB_AI_REMOVE_FROM_AVOID_GOALS:
			botlib_export->ai.BotRemoveFromAvoidGoals(args[1], args[2]);
			return 0;
		case BOTLIB_AI_PUSH_GOAL:
			botlib_export->ai.BotPushGoal(args[1], (bot_goal_s*)VMA(2));
			return 0;
		case BOTLIB_AI_POP_GOAL:
			botlib_export->ai.BotPopGoal(args[1]);
			return 0;
		case BOTLIB_AI_EMPTY_GOAL_STACK:
			botlib_export->ai.BotEmptyGoalStack(args[1]);
			return 0;
		case BOTLIB_AI_DUMP_AVOID_GOALS:
			botlib_export->ai.BotDumpAvoidGoals(args[1]);
			return 0;
		case BOTLIB_AI_DUMP_GOAL_STACK:
			botlib_export->ai.BotDumpGoalStack(args[1]);
			return 0;
		case BOTLIB_AI_GOAL_NAME:
			botlib_export->ai.BotGoalName(args[1], (char*)VMA(2), args[3]);
			return 0;
		case BOTLIB_AI_GET_TOP_GOAL:
			return botlib_export->ai.BotGetTopGoal(args[1], (bot_goal_s*)VMA(2));
		case BOTLIB_AI_GET_SECOND_GOAL:
			return botlib_export->ai.BotGetSecondGoal(args[1], (bot_goal_s*)VMA(2));
		case BOTLIB_AI_CHOOSE_LTG_ITEM:
			return botlib_export->ai.BotChooseLTGItem(args[1], (float*)VMA(2), (int*)VMA(3), args[4]);
		case BOTLIB_AI_CHOOSE_NBG_ITEM:
			return botlib_export->ai.BotChooseNBGItem(args[1], (float*)VMA(2), (int*)VMA(3), args[4], (bot_goal_s*)VMA(5), VMF(6));
		case BOTLIB_AI_TOUCHING_GOAL:
			return botlib_export->ai.BotTouchingGoal((float*)VMA(1), (bot_goal_s*)VMA(2));
		case BOTLIB_AI_ITEM_GOAL_IN_VIS_BUT_NOT_VISIBLE:
			return botlib_export->ai.BotItemGoalInVisButNotVisible(args[1], (float*)VMA(2), (float*)VMA(3), (bot_goal_s*)VMA(4));
		case BOTLIB_AI_GET_LEVEL_ITEM_GOAL:
			return botlib_export->ai.BotGetLevelItemGoal(args[1], (char*)VMA(2), (bot_goal_s*)VMA(3));
		case BOTLIB_AI_GET_NEXT_CAMP_SPOT_GOAL:
			return botlib_export->ai.BotGetNextCampSpotGoal(args[1], (bot_goal_s*)VMA(2));
		case BOTLIB_AI_GET_MAP_LOCATION_GOAL:
			return botlib_export->ai.BotGetMapLocationGoal((char*)VMA(1), (bot_goal_s*)VMA(2));
		case BOTLIB_AI_AVOID_GOAL_TIME:
			return FloatAsInt(botlib_export->ai.BotAvoidGoalTime(args[1], args[2]));
		case BOTLIB_AI_INIT_LEVEL_ITEMS:
			botlib_export->ai.BotInitLevelItems();
			return 0;
		case BOTLIB_AI_UPDATE_ENTITY_ITEMS:
			botlib_export->ai.BotUpdateEntityItems();
			return 0;
		case BOTLIB_AI_LOAD_ITEM_WEIGHTS:
			return botlib_export->ai.BotLoadItemWeights(args[1], (char*)VMA(2));
		case BOTLIB_AI_FREE_ITEM_WEIGHTS:
			botlib_export->ai.BotFreeItemWeights(args[1]);
			return 0;
		case BOTLIB_AI_INTERBREED_GOAL_FUZZY_LOGIC:
			botlib_export->ai.BotInterbreedGoalFuzzyLogic(args[1], args[2], args[3]);
			return 0;
		case BOTLIB_AI_SAVE_GOAL_FUZZY_LOGIC:
			botlib_export->ai.BotSaveGoalFuzzyLogic(args[1], (char*)VMA(2));
			return 0;
		case BOTLIB_AI_MUTATE_GOAL_FUZZY_LOGIC:
			botlib_export->ai.BotMutateGoalFuzzyLogic(args[1], VMF(2));
			return 0;
		case BOTLIB_AI_ALLOC_GOAL_STATE:
			return botlib_export->ai.BotAllocGoalState(args[1]);
		case BOTLIB_AI_FREE_GOAL_STATE:
			botlib_export->ai.BotFreeGoalState(args[1]);
			return 0;
		case BOTLIB_AI_RESET_MOVE_STATE:
			botlib_export->ai.BotResetMoveState(args[1]);
			return 0;
		case BOTLIB_AI_MOVE_TO_GOAL:
			botlib_export->ai.BotMoveToGoal((bot_moveresult_s*)VMA(1), args[2], (bot_goal_s*)VMA(3), args[4]);
			return 0;
		case BOTLIB_AI_MOVE_IN_DIRECTION:
			return botlib_export->ai.BotMoveInDirection(args[1], (float*)VMA(2), VMF(3), args[4]);
		case BOTLIB_AI_RESET_AVOID_REACH:
			botlib_export->ai.BotResetAvoidReach(args[1]);
			return 0;
		case BOTLIB_AI_RESET_LAST_AVOID_REACH:
			botlib_export->ai.BotResetLastAvoidReach(args[1]);
			return 0;
		case BOTLIB_AI_REACHABILITY_AREA:
			return botlib_export->ai.BotReachabilityArea((float*)VMA(1), args[2]);
		case BOTLIB_AI_MOVEMENT_VIEW_TARGET:
			return botlib_export->ai.BotMovementViewTarget(args[1], (bot_goal_s*)VMA(2), args[3], VMF(4), (float*)VMA(5));
		case BOTLIB_AI_PREDICT_VISIBLE_POSITION:
			return botlib_export->ai.BotPredictVisiblePosition((float*)VMA(1), args[2], (bot_goal_s*)VMA(3), args[4], (vec_t*)VMA(5));
		case BOTLIB_AI_ALLOC_MOVE_STATE:
			return botlib_export->ai.BotAllocMoveState();
		case BOTLIB_AI_FREE_MOVE_STATE:
			botlib_export->ai.BotFreeMoveState(args[1]);
			return 0;
		case BOTLIB_AI_INIT_MOVE_STATE:
			botlib_export->ai.BotInitMoveState(args[1], (bot_initmove_s*)VMA(2));
			return 0;
		case BOTLIB_AI_INIT_AVOID_REACH:
			botlib_export->ai.BotInitAvoidReach(args[1]);
			return 0;
		case BOTLIB_AI_CHOOSE_BEST_FIGHT_WEAPON:
			return botlib_export->ai.BotChooseBestFightWeapon(args[1], (int*)VMA(2));
		case BOTLIB_AI_GET_WEAPON_INFO:
			botlib_export->ai.BotGetWeaponInfo(args[1], args[2], (weaponinfo_s*)VMA(3));
			return 0;
		case BOTLIB_AI_LOAD_WEAPON_WEIGHTS:
			return botlib_export->ai.BotLoadWeaponWeights(args[1], (char*)VMA(2));
		case BOTLIB_AI_ALLOC_WEAPON_STATE:
			return botlib_export->ai.BotAllocWeaponState();
		case BOTLIB_AI_FREE_WEAPON_STATE:
			botlib_export->ai.BotFreeWeaponState(args[1]);
			return 0;
		case BOTLIB_AI_RESET_WEAPON_STATE:
			botlib_export->ai.BotResetWeaponState(args[1]);
			return 0;
		case BOTLIB_AI_GENETIC_PARENTS_AND_CHILD_SELECTION:
			return botlib_export->ai.GeneticParentsAndChildSelection(args[1], (float*)VMA(2), (int*)VMA(3), (int*)VMA(4), (int*)VMA(5));
		case G_ADD_PHYSICS_ENTITY:
#ifdef USE_PHYSICS
			CMod_PhysicsAddEntity((sharedEntity_t*)VMA(1));
#endif
			return 0;
		case G_ADD_PHYSICS_STATIC:
#ifdef USE_PHYSICS
			CMod_PhysicsAddStatic((sharedEntity_t*)VMA(1));
#endif
			return 0;
		case TRAP_MEMSET:
			memset(VMA(1), args[2], args[3]);
			return 0;
		case TRAP_MEMCPY:
			memcpy(VMA(1), VMA(2), args[3]);
			return 0;
		case TRAP_STRNCPY:
			return (intptr_t)strncpy( (char*)VMA( 1 ), (char*)VMA( 2 ), args[3] );
		case TRAP_SIN:
			return FloatAsInt(sin(VMF(1)));
		case TRAP_COS:
			return FloatAsInt(cos(VMF(1)));
		case TRAP_ATAN2:
			return FloatAsInt(atan2(VMF(1), VMF(2)));
		case TRAP_SQRT:
			return FloatAsInt(sqrt(VMF(1)));
		case TRAP_MATRIXMULTIPLY:
			AxisMultiply((vec3_t*)VMA(1), (vec3_t*)VMA(2), (vec3_t*)VMA(3));
			return 0;
		case TRAP_ANGLEVECTORS:
			AngleVectors((vec_t*)VMA(1), (vec_t*)VMA(2), (vec_t*)VMA(3), (vec_t*)VMA(4));
			return 0;
		case TRAP_PERPENDICULARVECTOR:
			PerpendicularVector((vec_t*)VMA(1), (vec_t*)VMA(2));
			return 0;
		case TRAP_FLOOR:
			return FloatAsInt(floor(VMF(1)));
		case TRAP_CEIL:
			return FloatAsInt(ceil(VMF(1)));
		case G_SENDMESSAGE:
			SV_SendBinaryMessage(args[1], (char*)VMA(2), args[3]);
			return 0;
		case G_MESSAGESTATUS:
			return SV_BinaryMessageStatus(args[1]);
#if defined(ET_MYSQL)
        case G_SQL_RUNQUERY:
                return OW_RunQuery( (char*)VMA(1) );
        case G_SQL_FINISHQUERY:
                OW_FinishQuery( args[1] );
                return 0;
        case G_SQL_NEXTROW:
                return OW_NextRow( args[1] );
        case G_SQL_ROWCOUNT:
                return OW_RowCount( args[1] );
        case G_SQL_GETFIELDBYID:
                OW_GetFieldByID( args[1], args[2], (char*)VMA(3), args[4]  );
                return 0;
        case G_SQL_GETFIELDBYNAME:
                OW_GetFieldByName( args[1], (char*)VMA(2), (char*)VMA(3), args[4] );
                return 0;
        case G_SQL_GETFIELDBYID_INT:
                return OW_GetFieldByID_int( args[1], args[2] );
        case G_SQL_GETFIELDBYNAME_INT:
                return OW_GetFieldByName_int( args[1], (char*)VMA(2) );
        case G_SQL_FIELDCOUNT:
                return OW_FieldCount( args[1] );
        case G_SQL_CLEANSTRING:
                OW_CleanString( (char*)VMA(1), (char*)VMA(2), args[3] );
                return 0;
#endif
		case G_RSA_GENMSG:
			return SV_RSAGenMsg( (char*)VMA(1), (char*)VMA(2), (char*)VMA(3) );
		default:
			Com_Error( ERR_DROP, "Bad game system trap: %ld", (long int) args[0] );
	}
	return -1;
}
Exemple #8
0
/*
============
CalculateRanks

Recalculates the score ranks of all players
This will be called on every client connect, begin, disconnect, death,
and team change.
============
*/
void CalculateRanks()
{
	theLevel.follow1_ = -1;
	theLevel.follow2_ = -1;
	theLevel.numConnectedClients_ = 0;
	theLevel.numNonSpectatorClients_ = 0;
	theLevel.numPlayingClients_ = 0;
	theLevel.numVotingClients_ = 0;		// don't count bots
	for( int i = 0; i < ClientBase::TEAM_NUM_TEAMS; i++ ) 
		theLevel.numteamVotingClients_[i] = 0;

	for( int i = 1 ; i <= theLevel.maxclients_ ; i++ ) 
	{
		GameClient* client = theLevel.getClient(i);
		if( client && client->pers_.connected_ != GameClient::ClientPersistant::CON_DISCONNECTED ) 
		{
			theLevel.sortedClients_[theLevel.numConnectedClients_] = i;
			theLevel.numConnectedClients_++;

			if( client->sess_.sessionTeam_ != ClientBase::TEAM_SPECTATOR ) 
			{
				theLevel.numNonSpectatorClients_++;
			
				// decide if this should be auto-followed
				if ( client->pers_.connected_ == GameClient::ClientPersistant::CON_CONNECTED ) 
				{
					theLevel.numPlayingClients_++;
					if( !(theLevel.getEntity(i)->r.svFlags & SVF_BOT) ) 
					{
						theLevel.numVotingClients_++;
						if( client->sess_.sessionTeam_ == ClientBase::TEAM_RED )
							theLevel.numteamVotingClients_[0]++;
						else if( client->sess_.sessionTeam_ == ClientBase::TEAM_BLUE )
							theLevel.numteamVotingClients_[1]++;
					}
					if( theLevel.follow1_ == -1 ) 
						theLevel.follow1_ = i;
					else if( theLevel.follow2_ == -1 ) 
						theLevel.follow2_ = i;
				}
			}
		}
	}

	qsort( theLevel.sortedClients_, theLevel.numConnectedClients_, 
		sizeof(theLevel.sortedClients_[0]), SortRanks );

	// set the rank value for all clients that are connected and not spectators
	if( g_gametype.integer >= GT_TEAM ) 
	{
		// in team games, rank is just the order of the teams, 0=red, 1=blue, 2=tied
		for ( int i = 0;  i < theLevel.numConnectedClients_; i++ ) 
		{
			GameClient *cl =  theLevel.getClient(theLevel.sortedClients_[i]);
			if( theLevel.teamScores_[ClientBase::TEAM_RED] == theLevel.teamScores_[ClientBase::TEAM_BLUE] ) 
				cl->ps_.persistant[PERS_RANK] = 2;
			else if( theLevel.teamScores_[ClientBase::TEAM_RED] > theLevel.teamScores_[ClientBase::TEAM_BLUE] ) 
				cl->ps_.persistant[PERS_RANK] = 0;
			else
				cl->ps_.persistant[PERS_RANK] = 1;
		}
	} 
	else 
	{	
		int rank = -1;
		int score = 0;
		for( int i = 0;  i < theLevel.numPlayingClients_; i++ ) 
		{
			GameClient *cl = theLevel.getClient(theLevel.sortedClients_[i]);
			int newScore = cl->ps_.persistant[PERS_SCORE];
			if( i == 0 || newScore != score ) 
			{
				rank = i;
				// assume we aren't tied until the next client is checked
				theLevel.getClient(theLevel.sortedClients_[i])->ps_.persistant[PERS_RANK] = rank;
			} 
			else 
			{
				// we are tied with the previous client
				theLevel.getClient(theLevel.sortedClients_[i-1])->ps_.persistant[PERS_RANK] = rank | RANK_TIED_FLAG;
				theLevel.getClient(theLevel.sortedClients_[i])->ps_.persistant[PERS_RANK] = rank | RANK_TIED_FLAG;
			}
			score = newScore;
			if( g_gametype.integer == GT_SINGLE_PLAYER && theLevel.numPlayingClients_ == 1 ) 
				theLevel.getClient(theLevel.sortedClients_[i])->ps_.persistant[PERS_RANK] = rank | RANK_TIED_FLAG;
		}
	}

	// set the CS_SCORES1/2 configstrings, which will be visible to everyone
	if( g_gametype.integer >= GT_TEAM ) 
	{
		SV_SetConfigstring( CS_SCORES1, va("%i", theLevel.teamScores_[ClientBase::TEAM_RED] ) );
		SV_SetConfigstring( CS_SCORES2, va("%i", theLevel.teamScores_[ClientBase::TEAM_BLUE] ) );
	} 
	else
	{
		if( theLevel.numConnectedClients_ == 0 ) 
		{
			SV_SetConfigstring( CS_SCORES1, va("%i", SCORE_NOT_PRESENT) );
			SV_SetConfigstring( CS_SCORES2, va("%i", SCORE_NOT_PRESENT) );
		}
		else if( theLevel.numConnectedClients_ == 1 ) 
		{
			SV_SetConfigstring( CS_SCORES1, va("%i", theLevel.getClient(theLevel.sortedClients_[0])->ps_.persistant[PERS_SCORE] ) );
			SV_SetConfigstring( CS_SCORES2, va("%i", SCORE_NOT_PRESENT) );
		} 
		else
		{
			SV_SetConfigstring( CS_SCORES1, va("%i", theLevel.getClient(theLevel.sortedClients_[0])->ps_.persistant[PERS_SCORE] ) );
			SV_SetConfigstring( CS_SCORES2, va("%i", theLevel.getClient(theLevel.sortedClients_[1])->ps_.persistant[PERS_SCORE] ) );
		}
	}

	// see if it is time to end the level
	CheckExitRules();

	// if we are at the intermission, send the New info to everyone
	if( theLevel.intermissiontime_ ) 
		SendScoreboardMessageToAllClients();
}
Exemple #9
0
static void SV_SpawnServer_after_FS_Restart( cb_context_t *context, int status ) {
	int                i;
	int                checksum;
	qboolean           isBot;
	char               systemInfo[16384];
	const char         *p;
	spawnserver_data_t *data;
	cb_context_t       *after;
	char               mapname[MAX_QPATH];
	qboolean           killBots;

	data = (spawnserver_data_t*)context->data;
	Q_strncpyz(mapname, data->mapname, MAX_QPATH);
	killBots = data->killBots;
	after = data->after;
	cb_free_context(context);
	
	CM_LoadMap( va("maps/%s.bsp", mapname), qfalse, &checksum );

	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, sv.time);
		SV_BotFrame (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;

			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->lastSnapshotTime = 0;	// 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, sv.time);
	SV_BotFrame (sv.time);
	sv.time += 100;
	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();

#ifndef DEDICATED
	if ( com_dedicated->integer ) {
		// restart renderer in order to show console for dedicated servers
		// launched through the regular binary
		CL_StartHunkUsers( qtrue );
	}
#endif

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

	if (after) {
		cb_run(after, 0);
	}
}
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
/*
================
SV_SpawnServer

Change the server to a new map, taking all connected
clients along with it.
================
*/
void SV_SpawnServer( const char *server, ForceReload_e eForceReload, qboolean bAllowScreenDissolve )
{
	int			i;
	int			checksum;

	re.RegisterMedia_LevelLoadBegin( server, eForceReload, bAllowScreenDissolve );


	Cvar_SetValue( "cl_paused", 0 );
	Cvar_Set( "timescale", "1" );//jic we were skipping

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

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

	// Moved up from below to help reduce fragmentation
	if (svs.snapshotEntities)
	{
		Z_Free(svs.snapshotEntities);
		svs.snapshotEntities = NULL;
	}

	// don't let sound stutter and dump all stuff on the hunk
	CL_MapLoading();

	if (!CM_SameMap(server))
	{ //rww - only clear if not loading the same map
		CM_ClearMap();
	}
	else if (CM_HasTerrain())
	{ //always clear when going between maps with terrain
		CM_ClearMap();
	}

	// Miniheap never changes sizes, so I just put it really early in mem.
	G2VertSpaceServer->ResetHeap();

	Hunk_Clear();

	// wipe the entire per-level structure
	// Also moved up, trying to do all freeing before new allocs
	for ( i = 0 ; i < MAX_CONFIGSTRINGS ; i++ ) {
		if ( sv.configstrings[i] ) {
			Z_Free( sv.configstrings[i] );
			sv.configstrings[i] = NULL;
		}
	}

	// Collect all the small allocations done by the cvar system
	// This frees, then allocates. Make it the last thing before other
	// allocations begin!
	Cvar_Defrag();

/*
		This is useful for debugging memory fragmentation.  Please don't
	   remove it.
*/

	// init client structures and svs.numSnapshotEntities
	// This is moved down quite a bit, but should be safe. And keeps
	// svs.clients right at the beginning of memory
	if ( !Cvar_VariableIntegerValue("sv_running") ) {
		SV_Startup();
	}

 	// clear out those shaders, images and Models
	/*R_InitImages();
	R_InitShaders();
	R_ModelInit();*/

	re.SVModelInit();

	// allocate the snapshot entities 
	svs.snapshotEntities = (entityState_t *) Z_Malloc (sizeof(entityState_t)*svs.numSnapshotEntities, TAG_CLIENTS, qtrue );

	Music_SetLevelName(server);

	// 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", va("map %s", server) );


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


	for ( i = 0 ; i < MAX_CONFIGSTRINGS ; i++ ) {
		sv.configstrings[i] = CopyString("");
	}

	sv.time = 1000;
	re.G2API_SetTime(sv.time,G2T_SV_TIME);

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

	// 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;
	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++ ) {
		ge->RunFrame( sv.time );
		sv.time += 100;
		re.G2API_SetTime(sv.time,G2T_SV_TIME);
	}
#ifndef JK2_MODE
	ge->ConnectNavs(sv_mapname->string, sv_mapChecksum->integer);
#endif

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

	for (i=0 ; i<1 ; i++) {
		// clear all time counters, because we have reset sv.time
		svs.clients[i].lastPacketTime = 0;
		svs.clients[i].lastConnectTime = 0;
		svs.clients[i].nextSnapshotTime = 0;

		// send the new gamestate to all connected clients
		if (svs.clients[i].state >= CS_CONNECTED) {
			char	*denied;

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

	// run another frame to allow things to look at all connected clients
	ge->RunFrame( sv.time );
	sv.time += 100;
	re.G2API_SetTime(sv.time,G2T_SV_TIME);


	// save systeminfo and serverinfo strings
	SV_SetConfigstring( CS_SYSTEMINFO, Cvar_InfoString( CVAR_SYSTEMINFO ) );
	cvar_modifiedFlags &= ~CVAR_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;

	Hunk_SetMark();
	Z_Validate();
	Z_Validate();
	Z_Validate();
	
	Com_Printf ("-----------------------------------\n");
}
/*
================
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, bool killBots ) 
{
	int			i;
	int			checksum;
	bool		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
	theSVS.snapshotEntities_ = reinterpret_cast<entityState_t*>(
					Hunk_Alloc( sizeof(entityState_t)*theSVS.numSnapshotEntities_, h_high ));
	theSVS.nextSnapshotEntities_ = 0;

	// toggle the server bit so clients can detect that a
	// server has changed
	theSVS.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++ ) {
		theSV.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());
	theSV.checksumFeed_ = ( ((int) rand() << 16) ^ rand() ) ^ Com_Milliseconds();
	FS_Restart( theSV.checksumFeed_ );

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

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

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

	// serverid should be different each time
	theSV.serverId_ = com_frameTime;
	theSV.restartedServerId_ = theSV.serverId_; // I suppose the init here is just to be safe
	theSV.checksumFeedServerId_ = theSV.serverId_;
	Cvar_Set( "sv_serverid", va("%i", theSV.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
	theSV.state_ = Server::SS_LOADING;

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

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

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

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

	for( i = 1 ; i <= sv_maxclients->integer ; i++ ) 
	{
		SV_Client* cl = theSVS.svClients_.at(i);

		if( !cl ) 
			continue;

		// send the New gamestate to all connected clients
		if( cl->state_ >= SV_Client::CS_CONNECTED )
		{
			char	*denied;

			if( cl->netchan_.remoteAddress.type == NA_BOT )
			{
				if( killBots ) 
				{
					SV_DropClient( cl, "" );
					continue;
				}
				isBot = true;
			}
			else 
			{
				isBot = false;
			}

			// connect the client again
			//denied = reinterpret_cast<char*>(VM_ExplicitArgPtr( gvm, VM_Call( gvm, GAME_CLIENT_CONNECT, i, false, isBot ) ));	// firstTime = false
			denied = theSG.clientConnect( i, false, isBot );
			if ( denied ) 
			{
				// this generally shouldn't happen, because the client
				// was connected before the level change
				SV_DropClient( cl, denied );
			} 
			else
			{
				if( !isBot ) 
				{
					// when we get the next packet from a connected client,
					// the New gamestate will be sent
					cl->state_ = SV_Client::CS_CONNECTED;
				}
				else 
				{
					EntityBase		*ent;

					cl->state_ = SV_Client::CS_ACTIVE;
//#pragma message("does the entity already exist there ??")
					ent = theSV.getEntityByNum( i );
					ent->s.number = i;
					//cl->gentity_ = ent;

					cl->deltaMessage_ = -1;
					cl->nextSnapshotTime_ = theSVS.time_;	// generate a snapshot immediately

					//VM_Call( gvm, GAME_CLIENT_BEGIN, i );
					theSG.clientBegin( i );
				}
			}
		}
	}	

	// run another frame to allow things to look at all the players
	//VM_Call( gvm, GAME_RUN_FRAME, svs.time );
	theSG.gameRunFrame( theSVS.time_ );
	theSVS.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
	theSV.state_ = Server::SS_GAME;

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

	Hunk_SetMark();

	Com_Printf ("-----------------------------------\n");
}
Exemple #13
0
/*
================
SV_MapRestart_f

Completely restarts a level, but doesn't send a new gamestate to the clients.
This allows fair starts with variable load times.
================
*/
static void SV_MapRestart_f(void)
{
	int         i;
	client_t    *client;
	char        *denied;
	qboolean    isBot;
	int         delay = 0;
	gamestate_t new_gs, old_gs;

	// make sure we aren't restarting twice in the same frame
	if (com_frameTime == sv.serverId)
	{
		return;
	}

	// make sure server is running
	if (!com_sv_running->integer)
	{
		Com_Printf("Server is not running.\n");
		return;
	}

	if (Cmd_Argc() > 1)
	{
		delay = atoi(Cmd_Argv(1));
	}

	if (delay)
	{
		sv.restartTime = svs.time + delay * 1000;
		SV_SetConfigstring(CS_WARMUP, va("%i", sv.restartTime));
		return;
	}

	// read in gamestate or just default to GS_PLAYING
	old_gs = atoi(Cvar_VariableString("gamestate"));

	if (Cmd_Argc() > 2)
	{
		new_gs = atoi(Cmd_Argv(2));
	}
	else
	{
		new_gs = GS_PLAYING;
	}

	if (!SV_TransitionGameState(new_gs, old_gs, delay))
	{
		return;
	}

	// check for changes in variables that can't just be restarted
	// check for maxclients change
	if (sv_maxclients->modified)
	{
		char mapname[MAX_QPATH];

		Com_Printf("sv_maxclients variable change -- restarting.\n");
		// restart the map the slow way
		Q_strncpyz(mapname, Cvar_VariableString("mapname"), sizeof(mapname));

		SV_SpawnServer(mapname);
		return;
	}

	SV_DemoStopAll();

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

	// generate a new serverid
	// don't update restartedserverId there, otherwise we won't deal correctly with multiple map_restart
	sv.serverId = com_frameTime;
	Cvar_Set("sv_serverid", va("%i", sv.serverId));

	// reset all the vm data in place without changing memory allocation
	// note that we do NOT set sv.state = SS_LOADING, so configstrings that
	// had been changed from their default values will generate broadcast updates
	sv.state      = SS_LOADING;
	sv.restarting = qtrue;

	SV_RestartGameProgs();

	// 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;
	}

	sv.state      = SS_GAME;
	sv.restarting = qfalse;

	// connect and begin all the clients
	for (i = 0 ; i < sv_maxclients->integer ; i++)
	{
		client = &svs.clients[i];

		// send the new gamestate to all connected clients
		if (client->state < CS_CONNECTED)
		{
			continue;
		}

		if (client->netchan.remoteAddress.type == NA_BOT)
		{
			isBot = qtrue;
		}
		else
		{
			isBot = qfalse;
		}

		// add the map_restart command
		SV_AddServerCommand(client, "map_restart\n");

		// connect the client again, without the firstTime flag
		denied = VM_ExplicitArgPtr(gvm, VM_Call(gvm, GAME_CLIENT_CONNECT, i, qfalse, isBot));
		if (denied)
		{
			// this generally shouldn't happen, because the client
			// was connected before the level change
			SV_DropClient(client, denied);
			if (!isBot)
			{
				Com_Printf("SV_MapRestart_f(%d): dropped client %i - denied!\n", delay, i);   // bk010125
			}

			continue;
		}

		// Player won't enter the world until the download is done
		if (client->download == 0)
		{
			if (client->state == CS_ACTIVE)
			{
				SV_ClientEnterWorld(client, &client->lastUsercmd);
			}
			else
			{
				// If we don't reset client->lastUsercmd and are restarting during map load,
				// the client will hang because we'll use the last Usercmd from the previous map,
				// which is wrong obviously.
				SV_ClientEnterWorld(client, NULL);
			}
		}
	}

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

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

Change the server to a new map, taking all connected
clients along with it.
================
*/
void SV_SpawnServer( char *server, ForceReload_e eForceReload, qboolean bAllowScreenDissolve )
{
	int			i;
	int			checksum;

	RE_RegisterMedia_LevelLoadBegin( server, eForceReload, bAllowScreenDissolve );


	Cvar_SetValue( "cl_paused", 0 );
	Cvar_Set( "timescale", "1" );//jic we were skipping

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

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

	// init client structures and svs.numSnapshotEntities 
	if ( !Cvar_VariableIntegerValue("sv_running") ) {
		SV_Startup();
	}		

	// don't let sound stutter and dump all stuff on the hunk
	CL_MapLoading();

	Hunk_Clear();
 	// clear out those shaders, images and Models
	R_InitImages();
	R_InitShaders();
	R_ModelInit();

	// create a heap for Ghoul2 to use for game side model vertex transforms used in collision detection
	if (!G2VertSpaceServer)
	{
		static const int MiniHeapSize=128 * 1024; // maxsize of ghoul2 miniheap
		G2VertSpaceServer	= new CMiniHeap(MiniHeapSize);
	}

	if (svs.snapshotEntities)
	{
		Z_Free(svs.snapshotEntities);
	}
	// allocate the snapshot entities 
	svs.snapshotEntities = (entityState_t *) Z_Malloc (sizeof(entityState_t)*svs.numSnapshotEntities, TAG_CLIENTS, qtrue );

	Music_SetLevelName(server);

	// 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", va("map %s", server) );

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

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


	for ( i = 0 ; i < MAX_CONFIGSTRINGS ; i++ ) {
		sv.configstrings[i] = CopyString("");
	}

	sv.time = 1000;
	G2API_SetTime(sv.time,G2T_SV_TIME);

	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;
	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++ ) {
		ge->RunFrame( sv.time );
		sv.time += 100;
		G2API_SetTime(sv.time,G2T_SV_TIME);
	}

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

	for (i=0 ; i<1 ; i++) {
		// clear all time counters, because we have reset sv.time
		svs.clients[i].lastPacketTime = 0;
		svs.clients[i].lastConnectTime = 0;
		svs.clients[i].nextSnapshotTime = 0;

		// send the new gamestate to all connected clients
		if (svs.clients[i].state >= CS_CONNECTED) {
			char	*denied;

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

	// run another frame to allow things to look at all connected clients
	ge->RunFrame( sv.time );
	sv.time += 100;
	G2API_SetTime(sv.time,G2T_SV_TIME);


	// save systeminfo and serverinfo strings
	SV_SetConfigstring( CS_SYSTEMINFO, Cvar_InfoString( CVAR_SYSTEMINFO ) );
	cvar_modifiedFlags &= ~CVAR_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
	svs.nextHeartbeatTime = -9999999;

	Hunk_SetMark();
	
	Com_Printf ("-----------------------------------\n");
}
Exemple #15
0
/*
==================
SV_Frame

Player movement occurs as a result of packet events, which
happen before SV_Frame is called
==================
*/
void SV_Frame(int msec) {
	int             frameMsec, startTime, frameStartTime = 0, frameEndTime;
	char            mapname[MAX_QPATH];
	// Dushan
	static int      start, end;

	start = Sys_Milliseconds ();
	svs.stats.idle += (double)(start - end) / 1000;

	// the menu kills the server with this cvar
	if(sv_killserver->integer) {
		SV_Shutdown("Server was killed.\n");
		Cvar_Set("sv_killserver", "0");
		return;
	}

	if(!com_sv_running->integer) {
		// Running as a server, but no map loaded
#if defined (DEDICATED)
		// Block until something interesting happens
		Sys_Sleep(-1);
#endif
		return;
	}

	// allow pause if only the local client is connected
	if(SV_CheckPaused()) {
		return;
	}

	if(com_dedicated->integer) {
		frameStartTime = Sys_Milliseconds();
	}

	// if it isn't time for the next frame, do nothing
	if(sv_fps->integer < 1) {
		Cvar_Set("sv_fps", "10");
	}

	frameMsec = 1000 / sv_fps->integer * com_timescale->value;
	// don't let it scale below 1ms
	if(frameMsec < 1) {
		Cvar_Set("timescale", va("%f", sv_fps->integer / 1000.0f));
		frameMsec = 1;
	}

	sv.timeResidual += msec;

	if(!com_dedicated->integer) {
		SV_BotFrame(svs.time + sv.timeResidual);
	}

	if(com_dedicated->integer && sv.timeResidual < frameMsec) {
		// NET_Sleep will give the OS time slices until either get a packet
		// or time enough for a server frame has gone by
		NET_Sleep(frameMsec - sv.timeResidual);
		return;
	}

	// if time is about to hit the 32nd bit, kick all clients
	// and clear sv.time, rather
	// than checking for negative time wraparound everywhere.
	// 2giga-milliseconds = 23 days, so it won't be too often
	if(svs.time > 0x70000000) {
		Q_strncpyz(mapname, sv_mapname->string, MAX_QPATH);
		SV_Shutdown("Restarting server due to time wrapping");
		// TTimo
		// show_bug.cgi?id=388
		// there won't be a map_restart if you have shut down the server
		// since it doesn't restart a non-running server
		// instead, re-run the current map
		Cbuf_AddText(va("map %s\n", mapname));
		return;
	}
	// this can happen considerably earlier when lots of clients play and the map doesn't change
	if(svs.nextSnapshotEntities >= 0x7FFFFFFE - svs.numSnapshotEntities) {
		Q_strncpyz(mapname, sv_mapname->string, MAX_QPATH);
		SV_Shutdown("Restarting server due to numSnapshotEntities wrapping");
		// TTimo see above
		Cbuf_AddText(va("map %s\n", mapname));
		return;
	}

	if(sv.restartTime && svs.time >= sv.restartTime) {
		sv.restartTime = 0;
		Cbuf_AddText("map_restart 0\n");
		return;
	}

	// update infostrings if anything has been changed
	if(cvar_modifiedFlags & CVAR_SERVERINFO) {
		SV_SetConfigstring(CS_SERVERINFO, Cvar_InfoString(CVAR_SERVERINFO | CVAR_SERVERINFO_NOUPDATE));
		cvar_modifiedFlags &= ~CVAR_SERVERINFO;
	}
	if(cvar_modifiedFlags & CVAR_SERVERINFO_NOUPDATE) {
		SV_SetConfigstringNoUpdate(CS_SERVERINFO, Cvar_InfoString(CVAR_SERVERINFO | CVAR_SERVERINFO_NOUPDATE));
		cvar_modifiedFlags &= ~CVAR_SERVERINFO_NOUPDATE;
	}
	if(cvar_modifiedFlags & CVAR_SYSTEMINFO) {
		SV_SetConfigstring(CS_SYSTEMINFO, Cvar_InfoString_Big(CVAR_SYSTEMINFO));
		cvar_modifiedFlags &= ~CVAR_SYSTEMINFO;
	}
	// NERVE - SMF
	if(cvar_modifiedFlags & CVAR_WOLFINFO) {
		SV_SetConfigstring(CS_WOLFINFO, Cvar_InfoString(CVAR_WOLFINFO));
		cvar_modifiedFlags &= ~CVAR_WOLFINFO;
	}

	if(com_speeds->integer) {
		startTime = Sys_Milliseconds();
	} else {
		startTime = 0;			// quite a compiler warning
	}

	// update ping based on the all received frames
	SV_CalcPings();

	if(com_dedicated->integer) {
		SV_BotFrame(svs.time);
	}

	// run the game simulation in chunks
	while(sv.timeResidual >= frameMsec) {
		sv.timeResidual -= frameMsec;
		svs.time += frameMsec;

		// let everything in the world think and move
#if !defined (UPDATE_SERVER)
		VM_Call(gvm, GAME_RUN_FRAME, svs.time);
#endif
		
#ifdef USE_PHYSICS
        CMod_PhysicsUpdate(svs.time, 1.0f / sv_fps->integer);
#endif
	}

	if(com_speeds->integer) {
		time_game = Sys_Milliseconds() - startTime;
	}

	// check timeouts
	SV_CheckTimeouts();

	// check user info buffer thingy
	SV_CheckClientUserinfoTimer();

	// send messages back to the clients
	SV_SendClientMessages();

	// send a heartbeat to the master if needed
	SV_MasterHeartbeat(HEARTBEAT_GAME);

	if(com_dedicated->integer) {
		frameEndTime = Sys_Milliseconds();

		svs.totalFrameTime += (frameEndTime - frameStartTime);
		svs.currentFrameIndex++;

		//if( svs.currentFrameIndex % 50 == 0 )
		//  Com_Printf( "currentFrameIndex: %i\n", svs.currentFrameIndex );

		if(svs.currentFrameIndex == SERVER_PERFORMANCECOUNTER_FRAMES) {
			int averageFrameTime;

			averageFrameTime = svs.totalFrameTime / SERVER_PERFORMANCECOUNTER_FRAMES;

			svs.sampleTimes[svs.currentSampleIndex % SERVER_PERFORMANCECOUNTER_SAMPLES] = averageFrameTime;
			svs.currentSampleIndex++;

			if(svs.currentSampleIndex > SERVER_PERFORMANCECOUNTER_SAMPLES) {
				int totalTime, i;

				totalTime = 0;
				for(i = 0; i < SERVER_PERFORMANCECOUNTER_SAMPLES; i++) {
					totalTime += svs.sampleTimes[i];
				}

				if(!totalTime) {
					totalTime = 1;
				}

				averageFrameTime = totalTime / SERVER_PERFORMANCECOUNTER_SAMPLES;

				svs.serverLoad = (averageFrameTime / (float)frameMsec) * 100;
			}

			//Com_Printf( "serverload: %i (%i/%i)\n", svs.serverLoad, averageFrameTime, frameMsec );

			svs.totalFrameTime = 0;
			svs.currentFrameIndex = 0;
		}
	} else {
		svs.serverLoad = -1;
	}

	// collect timing statistics
	end = Sys_Milliseconds ();
	svs.stats.active += ((double) (end-start)) / 1000;
	if (++svs.stats.count == STATFRAMES) {
		svs.stats.latched_active = svs.stats.active;
		svs.stats.latched_idle = svs.stats.idle;
		svs.stats.latched_packets = svs.stats.packets;
		svs.stats.active = 0;
		svs.stats.idle = 0;
		svs.stats.packets = 0;
		svs.stats.count = 0;
	}
}
Exemple #16
0
/*
=============
CheckTournament

Once a frame, check for changes in tournement player state
=============
*/
void CheckTournament() 
{
	// check because we run 3 game frames before calling Connect and/or ClientBegin
	// for clients on a map_restart
	if( theLevel.numPlayingClients_ == 0 ) 
		return;

	if( g_gametype.integer == GT_TOURNAMENT ) 
	{
		// pull in a spectator if needed
		if( theLevel.numPlayingClients_ < 2 ) 
			AddTournamentPlayer();

		// if we don't have two players, go back to "waiting for players"
		if( theLevel.numPlayingClients_ != 2 )
		{
			if( theLevel.warmupTime_ != -1 ) 
			{
				theLevel.warmupTime_ = -1;
				SV_SetConfigstring( CS_WARMUP, va("%i", theLevel.warmupTime_) );
				G_LogPrintf( "Warmup:\n" );
			}
			return;
		}

		if( theLevel.warmupTime_ == 0 ) 
			return;

		// if the warmup is changed at the console, restart it
		if( g_warmup.modificationCount != theLevel.warmupModificationCount_ ) 
		{
			theLevel.warmupModificationCount_ = g_warmup.modificationCount;
			theLevel.warmupTime_ = -1;
		}

		// if all players have arrived, start the countdown
		if( theLevel.warmupTime_ < 0 ) 
		{
			if( theLevel.numPlayingClients_ == 2 ) 
			{
				// fudge by -1 to account for extra delays
				theLevel.warmupTime_ = theLevel.time_ + ( g_warmup.integer - 1 ) * 1000;
				SV_SetConfigstring( CS_WARMUP, va("%i", theLevel.warmupTime_) );
			}
			return;
		}

		// if the warmup time has counted down, restart
		if( theLevel.time_ > theLevel.warmupTime_ ) 
		{
			theLevel.warmupTime_ += 10000;
			Cvar_Set( "g_restarted", "1" );
			Cbuf_ExecuteText( EXEC_APPEND, "map_restart 0\n" );
			theLevel.restarted_ = true;
			return;
		}
	} 
	else if( g_gametype.integer != GT_SINGLE_PLAYER && g_gametype.integer != GT_MISSION_EDITOR &&
			 theLevel.warmupTime_ != 0 ) 
	{
		int	 counts[ClientBase::TEAM_NUM_TEAMS];
		bool notEnough = false;

		if( g_gametype.integer > GT_TEAM ) 
		{
			counts[ClientBase::TEAM_BLUE] = TeamCount( -1, ClientBase::TEAM_BLUE );
			counts[ClientBase::TEAM_RED] = TeamCount( -1, ClientBase::TEAM_RED );

			if (counts[ClientBase::TEAM_RED] < 1 || counts[ClientBase::TEAM_BLUE] < 1) 
				notEnough = true;
		}
		else if( theLevel.numPlayingClients_ < 2 ) 
			notEnough = true;

		if( notEnough ) 
		{
			if( theLevel.warmupTime_ != -1 ) 
			{
				theLevel.warmupTime_ = -1;
				SV_SetConfigstring( CS_WARMUP, va("%i", theLevel.warmupTime_) );
				G_LogPrintf( "Warmup:\n" );
			}
			return; // still waiting for team members
		}

		if( theLevel.warmupTime_ == 0 ) 
			return;

		// if the warmup is changed at the console, restart it
		if( g_warmup.modificationCount != theLevel.warmupModificationCount_ ) 
		{
			theLevel.warmupModificationCount_ = g_warmup.modificationCount;
			theLevel.warmupTime_ = -1;
		}

		// if all players have arrived, start the countdown
		if( theLevel.warmupTime_ < 0 ) 
		{
			// fudge by -1 to account for extra delays
			theLevel.warmupTime_ = theLevel.time_ + ( g_warmup.integer - 1 ) * 1000;
			SV_SetConfigstring( CS_WARMUP, va("%i", theLevel.warmupTime_) );
			return;
		}

		// if the warmup time has counted down, restart
		if( theLevel.time_ > theLevel.warmupTime_ ) 
		{
			theLevel.warmupTime_ += 10000;
			Cvar_Set( "g_restarted", "1" );
			Cbuf_ExecuteText( EXEC_APPEND, "map_restart 0\n" );
			theLevel.restarted_ = true;
			return;
		}
	}
}
Exemple #17
0
/*
================
SV_MapRestart_f

Completely restarts a level, but doesn't send a new gamestate to the clients.
This allows fair starts with variable load times.
================
*/
static void SV_MapRestart_f(void) {
	int             i, delay = 0;
	client_t       *client;
	char           *denied;
	qboolean        isBot;
	gamestate_t     new_gs, old_gs;	// NERVE - SMF

	// make sure we aren't restarting twice in the same frame
	if(com_frameTime == sv.serverId) {
		return;
	}

	// make sure server is running
	if(!com_sv_running->integer) {
		Com_Printf("Server is not running.\n");
		return;
	}

	if(Cmd_Argc() > 1) {
		delay = atoi(Cmd_Argv(1));
	}

	if(delay) {
		sv.restartTime = svs.time + delay * 1000;
		SV_SetConfigstring(CS_WARMUP, va("%i", sv.restartTime));
		return;
	}

	// NERVE - SMF - read in gamestate or just default to GS_PLAYING
	old_gs = (gamestate_t)atoi(Cvar_VariableString("gamestate"));

	if(SV_GameIsSinglePlayer() || SV_GameIsCoop()) {
		new_gs = GS_PLAYING;
	} else {
		if(Cmd_Argc() > 2) {
			new_gs = (gamestate_t)atoi(Cmd_Argv(2));
		} else {
			new_gs = GS_PLAYING;
		}
	}

	if(!SV_TransitionGameState(new_gs, old_gs, delay)) {
		return;
	}

	// check for changes in variables that can't just be restarted
	// check for maxclients change
	if(sv_maxclients->modified) {
		char mapname[MAX_QPATH];

		Com_Printf("sv_maxclients variable change -- restarting.\n");
		// restart the map the slow way
		Q_strncpyz(mapname, Cvar_VariableString("mapname"), sizeof(mapname));

		SV_SpawnServer(mapname, qfalse);
		return;
	}

	// Check for loading a saved game
	if(Cvar_VariableIntegerValue("savegame_loading")) {
		// open the current savegame, and find out what the time is, everything else we can ignore
		char    savemap[MAX_QPATH], *cl_profileStr = Cvar_VariableString("cl_profile");
		byte    *buffer;
		int     size, savegameTime;

		if(com_gameInfo.usesProfiles) {
			Com_sprintf(savemap, sizeof(savemap), "profiles/%s/save/current.sav", cl_profileStr);
		} else {
			Q_strncpyz(savemap, "save/current.sav", sizeof(savemap));
		}

		size = FS_ReadFile(savemap, NULL);
		if(size < 0) {
			Com_Printf("Can't find savegame %s\n", savemap);
			return;
		}

		//buffer = Hunk_AllocateTempMemory(size);
		FS_ReadFile(savemap, (void **)&buffer);

		// the mapname is at the very start of the savegame file
		savegameTime = *(int *)(buffer + sizeof(int) + MAX_QPATH);

		if(savegameTime >= 0) {
			svs.time = savegameTime;
		}

		Hunk_FreeTempMemory(buffer);
	}
	// done.

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

	// generate a new serverid
	// TTimo - don't update restartedserverId there, otherwise we won't deal correctly with multiple map_restart
	sv.serverId = com_frameTime;
	Cvar_Set("sv_serverid", va("%i", sv.serverId));

	// reset all the vm data in place without changing memory allocation
	// note that we do NOT set sv.state = SS_LOADING, so configstrings that
	// had been changed from their default values will generate broadcast updates
	sv.state = SS_LOADING;
	sv.restarting = qtrue;

	Cvar_Set("sv_serverRestarting", "1");

	SV_RestartGameProgs();

	// 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
	// Gordon: meh, this wont work here as the client doesn't know it has happened
//  SV_CreateBaseline ();

	sv.state = SS_GAME;
	sv.restarting = qfalse;

	// connect and begin all the clients
	for(i = 0; i < sv_maxclients->integer; i++) {
		client = &svs.clients[i];

		// send the new gamestate to all connected clients
		if(client->state < CS_CONNECTED) {
			continue;
		}

		if(client->netchan.remoteAddress.type == NA_BOT) {
			if(SV_GameIsSinglePlayer() || SV_GameIsCoop()) {
				continue;		// dont carry across bots in single player
			}
			isBot = qtrue;
		} else {
			isBot = qfalse;
		}

		// add the map_restart command
		SV_AddServerCommand(client, "map_restart\n");

		// connect the client again, without the firstTime flag
		denied = (char*)VM_ExplicitArgPtr(gvm, VM_Call(gvm, GAME_CLIENT_CONNECT, i, qfalse, isBot));
		if(denied)
		{
			// this generally shouldn't happen, because the client
			// was connected before the level change
			SV_DropClient(client, denied);
			if((!SV_GameIsSinglePlayer()) || (!isBot)) {
				Com_Printf("SV_MapRestart_f(%d): dropped client %i - denied!\n", delay, i);	// bk010125
			}
			continue;
		}

		client->state = CS_ACTIVE;

		SV_ClientEnterWorld(client, &client->lastUsercmd);
	}

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

	Cvar_Set("sv_serverRestarting", "0");
}
Exemple #18
0
/*
==================
SV_Frame

Player movement occurs as a result of packet events, which
happen before SV_Frame is called
==================
*/
void SV_Frame( int msec ) {
	int		frameMsec;
	int		startTime;

	// the menu kills the server with this cvar
	if ( sv_killserver->integer ) {
		SV_Shutdown ("Server was killed.\n");
		Cvar_Set( "sv_killserver", "0" );
		return;
	}

	if ( !com_sv_running->integer ) {
		return;
	}

	// allow pause if only the local client is connected
	if ( SV_CheckPaused() ) {
		return;
	}

	// if it isn't time for the next frame, do nothing
	if ( sv_fps->integer < 1 ) {
		Cvar_Set( "sv_fps", "10" );
	}
	frameMsec = 1000 / sv_fps->integer ;

	sv.timeResidual += msec;

	if (!com_dedicated->integer) SV_BotFrame( svs.time + sv.timeResidual );

	if ( com_dedicated->integer && sv.timeResidual < frameMsec && (!com_timescale || com_timescale->value >= 1) ) {
		// NET_Sleep will give the OS time slices until either get a packet
		// or time enough for a server frame has gone by
		NET_Sleep(frameMsec - sv.timeResidual);
		return;
	}

	// if time is about to hit the 32nd bit, kick all clients
	// and clear sv.time, rather
	// than checking for negative time wraparound everywhere.
	// 2giga-milliseconds = 23 days, so it won't be too often
	if ( svs.time > 0x70000000 ) {
		SV_Shutdown( "Restarting server due to time wrapping" );
		Cbuf_AddText( "vstr nextmap\n" );
		return;
	}
	// this can happen considerably earlier when lots of clients play and the map doesn't change
	if ( svs.nextSnapshotEntities >= 0x7FFFFFFE - svs.numSnapshotEntities ) {
		SV_Shutdown( "Restarting server due to numSnapshotEntities wrapping" );
		Cbuf_AddText( "vstr nextmap\n" );
		return;
	}

	if( sv.restartTime && svs.time >= sv.restartTime ) {
		sv.restartTime = 0;
		Cbuf_AddText( "map_restart 0\n" );
		return;
	}

	// update infostrings if anything has been changed
	if ( cvar_modifiedFlags & CVAR_SERVERINFO ) {
		SV_SetConfigstring( CS_SERVERINFO, Cvar_InfoString( CVAR_SERVERINFO ) );
		cvar_modifiedFlags &= ~CVAR_SERVERINFO;
	}
	if ( cvar_modifiedFlags & CVAR_SYSTEMINFO ) {
		SV_SetConfigstring( CS_SYSTEMINFO, Cvar_InfoString_Big( CVAR_SYSTEMINFO ) );
		cvar_modifiedFlags &= ~CVAR_SYSTEMINFO;
	}

	if ( com_speeds->integer ) {
		startTime = Sys_Milliseconds ();
	} else {
		startTime = 0;	// quite a compiler warning
	}

	// update ping based on the all received frames
	SV_CalcPings();

	if (com_dedicated->integer) SV_BotFrame( svs.time );

	// run the game simulation in chunks
	while ( sv.timeResidual >= frameMsec ) {
		sv.timeResidual -= frameMsec;
		svs.time += frameMsec;

		// let everything in the world think and move
		VM_Call( gvm, GAME_RUN_FRAME, svs.time );
	}

	if ( com_speeds->integer ) {
		time_game = Sys_Milliseconds () - startTime;
	}

	// check timeouts
	SV_CheckTimeouts();

	// send messages back to the clients
	SV_SendClientMessages();

	// send a heartbeat to the master if needed
	SV_MasterHeartbeat();
}
Exemple #19
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_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 ) );

	// 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, qfalse );
				}
			}
		}
	}	

	// 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();
	}
	*/
}
Exemple #20
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;
	char		systemInfo[16384];
	const char	*p;

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

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

	// load map configurations
	SV_MapConfig( 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(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");

	// 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();

	// 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, sv.time);
		SV_BotFrame (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;

			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->lastSnapshotTime = 0;	// 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, sv.time);
	SV_BotFrame (sv.time);
	sv.time += 100;
	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();

#ifndef DEDICATED
	if ( com_dedicated->integer ) {
		// restart renderer in order to show console for dedicated servers
		// launched through the regular binary
		CL_StartHunkUsers( qtrue );
	}
#endif
	
	Com_VPrintf( "-------------------------------\n" );
}
Exemple #21
0
/*
==================
BotSetInfoConfigString
==================
*/
void BotSetInfoConfigString(bot_state_t *bs)
{
    char goalname[MAX_MESSAGE_SIZE];
    char netname[MAX_MESSAGE_SIZE];
    char action[MAX_MESSAGE_SIZE];
    char *leader, carrying[32], *cs;
    bot_goal_t goal;
    //
    ClientName(bs->client, netname, sizeof(netname));
    if (Q_stricmp(netname, bs->teamleader) == 0) leader = "L";
    else leader = " ";

    strcpy(carrying, "  ");
    if (gametype == GT_CTF)
    {
        if (BotCTFCarryingFlag(bs))
        {
            strcpy(carrying, "F ");
        }
    }

    switch(bs->ltgtype)
    {
    case LTG_TEAMHELP:
        {
            EasyClientName(bs->teammate, goalname, sizeof(goalname));
            Com_sprintf(action, sizeof(action), "helping %s", goalname);
            break;
        }
    case LTG_TEAMACCOMPANY:
        {
            EasyClientName(bs->teammate, goalname, sizeof(goalname));
            Com_sprintf(action, sizeof(action), "accompanying %s", goalname);
            break;
        }
    case LTG_DEFENDKEYAREA:
        {
            botlib_export->ai.BotGoalName(bs->teamgoal.number, goalname, sizeof(goalname));
            Com_sprintf(action, sizeof(action), "defending %s", goalname);
            break;
        }
    case LTG_GETITEM:
        {
            botlib_export->ai.BotGoalName(bs->teamgoal.number, goalname, sizeof(goalname));
            Com_sprintf(action, sizeof(action), "getting item %s", goalname);
            break;
        }
    case LTG_KILL:
        {
            ClientName(bs->teamgoal.entitynum, goalname, sizeof(goalname));
            Com_sprintf(action, sizeof(action), "killing %s", goalname);
            break;
        }
    case LTG_CAMP:
    case LTG_CAMPORDER:
        {
            Com_sprintf(action, sizeof(action), "camping");
            break;
        }
    case LTG_PATROL:
        {
            Com_sprintf(action, sizeof(action), "patrolling");
            break;
        }
    case LTG_GETFLAG:
        {
            Com_sprintf(action, sizeof(action), "capturing flag");
            break;
        }
    case LTG_RUSHBASE:
        {
            Com_sprintf(action, sizeof(action), "rushing base");
            break;
        }
    case LTG_RETURNFLAG:
        {
            Com_sprintf(action, sizeof(action), "returning flag");
            break;
        }
    case LTG_ATTACKENEMYBASE:
        {
            Com_sprintf(action, sizeof(action), "attacking the enemy base");
            break;
        }
    case LTG_HARVEST:
        {
            Com_sprintf(action, sizeof(action), "harvesting");
            break;
        }
    default:
        {
            botlib_export->ai.BotGetTopGoal(bs->gs, &goal);
            botlib_export->ai.BotGoalName(goal.number, goalname, sizeof(goalname));
            Com_sprintf(action, sizeof(action), "roaming %s", goalname);
            break;
        }
    }
    cs = va("l\\%s\\c\\%s\\a\\%s",
            leader,
            carrying,
            action);
    SV_SetConfigstring (CS_BOTINFO + bs->client, cs);
}
Exemple #22
0
/*
================
SV_MapRestart_f

Completely restarts a level, but doesn't send a new gamestate to the clients.
This allows fair starts with variable load times.
================
*/
static void SV_MapRestart_f( void ) {
	int			i;
	client_t	*client;
	char		*denied;
	qboolean	isBot;
	int			delay;

	// make sure we aren't restarting twice in the same frame
	if ( com_frameTime == sv.serverId ) {
		return;
	}

	// make sure server is running
	if ( !com_sv_running->integer ) {
		Com_Printf( "Server is not running.\n" );
		return;
	}

	if ( sv.restartTime ) {
		return;
	}

	if (Cmd_Argc() > 1 ) {
		delay = atoi( Cmd_Argv(1) );
	}
	else {
		delay = 5;
	}
	if( delay && !Cvar_VariableValue("g_doWarmup") ) {
		sv.restartTime = sv.time + delay * 1000;
		SV_SetConfigstring( CS_WARMUP, va("%i", sv.restartTime) );
		return;
	}

	// check for changes in variables that can't just be restarted
	// check for maxclients change
	if ( sv_maxclients->modified || sv_gametype->modified ) {
		char	mapname[MAX_QPATH];

		Com_Printf( "variable change -- restarting.\n" );
		// restart the map the slow way
		Q_strncpyz( mapname, Cvar_VariableString( "mapname" ), sizeof( mapname ) );

		SV_SpawnServer( mapname, qfalse );
		return;
	}

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

	// generate a new serverid	
	// TTimo - don't update restartedserverId there, otherwise we won't deal correctly with multiple map_restart
	sv.serverId = com_frameTime;
	Cvar_Set( "sv_serverid", va("%i", sv.serverId ) );

	// reset all the vm data in place without changing memory allocation
	// note that we do NOT set sv.state = SS_LOADING, so configstrings that
	// had been changed from their default values will generate broadcast updates
	sv.state = SS_LOADING;
	sv.restarting = qtrue;

	SV_RestartGameProgs();

	// 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;
	}

	sv.state = SS_GAME;
	sv.restarting = qfalse;

	// connect and begin all the clients
	for (i=0 ; i<sv_maxclients->integer ; i++) {
		client = &svs.clients[i];

		// send the new gamestate to all connected clients
		if ( client->state < CS_CONNECTED) {
			continue;
		}

		if ( client->netchan.remoteAddress.type == NA_BOT ) {
			isBot = qtrue;
		} else {
			isBot = qfalse;
		}

		// add the map_restart command
		SV_AddServerCommand( client, "map_restart\n" );

		// connect the client again, without the firstTime flag
		denied = VM_ExplicitArgPtr( gvm, VM_Call( gvm, GAME_CLIENT_CONNECT, i, qfalse, isBot ) );
		if ( denied ) {
			// this generally shouldn't happen, because the client
			// was connected before the level change
			SV_DropClient( client, denied );
			Com_Printf( "SV_MapRestart_f(%d): dropped client %i - denied!\n", delay, i );
			continue;
		}

		client->state = CS_ACTIVE;

		SV_ClientEnterWorld( client, &client->lastUsercmd );
	}	

	// 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;
}
Exemple #23
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 #24
0
/*
================
SV_MapRestart_f

Completely restarts a level, but doesn't send a new gamestate to the clients.
This allows fair starts with variable load times.
================
*/
static void SV_MapRestart_f( void ) {
	int i;
	client_t    *client;
	char        *denied;
	qboolean isBot;
	int delay = 0;
	gamestate_t new_gs, old_gs;     // NERVE - SMF
	int worldspawnflags;            // DHM - Nerve
	int nextgt;                     // DHM - Nerve
	sharedEntity_t  *world;

	// make sure we aren't restarting twice in the same frame
	if ( com_frameTime == sv.serverId ) {
		return;
	}

	// make sure server is running
	if ( !com_sv_running->integer ) {
		Com_Printf( "Server is not running.\n" );
		return;
	}

	if ( sv.restartTime ) {
		return;
	}

	// DHM - Nerve :: Check for invalid gametype
	sv_gametype = Cvar_Get( "g_gametype", "5", CVAR_SERVERINFO | CVAR_LATCH );
	nextgt = sv_gametype->integer;

	world = SV_GentityNum( ENTITYNUM_WORLD );
	worldspawnflags = world->r.worldflags;
	if  (
		( nextgt == GT_WOLF && ( worldspawnflags & 1 ) ) ||
		( nextgt == GT_WOLF_STOPWATCH && ( worldspawnflags & 2 ) ) ||
		( ( nextgt == GT_WOLF_CP || nextgt == GT_WOLF_CPH ) && ( worldspawnflags & 4 ) )
		) {

		if ( !( worldspawnflags & 1 ) ) {
			Cvar_Set( "g_gametype", "5" );
		} else {
			Cvar_Set( "g_gametype", "7" );
		}

		sv_gametype = Cvar_Get( "g_gametype", "5", CVAR_SERVERINFO | CVAR_LATCH );
	}
	// dhm

	if ( Cmd_Argc() > 1 ) {
		delay = atoi( Cmd_Argv( 1 ) );
	}

	if ( delay ) {
		sv.restartTime = svs.time + delay * 1000;
		SV_SetConfigstring( CS_WARMUP, va( "%i", sv.restartTime ) );
		return;
	}

	// NERVE - SMF - read in gamestate or just default to GS_PLAYING
	old_gs = atoi( Cvar_VariableString( "gamestate" ) );

	if ( Cmd_Argc() > 2 ) {
		new_gs = atoi( Cmd_Argv( 2 ) );
	} else {
		new_gs = GS_PLAYING;
	}

	if ( !SV_TransitionGameState( new_gs, old_gs, delay ) ) {
		return;
	}

	// check for changes in variables that can't just be restarted
	// check for maxclients change
	if ( sv_maxclients->modified ) {
		char mapname[MAX_QPATH];

		Com_Printf( "sv_maxclients variable change -- restarting.\n" );
		// restart the map the slow way
		Q_strncpyz( mapname, Cvar_VariableString( "mapname" ), sizeof( mapname ) );

		SV_SpawnServer( mapname, qfalse );
		return;
	}

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

	// generate a new serverid
	// TTimo - don't update restartedserverId there, otherwise we won't deal correctly with multiple map_restart
	sv.serverId = com_frameTime;
	Cvar_Set( "sv_serverid", va( "%i", sv.serverId ) );

	// reset all the vm data in place without changing memory allocation
	// note that we do NOT set sv.state = SS_LOADING, so configstrings that
	// had been changed from their default values will generate broadcast updates
	sv.state = SS_LOADING;
	sv.restarting = qtrue;

	Cvar_Set( "sv_serverRestarting", "1" );

	SV_RestartGameProgs();

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

	sv.state = SS_GAME;
	sv.restarting = qfalse;

	// connect and begin all the clients
	for ( i = 0 ; i < sv_maxclients->integer ; i++ ) {
		client = &svs.clients[i];

		// send the new gamestate to all connected clients
		if ( client->state < CS_CONNECTED ) {
			continue;
		}

		if ( client->netchan.remoteAddress.type == NA_BOT ) {
			isBot = qtrue;
		} else {
			isBot = qfalse;
		}

		// add the map_restart command
		SV_AddServerCommand( client, "map_restart\n" );

		// connect the client again, without the firstTime flag
		denied = VM_ExplicitArgPtr( gvm, VM_Call( gvm, GAME_CLIENT_CONNECT, i, qfalse, isBot ) );
		if ( denied ) {
			// this generally shouldn't happen, because the client
			// was connected before the level change
			SV_DropClient( client, denied );
			Com_Printf( "SV_MapRestart_f(%d): dropped client %i - denied!\n", delay, i ); // bk010125
			continue;
		}

		client->state = CS_ACTIVE;

		SV_ClientEnterWorld( client, &client->lastUsercmd );
	}

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

	Cvar_Set( "sv_serverRestarting", "0" );
}
Exemple #25
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;
	char systemInfo[MAX_INFO_STRING];
	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( "" );
	}

	// 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) );

	// Ridah
	// DHM - Nerve :: We want to use the completion bar in multiplayer as well
	if ( sv_gametype->integer == GT_SINGLE_PLAYER || sv_gametype->integer >= GT_WOLF ) {
		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 ) );

	// 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
	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 || Cvar_VariableValue( "g_gametype" ) == GT_SINGLE_PLAYER ) {
					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 );
	} 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
	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;

	// NERVE - SMF
	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
	SV_Heartbeat_f();

	Hunk_SetMark();

	Cvar_Set( "sv_serverRestarting", "0" );

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