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.

1234 lines
32 KiB

  1. //========= Copyright (c) 1996-2005, Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //
  7. //=============================================================================//
  8. // GameEventManager.cpp: implementation of the CGameEventManager class.
  9. //
  10. //////////////////////////////////////////////////////////////////////
  11. #include "GameEventManager.h"
  12. #include "filesystem_engine.h"
  13. #include "server.h"
  14. #include "client.h"
  15. #include "tier0/vprof.h"
  16. #include "cl_splitscreen.h"
  17. #include "tier1/tokenset.h"
  18. #include "gameeventtransmitter.h"
  19. // memdbgon must be the last include file in a .cpp file!!!
  20. #include "tier0/memdbgon.h"
  21. #define NETWORKED_TYPE_BITS 4
  22. //////////////////////////////////////////////////////////////////////
  23. // Construction/Destruction
  24. //////////////////////////////////////////////////////////////////////
  25. static CGameEventManager s_GameEventManager;
  26. CGameEventManager &g_GameEventManager = s_GameEventManager;
  27. static const tokenset_t< int > s_GameListenerTypeMap[] =
  28. {
  29. { "SERVERSIDE", CGameEventManager::SERVERSIDE }, // this is a server side listener, event logger etc
  30. { "CLIENTSIDE", CGameEventManager::CLIENTSIDE }, // this is a client side listenet, HUD element etc
  31. { "CLIENTSTUB", CGameEventManager::CLIENTSTUB }, // this is a serverside stub for a remote client listener (used by engine only)
  32. { "SERVERSIDE_OLD", CGameEventManager::SERVERSIDE_OLD }, // legacy support for old server event listeners
  33. { "CLIENTSIDE_OLD", CGameEventManager::CLIENTSIDE_OLD }, // legecy support for old client event listeners
  34. { NULL, -1 }
  35. };
  36. static const tokenset_t< int > s_GameEventTypesMap[] =
  37. {
  38. { "local", CGameEventManager::TYPE_LOCAL }, // 0 : don't network this field
  39. { "string", CGameEventManager::TYPE_STRING }, // 1 : zero terminated ASCII string
  40. { "float", CGameEventManager::TYPE_FLOAT }, // 2 : float 32 bit
  41. { "long", CGameEventManager::TYPE_LONG }, // 3 : signed int 32 bit
  42. { "short", CGameEventManager::TYPE_SHORT }, // 4 : signed int 16 bit
  43. { "byte", CGameEventManager::TYPE_BYTE }, // 5 : unsigned int 8 bit
  44. { "bool", CGameEventManager::TYPE_BOOL }, // 6 : unsigned int 1 bit
  45. { "uint64", CGameEventManager::TYPE_UINT64 }, // 7 : unsigned int 64 bit
  46. { "wstring", CGameEventManager::TYPE_WSTRING }, // 8 : zero terminated wide char string
  47. { NULL, -1 }
  48. };
  49. static ConVar net_showevents( "net_showevents", "0", 0, "Dump game events to console (1=client only, 2=all)." );
  50. static ConVar net_showeventlisteners( "net_showeventlisteners", "0", 0, "Show listening addition/removals" );
  51. // Expose CVEngineServer to the engine.
  52. EXPOSE_SINGLE_INTERFACE_GLOBALVAR( CGameEventManager, IGameEventManager2, INTERFACEVERSION_GAMEEVENTSMANAGER2, s_GameEventManager );
  53. CGameEvent::CGameEvent( CGameEventDescriptor *descriptor, const char *name )
  54. {
  55. Assert( descriptor );
  56. m_pDescriptor = descriptor;
  57. m_pDataKeys = new KeyValues( name );
  58. m_pDataKeys->SetInt( "splitscreenplayer", GET_ACTIVE_SPLITSCREEN_SLOT() );
  59. }
  60. CGameEvent::~CGameEvent()
  61. {
  62. m_pDataKeys->deleteThis();
  63. }
  64. bool CGameEvent::GetBool( const char *keyName, bool defaultValue) const
  65. {
  66. return m_pDataKeys->GetInt( keyName, defaultValue ) != 0;
  67. }
  68. int CGameEvent::GetInt( const char *keyName, int defaultValue) const
  69. {
  70. return m_pDataKeys->GetInt( keyName, defaultValue );
  71. }
  72. uint64 CGameEvent::GetUint64( const char *keyName, uint64 defaultValue) const
  73. {
  74. return m_pDataKeys->GetUint64( keyName, defaultValue );
  75. }
  76. float CGameEvent::GetFloat( const char *keyName, float defaultValue ) const
  77. {
  78. return m_pDataKeys->GetFloat( keyName, defaultValue );
  79. }
  80. const char *CGameEvent::GetString( const char *keyName, const char *defaultValue ) const
  81. {
  82. return m_pDataKeys->GetString( keyName, defaultValue );
  83. }
  84. const void *CGameEvent::GetPtr( const char *keyName ) const
  85. {
  86. Assert( IsLocal() );
  87. return m_pDataKeys->GetPtr( keyName );
  88. }
  89. const wchar_t *CGameEvent::GetWString( const char *keyName, const wchar_t *defaultValue ) const
  90. {
  91. return m_pDataKeys->GetWString( keyName, defaultValue );
  92. }
  93. void CGameEvent::SetBool( const char *keyName, bool value )
  94. {
  95. m_pDataKeys->SetInt( keyName, value?1:0 );
  96. }
  97. void CGameEvent::SetInt( const char *keyName, int value )
  98. {
  99. m_pDataKeys->SetInt( keyName, value );
  100. }
  101. void CGameEvent::SetUint64( const char *keyName, uint64 value )
  102. {
  103. m_pDataKeys->SetUint64( keyName, value );
  104. }
  105. void CGameEvent::SetFloat( const char *keyName, float value )
  106. {
  107. m_pDataKeys->SetFloat( keyName, value );
  108. }
  109. void CGameEvent::SetString( const char *keyName, const char *value )
  110. {
  111. m_pDataKeys->SetString( keyName, value );
  112. }
  113. void CGameEvent::SetPtr( const char *keyName, const void *value )
  114. {
  115. Assert( IsLocal() );
  116. m_pDataKeys->SetPtr( keyName, const_cast< void *>( value ) );
  117. }
  118. void CGameEvent::SetWString( const char* keyName, const wchar_t* value )
  119. {
  120. m_pDataKeys->SetWString( keyName, value );
  121. }
  122. bool CGameEvent::IsEmpty( const char *keyName ) const
  123. {
  124. return m_pDataKeys->IsEmpty( keyName );
  125. }
  126. const char *CGameEvent::GetName() const
  127. {
  128. return m_pDataKeys->GetName();
  129. }
  130. bool CGameEvent::IsLocal() const
  131. {
  132. return m_pDescriptor->local;
  133. }
  134. bool CGameEvent::IsReliable() const
  135. {
  136. return m_pDescriptor->reliable;
  137. }
  138. bool CGameEvent::ForEventData( IGameEventVisitor2* visitor ) const
  139. {
  140. CGameEventDescriptor *descriptor = m_pDescriptor;
  141. bool iterate = true;
  142. for ( KeyValues* key = descriptor->keys->GetFirstSubKey(); key && iterate; key = key->GetNextKey() )
  143. {
  144. const char * keyName = key->GetName();
  145. int type = key->GetInt();
  146. // see s_GameEventTypesMap for index
  147. switch ( type )
  148. {
  149. case CGameEventManager::TYPE_LOCAL: iterate = visitor->VisitLocal( keyName, GetPtr( keyName ) ); break;
  150. case CGameEventManager::TYPE_STRING: iterate = visitor->VisitString( keyName, GetString( keyName, "" ) ); break;
  151. case CGameEventManager::TYPE_FLOAT: iterate = visitor->VisitFloat( keyName, GetFloat( keyName, 0.0f ) ); break;
  152. case CGameEventManager::TYPE_LONG: iterate = visitor->VisitInt( keyName, GetInt( keyName, 0 ) ); break;
  153. case CGameEventManager::TYPE_SHORT: iterate = visitor->VisitInt( keyName, GetInt( keyName, 0 ) ); break;
  154. case CGameEventManager::TYPE_BYTE: iterate = visitor->VisitInt( keyName, GetInt( keyName, 0 ) ); break;
  155. case CGameEventManager::TYPE_BOOL: iterate = visitor->VisitBool( keyName, GetBool( keyName, false ) ); break;
  156. case CGameEventManager::TYPE_UINT64: iterate = visitor->VisitUint64( keyName, GetUint64( keyName, 0 ) ); break;
  157. case CGameEventManager::TYPE_WSTRING: iterate = visitor->VisitWString( keyName, GetWString( keyName, L"" ) ); break;
  158. }
  159. }
  160. return iterate;
  161. }
  162. CGameEventManager::CGameEventManager()
  163. {
  164. Reset();
  165. }
  166. CGameEventManager::~CGameEventManager()
  167. {
  168. Reset();
  169. }
  170. bool CGameEventManager::Init()
  171. {
  172. Reset();
  173. LoadEventsFromFile( "resource/serverevents.res" );
  174. g_GameEventTransmitter.Init();
  175. return true;
  176. }
  177. void CGameEventManager::Shutdown()
  178. {
  179. Reset();
  180. }
  181. void CGameEventManager::Reset()
  182. {
  183. AUTO_LOCK_FM( m_mutex );
  184. int number = m_GameEvents.Count();
  185. for (int i = 0; i<number; i++)
  186. {
  187. CGameEventDescriptor &e = m_GameEvents.Element( i );
  188. if ( e.keys )
  189. {
  190. e.keys->deleteThis(); // free the value keys
  191. e.keys = NULL;
  192. }
  193. e.listeners.Purge(); // remove listeners
  194. }
  195. m_GameEvents.Purge();
  196. m_Listeners.PurgeAndDeleteElements();
  197. m_EventFiles.RemoveAll();
  198. m_EventFileNames.RemoveAll();
  199. m_EventMap.Purge();
  200. m_bClientListenersChanged = true;
  201. Assert( m_GameEvents.Count() == 0 );
  202. }
  203. bool CGameEventManager::HasClientListenersChanged( bool bReset /* = true */)
  204. {
  205. if ( !m_bClientListenersChanged )
  206. return false;
  207. if ( bReset )
  208. m_bClientListenersChanged = false;
  209. return true;
  210. }
  211. void CGameEventManager::WriteEventList(CSVCMsg_GameEventList *msg)
  212. {
  213. for (int i=0; i < m_GameEvents.Count(); i++ )
  214. {
  215. CGameEventDescriptor &descriptor = m_GameEvents[i];
  216. if ( descriptor.local )
  217. continue;
  218. Assert( descriptor.eventid >= 0 && descriptor.eventid < MAX_EVENT_NUMBER );
  219. CSVCMsg_GameEventList::descriptor_t *pDescriptor = msg->add_descriptors();
  220. const char *pName = m_EventMap.GetElementName( descriptor.elementIndex );
  221. pDescriptor->set_eventid( descriptor.eventid );
  222. pDescriptor->set_name( pName );
  223. KeyValues *key = descriptor.keys->GetFirstSubKey();
  224. while ( key )
  225. {
  226. int type = key->GetInt();
  227. if ( type != TYPE_LOCAL )
  228. {
  229. CSVCMsg_GameEventList::key_t *pKey = pDescriptor->add_keys();
  230. pKey->set_type( type );
  231. pKey->set_name( key->GetName() );
  232. }
  233. key = key->GetNextKey();
  234. }
  235. }
  236. }
  237. bool CGameEventManager::ParseEventList(const CSVCMsg_GameEventList& msg)
  238. {
  239. int i;
  240. AUTO_LOCK_FM( m_mutex );
  241. // reset eventids to -1 first
  242. for ( i=0; i < m_GameEvents.Count(); i++ )
  243. {
  244. CGameEventDescriptor &descriptor = m_GameEvents[i];
  245. descriptor.eventid = -1;
  246. }
  247. // map server event IDs
  248. int nNumEvents = msg.descriptors_size();
  249. for (i = 0; i<nNumEvents; i++)
  250. {
  251. const CSVCMsg_GameEventList::descriptor_t& EventDescriptor = msg.descriptors( i );
  252. const char *name = EventDescriptor.name().c_str();
  253. CGameEventDescriptor *descriptor = GetEventDescriptor( name );
  254. // if event is known to client...
  255. if ( descriptor )
  256. {
  257. descriptor->eventid = EventDescriptor.eventid();
  258. // remove old definition list
  259. if ( descriptor->keys )
  260. descriptor->keys->deleteThis();
  261. descriptor->keys = new KeyValues("descriptor");
  262. int nNumKeys = EventDescriptor.keys_size();
  263. for (int key = 0; key < nNumKeys; key++)
  264. {
  265. const CSVCMsg_GameEventList::key_t &Key = EventDescriptor.keys( key );
  266. descriptor->keys->SetInt( Key.name().c_str(), Key.type() );
  267. }
  268. }
  269. }
  270. // force client to answer what events he listens to
  271. m_bClientListenersChanged = true;
  272. return true;
  273. }
  274. void CGameEventManager::WriteListenEventList(CCLCMsg_ListenEvents *msg)
  275. {
  276. CBitVec<MAX_EVENT_NUMBER> EventArray;
  277. EventArray.ClearAll();
  278. // and know tell the server what events we want to listen to
  279. for (int i=0; i < m_GameEvents.Count(); i++ )
  280. {
  281. CGameEventDescriptor &descriptor = m_GameEvents[i];
  282. if ( descriptor.local )
  283. {
  284. continue; // event isn't networked
  285. }
  286. bool bHasClientListener = false;
  287. for ( int j=0; j<descriptor.listeners.Count(); j++ )
  288. {
  289. CGameEventCallback *listener = descriptor.listeners[j];
  290. if ( listener->m_nListenerType == CGameEventManager::CLIENTSIDE ||
  291. listener->m_nListenerType == CGameEventManager::CLIENTSIDE_OLD )
  292. {
  293. // if we have a client side listener and server knows this event, add it
  294. bHasClientListener = true;
  295. break;
  296. }
  297. }
  298. if ( !bHasClientListener )
  299. continue;
  300. if ( descriptor.eventid == -1 )
  301. {
  302. const char *pName = m_EventMap.GetElementName(descriptor.elementIndex);
  303. DevMsg("Warning! Client listens to event '%s' unknown by server.\n", pName );
  304. continue;
  305. }
  306. EventArray.Set( descriptor.eventid );
  307. }
  308. int count = ( m_GameEvents.Count() + 31 ) / 32;
  309. for( int i = 0; i < count; i++ )
  310. {
  311. msg->add_event_mask( EventArray.GetDWord( i ) );
  312. }
  313. }
  314. IGameEvent *CGameEventManager::CreateEvent( CGameEventDescriptor *descriptor, const char *name )
  315. {
  316. AUTO_LOCK_FM( m_mutex );
  317. return new CGameEvent ( descriptor, name );
  318. }
  319. IGameEvent *CGameEventManager::CreateEvent( const char *name, bool bForce, int *pCookie )
  320. {
  321. AUTO_LOCK_FM( m_mutex );
  322. if ( !name || !name[0] )
  323. return NULL;
  324. CGameEventDescriptor *descriptor = GetEventDescriptor( name, pCookie );
  325. // check if this event name is known
  326. if ( !descriptor )
  327. {
  328. DevMsg( "CreateEvent: event '%s' not registered.\n", name );
  329. return NULL;
  330. }
  331. // event is known but no one listen to it
  332. if ( descriptor->listeners.Count() == 0 && !bForce )
  333. {
  334. return NULL;
  335. }
  336. // create & return the new event
  337. return new CGameEvent ( descriptor, name );
  338. }
  339. ConVar display_game_events("display_game_events", "0", FCVAR_CHEAT );
  340. bool CGameEventManager::FireEvent( IGameEvent *event, bool bServerOnly )
  341. {
  342. if( display_game_events.GetBool() )
  343. {
  344. Msg("Game Event Fired: %s\n", event->GetName() );
  345. }
  346. return FireEventIntern( event, bServerOnly, false );
  347. }
  348. bool CGameEventManager::FireEventClientSide( IGameEvent *event )
  349. {
  350. return FireEventIntern( event, false, true );
  351. }
  352. IGameEvent *CGameEventManager::DuplicateEvent( IGameEvent *event )
  353. {
  354. CGameEvent *gameEvent = dynamic_cast<CGameEvent*>(event);
  355. if ( !gameEvent )
  356. return NULL;
  357. // create new instance
  358. const char *pName = m_EventMap.GetElementName(gameEvent->m_pDescriptor->elementIndex );
  359. CGameEvent *newEvent = new CGameEvent ( gameEvent->m_pDescriptor, pName );
  360. // free keys
  361. newEvent->m_pDataKeys->deleteThis();
  362. // and make copy
  363. newEvent->m_pDataKeys = gameEvent->m_pDataKeys->MakeCopy();
  364. return newEvent;
  365. }
  366. void CGameEventManager::ConPrintEvent( IGameEvent *event)
  367. {
  368. CGameEventDescriptor *descriptor = GetEventDescriptor( event );
  369. if ( !descriptor )
  370. return;
  371. KeyValues *key = descriptor->keys->GetFirstSubKey();
  372. while ( key )
  373. {
  374. const char * keyName = key->GetName();
  375. int type = key->GetInt();
  376. switch ( type )
  377. {
  378. case TYPE_LOCAL : ConMsg( "- \"%s\" = \"%s\" (local)\n", keyName, event->GetString(keyName) ); break;
  379. case TYPE_STRING : ConMsg( "- \"%s\" = \"%s\"\n", keyName, event->GetString(keyName) ); break;
  380. case TYPE_WSTRING : ConMsg( "- \"%s\" = \"" PRI_WS_FOR_S "\"\n", keyName, event->GetWString(keyName) ); break;
  381. case TYPE_FLOAT : ConMsg( "- \"%s\" = \"%.2f\"\n", keyName, event->GetFloat(keyName) ); break;
  382. default: ConMsg( "- \"%s\" = \"%i\"\n", keyName, event->GetInt(keyName) ); break;
  383. }
  384. key = key->GetNextKey();
  385. }
  386. }
  387. bool CGameEventManager::FireEventIntern( IGameEvent *event, bool bServerOnly, bool bClientOnly )
  388. {
  389. AUTO_LOCK_FM( m_mutex );
  390. if ( event == NULL )
  391. return false;
  392. Assert( !(bServerOnly && bClientOnly) ); // it can't be both
  393. VPROF_("CGameEventManager::FireEvent", 1, VPROF_BUDGETGROUP_OTHER_UNACCOUNTED, false,
  394. bClientOnly ? BUDGETFLAG_CLIENT : ( bServerOnly ? BUDGETFLAG_SERVER : BUDGETFLAG_OTHER ) );
  395. CGameEventDescriptor *descriptor = GetEventDescriptor( event );
  396. if ( descriptor == NULL )
  397. {
  398. DevMsg( "FireEvent: event '%s' not registered.\n", event->GetName() );
  399. FreeEvent( event );
  400. return false;
  401. }
  402. // show game events in console
  403. if ( net_showevents.GetInt() > 0 )
  404. {
  405. if ( bClientOnly )
  406. {
  407. #ifndef DEDICATED
  408. const char *pName = m_EventMap.GetElementName(descriptor->elementIndex);
  409. ConMsg( "Game event \"%s\", Tick %i:\n", pName, GetBaseLocalClient().GetClientTickCount() );
  410. ConPrintEvent( event );
  411. #endif
  412. }
  413. else if ( net_showevents.GetInt() > 1 )
  414. {
  415. const char *pName = m_EventMap.GetElementName(descriptor->elementIndex);
  416. ConMsg( "Server event \"%s\", Tick %i:\n", pName, sv.GetTick() );
  417. ConPrintEvent( event );
  418. }
  419. }
  420. for ( int i = 0; i < descriptor->listeners.Count(); i++ )
  421. {
  422. CGameEventCallback *listener = descriptor->listeners.Element( i );
  423. Assert ( listener );
  424. // don't trigger server listners for clientside only events
  425. if ( ( listener->m_nListenerType == SERVERSIDE ||
  426. listener->m_nListenerType == SERVERSIDE_OLD ) &&
  427. bClientOnly )
  428. continue;
  429. // don't trigger clientside events, if not explicit a clientside event
  430. if ( ( listener->m_nListenerType == CLIENTSIDE ||
  431. listener->m_nListenerType == CLIENTSIDE_OLD ) &&
  432. !bClientOnly )
  433. continue;
  434. // don't broadcast events if server side only
  435. if ( listener->m_nListenerType == CLIENTSTUB && (bServerOnly || bClientOnly) )
  436. continue;
  437. // if the event is local, don't tell clients about it
  438. if ( listener->m_nListenerType == CLIENTSTUB && descriptor->local )
  439. continue;
  440. // TODO optimized the serialize event for clients, call only once and not per client
  441. // fire event in this listener module
  442. if ( listener->m_nListenerType == CLIENTSIDE_OLD ||
  443. listener->m_nListenerType == SERVERSIDE_OLD )
  444. {
  445. // legacy support for old system
  446. IGameEventListener *pCallback = static_cast<IGameEventListener*>(listener->m_pCallback);
  447. CGameEvent *pEvent = static_cast<CGameEvent*>(event);
  448. pCallback->FireGameEvent( pEvent->m_pDataKeys );
  449. }
  450. else
  451. {
  452. // new system
  453. IGameEventListener2 *pCallback = static_cast<IGameEventListener2*>(listener->m_pCallback);
  454. Assert( pCallback );
  455. if ( pCallback )
  456. {
  457. if ( pCallback->GetEventDebugID() != EVENT_DEBUG_ID_INIT )
  458. {
  459. Msg( "GameEventListener2 callback in list that should NOT be - %s!\n", event->GetName() );
  460. Assert( 0 );
  461. }
  462. else
  463. {
  464. pCallback->FireGameEvent( event );
  465. }
  466. }
  467. else
  468. {
  469. Warning( "Callback for event \"%s\" is NULL!!!\n", event->GetName() );
  470. }
  471. }
  472. }
  473. if ( bClientOnly || ( !Q_stricmp( "portal2", COM_GetModDirectory() ) ) )
  474. {
  475. // Pass all client only events to the game event transmiter
  476. g_GameEventTransmitter.TransmitGameEvent( event );
  477. }
  478. // free event resources
  479. FreeEvent( event );
  480. return true;
  481. }
  482. bool CGameEventManager::SerializeEvent( IGameEvent *event, CSVCMsg_GameEvent *eventMsg )
  483. {
  484. AUTO_LOCK_FM( m_mutex );
  485. CGameEventDescriptor *descriptor = GetEventDescriptor( event );
  486. Assert( descriptor );
  487. eventMsg->set_eventid( descriptor->eventid );
  488. // now iterate trough all fields described in gameevents.res and put them in the buffer
  489. KeyValues * key = descriptor->keys->GetFirstSubKey();
  490. if ( net_showevents.GetInt() > 2 )
  491. {
  492. const char *pName = m_EventMap.GetElementName(descriptor->elementIndex);
  493. DevMsg("Serializing event '%s' (%i):\n", pName, descriptor->eventid );
  494. }
  495. while ( key )
  496. {
  497. const char * keyName = key->GetName();
  498. int type = key->GetInt();
  499. if ( net_showevents.GetInt() > 2 )
  500. {
  501. DevMsg(" - %s (%s)\n", keyName, s_GameEventTypesMap->GetNameByToken( type ) );
  502. }
  503. if( type != TYPE_LOCAL )
  504. {
  505. CSVCMsg_GameEvent::key_t *pKey = eventMsg->add_keys();
  506. //Make sure every key is used in the event
  507. // Assert( event->FindKey(keyName) && "GameEvent field not found in passed KeyValues" );
  508. pKey->set_type( type );
  509. // see s_GameEventTypesMap for index
  510. switch ( type )
  511. {
  512. case TYPE_STRING: pKey->set_val_string( event->GetString( keyName, "") ); break;
  513. case TYPE_FLOAT : pKey->set_val_float( event->GetFloat( keyName, 0.0f) ); break;
  514. case TYPE_LONG : pKey->set_val_long( event->GetInt( keyName, 0) ); break;
  515. case TYPE_SHORT : pKey->set_val_short( event->GetInt( keyName, 0) ); break;
  516. case TYPE_BYTE : pKey->set_val_byte( event->GetInt( keyName, 0) ); break;
  517. case TYPE_BOOL : pKey->set_val_bool( !!event->GetInt( keyName, 0) ); break;
  518. case TYPE_UINT64: pKey->set_val_uint64( event->GetUint64( keyName, 0) ); break;
  519. case TYPE_WSTRING:
  520. {
  521. const wchar_t *pStr = event->GetWString( keyName, L"");
  522. pKey->set_val_wstring( pStr, wcslen( pStr ) + 1 );
  523. }
  524. break;
  525. default: DevMsg(1, "CGameEventManager: unknown type %i for key '%s'.\n", type, key->GetName() ); break;
  526. }
  527. }
  528. key = key->GetNextKey();
  529. }
  530. if ( net_showevents.GetInt() > 2 )
  531. {
  532. int nBytes = eventMsg->ByteSize();
  533. Msg( " took %d bits, %d bytes\n", nBytes * 8, nBytes );
  534. }
  535. descriptor->numSerialized++;
  536. descriptor->totalSerializedBits += eventMsg->ByteSize() * 8;
  537. return true;
  538. }
  539. IGameEvent *CGameEventManager::UnserializeEvent( const CSVCMsg_GameEvent& eventMsg )
  540. {
  541. AUTO_LOCK_FM( m_mutex );
  542. // read event id
  543. int eventid = eventMsg.eventid();
  544. // get event description
  545. CGameEventDescriptor *descriptor = GetEventDescriptor( eventid );
  546. if ( descriptor == NULL )
  547. {
  548. DevMsg( "CGameEventManager::UnserializeEvent:: unknown event id %i.\n", eventid );
  549. return NULL;
  550. }
  551. // create new event
  552. const char *pName = m_EventMap.GetElementName(descriptor->elementIndex);
  553. IGameEvent *event = CreateEvent( descriptor, pName );
  554. if ( !event )
  555. {
  556. DevMsg( "CGameEventManager::UnserializeEvent:: failed to create event %s.\n", pName );
  557. return NULL;
  558. }
  559. int nNumKeys = eventMsg.keys_size();
  560. KeyValues * key = descriptor->keys->GetFirstSubKey();
  561. for( int i = 0; key && ( i < nNumKeys ); i++, key = key->GetNextKey() )
  562. {
  563. const CSVCMsg_GameEvent::key_t &KeyEvent = eventMsg.keys( i );
  564. const char * keyName = key->GetName();
  565. int type = KeyEvent.type();
  566. switch ( type )
  567. {
  568. case TYPE_LOCAL : break; // ignore
  569. case TYPE_STRING : event->SetString( keyName, KeyEvent.val_string().c_str() ); break;
  570. case TYPE_FLOAT : event->SetFloat( keyName, KeyEvent.val_float() ); break;
  571. case TYPE_LONG : event->SetInt( keyName, KeyEvent.val_long() ); break;
  572. case TYPE_SHORT : event->SetInt( keyName, KeyEvent.val_short() ); break;
  573. case TYPE_BYTE : event->SetInt( keyName, KeyEvent.val_byte() ); break;
  574. case TYPE_BOOL : event->SetInt( keyName, KeyEvent.val_bool() ); break;
  575. case TYPE_UINT64 : event->SetUint64( keyName, KeyEvent.val_uint64() ); break;
  576. case TYPE_WSTRING : event->SetWString( keyName, (wchar_t*)KeyEvent.val_wstring().data() ); break;
  577. default: DevMsg(1, "CGameEventManager: unknown type %i for key '%s' [%s].\n", type, key->GetName(), pName ); break;
  578. }
  579. }
  580. descriptor->numUnSerialized++;
  581. descriptor->totalUnserializedBits += eventMsg.ByteSize() * 8;
  582. return event;
  583. }
  584. KeyValues* CGameEventManager::GetEventDataTypes( IGameEvent* event )
  585. {
  586. if ( event == nullptr )
  587. return nullptr;
  588. CGameEventDescriptor* descriptor = GetEventDescriptor( event );
  589. if ( descriptor == nullptr )
  590. return nullptr;
  591. return descriptor->keys;
  592. }
  593. // returns true if this listener is listens to given event
  594. bool CGameEventManager::FindListener( IGameEventListener2 *listener, const char *name )
  595. {
  596. AUTO_LOCK_FM( m_mutex );
  597. CGameEventDescriptor *pDescriptor = GetEventDescriptor( name );
  598. if ( !pDescriptor )
  599. return false; // event is unknown
  600. CGameEventCallback *pCallback = FindEventListener( listener );
  601. if ( !pCallback )
  602. return false; // listener is unknown
  603. // see if listener is in the list for this event
  604. return pDescriptor->listeners.IsValidIndex( pDescriptor->listeners.Find( pCallback ) );
  605. }
  606. CGameEventCallback* CGameEventManager::FindEventListener( void* pCallback )
  607. {
  608. for (int i=0; i < m_Listeners.Count(); i++ )
  609. {
  610. CGameEventCallback *listener = m_Listeners.Element(i);
  611. if ( listener->m_pCallback == pCallback )
  612. {
  613. return listener;
  614. }
  615. }
  616. return NULL;
  617. }
  618. void CGameEventManager::RemoveListener(IGameEventListener2 *listener)
  619. {
  620. AUTO_LOCK_FM( m_mutex );
  621. CGameEventCallback *pCallback = FindEventListener( listener );
  622. if ( pCallback == NULL )
  623. {
  624. return;
  625. }
  626. // remove reference from events
  627. for (int i=0; i < m_GameEvents.Count(); i++ )
  628. {
  629. CGameEventDescriptor &et = m_GameEvents.Element( i );
  630. et.listeners.FindAndRemove( pCallback );
  631. }
  632. // and from global list
  633. m_Listeners.FindAndRemove( pCallback );
  634. if ( pCallback->m_nListenerType == CLIENTSIDE )
  635. {
  636. m_bClientListenersChanged = true;
  637. }
  638. delete pCallback;
  639. }
  640. bool CGameEventManager::AddListenerGlobal( IGameEventListener2 *listener, bool bServerSide )
  641. {
  642. AUTO_LOCK_FM( m_mutex );
  643. if ( !listener )
  644. return false;
  645. for ( int i = 0; i < m_GameEvents.Count(); i++ )
  646. {
  647. CGameEventDescriptor *descriptor = &m_GameEvents[ i ];
  648. AddListener( listener, descriptor, bServerSide ? SERVERSIDE : CLIENTSIDE );
  649. }
  650. return true;
  651. }
  652. int CGameEventManager::LoadEventsFromFile( const char * filename )
  653. {
  654. AUTO_LOCK_FM( m_mutex );
  655. if ( UTL_INVAL_SYMBOL == m_EventFiles.Find( filename ) )
  656. {
  657. CUtlSymbol id = m_EventFiles.AddString( filename );
  658. m_EventFileNames.AddToTail( id );
  659. }
  660. KeyValues * key = new KeyValues(filename);
  661. KeyValues::AutoDelete autodelete_key( key );
  662. if ( !key->LoadFromFile( g_pFileSystem, filename, "GAME" ) )
  663. return false;
  664. int count = 0; // number new events
  665. KeyValues * subkey = key->GetFirstSubKey();
  666. while ( subkey )
  667. {
  668. if ( subkey->GetDataType() == KeyValues::TYPE_NONE )
  669. {
  670. RegisterEvent( subkey );
  671. count++;
  672. }
  673. subkey = subkey->GetNextKey();
  674. }
  675. if ( net_showevents.GetBool() )
  676. DevMsg( "Event System loaded %i events from file %s.\n", m_GameEvents.Count(), filename );
  677. return m_GameEvents.Count();
  678. }
  679. void CGameEventManager::ReloadEventDefinitions()
  680. {
  681. for ( int i=0; i< m_EventFileNames.Count(); i++ )
  682. {
  683. const char *filename = m_EventFiles.String( m_EventFileNames[i] );
  684. LoadEventsFromFile( filename );
  685. }
  686. // we are the server, build string table now
  687. int number = m_GameEvents.Count();
  688. for (int j = 0; j<number; j++)
  689. {
  690. m_GameEvents[j].eventid = j;
  691. }
  692. }
  693. bool CGameEventManager::AddListener( IGameEventListener2 *listener, const char *event, bool bServerSide )
  694. {
  695. AUTO_LOCK_FM( m_mutex );
  696. if ( !event )
  697. return false;
  698. // look for the event descriptor
  699. CGameEventDescriptor *descriptor = GetEventDescriptor( event );
  700. if ( !descriptor )
  701. {
  702. Warning( "CGameEventManager::AddListener: event '%s' unknown.\n", event );
  703. return false; // that should not happen
  704. }
  705. return AddListener( listener, descriptor, bServerSide ? SERVERSIDE : CLIENTSIDE );
  706. }
  707. bool CGameEventManager::AddListener( void *listener, CGameEventDescriptor *descriptor, int nListenerType )
  708. {
  709. AUTO_LOCK_FM( m_mutex );
  710. if ( !listener || !descriptor )
  711. return false; // bahh
  712. // check if we already know this listener
  713. CGameEventCallback *pCallback = FindEventListener( listener );
  714. if ( pCallback == NULL )
  715. {
  716. // add new callback
  717. pCallback = new CGameEventCallback;
  718. m_Listeners.AddToTail( pCallback );
  719. pCallback->m_nListenerType = nListenerType;
  720. pCallback->m_pCallback = listener;
  721. }
  722. else
  723. {
  724. // make sure that it hasn't changed:
  725. Assert( pCallback->m_nListenerType == nListenerType );
  726. Assert( pCallback->m_pCallback == listener );
  727. }
  728. // add to event listeners list if not already in there
  729. if ( descriptor->listeners.Find( pCallback ) == descriptor->listeners.InvalidIndex() )
  730. {
  731. descriptor->listeners.AddToTail( pCallback );
  732. if ( net_showeventlisteners.GetBool() )
  733. {
  734. const char *name = m_EventMap.GetElementName( descriptor->elementIndex );
  735. Msg("[GAMEEVENT] Event '%s' added %s listener %p\n",
  736. name ? name : "UNKNOWN",
  737. s_GameListenerTypeMap->GetNameByToken( nListenerType ),
  738. listener );
  739. }
  740. if ( nListenerType == CLIENTSIDE || nListenerType == CLIENTSIDE_OLD )
  741. m_bClientListenersChanged = true;
  742. }
  743. return true;
  744. }
  745. bool CGameEventManager::RegisterEvent( KeyValues * event)
  746. {
  747. if ( event == NULL )
  748. return false;
  749. AUTO_LOCK_FM( m_mutex );
  750. if ( m_GameEvents.Count() == MAX_EVENT_NUMBER )
  751. {
  752. DevMsg( "CGameEventManager: couldn't register event '%s', limit reached (%i).\n",
  753. event->GetName(), MAX_EVENT_NUMBER );
  754. return false;
  755. }
  756. const char *name = event->GetName();
  757. CGameEventDescriptor *descriptor = GetEventDescriptor( name );
  758. if ( !descriptor )
  759. {
  760. // event not known yet, create new one
  761. int index = m_GameEvents.AddToTail();
  762. descriptor = &m_GameEvents.Element(index);
  763. descriptor->elementIndex = m_EventMap.Insert( event->GetName(), index );
  764. }
  765. else
  766. {
  767. // descriptor already know, but delete old definitions
  768. descriptor->keys->deleteThis();
  769. }
  770. // create new descriptor keys
  771. descriptor->keys = new KeyValues("descriptor");
  772. KeyValues *subkey = event->GetFirstSubKey();
  773. // interate through subkeys
  774. while ( subkey )
  775. {
  776. const char *keyName = subkey->GetName();
  777. // ok, check it's data type
  778. const char * type = subkey->GetString();
  779. if ( !Q_strcmp( "local", keyName) )
  780. {
  781. descriptor->local = Q_atoi( type ) != 0;
  782. }
  783. else if ( !Q_strcmp( "reliable", keyName) )
  784. {
  785. descriptor->reliable = Q_atoi( type ) != 0;
  786. }
  787. else
  788. {
  789. int i = s_GameEventTypesMap->GetToken( type );
  790. if ( i < 0 )
  791. {
  792. descriptor->keys->SetInt( keyName, 0 ); // unknown
  793. DevMsg( "CGameEventManager:: unknown type '%s' for key '%s' [%s].\n", type, subkey->GetName(), name );
  794. }
  795. else
  796. {
  797. // set data type
  798. descriptor->keys->SetInt( keyName, i ); // set data type
  799. }
  800. }
  801. subkey = subkey->GetNextKey();
  802. }
  803. return true;
  804. }
  805. CGameEventDescriptor *CGameEventManager::GetEventDescriptor(IGameEvent *event)
  806. {
  807. CGameEvent *gameevent = dynamic_cast<CGameEvent*>(event);
  808. if ( !gameevent )
  809. return NULL;
  810. return gameevent->m_pDescriptor;
  811. }
  812. CGameEventDescriptor *CGameEventManager::GetEventDescriptor(int eventid) // returns event name or NULL
  813. {
  814. if ( eventid < 0 )
  815. return NULL;
  816. for ( int i = 0; i < m_GameEvents.Count(); i++ )
  817. {
  818. CGameEventDescriptor *descriptor = &m_GameEvents[i];
  819. if ( descriptor->eventid == eventid )
  820. return descriptor;
  821. }
  822. return NULL;
  823. }
  824. void CGameEventManager::FreeEvent( IGameEvent *event )
  825. {
  826. AUTO_LOCK_FM( m_mutex );
  827. if ( !event )
  828. return;
  829. delete event;
  830. }
  831. CGameEventDescriptor *CGameEventManager::GetEventDescriptor(const char * name, int *pCookie)
  832. {
  833. const uint32 cookieBit = 0x80000000;
  834. const uint32 cookieMask = ~cookieBit;
  835. if ( !name || !name[0] )
  836. return NULL;
  837. if ( pCookie && *pCookie )
  838. {
  839. int gameEventIndex = uint32(*pCookie) & cookieMask;
  840. CGameEventDescriptor *pDescriptor = &m_GameEvents[gameEventIndex];
  841. if ( !V_stricmp( m_EventMap.GetElementName(pDescriptor->elementIndex), name ) )
  842. {
  843. return pDescriptor;
  844. }
  845. }
  846. int eventMapIndex = m_EventMap.Find( name );
  847. if ( eventMapIndex == m_EventMap.InvalidIndex() )
  848. return NULL;
  849. int gameEventIndex = m_EventMap[eventMapIndex];
  850. if ( pCookie )
  851. {
  852. *pCookie = cookieBit | gameEventIndex;
  853. }
  854. return &m_GameEvents[gameEventIndex];
  855. }
  856. bool CGameEventManager::AddListenerAll( void *listener, int nListenerType )
  857. {
  858. AUTO_LOCK_FM( m_mutex );
  859. if ( !listener )
  860. return false;
  861. for (int i=0; i < m_GameEvents.Count(); i++ )
  862. {
  863. CGameEventDescriptor *descriptor = &m_GameEvents[i];
  864. AddListener( listener, descriptor, nListenerType );
  865. }
  866. DevMsg("Warning! Game event listener registerd for all events. Use newer game event interface.\n");
  867. return true;
  868. }
  869. void CGameEventManager::RemoveListenerOld( void *listener)
  870. {
  871. AUTO_LOCK_FM( m_mutex );
  872. CGameEventCallback *pCallback = FindEventListener( listener );
  873. if ( pCallback == NULL )
  874. {
  875. DevMsg("RemoveListenerOld: couldn't find listener\n");
  876. return;
  877. }
  878. // remove reference from events
  879. for (int i=0; i < m_GameEvents.Count(); i++ )
  880. {
  881. CGameEventDescriptor &et = m_GameEvents.Element( i );
  882. et.listeners.FindAndRemove( pCallback );
  883. }
  884. // and from global list
  885. m_Listeners.FindAndRemove( pCallback );
  886. if ( pCallback->m_nListenerType == CLIENTSIDE_OLD )
  887. {
  888. m_bClientListenersChanged = true;
  889. }
  890. delete pCallback;
  891. }
  892. void CGameEventManager::VerifyListenerList( void )
  893. {
  894. int nGameEventCount = m_GameEvents.Count();
  895. for ( int iEvent = 0; iEvent < nGameEventCount; ++iEvent )
  896. {
  897. CGameEventDescriptor *pEvent = &m_GameEvents.Element( iEvent );
  898. const char *pName = m_EventMap.GetElementName( iEvent );
  899. if ( !pEvent )
  900. {
  901. Msg( "VerifyListenerList-Bug: Bad event in list! (%d)\n", iEvent);
  902. continue;
  903. }
  904. int nListenerCount = pEvent->listeners.Count();
  905. for ( int iListen = 0; iListen < nListenerCount; ++iListen )
  906. {
  907. CGameEventCallback *pListener = pEvent->listeners.Element( iListen );
  908. if ( !pListener)
  909. {
  910. Msg( "VerifyListenerList-Bug: Bad listener in list! (%s)\n", pName );
  911. continue;
  912. }
  913. IGameEventListener2 *pCallback = static_cast<IGameEventListener2*>( pListener->m_pCallback );
  914. if ( pCallback->GetEventDebugID() != EVENT_DEBUG_ID_INIT )
  915. {
  916. Msg( "VerifyListenerList-Bug: Bad callback in list! (%s)\n", pName );
  917. continue;
  918. }
  919. }
  920. }
  921. }
  922. void CGameEventManager::DumpEventNetworkStats( void )
  923. {
  924. // find longest name
  925. int len = 0;
  926. for ( int i = 0; i < m_GameEvents.Count(); ++i )
  927. {
  928. CGameEventDescriptor &e = m_GameEvents.Element( i );
  929. const char *name = m_EventMap.GetElementName( e.elementIndex );
  930. if ( !name )
  931. {
  932. continue;
  933. }
  934. int l = Q_strlen( name );
  935. if ( l > len )
  936. {
  937. len = l;
  938. }
  939. }
  940. // ----- ----- ------- ------- ------- -------
  941. Msg( "%*s Out In OutBits InBits OutSize InSize Notes\n", len, "Name" );
  942. // %5d %5d %7d %7d %7d %7d
  943. for ( int i = 0; i < m_GameEvents.Count(); ++i )
  944. {
  945. CGameEventDescriptor &e = m_GameEvents.Element( i );
  946. const char *name = m_EventMap.GetElementName( e.elementIndex );
  947. if ( !name )
  948. {
  949. continue;
  950. }
  951. if ( !e.numSerialized && !e.numUnSerialized )
  952. {
  953. continue;
  954. }
  955. Msg( "%*s %5d %5d %7d %7d %7d %7d",
  956. len,
  957. name,
  958. e.numSerialized,
  959. e.numUnSerialized,
  960. e.totalSerializedBits,
  961. e.totalUnserializedBits,
  962. e.numSerialized ? e.totalSerializedBits / e.numSerialized : 0,
  963. e.numUnSerialized ? e.totalUnserializedBits / e.numUnSerialized : 0 );
  964. if ( e.local )
  965. {
  966. Msg( " local" );
  967. }
  968. if ( e.reliable )
  969. {
  970. Msg( " reliable" );
  971. }
  972. Msg( "\n" );
  973. }
  974. }
  975. CON_COMMAND_F( net_dumpeventstats, "Dumps out a report of game event network usage", 0 )
  976. {
  977. s_GameEventManager.DumpEventNetworkStats();
  978. }