/* * TVM_InitRelay */ tvm_relay_t *TVM_InitRelay( relay_t *relay_server, unsigned int snapFrameTime, int playernum ) { tvm_relay_t *relay; int i; assert( playernum >= -1 && playernum < MAX_CLIENTS ); TVM_Printf( "==== TVM_InitRelay ====\n" ); relay = TVM_Malloc( relay_server, sizeof( tvm_relay_t ) ); relay->server = relay_server; relay->playernum = playernum; relay->snapFrameTime = snapFrameTime; // initialize all entities for this game relay->maxentities = MAX_EDICTS; relay->maxclients = MAX_CLIENTS; relay->edicts = TVM_Malloc( relay_server, relay->maxentities * sizeof( relay->edicts[0] ) ); relay->clients = TVM_Malloc( relay_server, relay->maxclients * sizeof( relay->clients[0] ) ); relay->numentities = 0; // set relay for( i = 0; i < relay->maxentities; i++ ) relay->edicts[i].relay = relay; trap_LocateEntities( relay, relay->edicts, sizeof( relay->edicts[0] ), relay->numentities, relay->maxentities ); // initialize local entities relay->local_maxentities = MAX_EDICTS; relay->local_maxclients = tvm.maxclients; relay->local_edicts = TVM_Malloc( relay_server, relay->local_maxentities * sizeof( relay->local_edicts[0] ) ); relay->local_clients = TVM_Malloc( relay_server, relay->local_maxclients * sizeof( relay->local_clients[0] ) ); relay->local_numentities = relay->local_maxclients; // set relay and local for( i = 0; i < relay->local_maxentities; i++ ) { relay->local_edicts[i].local = true; relay->local_edicts[i].relay = relay; } // set client fields on player ents for( i = 0; i < relay->local_maxclients; i++ ) relay->local_edicts[i].r.client = relay->local_clients + i; trap_LocateLocalEntities( relay, relay->local_edicts, sizeof( relay->local_edicts[0] ), relay->local_numentities, relay->local_maxclients ); return relay; }
/* * SpawnEntities * * Creates a server's entity / program execution context by * parsing textual entity definitions out of an ent file. */ void G_InitLevel( char *mapname, char *entities, int entstrlen, unsigned int levelTime, unsigned int serverTime, unsigned int realTime ) { char *mapString = NULL; char name[MAX_CONFIGSTRING_CHARS]; int i; edict_t *ent; char *token; const gsitem_t *item; G_asGarbageCollect( true ); GT_asCallShutdown(); G_asCallMapExit(); G_asShutdownMapScript(); GT_asShutdownScript(); G_FreeCallvotes(); game.serverTime = serverTime; game.realtime = realTime; game.levelSpawnCount++; GClip_ClearWorld(); // clear areas links if( !entities ) G_Error( "G_SpawnLevel: NULL entities string\n" ); // make a copy of the raw entities string so it's not freed with the pool mapString = ( char * )G_Malloc( entstrlen + 1 ); memcpy( mapString, entities, entstrlen ); Q_strncpyz( name, mapname, sizeof( name ) ); // clear old data G_LevelInitPool( strlen( mapname ) + 1 + ( entstrlen + 1 ) * 2 + G_LEVELPOOL_BASE_SIZE ); G_StringPoolInit(); memset( &level, 0, sizeof( level_locals_t ) ); memset( &gs.gameState, 0, sizeof( gs.gameState ) ); level.spawnedTimeStamp = game.realtime; level.time = levelTime; level.gravity = g_gravity->value; // get the strings back Q_strncpyz( level.mapname, name, sizeof( level.mapname ) ); level.mapString = ( char * )G_LevelMalloc( entstrlen + 1 ); level.mapStrlen = entstrlen; memcpy( level.mapString, mapString, entstrlen ); G_Free( mapString ); mapString = NULL; // make a copy of the raw entities string for parsing level.map_parsed_ents = ( char * )G_LevelMalloc( entstrlen + 1 ); level.map_parsed_ents[0] = 0; if( !level.time ) memset( game.edicts, 0, game.maxentities * sizeof( game.edicts[0] ) ); else { G_FreeEdict( world ); for( i = gs.maxclients + 1; i < game.maxentities; i++ ) { if( game.edicts[i].r.inuse ) G_FreeEdict( game.edicts + i ); } } game.numentities = gs.maxclients + 1; // link client fields on player ents for( i = 0; i < gs.maxclients; i++ ) { game.edicts[i+1].s.number = i+1; game.edicts[i+1].r.client = &game.clients[i]; game.edicts[i+1].r.inuse = ( trap_GetClientState( i ) >= CS_CONNECTED ) ? true : false; memset( &game.clients[i].level, 0, sizeof( game.clients[0].level ) ); game.clients[i].level.timeStamp = level.time; } // initialize game subsystems trap_ConfigString( CS_MAPNAME, level.mapname ); trap_ConfigString( CS_SKYBOX, "" ); trap_ConfigString( CS_AUDIOTRACK, "" ); trap_ConfigString( CS_STATNUMS, va( "%i %i %i", STAT_SCORE, STAT_HEALTH, STAT_LAST_KILLER ) ); trap_ConfigString( CS_POWERUPEFFECTS, va( "%i %i %i %i", EF_QUAD, EF_SHELL, EF_CARRIER, EF_REGEN ) ); trap_ConfigString( CS_SCB_PLAYERTAB_LAYOUT, "" ); trap_ConfigString( CS_SCB_PLAYERTAB_TITLES, "" ); trap_ConfigString( CS_MATCHNAME, "" ); trap_ConfigString( CS_MATCHSCORE, "" ); // reset map messages for( i = 0; i < MAX_HELPMESSAGES; i++ ) { trap_ConfigString( CS_HELPMESSAGES + i, "" ); } G_InitGameCommands(); G_MapLocations_Init(); G_CallVotes_Init(); G_SpawnQueue_Init(); G_Teams_Init(); // load map script G_asLoadMapScript( level.mapname ); G_Gametype_Init(); // ch : this would be the location to "transfer ratings" G_PrecacheItems(); // set configstrings for items (gametype must be initialized) G_PrecacheMedia(); G_PrecacheGameCommands(); // adding commands after this point won't update them to the client AI_InitLevel(); // load navigation file of the current map // start spawning entities level.canSpawnEntities = true; G_InitBodyQueue(); // reserve some spots for dead player bodies entities = level.mapString; i = 0; ent = NULL; while( 1 ) { level.spawning_entity = NULL; // parse the opening brace token = COM_Parse( &entities ); if( !entities ) break; if( token[0] != '{' ) G_Error( "G_SpawnMapEntities: found %s when expecting {", token ); if( !ent ) { ent = world; G_InitEdict( world ); } else ent = G_Spawn(); ent->spawnString = entities; // keep track of string definition of this entity entities = ED_ParseEdict( entities, ent ); if( !ent->classname ) { i++; // racesow - introducing the freestyle map bug again in // order to make some freestyle maps work if( !level.gametype.freestyleMapFix ) G_FreeEdict( ent ); // !racesow G_FreeEdict( ent ); continue; } if( !G_CanSpawnEntity( ent ) ) { i++; G_FreeEdict( ent ); continue; } if( !G_CallSpawn( ent ) ) { i++; G_FreeEdict( ent ); continue; } // check whether an item is allowed to spawn if( ( item = ent->item ) ) { // not pickable items aren't spawnable if( item->flags & ITFLAG_PICKABLE ) { if( G_Gametype_CanSpawnItem( item ) ) { // override entity's classname with whatever item specifies ent->classname = item->classname; PrecacheItem( item ); continue; } } i++; G_FreeEdict( ent ); continue; } } G_FindTeams(); // is the parsing string sane? assert( (int)level.map_parsed_len < entstrlen ); level.map_parsed_ents[level.map_parsed_len] = 0; // make sure server got the edicts data trap_LocateEntities( game.edicts, sizeof( game.edicts[0] ), game.numentities, game.maxentities ); // items need brush model entities spawned before they are linked G_Items_FinishSpawningItems(); // // initialize game subsystems which require entities initialized // // call gametype specific GT_asCallSpawn(); // call map specific G_asCallMapInit(); AI_InitEntitiesData(); // always start in warmup match state and let the thinking code // revert it to wait state if empty ( so gametype based item masks are setup ) G_Match_LaunchState( MATCH_STATE_WARMUP ); G_asGarbageCollect( true ); // racesow RS_Init(); }
/* * G_Init * * This will be called when the dll is first loaded, which * only happens when a new game is started or a save game is loaded. */ void G_Init( unsigned int seed, unsigned int framemsec, int protocol, const char *demoExtension ) { cvar_t *g_maxentities; G_Printf( "==== G_Init ====\n" ); srand( seed ); G_InitGameShared(); SV_ReadIPList (); game.snapFrameTime = framemsec; game.frametime = game.snapFrameTime; game.protocol = protocol; Q_strncpyz( game.demoExtension, demoExtension, sizeof( game.demoExtension ) ); game.levelSpawnCount = 0; g_maxvelocity = trap_Cvar_Get( "g_maxvelocity", "16000", 0 ); if( g_maxvelocity->value < 20 ) { trap_Cvar_SetValue( "g_maxvelocity", 20 ); } g_gravity = trap_Cvar_Get( "g_gravity", va( "%i", GRAVITY ), 0 ); developer = trap_Cvar_Get( "developer", "0", 0 ); // noset vars dedicated = trap_Cvar_Get( "dedicated", "0", CVAR_NOSET ); // latched vars sv_cheats = trap_Cvar_Get( "sv_cheats", "0", CVAR_SERVERINFO | CVAR_LATCH ); sv_mm_enable = trap_Cvar_Get( "sv_mm_enable", "0", CVAR_ARCHIVE | CVAR_NOSET | CVAR_SERVERINFO ); // hack in CVAR_SERVERINFO flag trap_Cvar_Get( "gamename", trap_Cvar_String( "gamename" ), CVAR_SERVERINFO ); trap_Cvar_Get( "gamedate", __DATE__, CVAR_SERVERINFO | CVAR_LATCH ); password = trap_Cvar_Get( "password", "", CVAR_USERINFO ); password->modified = true; // force an update of g_needpass in G_UpdateServerInfo g_operator_password = trap_Cvar_Get( "g_operator_password", "", CVAR_ARCHIVE ); filterban = trap_Cvar_Get( "filterban", "1", 0 ); cm_mapHeader = trap_Cvar_Get( "cm_mapHeader", "", 0 ); cm_mapVersion = trap_Cvar_Get( "cm_mapVersion", "", 0 ); g_ammo_respawn = trap_Cvar_Get( "g_ammo_respawn", "0", CVAR_ARCHIVE ); g_weapon_respawn = trap_Cvar_Get( "g_weapon_respawn", "0", CVAR_ARCHIVE ); g_health_respawn = trap_Cvar_Get( "g_health_respawn", "0", CVAR_ARCHIVE ); g_armor_respawn = trap_Cvar_Get( "g_armor_respawn", "0", CVAR_ARCHIVE ); g_select_empty = trap_Cvar_Get( "g_select_empty", "0", CVAR_DEVELOPER ); g_projectile_touch_owner = trap_Cvar_Get( "g_projectile_touch_owner", "0", CVAR_DEVELOPER ); g_projectile_prestep = trap_Cvar_Get( "g_projectile_prestep", va( "%i", PROJECTILE_PRESTEP ), CVAR_DEVELOPER ); g_self_knockback = trap_Cvar_Get( "g_self_knockback", "1.18", CVAR_DEVELOPER ); g_knockback_scale = trap_Cvar_Get( "g_knockback_scale", "1.0", CVAR_ARCHIVE ); g_allow_stun = trap_Cvar_Get( "g_allow_stun", "1", CVAR_ARCHIVE ); g_armor_degradation = trap_Cvar_Get( "g_armor_degradation", va( "%.2f", ARMOR_DEGRADATION ), CVAR_DEVELOPER ); g_armor_protection = trap_Cvar_Get( "g_armor_protection", va( "%.2f", ARMOR_PROTECTION ), CVAR_DEVELOPER ); g_respawn_delay_min = trap_Cvar_Get( "g_respawn_delay_min", "600", CVAR_DEVELOPER ); g_respawn_delay_max = trap_Cvar_Get( "g_respawn_delay_max", "6000", CVAR_DEVELOPER ); g_numbots = trap_Cvar_Get( "g_numbots", "0", CVAR_ARCHIVE ); g_deadbody_followkiller = trap_Cvar_Get( "g_deadbody_followkiller", "1", CVAR_DEVELOPER ); g_deadbody_autogib_delay = trap_Cvar_Get( "g_deadbody_autogib_delay", "2000", CVAR_DEVELOPER ); g_maxtimeouts = trap_Cvar_Get( "g_maxtimeouts", "2", CVAR_ARCHIVE ); g_antilag = trap_Cvar_Get( "g_antilag", "1", CVAR_SERVERINFO|CVAR_ARCHIVE|CVAR_LATCH ); g_antilag_maxtimedelta = trap_Cvar_Get( "g_antilag_maxtimedelta", "200", CVAR_ARCHIVE ); g_antilag_maxtimedelta->modified = true; g_antilag_timenudge = trap_Cvar_Get( "g_antilag_timenudge", "0", CVAR_ARCHIVE ); g_antilag_timenudge->modified = true; g_allow_spectator_voting = trap_Cvar_Get( "g_allow_spectator_voting", "1", CVAR_ARCHIVE ); if( dedicated->integer ) { g_autorecord = trap_Cvar_Get( "g_autorecord", "1", CVAR_ARCHIVE ); g_autorecord_maxdemos = trap_Cvar_Get( "g_autorecord_maxdemos", "200", CVAR_ARCHIVE ); } else { g_autorecord = trap_Cvar_Get( "g_autorecord", "0", CVAR_ARCHIVE ); g_autorecord_maxdemos = trap_Cvar_Get( "g_autorecord_maxdemos", "0", CVAR_ARCHIVE ); } // flood control g_floodprotection_messages = trap_Cvar_Get( "g_floodprotection_messages", "4", 0 ); g_floodprotection_messages->modified = true; g_floodprotection_team = trap_Cvar_Get( "g_floodprotection_team", "0", 0 ); g_floodprotection_team->modified = true; g_floodprotection_seconds = trap_Cvar_Get( "g_floodprotection_seconds", "4", 0 ); g_floodprotection_seconds->modified = true; g_floodprotection_penalty = trap_Cvar_Get( "g_floodprotection_delay", "10", 0 ); g_floodprotection_penalty->modified = true; g_inactivity_maxtime = trap_Cvar_Get( "g_inactivity_maxtime", "90.0", 0 ); g_inactivity_maxtime->modified = true; // map list g_maplist = trap_Cvar_Get( "g_maplist", "", CVAR_ARCHIVE ); g_maprotation = trap_Cvar_Get( "g_maprotation", "1", CVAR_ARCHIVE ); // map pool g_enforce_map_pool = trap_Cvar_Get( "g_enforce_map_pool", "0", CVAR_ARCHIVE ); g_map_pool = trap_Cvar_Get( "g_map_pool", "", CVAR_ARCHIVE ); //game switches g_instagib = trap_Cvar_Get( "g_instagib", "0", CVAR_SERVERINFO|CVAR_ARCHIVE|CVAR_LATCH ); g_instajump = trap_Cvar_Get( "g_instajump", "1", CVAR_ARCHIVE ); g_instashield = trap_Cvar_Get( "g_instashield", "1", CVAR_ARCHIVE ); // helper cvars to show current status in serverinfo reply trap_Cvar_Get( "g_match_time", "", CVAR_SERVERINFO|CVAR_READONLY ); trap_Cvar_Get( "g_match_score", "", CVAR_SERVERINFO|CVAR_READONLY ); trap_Cvar_Get( "g_needpass", "", CVAR_SERVERINFO|CVAR_READONLY ); trap_Cvar_Get( "g_gametypes_available", "", CVAR_SERVERINFO|CVAR_READONLY ); trap_Cvar_Get( "g_race_gametype", "0", CVAR_SERVERINFO|CVAR_READONLY ); // define this one here so we can see when it's modified g_disable_vote_gametype = trap_Cvar_Get( "g_disable_vote_gametype", "0", CVAR_ARCHIVE ); g_asGC_stats = trap_Cvar_Get( "g_asGC_stats", "0", CVAR_ARCHIVE ); g_asGC_interval = trap_Cvar_Get( "g_asGC_interval", "10", CVAR_ARCHIVE ); g_skillRating = trap_Cvar_Get( "sv_skillRating", va("%.0f", MM_RATING_DEFAULT), CVAR_SERVERINFO|CVAR_READONLY ); // trap_Cvar_ForceSet( "sv_skillRating", va("%d", MM_RATING_DEFAULT) ); // nextmap trap_Cvar_ForceSet( "nextmap", "match \"advance\"" ); // initialize all entities for this game g_maxentities = trap_Cvar_Get( "sv_maxentities", "1024", CVAR_LATCH ); game.maxentities = g_maxentities->integer; game.edicts = ( edict_t * )G_Malloc( game.maxentities * sizeof( game.edicts[0] ) ); // initialize all clients for this game game.clients = ( gclient_t * )G_Malloc( gs.maxclients * sizeof( game.clients[0] ) ); game.quits = NULL; game.numentities = gs.maxclients + 1; trap_LocateEntities( game.edicts, sizeof( game.edicts[0] ), game.numentities, game.maxentities ); // server console commands G_AddServerCommands(); G_LoadFiredefsFromDisk(); // weapon items GS_InitWeapons(); // init AS engine G_asInitGameModuleEngine(); }