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.

280 lines
6.5 KiB

  1. //========= Copyright � 1996-2008, Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose: Client handler implementations for instruction players how to play
  4. //
  5. //=============================================================================//
  6. #include "cbase.h"
  7. #include "c_keyvalue_saver.h"
  8. #include "filesystem.h"
  9. #include "ixboxsystem.h"
  10. // memdbgon must be the last include file in a .cpp file!!!
  11. #include "tier0/memdbgon.h"
  12. // Key Value Saver auto game system instantiation
  13. C_KeyValueSaver g_KeyValueSaver[ MAX_SPLITSCREEN_PLAYERS ];
  14. C_KeyValueSaver &KeyValueSaver()
  15. {
  16. ASSERT_LOCAL_PLAYER_RESOLVABLE();
  17. return g_KeyValueSaver[ GET_ACTIVE_SPLITSCREEN_SLOT() ];
  18. }
  19. // C_KeyValueSaver
  20. //
  21. bool C_KeyValueSaver::Init( void )
  22. {
  23. // Make sure split slot is up to date
  24. for ( int i = 0 ; i < MAX_SPLITSCREEN_PLAYERS; ++i )
  25. {
  26. ACTIVE_SPLITSCREEN_PLAYER_GUARD( i );
  27. if ( &KeyValueSaver() == this )
  28. {
  29. SetSlot( i );
  30. break;
  31. }
  32. }
  33. ACTIVE_SPLITSCREEN_PLAYER_GUARD( m_nSplitScreenSlot );
  34. if ( !IsGameConsole() )
  35. {
  36. ListenForGameEvent( "round_end" );
  37. ListenForGameEvent( "map_transition" );
  38. ListenForGameEvent( "game_newmap" );
  39. }
  40. return true;
  41. }
  42. void C_KeyValueSaver::Shutdown( void )
  43. {
  44. ACTIVE_SPLITSCREEN_PLAYER_GUARD( m_nSplitScreenSlot );
  45. WriteAllDirtyKeyValues();
  46. for ( int i = 0; i < m_KeyValueData.Count(); ++i )
  47. {
  48. m_KeyValueData[ i ].pKeyValues->deleteThis();
  49. m_KeyValueData[ i ].pKeyValues = NULL;
  50. }
  51. m_KeyValueData.RemoveAll();
  52. // Stop listening for events
  53. StopListeningForAllEvents();
  54. }
  55. void C_KeyValueSaver::Update( float frametime )
  56. {
  57. ACTIVE_SPLITSCREEN_PLAYER_GUARD( m_nSplitScreenSlot );
  58. if ( IsGameConsole() )
  59. {
  60. // On X360 we want to save when they're not connected
  61. if ( !engine->IsInGame() )
  62. {
  63. // They aren't in game
  64. WriteAllDirtyKeyValues();
  65. }
  66. else
  67. {
  68. const char *levelName = engine->GetLevelName();
  69. if ( levelName && levelName[0] && engine->IsLevelMainMenuBackground() )
  70. {
  71. // The are in game, but it's a background map
  72. WriteAllDirtyKeyValues();
  73. }
  74. }
  75. }
  76. }
  77. void C_KeyValueSaver::FireGameEvent( IGameEvent *event )
  78. {
  79. ACTIVE_SPLITSCREEN_PLAYER_GUARD( m_nSplitScreenSlot );
  80. const char *name = event->GetName();
  81. if ( !IsGameConsole() )
  82. {
  83. if ( Q_strcmp( name, "round_end" ) == 0 ||
  84. Q_strcmp( name, "map_transition" ) == 0 ||
  85. Q_strcmp( name, "game_newmap" ) == 0 )
  86. {
  87. // Good place to save
  88. WriteAllDirtyKeyValues();
  89. }
  90. }
  91. }
  92. bool C_KeyValueSaver::InitKeyValues( const char *pchFileName, KeyValueBuilder funcKeyValueBuilder )
  93. {
  94. KeyValueSaverData *pKeyValueData = FindKeyValueData( pchFileName );
  95. if ( pKeyValueData )
  96. {
  97. // Already got one by this name
  98. return false;
  99. }
  100. int nNew = m_KeyValueData.AddToTail();
  101. pKeyValueData = &(m_KeyValueData[ nNew ]);
  102. V_strcpy( pKeyValueData->szFileName, pchFileName );
  103. pKeyValueData->bDirtySaveData = false;
  104. pKeyValueData->pKeyValues = NULL;
  105. pKeyValueData->funcKeyValueBuilder = funcKeyValueBuilder;
  106. return true;
  107. }
  108. bool C_KeyValueSaver::WriteDirtyKeyValues( const char *pchFileName, bool bForceWrite /*= false*/ )
  109. {
  110. return WriteDirtyKeyValues( FindKeyValueData( pchFileName ), bForceWrite );
  111. }
  112. KeyValues * C_KeyValueSaver::GetKeyValues( const char *pchFileName, bool bForceReread /*= false*/ )
  113. {
  114. KeyValueSaverData *pKeyValueData = FindKeyValueData( pchFileName );
  115. if ( pKeyValueData )
  116. {
  117. if ( !pKeyValueData->pKeyValues )
  118. {
  119. bForceReread = true;
  120. }
  121. if ( bForceReread )
  122. {
  123. if ( !ReadKeyValues( pKeyValueData ) )
  124. {
  125. return NULL;
  126. }
  127. }
  128. return pKeyValueData->pKeyValues;
  129. }
  130. return NULL;
  131. }
  132. void C_KeyValueSaver::MarkKeyValuesDirty( const char *pchFileName )
  133. {
  134. KeyValueSaverData *pKeyValueData = FindKeyValueData( pchFileName );
  135. if ( !pKeyValueData )
  136. return;
  137. pKeyValueData->bDirtySaveData = true;
  138. }
  139. bool C_KeyValueSaver::ReadKeyValues( KeyValueSaverData *pKeyValueData )
  140. {
  141. #if !defined( CSTRIKE15 )
  142. #ifdef _GAMECONSOLE
  143. DevMsg( "Read Game Instructor for splitscreen slot %d\n", m_nSplitScreenSlot );
  144. if ( m_nSplitScreenSlot < 0 )
  145. return false;
  146. if ( m_nSplitScreenSlot >= (int) XBX_GetNumGameUsers() )
  147. return false;
  148. #endif
  149. char szFilename[_MAX_PATH];
  150. Q_snprintf( szFilename, sizeof( szFilename ), VarArgs( "save/%s", pKeyValueData->szFileName ) );
  151. if ( pKeyValueData->pKeyValues )
  152. {
  153. pKeyValueData->pKeyValues->deleteThis();
  154. pKeyValueData->pKeyValues = NULL;
  155. }
  156. pKeyValueData->pKeyValues = new KeyValues( "KeyValueSaverData" );
  157. if ( pKeyValueData->pKeyValues->LoadFromFile( g_pFullFileSystem, szFilename, NULL ) )
  158. {
  159. return true;
  160. }
  161. #endif // !CSTRIKE15
  162. // Couldn't read from the file
  163. return false;
  164. }
  165. bool C_KeyValueSaver::WriteDirtyKeyValues( KeyValueSaverData *pKeyValueData, bool bForceWrite /*= false*/ )
  166. {
  167. if ( engine->IsPlayingDemo() )
  168. return false;
  169. if ( !pKeyValueData )
  170. return false;
  171. if ( !pKeyValueData->bDirtySaveData && !bForceWrite )
  172. return true;
  173. // Always mark as clean state to avoid re-entry on
  174. // subsequent frames when storage device might be
  175. // in a yet-unmounted state.
  176. pKeyValueData->bDirtySaveData = false;
  177. #ifdef _GAMECONSOLE
  178. DevMsg( "Write KeyValueSaver for splitscreen slot %d at time: %.1f\n", m_nSplitScreenSlot, Plat_FloatTime() );
  179. if ( m_nSplitScreenSlot < 0 )
  180. return false;
  181. if ( m_nSplitScreenSlot >= (int) XBX_GetNumGameUsers() )
  182. return false;
  183. #endif
  184. // Build key value data to save
  185. if ( pKeyValueData->pKeyValues )
  186. {
  187. pKeyValueData->pKeyValues->deleteThis();
  188. pKeyValueData->pKeyValues = NULL;
  189. }
  190. pKeyValueData->pKeyValues = new KeyValues( "KeyValueSaverData" );
  191. // Build key values
  192. pKeyValueData->funcKeyValueBuilder( pKeyValueData->pKeyValues );
  193. #if defined( CSTRIKE15 )
  194. // The key values are saved to the title data block in the callback above.
  195. return true;
  196. #else
  197. // Save it!
  198. CUtlBuffer buf( 0, 0, CUtlBuffer::TEXT_BUFFER );
  199. pKeyValueData->pKeyValues->RecursiveSaveToFile( buf, 0 );
  200. char szFilename[_MAX_PATH];
  201. Q_snprintf( szFilename, sizeof( szFilename ), VarArgs( "save/%s", pKeyValueData->szFileName ) );
  202. filesystem->CreateDirHierarchy( "save", "MOD" );
  203. bool bWriteSuccess = filesystem->WriteFile( szFilename, "MOD", buf );
  204. return bWriteSuccess;
  205. #endif
  206. }
  207. void C_KeyValueSaver::WriteAllDirtyKeyValues( void )
  208. {
  209. for ( int i = 0; i < m_KeyValueData.Count(); ++i )
  210. {
  211. WriteDirtyKeyValues( &(m_KeyValueData[ i ]) );
  212. }
  213. }
  214. KeyValueSaverData * C_KeyValueSaver::FindKeyValueData( const char *pchFileName )
  215. {
  216. for ( int i = 0; i < m_KeyValueData.Count(); ++i )
  217. {
  218. KeyValueSaverData *pKeyValueData = &(m_KeyValueData[ i ]);
  219. if ( V_strcmp( pKeyValueData->szFileName, pchFileName ) == 0 )
  220. {
  221. return pKeyValueData;
  222. }
  223. }
  224. return NULL;
  225. }