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.

374 lines
7.5 KiB

  1. //============ Copyright (c) Valve Corporation, All rights reserved. ============
  2. //
  3. // work in progress
  4. //
  5. //===============================================================================
  6. #include "cbase.h"
  7. #include "global_event_log.h"
  8. #include "filesystem.h"
  9. #include "utlbuffer.h"
  10. // memdbgon must be the last include file in a .cpp file!!!
  11. #include "tier0/memdbgon.h"
  12. #ifdef _PS3
  13. #define _vscprintf vprintf
  14. #define vsprintf_s vsnprintf
  15. #endif
  16. CGlobalEventLog GlobalEventLog;
  17. static CUtlSymbolTable EventSymbols;
  18. static ConVar global_event_log_enabled( "global_event_log_enabled", "0", FCVAR_CHEAT, "Enables the global event log system" );
  19. class CGlobalEventLine
  20. {
  21. public:
  22. CGlobalEventLine( );
  23. ~CGlobalEventLine( );
  24. void Clear( );
  25. bool SetStaticText( const char *pszValue );
  26. bool SetVaryingText( const char *pszValue );
  27. bool IsDirty( ) { return m_bDirty; }
  28. void Write( CUtlBuffer *pBuffer );
  29. void ClearDirty( );
  30. private:
  31. CUtlSymbol m_ValueSymbol;
  32. char *m_pszValue;
  33. bool m_bDirty;
  34. };
  35. CGlobalEventLine::CGlobalEventLine( )
  36. {
  37. m_ValueSymbol = UTL_INVAL_SYMBOL;
  38. m_pszValue = NULL;
  39. m_bDirty = true;
  40. }
  41. CGlobalEventLine::~CGlobalEventLine( )
  42. {
  43. Clear();
  44. }
  45. void CGlobalEventLine::Clear( )
  46. {
  47. m_ValueSymbol = UTL_INVAL_SYMBOL;
  48. if ( m_pszValue != NULL )
  49. {
  50. delete m_pszValue;
  51. m_pszValue = NULL;
  52. }
  53. m_bDirty = true;
  54. }
  55. bool CGlobalEventLine::SetStaticText( const char *pszValue )
  56. {
  57. if ( m_ValueSymbol != UTL_INVAL_SYMBOL && m_ValueSymbol == EventSymbols.Find( pszValue ) )
  58. {
  59. return false;
  60. }
  61. Clear();
  62. m_ValueSymbol = EventSymbols.AddString( pszValue );
  63. return true;
  64. }
  65. bool CGlobalEventLine::SetVaryingText( const char *pszValue )
  66. {
  67. if ( m_pszValue && strcmpi( m_pszValue, pszValue ) == 0 )
  68. { // no change
  69. return false;
  70. }
  71. Clear();
  72. m_pszValue = ( char * )malloc( strlen( pszValue ) + 1 );
  73. strcpy( m_pszValue, pszValue );
  74. return true;
  75. }
  76. void CGlobalEventLine::Write( CUtlBuffer *pBuffer )
  77. {
  78. const char *pszValue;
  79. if ( m_pszValue != NULL )
  80. {
  81. pszValue = m_pszValue;
  82. }
  83. else
  84. {
  85. pszValue = EventSymbols.String( m_ValueSymbol );
  86. }
  87. if ( strchr( pszValue, ' ' ) != NULL )
  88. {
  89. pBuffer->Printf( "\"%s\"\n", pszValue );
  90. }
  91. else
  92. {
  93. pBuffer->Printf( "%s\n", pszValue );
  94. }
  95. }
  96. void CGlobalEventLine::ClearDirty( )
  97. {
  98. m_bDirty = false;
  99. }
  100. class CGlobalEvent
  101. {
  102. public:
  103. CGlobalEvent( const char *pszName, unsigned int nID, bool bIsHighLevel, CGlobalEvent *pParent = NULL );
  104. bool AddValue( bool bVarying, const char *pszKey, const char *pszValue );
  105. unsigned int GetID( ) { return m_nID; }
  106. bool IsDirty( ) { return m_bDirty; }
  107. void Write( CUtlBuffer *pBuffer );
  108. void ClearDirty( );
  109. private:
  110. unsigned int m_nID;
  111. CUtlSymbol m_Name;
  112. float m_flTime;
  113. bool m_bIsHighLevel;
  114. bool m_bFullUpdate;
  115. bool m_bDirty;
  116. CGlobalEvent *m_pParent;
  117. CUtlMap< CUtlSymbol, CGlobalEventLine * > m_EventLines;
  118. };
  119. CGlobalEvent::CGlobalEvent( const char *pszName, unsigned int nID, bool bIsHighLevel, CGlobalEvent *pParent ) :
  120. m_EventLines( DefLessFunc( const CUtlSymbol ) )
  121. {
  122. m_Name = EventSymbols.AddString( pszName );
  123. m_nID = nID;
  124. m_bIsHighLevel = bIsHighLevel;
  125. m_pParent = pParent;
  126. m_bFullUpdate = true;
  127. m_flTime = gpGlobals->curtime;
  128. }
  129. bool CGlobalEvent::AddValue( bool bVarying, const char *pszKey, const char *pszValue )
  130. {
  131. CUtlSymbol KeyID;
  132. CGlobalEventLine *pEvent;
  133. int nIndex;
  134. bool bResult;
  135. KeyID = EventSymbols.AddString( pszKey );
  136. nIndex = m_EventLines.Find( KeyID );
  137. if ( nIndex == m_EventLines.InvalidIndex() )
  138. {
  139. pEvent = new CGlobalEventLine();
  140. m_EventLines.Insert( KeyID, pEvent );
  141. }
  142. else
  143. {
  144. pEvent = m_EventLines.Element( nIndex );
  145. }
  146. if ( bVarying )
  147. {
  148. bResult = pEvent->SetVaryingText( pszValue );
  149. }
  150. else
  151. {
  152. bResult = pEvent->SetStaticText( pszValue );
  153. }
  154. if ( bResult == true )
  155. {
  156. m_bDirty = true;
  157. m_flTime = gpGlobals->curtime;
  158. }
  159. return bResult;
  160. }
  161. void CGlobalEvent::Write( CUtlBuffer *pBuffer )
  162. {
  163. pBuffer->Printf( "event %u\n", m_nID );
  164. pBuffer->Printf( "{\n" );
  165. if ( m_bFullUpdate )
  166. {
  167. const char *pszName = EventSymbols.String( m_Name );
  168. if ( strchr( pszName, ' ' ) != NULL )
  169. {
  170. pBuffer->Printf( "\tName\t\"%s\"\n", pszName );
  171. }
  172. else
  173. {
  174. pBuffer->Printf( "\tName\t%s\n", pszName );
  175. }
  176. if ( m_pParent != NULL )
  177. {
  178. pBuffer->Printf( "\tParent_ID\t%u\n", m_pParent->GetID() );
  179. }
  180. if ( m_bIsHighLevel == true )
  181. {
  182. pBuffer->Printf( "\tHighLevel\t1\n" );
  183. }
  184. }
  185. pBuffer->Printf( "\tTime\t%g\n", m_flTime );
  186. for( unsigned i = 0; i < m_EventLines.Count(); i++ )
  187. {
  188. if ( m_EventLines.Element( i )->IsDirty() )
  189. {
  190. const char *pszKey = EventSymbols.String( m_EventLines.Key( i ) );
  191. if ( strchr( pszKey, ' ' ) != NULL )
  192. {
  193. pBuffer->Printf( "\t\"%s\"\t", pszKey );
  194. }
  195. else
  196. {
  197. pBuffer->Printf( "\t%s\t", pszKey );
  198. }
  199. m_EventLines.Element( i )->Write( pBuffer );
  200. }
  201. }
  202. pBuffer->Printf( "}\n" );
  203. }
  204. void CGlobalEvent::ClearDirty( )
  205. {
  206. m_bFullUpdate = false;
  207. m_bDirty = false;
  208. for( unsigned i = 0; i < m_EventLines.Count(); i++ )
  209. {
  210. m_EventLines.Element( i )->ClearDirty();
  211. }
  212. }
  213. CGlobalEventLog::CGlobalEventLog( )
  214. {
  215. m_nNextID = 1;
  216. }
  217. CGlobalEvent *CGlobalEventLog::GetGlobalEvent( EGlobalEvent GlobalEvent )
  218. {
  219. return m_pGlobalEvents[ GlobalEvent ];
  220. }
  221. CGlobalEvent *CGlobalEventLog::CreateEvent( const char *pszName, bool bIsHighLevel, CGlobalEvent *pParent )
  222. {
  223. CGlobalEvent *pEvent = new CGlobalEvent( pszName, m_nNextID, bIsHighLevel, pParent );
  224. m_Events.AddToTail( pEvent );
  225. m_DirtyEvents.AddToTail( pEvent );
  226. m_nNextID++;
  227. return pEvent;
  228. }
  229. CGlobalEvent *CGlobalEventLog::CreateTempEvent( const char *pszName, CGlobalEvent *pParent )
  230. {
  231. CGlobalEvent *pEvent = new CGlobalEvent( pszName, m_nNextID, false, pParent );
  232. m_TempEvents.AddToTail( pEvent );
  233. m_DirtyEvents.AddToTail( pEvent );
  234. m_nNextID++;
  235. return pEvent;
  236. }
  237. void CGlobalEventLog::RemoveEvent( CGlobalEvent *pEvent )
  238. {
  239. if ( m_Events.FindAndRemove( pEvent ) == true && m_TempEvents.Find( pEvent ) == -1 )
  240. {
  241. m_TempEvents.AddToTail( pEvent );
  242. }
  243. }
  244. void CGlobalEventLog::AddKeyValue( CGlobalEvent *pEvent, bool bVarying, const char *pszKey, const char *pszValueFormat, ... )
  245. {
  246. va_list Args;
  247. int nLen;
  248. char *pszBuffer;
  249. CUtlSymbol KeyID;
  250. bool bResult;
  251. va_start( Args, pszValueFormat );
  252. #if defined(_WIN32) || defined(_PS3)
  253. nLen = _vscprintf( pszValueFormat, Args ) + 1;
  254. #else
  255. nLen = vsnprintf( NULL, 0, pszValueFormat, Args ) + 1;
  256. #endif
  257. pszBuffer = ( char * )stackalloc( nLen * sizeof( char ) );
  258. V_vsnprintf( pszBuffer, nLen, pszValueFormat, Args );
  259. bResult = pEvent->AddValue( bVarying, pszKey, pszBuffer );
  260. if ( bResult == true && m_DirtyEvents.Find( pEvent ) == -1 )
  261. {
  262. m_DirtyEvents.AddToTail( pEvent );
  263. }
  264. }
  265. void CGlobalEventLog::SendUpdate( )
  266. {
  267. if ( m_DirtyEvents.Count() == 0 )
  268. {
  269. return;
  270. }
  271. if ( global_event_log_enabled.GetBool() == true )
  272. {
  273. FileHandle_t fh = g_pFullFileSystem->Open( "c:\\o.events", "a" );
  274. CUtlBuffer *pBuffer = new CUtlBuffer( 0, 0, CUtlBuffer::TEXT_BUFFER );
  275. pBuffer->Clear();
  276. for( int i = 0; i < m_DirtyEvents.Count(); i++ )
  277. {
  278. m_DirtyEvents[ i ]->Write( pBuffer );
  279. g_pFullFileSystem->Write( pBuffer->Base(), pBuffer->TellPut(), fh );
  280. pBuffer->Clear();
  281. }
  282. g_pFullFileSystem->Close( fh );
  283. }
  284. for( int i = 0; i < m_DirtyEvents.Count(); i++ )
  285. {
  286. m_DirtyEvents[ i ]->ClearDirty();
  287. }
  288. m_DirtyEvents.Purge();
  289. for( int i = 0; i < m_TempEvents.Count(); i++ )
  290. {
  291. delete m_TempEvents[ i ];
  292. }
  293. m_TempEvents.Purge();
  294. }
  295. void CGlobalEventLog::PostInit( )
  296. {
  297. m_pGlobalEvents[ GLOBAL_EVENT_NPCS ] = CreateEvent( "NPCs", true );
  298. }
  299. void CGlobalEventLog::FrameUpdatePostEntityThink( )
  300. {
  301. SendUpdate();
  302. }