Counter Strike : Global Offensive Source Code
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.

448 lines
12 KiB

  1. //========= Copyright � 1996-2005, 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. #elif defined( _PS3 )
  16. #include "materialsystem/imaterialsystem.h" // for loading fontlib
  17. #endif
  18. // memdbgon must be the last include file in a .cpp file!!!
  19. #include "tier0/memdbgon.h"
  20. // enable this #define (here or in your vpc) to have
  21. // each GameSystem accounted for individually in the vprof.
  22. // You must enable VPROF_LEVEL 1 too.
  23. // #define VPROF_ACCOUNT_GAMESYSTEMS
  24. // Pointer to a member method of IGameSystem
  25. typedef void (IGameSystem::*GameSystemFunc_t)();
  26. // Pointer to a member method of IGameSystem
  27. typedef void (IGameSystemPerFrame::*PerFrameGameSystemFunc_t)();
  28. // Used to invoke a method of all added Game systems in order
  29. static void InvokeMethod( GameSystemFunc_t f, char const *timed = 0 );
  30. // Used to invoke a method of all added Game systems in order
  31. static void InvokeMethodTickProgress( GameSystemFunc_t f, char const *timed = 0 );
  32. // Used to invoke a method of all added Game systems in reverse order
  33. static void InvokeMethodReverseOrder( GameSystemFunc_t f );
  34. // Used to invoke a method of all added Game systems in order
  35. static void InvokePerFrameMethod( PerFrameGameSystemFunc_t f, char const *timed = 0 );
  36. static bool s_bSystemsInitted = false;
  37. // List of all installed Game systems
  38. static CUtlVector<IGameSystem*> s_GameSystems( 0, 4 );
  39. // List of all installed Game systems
  40. static CUtlVector<IGameSystemPerFrame*> s_GameSystemsPerFrame( 0, 4 );
  41. // The map name
  42. static char* s_pMapName = 0;
  43. static CBasePlayer *s_pRunCommandPlayer = NULL;
  44. static CUserCmd *s_pRunCommandUserCmd = NULL;
  45. //-----------------------------------------------------------------------------
  46. // Auto-registration of game systems
  47. //-----------------------------------------------------------------------------
  48. static CAutoGameSystem *s_pSystemList = NULL;
  49. CAutoGameSystem::CAutoGameSystem( char const *name ) :
  50. m_pszName( name )
  51. {
  52. // If s_GameSystems hasn't been initted yet, then add ourselves to the global list
  53. // because we don't know if the constructor for s_GameSystems has happened yet.
  54. // Otherwise, we can add ourselves right into that list.
  55. if ( s_bSystemsInitted )
  56. {
  57. Add( this );
  58. }
  59. else
  60. {
  61. m_pNext = s_pSystemList;
  62. s_pSystemList = this;
  63. }
  64. }
  65. static CAutoGameSystemPerFrame *s_pPerFrameSystemList = NULL;
  66. //-----------------------------------------------------------------------------
  67. // Purpose: This is a CAutoGameSystem which also cares about the "per frame" hooks
  68. //-----------------------------------------------------------------------------
  69. CAutoGameSystemPerFrame::CAutoGameSystemPerFrame( char const *name ) :
  70. m_pszName( name )
  71. {
  72. // If s_GameSystems hasn't been initted yet, then add ourselves to the global list
  73. // because we don't know if the constructor for s_GameSystems has happened yet.
  74. // Otherwise, we can add ourselves right into that list.
  75. if ( s_bSystemsInitted )
  76. {
  77. Add( this );
  78. }
  79. else
  80. {
  81. m_pNext = s_pPerFrameSystemList;
  82. s_pPerFrameSystemList = this;
  83. }
  84. }
  85. //-----------------------------------------------------------------------------
  86. // destructor, cleans up automagically....
  87. //-----------------------------------------------------------------------------
  88. IGameSystem::~IGameSystem()
  89. {
  90. Remove( this );
  91. }
  92. //-----------------------------------------------------------------------------
  93. // destructor, cleans up automagically....
  94. //-----------------------------------------------------------------------------
  95. IGameSystemPerFrame::~IGameSystemPerFrame()
  96. {
  97. Remove( this );
  98. }
  99. //-----------------------------------------------------------------------------
  100. // Adds a system to the list of systems to run
  101. //-----------------------------------------------------------------------------
  102. void IGameSystem::Add( IGameSystem* pSys )
  103. {
  104. s_GameSystems.AddToTail( pSys );
  105. if ( dynamic_cast< IGameSystemPerFrame * >( pSys ) != NULL )
  106. {
  107. s_GameSystemsPerFrame.AddToTail( static_cast< IGameSystemPerFrame * >( pSys ) );
  108. }
  109. }
  110. //-----------------------------------------------------------------------------
  111. // Removes a system from the list of systems to update
  112. //-----------------------------------------------------------------------------
  113. void IGameSystem::Remove( IGameSystem* pSys )
  114. {
  115. s_GameSystems.FindAndRemove( pSys );
  116. if ( dynamic_cast< IGameSystemPerFrame * >( pSys ) != NULL )
  117. {
  118. s_GameSystemsPerFrame.FindAndRemove( static_cast< IGameSystemPerFrame * >( pSys ) );
  119. }
  120. }
  121. //-----------------------------------------------------------------------------
  122. // Removes *all* systems from the list of systems to update
  123. //-----------------------------------------------------------------------------
  124. void IGameSystem::RemoveAll( )
  125. {
  126. s_GameSystems.RemoveAll();
  127. s_GameSystemsPerFrame.RemoveAll();
  128. }
  129. //-----------------------------------------------------------------------------
  130. // Client systems can use this to get at the map name
  131. //-----------------------------------------------------------------------------
  132. char const* IGameSystem::MapName()
  133. {
  134. return s_pMapName;
  135. }
  136. #ifndef CLIENT_DLL
  137. CBasePlayer *IGameSystem::RunCommandPlayer()
  138. {
  139. return s_pRunCommandPlayer;
  140. }
  141. CUserCmd *IGameSystem::RunCommandUserCmd()
  142. {
  143. return s_pRunCommandUserCmd;
  144. }
  145. #endif
  146. //-----------------------------------------------------------------------------
  147. // Invokes methods on all installed game systems
  148. //-----------------------------------------------------------------------------
  149. bool IGameSystem::InitAllSystems()
  150. {
  151. int i;
  152. {
  153. // first add any auto systems to the end
  154. CAutoGameSystem *pSystem = s_pSystemList;
  155. while ( pSystem )
  156. {
  157. if ( s_GameSystems.Find( pSystem ) == s_GameSystems.InvalidIndex() )
  158. {
  159. Add( pSystem );
  160. }
  161. else
  162. {
  163. DevWarning( 1, "AutoGameSystem already added to game system list!!!\n" );
  164. }
  165. pSystem = pSystem->m_pNext;
  166. }
  167. s_pSystemList = NULL;
  168. }
  169. {
  170. CAutoGameSystemPerFrame *pSystem = s_pPerFrameSystemList;
  171. while ( pSystem )
  172. {
  173. if ( s_GameSystems.Find( pSystem ) == s_GameSystems.InvalidIndex() )
  174. {
  175. Add( pSystem );
  176. }
  177. else
  178. {
  179. DevWarning( 1, "AutoGameSystem already added to game system list!!!\n" );
  180. }
  181. pSystem = pSystem->m_pNext;
  182. }
  183. s_pSystemList = NULL;
  184. }
  185. // Now remember that we are initted so new CAutoGameSystems will add themselves automatically.
  186. s_bSystemsInitted = true;
  187. // PS3: haul the fontlib into memory; some systems (eg vgui) need it.
  188. for ( i = 0; i < s_GameSystems.Count(); ++i )
  189. {
  190. MDLCACHE_COARSE_LOCK();
  191. MDLCACHE_CRITICAL_SECTION();
  192. IGameSystem *sys = s_GameSystems[i];
  193. #if defined( _GAMECONSOLE )
  194. char sz[128];
  195. Q_snprintf( sz, sizeof( sz ), "%s->Init():Start", sys->Name() );
  196. COM_TimestampedLog( sz );
  197. #endif
  198. bool valid = sys->Init();
  199. #if defined( _GAMECONSOLE )
  200. Q_snprintf( sz, sizeof( sz ), "%s->Init():Finish", sys->Name() );
  201. COM_TimestampedLog( sz );
  202. #endif
  203. if ( !valid )
  204. {
  205. DevWarning( 1, "Failed to load %s\n", sys->Name() );
  206. return false;
  207. }
  208. }
  209. return true;
  210. }
  211. void IGameSystem::PostInitAllSystems( void )
  212. {
  213. InvokeMethod( &IGameSystem::PostInit, "PostInit" );
  214. }
  215. void IGameSystem::ShutdownAllSystems()
  216. {
  217. InvokeMethodReverseOrder( &IGameSystem::Shutdown );
  218. }
  219. void IGameSystem::LevelInitPreEntityAllSystems( char const* pMapName )
  220. {
  221. // Store off the map name
  222. if ( s_pMapName )
  223. {
  224. delete[] s_pMapName;
  225. }
  226. int len = Q_strlen(pMapName) + 1;
  227. s_pMapName = new char [ len ];
  228. Q_strncpy( s_pMapName, pMapName, len );
  229. InvokeMethodTickProgress( &IGameSystem::LevelInitPreEntity, "LevelInitPreEntity" );
  230. }
  231. void IGameSystem::LevelInitPostEntityAllSystems( void )
  232. {
  233. InvokeMethod( &IGameSystem::LevelInitPostEntity, "LevelInitPostEntity" );
  234. }
  235. void IGameSystem::LevelShutdownPreEntityAllSystems()
  236. {
  237. InvokeMethodReverseOrder( &IGameSystem::LevelShutdownPreEntity );
  238. }
  239. void IGameSystem::LevelShutdownPostEntityAllSystems()
  240. {
  241. InvokeMethodReverseOrder( &IGameSystem::LevelShutdownPostEntity );
  242. if ( s_pMapName )
  243. {
  244. delete[] s_pMapName;
  245. s_pMapName = 0;
  246. }
  247. }
  248. void IGameSystem::OnSaveAllSystems()
  249. {
  250. InvokeMethod( &IGameSystem::OnSave );
  251. }
  252. void IGameSystem::OnRestoreAllSystems()
  253. {
  254. InvokeMethod( &IGameSystem::OnRestore );
  255. }
  256. void IGameSystem::SafeRemoveIfDesiredAllSystems()
  257. {
  258. SNPROF("SafeRemoveIfDesiredAllSystems");
  259. InvokeMethodReverseOrder( &IGameSystem::SafeRemoveIfDesired );
  260. }
  261. #ifdef CLIENT_DLL
  262. void IGameSystem::PreRenderAllSystems()
  263. {
  264. VPROF("IGameSystem::PreRenderAllSystems");
  265. InvokePerFrameMethod( &IGameSystemPerFrame::PreRender );
  266. }
  267. void IGameSystem::UpdateAllSystems( float frametime )
  268. {
  269. SafeRemoveIfDesiredAllSystems();
  270. int i;
  271. int c = s_GameSystemsPerFrame.Count();
  272. MDLCACHE_CRITICAL_SECTION();
  273. for ( i = 0; i < c; ++i )
  274. {
  275. IGameSystemPerFrame *sys = s_GameSystemsPerFrame[i];
  276. sys->Update( frametime );
  277. }
  278. }
  279. void IGameSystem::PostRenderAllSystems()
  280. {
  281. InvokePerFrameMethod( &IGameSystemPerFrame::PostRender );
  282. }
  283. #else
  284. void IGameSystem::FrameUpdatePreEntityThinkAllSystems()
  285. {
  286. SNPROF("FrameUpdatePreEntityThinkAllSystems");
  287. InvokePerFrameMethod( &IGameSystemPerFrame::FrameUpdatePreEntityThink );
  288. }
  289. void IGameSystem::FrameUpdatePostEntityThinkAllSystems()
  290. {
  291. SNPROF("FrameUpdatePostEntityThinkAllSystems");
  292. SafeRemoveIfDesiredAllSystems();
  293. InvokePerFrameMethod( &IGameSystemPerFrame::FrameUpdatePostEntityThink );
  294. }
  295. void IGameSystem::PreClientUpdateAllSystems()
  296. {
  297. SNPROF("PreClientUpdateAllSystems");
  298. InvokePerFrameMethod( &IGameSystemPerFrame::PreClientUpdate );
  299. }
  300. #endif
  301. //-----------------------------------------------------------------------------
  302. // Invokes a method on all installed game systems in proper order
  303. //-----------------------------------------------------------------------------
  304. void InvokeMethod( GameSystemFunc_t f, char const *timed /*=0*/ )
  305. {
  306. NOTE_UNUSED( timed );
  307. MDLCACHE_COARSE_LOCK();
  308. MDLCACHE_CRITICAL_SECTION();
  309. int i;
  310. int c = s_GameSystems.Count();
  311. for ( i = 0; i < c ; ++i )
  312. {
  313. IGameSystem *sys = s_GameSystems[i];
  314. (sys->*f)();
  315. }
  316. }
  317. //-----------------------------------------------------------------------------
  318. // Invokes a method on all installed game systems in proper order
  319. //-----------------------------------------------------------------------------
  320. void InvokeMethodTickProgress( GameSystemFunc_t f, char const *timed /*=0*/ )
  321. {
  322. NOTE_UNUSED( timed );
  323. int i;
  324. int c = s_GameSystems.Count();
  325. for ( i = 0; i < c ; ++i )
  326. {
  327. IGameSystem *sys = s_GameSystems[i];
  328. MDLCACHE_COARSE_LOCK();
  329. MDLCACHE_CRITICAL_SECTION();
  330. #if defined( CLIENT_DLL )
  331. engine->TickProgressBar();
  332. #endif
  333. (sys->*f)();
  334. }
  335. }
  336. //-----------------------------------------------------------------------------
  337. // Invokes a method on all installed game systems in proper order
  338. //-----------------------------------------------------------------------------
  339. void InvokePerFrameMethod( PerFrameGameSystemFunc_t f, char const *timed /*=0*/ )
  340. {
  341. NOTE_UNUSED( timed );
  342. int i;
  343. int c = s_GameSystemsPerFrame.Count();
  344. for ( i = 0; i < c ; ++i )
  345. {
  346. IGameSystemPerFrame *sys = s_GameSystemsPerFrame[i];
  347. #if (VPROF_LEVEL > 0) && defined(VPROF_ACCOUNT_GAMESYSTEMS) // make sure each game system is individually attributed
  348. // because vprof nodes must really be constructed with a pointer to a static
  349. // string, we can't create a temporary char[] here and sprintf a distinctive
  350. // V_snprintf( buf, 63, "gamesys_preframe_%s", sys->Name() ). We'll have to
  351. // settle for just the system name, and distinguish between pre and post frame
  352. // in hierarchy.
  353. VPROF( sys->Name() );
  354. #endif
  355. (sys->*f)();
  356. }
  357. }
  358. //-----------------------------------------------------------------------------
  359. // Invokes a method on all installed game systems in reverse order
  360. //-----------------------------------------------------------------------------
  361. void InvokeMethodReverseOrder( GameSystemFunc_t f )
  362. {
  363. int i;
  364. int c = s_GameSystems.Count();
  365. MDLCACHE_CRITICAL_SECTION();
  366. for ( i = c; --i >= 0; )
  367. {
  368. IGameSystem *sys = s_GameSystems[i];
  369. #if (VPROF_LEVEL > 0) && defined(VPROF_ACCOUNT_GAMESYSTEMS) // make sure each game system is individually attributed
  370. // because vprof nodes must really be constructed with a pointer to a static
  371. // string, we can't create a temporary char[] here and sprintf a distinctive
  372. // V_snprintf( buf, 63, "gamesys_preframe_%s", sys->Name() ). We'll have to
  373. // settle for just the system name, and distinguish between pre and post frame
  374. // in hierarchy.
  375. VPROF( sys->Name() );
  376. #endif
  377. (sys->*f)();
  378. }
  379. }