BVB Source Codes

CRYENGINE Show GameStatistics.cpp Source code

Return Download CRYENGINE: download GameStatistics.cpp Source code - Download CRYENGINE Source code - Type:.cpp
  1. // Copyright 2001-2016 Crytek GmbH / Crytek Group. All rights reserved.
  2.  
  3. #include "StdAfx.h"
  4. #include "GameStatistics.h"
  5. #include <CryGame/GameUtils.h>
  6. #include "ScriptBind_GameStatistics.h"
  7. #include "IGameRulesSystem.h"
  8. #include "CryAction.h"
  9. #include "CryActionCVars.h"
  10. #include "StatsSizer.h"
  11.  
  12. static const int MAX_SAVE_ATTEMPTS = 100;
  13.  
  14. //////////////////////////////////////////////////////////////////////////
  15. // CGameStatistics
  16. //////////////////////////////////////////////////////////////////////////
  17.  
  18. CGameStatistics::CGameStatistics()
  19.         : m_gsCallback(0)
  20.         , m_storageFactory(&m_defaultStorageFactory)
  21.         , m_memoryLimit(MEMORY_LIMIT_MAXIMUM)
  22.         , m_currTimeStamp(0)
  23.         , m_cachedDeadMemory(0)
  24.         , m_cachedLiveUnloadableMemory(0)
  25. {
  26.         // Register common game events
  27.         SGameStatDesc commonEvents[eSE_Num] = {
  28.                 GAME_STAT_DESC(eSE_Kill,         "kill"),
  29.                 GAME_STAT_DESC(eSE_Score,        "score"),
  30.                 GAME_STAT_DESC(eSE_Shot,         "shot"),
  31.                 GAME_STAT_DESC(eSE_Throw,        "throw"),
  32.                 GAME_STAT_DESC(eSE_Hit,          "hit"),
  33.                 GAME_STAT_DESC(eSE_Activate,     "activate"),
  34.                 GAME_STAT_DESC(eSE_Explode,      "explode"),
  35.                 GAME_STAT_DESC(eSE_Death,        "death"),
  36.                 GAME_STAT_DESC(eSE_Reload,       "reload"),
  37.                 GAME_STAT_DESC(eSE_Position,     "position"),
  38.                 GAME_STAT_DESC(eSE_Health,       "health"),
  39.                 GAME_STAT_DESC(eSE_Stamina,      "stamina"),
  40.                 GAME_STAT_DESC(eSE_LookDir,      "lookdir"),
  41.                 GAME_STAT_DESC(eSE_LookRotation, "lookrotation"),
  42.                 GAME_STAT_DESC(eSE_Weapon,       "weapon"),
  43.                 GAME_STAT_DESC(eSE_Consume,      "consume"),
  44.                 GAME_STAT_DESC(eSE_Connect,      "connect"),
  45.                 GAME_STAT_DESC(eSE_Disconnect,   "disconnect"),
  46.                 GAME_STAT_DESC(eSE_TeamChange,   "team_change"),
  47.                 GAME_STAT_DESC(eSE_Lifetime,     "lifetime"),
  48.                 GAME_STAT_DESC(eSE_Resurrect,    "resurrect"),
  49.                 GAME_STAT_DESC(eSE_Damage,       "damage"),
  50.                 GAME_STAT_DESC(eSE_Action,       "action"),
  51.                 GAME_STAT_DESC(eSE_Enable,       "enable"),
  52.         };
  53.         RegisterGameEvents(commonEvents, eSE_Num);
  54.  
  55.         SGameStatDesc commonStates[eSS_Num] = {
  56.                 GAME_STAT_DESC(eSS_GameSettings,  "game_settings"),
  57.                 GAME_STAT_DESC(eSS_Map,           "map"),
  58.                 GAME_STAT_DESC(eSS_Gamemode,      "gamemode"),
  59.                 GAME_STAT_DESC(eSS_Team,          "team"),
  60.                 GAME_STAT_DESC(eSS_Winner,        "winner"),
  61.                 GAME_STAT_DESC(eSS_Weapons,       "weapons"),
  62.                 GAME_STAT_DESC(eSS_Ammos,         "ammos"),
  63.                 GAME_STAT_DESC(eSS_PlayerName,    "name"),
  64.                 GAME_STAT_DESC(eSS_ProfileId,     "profile_id"),
  65.                 GAME_STAT_DESC(eSS_PlayerInfo,    "player_info"),
  66.                 GAME_STAT_DESC(eSS_EntityId,      "entity_id"),
  67.                 GAME_STAT_DESC(eSS_Kind,          "kind"),
  68.                 GAME_STAT_DESC(eSS_TriggerParams, "trigger_params"),
  69.                 GAME_STAT_DESC(eSS_Score,         "score"),
  70.         };
  71.         RegisterGameStates(commonStates, eSS_Num);
  72. }
  73.  
  74. CGameStatistics::~CGameStatistics()
  75. {
  76.         CRY_ASSERT_MESSAGE(!m_gameScopes.GetStackSize(), "Stack should be empty now");
  77.         if (m_gameScopes.GetStackSize())
  78.         {
  79.                 CryWarning(VALIDATOR_MODULE_GAME, VALIDATOR_ERROR, "CGameStatistics::~CGameStatistics() Stack is not empty");
  80.         }
  81.  
  82.         // Remove all data left on the stack and do clean up
  83.         while (m_gameScopes.GetStackSize())
  84.                 PopGameScope(INVALID_STAT_ID);
  85. }
  86.  
  87. //////////////////////////////////////////////////////////////////////////
  88. // Events
  89. //////////////////////////////////////////////////////////////////////////
  90.  
  91. bool CGameStatistics::RegisterGameEvents(const SGameStatDesc* eventDescs, size_t numEvents)
  92. {
  93.         return m_eventRegistry.Register(eventDescs, numEvents);
  94. }
  95.  
  96. //////////////////////////////////////////////////////////////////////////
  97.  
  98. size_t CGameStatistics::RegisterGameEvent(const char* scriptName, const char* serializeName)
  99. {
  100.         return m_eventRegistry.Register(scriptName, serializeName);
  101. }
  102.  
  103. //////////////////////////////////////////////////////////////////////////
  104.  
  105. size_t CGameStatistics::GetEventCount() const
  106. {
  107.         return m_eventRegistry.Count();
  108. }
  109.  
  110. //////////////////////////////////////////////////////////////////////////
  111.  
  112. size_t CGameStatistics::GetEventID(const char* scriptName) const
  113. {
  114.         return m_eventRegistry.GetID(scriptName);
  115. }
  116.  
  117. //////////////////////////////////////////////////////////////////////////
  118.  
  119. size_t CGameStatistics::GetEventIDBySerializeName(const char* serializeName) const
  120. {
  121.         for (size_t index = 0; index < m_eventRegistry.Count(); ++index)
  122.         {
  123.                 const SGameStatDesc* pDesc = m_eventRegistry.GetDesc(index);
  124.                 if (pDesc && !strcmp(serializeName, pDesc->serializeName))
  125.                         return index;
  126.         }
  127.  
  128.         return INVALID_STAT_ID;
  129. }
  130.  
  131. //////////////////////////////////////////////////////////////////////////
  132.  
  133. const SGameStatDesc* CGameStatistics::GetEventDesc(size_t eventID) const
  134. {
  135.         return m_eventRegistry.GetDesc(eventID);
  136. }
  137.  
  138. //////////////////////////////////////////////////////////////////////////
  139. // States
  140. //////////////////////////////////////////////////////////////////////////
  141.  
  142. bool CGameStatistics::RegisterGameStates(const SGameStatDesc* stateDescs, size_t numStates)
  143. {
  144.         return m_stateRegistry.Register(stateDescs, numStates);
  145. }
  146.  
  147. //////////////////////////////////////////////////////////////////////////
  148.  
  149. size_t CGameStatistics::RegisterGameState(const char* scriptName, const char* serializeName)
  150. {
  151.         return m_stateRegistry.Register(scriptName, serializeName);
  152. }
  153.  
  154. //////////////////////////////////////////////////////////////////////////
  155.  
  156. size_t CGameStatistics::GetStateCount() const
  157. {
  158.         return m_stateRegistry.Count();
  159. }
  160.  
  161. //////////////////////////////////////////////////////////////////////////
  162.  
  163. size_t CGameStatistics::GetStateID(const char* scriptName) const
  164. {
  165.         return m_stateRegistry.GetID(scriptName);
  166. }
  167.  
  168. //////////////////////////////////////////////////////////////////////////
  169.  
  170. const SGameStatDesc* CGameStatistics::GetStateDesc(size_t stateID) const
  171. {
  172.         return m_stateRegistry.GetDesc(stateID);
  173. }
  174.  
  175. //////////////////////////////////////////////////////////////////////////
  176. // Scopes
  177. //////////////////////////////////////////////////////////////////////////
  178.  
  179. bool CGameStatistics::RegisterGameScopes(const SGameScopeDesc* scopeDescs, size_t numScopes)
  180. {
  181.         m_gameScopes.RegisterGameScopes(scopeDescs, numScopes);
  182.  
  183.         return true;
  184. }
  185.  
  186. //////////////////////////////////////////////////////////////////////////
  187.  
  188. size_t CGameStatistics::GetScopeCount() const
  189. {
  190.         return m_gameScopes.GetRegisteredCount();
  191. }
  192.  
  193. //////////////////////////////////////////////////////////////////////////
  194.  
  195. IStatsTracker* CGameStatistics::PushGameScope(size_t scopeID)
  196. {
  197.         FUNCTION_PROFILER(GetISystem(), PROFILE_ACTION);
  198.  
  199.         CStatsTracker* tracker = m_gameScopes.PushGameScope(scopeID, ++m_currTimeStamp, this);
  200.         if (tracker == 0)
  201.                 return 0;
  202.  
  203.         if (m_gameScopes.GetStackSize() == 1)
  204.         {
  205.                 CRY_ASSERT(!m_scriptBind.get());
  206.                 m_scriptBind.reset(new CScriptBind_GameStatistics(this));
  207.         }
  208.  
  209.         if (m_gsCallback)
  210.                 m_gsCallback->OnNodeAdded(tracker->GetLocator());
  211.  
  212.         m_scriptBind->BindTracker(GetGameRulesTable(), GetScopeDesc(scopeID)->trackerName, tracker);
  213.  
  214.         return tracker;
  215. }
  216.  
  217. //////////////////////////////////////////////////////////////////////////
  218.  
  219. void CGameStatistics::PopGameScope(size_t checkScopeID)
  220. {
  221.         FUNCTION_PROFILER(GetISystem(), PROFILE_ACTION);
  222.  
  223.         if (!ValidatePopScope(checkScopeID))
  224.                 return;
  225.  
  226.         SNodeLocator locator = m_gameScopes.GetLastScope().locator;
  227.         CStatsTracker* tracker = m_gameScopes.GetLastScope().tracker;
  228.  
  229.         RemoveAllElements(m_gameScopes.GetStackSize() - 1);
  230.  
  231.         m_scriptBind->UnbindTracker(GetGameRulesTable(), GetScopeDesc(locator.scopeID)->trackerName, tracker);
  232.  
  233.         SDeadStatNode* deadScope = m_gameScopes.PopGameScope();
  234.         m_cachedDeadMemory += deadScope->GetMemoryStatistics();
  235.  
  236.         if (m_gsCallback)
  237.                 m_gsCallback->OnNodeRemoved(locator, tracker);
  238.  
  239.         // Last scope removed from the stack?
  240.         if (!m_gameScopes.GetStackSize())
  241.         {
  242.                 SaveDeadNodesRec(deadScope);
  243.                 m_scriptBind.reset();
  244.         }
  245.         else
  246.         {
  247.                 CheckMemoryOverflow();
  248.         }
  249. }
  250.  
  251. //////////////////////////////////////////////////////////////////////////
  252.  
  253. bool CGameStatistics::ValidatePopScope(size_t checkScopeID)
  254. {
  255.         CRY_ASSERT(m_gameScopes.GetStackSize());
  256.         if (!m_gameScopes.GetStackSize())
  257.         {
  258.                 CryWarning(VALIDATOR_MODULE_GAME, VALIDATOR_ERROR, "CGameStatistics::PopGameScope() called when no scopes on the stack, ignoring.");
  259.                 return false;
  260.         }
  261.  
  262.         SNodeLocator locator = m_gameScopes.GetLastScope().locator;
  263.         CStatsTracker* tracker = m_gameScopes.GetLastScope().tracker;
  264.  
  265.         CRY_ASSERT(checkScopeID == INVALID_STAT_ID || checkScopeID == locator.scopeID);
  266.         if (checkScopeID != INVALID_STAT_ID && checkScopeID != locator.scopeID)
  267.         {
  268.                 CryWarning(VALIDATOR_MODULE_GAME, VALIDATOR_ERROR,
  269.                            "CGameStatistics::PopGameScope() scope validation failed, popping - %s, top scope - %s",
  270.                            GetScopeDesc(checkScopeID)->scriptName.c_str(), GetScopeDesc(locator.scopeID)->scriptName.c_str());
  271.                 PopScopesUntil(checkScopeID);
  272.                 return false;
  273.         }
  274.  
  275.         return true;
  276. }
  277.  
  278. //////////////////////////////////////////////////////////////////////////
  279.  
  280. void CGameStatistics::PopScopesUntil(size_t scopeID)
  281. {
  282.         size_t pos = m_gameScopes.FindScopePos(scopeID);
  283.         if (pos == m_gameScopes.GetStackSize())
  284.                 return;
  285.  
  286.         while (pos < m_gameScopes.GetStackSize())
  287.         {
  288.                 const SGameScopeDesc* desc = GetScopeDesc(m_gameScopes.GetLastScope().locator.scopeID);
  289.                 if (desc && desc->scriptName)
  290.                         CryWarning(VALIDATOR_MODULE_GAME, VALIDATOR_ERROR, "Normalizing scope state, popping %s", desc->scriptName.c_str());
  291.                 PopGameScope(INVALID_STAT_ID);
  292.         }
  293. }
  294.  
  295. //////////////////////////////////////////////////////////////////////////
  296.  
  297. size_t CGameStatistics::GetScopeStackSize() const
  298. {
  299.         return m_gameScopes.GetStackSize();
  300. }
  301.  
  302. //////////////////////////////////////////////////////////////////////////
  303.  
  304. size_t CGameStatistics::GetScopeID(size_t depth) const
  305. {
  306.         CRY_ASSERT(depth < m_gameScopes.GetStackSize());
  307.         if (depth < m_gameScopes.GetStackSize())
  308.                 return m_gameScopes.GetScopeAt(m_gameScopes.GetStackSize() - depth - 1).locator.scopeID;
  309.  
  310.         return INVALID_STAT_ID;
  311. }
  312.  
  313. //////////////////////////////////////////////////////////////////////////
  314.  
  315. size_t CGameStatistics::GetScopeID(const char* scriptName) const
  316. {
  317.         CRY_ASSERT(scriptName);
  318.         const SGameScopeDesc* desc = m_gameScopes.GetScopeDesc(scriptName);
  319.         return desc != 0 ? desc->statID : INVALID_STAT_ID;
  320. }
  321.  
  322. //////////////////////////////////////////////////////////////////////////
  323.  
  324. const SGameScopeDesc* CGameStatistics::GetScopeDesc(size_t scopeID) const
  325. {
  326.         return m_gameScopes.GetScopeDesc(scopeID);
  327. }
  328.  
  329. //////////////////////////////////////////////////////////////////////////
  330.  
  331. XmlNodeRef CGameStatistics::CreateStatXMLNode(const char* tag)
  332. {
  333.         return GetISystem()->GetXmlUtils()->CreateStatsXmlNode(tag);
  334. }
  335.  
  336. //////////////////////////////////////////////////////////////////////////
  337. // Elements
  338. //////////////////////////////////////////////////////////////////////////
  339.  
  340. bool CGameStatistics::RegisterGameElements(const SGameElementDesc* elemDescs, size_t numElems)
  341. {
  342.         return m_elemRegistry.Register(elemDescs, numElems);
  343. }
  344.  
  345. //////////////////////////////////////////////////////////////////////////
  346.  
  347. IStatsTracker* CGameStatistics::AddGameElement(const SNodeLocator& locator, IScriptTable* pTable)
  348. {
  349.         FUNCTION_PROFILER(GetISystem(), PROFILE_ACTION);
  350.  
  351.         if (!ValidateAddElement(locator))
  352.                 return 0;
  353.  
  354.         const SGameElementDesc* desc = m_elemRegistry.GetDesc(locator.elemID);
  355.         size_t stackPos = m_gameScopes.FindScopePos(locator.scopeID);
  356.  
  357.         CStatsTracker* tracker = NULL;
  358.  
  359.         SScopeData& scope = m_gameScopes.GetScopeAt(stackPos);
  360.         if (scope.elements.find(locator) == scope.elements.end())
  361.         {
  362.                 SNodeLocator newLocator(locator);
  363.                 newLocator.timeStamp = ++m_currTimeStamp;
  364.  
  365.                 tracker = new CStatsTracker(newLocator, this, pTable);
  366.  
  367.                 scope.elements.insert(std::make_pair(newLocator, tracker));
  368.  
  369.                 if (pTable)
  370.                         m_scriptBind->BindTracker(pTable, desc->trackerName, tracker);
  371.  
  372.                 if (m_gsCallback)
  373.                         m_gsCallback->OnNodeAdded(newLocator);
  374.         }
  375.  
  376.         return tracker;
  377. }
  378.  
  379. //////////////////////////////////////////////////////////////////////////
  380.  
  381. bool CGameStatistics::ValidateAddElement(const SNodeLocator& locator)
  382. {
  383.         const SGameElementDesc* desc = m_elemRegistry.GetDesc(locator.elemID);
  384.         CRY_ASSERT(desc && (desc->locatorID == locator.locatorType));
  385.         CRY_ASSERT(!locator.isScope());
  386.  
  387.         if (!desc || locator.isScope() || desc->locatorID != locator.locatorType)
  388.         {
  389.                 CryWarning(VALIDATOR_MODULE_GAME, VALIDATOR_ERROR, "CGameStatistics::AddGameElement() Invalid locator");
  390.                 return false;
  391.         }
  392.  
  393.         size_t stackPos = m_gameScopes.FindScopePos(locator.scopeID);
  394.  
  395.         CRY_ASSERT_MESSAGE(stackPos != m_gameScopes.GetStackSize(), "Elements can be added only to the scopes on the stack");
  396.         if (stackPos == m_gameScopes.GetStackSize())
  397.         {
  398.                 CryWarning(VALIDATOR_MODULE_GAME, VALIDATOR_ERROR, "CGameStatistics::AddGameElement() attempt to add element to non existing scope");
  399.                 return false;
  400.         }
  401.  
  402.         return true;
  403. }
  404.  
  405. //////////////////////////////////////////////////////////////////////////
  406.  
  407. void CGameStatistics::RemoveElement(const SNodeLocator& locator)
  408. {
  409.         FUNCTION_PROFILER(GetISystem(), PROFILE_ACTION);
  410.  
  411.         size_t stackPos = m_gameScopes.FindScopePos(locator.scopeID);
  412.  
  413.         CRY_ASSERT_MESSAGE(stackPos != m_gameScopes.GetStackSize(), "No such scope on the stack");
  414.         if (stackPos == m_gameScopes.GetStackSize())
  415.         {
  416.                 CryWarning(VALIDATOR_MODULE_GAME, VALIDATOR_ERROR, "CGameStatistics::RemoveElement() attempt to remove element from non existing scope");
  417.                 return;
  418.         }
  419.  
  420.         SScopeData::TElements& elems = m_gameScopes.GetScopeAt(stackPos).elements;
  421.  
  422.         SScopeData::TElements::iterator it = elems.find(locator);
  423.         if (it != elems.end())
  424.         {
  425.                 if (!DoRemoveElement(stackPos, it->first, it->second))
  426.                         delete it->second;
  427.  
  428.                 elems.erase(it);
  429.                 CheckMemoryOverflow();
  430.         }
  431. }
  432.  
  433. //////////////////////////////////////////////////////////////////////////
  434.  
  435. bool CGameStatistics::DoRemoveElement(size_t scopePos, const SNodeLocator& locator, CStatsTracker* tracker)
  436. {
  437.         const SGameElementDesc* desc = m_elemRegistry.GetDesc(locator.elemID);
  438.         CRY_ASSERT(desc);
  439.         if (!desc)
  440.                 return false;
  441.  
  442.         SDeadStatNode* deadNode = new SDeadStatNode(locator, tracker);
  443.         m_gameScopes.GetScopeAt(scopePos).deadNodes.push_back(deadNode);
  444.  
  445.         m_cachedDeadMemory += deadNode->GetMemoryStatistics();
  446.  
  447.         if (tracker->GetScriptTable())
  448.                 m_scriptBind->UnbindTracker(tracker->GetScriptTable(), desc->trackerName, tracker);
  449.  
  450.         if (m_gsCallback)
  451.                 m_gsCallback->OnNodeRemoved(locator, tracker);
  452.  
  453.         return true;
  454. }
  455.  
  456. //////////////////////////////////////////////////////////////////////////
  457.  
  458. void CGameStatistics::RemoveAllElements(size_t stackPos)
  459. {
  460.         SScopeData::TElements& elems = m_gameScopes.GetScopeAt(stackPos).elements;
  461.  
  462.         for (SScopeData::TElements::iterator it = elems.begin(); it != elems.end(); ++it)
  463.         {
  464.                 if (!DoRemoveElement(stackPos, it->first, it->second))
  465.                         delete it->second;
  466.         }
  467.  
  468.         elems.clear();
  469. }
  470.  
  471. //////////////////////////////////////////////////////////////////////////
  472.  
  473. size_t CGameStatistics::GetElementCount() const
  474. {
  475.         return m_elemRegistry.Count();
  476. }
  477.  
  478. //////////////////////////////////////////////////////////////////////////
  479.  
  480. size_t CGameStatistics::GetElementID(const char* scriptName) const
  481. {
  482.         return m_elemRegistry.GetID(scriptName);
  483. }
  484.  
  485. //////////////////////////////////////////////////////////////////////////
  486.  
  487. const SGameElementDesc* CGameStatistics::GetElementDesc(size_t elemID) const
  488. {
  489.         return m_elemRegistry.GetDesc(elemID);
  490. }
  491.  
  492. //////////////////////////////////////////////////////////////////////////
  493. //////////////////////////////////////////////////////////////////////////
  494.  
  495. IStatsTracker* CGameStatistics::GetTracker(const SNodeLocator& locator) const
  496. {
  497.         CRY_ASSERT(locator.scopeID < m_gameScopes.GetRegisteredCount());
  498.  
  499.         if (locator.isScope())
  500.         {
  501.                 CRY_ASSERT(locator.elemID == INVALID_STAT_ID);
  502.  
  503.                 size_t pos = m_gameScopes.FindScopePos(locator.scopeID);
  504.  
  505.                 if (pos != m_gameScopes.GetStackSize())
  506.                         return m_gameScopes.GetScopeAt(pos).tracker;
  507.         }
  508.         else
  509.         {
  510.                 CRY_ASSERT(m_elemRegistry.GetDesc(locator.elemID));
  511.                 CRY_ASSERT(m_elemRegistry.GetDesc(locator.elemID)->locatorID == locator.locatorType);
  512.  
  513.                 size_t pos = m_gameScopes.FindScopePos(locator.scopeID);
  514.  
  515.                 if (pos != m_gameScopes.GetStackSize())
  516.                 {
  517.                         const SScopeData::TElements& elems = m_gameScopes.GetScopeAt(pos).elements;
  518.                         SScopeData::TElements::const_iterator it = elems.find(locator);
  519.                         if (it != elems.end())
  520.                                 return it->second;
  521.                 }
  522.         }
  523.         return 0;
  524. }
  525.  
  526. //////////////////////////////////////////////////////////////////////////
  527.  
  528. SNodeLocator CGameStatistics::GetTrackedNode(IStatsTracker* tracker) const
  529. {
  530.         CRY_ASSERT(tracker);
  531.         if (!tracker)
  532.                 return SNodeLocator();
  533.  
  534.         CStatsTracker* track = static_cast<CStatsTracker*>(tracker);
  535.         return track->GetLocator();
  536. }
  537.  
  538. //////////////////////////////////////////////////////////////////////////
  539. // Misc
  540. //////////////////////////////////////////////////////////////////////////
  541.  
  542. // Wrapper for XML data for IXMLSerializable
  543. class CXMLStatsWrapper : public CXMLSerializableBase
  544. {
  545. public:
  546.         CXMLStatsWrapper(const XmlNodeRef& node) : m_node(node)
  547.         {}
  548.  
  549.         virtual XmlNodeRef GetXML(IGameStatistics* pGS)
  550.         { return m_node; }
  551.  
  552.         virtual void GetMemoryStatistics(ICrySizer* pSizer) const
  553.         { pSizer->Add(*this); }
  554.  
  555. private:
  556.         XmlNodeRef m_node;
  557. };
  558.  
  559. //////////////////////////////////////////////////////////////////////////
  560.  
  561. IXMLSerializable* CGameStatistics::WrapXMLNode(const XmlNodeRef& node)
  562. {
  563.         return new CXMLStatsWrapper(node);
  564. }
  565.  
  566. //////////////////////////////////////////////////////////////////////////
  567.  
  568. void CGameStatistics::PreprocessScriptedEventParameter(size_t eventID, SStatAnyValue& value)
  569. {
  570.         FUNCTION_PROFILER(GetISystem(), PROFILE_ACTION);
  571.  
  572.         if (m_gsCallback)
  573.                 m_gsCallback->PreprocessScriptedEventParameter(eventID, value);
  574. }
  575.  
  576. void CGameStatistics::PreprocessScriptedStateParameter(size_t stateID, SStatAnyValue& value)
  577. {
  578.         FUNCTION_PROFILER(GetISystem(), PROFILE_ACTION);
  579.  
  580.         if (m_gsCallback)
  581.                 m_gsCallback->PreprocessScriptedStateParameter(stateID, value);
  582. }
  583.  
  584. //////////////////////////////////////////////////////////////////////////
  585.  
  586. void CGameStatistics::SetStatisticsCallback(IGameStatisticsCallback* pCallback)
  587. {
  588.         // Allow reset only
  589.         CRY_ASSERT(!m_gsCallback || !pCallback);
  590.  
  591.         m_gsCallback = pCallback;
  592. }
  593.  
  594. //////////////////////////////////////////////////////////////////////////
  595.  
  596. IGameStatisticsCallback* CGameStatistics::GetStatisticsCallback() const
  597. {
  598.         return m_gsCallback;
  599. }
  600.  
  601. //////////////////////////////////////////////////////////////////////////
  602.  
  603. void CGameStatistics::SetStorageFactory(IStatsStorageFactory* pFactory)
  604. {
  605.         m_storageFactory = pFactory ? pFactory : &m_defaultStorageFactory;
  606. }
  607.  
  608. //////////////////////////////////////////////////////////////////////////
  609.  
  610. IStatsStorageFactory* CGameStatistics::GetStorageFactory() const
  611. {
  612.         return m_storageFactory;
  613. }
  614.  
  615. //////////////////////////////////////////////////////////////////////////
  616.  
  617. void CGameStatistics::RegisterSerializer(IStatsSerializer* serializer)
  618. {
  619.         CRY_ASSERT(serializer);
  620.         if (!serializer)
  621.                 return;
  622.  
  623.         m_serializers.push_back(serializer);
  624. }
  625.  
  626. //////////////////////////////////////////////////////////////////////////
  627.  
  628. void CGameStatistics::UnregisterSerializer(IStatsSerializer* serializer)
  629. {
  630.         stl::find_and_erase(m_serializers, serializer);
  631.         if (m_serializers.empty())
  632.                 stl::free_container(m_serializers);
  633. }
  634.  
  635. //////////////////////////////////////////////////////////////////////////
  636.  
  637. void CGameStatistics::SetMemoryLimit(size_t kb)
  638. {
  639.         m_memoryLimit = kb << 10;
  640.         CheckMemoryOverflow();
  641. }
  642.  
  643. //////////////////////////////////////////////////////////////////////////
  644.  
  645. void CGameStatistics::GetMemoryStatistics(ICrySizer* pSizer) const
  646. {
  647.         SIZER_COMPONENT_NAME(pSizer, "Statistics");
  648.         pSizer->Add(*this);
  649.  
  650.         m_eventRegistry.GetMemoryStatistics(pSizer);
  651.         m_stateRegistry.GetMemoryStatistics(pSizer);
  652.         m_elemRegistry.GetMemoryStatistics(pSizer);
  653.         m_gameScopes.GetMemoryStatistics(pSizer);
  654. }
  655.  
  656. //////////////////////////////////////////////////////////////////////////
  657.  
  658. void CGameStatistics::CheckMemoryOverflow()
  659. {
  660.         FUNCTION_PROFILER(GetISystem(), PROFILE_ACTION);
  661.  
  662.         size_t totalMemory = m_cachedDeadMemory + m_cachedLiveUnloadableMemory;
  663.  
  664.         if (totalMemory >= m_memoryLimit)
  665.         {
  666.                 m_cachedDeadMemory = 0;
  667.                 m_cachedLiveUnloadableMemory = 0;
  668.  
  669.                 SaveScopesRec();
  670.         }
  671. }
  672.  
  673. //////////////////////////////////////////////////////////////////////////
  674.  
  675. const char* CGameStatistics::GetSerializeName(const SNodeLocator& locator) const
  676. {
  677.         return locator.isScope()
  678.                ? GetScopeDesc(locator.scopeID)->serializeName
  679.                : GetElementDesc(locator.elemID)->serializeName;
  680. }
  681.  
  682. //////////////////////////////////////////////////////////////////////////
  683.  
  684. void CGameStatistics::SaveDeadNodesRec(SDeadStatNode* node)
  685. {
  686.         FUNCTION_PROFILER(GetISystem(), PROFILE_ACTION);
  687.  
  688.         const char* serializeName = GetSerializeName(node->locator);
  689.  
  690.         NotifyVisitNode(node->locator, serializeName, *node->tracker->GetStatsContainer(), eSNS_Dead);
  691.  
  692.         for (size_t i = 0; i != node->children.size(); ++i)
  693.                 SaveDeadNodesRec(node->children[i]);
  694.  
  695.         node->children.clear();
  696.         NotifyLeaveNode(node->locator, serializeName, *node->tracker->GetStatsContainer(), eSNS_Dead);
  697.  
  698.         delete node;
  699. }
  700.  
  701. //////////////////////////////////////////////////////////////////////////
  702.  
  703. void CGameStatistics::SaveScopesRec(size_t scopePos)
  704. {
  705.         FUNCTION_PROFILER(GetISystem(), PROFILE_ACTION);
  706.  
  707.         SScopeData& sd = m_gameScopes.GetScopeAt(scopePos);
  708.         IStatsContainer& scopeCont = *sd.tracker->GetStatsContainer();
  709.  
  710.         const char* sname = GetSerializeName(sd.locator);
  711.         NotifyVisitNode(sd.locator, sname, scopeCont, eSNS_Alive);
  712.  
  713.         CStatsSizer sizer;
  714.  
  715.         // Iterate over live elements and give a chance to save container data
  716.         for (SScopeData::TElements::const_iterator it = sd.elements.begin();
  717.              it != sd.elements.end();
  718.              ++it)
  719.         {
  720.                 IStatsContainer& cont = *it->second->GetStatsContainer();
  721.  
  722.                 if (cont.IsEmpty())
  723.                         continue;
  724.  
  725.                 const char* elName = GetSerializeName(it->first);
  726.                 NotifyVisitNode(it->first, elName, cont, eSNS_Alive);
  727.                 NotifyLeaveNode(it->first, elName, cont, eSNS_Alive);
  728.  
  729.                 cont.GetMemoryStatistics(&sizer);
  730.         }
  731.  
  732.         if ((scopePos + 1) < m_gameScopes.GetStackSize())
  733.                 SaveScopesRec(scopePos + 1);
  734.  
  735.         // Traverse dead elements
  736.         for (size_t i = 0; i != sd.deadNodes.size(); ++i)
  737.                 SaveDeadNodesRec(sd.deadNodes[i]);
  738.         sd.deadNodes.clear();
  739.  
  740.         NotifyLeaveNode(sd.locator, sname, scopeCont, eSNS_Alive);
  741.  
  742.         // Update memory
  743.         scopeCont.GetMemoryStatistics(&sizer);
  744.         m_cachedLiveUnloadableMemory += sizer.GetTotalSize();
  745. }
  746.  
  747. //////////////////////////////////////////////////////////////////////////
  748.  
  749. void CGameStatistics::NotifyVisitNode(const SNodeLocator& locator, const char* serializeName, IStatsContainer& container, EStatNodeState state)
  750. {
  751.         FUNCTION_PROFILER(GetISystem(), PROFILE_ACTION);
  752.  
  753.         for (size_t i = 0; i != m_serializers.size(); ++i)
  754.                 m_serializers[i]->VisitNode(locator, serializeName, container, state);
  755. }
  756.  
  757. void CGameStatistics::NotifyLeaveNode(const SNodeLocator& locator, const char* serializeName, IStatsContainer& container, EStatNodeState state)
  758. {
  759.         FUNCTION_PROFILER(GetISystem(), PROFILE_ACTION);
  760.  
  761.         for (size_t i = 0; i != m_serializers.size(); ++i)
  762.                 m_serializers[i]->LeaveNode(locator, serializeName, container, state);
  763. }
  764.  
  765. //////////////////////////////////////////////////////////////////////////
  766.  
  767. void CGameStatistics::GrowLiveMemUsage(const SStatAnyValue& value)
  768. {
  769.         CStatsSizer sizer;
  770.         value.GetMemoryUsage(&sizer);
  771.         m_cachedLiveUnloadableMemory += sizer.GetTotalSize();
  772. }
  773.  
  774. //////////////////////////////////////////////////////////////////////////
  775.  
  776. void CGameStatistics::OnTrackedEvent(const SNodeLocator& locator, size_t eventID, const CTimeValue& timeVal, const SStatAnyValue& value)
  777. {
  778.         GrowLiveMemUsage(value);
  779.  
  780.         if (!m_gsCallback)
  781.                 return;
  782.  
  783.         if (value.type == eSAT_TXML && value.pSerializable)
  784.                 value.pSerializable->DispatchEventToCallback(locator, eventID, timeVal, m_gsCallback);
  785.         else
  786.                 m_gsCallback->OnEvent(locator, eventID, timeVal, value);
  787.  
  788.         CheckMemoryOverflow();
  789. }
  790.  
  791. //////////////////////////////////////////////////////////////////////////
  792.  
  793. void CGameStatistics::OnTrackedState(const SNodeLocator& locator, size_t stateID, const SStatAnyValue& value)
  794. {
  795.         GrowLiveMemUsage(value);
  796.  
  797.         if (!m_gsCallback)
  798.                 return;
  799.  
  800.         if (value.type == eSAT_TXML && value.pSerializable)
  801.                 value.pSerializable->DispatchStateToCallback(locator, stateID, m_gsCallback);
  802.         else
  803.                 m_gsCallback->OnState(locator, stateID, value);
  804.  
  805.         CheckMemoryOverflow();
  806. }
  807.  
  808. //////////////////////////////////////////////////////////////////////////
  809.  
  810. IScriptTable* CGameStatistics::GetGameRulesTable()
  811. {
  812.         IGameRulesSystem* pGameRulesSystem = CCryAction::GetCryAction()->GetIGameRulesSystem();
  813.         IGameRules* pGameRules = pGameRulesSystem ? pGameRulesSystem->GetCurrentGameRules() : NULL;
  814.         IEntity* pRulesEntity = pGameRules ? pGameRules->GetEntity() : NULL;
  815.         IScriptTable* gameRulesTable = pRulesEntity ? pRulesEntity->GetScriptTable() : NULL;
  816.  
  817.         //-- LEAVING THIS ASSERT HERE BECAUSE WE'RE USING THIS FUNCTION WRONG AT THE END OF A SESSION FOR TELEMTERY AND WE NEED TO FIX IT LATER
  818.         CRY_ASSERT(gameRulesTable);
  819.         return gameRulesTable;
  820. }
  821.  
  822. //////////////////////////////////////////////////////////////////////////
  823.  
downloadGameStatistics.cpp Source code - Download CRYENGINE Source code
Related Source Codes/Software:
postal - 2017-06-11
reactide - Reactide is the first dedicated IDE for React web ... 2017-06-11
rkt - rkt is a pod-native container engine for Linux. It... 2017-06-11
uWebSockets - Tiny WebSockets https://for... 2017-06-11
realworld - TodoMVC for the RealWorld - Exemplary fullstack Me... 2017-06-11
CRYENGINE - CRYENGINE is a powerful real-time game development... 2017-06-11
goreplay - GoReplay is an open-source tool for capturing and ... 2017-06-10
pyenv - Simple Python version management 2017-06-10
redux-saga - An alternative side effect model for Redux apps ... 2017-06-10
angular-starter - 2017-06-10

 Back to top