BVB Source Codes

CRYENGINE Show CheckPointSystem.cpp Source code

Return Download CRYENGINE: download CheckPointSystem.cpp Source code - Download CRYENGINE Source code - Type:.cpp
  1. // Copyright 2001-2016 Crytek GmbH / Crytek Group. All rights reserved.
  2.  
  3. /*************************************************************************
  4.    -------------------------------------------------------------------------
  5.    $Id$
  6.    $DateTime$
  7.    Description: Checkpoint Save/Load system for Game04
  8.  
  9.    -------------------------------------------------------------------------
  10.    History:
  11.    - 10:07:2008 : Created By Jan M眉ller
  12.    - 05:02:2009 : Refactored and moved By Kevin Kirst
  13.  
  14. *************************************************************************/
  15.  
  16. #include "StdAfx.h"
  17. #include "CheckPointSystem.h"
  18.  
  19. //engine interfaces
  20. #include <Cry3DEngine/I3DEngine.h>
  21. #include <CryFlowGraph/IFlowSystem.h>
  22. #include <CryAISystem/IAISystem.h>
  23. #include <CryGame/IGameTokens.h>
  24. #include <CryGame/IGameFramework.h>
  25. #include <CryEntitySystem/IEntitySystem.h>
  26. #include "IActorSystem.h"
  27. #include "IPlayerProfiles.h"
  28. #include "IVehicleSystem.h"
  29. #include <CryMovie/IMovieSystem.h>
  30. #include <CryString/CryPath.h>
  31.  
  32. //statics
  33. FixedCheckpointString CCheckpointSystem::g_lastSavedCheckpoint;
  34. std::list<ICheckpointListener*> CCheckpointSystem::g_vCheckpointSystemListeners;
  35.  
  36. const static int CHECKPOINT_VERSION_NUMBER = 0;
  37. const static char* FILENAME_EXTENSION = ".jmc";
  38. const static char* CONSOLE_SAVEGAME_DIRECTORY = "%USER%/SaveGames";
  39.  
  40. //section flags
  41. const static int CHECKPOINT_DATA_SIZE = 1024000;
  42. const static char* ACTOR_FLAGS_SECTION = "ActorFlags";
  43. const static char* ACTIVATED_ACTORS_SECTION = "ActivatedActors";
  44. const static char* META_DATA_SECTION = "MetaData";
  45. const static char* GAMETOKEN_SECTION = "Gametokens";
  46. const static char* EXTERNAL_ENTITIES_SECTION = "ExternalEntities";
  47.  
  48. //checkpoint data sanity check, usually triggered by changed entity Id's
  49. static bool CHECKPOINT_RESAVE_NECESSARY = false;
  50.  
  51. //opened XML node for writing
  52. static XmlNodeRef CHECKPOINT_SAVE_XML_NODE = NULL;
  53. //opened XML node for reading
  54. static XmlNodeRef CHECKPOINT_LOAD_XML_NODE = NULL;
  55.  
  56. //////////////////////////////////////////////////////////////////////////
  57. CCheckpointSystem::CCheckpointSystem() : m_pGameHandler(NULL)
  58. {
  59.  
  60. }
  61.  
  62. //////////////////////////////////////////////////////////////////////////
  63. CCheckpointSystem::~CCheckpointSystem()
  64. {
  65.  
  66. }
  67.  
  68. //////////////////////////////////////////////////////////////////////////
  69. CCheckpointSystem* CCheckpointSystem::GetInstance()
  70. {
  71.         //singleton instance
  72.         static CCheckpointSystem* g_pSLS = NULL;
  73.         if (g_pSLS == NULL)
  74.         {
  75.                 g_pSLS = new CCheckpointSystem();
  76.                 g_lastSavedCheckpoint.clear();
  77.         }
  78.         return g_pSLS;
  79. }
  80.  
  81. //////////////////////////////////////////////////////////////////////////
  82. bool CCheckpointSystem::SaveXMLNode(XmlNodeRef node, const char* identifier)
  83. {
  84.         if (!identifier || !node)
  85.                 return false;
  86.         //check whether a checkpoint is currently open
  87.         if (!CHECKPOINT_SAVE_XML_NODE)
  88.         {
  89.                 CryWarning(VALIDATOR_MODULE_GAME, VALIDATOR_WARNING, "Tried writing checkpoint section %s while checkpoint was not open.", identifier);
  90.                 return false;
  91.         }
  92.  
  93.         //flag section as being external and save name
  94.         node->setAttr("external", identifier);
  95.  
  96.         //add section to opened file
  97.         CHECKPOINT_SAVE_XML_NODE->addChild(node);
  98.         return true;
  99. }
  100.  
  101. //////////////////////////////////////////////////////////////////////////
  102. XmlNodeRef CCheckpointSystem::LoadXMLNode(const char* identifier)
  103. {
  104.         if (!identifier)
  105.                 return NULL;
  106.         //check whether a checkpoint is currently open
  107.         if (!CHECKPOINT_LOAD_XML_NODE)
  108.         {
  109.                 CryWarning(VALIDATOR_MODULE_GAME, VALIDATOR_WARNING, "Tried reading checkpoint section %s while checkpoint was not open.", identifier);
  110.                 return NULL;
  111.         }
  112.  
  113.         int numChildren = CHECKPOINT_LOAD_XML_NODE->getChildCount();
  114.         for (int i = 0; i < numChildren; ++i)
  115.         {
  116.                 XmlNodeRef child = CHECKPOINT_LOAD_XML_NODE->getChild(i);
  117.                 //return external section if name matches
  118.                 const char* key = "external";
  119.                 const char* attribName = child->getAttr(key);
  120.                 if (attribName)
  121.                 {
  122.                         //check name
  123.                         if (!stricmp(identifier, attribName))
  124.                                 return child;
  125.                 }
  126.         }
  127.  
  128.         return NULL;
  129. }
  130.  
  131. //////////////////////////////////////////////////////////////////////////
  132. bool CCheckpointSystem::SaveExternalEntity(EntityId id)
  133. {
  134.         //this function allows external logic (flowgraph) to save specific entities
  135.         if (!CHECKPOINT_SAVE_XML_NODE)
  136.         {
  137.                 CryWarning(VALIDATOR_MODULE_GAME, VALIDATOR_WARNING, "Tried writing external entity %i while savegame was not open.", (int)id);
  138.                 return false;
  139.         }
  140.  
  141.         //find entity and access external section
  142.         IEntity* pEntity = gEnv->pEntitySystem->GetEntity(id);
  143.         if (pEntity)
  144.         {
  145.                 XmlNodeRef externalEntities = CHECKPOINT_SAVE_XML_NODE->findChild(EXTERNAL_ENTITIES_SECTION);
  146.                 if (!externalEntities)
  147.                 {
  148.                         externalEntities = GetISystem()->CreateXmlNode(EXTERNAL_ENTITIES_SECTION);
  149.                         CHECKPOINT_SAVE_XML_NODE->addChild(externalEntities);
  150.                 }
  151.  
  152.                 IActor* pActor = CCryAction::GetCryAction()->GetIActorSystem()->GetActor(pEntity->GetId());
  153.                 if (pActor)
  154.                 {
  155.                         CryWarning(VALIDATOR_MODULE_GAME, VALIDATOR_WARNING, "The actor %s is additionally saved as external entity.", pEntity->GetName());
  156.                 }
  157.  
  158.                 //create entity data
  159.                 char entityId[16];
  160.                 cry_sprintf(entityId, "%s%u", "id", id);
  161.                 XmlNodeRef nextEntity = GetISystem()->CreateXmlNode(entityId);
  162.                 if (nextEntity)
  163.                 {
  164.                         nextEntity->setAttr("id", pEntity->GetId());
  165.                         nextEntity->setAttr("name", pEntity->GetName());
  166.                         //save active / hidden
  167.                         nextEntity->setAttr("active", pEntity->IsActive());
  168.                         nextEntity->setAttr("hidden", pEntity->IsHidden());
  169.                         //save translation and rotation (complete tm matrix for simplicity)
  170.                         SerializeWorldTM(pEntity, nextEntity, true);
  171.                         //add new entity to checkpoint
  172.                         externalEntities->addChild(nextEntity);
  173.  
  174.                         return true;
  175.                 }
  176.  
  177.                 return false;
  178.         }
  179.  
  180.         return false;
  181. }
  182.  
  183. //SAVING *********************************
  184.  
  185. //////////////////////////////////////////////////////////////////////////
  186. bool CCheckpointSystem::SaveGame(EntityId checkpointId, const char* fileName)
  187. {
  188.         CRY_ASSERT(fileName);
  189.         if (!fileName || CHECKPOINT_SAVE_XML_NODE || CHECKPOINT_LOAD_XML_NODE)
  190.                 return false;
  191.  
  192.         //set extension
  193.         FixedCheckpointString file(fileName);
  194.         SetFilenameExtension(file);
  195.  
  196.         CryWarning(VALIDATOR_MODULE_GAME, VALIDATOR_COMMENT, "Saving checkpoint %s", file.c_str());
  197.  
  198.         CHECKPOINT_SAVE_XML_NODE = GetISystem()->CreateXmlNode("Checkpoint");
  199.  
  200.         //write checkpoint data
  201.         SCheckpointData metaData;
  202.         WriteMetaData(checkpointId, CHECKPOINT_SAVE_XML_NODE, metaData);
  203.  
  204.         //actor data
  205.         // TODO For now, not saving actor info (AI) - If this happens later, support needs to be added for entity pools
  206.         //WriteActorData(CHECKPOINT_SAVE_XML_NODE);
  207.  
  208.         //vehicle data
  209.         WriteVehicleData(CHECKPOINT_SAVE_XML_NODE);
  210.  
  211.         //write game tokens
  212.         WriteGameTokens(CHECKPOINT_SAVE_XML_NODE);
  213.  
  214.         //let game write
  215.         if (m_pGameHandler)
  216.         {
  217.                 m_pGameHandler->OnWriteData(CHECKPOINT_SAVE_XML_NODE);
  218.         }
  219.  
  220.         //inform listeners
  221.         UpdateListener(metaData, true);
  222.  
  223.         //write to file
  224.         WriteXML(CHECKPOINT_SAVE_XML_NODE, file.c_str());
  225.  
  226.         //draw text message on screen
  227.         //static const ColorF color (0.0f, 0.85f, 0.2f, 1.0f);
  228.         //g_pGame->GetIGameFramework()->GetIPersistantDebug()->Add2DText("Checkpoint saved", 2.5f, color, 2.0f);
  229.  
  230.         CHECKPOINT_SAVE_XML_NODE = NULL;
  231.  
  232.         return true;
  233. }
  234.  
  235. //////////////////////////////////////////////////////////////////////////
  236. void CCheckpointSystem::WriteActorData(XmlNodeRef parentNode)
  237. {
  238.         XmlNodeRef node = GetISystem()->CreateXmlNode(ACTOR_FLAGS_SECTION);
  239.         //write only data for non-active or hidden actors
  240.         XmlNodeRef activatedActors = GetISystem()->CreateXmlNode(ACTIVATED_ACTORS_SECTION);
  241.         IActorSystem* pActorSystem = CCryAction::GetCryAction()->GetIActorSystem();
  242.         IActorIteratorPtr it = pActorSystem->CreateActorIterator();
  243.         while (IActor* pActor = it->Next())
  244.         {
  245.                 IEntity* pEntity = pActor->GetEntity();
  246.                 if (!pEntity->IsHidden() && pEntity->IsActive())
  247.                 {
  248.                         EntityId id = pEntity->GetId();
  249.                         const char* name = pEntity->GetName(); //we have to rely on names, since Id's change on level reexport
  250.                         char buffer[100];
  251.                         cry_sprintf(buffer, "%s%u", "id", id);
  252.                         activatedActors->setAttr(buffer, name);
  253.                 }
  254.         }
  255.         node->addChild(activatedActors);
  256.  
  257.         parentNode->addChild(node);
  258. }
  259.  
  260. //////////////////////////////////////////////////////////////////////////
  261. void CCheckpointSystem::WriteVehicleData(XmlNodeRef parentNode)
  262. {
  263.         IVehicleSystem* pVehicleSystem = CCryAction::GetCryAction()->GetIVehicleSystem();
  264.         IVehicleIteratorPtr pVehIt = pVehicleSystem->CreateVehicleIterator();
  265.         while (IVehicle* pVehicle = pVehIt->Next())
  266.         {
  267.                 SaveExternalEntity(pVehicle->GetEntityId());
  268.         }
  269. }
  270.  
  271. //////////////////////////////////////////////////////////////////////////
  272. void CCheckpointSystem::WriteMetaData(EntityId checkpointId, XmlNodeRef parentNode, SCheckpointData& outMetaData)
  273. {
  274.         XmlNodeRef node = GetISystem()->CreateXmlNode(META_DATA_SECTION);
  275.  
  276.         const char* levelName = CCryAction::GetCryAction()->GetLevelName();
  277.         CRY_ASSERT(levelName);
  278.         CryFixedStringT<32> curlevelName = levelName;
  279.         RepairLevelName(curlevelName);
  280.  
  281.         node->setAttr("Version", CHECKPOINT_VERSION_NUMBER);
  282.         node->setAttr("LevelName", curlevelName.c_str());
  283.         node->setAttr("CheckpointId", checkpointId);
  284.  
  285.         //write checkpoint name to be independent of entityId
  286.         IEntity* pCheckpointEntity = gEnv->pEntitySystem->GetEntity(checkpointId);
  287.         if (pCheckpointEntity)
  288.                 node->setAttr("CheckpointName", pCheckpointEntity->GetName());
  289.         else
  290.                 node->setAttr("CheckpointName", "none");
  291.  
  292.         string timeString;
  293.         GameUtils::timeToString(time(NULL), timeString);
  294.         node->setAttr("Timestamp", timeString.c_str());
  295.  
  296.         parentNode->addChild(node);
  297.  
  298.         //write back metadata for listeners
  299.         outMetaData.m_checkPointId = checkpointId;
  300.         outMetaData.m_levelName = levelName;
  301.         outMetaData.m_saveTime = timeString.c_str();
  302. }
  303.  
  304. //////////////////////////////////////////////////////////////////////////
  305. void CCheckpointSystem::WriteGameTokens(XmlNodeRef parentNode)
  306. {
  307.         //create serialization writer
  308.         XmlNodeRef node = GetISystem()->CreateXmlNode(GAMETOKEN_SECTION);
  309.         IXmlSerializer* pSerializer = GetISystem()->GetXmlUtils()->CreateXmlSerializer();
  310.         ISerialize* pWriter = pSerializer->GetWriter(node);
  311.  
  312.         //get serialization data
  313.         TSerialize ser = TSerialize(pWriter);
  314.         IGameTokenSystem* pTokenSystem = CCryAction::GetCryAction()->GetIGameTokenSystem();
  315.         pTokenSystem->Serialize(ser);
  316.  
  317.         //add to parent node
  318.         parentNode->addChild(node);
  319.  
  320.         pSerializer->Release();
  321. }
  322.  
  323. //////////////////////////////////////////////////////////////////////////
  324. void CCheckpointSystem::WriteXML(XmlNodeRef data, const char* fileName)
  325. {
  326.         IPlayerProfileManager* pPlayerProfMan = CCryAction::GetCryAction()->GetIPlayerProfileManager();
  327.         ;
  328.  
  329.         string path;
  330.         if (!pPlayerProfMan)
  331.         {
  332.                 path = CONSOLE_SAVEGAME_DIRECTORY;
  333.         }
  334.         else
  335.         {
  336.                 const char* sharedSaveGameFolder = pPlayerProfMan->GetSharedSaveGameFolder();
  337.                 path = sharedSaveGameFolder;
  338.         }
  339.  
  340.         path = PathUtil::AddSlash(path);
  341.         path.append(fileName);
  342.         if (data)
  343.         {
  344.                 //write checkpoint data to xml file with given name
  345.                 const string xmlHeader("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
  346.  
  347.                 bool bSuccess = data->saveToFile(path.c_str(), 32767 / 2, NULL);
  348.                 if (bSuccess)
  349.                 {
  350.                         //remember last saved checkpoint for "quickload"
  351.                         g_lastSavedCheckpoint = fileName;
  352.                 }
  353.                 else
  354.                         CryWarning(VALIDATOR_MODULE_GAME, VALIDATOR_ERROR, "Failed writing checkpoint file at %s", path.c_str());
  355.         }
  356. }
  357.  
  358. //LOADING ********************************
  359.  
  360. //////////////////////////////////////////////////////////////////////////
  361. bool CCheckpointSystem::LoadLastCheckpoint()
  362. {
  363.         if (!g_lastSavedCheckpoint.empty())
  364.                 return LoadGame(g_lastSavedCheckpoint.c_str());
  365.         CryWarning(VALIDATOR_MODULE_GAME, VALIDATOR_WARNING, "Can't load latest checkpoint : no recent checkpoint found!");
  366.         return false;
  367. }
  368.  
  369. //////////////////////////////////////////////////////////////////////////
  370. bool CCheckpointSystem::LoadGame(const char* fileName)
  371. {
  372.         //make sure not not save/load recursively or multiple times at once
  373.         if (CHECKPOINT_SAVE_XML_NODE || CHECKPOINT_LOAD_XML_NODE)
  374.                 return false;
  375.  
  376.         //set extension
  377.         FixedCheckpointString file(fileName);
  378.         SetFilenameExtension(file);
  379.  
  380.         CHECKPOINT_LOAD_XML_NODE = ReadXML(file.c_str());
  381.         if (!CHECKPOINT_LOAD_XML_NODE)
  382.                 return false;
  383.  
  384.         CryWarning(VALIDATOR_MODULE_GAME, VALIDATOR_COMMENT, "Loading checkpoint %s", file.c_str());
  385.  
  386.         //check for EntityId errors
  387.         CHECKPOINT_RESAVE_NECESSARY = false;
  388.  
  389.         //process meta data
  390.         SCheckpointData metaData;
  391.         if (!ReadMetaData(CHECKPOINT_LOAD_XML_NODE, metaData))
  392.                 return false;
  393.  
  394.         //check version number
  395.         if (metaData.m_versionNumber != CHECKPOINT_VERSION_NUMBER)
  396.         {
  397.                 CryWarning(VALIDATOR_MODULE_GAME, VALIDATOR_ERROR, "Checkpoint version number (%i) does not match current version (%i). Please reexport all checkpoints of this level to prevent errors!", metaData.m_versionNumber, CHECKPOINT_VERSION_NUMBER);
  398.         }
  399.  
  400.         //check for level mismatch
  401.         CryFixedStringT<32> curlevelName = CCryAction::GetCryAction()->GetLevelName();
  402.         RepairLevelName(curlevelName);
  403.         if (curlevelName.empty() || stricmp(metaData.m_levelName.c_str(), curlevelName.c_str()))
  404.         {
  405.                 if (!LoadCheckpointMap(metaData, curlevelName))
  406.                         return false;
  407.         }
  408.         else
  409.         {
  410.                 //reset the dynamic parts of the engine
  411.                 ResetEngine();
  412.         }
  413.  
  414.         //read actor data and respawn AI
  415.         // TODO For now, not restoring actor info (AI) - If this happens later, support needs to be added for entity pools
  416.         //RespawnAI(CHECKPOINT_LOAD_XML_NODE);
  417.  
  418.         //load gametokens again
  419.         ReadGameTokens(CHECKPOINT_LOAD_XML_NODE);
  420.  
  421.         //let game read
  422.         if (m_pGameHandler)
  423.         {
  424.                 m_pGameHandler->OnReadData(CHECKPOINT_LOAD_XML_NODE);
  425.         }
  426.  
  427.         //resets some gameplay data like action filters etc.
  428.         RestartGameplay();
  429.  
  430.         //load external entities, that are controlled by flowgraph
  431.         LoadExternalEntities(CHECKPOINT_LOAD_XML_NODE);
  432.  
  433.         //inform listeners
  434.         UpdateListener(metaData, false);
  435.  
  436.         //trigger flowgraph node
  437.         OnCheckpointLoaded(metaData);
  438.  
  439.         //draw text message on screen
  440.         //static const ColorF color (0.0f, 0.85f, 0.2f, 1.0f);
  441.         //g_pGame->GetIGameFramework()->GetIPersistantDebug()->Add2DText("Checkpoint loaded", 2.5f, color, 2.0f);
  442.  
  443.         //checkpoint file sanity check
  444.         if (CHECKPOINT_RESAVE_NECESSARY)
  445.         {
  446.                 CryWarning(VALIDATOR_MODULE_GAME, VALIDATOR_WARNING, "Checkpoint file contained obsolete or wrong data, trying to re-save checkpoint.");
  447.                 //resave checkpoint to fix changed entity Ids
  448.                 SaveGame(metaData.m_checkPointId, fileName);
  449.                 //make sure the script entity is aware of the activity
  450.                 OnCheckpointLoaded(metaData);
  451.         }
  452.  
  453.         CHECKPOINT_LOAD_XML_NODE = NULL;
  454.  
  455.         //when a checkpoint was loaded, it becomes the most recent checkpoint
  456.         g_lastSavedCheckpoint = fileName;
  457.  
  458.         //make sure the scripts are clean
  459.         //CXP : this caused a crash after some reloads, which hints to problems in the gamerules script
  460.         //gEnv->pScriptSystem->ForceGarbageCollection();
  461.  
  462.         return true;
  463. }
  464.  
  465. //////////////////////////////////////////////////////////////////////////
  466. bool CCheckpointSystem::LoadCheckpointMap(const SCheckpointData& metaData, CryFixedStringT<32>& curLevelName)
  467. {
  468.         CryWarning(VALIDATOR_MODULE_GAME, VALIDATOR_COMMENT, "Checkpoint loads new level :  %s", metaData.m_levelName.c_str());
  469.  
  470.         //load map
  471.         if (gEnv->IsEditor())
  472.                 return false; //can't do that
  473.         CryFixedStringT<64> mapCmd("map ");
  474.         mapCmd += metaData.m_levelName.c_str();
  475.         gEnv->pConsole->ExecuteString(mapCmd.c_str());
  476.  
  477.         curLevelName = CCryAction::GetCryAction()->GetLevelName();
  478.         RepairLevelName(curLevelName);
  479.         if (stricmp(metaData.m_levelName.c_str(), curLevelName.c_str()))
  480.         {
  481.                 CryWarning(VALIDATOR_MODULE_GAME, VALIDATOR_ERROR, "Failed loaded level %s from checkpoint.", metaData.m_levelName.c_str());
  482.                 return false; //still wrong level
  483.         }
  484.  
  485.         return true;
  486. }
  487.  
  488. //////////////////////////////////////////////////////////////////////////
  489. void CCheckpointSystem::LoadExternalEntities(XmlNodeRef parentNode)
  490. {
  491.         XmlNodeRef data = parentNode->findChild(EXTERNAL_ENTITIES_SECTION);
  492.         if (!data)
  493.                 return;
  494.  
  495.         int numEntities = data->getChildCount();
  496.         for (int i = 0; i < numEntities; ++i)
  497.         {
  498.                 XmlNodeRef nextEntity = data->getChild(i);
  499.                 if (nextEntity)
  500.                 {
  501.                         EntityId id = 0;
  502.                         nextEntity->getAttr("id", id);
  503.                         const char* name = nextEntity->getAttr("name");
  504.  
  505.                         //fix entityId if broken
  506.                         if (RepairEntityId(id, name))
  507.                         {
  508.                                 IEntity* pEntity = gEnv->pEntitySystem->GetEntity(id);
  509.                                 //setup entity
  510.                                 bool bActive = false;
  511.                                 bool bHidden = false;
  512.                                 nextEntity->getAttr("active", bActive);
  513.                                 nextEntity->getAttr("hidden", bHidden);
  514.                                 pEntity->Activate(bActive);
  515.                                 pEntity->Hide(bHidden);
  516.                                 //load matrix
  517.                                 SerializeWorldTM(pEntity, nextEntity, false);
  518.                         }
  519.                 }
  520.         }
  521. }
  522.  
  523. //////////////////////////////////////////////////////////////////////////
  524. //clear everything out before loading a checkpoint
  525. void CCheckpointSystem::ResetEngine()
  526. {
  527.         //let game do initial resetting
  528.         if (m_pGameHandler)
  529.         {
  530.                 m_pGameHandler->OnPreResetEngine();
  531.         }
  532.  
  533.         //turn off physics
  534.         gEnv->pSystem->SetThreadState(ESubsys_Physics, false);
  535.  
  536.         //reset engine similar to editor when leaving game mode
  537.         //broken geometry and dynamics
  538.         CCryAction::GetCryAction()->FlushBreakableObjects();
  539.         DeleteDynamicEntities();
  540.         CCryAction::GetCryAction()->ResetBrokenGameObjects();
  541.  
  542.         //this should just reset the velocity of all moving things, but instead vehicle doors fall off ...
  543.         //CXP : add this back in after CXP, Anton has to fix it
  544.         //gEnv->pPhysicalWorld->ResetDynamicEntities();
  545.  
  546.         //particle and post process effects
  547.         gEnv->p3DEngine->ResetPostEffects();
  548.         gEnv->p3DEngine->ResetParticlesAndDecals();
  549.  
  550.         REINST("notify the audio system?");
  551.  
  552.         //AI System
  553.         if (gEnv->pAISystem)
  554.         {
  555.                 gEnv->pAISystem->Reset(IAISystem::RESET_EXIT_GAME);
  556.                 gEnv->pAISystem->Reset(IAISystem::RESET_ENTER_GAME);
  557.         }
  558.  
  559.         //flow system
  560.  
  561.         //reset trackview
  562.         gEnv->pMovieSystem->Reset(true, true);
  563.  
  564.         //entity system
  565.         SEntityEvent event;
  566.         event.event = ENTITY_EVENT_RESET;
  567.         event.nParam[0] = 0;
  568.         gEnv->pEntitySystem->SendEventToAll(event);
  569.  
  570.         //Vehicle System
  571.         IVehicleSystem* pVehicleSystem = CCryAction::GetCryAction()->GetIVehicleSystem();
  572.         IVehicleIteratorPtr pVehIt = pVehicleSystem->CreateVehicleIterator();
  573.         while (IVehicle* pVehicle = pVehIt->Next())
  574.         {
  575.                 pVehicle->Reset(true);
  576.         }
  577.  
  578.         //make sure the scripts are clean
  579.         gEnv->pScriptSystem->ForceGarbageCollection();
  580.  
  581.         //turn on physics again
  582.         gEnv->pSystem->SetThreadState(ESubsys_Physics, true);
  583.  
  584.         //let game do final resetting
  585.         if (m_pGameHandler)
  586.         {
  587.                 m_pGameHandler->OnPostResetEngine();
  588.         }
  589. }
  590.  
  591. //////////////////////////////////////////////////////////////////////////
  592. bool CCheckpointSystem::ReadMetaData(XmlNodeRef parentNode, SCheckpointData& metaData, bool bRepairId /*=true*/)
  593. {
  594.         XmlNodeRef data = parentNode->findChild(META_DATA_SECTION);
  595.         if (!data)
  596.                 return false;
  597.  
  598.         metaData.m_versionNumber = 0;
  599.         metaData.m_levelName.clear();
  600.         metaData.m_saveTime.clear();
  601.         metaData.m_checkPointId = 0;
  602.  
  603.         //read meta data
  604.         int numAttribs = data->getNumAttributes();
  605.         const char* key, * value;
  606.         const char* checkpointName = NULL;
  607.         for (int i = 0; i < numAttribs; ++i)
  608.         {
  609.                 data->getAttributeByIndex(i, &key, &value);
  610.  
  611.                 if (!stricmp("Version", key))
  612.                 {
  613.                         metaData.m_versionNumber = atoi(value);
  614.                 }
  615.                 else if (!stricmp("CheckpointId", key))
  616.                 {
  617.                         metaData.m_checkPointId = EntityId(atoi(value));
  618.                 }
  619.                 else if (!stricmp("CheckpointName", key))
  620.                 {
  621.                         checkpointName = value;
  622.                 }
  623.                 else if (!stricmp("LevelName", key))
  624.                 {
  625.                         metaData.m_levelName = value;
  626.                 }
  627.                 else if (!stricmp("Timestamp", key))
  628.                 {
  629.                         metaData.m_saveTime = value;
  630.                 }
  631.         }
  632.  
  633.         //EntityId's may change on level export -> fix id
  634.         if (checkpointName && bRepairId)
  635.         {
  636.                 if (!RepairEntityId(metaData.m_checkPointId, checkpointName))
  637.                         CryWarning(VALIDATOR_MODULE_GAME, VALIDATOR_ERROR, "Failed finding checkpoint entity during loading, flowgraph might be broken.");
  638.         }
  639.  
  640.         //check all values have been read
  641.         CRY_ASSERT(metaData.m_levelName.size() > 0);
  642.         CRY_ASSERT(metaData.m_saveTime.size() > 0);
  643.         //CRY_ASSERT(metaData.m_checkPointId);
  644.  
  645.         return true;
  646. }
  647.  
  648. //////////////////////////////////////////////////////////////////////////
  649. //this respawns the active AI at their spawn locations
  650. void CCheckpointSystem::RespawnAI(XmlNodeRef data)
  651. {
  652.         if (!data)
  653.                 return;
  654.  
  655.         XmlNodeRef actorData = data->findChild(ACTOR_FLAGS_SECTION);
  656.         if (!actorData)
  657.         {
  658.                 CryWarning(VALIDATOR_MODULE_GAME, VALIDATOR_ERROR, "Failed reading actor data from checkpoint, actors won't be respawned");
  659.                 return;
  660.         }
  661.  
  662.         IActorSystem* pActorSystem = CCryAction::GetCryAction()->GetIActorSystem();
  663.  
  664.         //first run through all actors and hide/deactivate them
  665.         IActorIteratorPtr it = pActorSystem->CreateActorIterator();
  666.         while (IActor* pActor = it->Next())
  667.         {
  668.                 IEntity* pEntity = pActor->GetEntity();
  669.                 //deactivate all actors
  670.                 pEntity->Hide(true);
  671.                 pEntity->Activate(false);
  672.         }
  673.  
  674.         //load actorflags for active actors
  675.         XmlNodeRef activatedActors = actorData->findChild(ACTIVATED_ACTORS_SECTION);
  676.         if (activatedActors)
  677.         {
  678.                 int actorFlags = activatedActors->getNumAttributes();
  679.                 const char* key;
  680.                 const char* value;
  681.                 for (int i = 0; i < actorFlags; ++i)
  682.                 {
  683.                         activatedActors->getAttributeByIndex(i, &key, &value);
  684.                         //format is "idXXX"
  685.                         CRY_ASSERT(strlen(key) > 2);
  686.                         EntityId id = (EntityId)(atoi(&key[2]));
  687.                         bool foundEntity = RepairEntityId(id, value);
  688.                         if (foundEntity)
  689.                         {
  690.                                 IActor* pActor = pActorSystem->GetActor(id);
  691.                                 if (pActor)
  692.                                 {
  693.                                         pActor->GetEntity()->Hide(false);
  694.                                         pActor->GetEntity()->Activate(true);
  695.                                 }
  696.                                 else
  697.                                         CryWarning(VALIDATOR_MODULE_GAME, VALIDATOR_ERROR, "Failed finding actor %i from checkpoint.", (int)id);
  698.                         }
  699.                         else
  700.                                 CryWarning(VALIDATOR_MODULE_GAME, VALIDATOR_ERROR, "Failed finding actor %s from checkpoint, actor is not setup correctly.", value);
  701.                 }
  702.         }
  703.         else
  704.                 CryWarning(VALIDATOR_MODULE_GAME, VALIDATOR_ERROR, "Deactivated actors section was missing in checkpoint.");
  705.  
  706.         it = pActorSystem->CreateActorIterator();
  707.         //iterate all actors and respawn if active
  708.         while (IActor* pActor = it->Next())
  709.         {
  710.                 IEntity* pEntity = pActor->GetEntity();
  711.                 if (pEntity->GetId() == LOCAL_PLAYER_ENTITY_ID) //don't respawn player
  712.                         continue;
  713.  
  714.                 //we don't respawn deactivated actors
  715.                 if (!pEntity->IsHidden() && pEntity->IsActive())
  716.                 {
  717.                         pActor->SetHealth(0);
  718.                         pActor->Respawn();
  719.                 }
  720.                 else //but we still reset their position
  721.                 {
  722.                         pActor->ResetToSpawnLocation();
  723.                 }
  724.         }
  725. }
  726.  
  727. //////////////////////////////////////////////////////////////////////////
  728. void CCheckpointSystem::ReadGameTokens(XmlNodeRef parentNode)
  729. {
  730.         //get source node
  731.         XmlNodeRef node = parentNode->findChild(GAMETOKEN_SECTION);
  732.         if (!node)
  733.         {
  734.                 CryWarning(VALIDATOR_MODULE_GAME, VALIDATOR_ERROR, "Couldn't find Gametoken section while reading checkpoint.");
  735.                 return;
  736.         }
  737.  
  738.         //create serialization reader
  739.         IXmlSerializer* pSerializer = GetISystem()->GetXmlUtils()->CreateXmlSerializer();
  740.         ISerialize* pReader = pSerializer->GetReader(node);
  741.  
  742.         //read serialization data
  743.         TSerialize ser = TSerialize(pReader);
  744.         IGameTokenSystem* pTokenSystem = CCryAction::GetCryAction()->GetIGameTokenSystem();
  745.         pTokenSystem->Serialize(ser);
  746.  
  747.         pSerializer->Release();
  748. }
  749.  
  750. //////////////////////////////////////////////////////////////////////////
  751. XmlNodeRef CCheckpointSystem::ReadXML(const char* fileName)
  752. {
  753.         IPlayerProfileManager* pPlayerProfMan = CCryAction::GetCryAction()->GetIPlayerProfileManager();
  754.         ;
  755.  
  756.         string path;
  757.         if (!pPlayerProfMan)
  758.         {
  759.                 //on consoles there is no profile manager
  760.                 path = CONSOLE_SAVEGAME_DIRECTORY;
  761.         }
  762.         else
  763.         {
  764.                 const char* sharedSaveGameFolder = pPlayerProfMan->GetSharedSaveGameFolder();
  765.                 path = sharedSaveGameFolder;
  766.         }
  767.  
  768.         path = PathUtil::AddSlash(path);
  769.         path.append(fileName);
  770.  
  771.         //read XML data from given checkpoint file
  772.         _smart_ptr<IXmlParser> xmlParser;
  773.         xmlParser.reset(GetISystem()->GetXmlUtils()->CreateXmlParser());
  774.         XmlNodeRef data = xmlParser->ParseFile(path.c_str(), true);
  775.  
  776.         if (!data)
  777.                 CryWarning(VALIDATOR_MODULE_GAME, VALIDATOR_ERROR, "Failed reading checkpoint at %s", path.c_str());
  778.  
  779.         return data;
  780. }
  781.  
  782. //////////////////////////////////////////////////////////////////////////
  783. void CCheckpointSystem::RestartGameplay()
  784. {
  785.         //if paused - start game
  786.         gEnv->pGameFramework->PauseGame(false, true);
  787.  
  788.         //let game restart
  789.         if (m_pGameHandler)
  790.         {
  791.                 m_pGameHandler->OnRestartGameplay();
  792.         }
  793. }
  794.  
  795. //////////////////////////////////////////////////////////////////////////
  796. void CCheckpointSystem::OnCheckpointLoaded(SCheckpointData metaData)
  797. {
  798.         IEntity* pCheckpoint = gEnv->pEntitySystem->GetEntity(metaData.m_checkPointId);
  799.         if (pCheckpoint)
  800.         {
  801.                 //Trigger OnLoad
  802.                 IScriptTable* pScript = pCheckpoint->GetScriptTable();
  803.                 if (pScript)
  804.                 {
  805.                         HSCRIPTFUNCTION hScriptFunc(NULL);
  806.                         pScript->GetValue("Event_OnLoadCheckpoint", hScriptFunc);
  807.  
  808.                         if (hScriptFunc) //this will trigger the flowgraph output
  809.                         {
  810.                                 IScriptSystem* pIScriptSystem = gEnv->pScriptSystem;
  811.                                 Script::Call(pIScriptSystem, hScriptFunc, pScript);
  812.                                 pIScriptSystem->ReleaseFunc(hScriptFunc);
  813.                         }
  814.                 }
  815.         }
  816. }
  817.  
  818. //SHARED ********************************
  819.  
  820. //////////////////////////////////////////////////////////////////////////
  821. bool CCheckpointSystem::GetMetaData(const char* fileName, SCheckpointData& metaData, bool bRepairId /*=true*/)
  822. {
  823.         XmlNodeRef data = ReadXML(fileName);
  824.         if (!data)
  825.                 return false;
  826.  
  827.         //process meta data
  828.         return ReadMetaData(data, metaData, bRepairId);
  829. }
  830.  
  831. //////////////////////////////////////////////////////////////////////////
  832. void CCheckpointSystem::SetFilenameExtension(FixedCheckpointString& fileName)
  833. {
  834.         int fileNameLen = fileName.length();
  835.  
  836.         //check for empty string
  837.         if (fileNameLen == 0)
  838.         {
  839.                 fileName = "placeholder";
  840.                 fileName.append(FILENAME_EXTENSION);
  841.                 return;
  842.         }
  843.  
  844.         //look up extension
  845.         size_t pos = fileName.find(FILENAME_EXTENSION);
  846.         if (pos != FixedCheckpointString::npos && pos == (fileNameLen - strlen(FILENAME_EXTENSION)))
  847.                 return;
  848.  
  849.         //look up and remove wrong extension
  850.         pos = fileName.rfind('.');
  851.         if (pos != FixedCheckpointString::npos)
  852.         {
  853.                 fileName = fileName.substr(0, pos);
  854.         }
  855.  
  856.         //add extension
  857.         fileName.append(FILENAME_EXTENSION);
  858. }
  859.  
  860. //////////////////////////////////////////////////////////////////////////
  861. bool CCheckpointSystem::RepairEntityId(EntityId& id, const char* pEntityName)
  862. {
  863.         //EntityId's may change on level export -> fix id
  864.         if (pEntityName)
  865.         {
  866.                 //test the original entity id
  867.                 IEntity* pOriginalEntity = gEnv->pEntitySystem->GetEntity(id);
  868.                 if (pOriginalEntity && !stricmp(pOriginalEntity->GetName(), pEntityName))
  869.                         return true; //seems correct
  870.  
  871.                 IEntity* pNewEntity = gEnv->pEntitySystem->FindEntityByName(pEntityName);
  872.                 if (!pNewEntity)
  873.                         CryWarning(VALIDATOR_MODULE_GAME, VALIDATOR_WARNING, "Entity %s in loaded checkpoint could not be found. This means the checkpoint file is not compatible with this level version.", pEntityName);
  874.                 else if (!stricmp(pNewEntity->GetName(), pEntityName))
  875.                 {
  876.                         //if the level was re-exported, the entity id might differ
  877.                         CHECKPOINT_RESAVE_NECESSARY = true;
  878.                         //this is a weakness of our entity system/editor and might be fixed in future
  879.                         id = pNewEntity->GetId();
  880.                         return true;
  881.                 }
  882.                 return false;
  883.         }
  884.  
  885.         return false;
  886. }
  887.  
  888. //////////////////////////////////////////////////////////////////////////
  889. void CCheckpointSystem::RepairLevelName(CryFixedStringT<32>& levelName)
  890. {
  891.         if (levelName.empty())
  892.                 return;
  893.         int posSlash = levelName.rfind('/');
  894.         if (posSlash != levelName.npos)  //This is a work-around for the editor/fullgame incompatible level name convention
  895.                 levelName = levelName.substr(posSlash + 1, levelName.size() - posSlash);
  896. }
  897.  
  898. //////////////////////////////////////////////////////////////////////////
  899. void CCheckpointSystem::SetGameHandler(ICheckpointGameHandler* pHandler)
  900. {
  901.         CRY_ASSERT(pHandler);
  902.         m_pGameHandler = pHandler;
  903. }
  904.  
  905. //////////////////////////////////////////////////////////////////////////
  906. void CCheckpointSystem::ClearGameHandler()
  907. {
  908.         m_pGameHandler = NULL;
  909. }
  910.  
  911. //////////////////////////////////////////////////////////////////////////
  912. void CCheckpointSystem::RegisterListener(ICheckpointListener* pListener)
  913. {
  914.         CRY_ASSERT(pListener);
  915.  
  916.         //check for existing listener
  917.         if (std::find(g_vCheckpointSystemListeners.begin(), g_vCheckpointSystemListeners.end(), pListener) == g_vCheckpointSystemListeners.end())
  918.         {
  919.                 //add listener
  920.                 g_vCheckpointSystemListeners.push_back(pListener);
  921.         }
  922. }
  923.  
  924. //////////////////////////////////////////////////////////////////////////
  925. void CCheckpointSystem::RemoveListener(ICheckpointListener* pListener)
  926. {
  927.         CRY_ASSERT(pListener);
  928.  
  929.         //look up listener
  930.         std::list<ICheckpointListener*>::iterator it = std::find(g_vCheckpointSystemListeners.begin(), g_vCheckpointSystemListeners.end(), pListener);
  931.         if (it != g_vCheckpointSystemListeners.end())
  932.         {
  933.                 //remove listener
  934.                 g_vCheckpointSystemListeners.erase(it);
  935.         }
  936. }
  937.  
  938. //////////////////////////////////////////////////////////////////////////
  939. void CCheckpointSystem::UpdateListener(SCheckpointData data, bool wasSaving)
  940. {
  941.         //external listeners may also read/write checkpoint data now
  942.         std::list<ICheckpointListener*>::iterator it = g_vCheckpointSystemListeners.begin();
  943.         std::list<ICheckpointListener*>::iterator end = g_vCheckpointSystemListeners.end();
  944.         for (; it != end; ++it)
  945.         {
  946.                 //send update - the global checkpoint flownode also is set here, but is not triggered until the flowgraph updates
  947.                 if (wasSaving)
  948.                         (*it)->OnSave(&data, GetInstance());
  949.                 else
  950.                         (*it)->OnLoad(&data, GetInstance());
  951.         }
  952. }
  953.  
  954. //////////////////////////////////////////////////////////////////////////
  955. void CCheckpointSystem::SerializeWorldTM(IEntity* pEntity, XmlNodeRef data, bool writing)
  956. {
  957.         if (!pEntity || !data)
  958.                 return;
  959.  
  960.         if (writing)
  961.         {
  962.                 //write all TM columns to checkpoint node
  963.                 const Matrix34& tm = pEntity->GetWorldTM();
  964.                 data->setAttr("TMcol0", tm.GetColumn0());
  965.                 data->setAttr("TMcol1", tm.GetColumn1());
  966.                 data->setAttr("TMcol2", tm.GetColumn2());
  967.                 data->setAttr("TMcol3", tm.GetColumn3());
  968.         }
  969.         else
  970.         {
  971.                 //read and set TM columns from node
  972.                 Matrix34 tm;
  973.                 Vec3 temp = Vec3(0, 0, 0);
  974.                 bool foundData = data->getAttr("TMcol0", temp);
  975.                 tm.SetColumn(0, temp);
  976.                 foundData &= data->getAttr("TMcol1", temp);
  977.                 tm.SetColumn(1, temp);
  978.                 foundData &= data->getAttr("TMcol2", temp);
  979.                 tm.SetColumn(2, temp);
  980.                 foundData &= data->getAttr("TMcol3", temp);
  981.                 tm.SetColumn(3, temp);
  982.                 CRY_ASSERT(foundData);
  983.                 //set matrix to entity
  984.                 pEntity->SetWorldTM(tm);
  985.         }
  986. }
  987.  
  988. //////////////////////////////////////////////////////////////////////////
  989. void CCheckpointSystem::DeleteDynamicEntities()
  990. {
  991.         IEntitySystem* pEntitySystem = gEnv->pEntitySystem;
  992.         IEntityItPtr pIt = pEntitySystem->GetEntityIterator();
  993.         //////////////////////////////////////////////////////////////////////////
  994.         pIt->MoveFirst();
  995.         while (!pIt->IsEnd())
  996.         {
  997.                 IEntity* pEntity = pIt->Next();
  998.                 uint32 nEntityFlags = pEntity->GetFlags();
  999.  
  1000.                 // Local player must not be deleted.
  1001.                 if (nEntityFlags & ENTITY_FLAG_LOCAL_PLAYER)
  1002.                         continue;
  1003.  
  1004.                 if (nEntityFlags & ENTITY_FLAG_SPAWNED)
  1005.                         pEntitySystem->RemoveEntity(pEntity->GetId());
  1006.         }
  1007.         // Force deletion of removed entities.
  1008.         pEntitySystem->DeletePendingEntities();
  1009. }
  1010.  
  1011. //////////////////////////////////////////////////////////////////////////
  1012. void CCheckpointSystem::GetCurrentLevelCheckpoints(std::vector<string>& saveNames)
  1013. {
  1014.         //get current level
  1015.         const char* levelName = CCryAction::GetCryAction()->GetLevelName();
  1016.         CryFixedStringT<32> curlevelName = levelName;
  1017.         if (levelName)
  1018.                 CCheckpointSystem::GetInstance()->RepairLevelName(curlevelName);
  1019.  
  1020.         //parse savegames fitting current level
  1021.         ParseSavedFiles(saveNames, curlevelName.c_str());
  1022. }
  1023.  
  1024. //////////////////////////////////////////////////////////////////////////
  1025. void CCheckpointSystem::ParseSavedFiles(std::vector<string>& saveNames, const char* pLevelName)
  1026. {
  1027.         //create search index
  1028.         string search = string(CONSOLE_SAVEGAME_DIRECTORY) + "/*" + string(FILENAME_EXTENSION);
  1029.  
  1030.         //scan savegame directory
  1031.         _finddata_t fd;
  1032.         intptr_t handle = gEnv->pCryPak->FindFirst(search.c_str(), &fd);
  1033.         if (handle != -1)
  1034.         {
  1035.                 do
  1036.                 {
  1037.                         //if levelname is provided, check metaData
  1038.                         if (pLevelName)
  1039.                         {
  1040.                                 //try to get meta data for save file
  1041.                                 SCheckpointData metaData;
  1042.                                 if (!CCheckpointSystem::GetInstance()->GetMetaData(fd.name, metaData, false))
  1043.                                 {
  1044.                                         CRY_ASSERT(0); //shouldn't happen
  1045.                                         continue;
  1046.                                 }
  1047.  
  1048.                                 if (stricmp(metaData.m_levelName.c_str(), pLevelName))
  1049.                                         continue;
  1050.                         }
  1051.  
  1052.                         //add filename to list
  1053.                         saveNames.push_back(fd.name);
  1054.                 }
  1055.                 while (gEnv->pCryPak->FindNext(handle, &fd) >= 0);
  1056.  
  1057.                 gEnv->pCryPak->FindClose(handle);
  1058.         }
  1059. }
  1060.  
  1061. //~CCheckpointSystem
  1062.  
downloadCheckPointSystem.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