Team Fortress 2 Source Code as on 22/4/2020
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

400 lines
10 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose: Deals with singleton
  4. //
  5. // $Revision: $
  6. // $NoKeywords: $
  7. //=============================================================================//
  8. #include "cbase.h"
  9. #include "igamesystem.h"
  10. #include "datacache/imdlcache.h"
  11. #include "utlvector.h"
  12. #include "vprof.h"
  13. #if defined( _X360 )
  14. #include "xbox/xbox_console.h"
  15. #endif
  16. // memdbgon must be the last include file in a .cpp file!!!
  17. #include "tier0/memdbgon.h"
  18. // Pointer to a member method of IGameSystem
  19. typedef void (IGameSystem::*GameSystemFunc_t)();
  20. // Pointer to a member method of IGameSystem
  21. typedef void (IGameSystemPerFrame::*PerFrameGameSystemFunc_t)();
  22. // Used to invoke a method of all added Game systems in order
  23. static void InvokeMethod( GameSystemFunc_t f, char const *timed = 0 );
  24. // Used to invoke a method of all added Game systems in reverse order
  25. static void InvokeMethodReverseOrder( GameSystemFunc_t f );
  26. // Used to invoke a method of all added Game systems in order
  27. static void InvokePerFrameMethod( PerFrameGameSystemFunc_t f, char const *timed = 0 );
  28. static bool s_bSystemsInitted = false;
  29. // List of all installed Game systems
  30. static CUtlVector<IGameSystem*> s_GameSystems( 0, 4 );
  31. // List of all installed Game systems
  32. static CUtlVector<IGameSystemPerFrame*> s_GameSystemsPerFrame( 0, 4 );
  33. // The map name
  34. static char* s_pMapName = 0;
  35. static CBasePlayer *s_pRunCommandPlayer = NULL;
  36. static CUserCmd *s_pRunCommandUserCmd = NULL;
  37. //-----------------------------------------------------------------------------
  38. // Auto-registration of game systems
  39. //-----------------------------------------------------------------------------
  40. static CAutoGameSystem *s_pSystemList = NULL;
  41. CAutoGameSystem::CAutoGameSystem( char const *name ) :
  42. m_pszName( name )
  43. {
  44. // If s_GameSystems hasn't been initted yet, then add ourselves to the global list
  45. // because we don't know if the constructor for s_GameSystems has happened yet.
  46. // Otherwise, we can add ourselves right into that list.
  47. if ( s_bSystemsInitted )
  48. {
  49. Add( this );
  50. }
  51. else
  52. {
  53. m_pNext = s_pSystemList;
  54. s_pSystemList = this;
  55. }
  56. }
  57. static CAutoGameSystemPerFrame *s_pPerFrameSystemList = NULL;
  58. //-----------------------------------------------------------------------------
  59. // Purpose: This is a CAutoGameSystem which also cares about the "per frame" hooks
  60. //-----------------------------------------------------------------------------
  61. CAutoGameSystemPerFrame::CAutoGameSystemPerFrame( char const *name ) :
  62. m_pszName( name )
  63. {
  64. // If s_GameSystems hasn't been initted yet, then add ourselves to the global list
  65. // because we don't know if the constructor for s_GameSystems has happened yet.
  66. // Otherwise, we can add ourselves right into that list.
  67. if ( s_bSystemsInitted )
  68. {
  69. Add( this );
  70. }
  71. else
  72. {
  73. m_pNext = s_pPerFrameSystemList;
  74. s_pPerFrameSystemList = this;
  75. }
  76. }
  77. //-----------------------------------------------------------------------------
  78. // destructor, cleans up automagically....
  79. //-----------------------------------------------------------------------------
  80. IGameSystem::~IGameSystem()
  81. {
  82. Remove( this );
  83. }
  84. //-----------------------------------------------------------------------------
  85. // destructor, cleans up automagically....
  86. //-----------------------------------------------------------------------------
  87. IGameSystemPerFrame::~IGameSystemPerFrame()
  88. {
  89. Remove( this );
  90. }
  91. //-----------------------------------------------------------------------------
  92. // Adds a system to the list of systems to run
  93. //-----------------------------------------------------------------------------
  94. void IGameSystem::Add( IGameSystem* pSys )
  95. {
  96. s_GameSystems.AddToTail( pSys );
  97. if ( dynamic_cast< IGameSystemPerFrame * >( pSys ) != NULL )
  98. {
  99. s_GameSystemsPerFrame.AddToTail( static_cast< IGameSystemPerFrame * >( pSys ) );
  100. }
  101. }
  102. //-----------------------------------------------------------------------------
  103. // Removes a system from the list of systems to update
  104. //-----------------------------------------------------------------------------
  105. void IGameSystem::Remove( IGameSystem* pSys )
  106. {
  107. s_GameSystems.FindAndRemove( pSys );
  108. if ( dynamic_cast< IGameSystemPerFrame * >( pSys ) != NULL )
  109. {
  110. s_GameSystemsPerFrame.FindAndRemove( static_cast< IGameSystemPerFrame * >( pSys ) );
  111. }
  112. }
  113. //-----------------------------------------------------------------------------
  114. // Removes *all* systems from the list of systems to update
  115. //-----------------------------------------------------------------------------
  116. void IGameSystem::RemoveAll( )
  117. {
  118. s_GameSystems.RemoveAll();
  119. s_GameSystemsPerFrame.RemoveAll();
  120. }
  121. //-----------------------------------------------------------------------------
  122. // Client systems can use this to get at the map name
  123. //-----------------------------------------------------------------------------
  124. char const* IGameSystem::MapName()
  125. {
  126. return s_pMapName;
  127. }
  128. #ifndef CLIENT_DLL
  129. CBasePlayer *IGameSystem::RunCommandPlayer()
  130. {
  131. return s_pRunCommandPlayer;
  132. }
  133. CUserCmd *IGameSystem::RunCommandUserCmd()
  134. {
  135. return s_pRunCommandUserCmd;
  136. }
  137. #endif
  138. //-----------------------------------------------------------------------------
  139. // Invokes methods on all installed game systems
  140. //-----------------------------------------------------------------------------
  141. bool IGameSystem::InitAllSystems()
  142. {
  143. int i;
  144. {
  145. // first add any auto systems to the end
  146. CAutoGameSystem *pSystem = s_pSystemList;
  147. while ( pSystem )
  148. {
  149. if ( s_GameSystems.Find( pSystem ) == s_GameSystems.InvalidIndex() )
  150. {
  151. Add( pSystem );
  152. }
  153. else
  154. {
  155. DevWarning( 1, "AutoGameSystem already added to game system list!!!\n" );
  156. }
  157. pSystem = pSystem->m_pNext;
  158. }
  159. s_pSystemList = NULL;
  160. }
  161. {
  162. CAutoGameSystemPerFrame *pSystem = s_pPerFrameSystemList;
  163. while ( pSystem )
  164. {
  165. if ( s_GameSystems.Find( pSystem ) == s_GameSystems.InvalidIndex() )
  166. {
  167. Add( pSystem );
  168. }
  169. else
  170. {
  171. DevWarning( 1, "AutoGameSystem already added to game system list!!!\n" );
  172. }
  173. pSystem = pSystem->m_pNext;
  174. }
  175. s_pSystemList = NULL;
  176. }
  177. // Now remember that we are initted so new CAutoGameSystems will add themselves automatically.
  178. s_bSystemsInitted = true;
  179. for ( i = 0; i < s_GameSystems.Count(); ++i )
  180. {
  181. MDLCACHE_CRITICAL_SECTION();
  182. IGameSystem *sys = s_GameSystems[i];
  183. #if defined( _X360 )
  184. char sz[128];
  185. Q_snprintf( sz, sizeof( sz ), "%s->Init():Start", sys->Name() );
  186. XBX_rTimeStampLog( Plat_FloatTime(), sz );
  187. #endif
  188. bool valid = sys->Init();
  189. #if defined( _X360 )
  190. Q_snprintf( sz, sizeof( sz ), "%s->Init():Finish", sys->Name() );
  191. XBX_rTimeStampLog( Plat_FloatTime(), sz );
  192. #endif
  193. if ( !valid )
  194. return false;
  195. }
  196. return true;
  197. }
  198. void IGameSystem::PostInitAllSystems( void )
  199. {
  200. InvokeMethod( &IGameSystem::PostInit, "PostInit" );
  201. }
  202. void IGameSystem::ShutdownAllSystems()
  203. {
  204. InvokeMethodReverseOrder( &IGameSystem::Shutdown );
  205. }
  206. void IGameSystem::LevelInitPreEntityAllSystems( char const* pMapName )
  207. {
  208. // Store off the map name
  209. if ( s_pMapName )
  210. {
  211. delete[] s_pMapName;
  212. }
  213. int len = Q_strlen(pMapName) + 1;
  214. s_pMapName = new char [ len ];
  215. Q_strncpy( s_pMapName, pMapName, len );
  216. InvokeMethod( &IGameSystem::LevelInitPreEntity, "LevelInitPreEntity" );
  217. }
  218. void IGameSystem::LevelInitPostEntityAllSystems( void )
  219. {
  220. InvokeMethod( &IGameSystem::LevelInitPostEntity, "LevelInitPostEntity" );
  221. }
  222. void IGameSystem::LevelShutdownPreClearSteamAPIContextAllSystems()
  223. {
  224. InvokeMethodReverseOrder( &IGameSystem::LevelShutdownPreClearSteamAPIContext );
  225. }
  226. void IGameSystem::LevelShutdownPreEntityAllSystems()
  227. {
  228. InvokeMethodReverseOrder( &IGameSystem::LevelShutdownPreEntity );
  229. }
  230. void IGameSystem::LevelShutdownPostEntityAllSystems()
  231. {
  232. InvokeMethodReverseOrder( &IGameSystem::LevelShutdownPostEntity );
  233. if ( s_pMapName )
  234. {
  235. delete[] s_pMapName;
  236. s_pMapName = 0;
  237. }
  238. }
  239. void IGameSystem::OnSaveAllSystems()
  240. {
  241. InvokeMethod( &IGameSystem::OnSave );
  242. }
  243. void IGameSystem::OnRestoreAllSystems()
  244. {
  245. InvokeMethod( &IGameSystem::OnRestore );
  246. }
  247. void IGameSystem::SafeRemoveIfDesiredAllSystems()
  248. {
  249. InvokeMethodReverseOrder( &IGameSystem::SafeRemoveIfDesired );
  250. }
  251. #ifdef CLIENT_DLL
  252. void IGameSystem::PreRenderAllSystems()
  253. {
  254. VPROF("IGameSystem::PreRenderAllSystems");
  255. InvokePerFrameMethod( &IGameSystemPerFrame::PreRender );
  256. }
  257. void IGameSystem::UpdateAllSystems( float frametime )
  258. {
  259. SafeRemoveIfDesiredAllSystems();
  260. int i;
  261. int c = s_GameSystemsPerFrame.Count();
  262. for ( i = 0; i < c; ++i )
  263. {
  264. IGameSystemPerFrame *sys = s_GameSystemsPerFrame[i];
  265. MDLCACHE_CRITICAL_SECTION();
  266. tmZone( TELEMETRY_LEVEL0, TMZF_NONE, "%s - %s", __FUNCTION__, sys->Name() );
  267. sys->Update( frametime );
  268. }
  269. }
  270. void IGameSystem::PostRenderAllSystems()
  271. {
  272. InvokePerFrameMethod( &IGameSystemPerFrame::PostRender );
  273. }
  274. #else
  275. void IGameSystem::FrameUpdatePreEntityThinkAllSystems()
  276. {
  277. InvokePerFrameMethod( &IGameSystemPerFrame::FrameUpdatePreEntityThink );
  278. }
  279. void IGameSystem::FrameUpdatePostEntityThinkAllSystems()
  280. {
  281. SafeRemoveIfDesiredAllSystems();
  282. InvokePerFrameMethod( &IGameSystemPerFrame::FrameUpdatePostEntityThink );
  283. }
  284. void IGameSystem::PreClientUpdateAllSystems()
  285. {
  286. InvokePerFrameMethod( &IGameSystemPerFrame::PreClientUpdate );
  287. }
  288. #endif
  289. //-----------------------------------------------------------------------------
  290. // Invokes a method on all installed game systems in proper order
  291. //-----------------------------------------------------------------------------
  292. void InvokeMethod( GameSystemFunc_t f, char const *timed /*=0*/ )
  293. {
  294. NOTE_UNUSED( timed );
  295. int i;
  296. int c = s_GameSystems.Count();
  297. for ( i = 0; i < c ; ++i )
  298. {
  299. IGameSystem *sys = s_GameSystems[i];
  300. MDLCACHE_CRITICAL_SECTION();
  301. (sys->*f)();
  302. }
  303. }
  304. //-----------------------------------------------------------------------------
  305. // Invokes a method on all installed game systems in proper order
  306. //-----------------------------------------------------------------------------
  307. void InvokePerFrameMethod( PerFrameGameSystemFunc_t f, char const *timed /*=0*/ )
  308. {
  309. NOTE_UNUSED( timed );
  310. int i;
  311. int c = s_GameSystemsPerFrame.Count();
  312. for ( i = 0; i < c ; ++i )
  313. {
  314. IGameSystemPerFrame *sys = s_GameSystemsPerFrame[i];
  315. MDLCACHE_CRITICAL_SECTION();
  316. (sys->*f)();
  317. }
  318. }
  319. //-----------------------------------------------------------------------------
  320. // Invokes a method on all installed game systems in reverse order
  321. //-----------------------------------------------------------------------------
  322. void InvokeMethodReverseOrder( GameSystemFunc_t f )
  323. {
  324. int i;
  325. int c = s_GameSystems.Count();
  326. for ( i = c; --i >= 0; )
  327. {
  328. IGameSystem *sys = s_GameSystems[i];
  329. MDLCACHE_CRITICAL_SECTION();
  330. (sys->*f)();
  331. }
  332. }