BVB Source Codes

CRYENGINE Show GameSerialize.cpp Source code

Return Download CRYENGINE: download GameSerialize.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 "GameSerialize.h"
  5.  
  6. #include "GameSerializeHelpers.h"
  7.  
  8. #include "CryAction.h"
  9. #include "CryActionCVars.h"
  10.  
  11. #include <CryGame/IGameTokens.h>
  12. #include "ILevelSystem.h"
  13. #include "IActorSystem.h"
  14. #include "IItemSystem.h"
  15. #include "IGameRulesSystem.h"
  16. #include "IVehicleSystem.h"
  17. #include <CryMovie/IMovieSystem.h>
  18. #include "IPlayerProfiles.h"
  19. #include <CrySystem/IStreamEngine.h>
  20. #include "DialogSystem/DialogSystem.h"
  21. #include "MaterialEffects/MaterialEffects.h"
  22. #include "Network/GameContext.h"
  23. #include "Network/GameServerNub.h"
  24. #include "ColorGradientManager.h"
  25.  
  26. #ifdef USE_COPYPROTECTION
  27.         #include "CopyProtection.h"
  28. #endif
  29.  
  30. #include <CryCore/Platform/IPlatformOS.h>
  31. #include <CryPhysics/IDeferredCollisionEvent.h>
  32.  
  33. #include <set>
  34. #include <time.h>
  35. #include <CrySystem/ITimer.h>
  36.  
  37. //#define EXCESSIVE_ENTITY_DEBUG 1
  38. //#undef  EXCESSIVE_ENTITY_DEBUG
  39.  
  40. static const char* SAVEGAME_GAMESTATE_SECTION = "GameState";
  41. static const char* SAVEGAME_AISTATE_SECTION = "AIState";
  42. static const char* SAVEGAME_AIOBJECTID_SECTION = "AIObjectReservedIDs";
  43. static const char* SAVEGAME_GAMETOKEN_SECTION = "GameTokens";
  44. static const char* SAVEGAME_TERRAINSTATE_SECTION = "TerrainState";
  45. static const char* SAVEGAME_TIMER_SECTION = "Timer";
  46. static const char* SAVEGAME_FLOWSYSTEM_SECTION = "FlowSystem";
  47. static const char* SAVEGAME_COLORGRADIANTMANAGER_SECTION = "ColorGradientManager";
  48. static const char* SAVEGAME_DIALOGSYSTEM_SECTION = "DialogSystem";
  49. static const char* SAVEGAME_AUDIOSYSTEM_SECTION = "AudioSystem";
  50. static const char* SAVEGAME_LTLINVENTORY_SECTION = "LTLInventory";
  51. static const char* SAVEGAME_VIEWSYSTEM_SECTION = "ViewSystem";
  52. static const char* SAVEGAME_MATERIALEFFECTS_SECTION = "MatFX";
  53. static const char* SAVEGAME_BUILD_TAG = "build";
  54. static const char* SAVEGAME_TIME_TAG = "saveTime";
  55. static const char* SAVEGAME_VERSION_TAG = "version";
  56. static const char* SAVEGAME_LEVEL_TAG = "level";
  57. static const char* SAVEGAME_GAMERULES_TAG = "gameRules";
  58. static const char* SAVEGAME_CHECKPOINT_TAG = "checkPointName";
  59.  
  60. //static const char * SAVEGAME_DEFINITIONFILE_VALUE = "definitionFile";
  61.  
  62. static const int SAVEGAME_VERSION_VALUE = 32;
  63.  
  64. #ifndef _RELEASE
  65. struct CGameSerialize::DebugSaveParts
  66. {
  67.         DebugSaveParts(const TEntitiesToSerialize& entities, const CSaveGameHolder& saveGameHolder)
  68.                 : m_entities(entities)
  69.                 , m_saveGameHolder(saveGameHolder)
  70.         {
  71.         }
  72.  
  73.         void GetMemoryUsage(ICrySizer* pSizer) const
  74.         {
  75.                 pSizer->AddContainer(m_entities);
  76.                 pSizer->AddObject(m_saveGameHolder.Get());
  77.         }
  78.  
  79.         const TEntitiesToSerialize& m_entities;
  80.         const CSaveGameHolder&      m_saveGameHolder;
  81. };
  82. #endif
  83.  
  84. #define CHECKPOINT_OUTPUT true
  85.  
  86. ILevelInfo* GetLevelInfo()
  87. {
  88.         ILevelSystem* pLevelSystem = CCryAction::GetCryAction()->GetILevelSystem();
  89.         assert(pLevelSystem != 0);
  90.         if (pLevelSystem)
  91.         {
  92.                 return pLevelSystem->GetCurrentLevel();
  93.         }
  94.  
  95.         return NULL;
  96. }
  97.  
  98. bool VerifyEntities(const TBasicEntityDatas& basicEntityData)
  99. {
  100.         CRY_ASSERT(gEnv);
  101.         IEntitySystem* pEntitySystem = gEnv->pEntitySystem;
  102.         CRY_ASSERT(pEntitySystem);
  103.  
  104.         TBasicEntityDatas::const_iterator itEnd = basicEntityData.end();
  105.         for (TBasicEntityDatas::const_iterator it = basicEntityData.begin(); it != itEnd; ++it)
  106.         {
  107.                 if (IEntity* pEntity = gEnv->pEntitySystem->GetEntity(it->id))
  108.                 {
  109.                         if (!pEntity->IsGarbage() && !(pEntity->GetFlags() & ENTITY_FLAG_UNREMOVABLE) && (0 != strcmp(it->className, pEntity->GetClass()->GetName())))
  110.                         {
  111.                                 GameWarning("[LoadGame] Entity ID=%d '%s', class mismatch, should be '%s'", pEntity->GetId(), pEntity->GetEntityTextDescription().c_str(), it->className.c_str());
  112.                                 return false;
  113.                         }
  114.                 }
  115.         }
  116.  
  117.         return true;
  118. }
  119.  
  120. bool SSaveEnvironment::InitSave(const char* name, ESaveGameReason reason)
  121. {
  122.         // initialize serialization method
  123.         if (!m_pSaveGame.PointerOk())
  124.         {
  125.                 GameWarning("Invalid serialization method: %s", m_saveMethod);
  126.                 return false;
  127.         }
  128.         // TODO: figure correct path?
  129.         if (!m_pSaveGame->Init(name))
  130.         {
  131.                 GameWarning("Unable to save to %s", name);
  132.                 return false;
  133.         }
  134.  
  135.         m_pSaveGame->SetSaveGameReason(reason);
  136.  
  137.         return true;
  138. }
  139.  
  140. bool SLoadEnvironment::InitLoad(bool requireQuickLoad, const char* path)
  141. {
  142.         if (!m_pLoadGame.PointerOk())
  143.         {
  144.                 GameWarning("Failed to initialize loadgame.");
  145.                 return false;
  146.         }
  147.         // TODO: figure correct path?
  148.         if (!m_pLoadGame->Init(path))
  149.         {
  150.                 GameWarning("Unable to Load to %s", path);
  151.                 return false;
  152.         }
  153.  
  154.         m_checkpoint.Check("Loading&Uncompress");
  155.  
  156.         // editor always requires quickload
  157.         requireQuickLoad |= gEnv->IsEditor();
  158.  
  159.         // sanity checks - version, node names, etc
  160.         /*
  161.            if (0 != strcmp(rootNode->getTag(), SAVEGAME_ROOT_SECTION))
  162.            {
  163.            GameWarning( "Not a save game file: %s", path );
  164.            return false;
  165.            }
  166.          */
  167.  
  168.         int version = -1;
  169.         if (!m_pLoadGame->GetMetadata(SAVEGAME_VERSION_TAG, version) || version != SAVEGAME_VERSION_VALUE)
  170.         {
  171.                 GameWarning("Invalid save game version in %s; expecting %d got %d", path, SAVEGAME_VERSION_VALUE, version);
  172.                 return false;
  173.         }
  174.  
  175.         return true;
  176. }
  177.  
  178. //////////////////////////////////////////////////////////////////////////
  179. CGameSerialize::CGameSerialize()
  180. {
  181.         if (!gEnv->IsEditor())
  182.         {
  183.                 gEnv->pEntitySystem->AddSink(this, IEntitySystem::OnSpawn | IEntitySystem::OnRemove, 0);
  184.  
  185.                 if (ILevelSystem* pLS = CCryAction::GetCryAction()->GetILevelSystem())
  186.                         pLS->AddListener(this);
  187.         }
  188. }
  189.  
  190. CGameSerialize::~CGameSerialize()
  191. {
  192.         if (!gEnv->IsEditor())
  193.         {
  194.                 gEnv->pEntitySystem->RemoveSink(this);
  195.  
  196.                 if (ILevelSystem* pLS = CCryAction::GetCryAction()->GetILevelSystem())
  197.                         pLS->RemoveListener(this);
  198.         }
  199. }
  200.  
  201. //////////////////////////////////////////////////////////////////////////
  202. void CGameSerialize::OnSpawn(IEntity* pEntity, SEntitySpawnParams&)
  203. {
  204.         assert(pEntity);
  205.  
  206.         if (!gEnv->bMultiplayer && !(pEntity->GetFlags() & ENTITY_FLAG_UNREMOVABLE))
  207.         {
  208.                 bool bSerializeEntity = gEnv->pEntitySystem->ShouldSerializedEntity(pEntity);
  209.  
  210.                 if (bSerializeEntity)
  211.                 {
  212.                         m_dynamicEntities.insert(pEntity->GetId());
  213.                 }
  214.         }
  215. }
  216.  
  217. bool CGameSerialize::OnRemove(IEntity* pEntity)
  218. {
  219.         if (!gEnv->bMultiplayer)
  220.                 stl::find_and_erase(m_dynamicEntities, pEntity->GetId());
  221.  
  222.         // true means allow removal of entity
  223.         return true;
  224. }
  225.  
  226. //////////////////////////////////////////////////////////////////////////
  227. void CGameSerialize::OnLoadingStart(ILevelInfo* pLevelInfo)
  228. {
  229.         assert(pLevelInfo);
  230.  
  231.         // load the list of entities to serialize from the level pak.
  232.         //      This creates a list of ids which will be fully serialized.
  233.  
  234.         m_dynamicEntities.clear();
  235.         m_serializeEntities.clear();
  236.  
  237.         if (pLevelInfo)
  238.         {
  239.                 string levelPath = pLevelInfo->GetPath();
  240.                 string file = PathUtil::Make(levelPath.c_str(), "Serialize.xml");
  241.                 XmlNodeRef node = gEnv->pSystem->LoadXmlFromFile(file.c_str());
  242.                 if (node)
  243.                 {
  244.                         int count = node->getChildCount();
  245.                         m_serializeEntities.reserve(count);
  246.                         for (int i = 0; i < count; ++i)
  247.                         {
  248.                                 XmlNodeRef child = node->getChild(i);
  249.                                 EntityId id = 0;
  250.                                 child->getAttr("id", id);
  251.  
  252.                                 m_serializeEntities.push_back(id);
  253.                         }
  254.                 }
  255.         }
  256. }
  257.  
  258. void CGameSerialize::OnUnloadComplete(ILevelInfo* pLevel)
  259. {
  260.         stl::free_container(m_serializeEntities);
  261.         stl::free_container(m_dynamicEntities);
  262. }
  263.  
  264. //////////////////////////////////////////////////////////////////////////
  265. void CGameSerialize::RegisterSaveGameFactory(const char* name, SaveGameFactory factory)
  266. {
  267.         m_saveGameFactories[name] = factory;
  268. }
  269.  
  270. void CGameSerialize::RegisterLoadGameFactory(const char* name, LoadGameFactory factory)
  271. {
  272.         m_loadGameFactories[name] = factory;
  273. }
  274.  
  275. //////////////////////////////////////////////////////////////////////////
  276. void CGameSerialize::Clean()
  277. {
  278.         gEnv->pEntitySystem->DeletePendingEntities();
  279. }
  280.  
  281. bool CGameSerialize::IsUserSignedIn(CCryAction* pCryAction) const
  282. {
  283.         unsigned int user;
  284.         return pCryAction->GetISystem()->GetPlatformOS()->UserIsSignedIn(pCryAction->GetIPlayerProfileManager()->GetCurrentUser(), user);
  285. }
  286.  
  287. #ifndef _RELEASE
  288. void CGameSerialize::DebugPrintMemoryUsage(const DebugSaveParts& debugSaveParts) const
  289. {
  290.         if (CCryActionCVars::Get().g_debugSaveLoadMemory)
  291.         {
  292.                 ICrySizer* pSizer = GetISystem()->CreateSizer();
  293.  
  294.                 pSizer->AddObject(debugSaveParts);
  295.  
  296.                 const size_t bytes = pSizer->GetTotalSize();
  297.                 const size_t kb = bytes / 1024;
  298.  
  299.                 CryLogAlways("[SaveGame]: Spiked more than %" PRISIZE_T "KB while saving", kb);
  300.  
  301.                 pSizer->Release();
  302.         }
  303. }
  304. #endif
  305.  
  306. bool CGameSerialize::SaveGame(CCryAction* pCryAction, const char* method, const char* name, ESaveGameReason reason, const char* checkPointName)
  307. {
  308.         struct SSaveGameAutoCleanup
  309.         {
  310.                 SSaveGameAutoCleanup()
  311.                 {
  312.                         gEnv->pSystem->SetThreadState(ESubsys_Physics, false);
  313.                 }
  314.                 ~SSaveGameAutoCleanup()
  315.                 {
  316.                         gEnv->pSystem->SetThreadState(ESubsys_Physics, true);
  317.                 }
  318.         };
  319.  
  320.         // [AlexMcC|31.05.10] Wrap this whole giant scope so we can measure memory usage after freeing local variables
  321.         Checkpoint total(CHECKPOINT_OUTPUT, "TotalTime");
  322.         Checkpoint checkpoint(CHECKPOINT_OUTPUT);
  323.  
  324.         bool bResult = false;
  325.  
  326.         if (reason == eSGR_FlowGraph)
  327.         {
  328.                 if (pCryAction->IsInTimeDemo())
  329.                         return true; // Ignore checkpoint saving when running time demo
  330.         }
  331.  
  332.         if (gEnv->IsEditor())
  333.         {
  334.                 if (CCryActionCVars::Get().g_allowSaveLoadInEditor == 0)
  335.                 {
  336.                         const char* const szSafeName = name ? name : "<UNKNOWN>";
  337.                         const char* const szSafeCheckpointName = checkPointName ? checkPointName : "<UNKNOWN>";
  338.                         GameWarning("Ignoring editor savegame \"%s\" at checkpoint \"%s\"", szSafeName, szSafeCheckpointName);
  339.                         return false;
  340.                 }
  341.         }
  342.         else if (!IsUserSignedIn(pCryAction))
  343.         {
  344.                 return false;
  345.         }
  346.  
  347.         Vec3 camPos = gEnv->pSystem->GetViewCamera().GetPosition();
  348.         MEMSTAT_LABEL_FMT("Savegame_start (pos=%4.2f,%4.2f,%4.2f)", camPos.x, camPos.y, camPos.z);
  349.  
  350.         Clean();
  351.         checkpoint.Check("Clean");
  352.  
  353.         checkpoint.Check("Init");
  354.  
  355.         SSaveEnvironment saveEnvironment(pCryAction, checkPointName, method, checkpoint, m_saveGameFactories);
  356.         if (!saveEnvironment.InitSave(name, reason))
  357.                 return false;
  358.  
  359.         assert(gEnv->pSystem);
  360.         SSaveGameAutoCleanup autoCleanup;
  361.  
  362.         //savegame header
  363.         if (!SaveMetaData(saveEnvironment))
  364.         {
  365.                 return false;
  366.         }
  367.  
  368.         // engine and systems
  369.         SaveEngineSystems(saveEnvironment);
  370.  
  371.         // now the primary game stuff
  372.         if (!SaveEntities(saveEnvironment))
  373.         {
  374.                 return false;
  375.         }
  376.  
  377.         // AI final serialize (needs to be after both the AI and entity serialization)
  378.         if (gEnv->pAISystem)
  379.                 gEnv->pAISystem->SerializeObjectIDs(saveEnvironment.m_pSaveGame->AddSection(SAVEGAME_AIOBJECTID_SECTION));
  380.         checkpoint.Check("AI_FinalSerialize");
  381.  
  382.         Clean();
  383.         checkpoint.Check("Clean2");
  384.  
  385.         // final serialization
  386.         MEMSTAT_LABEL("Savegame_flush");
  387.         bResult = saveEnvironment.m_pSaveGame.Complete();
  388.         checkpoint.Check("Writing");
  389.  
  390.         MEMSTAT_LABEL("Savegame_end");
  391.         checkpoint.Check("Flushed memory");
  392.         return bResult;
  393. }
  394.  
  395. // helper function to position/rotate/etc.. all entities that currently
  396. // exist in the entity system based on current game state
  397. bool CGameSerialize::RepositionEntities(const TBasicEntityDatas& basicEntityData, bool insistOnAllEntitiesBeingThere)
  398. {
  399.         bool bErrors = false;
  400.         IEntitySystem* pEntitySystem = gEnv->pEntitySystem;
  401.         IEntityClass* pClothEntityClass = gEnv->pEntitySystem->GetClassRegistry()->FindClass("Cloth");
  402.  
  403.         TBasicEntityDatas::const_iterator iter = basicEntityData.begin();
  404.         TBasicEntityDatas::const_iterator end = basicEntityData.end();
  405.         for (; iter != end; ++iter)
  406.         {
  407.                 if (iter->ignorePosRotScl || iter->iPhysType == PE_SOFT)
  408.                         continue;
  409.  
  410.                 IEntity* pEntity = pEntitySystem->GetEntity(iter->id);
  411.                 if (pEntity)
  412.                 {
  413.                         // TODO: find a more generic way to do this. The basic problem is that we can not call SetPosRotScale atwill for clothes, because then the transformation is stacked for the verts.
  414.                         //       the iPhysType==PE_SOFT check does not always prevent this from happening, because cloth entities destroy their physical entity when hiden.
  415.                         //       so, if a cloth was hiden when the savegame was created, iPhysType will be NONE, and then SetPos will be called here on loading, and the cloth will look wrong (usually with accumulated rotation)
  416.                         if (pEntity->GetClass() == pClothEntityClass)
  417.                                 continue;
  418.  
  419.                         if (iter->parentEntity)
  420.                         {
  421.                                 IEntity* pParentEntity = pEntitySystem->GetEntity(iter->parentEntity);
  422.                                 if (!pParentEntity && insistOnAllEntitiesBeingThere)
  423.                                 {
  424.                                         GameWarning("[LoadGame] Missing Entity with ID=%d, probably was removed during Serialization.", iter->parentEntity);
  425.                                         bErrors = true;
  426.                                         continue;
  427.                                 }
  428.                                 else if (pParentEntity)
  429.                                 {
  430.                                         IEntity* pCurrentParentEntity = pEntity->GetParent();
  431.                                         if (pCurrentParentEntity != pParentEntity)
  432.                                         {
  433.                                                 if (pCurrentParentEntity)
  434.                                                         pEntity->DetachThis();
  435.                                                 pParentEntity->AttachChild(pEntity);
  436.                                         }
  437.                                 }
  438.                         }
  439.                         else
  440.                         {
  441.                                 if (pEntity->GetParent())
  442.                                         pEntity->DetachThis();
  443.                         }
  444.                         pEntity->SetPosRotScale(iter->pos, iter->rot, iter->scale);
  445.                 }
  446.                 else if (insistOnAllEntitiesBeingThere)
  447.                 {
  448.                         GameWarning("[LoadGame] Missing Entity ID=%d", iter->id);
  449.                         bErrors = true;
  450.                 }
  451.         }
  452.  
  453.         return !bErrors;
  454. }
  455.  
  456. //////////////////////////////////////////////////////////////////////////
  457. void CGameSerialize::ReserveEntityIds(const TBasicEntityDatas& basicEntityData)
  458. {
  459.         //////////////////////////////////////////////////////////////////////////
  460.         // Reserve id for local player.
  461.         //////////////////////////////////////////////////////////////////////////
  462.         gEnv->pEntitySystem->ReserveEntityId(LOCAL_PLAYER_ENTITY_ID);
  463.  
  464.         //////////////////////////////////////////////////////////////////////////
  465.         TBasicEntityDatas::const_iterator iter = basicEntityData.begin();
  466.         TBasicEntityDatas::const_iterator end = basicEntityData.end();
  467.         for (; iter != end; ++iter)
  468.         {
  469.                 const IEntity* pEntity = gEnv->pEntitySystem->GetEntity(iter->id);
  470.                 if (!pEntity)
  471.                 {
  472.                         // for existing entities this will set the salt to 0!
  473.                         gEnv->pEntitySystem->ReserveEntityId(iter->id);
  474. #ifdef EXCESSIVE_ENTITY_DEBUG
  475.                         EntityId id = iter->id;
  476.                         CryLogAlways("> ReserveEntityId: ID=%d HexID=%X", id, id);
  477. #endif
  478.                 }
  479.         }
  480. }
  481.  
  482. //////////////////////////////////////////////////////////////////////////
  483. void CGameSerialize::FlushActivatableGameObjectExtensions()
  484. {
  485.         IEntityItPtr pIt = gEnv->pEntitySystem->GetEntityIterator();
  486.  
  487.         pIt->MoveFirst();
  488.         while (!pIt->IsEnd())
  489.         {
  490.                 const IEntity* pEntity = pIt->Next();
  491.                 CGameObject* pGameObject = (CGameObject*) pEntity->GetProxy(ENTITY_PROXY_USER);
  492.                 if (pGameObject)
  493.                         pGameObject->FlushActivatableExtensions();
  494.         }
  495. }
  496.  
  497. //////////////////////////////////////////////////////////////////////////
  498. void CGameSerialize::DeleteDynamicEntities(const TBasicEntityDatas& basicEntityData)
  499. {
  500.         IEntitySystem* pEntitySystem = gEnv->pEntitySystem;
  501.  
  502. #ifdef EXCESSIVE_ENTITY_DEBUG
  503.         // dump entities which can potentially be re-used (if class matches)
  504.         CryLogAlways("*QL -----------------------------------------");
  505.         CryLogAlways("*QL DeleteDynamicEntities");
  506. #endif
  507.  
  508.         IEntityItPtr pIt = pEntitySystem->GetEntityIterator();
  509.         SBasicEntityData tempSearchEntity;
  510.         //////////////////////////////////////////////////////////////////////////
  511.         // Delete all entities except the unremovable ones and the local player.
  512.         pIt->MoveFirst();
  513.         while (!pIt->IsEnd())
  514.         {
  515.                 IEntity* pEntity = pIt->Next();
  516.                 uint32 nEntityFlags = pEntity->GetFlags();
  517.  
  518.                 // Local player must not be deleted.
  519.                 if (nEntityFlags & ENTITY_FLAG_LOCAL_PLAYER)
  520.                         continue;
  521.  
  522.                 if (nEntityFlags & ENTITY_FLAG_UNREMOVABLE)
  523.                 {
  524. #ifdef EXCESSIVE_ENTITY_DEBUG
  525.                         CryLogAlways(">Unremovable Entity ID=%d Name='%s'", pEntity->GetId(), pEntity->GetEntityTextDescription().c_str());
  526. #endif
  527.  
  528.                         tempSearchEntity.id = pEntity->GetId();
  529.                         if (pEntity->IsGarbage() && (stl::binary_find(basicEntityData.begin(), basicEntityData.end(), tempSearchEntity) != basicEntityData.end()))
  530.                         {
  531.                                 // Restore disabled, un-removable entity.
  532.                                 SEntityEvent event;
  533.                                 event.event = ENTITY_EVENT_INIT;
  534.                                 pEntity->SendEvent(event);
  535.                         }
  536.                 }
  537.                 else
  538.                 {
  539. #ifdef EXCESSIVE_ENTITY_DEBUG
  540.                         CryLogAlways(">Removing Entity ID=%d Name='%s'", pEntity->GetId(), pEntity->GetEntityTextDescription().c_str());
  541. #endif
  542.  
  543.                         pEntity->ResetKeepAliveCounter();
  544.                         pEntitySystem->RemoveEntity(pEntity->GetId());
  545.                 }
  546.         }
  547.         // Force deletion of removed entities.
  548.         pEntitySystem->DeletePendingEntities();
  549.         //////////////////////////////////////////////////////////////////////////
  550.  
  551. #ifdef EXCESSIVE_ENTITY_DEBUG
  552.         // dump entities which can potentially be re-used (if class matches)
  553.         CryLogAlways("*QL DeleteDynamicEntities Done");
  554.         CryLogAlways("*QL -----------------------------------------");
  555. #endif
  556. }
  557.  
  558. //////////////////////////////////////////////////////////////////////////
  559. void CGameSerialize::DumpEntities()
  560. {
  561.         IEntityItPtr pIt = gEnv->pEntitySystem->GetEntityIterator();
  562.         pIt->MoveFirst();
  563.         while (!pIt->IsEnd())
  564.         {
  565.                 IEntity* pEntity = pIt->Next();
  566.                 if (pEntity)
  567.                 {
  568.                         CryLogAlways("ID=%u Name='%s'", pEntity->GetId(), pEntity->GetEntityTextDescription().c_str());
  569.                 }
  570.                 else
  571.                 {
  572.                         CryLogAlways("Invalid NULL entity encountered.");
  573.                 }
  574.         }
  575. }
  576.  
  577. //////////////////////////////////////////////////////////////////////////
  578. // TODO: split maybe into some separate classes...
  579. ELoadGameResult CGameSerialize::LoadGame(CCryAction* pCryAction, const char* method, const char* path, SGameStartParams& startParams, bool requireQuickLoad)
  580. {
  581.         struct SLoadGameAutoCleanup
  582.         {
  583.                 SLoadGameAutoCleanup(bool _pauseStreaming)
  584.                         : pauseStreaming(_pauseStreaming)
  585.                 {
  586.                         if (pauseStreaming)
  587.                         {
  588.                                 // Pause streaming engine for anything but sound, video and flash.
  589.                                 uint32 nMask = (1 << eStreamTaskTypeFlash) | (1 << eStreamTaskTypeVideo) | STREAM_TASK_TYPE_AUDIO_ALL; // Unblock specified streams
  590.                                 nMask = ~nMask;                                                                                        // Invert mask, bit set means blocking type.
  591.                                 GetISystem()->GetStreamEngine()->PauseStreaming(true, nMask);
  592.                         }
  593.  
  594.                         gEnv->pSystem->SetThreadState(ESubsys_Physics, false);
  595.                 }
  596.                 ~SLoadGameAutoCleanup()
  597.                 {
  598.                         if (pauseStreaming)
  599.                         {
  600.                                 GetISystem()->GetStreamEngine()->PauseStreaming(false, -1);
  601.                         }
  602.  
  603.                         gEnv->pSystem->SetThreadState(ESubsys_Physics, true);
  604.                 }
  605.                 bool pauseStreaming;
  606.         } autoCleanup(requireQuickLoad);
  607.  
  608.         if (gEnv->IsEditor())
  609.         {
  610.                 if (CCryActionCVars::Get().g_allowSaveLoadInEditor == 0)
  611.                 {
  612.                         const char* const szSafeName = path ? path : "<UNKNOWN>";
  613.                         GameWarning("Ignoring editor loadgame \"%s\"", szSafeName);
  614.                         return eLGR_Failed;
  615.                 }
  616.         }
  617.         else if (!IsUserSignedIn(pCryAction))
  618.         {
  619.                 return eLGR_Failed;
  620.         }
  621.  
  622.         CryGetIMemReplay()->AddLabel("Loadgame_start");
  623.         Checkpoint total(CHECKPOINT_OUTPUT, "TotalTime");
  624.         Checkpoint checkpoint(CHECKPOINT_OUTPUT);
  625.  
  626.         // stop all deferred physics events in the fly
  627.         if (gEnv->p3DEngine)
  628.         {
  629.                 IDeferredPhysicsEventManager* pDeferredPhysicsEventManager = gEnv->p3DEngine->GetDeferredPhysicsEventManager();
  630.                 if (pDeferredPhysicsEventManager)
  631.                         pDeferredPhysicsEventManager->ClearDeferredEvents();
  632.         }
  633.  
  634.         Clean();
  635.  
  636.         // need to leave the player entity in the list, else it won't get
  637.         //      saved after this point (it isn't deleted/respawned)
  638.         m_dynamicEntities.clear();
  639.         m_dynamicEntities.insert(CCryAction::GetCryAction()->GetClientActorId());
  640.         checkpoint.Check("Clean");
  641.  
  642.         //////////////////////////////////////////////////////////////////////////
  643.         // Lock geometries to not be released during game loading.
  644.         STempAutoResourcesLock autoResourcesLock;
  645.         //////////////////////////////////////////////////////////////////////////
  646.  
  647.         IEntitySystem* pEntitySystem = gEnv->pEntitySystem;
  648.  
  649.         //create load environment
  650.         SLoadEnvironment loadEnvironment(pCryAction, checkpoint, method, m_loadGameFactories);
  651.         if (!loadEnvironment.InitLoad(requireQuickLoad, path)) // the savegame file is actually loaded into memory in this call.
  652.         {
  653.                 return eLGR_Failed;
  654.         }
  655.  
  656.         const char* levelName = loadEnvironment.m_pLoadGame->GetMetadata(SAVEGAME_LEVEL_TAG);
  657.         pCryAction->NotifySavegameFileLoadedToListeners(levelName);
  658.         TBasicEntityDatas& basicEntityData = loadEnvironment.m_basicEntityData;
  659.  
  660.         // compare the build numbers; output a warning if different to notify that there might be
  661.         //      issues (if level or code have changed).
  662.         //      Ideally we'd refuse to load saves from another build but that won't work for post-release patching.
  663.         const char* buildName = loadEnvironment.m_pLoadGame->GetMetadata(SAVEGAME_BUILD_TAG);
  664.         const SFileVersion& fileVersion = GetISystem()->GetFileVersion();
  665.         char tmpbuf[128];
  666.         fileVersion.ToString(tmpbuf);
  667.         if (strcmp(tmpbuf, buildName))
  668.         {
  669.                 GameWarning("Loading a save from a different build, may result in errors. Save = %s; Current = %s", buildName, tmpbuf);
  670.         }
  671.  
  672.         // also output the checkpoint name if available - helps with Resume bugs
  673.         const char* checkpointName = loadEnvironment.m_pLoadGame->GetMetadata(SAVEGAME_CHECKPOINT_TAG);
  674.         if (checkpointName && checkpointName[0])
  675.         {
  676.                 CryLog("Loading checkpoint %s", checkpointName);
  677.         }
  678.  
  679.         const char* sCurrentLevel = pCryAction->GetLevelName();
  680.         const bool bIsQuickLoading = sCurrentLevel != 0 && (stricmp(sCurrentLevel, levelName) == 0);
  681.         if (requireQuickLoad && !bIsQuickLoading)
  682.         {
  683.                 GameWarning("Unable to quick load: different level names (%s != %s)", sCurrentLevel, levelName);
  684.                 return eLGR_CantQuick_NeedFullLoad;
  685.         }
  686.  
  687.         // basic game state loading... need to do it early to verify and reserve entity id's
  688.         std::unique_ptr<TSerialize> pGameStateSer(loadEnvironment.m_pLoadGame->GetSection(SAVEGAME_GAMESTATE_SECTION));
  689.         if (!pGameStateSer.get())
  690.         {
  691.                 return eLGR_Failed;
  692.         }
  693.  
  694.         {
  695.                 pGameStateSer->BeginGroup("BasicEntityData");
  696.                 int size = 0;
  697.                 pGameStateSer->Value("BasicEntityDataSize", size);
  698.                 basicEntityData.resize(size);
  699.                 for (int i = 0; i < size; ++i)
  700.                 {
  701.                         pGameStateSer->BeginGroup("BasicEntity");
  702.                         basicEntityData[i].Serialize(*pGameStateSer);
  703.                         pGameStateSer->EndGroup();
  704.                 }
  705.                 pGameStateSer->EndGroup();
  706.         }
  707.  
  708.         //this early out doesn't work anymore, find better ways to identify corrupt savegames
  709.         /*
  710.            if (bIsQuickLoading && !VerifyEntities(basicEntityData))
  711.            {
  712.             GameWarning("[LoadGame] Corrupt savegame detected, aborting load");
  713.             return eLGR_Failed;
  714.            }*/
  715.  
  716.         //point of no return, if loading fails now, the game can't recover
  717.         //this has to be fixed in Crysis 3
  718.  
  719.         //reset all entities if using layer-based serialization
  720.         SEntityEvent resetEvent(ENTITY_EVENT_RESET);
  721.         ICVar* pLayerSaveLoad = gEnv->pConsole->GetCVar("es_layerSaveLoadSerialization");
  722.         //we only need this reset for non-serialized stuff on deactivated layers
  723.         //but it probably doesn't hurt to always use it ..
  724.         if (pLayerSaveLoad && pLayerSaveLoad->GetIVal() == 1)
  725.                 gEnv->pEntitySystem->SendEventToAll(resetEvent);
  726.  
  727.         //tell existing entities that serialization starts
  728.         SEntityEvent serializeEvent(ENTITY_EVENT_PRE_SERIALIZE);
  729.         gEnv->pEntitySystem->SendEventToAll(serializeEvent);
  730.  
  731.         loadEnvironment.m_checkpoint.Check("PreSerialize Event");
  732.  
  733.         // load timer data
  734.         loadEnvironment.m_pSer = loadEnvironment.m_pLoadGame->GetSection(SAVEGAME_TIMER_SECTION);
  735.         if (loadEnvironment.m_pSer.get())
  736.                 gEnv->pTimer->Serialize(*loadEnvironment.m_pSer);
  737.         else
  738.         {
  739.                 GameWarning("Unable to find timer");
  740.                 return eLGR_Failed;
  741.         }
  742.  
  743.         // call CryAction's Framework listeners
  744.         pCryAction->NotifyGameFrameworkListeners(loadEnvironment.m_pLoadGame.Get());
  745.  
  746.         checkpoint.Check("FrameWork Listeners");
  747.  
  748.         // reset movie system, don't play any sequences
  749.         if (gEnv->pMovieSystem)
  750.                 gEnv->pMovieSystem->Reset(false, false);
  751.  
  752.         checkpoint.Check("MovieSystem");
  753.  
  754.         // reset areas (who entered who caches get flushed)
  755.         pEntitySystem->ResetAreas();
  756.  
  757.         // Prepare next level?
  758.         if (!bIsQuickLoading)
  759.         {
  760.                 gEnv->pSystem->GetISystemEventDispatcher()->OnSystemEvent(ESYSTEM_EVENT_LEVEL_LOAD_PREPARE, 0, 0);
  761.  
  762.                 pEntitySystem->Reset();
  763.  
  764.                 // delete any left-over entities
  765.                 pEntitySystem->DeletePendingEntities();
  766.                 FlushActivatableGameObjectExtensions();
  767.                 pCryAction->FlushBreakableObjects();
  768.  
  769.                 // Clean all entities that should not be in system before loading entities from savegame.
  770.                 DeleteDynamicEntities(loadEnvironment.m_basicEntityData); //must happen before reserving entities
  771.  
  772.                 // end the game context
  773.                 autoResourcesLock.Unlock();
  774.                 pCryAction->EndGameContext();
  775.                 autoResourcesLock.Lock();
  776.  
  777.                 if (ILevelSystem* pLevelSystem = CCryAction::GetCryAction()->GetILevelSystem())
  778.                 {
  779.                         pLevelSystem->PrepareNextLevel(levelName);
  780.                 }
  781.  
  782.                 // For the non-quickload path, the flush/reload nav happens after
  783.                 //      the level load. This ensures AI objects created during level load
  784.                 //      are not present when the entity pool etc are serialized.
  785.         }
  786.         else
  787.         {
  788.                 // ai system data
  789.                 // let's reset first
  790.                 if (gEnv->pAISystem)
  791.                         gEnv->pAISystem->FlushSystem();
  792.  
  793.                 // Flushing the system clears the navagation data, so reload it.
  794.                 const ILevelInfo* pLevelInfo = GetLevelInfo();
  795.                 CRY_ASSERT_MESSAGE(CCryAction::GetCryAction()->StartedGameContext() == false || (pLevelInfo != 0), "Can't find level info: This might break AI");
  796.                 if (pLevelInfo)
  797.                 {
  798.                         const ILevelInfo::TGameTypeInfo* pGameTypeInfo = pLevelInfo->GetDefaultGameType();
  799.                         const char* const szGameTypeName = pGameTypeInfo ? pGameTypeInfo->name.c_str() : "";
  800.                         if (gEnv->pAISystem)
  801.                         {
  802.                                 const EAILoadDataFlags loadDataFlags = eAILoadDataFlag_AllSystems | (bIsQuickLoading ? eAILoadDataFlag_QuickLoad : eAILoadDataFlag_None);
  803.                                 gEnv->pAISystem->LoadLevelData(pLevelInfo->GetPath(), szGameTypeName, loadDataFlags);
  804.                         }
  805.                 }
  806.  
  807.                 checkpoint.Check("AIFlush");
  808.         }
  809.  
  810.         // Entity ids vector must always be sorted, binary search is used on it.
  811.         std::sort(basicEntityData.begin(), basicEntityData.end());
  812.  
  813.         checkpoint.Check("EntityIDSort");
  814.  
  815.         // load the level
  816.         if (!LoadLevel(loadEnvironment, startParams, autoResourcesLock, bIsQuickLoading, requireQuickLoad))
  817.         {
  818.                 return loadEnvironment.m_failure;
  819.         }
  820.  
  821.         // AI object ID serialization (needs to be before the AI and entity serialization, but after the AI flush)
  822.         {
  823.                 loadEnvironment.m_pSer = loadEnvironment.m_pLoadGame->GetSection(SAVEGAME_AIOBJECTID_SECTION);
  824.  
  825.                 if (loadEnvironment.m_pSer.get())
  826.                 {
  827.                         if (gEnv->pAISystem)
  828.                                 gEnv->pAISystem->SerializeObjectIDs(*loadEnvironment.m_pSer);
  829.                 }
  830.                 else
  831.                 {
  832.                         GameWarning("Unable to open section %s", SAVEGAME_AIOBJECTID_SECTION);
  833.                 }
  834.                 checkpoint.Check("AI_ObjectIDs");
  835.         }
  836.  
  837.         // load engine systems
  838.         LoadEngineSystems(loadEnvironment);
  839.  
  840.         // load entities
  841.         if (!LoadEntities(loadEnvironment, std::move(pGameStateSer)))
  842.         {
  843.                 return loadEnvironment.m_failure;
  844.         }
  845.         assert(!loadEnvironment.m_bLoadingErrors);
  846.  
  847.         // load game data and proxies
  848.         LoadGameData(loadEnvironment);
  849.         //assert(!loadEnvironment.m_bLoadingErrors);
  850.  
  851.         //unlock entity system
  852.         pEntitySystem->LockSpawning(false);
  853.  
  854. #ifdef _DEBUG
  855.         //look for additionally spawned entities (that are not in the save file)
  856.         {
  857.                 IEntityItPtr pIt = pEntitySystem->GetEntityIterator();
  858.                 pIt->MoveFirst();
  859.                 SBasicEntityData tempSearchEntity;
  860.                 while (!pIt->IsEnd())
  861.                 {
  862.                         IEntity* pNextEntity = pIt->Next();
  863.                         uint32 flags = pNextEntity->GetFlags();
  864.                         if (!pNextEntity->IsGarbage() && !(flags & ENTITY_FLAG_UNREMOVABLE && flags & ENTITY_FLAG_NO_SAVE))
  865.                         {
  866.                                 tempSearchEntity.id = pNextEntity->GetId();
  867.                                 if ((stl::binary_find(loadEnvironment.m_basicEntityData.begin(), loadEnvironment.m_basicEntityData.end(), tempSearchEntity) == loadEnvironment.m_basicEntityData.end()))
  868.                                         GameWarning("[LoadGame] Entities were spawned that are not in the save file! : %s with ID=%d", pNextEntity->GetEntityTextDescription().c_str(), pNextEntity->GetId());
  869.                         }
  870.                 }
  871.         }
  872. #endif
  873.  
  874.         loadEnvironment.m_pSer = loadEnvironment.m_pLoadGame->GetSection(SAVEGAME_AISTATE_SECTION);
  875.  
  876.         if (!loadEnvironment.m_pSer.get())
  877.         {
  878.                 GameWarning("No AI section in save game");
  879.                 //return failure;
  880.                 loadEnvironment.m_bLoadingErrors = true;
  881.         }
  882.         else
  883.         {
  884.                 if (gEnv->pAISystem)
  885.                         gEnv->pAISystem->Serialize(*loadEnvironment.m_pSer);
  886.         }
  887.         checkpoint.Check("AI System");
  888.  
  889.         //clear old entities from the systems [could become obsolete]
  890.         //gEnv->pGameFramework->GetIItemSystem()->Reset(); //this respawns ammo, moved before serialization
  891.         gEnv->pGameFramework->GetIActorSystem()->Reset();
  892.         gEnv->pGameFramework->GetIVehicleSystem()->Reset();
  893.         //We need to reset particles to get rid of certain effects from before the load
  894.         gEnv->pParticleManager->Reset();
  895.         checkpoint.Check("ResetSubSystems");
  896.  
  897.         //when loading a save game from scratch this is hopefully singleplayer; let network know ...
  898.         pCryAction->GetGameServerNub()->SetMaxPlayers(1);
  899.  
  900.         if (GetISystem()->IsSerializingFile() == 1)    //general quickload fix-ups
  901.         {
  902.                 //clear keys
  903.                 gEnv->pInput->ClearKeyState();
  904.         }
  905.  
  906.         if (gEnv->p3DEngine)
  907.         {
  908.                 gEnv->p3DEngine->PostSerialize(true);
  909.                 checkpoint.Check("3DPostSerialize");
  910.         }
  911.  
  912. #ifdef EXCESSIVE_ENTITY_DEBUG
  913.         CryLogAlways("Dumping Entities after serialization");
  914.         DumpEntities();
  915. #endif
  916.  
  917.         //inform all entities that serialization is over
  918.         SEntityEvent event2(ENTITY_EVENT_POST_SERIALIZE);
  919.         pEntitySystem->SendEventToAll(event2);
  920.  
  921.         if (auto* pGame = CCryAction::GetCryAction()->GetIGame())
  922.                 pGame->PostSerialize();
  923.  
  924.         gEnv->pGameFramework->GetIViewSystem()->PostSerialize();
  925.  
  926.         //return failure;
  927.         if (loadEnvironment.m_bLoadingErrors)
  928.         {
  929.                 //TODO [AlexMcC|10.05.10]: return failure here! We can't do this right now
  930.                 //because there's a crash on level unload :( http://jira/browse/CRYII-4903
  931.                 GameWarning("Errors during Game Loading");
  932.         }
  933.         checkpoint.Check("EntityPostSerialize");
  934.  
  935.         if (gEnv->pScriptSystem)
  936.                 gEnv->pScriptSystem->ForceGarbageCollection();
  937.  
  938.         checkpoint.Check("Lua GC Cycle");
  939.  
  940.         Clean();
  941.         checkpoint.Check("PostClean");
  942.  
  943.         // Make sure player entity is not hidden.
  944.         if (IActor* pClientActor = CCryAction::GetCryAction()->GetClientActor())
  945.         {
  946.                 if (IEntity* pClientEntity = pClientActor->GetEntity())
  947.                 {
  948.                         if (pClientEntity->IsHidden())
  949.                         {
  950.                                 GameWarning("Player entity was hidden in save game");
  951.  
  952.                                 pClientEntity->Hide(false);
  953.                         }
  954.                 }
  955.         }
  956.  
  957.         if (gEnv->pFlowSystem != NULL)
  958.         {
  959.                 // this guarantees that the values sent by the scripts in OnPostLoad
  960.                 // through their FG nodes get delivered to all of the connected nodes
  961.                 gEnv->pFlowSystem->Update();
  962.         }
  963.  
  964.         CryGetIMemReplay()->AddLabel("Loadgame_end");
  965.  
  966.         return eLGR_Ok;
  967. }
  968.  
  969. //////////////////////////////////////////////////////////////////////////
  970. bool CGameSerialize::SaveMetaData(SSaveEnvironment& savEnv)
  971. {
  972.         // verify that there's a game active
  973.         const char* levelName = savEnv.m_pCryAction->GetLevelName();
  974.         if (!levelName)
  975.         {
  976.                 GameWarning("No game active - cannot save");
  977.                 return false;
  978.         }
  979.  
  980.         // save serialization version
  981.         savEnv.m_pSaveGame->AddMetadata(SAVEGAME_VERSION_TAG, SAVEGAME_VERSION_VALUE);
  982.         // save current level and game rules
  983.         savEnv.m_pSaveGame->AddMetadata(SAVEGAME_LEVEL_TAG, levelName);
  984.         savEnv.m_pSaveGame->AddMetadata(SAVEGAME_GAMERULES_TAG, savEnv.m_pCryAction->GetIGameRulesSystem()->GetCurrentGameRulesEntity()->GetClass()->GetName());
  985.         // save some useful information for debugging - should not be relied upon in loading
  986.         const SFileVersion& fileVersion = GetISystem()->GetFileVersion();
  987.         char tmpbuf[128];
  988.         fileVersion.ToString(tmpbuf);
  989.         savEnv.m_pSaveGame->AddMetadata(SAVEGAME_BUILD_TAG, tmpbuf);
  990.         int bitSize = sizeof(char*) * 8;
  991.         savEnv.m_pSaveGame->AddMetadata("Bit", bitSize);
  992.  
  993.         //add savEnv.m_checkpoint name if available
  994.         if (savEnv.m_checkPointName)
  995.                 savEnv.m_pSaveGame->AddMetadata(SAVEGAME_CHECKPOINT_TAG, savEnv.m_checkPointName);
  996.         else
  997.                 savEnv.m_pSaveGame->AddMetadata(SAVEGAME_CHECKPOINT_TAG, "");
  998.  
  999.         string timeString;
  1000.         GameUtils::timeToString(time(NULL), timeString);
  1001.         savEnv.m_pSaveGame->AddMetadata(SAVEGAME_TIME_TAG, timeString.c_str());
  1002.  
  1003.         return true;
  1004. }
  1005.  
  1006. //////////////////////////////////////////////////////////////////////////
  1007. void CGameSerialize::SaveEngineSystems(SSaveEnvironment& savEnv)
  1008. {
  1009.         // call CryAction's Framework listeners
  1010.         savEnv.m_pCryAction->NotifyGameFrameworkListeners(savEnv.m_pSaveGame.Get());
  1011.  
  1012.         savEnv.m_checkpoint.Start();
  1013.  
  1014.         // timer data
  1015.         gEnv->pTimer->Serialize(savEnv.m_pSaveGame->AddSection(SAVEGAME_TIMER_SECTION));
  1016.         savEnv.m_checkpoint.Check("Timer");
  1017.  
  1018.         // terrain modifications (e.g. heightmap changes)
  1019.         gEnv->p3DEngine->SerializeState(savEnv.m_pSaveGame->AddSection(SAVEGAME_TERRAINSTATE_SECTION));
  1020.         savEnv.m_checkpoint.Check("3DEngine");
  1021.         {
  1022.                 // game tokens
  1023.                 MEMSTAT_CONTEXT(EMemStatContextTypes::MSC_Other, 0, "Game token serialization");
  1024.                 savEnv.m_pCryAction->GetIGameTokenSystem()->Serialize(savEnv.m_pSaveGame->AddSection(SAVEGAME_GAMETOKEN_SECTION));
  1025.                 savEnv.m_checkpoint.Check("GameToken");
  1026.         }
  1027.         // view system
  1028.         savEnv.m_pCryAction->GetIViewSystem()->Serialize(savEnv.m_pSaveGame->AddSection(SAVEGAME_VIEWSYSTEM_SECTION));
  1029.         savEnv.m_checkpoint.Check("ViewSystem");
  1030.         // ai system data
  1031.         if (gEnv->pAISystem)
  1032.                 gEnv->pAISystem->Serialize(savEnv.m_pSaveGame->AddSection(SAVEGAME_AISTATE_SECTION));
  1033.         savEnv.m_checkpoint.Check("AISystem");
  1034.  
  1035.         //itemsystem - LTL inventory only
  1036.         if (savEnv.m_pCryAction->GetIItemSystem())
  1037.                 savEnv.m_pCryAction->GetIItemSystem()->Serialize(savEnv.m_pSaveGame->AddSection(SAVEGAME_LTLINVENTORY_SECTION));
  1038.         savEnv.m_checkpoint.Check("Inventory");
  1039.  
  1040.         //FlowSystem data
  1041.         if (savEnv.m_pCryAction->GetIFlowSystem())
  1042.                 savEnv.m_pCryAction->GetIFlowSystem()->Serialize(savEnv.m_pSaveGame->AddSection(SAVEGAME_FLOWSYSTEM_SECTION));
  1043.         savEnv.m_checkpoint.Check("FlowSystem");
  1044.  
  1045.         //ColorGradientManager data
  1046.         if (savEnv.m_pCryAction->GetColorGradientManager())
  1047.                 savEnv.m_pCryAction->GetColorGradientManager()->Serialize(savEnv.m_pSaveGame->AddSection(SAVEGAME_COLORGRADIANTMANAGER_SECTION));
  1048.         savEnv.m_checkpoint.Check("ColorGradientManager");
  1049.  
  1050.         CMaterialEffects* pMatFX = static_cast<CMaterialEffects*>(savEnv.m_pCryAction->GetIMaterialEffects());
  1051.         if (pMatFX)
  1052.                 pMatFX->Serialize(savEnv.m_pSaveGame->AddSection(SAVEGAME_MATERIALEFFECTS_SECTION));
  1053.         savEnv.m_checkpoint.Check("MaterialFX");
  1054.  
  1055.         CDialogSystem* pDS = savEnv.m_pCryAction->GetDialogSystem();
  1056.         if (pDS)
  1057.                 pDS->Serialize(savEnv.m_pSaveGame->AddSection(SAVEGAME_DIALOGSYSTEM_SECTION));
  1058.         savEnv.m_checkpoint.Check("DialogSystem");
  1059. }
  1060.  
  1061. //////////////////////////////////////////////////////////////////////////
  1062. bool CGameSerialize::SaveEntities(SSaveEnvironment& savEnv)
  1063. {
  1064.         TSerialize gameState = savEnv.m_pSaveGame->AddSection(SAVEGAME_GAMESTATE_SECTION);
  1065.  
  1066.         ICVar* pUseNoSaveFlag = gEnv->pConsole->GetCVar("es_SaveLoadUseLUANoSaveFlag");
  1067.         bool bUseNoSaveFlag = (pUseNoSaveFlag && pUseNoSaveFlag->GetIVal() != 0);
  1068.  
  1069.         TEntitiesToSerialize entities;
  1070.         entities.reserve(gEnv->pEntitySystem->GetNumEntities());
  1071.  
  1072.         {
  1073.                 MEMSTAT_CONTEXT(EMemStatContextTypes::MSC_Other, 0, "Basic entity data serialization");
  1074.  
  1075.                 gameState.BeginGroup("BasicEntityData");
  1076.                 int nSavedEntityCount = 0;
  1077.  
  1078.                 IEntityItPtr pIt = gEnv->pEntitySystem->GetEntityIterator();
  1079.                 while (IEntity* pEntity = pIt->Next())
  1080.                 {
  1081.                         uint32 flags = pEntity->GetFlags();
  1082.                         if (flags & ENTITY_FLAG_NO_SAVE)
  1083.                         {
  1084.                                 // GameWarning("Skipping Entity %d '%s' '%s' NoSave", pEntity->GetId(), pEntity->GetName(), pEntity->GetClass()->GetName());
  1085.                                 continue;
  1086.                         }
  1087.  
  1088.                         {
  1089.                                 MEMSTAT_CONTEXT(EMemStatContextTypes::MSC_Other, 0, "Basic entity data serialization");
  1090.  
  1091.                                 // basic entity data
  1092.                                 SBasicEntityData bed;
  1093.                                 bed.pEntity = pEntity;
  1094.                                 bed.id = pEntity->GetId();
  1095.  
  1096.                                 // if we're not going to serialize these, don't bother fetching them
  1097.                                 if (!(flags & ENTITY_FLAG_UNREMOVABLE) || !CCryActionCVars::Get().g_saveLoadBasicEntityOptimization)
  1098.                                 {
  1099.                                         bed.name = pEntity->GetName();
  1100.                                         bed.className = pEntity->GetClass()->GetName();
  1101.                                         if (pEntity->GetArchetype())
  1102.                                                 bed.archetype = pEntity->GetArchetype()->GetName();
  1103.                                 }
  1104.  
  1105.                                 bed.ignorePosRotScl = false;
  1106.                                 //lua flag
  1107.                                 if (bUseNoSaveFlag)
  1108.                                 {
  1109.                                         IScriptTable* pEntityScript = pEntity->GetScriptTable();
  1110.                                         SmartScriptTable props;
  1111.                                         if (pEntityScript && pEntityScript->GetValue("Properties", props))
  1112.                                         {
  1113.                                                 bool bSerialize = true;
  1114.                                                 if (props->GetValue("bSerialize", bSerialize) && (bSerialize == false))
  1115.                                                         bed.ignorePosRotScl = true;
  1116.                                         }
  1117.                                 }
  1118.  
  1119.                                 bed.aiObjectId = pEntity->GetAIObjectID();
  1120.  
  1121.                                 IEntity* pParentEntity = pEntity->GetParent();
  1122.                                 IPhysicalEntity* pPhysEnt;
  1123.                                 pe_status_awake sa;
  1124.                                 pe_status_pos sp;
  1125.                                 // for active rigid bodies, query the most recent position from the physics, since due to multithreading
  1126.                                 // CEntity position might be lagging behind
  1127.                                 if (!pParentEntity && (pPhysEnt = pEntity->GetPhysics()) && pPhysEnt->GetType() == PE_RIGID && pPhysEnt->GetStatus(&sa) && pPhysEnt->GetStatus(&sp))
  1128.                                 {
  1129.                                         bed.pos = sp.pos;
  1130.                                         bed.rot = sp.q;
  1131.                                 }
  1132.                                 else
  1133.                                 {
  1134.                                         bed.pos = pEntity->GetPos();
  1135.                                         bed.rot = pEntity->GetRotation();
  1136.                                 }
  1137.                                 bed.scale = pEntity->GetScale();
  1138.                                 bed.flags = flags;
  1139.                                 bed.updatePolicy = (uint32)pEntity->GetUpdatePolicy();
  1140.                                 bed.isHidden = pEntity->IsHidden();
  1141.                                 bed.isActive = pEntity->IsActive();
  1142.                                 bed.isInvisible = pEntity->IsInvisible();
  1143.  
  1144.                                 bed.isPhysicsEnabled = pEntity->IsPhysicsEnabled();
  1145.  
  1146.                                 bed.parentEntity = pParentEntity ? pParentEntity->GetId() : 0;
  1147.                                 bed.iPhysType = pEntity->GetPhysics() ? pEntity->GetPhysics()->GetType() : PE_NONE;
  1148.  
  1149.                                 entities.push_back(pEntity);
  1150.  
  1151.                                 gameState.BeginGroup("BasicEntity");
  1152.                                 bed.Serialize(gameState);
  1153.                                 gameState.EndGroup();
  1154.                                 ++nSavedEntityCount;
  1155.                         }
  1156.                 }
  1157.  
  1158.                 gameState.Value("BasicEntityDataSize", nSavedEntityCount);
  1159.                 gameState.EndGroup();
  1160.  
  1161.                 savEnv.m_checkpoint.Check("EntityPrep");
  1162.         }
  1163.  
  1164.         {
  1165.                 SSerializeScopedBeginGroup entity_group(gameState, "NormalEntityData");
  1166.                 TEntitiesToSerialize::const_iterator itEnd = entities.end();
  1167.                 for (TEntitiesToSerialize::const_iterator it = entities.begin(); it != itEnd; ++it)
  1168.                 {
  1169.                         IEntity* pEntity = *it;
  1170.                         assert(pEntity);
  1171.                         //that's all that is left from entity properties (using early out to reduce save size)
  1172.                         int32 iEntityFlags = pEntity->GetFlags();
  1173.                         if ((iEntityFlags & ENTITY_SERIALIZE_PROPERTIES) && !(iEntityFlags & ENTITY_FLAG_UNREMOVABLE))
  1174.                         {
  1175.                                 SSerializeScopedBeginGroup entity_group2(gameState, "EntityProps");
  1176.                                 pEntity->Serialize(gameState, ENTITY_SERIALIZE_PROPERTIES);
  1177.                         }
  1178.                 }
  1179.         }
  1180.  
  1181.         savEnv.m_checkpoint.Check("EntitySystem2");
  1182.  
  1183.         // Must be serialized after basic entity data.
  1184.         savEnv.m_pCryAction->Serialize(gameState); //breakable objects ..
  1185.  
  1186.         savEnv.m_checkpoint.Check("Breakables");
  1187.  
  1188. #ifndef _RELEASE
  1189.         {
  1190.                 DebugSaveParts debugSaveParts(entities, savEnv.m_pSaveGame);
  1191.                 DebugPrintMemoryUsage(debugSaveParts);
  1192.                 savEnv.m_checkpoint.Check("Debug memory usage");
  1193.         }
  1194. #endif
  1195.  
  1196.         return SaveGameData(savEnv, gameState, entities);
  1197. }
  1198.  
  1199. //////////////////////////////////////////////////////////////////////////
  1200. bool CGameSerialize::SaveGameData(SSaveEnvironment& savEnv, TSerialize& gameState, TEntitiesToSerialize& entities)
  1201. {
  1202.         //EntitySystem
  1203.         gEnv->pEntitySystem->Serialize(gameState);
  1204.  
  1205.         savEnv.m_checkpoint.Check("EntitySystem");
  1206.  
  1207.         // this was previously done 32x for every game object serialize ... once here should be enough
  1208.         gEnv->pNetwork->SyncWithGame(eNGS_FrameEnd);
  1209.  
  1210.         gameState.BeginGroup("ExtraEntityData");
  1211.         uint32 saveCount = 0;
  1212.  
  1213.         for (int pass = 0; pass < 2; pass++) // save (and thus load) ropes after other entities (during pass 1) to make sure attachments are ready during loading
  1214.                 // fall back on the previous save code if no list is present
  1215.                 if (m_serializeEntities.empty() || CCryActionCVars::Get().g_saveLoadUseExportedEntityList == 0)
  1216.                 {
  1217.                         for (TEntitiesToSerialize::const_iterator iter = entities.begin(), end = entities.end(); iter != end; ++iter)
  1218.                         {
  1219.                                 IEntity* pEntity = *iter;
  1220.                                 CRY_ASSERT(pEntity);
  1221.  
  1222.                                 bool bSerializeEntity = gEnv->pEntitySystem->ShouldSerializedEntity(pEntity);
  1223.                                 //step over entities in hidden layers
  1224.                                 if (!bSerializeEntity)
  1225.                                 {
  1226.                                         //CryLogAlways("Saved Entity On Deactivated Layer : %i, %s", iter->id, iter->name);
  1227.                                         //gameState.EndGroup();
  1228.                                         continue;
  1229.                                 }
  1230.                                 if ((pEntity->GetPhysics() && pEntity->GetPhysics()->GetType() == PE_ROPE) == !pass)
  1231.                                         continue;
  1232.  
  1233.                                 // c++ entity data
  1234.                                 gameState.BeginGroup("Entity");
  1235.  
  1236.                                 EntityId temp = pEntity->GetId();
  1237.                                 gameState.Value("id", temp);
  1238.                                 ++saveCount;
  1239.  
  1240.                                 if (pEntity->GetFlags() & ENTITY_FLAG_MODIFIED_BY_PHYSICS)
  1241.                                 {
  1242.                                         gameState.BeginGroup("EntityGeometry");
  1243.                                         pEntity->Serialize(gameState, ENTITY_SERIALIZE_GEOMETRIES);
  1244.                                         gameState.EndGroup();
  1245.                                 }
  1246.                                 pEntity->Serialize(gameState, ENTITY_SERIALIZE_PROXIES);
  1247.  
  1248.                                 gameState.EndGroup();//Entity
  1249.                         }
  1250.                 }
  1251.                 else
  1252.                 {
  1253.                         for (TEntityVector::iterator iter = m_serializeEntities.begin(), end = m_serializeEntities.end(); iter != end; ++iter)
  1254.                         {
  1255.                                 EntityId id = *iter;
  1256.                                 IEntity* pEntity = gEnv->pEntitySystem->GetEntity(id);
  1257.  
  1258.                                 if (pEntity)
  1259.                                 {
  1260.                                         if ((pEntity->GetPhysics() && pEntity->GetPhysics()->GetType() == PE_ROPE) == !pass)
  1261.                                                 continue;
  1262.                                         CRY_ASSERT_TRACE(!(pEntity->GetFlags() & ENTITY_FLAG_LOCAL_PLAYER), ("%s has ENTITY_FLAG_LOCAL_PLAYER - local player should not be in m_serializeEntities!", pEntity->GetEntityTextDescription().c_str()));
  1263.  
  1264.                                         // c++ entity data
  1265.                                         gameState.BeginGroup("Entity");
  1266.  
  1267.                                         EntityId temp = id;
  1268.                                         gameState.Value("id", temp);
  1269.                                         ++saveCount;
  1270.  
  1271.                                         if (pEntity->GetFlags() & ENTITY_FLAG_MODIFIED_BY_PHYSICS)
  1272.                                         {
  1273.                                                 gameState.BeginGroup("EntityGeometry");
  1274.                                                 pEntity->Serialize(gameState, ENTITY_SERIALIZE_GEOMETRIES);
  1275.                                                 gameState.EndGroup();
  1276.                                         }
  1277.                                         pEntity->Serialize(gameState, ENTITY_SERIALIZE_PROXIES);
  1278.  
  1279.                                         gameState.EndGroup();//Entity
  1280.                                 }
  1281.                         }
  1282.  
  1283.                         // also save all dynamic entities
  1284.                         assert(stl::find(m_dynamicEntities, CCryAction::GetCryAction()->GetClientActorId()));
  1285.                         for (TEntitySet::iterator iter = m_dynamicEntities.begin(), end = m_dynamicEntities.end(); iter != end; ++iter)
  1286.                         {
  1287.                                 IEntity* pEntity = gEnv->pEntitySystem->GetEntity(*iter);
  1288.                                 CRY_ASSERT(pEntity);
  1289.                                 if ((pEntity->GetPhysics() && pEntity->GetPhysics()->GetType() == PE_ROPE) == !pass)
  1290.                                         continue;
  1291.  
  1292.                                 // c++ entity data
  1293.                                 gameState.BeginGroup("Entity");
  1294.  
  1295.                                 EntityId temp = *iter;
  1296.                                 gameState.Value("id", temp);
  1297.                                 ++saveCount;
  1298.  
  1299.                                 if (pEntity)
  1300.                                 {
  1301.                                         if (pEntity->GetFlags() & ENTITY_FLAG_MODIFIED_BY_PHYSICS)
  1302.                                         {
  1303.                                                 gameState.BeginGroup("EntityGeometry");
  1304.                                                 pEntity->Serialize(gameState, ENTITY_SERIALIZE_GEOMETRIES);
  1305.                                                 gameState.EndGroup();
  1306.                                         }
  1307.                                         pEntity->Serialize(gameState, ENTITY_SERIALIZE_PROXIES);
  1308.                                 }
  1309.  
  1310.                                 gameState.EndGroup();//Entity
  1311.                         }
  1312.                 }
  1313.  
  1314.         gameState.Value("savedEntityCount", saveCount);
  1315.  
  1316.         gameState.EndGroup();//ExtraEntityData
  1317.  
  1318.         savEnv.m_checkpoint.Check("ExtraEntity");
  1319.  
  1320.         if (auto* pGame = CCryAction::GetCryAction()->GetIGame())
  1321.                 pGame->FullSerialize(gameState);
  1322.  
  1323.         // 3DEngine
  1324.         gEnv->p3DEngine->PostSerialize(false);
  1325.  
  1326.         savEnv.m_checkpoint.Check("3DEnginePost");
  1327.  
  1328.         return true;
  1329. }
  1330.  
  1331. //////////////////////////////////////////////////////////////////////////
  1332. void CGameSerialize::LoadEngineSystems(SLoadEnvironment& loadEnv)
  1333. {
  1334.         // Reset the flowsystem here (sending eFE_Initialize) to all FGs
  1335.         // also makes sure, that nodes present in the level.pak but not in the
  1336.         // savegame loaded afterwards get initialized correctly
  1337.         gEnv->pFlowSystem->Reset(false);
  1338.  
  1339.         loadEnv.m_checkpoint.Check("DestroyedState");
  1340.  
  1341.         loadEnv.m_failure = eLGR_FailedAndDestroyedState;
  1342.  
  1343.         // timer serialization (after potential context switch, e.g. when loading a savegame for which Level has not been loaded yet)
  1344.         loadEnv.m_pSer = loadEnv.m_pLoadGame->GetSection(SAVEGAME_TIMER_SECTION);
  1345.         if (!loadEnv.m_pSer.get())
  1346.                 GameWarning("Unable to open timer %s", SAVEGAME_TIMER_SECTION);
  1347.         else
  1348.                 gEnv->pTimer->Serialize(*loadEnv.m_pSer);
  1349.  
  1350.         // Now Pause the Game timer if not already done!
  1351.         // so no time passes until serialization is over
  1352.         SPauseGameTimer pauseGameTimer;
  1353.  
  1354.         // terrain modifications (e.g. heightmap changes)
  1355.         loadEnv.m_pSer = loadEnv.m_pLoadGame->GetSection(SAVEGAME_TERRAINSTATE_SECTION);
  1356.         if (!loadEnv.m_pSer.get())
  1357.                 GameWarning("Unable to open section %s", SAVEGAME_TERRAINSTATE_SECTION);
  1358.         else
  1359.                 gEnv->p3DEngine->SerializeState(*loadEnv.m_pSer);
  1360.  
  1361.         loadEnv.m_checkpoint.Check("3DEngine");
  1362.  
  1363.         // game tokens
  1364.         loadEnv.m_pSer = loadEnv.m_pLoadGame->GetSection(SAVEGAME_GAMETOKEN_SECTION);
  1365.         if (!loadEnv.m_pSer.get())
  1366.                 GameWarning("No game token data in save game");
  1367.         else
  1368.         {
  1369.                 IGameTokenSystem* pGTS = CCryAction::GetCryAction()->GetIGameTokenSystem();
  1370.                 if (pGTS)
  1371.                 {
  1372.                         if (gEnv->IsEditor())
  1373.                         {
  1374.                                 char* sLevelName;
  1375.                                 char* levelFolder;
  1376.                                 loadEnv.m_pCryAction->GetEditorLevel(&sLevelName, &levelFolder);
  1377.                                 string tokenPath = levelFolder;
  1378.                                 tokenPath += "/GameTokens/*.xml";
  1379.                                 pGTS->Reset();
  1380.                                 pGTS->LoadLibs(tokenPath);
  1381.                                 pGTS->Serialize(*loadEnv.m_pSer);
  1382.                         }
  1383.                         else
  1384.                         {
  1385.                                 // no need to reload token libraries
  1386.                                 pGTS->Serialize(*loadEnv.m_pSer);
  1387.                         }
  1388.                 }
  1389.         }
  1390.  
  1391.         loadEnv.m_checkpoint.Check("GameTokens");
  1392.  
  1393.         CMaterialEffects* pMatFX = static_cast<CMaterialEffects*>(loadEnv.m_pCryAction->GetIMaterialEffects());
  1394.         if (pMatFX)
  1395.                 pMatFX->Reset(false);
  1396.  
  1397.         loadEnv.m_pSer = loadEnv.m_pLoadGame->GetSection(SAVEGAME_MATERIALEFFECTS_SECTION);
  1398.         if (!loadEnv.m_pSer.get())
  1399.                 GameWarning("Unable to open section %s", SAVEGAME_MATERIALEFFECTS_SECTION);
  1400.         else
  1401.         {
  1402.                 if (pMatFX)
  1403.                 {
  1404.                         pMatFX->Serialize(*loadEnv.m_pSer);
  1405.                 }
  1406.         }
  1407.         loadEnv.m_checkpoint.Check("MaterialFX");
  1408.  
  1409.         // ViewSystem Serialization
  1410.         IViewSystem* pViewSystem = loadEnv.m_pCryAction->GetIViewSystem();
  1411.  
  1412.         loadEnv.m_pSer = loadEnv.m_pLoadGame->GetSection(SAVEGAME_VIEWSYSTEM_SECTION);
  1413.         if (!loadEnv.m_pSer.get())
  1414.                 GameWarning("Unable to open section %s", SAVEGAME_VIEWSYSTEM_SECTION);
  1415.         else
  1416.         {
  1417.                 if (pViewSystem)
  1418.                 {
  1419.                         pViewSystem->Serialize(*loadEnv.m_pSer);
  1420.                 }
  1421.         }
  1422.  
  1423.         loadEnv.m_checkpoint.Check("ViewSystem");
  1424.  
  1425.         if (loadEnv.m_pCryAction->GetIItemSystem())
  1426.         {
  1427.                 loadEnv.m_pSer = loadEnv.m_pLoadGame->GetSection(SAVEGAME_LTLINVENTORY_SECTION);
  1428.                 if (loadEnv.m_pSer.get())
  1429.                         loadEnv.m_pCryAction->GetIItemSystem()->Serialize(*loadEnv.m_pSer);
  1430.                 else
  1431.                         GameWarning("Unable to open section %s", SAVEGAME_LTLINVENTORY_SECTION);
  1432.         }
  1433.         loadEnv.m_checkpoint.Check("ItemSystem");
  1434.  
  1435.         // load flowsystem data
  1436.         if (loadEnv.m_pCryAction->GetIFlowSystem())
  1437.         {
  1438.                 loadEnv.m_pSer = loadEnv.m_pLoadGame->GetSection(SAVEGAME_FLOWSYSTEM_SECTION);
  1439.                 if (loadEnv.m_pSer.get())
  1440.                         loadEnv.m_pCryAction->GetIFlowSystem()->Serialize(*loadEnv.m_pSer);
  1441.                 else
  1442.                         GameWarning("Unable to open section %s", SAVEGAME_FLOWSYSTEM_SECTION);
  1443.         }
  1444.         loadEnv.m_checkpoint.Check("FlowSystem");
  1445.  
  1446.         // Load ColorGradientManager data
  1447.         if (loadEnv.m_pCryAction->GetColorGradientManager())
  1448.         {
  1449.                 loadEnv.m_pSer = loadEnv.m_pLoadGame->GetSection(SAVEGAME_COLORGRADIANTMANAGER_SECTION);
  1450.                 if (loadEnv.m_pSer)
  1451.                         loadEnv.m_pCryAction->GetColorGradientManager()->Serialize(*loadEnv.m_pSer);
  1452.                 else
  1453.                         GameWarning("Unable to open section %s", SAVEGAME_COLORGRADIANTMANAGER_SECTION);
  1454.         }
  1455.         loadEnv.m_checkpoint.Check("ColorGradientManager");
  1456.  
  1457.         // Dialog System Reset & Serialization
  1458.         CDialogSystem* pDS = loadEnv.m_pCryAction->GetDialogSystem();
  1459.         if (pDS)
  1460.                 pDS->Reset(false);
  1461.  
  1462.         // Dialog System First Pass [recreates DialogSessions]
  1463.         loadEnv.m_pSer = loadEnv.m_pLoadGame->GetSection(SAVEGAME_DIALOGSYSTEM_SECTION);
  1464.         if (!loadEnv.m_pSer.get())
  1465.                 GameWarning("Unable to open section %s", SAVEGAME_DIALOGSYSTEM_SECTION);
  1466.         else
  1467.         {
  1468.                 if (pDS)
  1469.                 {
  1470.                         pDS->Serialize(*loadEnv.m_pSer);
  1471.                 }
  1472.         }
  1473.         loadEnv.m_checkpoint.Check("DialogSystem");
  1474. }
  1475.  
  1476. //////////////////////////////////////////////////////////////////////////
  1477. bool CGameSerialize::LoadLevel(SLoadEnvironment& loadEnv, SGameStartParams& startParams, STempAutoResourcesLock& autoResourcesLock, bool bIsQuickLoading, bool requireQuickLoad)
  1478. {
  1479.         const char* sCurrentLevel = loadEnv.m_pCryAction->GetLevelName();
  1480.  
  1481.         IEntitySystem* pEntitySystem = gEnv->pEntitySystem;
  1482.         SGameContextParams ctx;
  1483.  
  1484.         if (!loadEnv.m_pLoadGame->HaveMetadata(SAVEGAME_LEVEL_TAG) || !loadEnv.m_pLoadGame->HaveMetadata(SAVEGAME_GAMERULES_TAG))
  1485.         {
  1486.                 return false;
  1487.         }
  1488.  
  1489.         ctx.levelName = loadEnv.m_pLoadGame->GetMetadata(SAVEGAME_LEVEL_TAG);
  1490.         ctx.gameRules = loadEnv.m_pLoadGame->GetMetadata(SAVEGAME_GAMERULES_TAG);
  1491.  
  1492.         if (bIsQuickLoading)
  1493.         {
  1494.                 // can quick-load
  1495.                 if (!gEnv->p3DEngine->RestoreTerrainFromDisk())
  1496.                         return false;
  1497.  
  1498.                 if (gEnv->p3DEngine)
  1499.                 {
  1500.                         gEnv->p3DEngine->ResetPostEffects();
  1501.                 }
  1502.  
  1503.                 // [AlexMcC|18.03.10] Taken from CEntitySytem::Reset:
  1504.                 // This fixes physics crashes caused by old update events
  1505.                 // Flush the physics linetest and events queue, but don't pump events (on Anton's recommendation)
  1506.                 gEnv->pPhysicalWorld->TracePendingRays(0);
  1507.                 gEnv->pPhysicalWorld->ClearLoggedEvents();
  1508.  
  1509.                 pEntitySystem->DeletePendingEntities();
  1510.                 loadEnv.m_failure = eLGR_FailedAndDestroyedState;
  1511.  
  1512.                 gEnv->pNetwork->SyncWithGame(eNGS_Shutdown);
  1513.                 gEnv->pNetwork->SyncWithGame(eNGS_Shutdown_Clear);
  1514.  
  1515.                 // no level loading, so imm start the precaching phase
  1516.                 gEnv->pSystem->GetISystemEventDispatcher()->OnSystemEvent(ESYSTEM_EVENT_LEVEL_PRECACHE_START, 0, 0);
  1517.  
  1518.                 return true;
  1519.         }
  1520.         else if (requireQuickLoad)
  1521.         {
  1522.                 GameWarning("Unable to quick load: different level names (%s != %s)", sCurrentLevel, ctx.levelName);
  1523.                 return false;
  1524.         }
  1525.         else if (gEnv->IsEditor())
  1526.         {
  1527.                 GameWarning("Can only quick-load in editor");
  1528.                 return false;
  1529.         }
  1530.  
  1531.         //NON-QUICKLOAD PATH
  1532.         startParams.pContextParams = &ctx;
  1533.         startParams.flags |= eGSF_BlockingClientConnect | eGSF_LocalOnly;
  1534.  
  1535.         loadEnv.m_failure = eLGR_FailedAndDestroyedState;
  1536.  
  1537.         // Note: About to load the level this save file is from, so unlock resources during the level load duration
  1538.         autoResourcesLock.Unlock();
  1539.         if (!loadEnv.m_pCryAction->StartGameContext(&startParams))    // this is the call that actually loads the level data
  1540.         {
  1541.                 GameWarning("Could not start game context.");
  1542.                 return false;
  1543.         }
  1544.         autoResourcesLock.Lock();
  1545.         loadEnv.m_pCryAction->GetGameContext()->SetLoadingSaveGame();
  1546.  
  1547.         // Delete any new dynamic entities (eg. items, accessories) that were created from starting the game context
  1548.         DeleteDynamicEntities(loadEnv.m_basicEntityData);
  1549.  
  1550.         // Remove all AI objects created during the level load too (to avoid collisions with ones in the save file).
  1551.         //      For quickloads this flush/reload happens earlier.
  1552.         assert(!bIsQuickLoading);
  1553.         if (gEnv->pAISystem)
  1554.                 gEnv->pAISystem->FlushSystem();
  1555.  
  1556.         // Flushing the system clears the navagation data, so reload it.
  1557.         const ILevelInfo* pLevelInfo = GetLevelInfo();
  1558.         CRY_ASSERT_MESSAGE(CCryAction::GetCryAction()->StartedGameContext() == false || (pLevelInfo != 0), "Can't find level info: This might break AI");
  1559.         if (pLevelInfo)
  1560.         {
  1561.                 const ILevelInfo::TGameTypeInfo* pGameTypeInfo = pLevelInfo->GetDefaultGameType();
  1562.                 const char* const szGameTypeName = pGameTypeInfo ? pGameTypeInfo->name.c_str() : "";
  1563.                 if (gEnv->pAISystem)
  1564.                 {
  1565.                         const EAILoadDataFlags loadDataFlags = eAILoadDataFlag_AllSystems | (bIsQuickLoading ? eAILoadDataFlag_QuickLoad : eAILoadDataFlag_None);
  1566.                         gEnv->pAISystem->LoadLevelData(pLevelInfo->GetPath(), szGameTypeName, loadDataFlags);
  1567.                 }
  1568.         }
  1569.  
  1570.         loadEnv.m_bHaveReserved = true;
  1571.         ReserveEntityIds(loadEnv.m_basicEntityData);
  1572.  
  1573.         SEntityEvent serializeEvent(ENTITY_EVENT_PRE_SERIALIZE);
  1574.         gEnv->pEntitySystem->SendEventToAll(serializeEvent);
  1575.  
  1576.         return true;
  1577. }
  1578.  
  1579. //////////////////////////////////////////////////////////////////////////
  1580. bool CGameSerialize::LoadEntities(SLoadEnvironment& loadEnv, std::unique_ptr<TSerialize> pGameStateSer)
  1581. {
  1582.         IEntitySystem* pEntitySystem = gEnv->pEntitySystem;
  1583.         // entity creation/deletion/repositioning
  1584.         loadEnv.m_checkpoint.Check("DeleteDynamicEntities");
  1585.  
  1586. #ifdef EXCESSIVE_ENTITY_DEBUG
  1587.         // dump entities which can potentially be re-used (if class matches)
  1588.         CryLogAlways("*QL -----------------------------------------");
  1589.         CryLogAlways("*QL Dumping Entities after deletion of unused");
  1590.         DumpEntities();
  1591.         CryLogAlways("*QL Done Dumping Entities after deletion of unused");
  1592.         CryLogAlways("*QL -----------------------------------------");
  1593. #endif
  1594.  
  1595.         // we reserve the Entities AFTER we deleted any left-overs
  1596.         // = entities which are in mem, but not in savegame.
  1597.         // this could cause collisions with SaltHandles because a left-over and a new one can point to the same
  1598.         // handle (with different salts). if we reserve before deletion, we would actually delete our reserved handle
  1599.  
  1600.         {
  1601.                 FlushActivatableGameObjectExtensions();
  1602.                 loadEnv.m_checkpoint.Check("FlushExtensions");
  1603.  
  1604.                 loadEnv.m_pCryAction->FlushBreakableObjects();
  1605.                 loadEnv.m_checkpoint.Check("FlushBreakables");
  1606.  
  1607.                 // Clean all entities that should not be in system before loading entties from savegame.
  1608.                 // delete any left-over entities
  1609.                 DeleteDynamicEntities(loadEnv.m_basicEntityData); //must happen before reserving entities
  1610.                 loadEnv.m_checkpoint.Check("DeletePending");
  1611.  
  1612.                 ReserveEntityIds(loadEnv.m_basicEntityData);
  1613.                 loadEnv.m_bHaveReserved = true;
  1614.         }
  1615.  
  1616.         // serialize breakable objects AFTER reservation
  1617.         // this will quite likely spawn new entities
  1618.         CRY_ASSERT(pGameStateSer.get());
  1619.         loadEnv.m_pSer = std::move(pGameStateSer);
  1620.         if (!loadEnv.m_pSer.get())
  1621.                 return false;
  1622.  
  1623.         loadEnv.m_pCryAction->Serialize(*loadEnv.m_pSer); //breakable object
  1624.         loadEnv.m_checkpoint.Check("SerializeBreakables");
  1625.  
  1626.         //reset item system, used to be after entity serialization
  1627.         gEnv->pGameFramework->GetIItemSystem()->Reset();
  1628.  
  1629.         //lock entity system
  1630.         pEntitySystem->LockSpawning(true);
  1631.  
  1632.         //fix breakables forced ids
  1633.         pEntitySystem->SetNextSpawnId(0);
  1634.  
  1635.         // basic entity data
  1636.         LoadBasicEntityData(loadEnv);
  1637.  
  1638.         if (!VerifyEntities(loadEnv.m_basicEntityData))
  1639.                 return false;
  1640.  
  1641.         loadEnv.m_checkpoint.Check("AllEntities");
  1642.  
  1643.         // reposition any entities (once again for sanities sake)
  1644.         if (!RepositionEntities(loadEnv.m_basicEntityData, true))
  1645.         {
  1646.                 //return loadEnv.m_failure;
  1647.                 loadEnv.m_bLoadingErrors = true;
  1648.         }
  1649.  
  1650.         loadEnv.m_checkpoint.Check("Reposition");
  1651.  
  1652.         //~ entity creation/deletion/repositioning
  1653.  
  1654.         FlushActivatableGameObjectExtensions();
  1655.         loadEnv.m_checkpoint.Check("FlushExtensions2");
  1656.  
  1657.         return true;
  1658. }
  1659.  
  1660. //////////////////////////////////////////////////////////////////////////
  1661. void CGameSerialize::LoadBasicEntityData(SLoadEnvironment& loadEnv)
  1662. {
  1663.         IEntitySystem* pEntitySystem = gEnv->pEntitySystem;
  1664.         loadEnv.m_pSer->BeginGroup("NormalEntityData");
  1665.  
  1666.         // create any entities that are not in the level, but are in the save game
  1667.         // or that have the wrong class
  1668.         TBasicEntityDatas::const_iterator itEnd = loadEnv.m_basicEntityData.end();
  1669.         for (TBasicEntityDatas::const_iterator it = loadEnv.m_basicEntityData.begin(); it != itEnd; ++it)
  1670.         {
  1671.                 const SBasicEntityData& bed = *it;
  1672.  
  1673.                 IEntity* pEntity = pEntitySystem->GetEntity(bed.id);
  1674.                 if (!pEntity)
  1675.                 {
  1676.                         IEntityClass* pClass = pEntitySystem->GetClassRegistry()->FindClass(bed.className.c_str());
  1677.                         if (!pClass)
  1678.                         {
  1679.                                 GameWarning("[LoadGame] Failed Spawning Entity ID=%d, Class '%s' not found", bed.id, bed.className.c_str());
  1680.                                 loadEnv.m_bLoadingErrors = true;
  1681.                                 continue;
  1682.                                 //return loadEnv.m_failure;
  1683.                         }
  1684.  
  1685.                         SEntitySpawnParams params;
  1686.                         params.id = bed.id;
  1687.                         assert(!bed.ignorePosRotScl);
  1688.                         //this will also be set in RepositionEntities
  1689.                         params.vPosition = bed.pos;
  1690.                         params.qRotation = bed.rot;
  1691.                         params.vScale = bed.scale;
  1692.                         params.sName = bed.name.c_str();
  1693.                         params.nFlags = bed.flags;
  1694.                         params.pClass = pClass;
  1695.                         params.bIgnoreLock = true;
  1696.                         if (!bed.archetype.empty())
  1697.                         {
  1698.                                 params.pArchetype = pEntitySystem->LoadEntityArchetype(bed.archetype);
  1699.                         }
  1700.                         pEntity = pEntitySystem->SpawnEntity(params, false);
  1701.                         if (!pEntity)
  1702.                         {
  1703.                                 GameWarning("[LoadGame] Failed Spawning Entity ID=%d, %s (%s)", params.id, bed.name.c_str(), bed.className.c_str());
  1704.                                 //return loadEnv.m_failure;
  1705.                                 loadEnv.m_bLoadingErrors = true;
  1706.                                 continue;
  1707.                         }
  1708.                         else if (pEntity->GetId() != bed.id)
  1709.                         {
  1710.                                 GameWarning("[LoadGame] Spawned Entity ID=%d, %s (%s), with wrong ID=%d", bed.id, bed.name.c_str(), bed.className.c_str(), pEntity->GetId());
  1711.                                 //return loadEnv.m_failure;
  1712.                                 loadEnv.m_bLoadingErrors = true;
  1713.                                 continue;
  1714.                         }
  1715.  
  1716.                         // Serialize script properties, this must happen before entity Init
  1717.                         if ((bed.flags & ENTITY_SERIALIZE_PROPERTIES) && !(bed.flags & ENTITY_FLAG_UNREMOVABLE))
  1718.                         {
  1719.                                 SSerializeScopedBeginGroup entity_group(*loadEnv.m_pSer, "EntityProps");
  1720.                                 pEntity->Serialize(*loadEnv.m_pSer, ENTITY_SERIALIZE_PROPERTIES);
  1721.                         }
  1722.  
  1723.                         // Initialize entity after properties have been loaded.
  1724.                         if (!pEntitySystem->InitEntity(pEntity, params))
  1725.                         {
  1726.                                 GameWarning("[LoadGame] Failed Initializing Entity ID=%d, %s (%s)", params.id, bed.name.c_str(), bed.className.c_str());
  1727.                                 loadEnv.m_bLoadingErrors = true;
  1728.                                 continue;
  1729.                         }
  1730.                 }
  1731.                 if (!pEntitySystem->GetEntity(bed.id))
  1732.                 {
  1733.                         GameWarning("[LoadGame] Failed Loading Entity ID=%d, %s (%s)", bed.id, bed.name.c_str(), bed.className.c_str());
  1734.                         //return loadEnv.m_failure;
  1735.                         loadEnv.m_bLoadingErrors = true;
  1736.                         continue;
  1737.                 }
  1738.         }
  1739.         loadEnv.m_pSer->EndGroup(); // loadEnv.m_pSer->BeginGroup( "NormalEntityData" );
  1740. }
  1741.  
  1742. //////////////////////////////////////////////////////////////////////////
  1743. void CGameSerialize::LoadGameData(SLoadEnvironment& loadEnv)
  1744. {
  1745.         IEntitySystem* pEntitySystem = gEnv->pEntitySystem;
  1746.  
  1747.         //serialize timers etc. in entity system, also layers have to be serialized before other entities
  1748.         pEntitySystem->Serialize(*loadEnv.m_pSer);
  1749.         loadEnv.m_checkpoint.Check("EntitySystem");
  1750.  
  1751.         // entity state restoration
  1752.         loadEnv.m_pSer->BeginGroup("ExtraEntityData");
  1753.  
  1754.         uint32 saveCount = 0;
  1755.         loadEnv.m_pSer->Value("savedEntityCount", saveCount);
  1756.  
  1757.         // set the basic entity data
  1758.         for (TBasicEntityDatas::const_iterator iter = loadEnv.m_basicEntityData.begin(); iter != loadEnv.m_basicEntityData.end(); ++iter)
  1759.         {
  1760.                 IEntity* pEntity = pEntitySystem->GetEntity(iter->id);
  1761.                 if (!pEntity)
  1762.                 {
  1763.                         GameWarning("[LoadGame] Missing Entity ID %d", iter->id);
  1764.                         //return loadEnv.m_failure;
  1765.                         loadEnv.m_bLoadingErrors = true;
  1766.                         continue;
  1767.                 }
  1768.  
  1769.                 pEntity->SetFlags(iter->flags);
  1770.  
  1771.                 // unhide and activate so that physicalization works (will be corrected after extra entity data is loaded)
  1772.                 pEntity->SetUpdatePolicy((EEntityUpdatePolicy) iter->updatePolicy);
  1773.  
  1774.                 {
  1775.                         pEntity->EnablePhysics(true);
  1776.                 }
  1777.  
  1778.                 pEntity->Hide(false);
  1779.                 pEntity->Invisible(false);
  1780.                 pEntity->Activate(true);
  1781.  
  1782.                 // Warning: since the AI system serialize hasn't happened yet, the AI object won't exist yet (previous ones were
  1783.                 //  removed by the AI flush). Essentially, between this point and the AI serialize
  1784.                 //      it is not safe to call GetAI() on the entity.
  1785.                 // Fixing this properly would probably mean making the entity serialize it's own AI object as it does with other proxies.
  1786.                 pEntity->SetAIObjectID(iter->aiObjectId);
  1787.  
  1788.                 // extra sanity check for matching class
  1789.                 if (!(pEntity->GetFlags() & ENTITY_FLAG_UNREMOVABLE) && iter->className != pEntity->GetClass()->GetName())
  1790.                 {
  1791.                         GameWarning("[LoadGame] Entity class mismatch ID=%d %s, should have class '%s'", pEntity->GetId(), pEntity->GetEntityTextDescription().c_str(), iter->className.c_str());
  1792.                         loadEnv.m_bLoadingErrors = true;
  1793.                         continue;
  1794.                 }
  1795.  
  1796.                 if (pEntity->CheckFlags(ENTITY_FLAG_SPAWNED | ENTITY_FLAG_MODIFIED_BY_PHYSICS) && iter->iPhysType != PE_NONE)
  1797.                 {
  1798.                         SEntityPhysicalizeParams epp;
  1799.                         epp.type = iter->iPhysType;
  1800.                         pEntity->Physicalize(epp);
  1801.                 }
  1802.                 if ((iter->flags & (ENTITY_FLAG_MODIFIED_BY_PHYSICS | ENTITY_FLAG_SPAWNED)) == ENTITY_FLAG_MODIFIED_BY_PHYSICS)
  1803.                         pEntity->AddFlags(iter->flags & ENTITY_FLAG_MODIFIED_BY_PHYSICS);
  1804.         }
  1805.         // now the extra entity data:
  1806.         for (uint32 index = 0; index < saveCount; ++index)
  1807.         {
  1808.                 // c++ state
  1809.                 loadEnv.m_pSer->BeginGroup("Entity");
  1810.  
  1811.                 EntityId id = 0;
  1812.                 loadEnv.m_pSer->Value("id", id);
  1813.  
  1814.                 IEntity* pEntity = gEnv->pEntitySystem->GetEntity(id);
  1815.                 if (!pEntity)
  1816.                 {
  1817.                         loadEnv.m_pSer->EndGroup();
  1818.                         GameWarning("[LoadGame] Expected Entity ID=%d: Entity not found.", id);
  1819.                         loadEnv.m_bLoadingErrors = true;
  1820.                         continue;
  1821.                 }
  1822.  
  1823.                 int nEntityFlags = pEntity->GetFlags();
  1824.  
  1825.                 if ((nEntityFlags & ENTITY_FLAG_MODIFIED_BY_PHYSICS) != 0)
  1826.                 {
  1827.                         loadEnv.m_pSer->BeginGroup("EntityGeometry");
  1828.                         pEntity->Serialize(*loadEnv.m_pSer, ENTITY_SERIALIZE_GEOMETRIES);
  1829.                         loadEnv.m_pSer->EndGroup();
  1830.                 }
  1831.  
  1832.                 pEntity->Serialize(*loadEnv.m_pSer, ENTITY_SERIALIZE_PROXIES);
  1833.  
  1834.                 loadEnv.m_pSer->EndGroup();
  1835.         }
  1836.  
  1837.         loadEnv.m_pSer->EndGroup();
  1838.  
  1839.         // set the hidden/active state again for all entities
  1840.         for (int pass = 0; pass < 2; pass++) // hide ropes before other entities to prevent detachment
  1841.                 for (TBasicEntityDatas::const_iterator iter = loadEnv.m_basicEntityData.begin(); iter != loadEnv.m_basicEntityData.end(); ++iter)
  1842.                 {
  1843.                         IEntity* pEntity = pEntitySystem->GetEntity(iter->id);
  1844.                         if (pEntity)
  1845.                         {
  1846.                                 if ((pEntity->GetPhysics() && pEntity->GetPhysics()->GetType() == PE_ROPE) != !pass)
  1847.                                         continue;
  1848.                                 // moved to after serialize so physicalization works as expected
  1849.                                 pEntity->Hide(iter->isHidden);
  1850.                                 pEntity->Invisible(iter->isInvisible);
  1851.                                 pEntity->Activate(iter->isActive);
  1852.  
  1853.                                 {
  1854.                                         pEntity->EnablePhysics(iter->isPhysicsEnabled);
  1855.                                 }
  1856.                         }
  1857.                 }
  1858.  
  1859.         loadEnv.m_checkpoint.Check("ExtraEntityData");
  1860.  
  1861.         if (auto* pGame = CCryAction::GetCryAction()->GetIGame())
  1862.                 pGame->FullSerialize(*loadEnv.m_pSer);
  1863. }
  1864.  
downloadGameSerialize.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