BVB Source Codes

CRYENGINE Show PlayerProfileImplFS.cpp Source code

Return Download CRYENGINE: download PlayerProfileImplFS.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 <CrySystem/XML/IXml.h>
  5. #include <CryString/StringUtils.h>
  6. #include "PlayerProfileImplFS.h"
  7. #include "PlayerProfileImplRSFHelper.h"
  8. #include "PlayerProfile.h"
  9. #include "Serialization/XmlSaveGame.h"
  10. #include "Serialization/XmlLoadGame.h"
  11. #include "BMPHelper.h"
  12. #include "CryAction.h"
  13. #include <CryCore/Platform/IPlatformOS.h>
  14. #include "CryActionCVars.h"
  15. #include "Serialization/SerializeWriterXMLCPBin.h"
  16. #include "Serialization/SerializeReaderXMLCPBin.h"
  17. #include "Serialization/XMLCPBin/Writer/XMLCPB_WriterInterface.h"
  18. #include "Serialization/XMLCPBin/Reader/XMLCPB_ReaderInterface.h"
  19. #include "Serialization/XMLCPBin/XMLCPB_Utils.h"
  20.  
  21. using namespace PlayerProfileImpl;
  22.  
  23. #define PLAYER_PROFILE_SAVE_AS_TEXT_IN_DEVMODE 1
  24.  
  25. //------------------------------------------------------------------------
  26. CPlayerProfileImplFS::CPlayerProfileImplFS() : m_pMgr(0)
  27. {
  28. }
  29.  
  30. //------------------------------------------------------------------------
  31. CPlayerProfileImplFS::~CPlayerProfileImplFS()
  32. {
  33. }
  34.  
  35. //------------------------------------------------------------------------
  36. bool CPlayerProfileImplFS::Initialize(CPlayerProfileManager* pMgr)
  37. {
  38.         m_pMgr = pMgr;
  39.         return true;
  40. }
  41.  
  42. //------------------------------------------------------------------------
  43. void CPlayerProfileImplFS::InternalMakeFSPath(SUserEntry* pEntry, const char* profileName, string& outPath)
  44. {
  45.         if (pEntry)
  46.         {
  47.                 outPath = ("%USER%/ProfilesSingle/");
  48.         }
  49.         else
  50.         {
  51.                 // default profile always in game folder
  52.                 outPath = "Libs/Config/ProfilesSingle/";
  53.         }
  54.         if (profileName && *profileName)
  55.         {
  56.                 outPath.append(profileName);
  57.                 outPath.append("/");
  58.         }
  59. }
  60.  
  61. //------------------------------------------------------------------------
  62. void CPlayerProfileImplFS::InternalMakeFSSaveGamePath(SUserEntry* pEntry, const char* profileName, string& outPath, bool bNeedFolder)
  63. {
  64.         assert(pEntry != 0);
  65.         assert(profileName != 0);
  66.  
  67.         if (m_pMgr->IsSaveGameFolderShared())
  68.         {
  69.                 outPath = m_pMgr->GetSharedSaveGameFolder();
  70.                 outPath.append("/");
  71.                 if (!bNeedFolder)
  72.                 {
  73.                         outPath.append(profileName);
  74.                         outPath.append("_");
  75.                 }
  76.         }
  77.         else
  78.         {
  79.                 outPath = "%USER%/ProfilesSingle/";
  80.                 outPath.append(profileName);
  81.                 outPath.append("/SaveGames/");
  82.         }
  83. }
  84.  
  85. //------------------------------------------------------------------------
  86. bool CPlayerProfileImplFS::SaveProfile(SUserEntry* pEntry, CPlayerProfile* pProfile, const char* name, bool initialSave, int reason /* = ePR_All*/)
  87. {
  88.         // save the profile into a specific location
  89.  
  90.         // check, if it's a valid filename
  91.         if (IsValidFilename(name) == false)
  92.                 return false;
  93.  
  94.         // XML for now
  95.         string filename;
  96.         InternalMakeFSPath(pEntry, name, filename);
  97.  
  98.         // currently all (attributes, action maps, ...) in one file
  99.         XmlNodeRef rootNode = GetISystem()->CreateXmlNode(PROFILE_ROOT_TAG);
  100.         rootNode->setAttr(PROFILE_NAME_TAG, name);
  101.         CSerializerXML serializer(rootNode, false); // SerializerXML no longer supports using sections in 1 file.
  102.  
  103.         bool ok = pProfile->SerializeXML(&serializer);
  104.         if (ok)
  105.         {
  106.                 ok = SaveXMLFile(filename, rootNode);
  107.         }
  108.         return ok;
  109. }
  110.  
  111. //------------------------------------------------------------------------
  112. bool CPlayerProfileImplFS::LoadProfile(SUserEntry* pEntry, CPlayerProfile* pProfile, const char* name)
  113. {
  114.         // load the profile from a specific location
  115.  
  116.         // XML for now
  117.         // if pEntry==0 -> use factory default
  118.         string filename;
  119.         InternalMakeFSPath(pEntry, name, filename);
  120.  
  121.         // currently all (attributes, action maps, ...) in one file
  122.         XmlNodeRef rootNode = LoadXMLFile(filename.c_str());
  123.         if (rootNode == 0)
  124.                 return false;
  125.  
  126.         if (stricmp(rootNode->getTag(), PROFILE_ROOT_TAG) != 0)
  127.         {
  128.                 GameWarning("CPlayerProfileImplFS::LoadProfile: Profile '%s' of user '%s' seems to exist, but is invalid (File '%s). Skipped", name, pEntry->userId.c_str(), filename.c_str());
  129.                 return false;
  130.         }
  131.         CSerializerXML serializer(rootNode, true); // SerializerXML no longer supports using sections in 1 file.
  132.  
  133.         bool ok = pProfile->SerializeXML(&serializer);
  134.         return ok;
  135. }
  136.  
  137. //------------------------------------------------------------------------
  138. bool CPlayerProfileImplFS::LoginUser(SUserEntry* pEntry)
  139. {
  140.         // lookup stored profiles of the user (pEntry->userId) and fill in the pEntry->profileDesc
  141.         // vector
  142.         pEntry->profileDesc.clear();
  143.  
  144.         // scan directory for profiles
  145.  
  146.         string path;
  147.         InternalMakeFSPath(pEntry, "", path);  // no profile name -> only path
  148.  
  149.         ICryPak* pCryPak = gEnv->pCryPak;
  150.         _finddata_t fd;
  151.  
  152.         path.TrimRight("/\\");
  153.         string search = path + "/*.xml";
  154.         intptr_t handle = pCryPak->FindFirst(search.c_str(), &fd);
  155.         if (handle != -1)
  156.         {
  157.                 do
  158.                 {
  159.                         // fd.name contains the profile name
  160.                         string filename = path;
  161.                         filename += "/";
  162.                         filename += fd.name;
  163.                         XmlNodeRef rootNode = LoadXMLFile(filename.c_str());
  164.  
  165.                         // see if the root tag is o.k.
  166.                         if (rootNode && stricmp(rootNode->getTag(), PROFILE_ROOT_TAG) == 0)
  167.                         {
  168.                                 string profileName = fd.name;
  169.                                 PathUtil::RemoveExtension(profileName);
  170.                                 if (rootNode->haveAttr(PROFILE_NAME_TAG))
  171.                                 {
  172.                                         const char* profileHumanName = rootNode->getAttr(PROFILE_NAME_TAG);
  173.                                         if (profileHumanName != 0 && stricmp(profileHumanName, profileName) == 0)
  174.                                         {
  175.                                                 profileName = profileHumanName;
  176.                                         }
  177.                                 }
  178.                                 pEntry->profileDesc.push_back(SLocalProfileInfo(profileName));
  179.                         }
  180.                         else
  181.                         {
  182.                                 GameWarning("CPlayerProfileImplFS::LoginUser: Profile '%s' of User '%s' seems to exist, but is invalid (File '%s). Skipped", fd.name, pEntry->userId.c_str(), filename.c_str());
  183.                         }
  184.                 }
  185.                 while (pCryPak->FindNext(handle, &fd) >= 0);
  186.  
  187.                 pCryPak->FindClose(handle);
  188.         }
  189.  
  190.         return true;
  191. }
  192.  
  193. //------------------------------------------------------------------------
  194. bool CPlayerProfileImplFS::DeleteProfile(SUserEntry* pEntry, const char* name)
  195. {
  196.         string path;
  197.         InternalMakeFSPath(pEntry, name, path);  // no profile name -> only path
  198.         bool bOK = gEnv->pCryPak->RemoveFile(path.c_str());
  199.         // in case the savegame folder is shared, we have to delete the savegames from the shared folder
  200.         if (bOK && m_pMgr->IsSaveGameFolderShared())
  201.         {
  202.                 CPlayerProfileManager::TSaveGameInfoVec saveGameInfoVec;
  203.                 if (GetSaveGames(pEntry, saveGameInfoVec, name)) // provide alternate profileName, because pEntry->pCurrentProfile points to the active profile
  204.                 {
  205.                         CPlayerProfileManager::TSaveGameInfoVec::iterator iter = saveGameInfoVec.begin();
  206.                         CPlayerProfileManager::TSaveGameInfoVec::iterator iterEnd = saveGameInfoVec.end();
  207.                         while (iter != iterEnd)
  208.                         {
  209.                                 DeleteSaveGame(pEntry, iter->name);
  210.                                 ++iter;
  211.                         }
  212.                 }
  213.         }
  214.         return bOK;
  215. }
  216.  
  217. //------------------------------------------------------------------------
  218. bool CPlayerProfileImplFS::RenameProfile(SUserEntry* pEntry, const char* newName)
  219. {
  220.         // TODO: only rename in the filesystem. for now save new and delete old
  221.         const char* oldName = pEntry->pCurrentProfile->GetName();
  222.         bool ok = SaveProfile(pEntry, pEntry->pCurrentProfile, newName);
  223.         if (!ok)
  224.                 return false;
  225.  
  226.         // move the save games
  227.         if (CPlayerProfileManager::sUseRichSaveGames)
  228.         {
  229.                 CRichSaveGameHelper sgHelper(this);
  230.                 sgHelper.MoveSaveGames(pEntry, oldName, newName);
  231.         }
  232.         else
  233.         {
  234.                 CCommonSaveGameHelper sgHelper(this);
  235.                 sgHelper.MoveSaveGames(pEntry, oldName, newName);
  236.         }
  237.  
  238.         DeleteProfile(pEntry, oldName);
  239.         return true;
  240. }
  241.  
  242. //------------------------------------------------------------------------
  243. bool CPlayerProfileImplFS::LogoutUser(SUserEntry* pEntry)
  244. {
  245.         return true;
  246. }
  247.  
  248. //------------------------------------------------------------------------
  249. bool CPlayerProfileImplFS::GetSaveGames(SUserEntry* pEntry, CPlayerProfileManager::TSaveGameInfoVec& outVec, const char* altProfileName)
  250. {
  251.         if (CPlayerProfileManager::sUseRichSaveGames)
  252.         {
  253.                 CRichSaveGameHelper sgHelper(this);
  254.                 return sgHelper.GetSaveGames(pEntry, outVec, altProfileName);
  255.         }
  256.         else
  257.         {
  258.                 CCommonSaveGameHelper sgHelper(this);
  259.                 return sgHelper.GetSaveGames(pEntry, outVec, altProfileName);
  260.         }
  261. }
  262.  
  263. //------------------------------------------------------------------------
  264. ISaveGame* CPlayerProfileImplFS::CreateSaveGame(SUserEntry* pEntry)
  265. {
  266.         if (CPlayerProfileManager::sUseRichSaveGames)
  267.         {
  268.                 CRichSaveGameHelper sgHelper(this);
  269.                 return sgHelper.CreateSaveGame(pEntry);
  270.         }
  271.         else
  272.         {
  273.                 CCommonSaveGameHelper sgHelper(this);
  274.                 return sgHelper.CreateSaveGame(pEntry);
  275.         }
  276. }
  277.  
  278. //------------------------------------------------------------------------
  279. ILoadGame* CPlayerProfileImplFS::CreateLoadGame(SUserEntry* pEntry)
  280. {
  281.         if (CPlayerProfileManager::sUseRichSaveGames)
  282.         {
  283.                 CRichSaveGameHelper sgHelper(this);
  284.                 return sgHelper.CreateLoadGame(pEntry);
  285.         }
  286.         else
  287.         {
  288.                 CCommonSaveGameHelper sgHelper(this);
  289.                 return sgHelper.CreateLoadGame(pEntry);
  290.         }
  291. }
  292.  
  293. //------------------------------------------------------------------------
  294. bool CPlayerProfileImplFS::DeleteSaveGame(SUserEntry* pEntry, const char* name)
  295. {
  296.         if (CPlayerProfileManager::sUseRichSaveGames)
  297.         {
  298.                 CRichSaveGameHelper sgHelper(this);
  299.                 return sgHelper.DeleteSaveGame(pEntry, name);
  300.         }
  301.         else
  302.         {
  303.                 CCommonSaveGameHelper sgHelper(this);
  304.                 return sgHelper.DeleteSaveGame(pEntry, name);
  305.         }
  306. }
  307.  
  308. //------------------------------------------------------------------------
  309. bool CPlayerProfileImplFS::GetSaveGameThumbnail(SUserEntry* pEntry, const char* saveGameName, SThumbnail& thumbnail)
  310. {
  311.         if (CPlayerProfileManager::sUseRichSaveGames)
  312.         {
  313.                 CRichSaveGameHelper sgHelper(this);
  314.                 return sgHelper.GetSaveGameThumbnail(pEntry, saveGameName, thumbnail);
  315.         }
  316.         else
  317.         {
  318.                 CCommonSaveGameHelper sgHelper(this);
  319.                 return sgHelper.GetSaveGameThumbnail(pEntry, saveGameName, thumbnail);
  320.         }
  321. }
  322.  
  323. // Profile Implementation which stores most of the stuff ActionMaps/Attributes in separate files
  324.  
  325. //------------------------------------------------------------------------
  326. CPlayerProfileImplFSDir::CPlayerProfileImplFSDir() : m_pMgr(0)
  327. {
  328. }
  329.  
  330. //------------------------------------------------------------------------
  331. CPlayerProfileImplFSDir::~CPlayerProfileImplFSDir()
  332. {
  333. }
  334.  
  335. //------------------------------------------------------------------------
  336. bool CPlayerProfileImplFSDir::Initialize(CPlayerProfileManager* pMgr)
  337. {
  338.         m_pMgr = pMgr;
  339.         return true;
  340. }
  341.  
  342. //------------------------------------------------------------------------
  343. void CPlayerProfileImplFSDir::GetMemoryStatistics(ICrySizer* s)
  344. {
  345.         s->Add(*this);
  346. }
  347.  
  348. //------------------------------------------------------------------------
  349. void CPlayerProfileImplFSDir::InternalMakeFSPath(SUserEntry* pEntry, const char* profileName, string& outPath)
  350. {
  351.         if (pEntry)
  352.         {
  353.                 outPath = ("%USER%/Profiles/");
  354.         }
  355.         else
  356.         {
  357.                 // default profile always in game folder
  358.                 outPath = "Libs/Config/Profiles/";
  359.         }
  360.         if (profileName && *profileName)
  361.         {
  362.                 outPath.append(profileName);
  363.                 outPath.append("/");
  364.         }
  365. }
  366.  
  367. //------------------------------------------------------------------------
  368. void CPlayerProfileImplFSDir::InternalMakeFSSaveGamePath(SUserEntry* pEntry, const char* profileName, string& outPath, bool bNeedFolder)
  369. {
  370.         assert(pEntry != 0);
  371.         assert(profileName != 0);
  372.  
  373.         if (m_pMgr->IsSaveGameFolderShared())
  374.         {
  375.                 outPath = m_pMgr->GetSharedSaveGameFolder();
  376.                 outPath.append("/");
  377.                 if (!bNeedFolder)
  378.                 {
  379.                         outPath.append(profileName);
  380.                         outPath.append("_");
  381.                 }
  382.         }
  383.         else
  384.         {
  385.                 outPath = "%USER%/Profiles/";
  386.                 outPath.append(profileName);
  387.                 outPath.append("/SaveGames/");
  388.         }
  389. }
  390.  
  391. //------------------------------------------------------------------------
  392. bool CPlayerProfileImplFSDir::SaveProfile(SUserEntry* pEntry, CPlayerProfile* pProfile, const char* name, bool initialSave, int reason /* = ePR_All*/)
  393. {
  394.         // save the profile into a specific location
  395.  
  396.         // check if it's a valid filename
  397.         if (IsValidFilename(name) == false)
  398.                 return false;
  399.  
  400.         string path;
  401.         InternalMakeFSPath(pEntry, name, path);
  402.  
  403.         XmlNodeRef rootNode = GetISystem()->CreateXmlNode(PROFILE_ROOT_TAG);
  404.         rootNode->setAttr(PROFILE_NAME_TAG, name);
  405.  
  406.         time_t lastPlayed = NULL;
  407.         time(&lastPlayed);
  408.         rootNode->setAttr(PROFILE_LAST_PLAYED, lastPlayed);
  409.  
  410.         // save profile.xml
  411.         bool ok = SaveXMLFile(path + "profile.xml", rootNode);
  412.         if (ok)
  413.         {
  414.                 CSerializerXML serializer(rootNode, false);
  415.                 ok = pProfile->SerializeXML(&serializer);
  416.  
  417.                 // save action map and attributes into separate files
  418.                 if (ok)
  419.                 {
  420.                         ok &= SaveXMLFile(path + "attributes.xml", serializer.GetSection(CPlayerProfileManager::ePPS_Attribute));
  421.                         ok &= SaveXMLFile(path + "actionmaps.xml", serializer.GetSection(CPlayerProfileManager::ePPS_Actionmap));
  422.                 }
  423.         }
  424.         return ok;
  425. }
  426.  
  427. //------------------------------------------------------------------------
  428. bool CPlayerProfileImplFSDir::LoadProfile(SUserEntry* pEntry, CPlayerProfile* pProfile, const char* name)
  429. {
  430.         // load the profile from a specific location
  431.  
  432.         // XML for now
  433.         string path;
  434.         InternalMakeFSPath(pEntry, name, path);
  435.  
  436.         XmlNodeRef rootNode = GetISystem()->CreateXmlNode(PROFILE_ROOT_TAG);
  437.         CSerializerXML serializer(rootNode, true);
  438.         XmlNodeRef attrNode = LoadXMLFile(path + "attributes.xml");
  439.         XmlNodeRef actionNode = LoadXMLFile(path + "actionmaps.xml");
  440.         //      serializer.AddSection(attrNode);
  441.         //      serializer.AddSection(actionNode);
  442.         serializer.SetSection(CPlayerProfileManager::ePPS_Attribute, attrNode);
  443.         serializer.SetSection(CPlayerProfileManager::ePPS_Actionmap, actionNode);
  444.  
  445.         bool ok = pProfile->SerializeXML(&serializer);
  446.         return ok;
  447. }
  448.  
  449. //------------------------------------------------------------------------
  450. bool CPlayerProfileImplFSDir::LoginUser(SUserEntry* pEntry)
  451. {
  452.         // lookup stored profiles of the user (pEntry->userId) and fill in the pEntry->profileDesc
  453.         // vector
  454.         pEntry->profileDesc.clear();
  455.  
  456.         // scan directory for profiles
  457.  
  458.         string path;
  459.         InternalMakeFSPath(pEntry, "", path);  // no profile name -> only path
  460.  
  461.         std::multimap<time_t, SLocalProfileInfo> profiles;
  462.  
  463.         ICryPak* pCryPak = gEnv->pCryPak;
  464.         _finddata_t fd;
  465.  
  466.         path.TrimRight("/\\");
  467.         string search = path + "/*.*";
  468.  
  469.         IPlatformOS* pOS = GetISystem()->GetPlatformOS();
  470.         IPlatformOS::IFileFinderPtr fileFinder = pOS->GetFileFinder(IPlatformOS::Unknown_User);
  471.         intptr_t handle = fileFinder->FindFirst(search.c_str(), &fd);
  472.         if (handle != -1)
  473.         {
  474.                 do
  475.                 {
  476.                         if (strcmp(fd.name, ".") == 0 || strcmp(fd.name, "..") == 0)
  477.                                 continue;
  478.  
  479.                         if (fd.attrib & _A_SUBDIR)
  480.                         {
  481.                                 // profile name = folder name
  482.                                 // but make sure there is a profile.xml in it
  483.                                 string filename = path + "/" + fd.name;
  484.                                 filename += "/";
  485.                                 filename += "profile.xml";
  486.                                 XmlNodeRef rootNode = LoadXMLFile(filename.c_str());
  487.  
  488.                                 // see if the root tag is o.k.
  489.                                 if (rootNode && stricmp(rootNode->getTag(), PROFILE_ROOT_TAG) == 0)
  490.                                 {
  491.                                         string profileName = fd.name;
  492.                                         if (rootNode->haveAttr(PROFILE_NAME_TAG))
  493.                                         {
  494.                                                 const char* profileHumanName = rootNode->getAttr(PROFILE_NAME_TAG);
  495.                                                 if (profileHumanName != 0 && stricmp(profileHumanName, profileName) == 0)
  496.                                                 {
  497.                                                         profileName = profileHumanName;
  498.                                                 }
  499.                                         }
  500.                                         time_t time = NULL;
  501.                                         if (rootNode->haveAttr(PROFILE_LAST_PLAYED))
  502.                                         {
  503.                                                 rootNode->getAttr(PROFILE_LAST_PLAYED, time);
  504.                                         }
  505.                                         SLocalProfileInfo info(profileName);
  506.                                         info.SetLastLoginTime(time);
  507.                                         profiles.insert(std::make_pair(time, info));
  508.                                 }
  509.                                 else
  510.                                 {
  511.                                         GameWarning("CPlayerProfileImplFSDir::LoginUser: Profile '%s' of User '%s' seems to exists but is invalid (File '%s). Skipped", fd.name, pEntry->userId.c_str(), filename.c_str());
  512.                                 }
  513.                         }
  514.                 }
  515.                 while (fileFinder->FindNext(handle, &fd) >= 0);
  516.  
  517.                 fileFinder->FindClose(handle);
  518.         }
  519.  
  520.         // Insert in most recently played order
  521.         std::multimap<time_t, SLocalProfileInfo>::const_reverse_iterator itend = profiles.rend();
  522.         for (std::multimap<time_t, SLocalProfileInfo>::const_reverse_iterator it = profiles.rbegin(); it != itend; ++it)
  523.                 pEntry->profileDesc.push_back(it->second);
  524.  
  525.         return true;
  526. }
  527.  
  528. //------------------------------------------------------------------------
  529. bool CPlayerProfileImplFSDir::DeleteProfile(SUserEntry* pEntry, const char* name)
  530. {
  531.         string path;
  532.         InternalMakeFSPath(pEntry, name, path);  // no profile name -> only path
  533.         bool bOK = gEnv->pCryPak->RemoveDir(path.c_str(), true);
  534.         // in case the savegame folder is shared, we have to delete the savegames from the shared folder
  535.         if (bOK && m_pMgr->IsSaveGameFolderShared())
  536.         {
  537.                 CPlayerProfileManager::TSaveGameInfoVec saveGameInfoVec;
  538.                 if (GetSaveGames(pEntry, saveGameInfoVec, name)) // provide alternate profileName, because pEntry->pCurrentProfile points to the active profile
  539.                 {
  540.                         CPlayerProfileManager::TSaveGameInfoVec::iterator iter = saveGameInfoVec.begin();
  541.                         CPlayerProfileManager::TSaveGameInfoVec::iterator iterEnd = saveGameInfoVec.end();
  542.                         while (iter != iterEnd)
  543.                         {
  544.                                 DeleteSaveGame(pEntry, iter->name);
  545.                                 ++iter;
  546.                         }
  547.                 }
  548.         }
  549.         return bOK;
  550. }
  551.  
  552. //------------------------------------------------------------------------
  553. bool CPlayerProfileImplFSDir::RenameProfile(SUserEntry* pEntry, const char* newName)
  554. {
  555.         // TODO: only rename in the filesystem. for now save new and delete old
  556.         const char* oldName = pEntry->pCurrentProfile->GetName();
  557.         bool ok = SaveProfile(pEntry, pEntry->pCurrentProfile, newName);
  558.         if (!ok)
  559.                 return false;
  560.  
  561.         // move the save games
  562.         if (CPlayerProfileManager::sUseRichSaveGames)
  563.         {
  564.                 CRichSaveGameHelper sgHelper(this);
  565.                 sgHelper.MoveSaveGames(pEntry, oldName, newName);
  566.         }
  567.         else
  568.         {
  569.                 CCommonSaveGameHelper sgHelper(this);
  570.                 sgHelper.MoveSaveGames(pEntry, oldName, newName);
  571.         }
  572.  
  573.         DeleteProfile(pEntry, oldName);
  574.         return true;
  575. }
  576.  
  577. //------------------------------------------------------------------------
  578. bool CPlayerProfileImplFSDir::LogoutUser(SUserEntry* pEntry)
  579. {
  580.         return true;
  581. }
  582.  
  583. //------------------------------------------------------------------------
  584. bool CPlayerProfileImplFSDir::GetSaveGames(SUserEntry* pEntry, CPlayerProfileManager::TSaveGameInfoVec& outVec, const char* altProfileName)
  585. {
  586.         if (CPlayerProfileManager::sUseRichSaveGames)
  587.         {
  588.                 CRichSaveGameHelper sgHelper(this);
  589.                 return sgHelper.GetSaveGames(pEntry, outVec, altProfileName);
  590.         }
  591.         else
  592.         {
  593.                 CCommonSaveGameHelper sgHelper(this);
  594.                 return sgHelper.GetSaveGames(pEntry, outVec, altProfileName);
  595.         }
  596. }
  597.  
  598. //------------------------------------------------------------------------
  599. ISaveGame* CPlayerProfileImplFSDir::CreateSaveGame(SUserEntry* pEntry)
  600. {
  601.         if (CPlayerProfileManager::sUseRichSaveGames)
  602.         {
  603.                 CRichSaveGameHelper sgHelper(this);
  604.                 return sgHelper.CreateSaveGame(pEntry);
  605.         }
  606.         else
  607.         {
  608.                 CCommonSaveGameHelper sgHelper(this);
  609.                 return sgHelper.CreateSaveGame(pEntry);
  610.         }
  611. }
  612.  
  613. //------------------------------------------------------------------------
  614. ILoadGame* CPlayerProfileImplFSDir::CreateLoadGame(SUserEntry* pEntry)
  615. {
  616.         if (CPlayerProfileManager::sUseRichSaveGames)
  617.         {
  618.                 CRichSaveGameHelper sgHelper(this);
  619.                 return sgHelper.CreateLoadGame(pEntry);
  620.         }
  621.         else
  622.         {
  623.                 CCommonSaveGameHelper sgHelper(this);
  624.                 return sgHelper.CreateLoadGame(pEntry);
  625.         }
  626. }
  627.  
  628. //------------------------------------------------------------------------
  629. bool CPlayerProfileImplFSDir::DeleteSaveGame(SUserEntry* pEntry, const char* name)
  630. {
  631.         if (CPlayerProfileManager::sUseRichSaveGames)
  632.         {
  633.                 CRichSaveGameHelper sgHelper(this);
  634.                 return sgHelper.DeleteSaveGame(pEntry, name);
  635.         }
  636.         else
  637.         {
  638.                 CCommonSaveGameHelper sgHelper(this);
  639.                 return sgHelper.DeleteSaveGame(pEntry, name);
  640.         }
  641. }
  642.  
  643. //------------------------------------------------------------------------
  644. bool CPlayerProfileImplFSDir::GetSaveGameThumbnail(SUserEntry* pEntry, const char* saveGameName, SThumbnail& thumbnail)
  645. {
  646.         if (CPlayerProfileManager::sUseRichSaveGames)
  647.         {
  648.                 CRichSaveGameHelper sgHelper(this);
  649.                 return sgHelper.GetSaveGameThumbnail(pEntry, saveGameName, thumbnail);
  650.         }
  651.         else
  652.         {
  653.                 CCommonSaveGameHelper sgHelper(this);
  654.                 return sgHelper.GetSaveGameThumbnail(pEntry, saveGameName, thumbnail);
  655.         }
  656. }
  657.  
  658. ILevelRotationFile* CPlayerProfileImplFSDir::GetLevelRotationFile(SUserEntry* pEntry, const char* name)
  659. {
  660.         CCommonSaveGameHelper sgHelper(this);
  661.         return sgHelper.GetLevelRotationFile(pEntry, name);
  662. }
  663.  
  664. //------------------------------------------------------------------------
  665. // COMMON SaveGameHelper used by both CPlayerProfileImplFSDir and CPlayerProfileImplFS
  666. //------------------------------------------------------------------------
  667.  
  668. bool CCommonSaveGameHelper::GetSaveGameThumbnail(CPlayerProfileManager::SUserEntry* pEntry, const char* saveGameName, CPlayerProfileManager::SThumbnail& thumbnail)
  669. {
  670.         assert(pEntry->pCurrentProfile != 0);
  671.         if (pEntry->pCurrentProfile == 0)
  672.         {
  673.                 GameWarning("CCommonSaveGameHelper:GetSaveGameThumbnail: Entry for user '%s' has no current profile", pEntry->userId.c_str());
  674.                 return false;
  675.         }
  676.         const char* name = saveGameName;
  677.         string filename;
  678.         m_pImpl->InternalMakeFSSaveGamePath(pEntry, pEntry->pCurrentProfile->GetName(), filename, true);
  679.         string strippedName = PathUtil::ReplaceExtension(PathUtil::GetFile(name), ".bmp");
  680.         filename.append(strippedName);
  681.  
  682.         int width = 0;
  683.         int height = 0;
  684.         int depth = 0;
  685.         bool bSuccess = BMPHelper::LoadBMP(filename, 0, width, height, depth);
  686.         if (bSuccess)
  687.         {
  688.                 thumbnail.data.resize(width * height * depth);
  689.                 bSuccess = BMPHelper::LoadBMP(filename, thumbnail.data.begin(), width, height, depth);
  690.                 if (bSuccess)
  691.                 {
  692.                         thumbnail.height = height;
  693.                         thumbnail.width = width;
  694.                         thumbnail.depth = depth;
  695.                 }
  696.         }
  697.         if (!bSuccess)
  698.                 thumbnail.ReleaseData();
  699.         return bSuccess;
  700. }
  701.  
  702. bool CCommonSaveGameHelper::FetchMetaData(XmlNodeRef& root, CPlayerProfileManager::SSaveGameMetaData& metaData)
  703. {
  704.         // TODO: use CXmlLoadGame for this
  705.         XmlNodeRef metaDataNode = root;
  706.         if (metaDataNode->isTag("Metadata") == false)
  707.                 metaDataNode = root->findChild("Metadata");
  708.         if (metaDataNode == 0)
  709.                 return false;
  710.         bool ok = true;
  711.         ok &= GetAttr(metaDataNode, "level", metaData.levelName);
  712.         ok &= GetAttr(metaDataNode, "gameRules", metaData.gameRules);
  713.         ok &= GetAttr(metaDataNode, "version", metaData.fileVersion);
  714.         ok &= GetAttr(metaDataNode, "build", metaData.buildVersion);
  715.         ok &= GetTimeAttr(metaDataNode, "saveTime", metaData.saveTime);
  716.         metaData.loadTime = metaData.saveTime;
  717.         metaData.xmlMetaDataNode = metaDataNode;
  718.         return ok;
  719. }
  720.  
  721. bool CCommonSaveGameHelper::GetSaveGames(CPlayerProfileManager::SUserEntry* pEntry, CPlayerProfileManager::TSaveGameInfoVec& outVec, const char* altProfileName = "")
  722. {
  723.         // Scan savegames directory for XML files
  724.         // we scan only for save game meta information
  725.         string path;
  726.         string profileName = (altProfileName && *altProfileName) ? altProfileName : pEntry->pCurrentProfile->GetName();
  727.         m_pImpl->InternalMakeFSSaveGamePath(pEntry, profileName, path, true);
  728.  
  729.         const bool bNeedProfilePrefix = m_pImpl->GetManager()->IsSaveGameFolderShared();
  730.         string profilePrefix = profileName;
  731.         profilePrefix += '_';
  732.         size_t profilePrefixLen = profilePrefix.length();
  733.  
  734.         path.TrimRight("/\\");
  735.         string search;
  736.         search.Format("%s/*%s", path.c_str(), CRY_SAVEGAME_FILE_EXT);
  737.  
  738.         IPlatformOS* os = GetISystem()->GetPlatformOS();
  739.         IPlatformOS::IFileFinderPtr fileFinder = os->GetFileFinder(IPlatformOS::Unknown_User);
  740.         _finddata_t fd;
  741.         intptr_t handle = fileFinder->FindFirst(search.c_str(), &fd);
  742.         if (handle != -1)
  743.         {
  744.                 CPlayerProfileManager::SSaveGameInfo sgInfo;
  745.                 do
  746.                 {
  747.                         if (strcmp(fd.name, ".") == 0 || strcmp(fd.name, "..") == 0)
  748.                                 continue;
  749.  
  750.                         if (bNeedProfilePrefix)
  751.                         {
  752.                                 if (strnicmp(profilePrefix, fd.name, profilePrefixLen) != 0)
  753.                                         continue;
  754.                         }
  755.  
  756.                         sgInfo.name = fd.name;
  757.                         if (bNeedProfilePrefix) // skip profile_ prefix (we made sure this is valid by comparism above)
  758.                                 sgInfo.humanName = fd.name + profilePrefixLen;
  759.                         else
  760.                                 sgInfo.humanName = fd.name;
  761.                         PathUtil::RemoveExtension(sgInfo.humanName);
  762.                         sgInfo.description = "no description";
  763.  
  764.                         bool ok = false;
  765.  
  766.                         // filename construction
  767.                         string metaFilename = path;
  768.                         metaFilename.append("/");
  769.                         metaFilename.append(fd.name);
  770.                         metaFilename = PathUtil::ReplaceExtension(metaFilename, ".meta");
  771.                         XmlNodeRef rootNode = LoadXMLFile(metaFilename.c_str());
  772.                         // see if the root tag is o.k.
  773.                         if (rootNode && stricmp(rootNode->getTag(), "Metadata") == 0)
  774.                         {
  775.                                 // get meta data
  776.                                 ok = FetchMetaData(rootNode, sgInfo.metaData);
  777.                         }
  778.                         else
  779.                         {
  780.                                 // when there is no meta information, we currently reject the savegame
  781.                                 //ok = true; // un-comment this, if you want to accept savegames without meta
  782.                         }
  783.                         // Use the file modified time for the load time as we touch the saves when they are used to keep most recent checkpoint
  784.                         sgInfo.metaData.loadTime = static_cast<time_t>(fd.time_write);
  785.  
  786.                         if (ok)
  787.                         {
  788.                                 outVec.push_back(sgInfo);
  789.                         }
  790.                         else
  791.                         {
  792.                                 GameWarning("CPlayerProfileImplFS::GetSaveGames: SaveGame '%s' of user '%s' is invalid", fd.name, pEntry->userId.c_str());
  793.                         }
  794.  
  795.                 }
  796.                 while (fileFinder->FindNext(handle, &fd) >= 0);
  797.  
  798.                 fileFinder->FindClose(handle);
  799.         }
  800.  
  801.         return true;
  802. }
  803.  
  804. //////////////////////////////////////////////////////////////////////////
  805.  
  806. class CXMLSaveGameFSDir : public CXmlSaveGame
  807. {
  808.         typedef CXmlSaveGame inherited;
  809.  
  810. public:
  811.         CXMLSaveGameFSDir(ICommonProfileImpl* pImpl, CPlayerProfileImplFSDir::SUserEntry* pEntry)
  812.         {
  813.                 m_pProfileImpl = pImpl;
  814.                 m_pEntry = pEntry;
  815.                 assert(m_pProfileImpl != 0);
  816.                 assert(m_pEntry != 0);
  817.         }
  818.  
  819.         // ILoadGame
  820.         virtual bool Init(const char* name)
  821.         {
  822.                 assert(m_pEntry->pCurrentProfile != 0);
  823.                 if (m_pEntry->pCurrentProfile == 0)
  824.                 {
  825.                         GameWarning("CXMLSaveGameFSDir: Entry for user '%s' has no current profile", m_pEntry->userId.c_str());
  826.                         return false;
  827.                 }
  828.                 string path;
  829.                 m_pProfileImpl->InternalMakeFSSaveGamePath(m_pEntry, m_pEntry->pCurrentProfile->GetName(), path, false);
  830.                 // make directory or use the SaveXMLFile helper function
  831.                 // CryCreateDirectory(...)
  832.                 string strippedName = PathUtil::GetFile(name);
  833.                 path.append(strippedName);
  834.                 return inherited::Init(path.c_str());
  835.         }
  836.  
  837.         virtual bool Write(const char* filename, XmlNodeRef data)
  838.         {
  839.                 const string fname(filename);
  840.                 bool bOK = inherited::Write(fname, data);
  841.                 if (bOK)
  842.                         bOK = WriteAdditionalData(filename, data);
  843.  
  844.                 return bOK;
  845.         }
  846.  
  847.         bool WriteAdditionalData(const char* filename, XmlNodeRef data)
  848.         {
  849.                 bool bOK = true;
  850.                 // we save the meta information also in a separate file
  851.                 XmlNodeRef meta = data->findChild("Metadata");
  852.                 const string fname(filename);
  853.                 if (meta)
  854.                 {
  855.                         const string metaPath = PathUtil::ReplaceExtension(fname, ".meta");
  856.                         bOK = ::SaveXMLFile(metaPath, meta);
  857.                 }
  858.                 if (m_thumbnail.data.size() > 0)
  859.                 {
  860.                         const string bmpPath = PathUtil::ReplaceExtension(fname, ".bmp");
  861.                         BMPHelper::SaveBMP(bmpPath, m_thumbnail.data.begin(), m_thumbnail.width, m_thumbnail.height, m_thumbnail.depth, false);
  862.                 }
  863.                 return bOK;
  864.         }
  865.  
  866.         virtual uint8* SetThumbnail(const uint8* imageData, int width, int height, int depth)
  867.         {
  868.                 m_thumbnail.width = width;
  869.                 m_thumbnail.height = height;
  870.                 m_thumbnail.depth = depth;
  871.                 size_t size = width * height * depth;
  872.                 m_thumbnail.data.resize(size);
  873.                 if (imageData)
  874.                         memcpy(m_thumbnail.data.begin(), imageData, size);
  875.                 else
  876.                 {
  877.                         if (m_thumbnail.depth == 3)
  878.                         {
  879.                                 uint8* p = (uint8*) m_thumbnail.data.begin();
  880.                                 size_t n = size;
  881.                                 while (n)
  882.                                 {
  883.                                         *p++ = 0x00; // B
  884.                                         *p++ = 0x00; // G
  885.                                         *p++ = 0x00; // R
  886.                                         n -= 3;
  887.                                 }
  888.                         }
  889.                         else if (m_thumbnail.depth == 4)
  890.                         {
  891.                                 const uint32 col = RGBA8(0x00, 0x00, 0x00, 0x00); // alpha see through
  892.                                 uint32* p = (uint32*) m_thumbnail.data.begin();
  893.                                 size_t n = size >> 2;
  894.                                 while (n--)
  895.                                         *p++ = col;
  896.                         }
  897.                         else
  898.                         {
  899.                                 memset(m_thumbnail.data.begin(), 0, size);
  900.                         }
  901.                 }
  902.                 return m_thumbnail.data.begin();
  903.         }
  904.  
  905.         virtual bool SetThumbnailFromBMP(const char* filename)
  906.         {
  907.                 int width = 0;
  908.                 int height = 0;
  909.                 int depth = 0;
  910.                 bool bSuccess = BMPHelper::LoadBMP(filename, 0, width, height, depth, true);
  911.                 if (bSuccess)
  912.                 {
  913.                         CPlayerProfileManager::SThumbnail thumbnail;
  914.                         thumbnail.data.resize(width * height * depth);
  915.                         bSuccess = BMPHelper::LoadBMP(filename, thumbnail.data.begin(), width, height, depth, true);
  916.                         if (bSuccess)
  917.                         {
  918.                                 SetThumbnail(thumbnail.data.begin(), width, height, depth);
  919.                         }
  920.                 }
  921.                 return bSuccess;
  922.         }
  923.  
  924.         ICommonProfileImpl*                  m_pProfileImpl;
  925.         CPlayerProfileImplFSDir::SUserEntry* m_pEntry;
  926.         CPlayerProfileImplFSDir::SThumbnail  m_thumbnail;
  927. };
  928.  
  929. //////////////////////////////////////////////////////////////////////////
  930.  
  931. class CXMLCPBinSaveGameFSDir : public CXMLSaveGameFSDir
  932. {
  933.         typedef CXMLSaveGameFSDir inherited;
  934.  
  935.         class CSerializeCtx : public _reference_target_t
  936.         {
  937.         public:
  938.                 CSerializeCtx(XMLCPB::CNodeLiveWriterRef node, XMLCPB::CWriterInterface& binWriter)
  939.                         : m_pWriterXMLCPBin(std::unique_ptr<CSerializeWriterXMLCPBin>(new CSerializeWriterXMLCPBin(node, binWriter)))
  940.                         , m_pWriter(std::unique_ptr<ISerialize>(new CSimpleSerializeWithDefaults<CSerializeWriterXMLCPBin>(*m_pWriterXMLCPBin)))
  941.                 {
  942.                 }
  943.  
  944.                 TSerialize GetTSerialize() { return TSerialize(m_pWriter.get()); }
  945.  
  946.         private:
  947.                 std::unique_ptr<CSerializeWriterXMLCPBin> m_pWriterXMLCPBin;
  948.                 std::unique_ptr<ISerialize>               m_pWriter;
  949.         };
  950.  
  951. public:
  952.         CXMLCPBinSaveGameFSDir(ICommonProfileImpl* pImpl, CPlayerProfileImplFSDir::SUserEntry* pEntry) : inherited(pImpl, pEntry)
  953.         {
  954.         }
  955.  
  956.         virtual bool Init(const char* name)
  957.         {
  958.                 bool ok = inherited::Init(name);
  959.                 if (ok)
  960.                         m_binXmlWriter.Init("SaveGame", GetFileName());
  961.                 return ok;
  962.         }
  963.  
  964.         // adds a node with only attributes to the root
  965.         void AddSimpleXmlToRoot(XmlNodeRef node)
  966.         {
  967.                 XMLCPB::CNodeLiveWriterRef binNode = m_binXmlWriter.GetRoot();
  968.                 assert(binNode.IsValid());
  969.                 assert(node->getChildCount() == 0);
  970.                 binNode = binNode->AddChildNode(node->getTag());
  971.                 for (int i = 0; i < node->getNumAttributes(); ++i)
  972.                 {
  973.                         const char* pKey;
  974.                         const char* pVal;
  975.                         node->getAttributeByIndex(i, &pKey, &pVal);
  976.                         binNode->AddAttr(pKey, pVal);
  977.                 }
  978.                 binNode->Done();
  979.         }
  980.  
  981.         virtual bool Write(const char* filename, XmlNodeRef data)
  982.         {
  983.                 bool bResult = false;
  984.  
  985.                 AddSimpleXmlToRoot(GetMetadataXmlNode());
  986.  
  987.                 if (m_binXmlWriter.FinishWritingFile())
  988.                 {
  989.                         bResult = inherited::WriteAdditionalData(filename, data);
  990.                 }
  991.  
  992.                 return bResult;
  993.         }
  994.  
  995.         TSerialize AddSection(const char* section)
  996.         {
  997.                 XMLCPB::CNodeLiveWriterRef nodeRef = m_binXmlWriter.GetRoot()->AddChildNode(section);
  998.                 _smart_ptr<CSerializeCtx> pCtx = new CSerializeCtx(nodeRef, m_binXmlWriter);
  999.                 m_sections.push_back(pCtx);
  1000.                 return pCtx->GetTSerialize();
  1001.         }
  1002.  
  1003.         XMLCPB::CWriterInterface               m_binXmlWriter; // XMLCPB -> Compressed Binary XML  TODO: change all those XMLCPB names...
  1004.         std::vector<_smart_ptr<CSerializeCtx>> m_sections;
  1005. };
  1006.  
  1007. ISaveGame* CCommonSaveGameHelper::CreateSaveGame(CPlayerProfileManager::SUserEntry* pEntry)
  1008. {
  1009.         bool useXMLCPBin = CCryActionCVars::Get().g_useXMLCPBinForSaveLoad == 1;
  1010.  
  1011.         if (useXMLCPBin)
  1012.                 return new CXMLCPBinSaveGameFSDir(m_pImpl, pEntry);
  1013.         else
  1014.                 return new CXMLSaveGameFSDir(m_pImpl, pEntry);
  1015. }
  1016.  
  1017. //////////////////////////////////////////////////////////////////////////
  1018.  
  1019. class CXMLLoadGameFSDir : public CXmlLoadGame
  1020. {
  1021.         typedef CXmlLoadGame inherited;
  1022.  
  1023. public:
  1024.         CXMLLoadGameFSDir(ICommonProfileImpl* pImpl, CPlayerProfileImplFSDir::SUserEntry* pEntry)
  1025.         {
  1026.                 m_pImpl = pImpl;
  1027.                 m_pEntry = pEntry;
  1028.                 assert(m_pImpl != 0);
  1029.                 assert(m_pEntry != 0);
  1030.         }
  1031.  
  1032.         // ILoadGame
  1033.         virtual bool Init(const char* name)
  1034.         {
  1035.                 bool ok = ObtainFinalFileName(name);
  1036.                 if (ok)
  1037.                         ok = inherited::Init(m_filename.c_str());
  1038.  
  1039.                 return ok;
  1040.         }
  1041.  
  1042.         bool ObtainFinalFileName(const char* name)
  1043.         {
  1044.                 assert(m_pEntry->pCurrentProfile != 0);
  1045.                 if (m_pEntry->pCurrentProfile == 0)
  1046.                 {
  1047.                         GameWarning("CXMLLoadGameFSDir: Entry for user '%s' has no current profile", m_pEntry->userId.c_str());
  1048.                         return false;
  1049.                 }
  1050.  
  1051.                 // figure out, if 'name' is an absolute path or a profile-relative path
  1052.                 if (gEnv->pCryPak->IsAbsPath(name) == false)
  1053.                 {
  1054.                         // no full path, assume 'name' is local to profile directory
  1055.                         bool bNeedFolder = true;
  1056.                         if (m_pImpl->GetManager()->IsSaveGameFolderShared())
  1057.                         {
  1058.                                 // if the savegame's name doesn't start with a profile_ prefix
  1059.                                 // add one (for quickload)
  1060.                                 string profilePrefix = m_pEntry->pCurrentProfile->GetName();
  1061.                                 profilePrefix.append("_");
  1062.                                 size_t profilePrefixLen = profilePrefix.length();
  1063.                                 if (strnicmp(name, profilePrefix, profilePrefixLen) != 0)
  1064.                                         bNeedFolder = false;
  1065.                         }
  1066.                         m_pImpl->InternalMakeFSSaveGamePath(m_pEntry, m_pEntry->pCurrentProfile->GetName(), m_filename, bNeedFolder);
  1067.                         string strippedName = PathUtil::GetFile(name);
  1068.                         m_filename.append(strippedName);
  1069.                 }
  1070.                 else
  1071.                 {
  1072.                         // it's an abs path, assign it
  1073.                         m_filename.assign(name);
  1074.                 }
  1075.                 return true;
  1076.         }
  1077.  
  1078.         string                               m_filename;
  1079.         ICommonProfileImpl*                  m_pImpl;
  1080.         CPlayerProfileImplFSDir::SUserEntry* m_pEntry;
  1081. };
  1082.  
  1083. //////////////////////////////////////////////////////////////////////////
  1084.  
  1085. class CXMLCPBinLoadGameFSDir : public CXMLLoadGameFSDir
  1086. {
  1087.         typedef CXMLLoadGameFSDir inherited;
  1088.  
  1089.         class CSerializeCtx : public _reference_target_t
  1090.         {
  1091.         public:
  1092.                 CSerializeCtx(XMLCPB::CNodeLiveReaderRef node, XMLCPB::CReaderInterface& binReader)
  1093.                         : m_pReaderXMLCPBin(std::unique_ptr<CSerializeReaderXMLCPBin>(new CSerializeReaderXMLCPBin(node, binReader)))
  1094.                         , m_pReader(std::unique_ptr<ISerialize>(new CSimpleSerializeWithDefaults<CSerializeReaderXMLCPBin>(*m_pReaderXMLCPBin)))
  1095.                 {}
  1096.  
  1097.                 TSerialize GetTSerialize() { return TSerialize(m_pReader.get()); }
  1098.  
  1099.         private:
  1100.                 std::unique_ptr<CSerializeReaderXMLCPBin> m_pReaderXMLCPBin;
  1101.                 std::unique_ptr<ISerialize>               m_pReader;
  1102.         };
  1103.  
  1104. public:
  1105.         CXMLCPBinLoadGameFSDir(ICommonProfileImpl* pImpl, CPlayerProfileImplFSDir::SUserEntry* pEntry)
  1106.                 : inherited(pImpl, pEntry)
  1107.                 , m_pHeap(XMLCPB::CReader::CreateHeap())
  1108.                 , m_binXmlReader(m_pHeap)
  1109.                 , m_metadataNode(m_binXmlReader.CreateNodeRef())
  1110.         {
  1111.         }
  1112.  
  1113.         virtual bool Init(const char* name)
  1114.         {
  1115.                 bool ok = ObtainFinalFileName(name);
  1116.  
  1117.                 if (ok)
  1118.                 {
  1119.                         ok = m_binXmlReader.ReadBinaryFile(m_filename.c_str());
  1120.                         if (ok)
  1121.                         {
  1122. #ifdef XMLCPB_DEBUGUTILS
  1123.                                 if (CCryActionCVars::Get().g_XMLCPBGenerateXmlDebugFiles == 1)
  1124.                                         XMLCPB::CDebugUtils::DumpToXmlFile(m_binXmlReader.GetRoot(), "LastBinaryLoaded.xml");
  1125. #endif
  1126.                                 m_metadataNode = m_binXmlReader.GetRoot()->GetChildNode("Metadata");
  1127.                         }
  1128.                 }
  1129.  
  1130.                 return ok;
  1131.         }
  1132.  
  1133.         IGeneralMemoryHeap* GetHeap()
  1134.         {
  1135.                 return m_pHeap;
  1136.         }
  1137.  
  1138.         const char* GetMetadata(const char* pTag)
  1139.         {
  1140.                 const char* pVal = NULL;
  1141.                 m_metadataNode->ReadAttr(pTag, pVal);
  1142.                 return pVal;
  1143.         }
  1144.  
  1145.         bool GetMetadata(const char* pTag, int& value)
  1146.         {
  1147.                 return m_metadataNode->ReadAttr(pTag, value);
  1148.         }
  1149.  
  1150.         bool HaveMetadata(const char* pTag)
  1151.         {
  1152.                 return m_metadataNode->HaveAttr(pTag);
  1153.         }
  1154.  
  1155.         std::unique_ptr<TSerialize> GetSection(const char* pSection)
  1156.         {
  1157.                 XMLCPB::CNodeLiveReaderRef node = m_binXmlReader.GetRoot()->GetChildNode(pSection);
  1158.                 if (!node.IsValid())
  1159.                         return std::unique_ptr<TSerialize>();
  1160.                 _smart_ptr<CSerializeCtx> pCtx = new CSerializeCtx(node, m_binXmlReader);
  1161.                 m_sections.push_back(pCtx);
  1162.                 return std::unique_ptr<TSerialize>(new TSerialize(pCtx->GetTSerialize()));
  1163.         }
  1164.  
  1165.         bool HaveSection(const char* pSection)
  1166.         {
  1167.                 return m_binXmlReader.GetRoot()->GetChildNode(pSection).IsValid();
  1168.         }
  1169.  
  1170.         const char* GetFileName() const
  1171.         {
  1172.                 return m_filename.c_str();
  1173.         }
  1174.  
  1175.         _smart_ptr<IGeneralMemoryHeap>         m_pHeap;
  1176.         XMLCPB::CReaderInterface               m_binXmlReader; // XMLCPB -> Compressed Binary XML  TODO: change all those XMLCPB names...
  1177.         std::vector<_smart_ptr<CSerializeCtx>> m_sections;
  1178.         XMLCPB::CNodeLiveReaderRef             m_metadataNode;
  1179. };
  1180.  
  1181. ILoadGame* CCommonSaveGameHelper::CreateLoadGame(CPlayerProfileManager::SUserEntry* pEntry)
  1182. {
  1183.         bool useXMLCPBin = CCryActionCVars::Get().g_useXMLCPBinForSaveLoad == 1;
  1184.  
  1185.         if (useXMLCPBin)
  1186.                 return new CXMLCPBinLoadGameFSDir(m_pImpl, pEntry);
  1187.         else
  1188.                 return new CXMLLoadGameFSDir(m_pImpl, pEntry);
  1189. }
  1190.  
  1191. bool CCommonSaveGameHelper::DeleteSaveGame(CPlayerProfileManager::SUserEntry* pEntry, const char* name)
  1192. {
  1193.         string filename;
  1194.         m_pImpl->InternalMakeFSSaveGamePath(pEntry, pEntry->pCurrentProfile->GetName(), filename, true);
  1195.         string strippedName = PathUtil::GetFile(name);
  1196.         filename.append(strippedName);
  1197.         bool ok = gEnv->pCryPak->RemoveFile(filename.c_str()); // normal savegame
  1198.         filename = PathUtil::ReplaceExtension(filename, ".meta");
  1199.         gEnv->pCryPak->RemoveFile(filename.c_str()); // meta data
  1200.         filename = PathUtil::ReplaceExtension(filename, ".bmp");
  1201.         gEnv->pCryPak->RemoveFile(filename.c_str()); // thumbnail
  1202.         return ok;
  1203. }
  1204.  
  1205. bool CCommonSaveGameHelper::MoveSaveGames(CPlayerProfileManager::SUserEntry* pEntry, const char* oldProfileName, const char* newProfileName)
  1206. {
  1207.         // move savegames or, if savegame folder is shared, rename them
  1208.         string oldSaveGamesPath;
  1209.         string newSaveGamesPath;
  1210.         m_pImpl->InternalMakeFSSaveGamePath(pEntry, oldProfileName, oldSaveGamesPath, true);
  1211.         m_pImpl->InternalMakeFSSaveGamePath(pEntry, newProfileName, newSaveGamesPath, true);
  1212.  
  1213.         CPlayerProfileManager* pMgr = m_pImpl->GetManager();
  1214.         if (pMgr->IsSaveGameFolderShared() == false)
  1215.         {
  1216.                 // move complete folder
  1217.                 pMgr->MoveFileHelper(oldSaveGamesPath, newSaveGamesPath);
  1218.         }
  1219.         else
  1220.         {
  1221.                 // save game folder is shared, move file by file
  1222.                 CPlayerProfileManager::TSaveGameInfoVec saveGameInfoVec;
  1223.                 if (GetSaveGames(pEntry, saveGameInfoVec, oldProfileName))
  1224.                 {
  1225.                         CPlayerProfileManager::TSaveGameInfoVec::iterator iter = saveGameInfoVec.begin();
  1226.                         CPlayerProfileManager::TSaveGameInfoVec::iterator iterEnd = saveGameInfoVec.end();
  1227.                         string oldPrefix = oldProfileName;
  1228.                         oldPrefix += "_";
  1229.                         size_t oldPrefixLen = oldPrefix.length();
  1230.                         string newPrefix = newProfileName;
  1231.                         newPrefix += "_";
  1232.                         while (iter != iterEnd)
  1233.                         {
  1234.                                 const string& oldSGName = iter->name;
  1235.                                 // begins with old profile's prefix?
  1236.                                 if (strnicmp(oldSGName, oldPrefix, oldPrefixLen) == 0)
  1237.                                 {
  1238.                                         string newSGName = newPrefix;
  1239.                                         newSGName.append(oldSGName, oldPrefixLen, oldSGName.length() - oldPrefixLen);
  1240.                                         string oldPath = oldSaveGamesPath + oldSGName;
  1241.                                         string newPath = newSaveGamesPath + newSGName;
  1242.                                         pMgr->MoveFileHelper(oldPath, newPath); // savegame
  1243.  
  1244.                                         oldPath = PathUtil::ReplaceExtension(oldPath, ".meta");
  1245.                                         newPath = PathUtil::ReplaceExtension(newPath, ".meta");
  1246.                                         pMgr->MoveFileHelper(oldPath, newPath); // meta
  1247.  
  1248.                                         oldPath = PathUtil::ReplaceExtension(oldPath, ".bmp");
  1249.                                         newPath = PathUtil::ReplaceExtension(newPath, ".bmp");
  1250.                                         pMgr->MoveFileHelper(oldPath, newPath); // thumbnail
  1251.                                 }
  1252.                                 ++iter;
  1253.                         }
  1254.                 }
  1255.         }
  1256.         return true;
  1257. }
  1258.  
  1259. class CLevelRotationFile : public ILevelRotationFile
  1260. {
  1261. public:
  1262.         CLevelRotationFile(const string& fname) : m_filename(fname)
  1263.         {}
  1264.         ~CLevelRotationFile()
  1265.         {}
  1266.  
  1267.         virtual bool Save(XmlNodeRef r)
  1268.         {
  1269.                 return r->saveToFile(m_filename, 256 * 1024);
  1270.         }
  1271.  
  1272.         virtual XmlNodeRef Load()
  1273.         {
  1274.                 if (FILE* f = gEnv->pCryPak->FOpen(m_filename, "rb"))
  1275.                 {
  1276.                         gEnv->pCryPak->FClose(f);
  1277.                         return gEnv->pSystem->LoadXmlFromFile(m_filename);
  1278.                 }
  1279.                 else
  1280.                         return gEnv->pSystem->LoadXmlFromFile("Libs/Config/Profiles/Default/levelrotation/levelrotation.xml");
  1281.         }
  1282.  
  1283.         virtual void Complete()
  1284.         {
  1285.                 delete this;
  1286.         }
  1287. private:
  1288.         string m_filename;
  1289. };
  1290.  
  1291. ILevelRotationFile* CCommonSaveGameHelper::GetLevelRotationFile(CPlayerProfileManager::SUserEntry* pEntry, const char* name)
  1292. {
  1293.         string filename = gEnv->pSystem->GetRootFolder();
  1294.         if (filename.empty())
  1295.         {
  1296.                 m_pImpl->InternalMakeFSPath(pEntry, pEntry->pCurrentProfile->GetName(), filename);
  1297.                 filename.append("levelrotation/");
  1298.         }
  1299.         string strippedName = PathUtil::GetFile(name);
  1300.         filename.append(strippedName);
  1301.         filename.append(".xml");
  1302.         return new CLevelRotationFile(filename);
  1303. }
  1304.  
  1305. namespace PlayerProfileImpl
  1306. {
  1307. const char* PROFILE_ROOT_TAG = "Profile";
  1308. const char* PROFILE_NAME_TAG = "Name";
  1309. const char* PROFILE_LAST_PLAYED = "LastPlayed";
  1310.  
  1311. // a simple serializer. manages sections (XmlNodes)
  1312. // is used during load and save
  1313. // CSerializerXML no longer supports sections being within the root node. In future it could be modified to but for now because of BinaryXML loading on consoles the ProfileImplFSDir is preferred.
  1314.  
  1315. CSerializerXML::CSerializerXML(XmlNodeRef& root, bool bLoading) : m_bLoading(bLoading), m_root(root)
  1316. {
  1317.         assert(m_root != 0);
  1318. }
  1319.  
  1320. XmlNodeRef CSerializerXML::CreateNewSection(CPlayerProfileManager::EPlayerProfileSection section, const char* name)
  1321. {
  1322.         int sectionIdx = (int)section;
  1323.         assert(sectionIdx >= 0 && sectionIdx < (int)CPlayerProfileManager::ePPS_Num);
  1324.         assert(m_sections[sectionIdx] == 0);
  1325.  
  1326.         XmlNodeRef newNode = GetISystem()->CreateXmlNode(name);
  1327.         m_sections[sectionIdx] = newNode;
  1328.  
  1329.         return newNode;
  1330. }
  1331.  
  1332. void CSerializerXML::SetSection(CPlayerProfileManager::EPlayerProfileSection section, XmlNodeRef& node)
  1333. {
  1334.         int sectionIdx = (int)section;
  1335.         assert(sectionIdx >= 0 && sectionIdx < (int)CPlayerProfileManager::ePPS_Num);
  1336.         assert(m_sections[sectionIdx] == 0);
  1337.  
  1338.         if (node != 0)
  1339.                 m_sections[sectionIdx] = node;
  1340. }
  1341.  
  1342. XmlNodeRef CSerializerXML::GetSection(CPlayerProfileManager::EPlayerProfileSection section)
  1343. {
  1344.         int sectionIdx = (int)section;
  1345.         assert(sectionIdx >= 0 && sectionIdx < (int)CPlayerProfileManager::ePPS_Num);
  1346.  
  1347.         return m_sections[sectionIdx];
  1348. }
  1349.  
  1350. /*
  1351.    XmlNodeRef CSerializerXML::AddSection(const char* name)
  1352.    {
  1353.    XmlNodeRef child = m_root->findChild(name);
  1354.    if (child == 0)
  1355.    {
  1356.     child = m_root->newChild(name);
  1357.    }
  1358.    return child;
  1359.    }
  1360.  
  1361.    XmlNodeRef CSerializerXML::GetSection(const char* name)
  1362.    {
  1363.    XmlNodeRef child = m_root->findChild(name);
  1364.    return child;
  1365.    }
  1366.    // ~CPlayerProfileManager::ISerializer
  1367.  
  1368.    // --- used by impl ---
  1369.  
  1370.    void CSerializerXML::AddSection(XmlNodeRef& node)
  1371.    {
  1372.    if (node != 0)
  1373.     m_root->addChild(node);
  1374.    }
  1375.  
  1376.    int CSerializerXML::GetSectionCount()
  1377.    {
  1378.    return m_root->getChildCount();
  1379.    }
  1380.  
  1381.    XmlNodeRef CSerializerXML::GetSectionByIndex(int index)
  1382.    {
  1383.    assert (index >=0 && index < m_root->getChildCount());
  1384.    return m_root->getChild(index);
  1385.    }
  1386.  */
  1387.  
  1388. // some helpers
  1389. bool SaveXMLFile(const string& filename, const XmlNodeRef& rootNode)
  1390. {
  1391.         LOADING_TIME_PROFILE_SECTION(gEnv->pSystem);
  1392.  
  1393.         bool ok = false;
  1394.  
  1395.         if (rootNode != 0)
  1396.         {
  1397.                 ok = rootNode->saveToFile(filename.c_str());
  1398.         }
  1399.  
  1400.         if (!ok)
  1401.         {
  1402.                 GameWarning("[PlayerProfiles] PlayerProfileImplFS: Cannot save XML file '%s'", filename.c_str());
  1403.         }
  1404.         return ok;
  1405. }
  1406.  
  1407. XmlNodeRef LoadXMLFile(const string& filename)
  1408. {
  1409.         XmlNodeRef rootNode = GetISystem()->LoadXmlFromFile(filename.c_str());
  1410.         if (rootNode == 0)
  1411.         {
  1412.                 GameWarning("[PlayerProfiles] PlayerProfileImplFS: Cannot load XML file '%s'", filename.c_str());
  1413.         }
  1414.         return rootNode;
  1415. }
  1416.  
  1417. bool IsValidFilename(const char* filename)
  1418. {
  1419.         const char* invalidChars = "\\/:*?\"<>~|";
  1420.         return strpbrk(filename, invalidChars) == 0;
  1421. }
  1422.  
  1423. } // namespace PlayerProfileImpl
  1424.  
downloadPlayerProfileImplFS.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