//----------------------------------------------------------------------------- // Invokes a method on all installed game systems in proper order //----------------------------------------------------------------------------- void InvokeMethod( GameSystemFunc_t f, char const *timed /*=0*/ ) { #if defined( _XBOX ) #if !defined( _RETAIL ) char sz[ 128 ]; #endif #else NOTE_UNUSED( timed ); #endif int i; int c = s_GameSystems.Count(); for ( i = 0; i < c ; ++i ) { IGameSystem *sys = s_GameSystems[i]; MDLCACHE_CRITICAL_SECTION(); #if !defined( _RETAIL ) #if defined( _XBOX ) if ( timed ) { Q_snprintf( sz, sizeof( sz ), "%s->%s():Start", sys->Name(), timed ); XBX_rTimeStampLog( Plat_FloatTime(), sz ); } #endif #endif (sys->*f)(); #if !defined( _RETAIL ) #if defined( _XBOX ) if ( timed ) { Q_snprintf( sz, sizeof( sz ), "%s->%s():Finish", sys->Name(), timed ); XBX_rTimeStampLog( Plat_FloatTime(), sz ); } #endif #endif } }
//----------------------------------------------------------------------------- // Purpose: For debugging startup times, etc. // Input : *fmt - // ... - //----------------------------------------------------------------------------- void COM_TimestampedLog( char const *fmt, ... ) { static float s_LastStamp = 0.0; static bool s_bShouldLog = false; static bool s_bChecked = false; static bool s_bFirstWrite = false; if ( !s_bChecked ) { // s_bShouldLog = ( IsX360() || CommandLine()->CheckParm( "-profile" ) ) ? true : false; s_bShouldLog = false; s_bChecked = true; } if ( !s_bShouldLog ) { return; } char string[1024]; va_list argptr; va_start( argptr, fmt ); _vsnprintf( string, sizeof( string ), fmt, argptr ); va_end( argptr ); float curStamp = Plat_FloatTime(); #if defined( _X360 ) XBX_rTimeStampLog( curStamp, string ); #endif if ( IsPC() ) { if ( !s_bFirstWrite ) { unlink( "timestamped.log" ); s_bFirstWrite = true; } FILE* fp = fopen( "timestamped.log", "at+" ); fprintf( fp, "%8.4f / %8.4f: %s\n", curStamp, curStamp - s_LastStamp, string ); fclose( fp ); } s_LastStamp = curStamp; }
//----------------------------------------------------------------------------- // Invokes methods on all installed game systems //----------------------------------------------------------------------------- bool IGameSystem::InitAllSystems() { int i; { // first add any auto systems to the end CAutoGameSystem *pSystem = s_pSystemList; while ( pSystem ) { if ( s_GameSystems.Find( pSystem ) == s_GameSystems.InvalidIndex() ) { Add( pSystem ); } else { DevWarning( 1, "AutoGameSystem already added to game system list!!!\n" ); } pSystem = pSystem->m_pNext; } s_pSystemList = NULL; } { CAutoGameSystemPerFrame *pSystem = s_pPerFrameSystemList; while ( pSystem ) { if ( s_GameSystems.Find( pSystem ) == s_GameSystems.InvalidIndex() ) { Add( pSystem ); } else { DevWarning( 1, "AutoGameSystem already added to game system list!!!\n" ); } pSystem = pSystem->m_pNext; } s_pSystemList = NULL; } // Now remember that we are initted so new CAutoGameSystems will add themselves automatically. s_bSystemsInitted = true; for ( i = 0; i < s_GameSystems.Count(); ++i ) { MDLCACHE_CRITICAL_SECTION(); IGameSystem *sys = s_GameSystems[i]; #if defined( _X360 ) char sz[128]; Q_snprintf( sz, sizeof( sz ), "%s->Init():Start", sys->Name() ); XBX_rTimeStampLog( Plat_FloatTime(), sz ); #endif bool valid = sys->Init(); #if defined( _X360 ) Q_snprintf( sz, sizeof( sz ), "%s->Init():Finish", sys->Name() ); XBX_rTimeStampLog( Plat_FloatTime(), sz ); #endif if ( !valid ) return false; } return true; }
bool ConCommandBaseMgr::Fixup(ConCommandBase* pConCommand) { ConCommandBase *pCur; ConCommandBase *pPrev2; ConCommandBase *pCur2; ConCommandBase *pNext2; const char *name; static int initCount = 0; // xboxissue - cvars and its class hierarchy could not be made to instance per subsystem // without massive mangling and re-arranging, instead... // there is only a single chain and therefore single /init/fixup // missing: need to identify which subsystem // could pass as part of declaration in constructor, but how to hide parameter for pc // the accessors (aka callbacks to subsystems) to register with engine // cannot be invoked as their unlink logic expect private lists // so this just mimics the expected end result // must handle early and late constructors // late constructors are usually function scoped static if (!pConCommand) { // the caller is one-time-init if (++initCount > 1) { // the list has already been fixed return true; } } else { // the caller is a console command constructor if (!initCount) { // the list has not been fixed yet // no special behavior return false; } else { // the list has already been fixed // the console command is a late constructor // add in to fixed list bool hasParent = false; if (!pConCommand->IsCommand()) { pCur = ConCommandBase::s_pConCommandBases; while (pCur) { if (pCur->IsCommand() && !stricmp(pCur->m_pszName, pConCommand->m_pszName)) { // set its parent ((ConVar*)pConCommand)->m_pParent = ((ConVar*)pCur)->m_pParent; hasParent = true; break; } pCur = pCur->m_pNext; } } if (!hasParent) { // add to head of list pConCommand->m_pNext = ConCommandBase::s_pConCommandBases; ConCommandBase::s_pConCommandBases = pConCommand; } else return true; } } if (initCount == 1) { // iterate the cvars and set their possible proxy parents // skip over registered (fixed) entries pCur = ConCommandBase::s_pConCommandBases; while (pCur) { if (!pCur->IsCommand() && !pCur->m_bRegistered) { // iterate from the next node until end of list name = pCur->m_pszName; pPrev2 = pCur; pCur2 = pCur->m_pNext; while (pCur2) { pNext2 = pCur2->m_pNext; if (!pCur2->IsCommand() && !stricmp(pCur2->m_pszName, name)) { // found duplicate // unlink and fixup pCur2->m_pNext = NULL; pPrev2->m_pNext = pNext2; // set its parent ((ConVar*)pCur2)->m_pParent = ((ConVar*)pCur)->m_pParent; } else { // no unlink, advance to next node pPrev2 = pCur2; } pCur2 = pNext2; } char const *pValue = GetCommandLineValue(name); if (pValue) ((ConVar*)pCur)->SetValue(pValue); } pCur = pCur->m_pNext; } } #if !defined( _RETAIL ) XBX_rTimeStampLog( Plat_FloatTime(), "xbx PublishCommands:Start" ); PublishCommands( false ); XBX_rTimeStampLog( Plat_FloatTime(), "xbx PublishCommands:Done" ); #endif // fixup has been performed return true; }
//----------------------------------------------------------------------------- // Purpose: Only called on BSP load. Parses and spawns all the entities in the BSP. // Input : pMapData - Pointer to the entity data block to parse. //----------------------------------------------------------------------------- void MapEntity_ParseAllEntities(const char *pMapData, IMapEntityFilter *pFilter, bool bActivateEntities) { VPROF("MapEntity_ParseAllEntities"); HierarchicalSpawnMapData_t pSpawnMapData[NUM_ENT_ENTRIES]; HierarchicalSpawn_t pSpawnList[NUM_ENT_ENTRIES]; CUtlVector< CPointTemplate* > pPointTemplates; int nEntities = 0; char szTokenBuffer[MAPKEY_MAXLENGTH]; #if !defined( _RETAIL ) #if defined( _XBOX ) char sz[ 128 ]; Q_snprintf( sz, sizeof( sz ), "MapEntity_ParseAllEntities():Start" ); XBX_rTimeStampLog( Plat_FloatTime(), sz ); #endif #endif // Allow the tools to spawn different things if ( serverenginetools ) { pMapData = serverenginetools->GetEntityData( pMapData ); } // Loop through all entities in the map data, creating each. for ( ; true; pMapData = MapEntity_SkipToNextEntity(pMapData, szTokenBuffer) ) { // // Parse the opening brace. // char token[MAPKEY_MAXLENGTH]; pMapData = MapEntity_ParseToken( pMapData, token ); // // Check to see if we've finished or not. // if (!pMapData) break; if (token[0] != '{') { Error( "MapEntity_ParseAllEntities: found %s when expecting {", token); continue; } // // Parse the entity and add it to the spawn list. // CBaseEntity *pEntity; const char *pCurMapData = pMapData; pMapData = MapEntity_ParseEntity(pEntity, pMapData, pFilter); if (pEntity == NULL) continue; if (pEntity->IsTemplate()) { // It's a template entity. Squirrel away its keyvalue text so that we can // recreate the entity later via a spawner. pMapData points at the '}' // so we must add one to include it in the string. Templates_Add(pEntity, pCurMapData, (pMapData - pCurMapData) + 2); // Remove the template entity so that it does not show up in FindEntityXXX searches. UTIL_Remove(pEntity); gEntList.CleanupDeleteList(); continue; } // To if ( dynamic_cast<CWorld*>( pEntity ) ) { VPROF( "MapEntity_ParseAllEntities_SpawnWorld"); pEntity->m_iParent = NULL_STRING; // don't allow a parent on the first entity (worldspawn) DispatchSpawn(pEntity); continue; } CNodeEnt *pNode = dynamic_cast<CNodeEnt*>(pEntity); if ( pNode ) { VPROF( "MapEntity_ParseAllEntities_SpawnTransients"); // We overflow the max edicts on large maps that have lots of entities. // Nodes & Lights remove themselves immediately on Spawn(), so dispatch their // spawn now, to free up the slot inside this loop. // NOTE: This solution prevents nodes & lights from being used inside point_templates. // // NOTE: Nodes spawn other entities (ai_hint) if they need to have a persistent presence. // To ensure keys are copied over into the new entity, we pass the mapdata into the // node spawn function. if ( pNode->Spawn( pCurMapData ) < 0 ) { gEntList.CleanupDeleteList(); } continue; } if ( dynamic_cast<CLight*>(pEntity) ) { VPROF( "MapEntity_ParseAllEntities_SpawnTransients"); // We overflow the max edicts on large maps that have lots of entities. // Nodes & Lights remove themselves immediately on Spawn(), so dispatch their // spawn now, to free up the slot inside this loop. // NOTE: This solution prevents nodes & lights from being used inside point_templates. if (DispatchSpawn(pEntity) < 0) { gEntList.CleanupDeleteList(); } continue; } // Build a list of all point_template's so we can spawn them before everything else CPointTemplate *pTemplate = dynamic_cast< CPointTemplate* >(pEntity); if ( pTemplate ) { pPointTemplates.AddToTail( pTemplate ); } else { // Queue up this entity for spawning pSpawnList[nEntities].m_pEntity = pEntity; pSpawnList[nEntities].m_nDepth = 0; pSpawnMapData[nEntities].m_pMapData = pCurMapData; pSpawnMapData[nEntities].m_iMapDataLength = (pMapData - pCurMapData) + 2; nEntities++; } } #if !defined( _RETAIL ) #if defined( _XBOX ) Q_snprintf( sz, sizeof( sz ), "Template Spawn:Start" ); XBX_rTimeStampLog( Plat_FloatTime(), sz ); #endif #endif // Now loop through all our point_template entities and tell them to make templates of everything they're pointing to int iTemplates = pPointTemplates.Count(); for ( int i = 0; i < iTemplates; i++ ) { VPROF( "MapEntity_ParseAllEntities_SpawnTemplates"); CPointTemplate *pPointTemplate = pPointTemplates[i]; // First, tell the Point template to Spawn if ( DispatchSpawn(pPointTemplate) < 0 ) { UTIL_Remove(pPointTemplate); gEntList.CleanupDeleteList(); continue; } pPointTemplate->StartBuildingTemplates(); // Now go through all it's templates and turn the entities into templates int iNumTemplates = pPointTemplate->GetNumTemplateEntities(); for ( int iTemplateNum = 0; iTemplateNum < iNumTemplates; iTemplateNum++ ) { // Find it in the spawn list CBaseEntity *pEntity = pPointTemplate->GetTemplateEntity( iTemplateNum ); for ( int iEntNum = 0; iEntNum < nEntities; iEntNum++ ) { if ( pSpawnList[iEntNum].m_pEntity == pEntity ) { // Give the point_template the mapdata pPointTemplate->AddTemplate( pEntity, pSpawnMapData[iEntNum].m_pMapData, pSpawnMapData[iEntNum].m_iMapDataLength ); if ( pPointTemplate->ShouldRemoveTemplateEntities() ) { // Remove the template entity so that it does not show up in FindEntityXXX searches. UTIL_Remove(pEntity); gEntList.CleanupDeleteList(); // Remove the entity from the spawn list pSpawnList[iEntNum].m_pEntity = NULL; } break; } } } pPointTemplate->FinishBuildingTemplates(); } #if !defined( _RETAIL ) #if defined( _XBOX ) Q_snprintf( sz, sizeof( sz ), "Template Spawn:Finish" ); XBX_rTimeStampLog( Plat_FloatTime(), sz ); #endif #endif SpawnHierarchicalList( nEntities, pSpawnList, bActivateEntities ); #if !defined( _RETAIL ) #if defined( _XBOX ) Q_snprintf( sz, sizeof( sz ), "SpawnHierarchicalList" ); XBX_rTimeStampLog( Plat_FloatTime(), sz ); #endif #endif }
void SpawnAllEntities( int nEntities, HierarchicalSpawn_t *pSpawnList, bool bActivateEntities ) { #if !defined( _RETAIL ) #if defined( _XBOX ) char sz[ 128 ]; Q_snprintf( sz, sizeof( sz ), "SpawnAllEntities(%d)", nEntities ); XBX_rTimeStampLog( Plat_FloatTime(), sz ); #endif #endif int nEntity; for (nEntity = 0; nEntity < nEntities; nEntity++) { VPROF( "MapEntity_ParseAllEntities_Spawn"); CBaseEntity *pEntity = pSpawnList[nEntity].m_pEntity; if ( pEntity ) { if (DispatchSpawn(pEntity) < 0) { for ( int i = nEntity+1; i < nEntities; i++ ) { // this is a child object that will be deleted now if ( pSpawnList[i].m_pEntity && pSpawnList[i].m_pEntity->IsMarkedForDeletion() ) { pSpawnList[i].m_pEntity = NULL; } } // Spawn failed. gEntList.CleanupDeleteList(); // Remove the entity from the spawn list pSpawnList[nEntity].m_pEntity = NULL; } } } #if !defined( _RETAIL ) #if defined( _XBOX ) Q_snprintf( sz, sizeof( sz ), "SpawnAllEntities(%d) -activate", nEntities ); XBX_rTimeStampLog( Plat_FloatTime(), sz ); #endif #endif if ( bActivateEntities ) { VPROF( "MapEntity_ParseAllEntities_Activate"); bool bAsyncAnims = mdlcache->SetAsyncLoad( MDLCACHE_ANIMBLOCK, false ); for (nEntity = 0; nEntity < nEntities; nEntity++) { CBaseEntity *pEntity = pSpawnList[nEntity].m_pEntity; if ( pEntity ) { MDLCACHE_CRITICAL_SECTION(); pEntity->Activate(); } } mdlcache->SetAsyncLoad( MDLCACHE_ANIMBLOCK, bAsyncAnims ); } #if !defined( _RETAIL ) #if defined( _XBOX ) Q_snprintf( sz, sizeof( sz ), "SpawnAllEntities(%d) -done activating", nEntities ); XBX_rTimeStampLog( Plat_FloatTime(), sz ); #endif #endif }