//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// // // Purpose: // // $NoKeywords: $ // //=============================================================================// #include "cbase.h" #include "basetypes.h" #include "saverestore.h" #include "saverestore_utlvector.h" #include "saverestore_utlsymbol.h" #include "globalstate.h" #include "igamesystem.h" // memdbgon must be the last include file in a .cpp file!!! #include "tier0/memdbgon.h" struct globalentity_t { DECLARE_SIMPLE_DATADESC(); CUtlSymbol name; CUtlSymbol levelName; GLOBALESTATE state; int counter; }; class CGlobalState : public CAutoGameSystem { public: CGlobalState( char const *name ) : CAutoGameSystem( name ), m_disableStateUpdates(false) { } // IGameSystem virtual void LevelShutdownPreEntity() { // don't allow state updates during shutdowns Assert( !m_disableStateUpdates ); m_disableStateUpdates = true; } virtual void LevelShutdownPostEntity() { Assert( m_disableStateUpdates ); m_disableStateUpdates = false; } void EnableStateUpdates( bool bEnable ) { m_disableStateUpdates = !bEnable; } void SetState( int globalIndex, GLOBALESTATE state ) { if ( m_disableStateUpdates || !m_list.IsValidIndex(globalIndex) ) return; m_list[globalIndex].state = state; } GLOBALESTATE GetState( int globalIndex ) { if ( !m_list.IsValidIndex(globalIndex) ) return GLOBAL_OFF; return m_list[globalIndex].state; } void SetCounter( int globalIndex, int counter ) { if ( m_disableStateUpdates || !m_list.IsValidIndex(globalIndex) ) return; m_list[globalIndex].counter = counter; } int AddToCounter( int globalIndex, int delta ) { if ( m_disableStateUpdates || !m_list.IsValidIndex(globalIndex) ) return 0; return ( m_list[globalIndex].counter += delta ); } int GetCounter( int globalIndex ) { if ( !m_list.IsValidIndex(globalIndex) ) return 0; return m_list[globalIndex].counter; } void SetMap( int globalIndex, string_t mapname ) { if ( !m_list.IsValidIndex(globalIndex) ) return; m_list[globalIndex].levelName = m_nameList.AddString( STRING(mapname) ); } const char *GetMap( int globalIndex ) { if ( !m_list.IsValidIndex(globalIndex) ) return NULL; return m_nameList.String( m_list[globalIndex].levelName ); } const char *GetName( int globalIndex ) { if ( !m_list.IsValidIndex(globalIndex) ) return NULL; return m_nameList.String( m_list[globalIndex].name ); } int GetIndex( const char *pGlobalname ) { CUtlSymbol symName = m_nameList.Find( pGlobalname ); if ( symName.IsValid() ) { for ( int i = m_list.Count() - 1; i >= 0; --i ) { if ( m_list[i].name == symName ) return i; } } return -1; } int AddEntity( const char *pGlobalname, const char *pMapName, GLOBALESTATE state ) { globalentity_t entity; entity.name = m_nameList.AddString( pGlobalname ); entity.levelName = m_nameList.AddString( pMapName ); entity.state = state; int index = GetIndex( m_nameList.String( entity.name ) ); if ( index >= 0 ) return index; return m_list.AddToTail( entity ); } int GetNumGlobals( void ) { return m_list.Count(); } void Reset( void ); int Save( ISave &save ); int Restore( IRestore &restore ); DECLARE_SIMPLE_DATADESC(); //#ifdef _DEBUG void DumpGlobals( void ); //#endif public: CUtlSymbolTable m_nameList; private: bool m_disableStateUpdates; CUtlVector m_list; }; static CGlobalState gGlobalState( "CGlobalState" ); static CUtlSymbolDataOps g_GlobalSymbolDataOps( gGlobalState.m_nameList ); void GlobalEntity_SetState( int globalIndex, GLOBALESTATE state ) { gGlobalState.SetState( globalIndex, state ); } void GlobalEntity_SetCounter( int globalIndex, int counter ) { gGlobalState.SetCounter( globalIndex, counter ); } int GlobalEntity_AddToCounter( int globalIndex, int delta ) { return gGlobalState.AddToCounter( globalIndex, delta ); } void GlobalEntity_SetFlags( int globalIndex, int flags ) { // Flags are stored in counter var gGlobalState.SetCounter( globalIndex, flags ); } void GlobalEntity_AddFlags( int globalIndex, int flags ) { // Flags are stored in counter var gGlobalState.SetCounter( globalIndex, gGlobalState.GetCounter( globalIndex ) | flags ); } void GlobalEntity_RemoveFlags( int globalIndex, int flags ) { // Flags are stored in counter var gGlobalState.SetCounter( globalIndex, gGlobalState.GetCounter( globalIndex ) & ~flags ); } void GlobalEntity_EnableStateUpdates( bool bEnable ) { gGlobalState.EnableStateUpdates( bEnable ); } void GlobalEntity_SetMap( int globalIndex, string_t mapname ) { gGlobalState.SetMap( globalIndex, mapname ); } int GlobalEntity_Add( const char *pGlobalname, const char *pMapName, GLOBALESTATE state ) { return gGlobalState.AddEntity( pGlobalname, pMapName, state ); } int GlobalEntity_GetIndex( const char *pGlobalname ) { return gGlobalState.GetIndex( pGlobalname ); } GLOBALESTATE GlobalEntity_GetState( int globalIndex ) { return gGlobalState.GetState( globalIndex ); } int GlobalEntity_GetCounter( int globalIndex ) { return gGlobalState.GetCounter( globalIndex ); } int GlobalEntity_GetFlags( int globalIndex ) { // Flags are stored in counter var return gGlobalState.GetCounter( globalIndex ); } const char *GlobalEntity_GetMap( int globalIndex ) { return gGlobalState.GetMap( globalIndex ); } const char *GlobalEntity_GetName( int globalIndex ) { return gGlobalState.GetName( globalIndex ); } int GlobalEntity_GetNumGlobals( void ) { return gGlobalState.GetNumGlobals(); } CON_COMMAND(dump_globals, "Dump all global entities/states") { if ( !UTIL_IsCommandIssuedByServerAdmin() ) return; gGlobalState.DumpGlobals(); } // This is available all the time now on impulse 104, remove later //#ifdef _DEBUG void CGlobalState::DumpGlobals( void ) { static char *estates[] = { "Off", "On", "Dead" }; Msg( "-- Globals --\n" ); for ( int i = 0; i < m_list.Count(); i++ ) { Msg( "%s: %s (%s) = %d\n", m_nameList.String( m_list[i].name ), m_nameList.String( m_list[i].levelName ), estates[m_list[i].state], m_list[i].counter ); } } //#endif // Global state Savedata BEGIN_SIMPLE_DATADESC( CGlobalState ) DEFINE_UTLVECTOR( m_list, FIELD_EMBEDDED ), // DEFINE_FIELD( m_nameList, CUtlSymbolTable ), // DEFINE_FIELD( m_disableStateUpdates, FIELD_BOOLEAN ), END_DATADESC() BEGIN_SIMPLE_DATADESC( globalentity_t ) DEFINE_CUSTOM_FIELD( name, &g_GlobalSymbolDataOps ), DEFINE_CUSTOM_FIELD( levelName, &g_GlobalSymbolDataOps ), DEFINE_FIELD( state, FIELD_INTEGER ), DEFINE_FIELD( counter, FIELD_INTEGER ), END_DATADESC() int CGlobalState::Save( ISave &save ) { if ( !save.WriteFields( "GLOBAL", this, NULL, m_DataMap.dataDesc, m_DataMap.dataNumFields ) ) return 0; return 1; } int CGlobalState::Restore( IRestore &restore ) { Reset(); if ( !restore.ReadFields( "GLOBAL", this, NULL, m_DataMap.dataDesc, m_DataMap.dataNumFields ) ) return 0; return 1; } void CGlobalState::Reset( void ) { m_list.Purge(); m_nameList.RemoveAll(); } void SaveGlobalState( CSaveRestoreData *pSaveData ) { CSave saveHelper( pSaveData ); gGlobalState.Save( saveHelper ); } void RestoreGlobalState( CSaveRestoreData *pSaveData ) { CRestore restoreHelper( pSaveData ); gGlobalState.Restore( restoreHelper ); } //----------------------------------------------------------------------------- // Purpose: This gets called when a level is shut down //----------------------------------------------------------------------------- void ResetGlobalState( void ) { gGlobalState.Reset(); } void ShowServerGameTime() { Msg( "Server game time: %f\n", gpGlobals->curtime ); } CON_COMMAND(server_game_time, "Gives the game time in seconds (server's curtime)") { if ( !UTIL_IsCommandIssuedByServerAdmin() ) return; ShowServerGameTime(); }