BVB Source Codes

CRYENGINE Show PlayerProfileManager.cpp Source code

Return Download CRYENGINE: download PlayerProfileManager.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 "PlayerProfileManager.h"
  5. #include "PlayerProfile.h"
  6. #include "CryAction.h"
  7. #include "IActionMapManager.h"
  8. #include <CryCore/Platform/IPlatformOS.h>
  9. #include <CryCore/CryCrc32.h>
  10. #include <CryCore/Platform/CryWindows.h>
  11.  
  12. #define SHARED_SAVEGAME_FOLDER            "%USER%/SaveGames"
  13.  
  14. #define ONLINE_ATTRIBUTES_DEFINITION_FILE "Scripts/Network/OnlineAttributes.xml"
  15. #define ONLINE_VERSION_ATTRIBUTE_NAME     "OnlineAttributes/version"
  16.  
  17. const char* CPlayerProfileManager::FACTORY_DEFAULT_NAME = "default";
  18. const char* CPlayerProfileManager::PLAYER_DEFAULT_PROFILE_NAME = "default";
  19.  
  20. namespace TESTING
  21. {
  22. void DumpProfiles(IPlayerProfileManager* pFS, const char* userId)
  23. {
  24.         int nProfiles = pFS->GetProfileCount(userId);
  25.         IPlayerProfileManager::SProfileDescription desc;
  26.         CryLogAlways("User %s has %d profiles", userId, nProfiles);
  27.         for (int i = 0; i < nProfiles; ++i)
  28.         {
  29.                 pFS->GetProfileInfo(userId, i, desc);
  30.                 CryLogAlways("#%d: '%s'", i, desc.name);
  31.         }
  32. }
  33.  
  34. void DumpAttrs(IPlayerProfile* pProfile)
  35. {
  36.         if (pProfile == 0)
  37.                 return;
  38.         IAttributeEnumeratorPtr pEnum = pProfile->CreateAttributeEnumerator();
  39.         IAttributeEnumerator::SAttributeDescription desc;
  40.         CryLogAlways("Attributes of profile %s", pProfile->GetName());
  41.         int i = 0;
  42.         TFlowInputData val;
  43.         while (pEnum->Next(desc))
  44.         {
  45.                 pProfile->GetAttribute(desc.name, val);
  46.                 string sVal;
  47.                 val.GetValueWithConversion(sVal);
  48.                 CryLogAlways("Attr %d: %s=%s", i, desc.name, sVal.c_str());
  49.                 ++i;
  50.         }
  51. }
  52.  
  53. void DumpSaveGames(IPlayerProfile* pProfile)
  54. {
  55.         ISaveGameEnumeratorPtr pSGE = pProfile->CreateSaveGameEnumerator();
  56.         ISaveGameEnumerator::SGameDescription desc;
  57.         CryLogAlways("SaveGames for Profile '%s'", pProfile->GetName());
  58.         char timeBuf[256];
  59.         struct tm* timePtr;
  60.         for (int i = 0; i < pSGE->GetCount(); ++i)
  61.         {
  62.                 pSGE->GetDescription(i, desc);
  63.                 timePtr = localtime(&desc.metaData.saveTime);
  64.                 const char* timeString = timeBuf;
  65.                 if (strftime(timeBuf, sizeof(timeBuf), "%#c", timePtr) == 0)
  66.                         timeString = asctime(timePtr);
  67.                 CryLogAlways("SaveGame %d/%d: name='%s' humanName='%s' desc='%s'", i, pSGE->GetCount() - 1, desc.name, desc.humanName, desc.description);
  68.                 CryLogAlways("MetaData: level=%s gr=%s version=%d build=%s savetime=%s",
  69.                              desc.metaData.levelName, desc.metaData.gameRules, desc.metaData.fileVersion, desc.metaData.buildVersion,
  70.                              timeString);
  71.         }
  72. }
  73.  
  74. void DumpActionMap(IPlayerProfile* pProfile, const char* name)
  75. {
  76.         IActionMap* pMap = pProfile->GetActionMap(name);
  77.         if (pMap)
  78.         {
  79.                 int iAction = 0;
  80.                 IActionMapActionIteratorPtr pIter = pMap->CreateActionIterator();
  81.                 while (const IActionMapAction* pAction = pIter->Next())
  82.                 {
  83.                         CryLogAlways("Action %d: '%s'", iAction++, pAction->GetActionId().c_str());
  84.  
  85.                         int iNumInputData = pAction->GetNumActionInputs();
  86.                         for (int i = 0; i < iNumInputData; ++i)
  87.                         {
  88.                                 const SActionInput* pActionInput = pAction->GetActionInput(i);
  89.                                 CRY_ASSERT(pActionInput != NULL);
  90.                                 CryLogAlways("Key %d/%d: '%s'", i, iNumInputData - 1, pActionInput->input.c_str());
  91.                         }
  92.                 }
  93.         }
  94. }
  95.  
  96. void DumpMap(IConsoleCmdArgs* args)
  97. {
  98.         IActionMapManager* pAM = CCryAction::GetCryAction()->GetIActionMapManager();
  99.         IActionMapIteratorPtr iter = pAM->CreateActionMapIterator();
  100.         while (IActionMap* pMap = iter->Next())
  101.         {
  102.                 CryLogAlways("ActionMap: '%s' 0x%p", pMap->GetName(), pMap);
  103.                 int iAction = 0;
  104.                 IActionMapActionIteratorPtr pIter = pMap->CreateActionIterator();
  105.                 while (const IActionMapAction* pAction = pIter->Next())
  106.                 {
  107.                         CryLogAlways("Action %d: '%s'", iAction++, pAction->GetActionId().c_str());
  108.  
  109.                         int iNumInputData = pAction->GetNumActionInputs();
  110.                         for (int i = 0; i < iNumInputData; ++i)
  111.                         {
  112.                                 const SActionInput* pActionInput = pAction->GetActionInput(i);
  113.                                 CRY_ASSERT(pActionInput != NULL);
  114.                                 CryLogAlways("Key %d/%d: '%s'", i, iNumInputData - 1, pActionInput->input.c_str());
  115.                         }
  116.                 }
  117.         }
  118. }
  119.  
  120. void TestProfile(IConsoleCmdArgs* args)
  121. {
  122.         const char* userName = GetISystem()->GetUserName();
  123.         IPlayerProfileManager::EProfileOperationResult result;
  124.         IPlayerProfileManager* pFS = CCryAction::GetCryAction()->GetIPlayerProfileManager();
  125.  
  126.         // test renaming current profile
  127. #if 0
  128.         pFS->RenameProfile(userName, "newOne4", result);
  129.         return;
  130. #endif
  131.  
  132.         bool bFirstTime = false;
  133.         pFS->LoginUser(userName, bFirstTime);
  134.         DumpProfiles(pFS, userName);
  135.         pFS->DeleteProfile(userName, "PlayerCool", result);
  136.         IPlayerProfile* pProfile = pFS->ActivateProfile(userName, "default");
  137.         if (pProfile)
  138.         {
  139.                 DumpActionMap(pProfile, "default");
  140.                 DumpAttrs(pProfile);
  141.                 pProfile->SetAttribute("hallo2", TFlowInputData(222));
  142.                 pProfile->SetAttribute("newAddedAttribute", TFlowInputData(24.10f));
  143.                 DumpAttrs(pProfile);
  144.                 pProfile->SetAttribute("newAddedAttribute", TFlowInputData(25.10f));
  145.                 DumpAttrs(pProfile);
  146.                 pProfile->ResetAttribute("newAddedAttribute");
  147.                 pProfile->ResetAttribute("hallo2");
  148.                 DumpAttrs(pProfile);
  149.                 DumpSaveGames(pProfile);
  150.                 float fVal;
  151.                 pProfile->GetAttribute("newAddedAttribute", fVal);
  152.                 pProfile->SetAttribute("newAddedAttribute", 2.22f);
  153.         }
  154.         else
  155.         {
  156.                 CryLogAlways("Can't activate profile 'default'");
  157.         }
  158.  
  159.         const IPlayerProfile* pPreviewProfile = pFS->PreviewProfile(userName, "previewTest");
  160.         if (pPreviewProfile)
  161.         {
  162.                 float fVal;
  163.                 pPreviewProfile->GetAttribute("previewData", fVal);
  164.                 pPreviewProfile->GetAttribute("previewData2", fVal, true);
  165.         }
  166.  
  167.         DumpProfiles(pFS, userName);
  168.         // pFS->RenameProfile(userName, "new new profile");
  169.         pFS->LogoutUser(userName);
  170. }
  171. }
  172.  
  173. int CPlayerProfileManager::sUseRichSaveGames = 0;
  174. int CPlayerProfileManager::sRSFDebugWrite = 0;
  175. int CPlayerProfileManager::sRSFDebugWriteOnLoad = 0;
  176. int CPlayerProfileManager::sLoadOnlineAttributes = 1;
  177.  
  178. //------------------------------------------------------------------------
  179. CPlayerProfileManager::CPlayerProfileManager(CPlayerProfileManager::IPlatformImpl* pImpl)
  180.         : m_curUserIndex(IPlatformOS::Unknown_User)
  181.         , m_exclusiveControllerDeviceIndex(INVALID_CONTROLLER_INDEX) // start uninitialized
  182.         , m_onlineDataCount(0)
  183.         , m_onlineDataByteCount(0)
  184.         , m_onlineAttributeAutoGeneratedVersion(0)
  185.         , m_pImpl(pImpl)
  186.         , m_pDefaultProfile(nullptr)
  187.         , m_pReadingProfile(nullptr)
  188.         , m_onlineAttributesListener(nullptr)
  189.         , m_onlineAttributeDefinedVersion(0)
  190.         , m_lobbyTaskId(CryLobbyInvalidTaskID)
  191.         , m_registered(false)
  192.         , m_bInitialized(false)
  193.         , m_enableOnlineAttributes(false)
  194.         , m_allowedToProcessOnlineAttributes(true)
  195.         , m_loadingProfile(false)
  196.         , m_savingProfile(false)
  197. {
  198.         assert(m_pImpl != 0);
  199.  
  200.         // FIXME: TODO: temp stuff
  201.         static bool testInit = false;
  202.         if (testInit == false)
  203.         {
  204.                 testInit = true;
  205.                 REGISTER_CVAR2("pp_RichSaveGames", &CPlayerProfileManager::sUseRichSaveGames, 0, 0, "Enable RichSaveGame Format for SaveGames");
  206.                 REGISTER_CVAR2("pp_RSFDebugWrite", &CPlayerProfileManager::sRSFDebugWrite, gEnv->pSystem->IsDevMode() ? 1 : 0, 0, "When RichSaveGames are enabled, save plain XML Data alongside for debugging");
  207.                 REGISTER_CVAR2("pp_RSFDebugWriteOnLoad", &CPlayerProfileManager::sRSFDebugWriteOnLoad, 0, 0, "When RichSaveGames are enabled, save plain XML Data alongside for debugging when loading a savegame");
  208.                 REGISTER_CVAR2("pp_LoadOnlineAttributes", &CPlayerProfileManager::sLoadOnlineAttributes, CPlayerProfileManager::sLoadOnlineAttributes, VF_REQUIRE_APP_RESTART, "Load online attributes");
  209.  
  210.                 REGISTER_COMMAND("test_profile", TESTING::TestProfile, VF_NULL, "");
  211.                 REGISTER_COMMAND("dump_action_maps", TESTING::DumpMap, VF_NULL, "Prints all action map bindings to console");
  212.  
  213. #if PROFILE_DEBUG_COMMANDS
  214.                 REGISTER_COMMAND("loadOnlineAttributes", &CPlayerProfileManager::DbgLoadOnlineAttributes, VF_NULL, "Loads online attributes");
  215.                 REGISTER_COMMAND("saveOnlineAttributes", &CPlayerProfileManager::DbgSaveOnlineAttributes, VF_NULL, "Saves online attributes");
  216.                 REGISTER_COMMAND("testOnlineAttributes", &CPlayerProfileManager::DbgTestOnlineAttributes, VF_NULL, "Tests online attributes");
  217.  
  218.                 REGISTER_COMMAND("loadProfile", &CPlayerProfileManager::DbgLoadProfile, VF_NULL, "Load current user profile");
  219.                 REGISTER_COMMAND("saveProfile", &CPlayerProfileManager::DbgSaveProfile, VF_NULL, "Save current user profile");
  220. #endif
  221.         }
  222.  
  223.         m_sharedSaveGameFolder = SHARED_SAVEGAME_FOLDER; // by default, use a shared savegame folder (Games For Windows Requirement)
  224.         m_sharedSaveGameFolder.TrimRight("/\\");
  225.  
  226.         memset(m_onlineOnlyData, 0, sizeof(m_onlineOnlyData));
  227.         memset(m_onlineAttributesState, IOnlineAttributesListener::eOAS_None, sizeof(m_onlineAttributesState));
  228. #if PROFILE_DEBUG_COMMANDS
  229.         m_testingPhase = 0;
  230.  
  231.         for (int i = 0; i < k_maxOnlineDataCount; ++i)
  232.         {
  233.                 m_testFlowData[i] = 0;
  234.         }
  235. #endif
  236. }
  237.  
  238. //------------------------------------------------------------------------
  239. CPlayerProfileManager::~CPlayerProfileManager()
  240. {
  241.         // don't call virtual Shutdown or any other virtual function,
  242.         // but delete things directly
  243.         if (m_bInitialized)
  244.         {
  245.                 GameWarning("[PlayerProfiles] CPlayerProfileManager::~CPlayerProfileManager Shutdown not called!");
  246.         }
  247.         std::for_each(m_userVec.begin(), m_userVec.end(), stl::container_object_deleter());
  248.         SAFE_DELETE(m_pDefaultProfile);
  249.         if (m_pImpl)
  250.         {
  251.                 m_pImpl->Release();
  252.                 m_pImpl = 0;
  253.         }
  254.  
  255.         IConsole* pC = ::gEnv->pConsole;
  256.         pC->UnregisterVariable("pp_RichSaveGames", true);
  257.         pC->RemoveCommand("test_profile");
  258.         pC->RemoveCommand("dump_action_maps");
  259. }
  260.  
  261. //------------------------------------------------------------------------
  262. bool CPlayerProfileManager::Initialize()
  263. {
  264.         if (m_bInitialized)
  265.                 return true;
  266.  
  267.         m_pImpl->Initialize(this);
  268.  
  269.         CPlayerProfile* pDefaultProfile = new CPlayerProfile(this, FACTORY_DEFAULT_NAME, "", false);
  270.         bool ok = LoadProfile(0, pDefaultProfile, pDefaultProfile->GetName());
  271.         if (!ok)
  272.         {
  273.                 GameWarning("[PlayerProfiles] Cannot load factory default profile '%s'", FACTORY_DEFAULT_NAME);
  274.                 SAFE_DELETE(pDefaultProfile);
  275.         }
  276.  
  277.         m_pDefaultProfile = pDefaultProfile;
  278.  
  279.         m_bInitialized = ok;
  280.         return m_bInitialized;
  281. }
  282.  
  283. //------------------------------------------------------------------------
  284. bool CPlayerProfileManager::Shutdown()
  285. {
  286.         while (m_userVec.empty() == false)
  287.         {
  288.                 SUserEntry* pEntry = m_userVec.back();
  289.                 LogoutUser(pEntry->userId);
  290.         }
  291.         SAFE_DELETE(m_pDefaultProfile);
  292.         m_bInitialized = false;
  293.         return true;
  294. }
  295.  
  296. //------------------------------------------------------------------------
  297. int CPlayerProfileManager::GetUserCount()
  298. {
  299.         return m_userVec.size();
  300. }
  301.  
  302. //------------------------------------------------------------------------
  303. bool CPlayerProfileManager::GetUserInfo(int index, IPlayerProfileManager::SUserInfo& outInfo)
  304. {
  305.         if (index < 0 || index >= m_userVec.size())
  306.         {
  307.                 assert(index >= 0 && index < m_userVec.size());
  308.                 return false;
  309.         }
  310.  
  311.         SUserEntry* pEntry = m_userVec[index];
  312.         outInfo.userId = pEntry->userId;
  313.         return true;
  314. }
  315.  
  316. //------------------------------------------------------------------------
  317. bool CPlayerProfileManager::LoginUser(const char* userId, bool& bOutFirstTime)
  318. {
  319.         if (m_bInitialized == false)
  320.                 return false;
  321.  
  322.         bOutFirstTime = false;
  323.  
  324.         m_curUserID = userId;
  325.  
  326.         // user already logged in
  327.         SUserEntry* pEntry = FindEntry(userId);
  328.         if (pEntry)
  329.         {
  330.                 m_curUserIndex = pEntry->userIndex;
  331.                 return true;
  332.         }
  333.  
  334.         SUserEntry* newEntry = new SUserEntry(userId);
  335.         newEntry->pCurrentProfile = 0;
  336.         newEntry->userIndex = m_userVec.size();
  337.         // login the user and fill SUserEntry
  338.         bool ok = m_pImpl->LoginUser(newEntry);
  339.  
  340.         if (!ok)
  341.         {
  342.                 delete newEntry;
  343.                 GameWarning("[PlayerProfiles] Cannot login user '%s'", userId);
  344.                 return false;
  345.         }
  346.  
  347.         // no entries yet -> create default profile by copying/saving factory default
  348.         if (m_pDefaultProfile && newEntry->profileDesc.empty())
  349.         {
  350.                 // save the default profile
  351.                 ok = m_pImpl->SaveProfile(newEntry, m_pDefaultProfile, PLAYER_DEFAULT_PROFILE_NAME);
  352.                 if (!ok)
  353.                 {
  354.                         GameWarning("[PlayerProfiles] Login of user '%s' failed because default profile '%s' cannot be created", userId, PLAYER_DEFAULT_PROFILE_NAME);
  355.  
  356.                         delete newEntry;
  357.                         // TODO: maybe assign use factory default in this case, but then
  358.                         // cannot save anything incl. save-games
  359.                         return false;
  360.                 }
  361.                 CryLog("[PlayerProfiles] Login of user '%s': First Time Login - Successfully created default profile '%s'", userId, PLAYER_DEFAULT_PROFILE_NAME);
  362.                 SLocalProfileInfo info(PLAYER_DEFAULT_PROFILE_NAME);
  363.                 time_t lastLoginTime;
  364.                 time(&lastLoginTime);
  365.                 info.SetLastLoginTime(lastLoginTime);
  366.                 newEntry->profileDesc.push_back(info);
  367.                 bOutFirstTime = true;
  368.         }
  369.  
  370.         CryLog("[PlayerProfiles] Login of user '%s' successful.", userId);
  371.         if (bOutFirstTime == false)
  372.         {
  373.                 CryLog("[PlayerProfiles] Found %" PRISIZE_T " profiles.", newEntry->profileDesc.size());
  374.                 for (int i = 0; i < newEntry->profileDesc.size(); ++i)
  375.                         CryLog("   Profile %d : '%s'", i, newEntry->profileDesc[i].GetName().c_str());
  376.         }
  377.  
  378.         m_curUserIndex = newEntry->userIndex;
  379.         m_userVec.push_back(newEntry);
  380.         return true;
  381. }
  382.  
  383. //------------------------------------------------------------------------
  384. bool CPlayerProfileManager::LogoutUser(const char* userId)
  385. {
  386.         if (!m_bInitialized)
  387.                 return false;
  388.  
  389.         // check if user already logged in
  390.         TUserVec::iterator iter;
  391.         SUserEntry* pEntry = FindEntry(userId, iter);
  392.         if (pEntry == 0)
  393.         {
  394.                 GameWarning("[PlayerProfiles] Logout of user '%s' failed [was not logged in]", userId);
  395.                 return false;
  396.         }
  397.  
  398. #if !CRY_PLATFORM_DURANGO // We don't want to auto save profile on durango, all settings are save to profile at the appropriate time
  399.         // auto-save profile
  400.         if (pEntry->pCurrentProfile && (gEnv && gEnv->pSystem && (!gEnv->pSystem->IsQuitting())))
  401.         {
  402.                 EProfileOperationResult result;
  403.                 bool ok = SaveProfile(userId, result, ePR_Options);
  404.                 if (!ok)
  405.                 {
  406.                         GameWarning("[PlayerProfiles] Logout of user '%s': Couldn't save profile '%s'", userId, pEntry->pCurrentProfile->GetName());
  407.                 }
  408.         }
  409. #endif
  410.  
  411.         m_pImpl->LogoutUser(pEntry);
  412.  
  413.         if (m_curUserIndex == std::distance(m_userVec.begin(), iter))
  414.         {
  415.                 m_curUserIndex = IPlatformOS::Unknown_User;
  416.                 m_curUserID.clear();
  417.         }
  418.  
  419.         // delete entry from vector
  420.         m_userVec.erase(iter);
  421.  
  422.         ClearOnlineAttributes();
  423.  
  424.         SAFE_DELETE(pEntry->pCurrentProfile);
  425.         SAFE_DELETE(pEntry->pCurrentPreviewProfile);
  426.  
  427.         // delete entry
  428.         delete pEntry;
  429.  
  430.         return true;
  431. }
  432.  
  433. //------------------------------------------------------------------------
  434. int CPlayerProfileManager::GetProfileCount(const char* userId)
  435. {
  436.         SUserEntry* pEntry = FindEntry(userId);
  437.         if (pEntry == 0)
  438.                 return 0;
  439.         return pEntry->profileDesc.size();
  440. }
  441.  
  442. //------------------------------------------------------------------------
  443. bool CPlayerProfileManager::GetProfileInfo(const char* userId, int index, IPlayerProfileManager::SProfileDescription& outInfo)
  444. {
  445.         if (!m_bInitialized)
  446.                 return false;
  447.  
  448.         SUserEntry* pEntry = FindEntry(userId);
  449.         if (pEntry == 0)
  450.         {
  451.                 GameWarning("[PlayerProfiles] GetProfileInfo: User '%s' not logged in", userId);
  452.                 return false;
  453.         }
  454.         int count = pEntry->profileDesc.size();
  455.         if (index >= count)
  456.         {
  457.                 assert(index < count);
  458.                 return false;
  459.         }
  460.         SLocalProfileInfo& info = pEntry->profileDesc[index];
  461.         outInfo.name = info.GetName().c_str();
  462.         outInfo.lastLoginTime = info.GetLastLoginTime();
  463.         return true;
  464. }
  465.  
  466. //------------------------------------------------------------------------
  467. void CPlayerProfileManager::SetProfileLastLoginTime(const char* userId, int index, time_t lastLoginTime)
  468. {
  469.         if (!m_bInitialized)
  470.                 return;
  471.  
  472.         SUserEntry* pEntry = FindEntry(userId);
  473.         if (pEntry == 0)
  474.         {
  475.                 GameWarning("[PlayerProfiles] GetProfileInfo: User '%s' not logged in", userId);
  476.                 return;
  477.         }
  478.         int count = pEntry->profileDesc.size();
  479.         if (index >= count)
  480.         {
  481.                 assert(index < count);
  482.                 return;
  483.         }
  484.         SLocalProfileInfo& info = pEntry->profileDesc[index];
  485.         info.SetLastLoginTime(lastLoginTime);
  486. }
  487.  
  488. //------------------------------------------------------------------------
  489. bool CPlayerProfileManager::CreateProfile(const char* userId, const char* profileName, bool bOverride, IPlayerProfileManager::EProfileOperationResult& result)
  490. {
  491.         if (!m_bInitialized)
  492.         {
  493.                 result = ePOR_NotInitialized;
  494.                 return false;
  495.         }
  496.         SUserEntry* pEntry = FindEntry(userId);
  497.         if (pEntry == 0)
  498.         {
  499.                 GameWarning("[PlayerProfiles] CreateProfile: User '%s' not logged in", userId);
  500.                 result = ePOR_UserNotLoggedIn;
  501.                 return false;
  502.         }
  503.  
  504.         SLocalProfileInfo* pInfo = GetLocalProfileInfo(pEntry, profileName);
  505.         if (pInfo != 0 && !bOverride) // profile with this name already exists
  506.         {
  507.                 GameWarning("[PlayerProfiles] CreateProfile: User '%s' already has a profile with name '%s'", userId, profileName);
  508.                 result = ePOR_NameInUse;
  509.                 return false;
  510.         }
  511.  
  512.         result = ePOR_Unknown;
  513.         bool ok = true;
  514.         if (pEntry->pCurrentProfile == 0)
  515.         {
  516.                 // save the default profile
  517.                 ok = m_pImpl->SaveProfile(pEntry, m_pDefaultProfile, profileName, bOverride);
  518.         }
  519.         if (ok)
  520.         {
  521.                 result = ePOR_Success;
  522.  
  523.                 if (pInfo == 0) // if we override, it's already present
  524.                 {
  525.                         SLocalProfileInfo info(profileName);
  526.                         time_t lastPlayTime;
  527.                         time(&lastPlayTime);
  528.                         info.SetLastLoginTime(lastPlayTime);
  529.                         pEntry->profileDesc.push_back(info);
  530.  
  531.                         // create default profile by copying/saving factory default
  532.                         ok = m_pImpl->SaveProfile(pEntry, m_pDefaultProfile, profileName);
  533.  
  534.                         if (!ok)
  535.                         {
  536.                                 pEntry->profileDesc.pop_back();
  537.                                 result = ePOR_Unknown;
  538.                         }
  539.                 }
  540.         }
  541.         if (!ok)
  542.         {
  543.                 GameWarning("[PlayerProfiles] CreateProfile: User '%s' cannot create profile '%s'", userId, profileName);
  544.         }
  545.         return ok;
  546. }
  547.  
  548. //------------------------------------------------------------------------
  549. bool CPlayerProfileManager::DeleteProfile(const char* userId, const char* profileName, IPlayerProfileManager::EProfileOperationResult& result)
  550. {
  551.         if (!m_bInitialized)
  552.         {
  553.                 result = ePOR_NotInitialized;
  554.                 return false;
  555.         }
  556.         SUserEntry* pEntry = FindEntry(userId);
  557.         if (pEntry == 0)
  558.         {
  559.                 GameWarning("[PlayerProfiles] DeleteProfile: User '%s' not logged in", userId);
  560.                 result = ePOR_UserNotLoggedIn;
  561.                 return false;
  562.         }
  563.  
  564.         // cannot delete last profile
  565.         if (pEntry->profileDesc.size() <= 1)
  566.         {
  567.                 GameWarning("[PlayerProfiles] DeleteProfile: User '%s' cannot delete last profile", userId);
  568.                 result = ePOR_ProfileInUse;
  569.                 return false;
  570.         }
  571.  
  572.         // make sure there is such a profile
  573.         std::vector<SLocalProfileInfo>::iterator iter;
  574.         SLocalProfileInfo* info = GetLocalProfileInfo(pEntry, profileName, iter);
  575.         if (info)
  576.         {
  577.                 bool ok = m_pImpl->DeleteProfile(pEntry, profileName);
  578.                 if (ok)
  579.                 {
  580.                         pEntry->profileDesc.erase(iter);
  581.                         // if the profile was the current profile, delete it
  582.                         if (pEntry->pCurrentProfile != 0 && stricmp(profileName, pEntry->pCurrentProfile->GetName()) == 0)
  583.                         {
  584.                                 delete pEntry->pCurrentProfile;
  585.                                 pEntry->pCurrentProfile = 0;
  586.                                 // TODO: Maybe auto-select a profile
  587.                         }
  588.                         result = ePOR_Success;
  589.                         return true;
  590.                 }
  591.                 result = ePOR_Unknown;
  592.         }
  593.         else
  594.                 result = ePOR_NoSuchProfile;
  595.  
  596.         return false;
  597. }
  598.  
  599. //------------------------------------------------------------------------
  600. bool CPlayerProfileManager::RenameProfile(const char* userId, const char* newName, IPlayerProfileManager::EProfileOperationResult& result)
  601. {
  602.         if (!m_bInitialized)
  603.         {
  604.                 result = ePOR_NotInitialized;
  605.                 return false;
  606.         }
  607.  
  608.         SUserEntry* pEntry = FindEntry(userId);
  609.         if (pEntry == 0)
  610.         {
  611.                 GameWarning("[PlayerProfiles] RenameProfile: User '%s' not logged in", userId);
  612.                 result = ePOR_UserNotLoggedIn;
  613.                 return false;
  614.         }
  615.  
  616.         // make sure there is no such profile
  617.         if (GetLocalProfileInfo(pEntry, newName) != 0)
  618.         {
  619.                 result = ePOR_NoSuchProfile;
  620.                 return false;
  621.         }
  622.  
  623.         // can only rename current active profile
  624.         if (pEntry->pCurrentProfile == 0)
  625.         {
  626.                 result = ePOR_NoActiveProfile;
  627.                 return false;
  628.         }
  629.  
  630.         if (stricmp(pEntry->pCurrentProfile->GetName(), PLAYER_DEFAULT_PROFILE_NAME) == 0)
  631.         {
  632.                 GameWarning("[PlayerProfiles] RenameProfile: User '%s' cannot rename default profile", userId);
  633.                 result = ePOR_DefaultProfile;
  634.                 return false;
  635.         }
  636.  
  637.         result = ePOR_Unknown;
  638.         bool ok = m_pImpl->RenameProfile(pEntry, newName);
  639.  
  640.         if (ok)
  641.         {
  642.                 // assign a new name in the info DB
  643.                 SLocalProfileInfo* info = GetLocalProfileInfo(pEntry, pEntry->pCurrentProfile->GetName());
  644.                 info->SetName(newName);
  645.  
  646.                 // assign a new name in the profile itself
  647.                 pEntry->pCurrentProfile->SetName(newName);
  648.  
  649.                 result = ePOR_Success;
  650.         }
  651.         else
  652.         {
  653.                 GameWarning("[PlayerProfiles] RenameProfile: Failed to rename profile to '%s' for user '%s' ", newName, userId);
  654.         }
  655.         return ok;
  656. }
  657.  
  658. //------------------------------------------------------------------------
  659. bool CPlayerProfileManager::SaveProfile(const char* userId, IPlayerProfileManager::EProfileOperationResult& result, unsigned int reason)
  660. {
  661.         if (!m_bInitialized)
  662.         {
  663.                 result = ePOR_NotInitialized;
  664.                 return false;
  665.         }
  666.  
  667.         SUserEntry* pEntry = FindEntry(userId);
  668.         if (pEntry == 0)
  669.         {
  670.                 GameWarning("[PlayerProfiles] SaveProfile: User '%s' not logged in", userId);
  671.                 result = ePOR_UserNotLoggedIn;
  672.                 return false;
  673.         }
  674.  
  675.         if (pEntry->pCurrentProfile == 0)
  676.         {
  677.                 GameWarning("[PlayerProfiles] SaveProfile: User '%s' not logged in", userId);
  678.                 result = ePOR_NoActiveProfile;
  679.                 return false;
  680.         }
  681.  
  682.         if (m_loadingProfile || m_savingProfile)
  683.         {
  684.                 result = ePOR_LoadingProfile;
  685.  
  686.                 return false;
  687.         }
  688.         else
  689.         {
  690.                 m_savingProfile = true;
  691.         }
  692.  
  693.         result = ePOR_Success;
  694.  
  695.         // notify game systems that the profile is about to be saved
  696.         const int listenerSize = m_listeners.size();
  697.         for (int i = 0; i < listenerSize; i++)
  698.         {
  699.                 m_listeners[i]->SaveToProfile(pEntry->pCurrentProfile, false, reason);
  700.         }
  701.  
  702.         bool ok = m_pImpl->SaveProfile(pEntry, pEntry->pCurrentProfile, pEntry->pCurrentProfile->GetName());
  703.  
  704.         if (!ok)
  705.         {
  706.                 GameWarning("[PlayerProfiles] SaveProfile: User '%s' cannot save profile '%s'", userId, pEntry->pCurrentProfile->GetName());
  707.                 result = ePOR_Unknown;
  708.         }
  709.  
  710.         m_savingProfile = false;
  711.  
  712.         return ok;
  713. }
  714.  
  715. //------------------------------------------------------------------------
  716. bool CPlayerProfileManager::SaveInactiveProfile(const char* userId, const char* profileName, EProfileOperationResult& result, unsigned int reason)
  717. {
  718.         if (!m_bInitialized)
  719.         {
  720.                 result = ePOR_NotInitialized;
  721.                 return false;
  722.         }
  723.  
  724.         SUserEntry* pEntry = FindEntry(userId);
  725.         if (pEntry == 0)
  726.         {
  727.                 GameWarning("[PlayerProfiles] SaveProfile: User '%s' not logged in", userId);
  728.                 result = ePOR_UserNotLoggedIn;
  729.                 return false;
  730.         }
  731.  
  732.         CPlayerProfile* pProfile = profileName ? new CPlayerProfile(this, profileName, userId, false) : 0;
  733.  
  734.         if (!pProfile || !LoadProfile(pEntry, pProfile, profileName, true))
  735.         {
  736.                 result = ePOR_NoSuchProfile;
  737.                 return false;
  738.         }
  739.  
  740.         result = ePOR_Success;
  741.  
  742.         // notify game systems that the profile is about to be saved
  743.         const int listenerSize = m_listeners.size();
  744.         for (int i = 0; i < listenerSize; i++)
  745.         {
  746.                 m_listeners[i]->SaveToProfile(pProfile, false, reason);
  747.         }
  748.  
  749.         bool ok = m_pImpl->SaveProfile(pEntry, pProfile, pProfile->GetName());
  750.  
  751.         if (!ok)
  752.         {
  753.                 GameWarning("[PlayerProfiles] SaveProfile: User '%s' cannot save profile '%s'", userId, pProfile->GetName());
  754.                 result = ePOR_Unknown;
  755.         }
  756.  
  757.         delete pProfile;
  758.  
  759.         return ok;
  760. }
  761.  
  762. //------------------------------------------------------------------------
  763. bool CPlayerProfileManager::IsLoadingProfile() const
  764. {
  765.         return m_loadingProfile;
  766. }
  767.  
  768. //------------------------------------------------------------------------
  769. bool CPlayerProfileManager::IsSavingProfile() const
  770. {
  771.         return m_savingProfile;
  772. }
  773.  
  774. //------------------------------------------------------------------------
  775. bool CPlayerProfileManager::LoadProfile(SUserEntry* pEntry, CPlayerProfile* pProfile, const char* name, bool bPreview /*false*/)
  776. {
  777.         if (m_loadingProfile || m_savingProfile)
  778.         {
  779.                 return false;
  780.         }
  781.         else
  782.         {
  783.                 m_loadingProfile = true;
  784.         }
  785.  
  786.         bool ok = m_pImpl->LoadProfile(pEntry, pProfile, name);
  787.  
  788.         if (ok && !bPreview)
  789.         {
  790.                 // notify game systems about the new profile data
  791.                 const int listenerSize = m_listeners.size();
  792.                 for (int i = 0; i < listenerSize; i++)
  793.                 {
  794.                         m_listeners[i]->LoadFromProfile(pProfile, false, ePR_All);
  795.                 }
  796.         }
  797.  
  798.         m_loadingProfile = false;
  799.  
  800.         return ok;
  801. }
  802.  
  803. //------------------------------------------------------------------------
  804. const IPlayerProfile* CPlayerProfileManager::PreviewProfile(const char* userId, const char* profileName)
  805. {
  806.         SUserEntry* pEntry = FindEntry(userId);
  807.         if (pEntry == 0) // no such user
  808.         {
  809.                 GameWarning("[PlayerProfiles] ActivateProfile: User '%s' not logged in", userId);
  810.                 return 0;
  811.         }
  812.  
  813.         // if this is the current profile, do nothing
  814.         if (pEntry->pCurrentPreviewProfile != 0 && profileName && stricmp(profileName, pEntry->pCurrentPreviewProfile->GetName()) == 0)
  815.         {
  816.                 return pEntry->pCurrentPreviewProfile;
  817.         }
  818.  
  819.         if (pEntry->pCurrentPreviewProfile != 0)
  820.         {
  821.                 delete pEntry->pCurrentPreviewProfile;
  822.                 pEntry->pCurrentPreviewProfile = 0;
  823.         }
  824.  
  825.         if (profileName == 0 || *profileName == '\0')
  826.                 return 0;
  827.  
  828.         SLocalProfileInfo* info = GetLocalProfileInfo(pEntry, profileName);
  829.         if (info == 0) // no such profile
  830.         {
  831.                 GameWarning("[PlayerProfiles] PreviewProfile: User '%s' has no profile '%s'", userId, profileName);
  832.                 return 0;
  833.         }
  834.  
  835.         pEntry->pCurrentPreviewProfile = new CPlayerProfile(this, profileName, userId, true);
  836.         const bool ok = LoadProfile(pEntry, pEntry->pCurrentPreviewProfile, profileName, true);
  837.         if (!ok)
  838.         {
  839.                 GameWarning("[PlayerProfiles] PreviewProfile: User '%s' cannot load profile '%s'", userId, profileName);
  840.                 delete pEntry->pCurrentPreviewProfile;
  841.                 pEntry->pCurrentPreviewProfile = 0;
  842.         }
  843.  
  844.         return pEntry->pCurrentPreviewProfile;
  845. }
  846.  
  847. //------------------------------------------------------------------------
  848. IPlayerProfile* CPlayerProfileManager::ActivateProfile(const char* userId, const char* profileName)
  849. {
  850.         SUserEntry* pEntry = FindEntry(userId);
  851.         if (pEntry == 0) // no such user
  852.         {
  853.                 GameWarning("[PlayerProfiles] ActivateProfile: User '%s' not logged in", userId);
  854.                 return 0;
  855.         }
  856.  
  857.         // if this is the current profile, do nothing
  858.         if (pEntry->pCurrentProfile != 0 && stricmp(profileName, pEntry->pCurrentProfile->GetName()) == 0)
  859.         {
  860.                 return pEntry->pCurrentProfile;
  861.         }
  862.  
  863.         SLocalProfileInfo* info = GetLocalProfileInfo(pEntry, profileName);
  864.         time_t lastPlayTime;
  865.         time(&lastPlayTime);
  866.         if (info == 0) // no such profile
  867.         {
  868.                 GameWarning("[PlayerProfiles] ActivateProfile: User '%s' has no profile '%s'", userId, profileName);
  869.                 return 0;
  870.         }
  871.         info->SetLastLoginTime(lastPlayTime);
  872.         CPlayerProfile* pNewProfile = new CPlayerProfile(this, profileName, userId, false);
  873.  
  874.         const bool ok = LoadProfile(pEntry, pNewProfile, profileName);
  875.         if (ok)
  876.         {
  877.                 delete pEntry->pCurrentProfile;
  878.                 pEntry->pCurrentProfile = pNewProfile;
  879.         }
  880.         else
  881.         {
  882.                 GameWarning("[PlayerProfiles] ActivateProfile: User '%s' cannot load profile '%s'", userId, profileName);
  883.                 delete pNewProfile;
  884.         }
  885.         return pEntry->pCurrentProfile;
  886. }
  887.  
  888. //------------------------------------------------------------------------
  889. IPlayerProfile* CPlayerProfileManager::GetCurrentProfile(const char* userId)
  890. {
  891.         SUserEntry* pEntry = FindEntry(userId);
  892.         return pEntry ? pEntry->pCurrentProfile : 0;
  893. }
  894.  
  895. //------------------------------------------------------------------------
  896. const char* CPlayerProfileManager::GetCurrentUser()
  897. {
  898.         return m_curUserID.c_str();
  899. }
  900.  
  901. //------------------------------------------------------------------------
  902. int CPlayerProfileManager::GetCurrentUserIndex()
  903. {
  904.         return m_curUserIndex;
  905. }
  906.  
  907. void CPlayerProfileManager::SetExclusiveControllerDeviceIndex(unsigned int exclusiveDeviceIndex)
  908. {
  909.         m_exclusiveControllerDeviceIndex = exclusiveDeviceIndex;
  910. }
  911.  
  912. unsigned int CPlayerProfileManager::GetExclusiveControllerDeviceIndex() const
  913. {
  914.         return m_exclusiveControllerDeviceIndex;
  915. }
  916.  
  917. //------------------------------------------------------------------------
  918. bool CPlayerProfileManager::ResetProfile(const char* userId)
  919. {
  920.         SUserEntry* pEntry = FindEntry(userId);
  921.         if (pEntry == 0) // no such user
  922.         {
  923.                 GameWarning("[PlayerProfiles] ResetProfile: User '%s' not logged in", userId);
  924.                 return false;
  925.         }
  926.  
  927.         if (pEntry->pCurrentProfile == 0)
  928.                 return false;
  929.  
  930.         pEntry->pCurrentProfile->Reset();
  931.         return true;
  932. }
  933.  
  934. //------------------------------------------------------------------------
  935. IPlayerProfile* CPlayerProfileManager::GetDefaultProfile()
  936. {
  937.         return m_pDefaultProfile;
  938. }
  939.  
  940. //------------------------------------------------------------------------
  941. CPlayerProfileManager::SUserEntry*
  942. CPlayerProfileManager::FindEntry(const char* userId) const
  943. {
  944.         TUserVec::const_iterator iter = m_userVec.begin();
  945.         while (iter != m_userVec.end())
  946.         {
  947.                 const SUserEntry* pEntry = *iter;
  948.                 if (pEntry->userId.compare(userId) == 0)
  949.                 {
  950.                         return (const_cast<SUserEntry*>(pEntry));
  951.                 }
  952.                 ++iter;
  953.         }
  954.         return 0;
  955. }
  956.  
  957. //------------------------------------------------------------------------
  958. CPlayerProfileManager::SUserEntry*
  959. CPlayerProfileManager::FindEntry(const char* userId, CPlayerProfileManager::TUserVec::iterator& outIter)
  960. {
  961.         TUserVec::iterator iter = m_userVec.begin();
  962.         while (iter != m_userVec.end())
  963.         {
  964.                 SUserEntry* pEntry = *iter;
  965.                 if (pEntry->userId.compare(userId) == 0)
  966.                 {
  967.                         outIter = iter;
  968.                         return pEntry;
  969.                 }
  970.                 ++iter;
  971.         }
  972.         outIter = iter;
  973.         return 0;
  974. }
  975.  
  976. //------------------------------------------------------------------------
  977. CPlayerProfileManager::SLocalProfileInfo*
  978. CPlayerProfileManager::GetLocalProfileInfo(SUserEntry* pEntry, const char* profileName) const
  979. {
  980.         std::vector<SLocalProfileInfo>::iterator iter = pEntry->profileDesc.begin();
  981.         while (iter != pEntry->profileDesc.end())
  982.         {
  983.                 SLocalProfileInfo& info = *iter;
  984.                 if (info.compare(profileName) == 0)
  985.                 {
  986.                         return &(const_cast<SLocalProfileInfo&>(info));
  987.                 }
  988.                 ++iter;
  989.         }
  990.         return 0;
  991. }
  992.  
  993. //------------------------------------------------------------------------
  994. CPlayerProfileManager::SLocalProfileInfo*
  995. CPlayerProfileManager::GetLocalProfileInfo(SUserEntry* pEntry, const char* profileName, std::vector<SLocalProfileInfo>::iterator& outIter) const
  996. {
  997.         std::vector<SLocalProfileInfo>::iterator iter = pEntry->profileDesc.begin();
  998.         while (iter != pEntry->profileDesc.end())
  999.         {
  1000.                 SLocalProfileInfo& info = *iter;
  1001.                 if (info.compare(profileName) == 0)
  1002.                 {
  1003.                         outIter = iter;
  1004.                         return &(const_cast<SLocalProfileInfo&>(info));
  1005.                 }
  1006.                 ++iter;
  1007.         }
  1008.         outIter = iter;
  1009.         return 0;
  1010. }
  1011.  
  1012. struct CSaveGameThumbnail : public ISaveGameThumbnail
  1013. {
  1014.         CSaveGameThumbnail(const string& name) : m_nRefs(0), m_name(name)
  1015.         {
  1016.         }
  1017.  
  1018.         void AddRef()
  1019.         {
  1020.                 ++m_nRefs;
  1021.         }
  1022.  
  1023.         void Release()
  1024.         {
  1025.                 if (0 == --m_nRefs)
  1026.                         delete this;
  1027.         }
  1028.  
  1029.         void GetImageInfo(int& width, int& height, int& depth)
  1030.         {
  1031.                 width = m_image.width;
  1032.                 height = m_image.height;
  1033.                 depth = m_image.depth;
  1034.         }
  1035.  
  1036.         int GetWidth()
  1037.         {
  1038.                 return m_image.width;
  1039.         }
  1040.  
  1041.         int GetHeight()
  1042.         {
  1043.                 return m_image.height;
  1044.         }
  1045.  
  1046.         int GetDepth()
  1047.         {
  1048.                 return m_image.depth;
  1049.         }
  1050.  
  1051.         const uint8* GetImageData()
  1052.         {
  1053.                 return m_image.data.begin();
  1054.         }
  1055.  
  1056.         const char* GetSaveGameName()
  1057.         {
  1058.                 return m_name;
  1059.         }
  1060.  
  1061.         CPlayerProfileManager::SThumbnail m_image;
  1062.         string                            m_name;
  1063.         int                               m_nRefs;
  1064. };
  1065.  
  1066. // TODO: currently we don't cache thumbnails.
  1067. // every entry in CPlayerProfileManager::TSaveGameInfoVec could store the thumbnail
  1068. // or we store ISaveGameThumbailPtr there.
  1069. // current access pattern (only one thumbnail at a time) doesn't call for optimization/caching
  1070. // but: maybe store also image format, so we don't need to swap RB
  1071. class CSaveGameEnumerator : public ISaveGameEnumerator
  1072. {
  1073. public:
  1074.         CSaveGameEnumerator(CPlayerProfileManager::IPlatformImpl* pImpl, CPlayerProfileManager::SUserEntry* pEntry) : m_nRefs(0), m_pImpl(pImpl), m_pEntry(pEntry)
  1075.         {
  1076.                 assert(m_pImpl != 0);
  1077.                 assert(m_pEntry != 0);
  1078.                 pImpl->GetSaveGames(m_pEntry, m_saveGameInfoVec);
  1079.         }
  1080.  
  1081.         int GetCount()
  1082.         {
  1083.                 return m_saveGameInfoVec.size();
  1084.         }
  1085.  
  1086.         bool GetDescription(int index, SGameDescription& desc)
  1087.         {
  1088.                 if (index < 0 || index >= m_saveGameInfoVec.size())
  1089.                         return false;
  1090.  
  1091.                 CPlayerProfileManager::SSaveGameInfo& info = m_saveGameInfoVec[index];
  1092.                 info.CopyTo(desc);
  1093.                 return true;
  1094.         }
  1095.  
  1096.         virtual ISaveGameThumbailPtr GetThumbnail(int index)
  1097.         {
  1098.                 if (index >= 0 && index < m_saveGameInfoVec.size())
  1099.                 {
  1100.                         ISaveGameThumbailPtr pThumbnail = new CSaveGameThumbnail(m_saveGameInfoVec[index].name);
  1101.                         CSaveGameThumbnail* pCThumbnail = static_cast<CSaveGameThumbnail*>(pThumbnail.get());
  1102.                         if (m_pImpl->GetSaveGameThumbnail(m_pEntry, m_saveGameInfoVec[index].name, pCThumbnail->m_image))
  1103.                         {
  1104.                                 return pThumbnail;
  1105.                         }
  1106.                 }
  1107.                 return 0;
  1108.         }
  1109.  
  1110.         virtual ISaveGameThumbailPtr GetThumbnail(const char* saveGameName)
  1111.         {
  1112.                 CPlayerProfileManager::TSaveGameInfoVec::const_iterator iter = m_saveGameInfoVec.begin();
  1113.                 CPlayerProfileManager::TSaveGameInfoVec::const_iterator iterEnd = m_saveGameInfoVec.end();
  1114.                 while (iter != iterEnd)
  1115.                 {
  1116.                         if (iter->name.compareNoCase(saveGameName) == 0)
  1117.                         {
  1118.                                 ISaveGameThumbailPtr pThumbnail = new CSaveGameThumbnail(iter->name);
  1119.                                 CSaveGameThumbnail* pCThumbnail = static_cast<CSaveGameThumbnail*>(pThumbnail.get());
  1120.                                 if (m_pImpl->GetSaveGameThumbnail(m_pEntry, pCThumbnail->m_name, pCThumbnail->m_image))
  1121.                                 {
  1122.                                         return pThumbnail;
  1123.                                 }
  1124.                                 return 0;
  1125.                         }
  1126.                         ++iter;
  1127.                 }
  1128.                 return 0;
  1129.         }
  1130.  
  1131.         void AddRef()
  1132.         {
  1133.                 ++m_nRefs;
  1134.         }
  1135.  
  1136.         void Release()
  1137.         {
  1138.                 if (0 == --m_nRefs)
  1139.                         delete this;
  1140.         }
  1141.  
  1142. private:
  1143.         int m_nRefs;
  1144.         CPlayerProfileManager::IPlatformImpl*   m_pImpl;
  1145.         CPlayerProfileManager::SUserEntry*      m_pEntry;
  1146.         CPlayerProfileManager::TSaveGameInfoVec m_saveGameInfoVec;
  1147. };
  1148.  
  1149. //------------------------------------------------------------------------
  1150. ISaveGameEnumeratorPtr CPlayerProfileManager::CreateSaveGameEnumerator(const char* userId, CPlayerProfile* pProfile)
  1151. {
  1152.         if (!m_bInitialized)
  1153.                 return 0;
  1154.  
  1155.         SUserEntry* pEntry = FindEntry(userId);
  1156.         if (pEntry == 0) // no such user
  1157.         {
  1158.                 GameWarning("[PlayerProfiles] CreateSaveGameEnumerator: User '%s' not logged in", userId);
  1159.                 return 0;
  1160.         }
  1161.  
  1162.         if (pEntry->pCurrentProfile == 0 || pEntry->pCurrentProfile != pProfile)
  1163.                 return 0;
  1164.  
  1165.         return new CSaveGameEnumerator(m_pImpl, pEntry);
  1166. }
  1167.  
  1168. //------------------------------------------------------------------------
  1169. ISaveGame* CPlayerProfileManager::CreateSaveGame(const char* userId, CPlayerProfile* pProfile)
  1170. {
  1171.         if (!m_bInitialized)
  1172.                 return 0;
  1173.  
  1174.         SUserEntry* pEntry = FindEntry(userId);
  1175.         if (pEntry == 0) // no such user
  1176.         {
  1177.                 GameWarning("[PlayerProfiles] CreateSaveGame: User '%s' not logged in", userId);
  1178.                 return 0;
  1179.         }
  1180.  
  1181.         if (pEntry->pCurrentProfile == 0 || pEntry->pCurrentProfile != pProfile)
  1182.                 return 0;
  1183.  
  1184.         return m_pImpl->CreateSaveGame(pEntry);
  1185. }
  1186.  
  1187. //------------------------------------------------------------------------
  1188. ILoadGame* CPlayerProfileManager::CreateLoadGame(const char* userId, CPlayerProfile* pProfile)
  1189. {
  1190.         if (!m_bInitialized)
  1191.                 return 0;
  1192.  
  1193.         SUserEntry* pEntry = FindEntry(userId);
  1194.         if (pEntry == 0) // no such user
  1195.         {
  1196.                 GameWarning("[PlayerProfiles] CreateLoadGame: User '%s' not logged in", userId);
  1197.                 return 0;
  1198.         }
  1199.  
  1200.         if (pEntry->pCurrentProfile == 0 || pEntry->pCurrentProfile != pProfile)
  1201.                 return 0;
  1202.  
  1203.         return m_pImpl->CreateLoadGame(pEntry);
  1204. }
  1205.  
  1206. //------------------------------------------------------------------------
  1207. bool CPlayerProfileManager::DeleteSaveGame(const char* userId, CPlayerProfile* pProfile, const char* name)
  1208. {
  1209.         if (!m_bInitialized)
  1210.                 return false;
  1211.  
  1212.         SUserEntry* pEntry = FindEntry(userId);
  1213.         if (pEntry == 0) // no such user
  1214.         {
  1215.                 GameWarning("[PlayerProfiles] DeleteSaveGame: User '%s' not logged in", userId);
  1216.                 return false;
  1217.         }
  1218.  
  1219.         if (pEntry->pCurrentProfile == 0 || pEntry->pCurrentProfile != pProfile)
  1220.                 return false;
  1221.  
  1222.         return m_pImpl->DeleteSaveGame(pEntry, name);
  1223. }
  1224.  
  1225. //------------------------------------------------------------------------
  1226. ILevelRotationFile* CPlayerProfileManager::GetLevelRotationFile(const char* userId, CPlayerProfile* pProfile, const char* name)
  1227. {
  1228.         if (!m_bInitialized)
  1229.                 return 0;
  1230.  
  1231.         SUserEntry* pEntry = FindEntry(userId);
  1232.         if (pEntry == 0) // no such user
  1233.         {
  1234.                 GameWarning("[PlayerProfiles] GetLevelRotationFile: User '%s' not logged in", userId);
  1235.                 return NULL;
  1236.         }
  1237.  
  1238.         if (pEntry->pCurrentProfile == 0 || pEntry->pCurrentProfile != pProfile)
  1239.                 return NULL;
  1240.  
  1241.         return m_pImpl->GetLevelRotationFile(pEntry, name);
  1242. }
  1243.  
  1244. //------------------------------------------------------------------------
  1245. bool CPlayerProfileManager::ResolveAttributeBlock(const char* userId, const char* attrBlockName, IResolveAttributeBlockListener* pListener, int reason)
  1246. {
  1247.         SUserEntry* pEntry = FindEntry(userId);
  1248.         if (pEntry == 0) // no such user
  1249.         {
  1250.                 GameWarning("[PlayerProfiles] ResolveAttributeBlock: User '%s' not logged in", userId);
  1251.                 if (pListener)
  1252.                 {
  1253.                         pListener->OnFailure();
  1254.                 }
  1255.  
  1256.                 return false;
  1257.         }
  1258.  
  1259.         if (pEntry->pCurrentProfile == NULL)
  1260.         {
  1261.                 if (pListener)
  1262.                 {
  1263.                         pListener->OnFailure();
  1264.                 }
  1265.  
  1266.                 return false;
  1267.         }
  1268.  
  1269.         return m_pImpl->ResolveAttributeBlock(pEntry, pEntry->pCurrentProfile, attrBlockName, pListener, reason);
  1270. }
  1271.  
  1272. //------------------------------------------------------------------------
  1273. bool CPlayerProfileManager::ResolveAttributeBlock(const char* userId, const SResolveAttributeRequest& attrBlockNameRequest, IResolveAttributeBlockListener* pListener, int reason)
  1274. {
  1275.         SUserEntry* pEntry = FindEntry(userId);
  1276.         if (pEntry == 0) // no such user
  1277.         {
  1278.                 GameWarning("[PlayerProfiles] ResolveAttributeBlock: User '%s' not logged in", userId);
  1279.                 if (pListener)
  1280.                 {
  1281.                         pListener->OnFailure();
  1282.                 }
  1283.  
  1284.                 return false;
  1285.         }
  1286.  
  1287.         if (pEntry->pCurrentProfile == NULL)
  1288.         {
  1289.                 GameWarning("[PlayerProfiles] ResolveAttributeBlock: User '%s' doesn't have a profile", userId);
  1290.                 if (pListener)
  1291.                 {
  1292.                         pListener->OnFailure();
  1293.                 }
  1294.  
  1295.                 return false;
  1296.         }
  1297.  
  1298.         return m_pImpl->ResolveAttributeBlock(pEntry, pEntry->pCurrentProfile, attrBlockNameRequest, pListener, reason);
  1299. }
  1300.  
  1301. //------------------------------------------------------------------------
  1302. void CPlayerProfileManager::SetSharedSaveGameFolder(const char* sharedSaveGameFolder)
  1303. {
  1304.         m_sharedSaveGameFolder = sharedSaveGameFolder;
  1305.         m_sharedSaveGameFolder.TrimRight("/\\");
  1306. }
  1307.  
  1308. //------------------------------------------------------------------------
  1309. void CPlayerProfileManager::AddListener(IPlayerProfileListener* pListener, bool updateNow)
  1310. {
  1311.         m_listeners.reserve(8);
  1312.         stl::push_back_unique(m_listeners, pListener);
  1313.  
  1314.         if (updateNow)
  1315.         {
  1316.                 // allow new listener to init from the current profile
  1317.                 if (IPlayerProfile* pCurrentProfile = GetCurrentProfile(GetCurrentUser()))
  1318.                 {
  1319.                         pListener->LoadFromProfile(pCurrentProfile, false, ePR_All);
  1320.                 }
  1321.         }
  1322. }
  1323.  
  1324. //------------------------------------------------------------------------
  1325. void CPlayerProfileManager::RemoveListener(IPlayerProfileListener* pListener)
  1326. {
  1327.         stl::find_and_erase(m_listeners, pListener);
  1328. }
  1329.  
  1330. //------------------------------------------------------------------------
  1331. void CPlayerProfileManager::AddOnlineAttributesListener(IOnlineAttributesListener* pListener)
  1332. {
  1333.         CRY_ASSERT_MESSAGE(m_onlineAttributesListener == NULL, "PlayerProfileManager only handles a single OnlineAttributes Listener");
  1334.         m_onlineAttributesListener = pListener;
  1335. }
  1336.  
  1337. //------------------------------------------------------------------------
  1338. void CPlayerProfileManager::RemoveOnlineAttributesListener(IOnlineAttributesListener* pListener)
  1339. {
  1340.         CRY_ASSERT_MESSAGE(m_onlineAttributesListener == pListener, "Can't remove listener that hasn't been added!");
  1341.         if (m_onlineAttributesListener == pListener)
  1342.         {
  1343.                 m_onlineAttributesListener = NULL;
  1344.         }
  1345. }
  1346.  
  1347. //------------------------------------------------------------------------
  1348. void CPlayerProfileManager::SetOnlineAttributesState(const IOnlineAttributesListener::EEvent event, const IOnlineAttributesListener::EState newState)
  1349. {
  1350.         if (m_onlineAttributesState[event] != newState)
  1351.         {
  1352.                 m_onlineAttributesState[event] = newState;
  1353.                 SendOnlineAttributeState(event, newState);
  1354.         }
  1355. }
  1356.  
  1357. //------------------------------------------------------------------------
  1358. void CPlayerProfileManager::SendOnlineAttributeState(const IOnlineAttributesListener::EEvent event, const IOnlineAttributesListener::EState newState)
  1359. {
  1360.         if (m_onlineAttributesListener)
  1361.         {
  1362.                 m_onlineAttributesListener->OnlineAttributeState(event, newState);
  1363.         }
  1364. }
  1365.  
  1366. //------------------------------------------------------------------------
  1367. void CPlayerProfileManager::GetOnlineAttributesState(const IOnlineAttributesListener::EEvent event, IOnlineAttributesListener::EState& state) const
  1368. {
  1369.         CRY_ASSERT(event > IOnlineAttributesListener::eOAE_Invalid && event < IOnlineAttributesListener::eOAE_Max);
  1370.         state = m_onlineAttributesState[event];
  1371. }
  1372.  
  1373. //------------------------------------------------------------------------
  1374. void CPlayerProfileManager::EnableOnlineAttributes(bool enable)
  1375. {
  1376.         m_enableOnlineAttributes = enable;
  1377. }
  1378.  
  1379. //------------------------------------------------------------------------
  1380. // if saving and loading online is enabled
  1381. bool CPlayerProfileManager::HasEnabledOnlineAttributes() const
  1382. {
  1383.         return m_enableOnlineAttributes;
  1384. }
  1385.  
  1386. //------------------------------------------------------------------------
  1387. // if saving and loading online is possible
  1388. bool CPlayerProfileManager::CanProcessOnlineAttributes() const
  1389. {
  1390.         return m_allowedToProcessOnlineAttributes;
  1391. }
  1392.  
  1393. //------------------------------------------------------------------------
  1394. // whether the game is in a state that it can save/load online attributes - e.g. when in a mp game session is in progress saving online is disabled
  1395. void CPlayerProfileManager::SetCanProcessOnlineAttributes(bool enable)
  1396. {
  1397.         m_allowedToProcessOnlineAttributes = enable;
  1398. }
  1399.  
  1400. //------------------------------------------------------------------------
  1401. bool CPlayerProfileManager::IsOnlineOnlyAttribute(const char* name)
  1402. {
  1403.         if (m_enableOnlineAttributes && m_registered)
  1404.         {
  1405.                 TOnlineAttributeMap::const_iterator end = m_onlineAttributeMap.end();
  1406.  
  1407.                 TOnlineAttributeMap::const_iterator attr = m_onlineAttributeMap.find(name);
  1408.                 if (attr != end)
  1409.                 {
  1410.                         uint32 index = attr->second;
  1411.                         CRY_ASSERT(index >= 0 && index <= m_onlineDataCount);
  1412.                         return m_onlineOnlyData[index];
  1413.                 }
  1414.         }
  1415.  
  1416.         return false;
  1417. }
  1418.  
  1419. //------------------------------------------------------------------------
  1420. bool CPlayerProfileManager::RegisterOnlineAttributes()
  1421. {
  1422.         LOADING_TIME_PROFILE_SECTION;
  1423.         ECryLobbyError error = eCLE_ServiceNotSupported;
  1424.         ICryStats* stats = gEnv->pLobby ? gEnv->pLobby->GetStats() : nullptr;
  1425.  
  1426.         IOnlineAttributesListener::EState currentState = IOnlineAttributesListener::eOAS_None;
  1427.         GetOnlineAttributesState(IOnlineAttributesListener::eOAE_Register, currentState);
  1428.  
  1429.         if (stats && !m_registered)
  1430.         {
  1431.                 if (currentState != IOnlineAttributesListener::eOAS_Processing)
  1432.                 {
  1433.                         XmlNodeRef xmlData = GetISystem()->LoadXmlFromFile(ONLINE_ATTRIBUTES_DEFINITION_FILE);
  1434.                         if (xmlData)
  1435.                         {
  1436.                                 xmlData->getAttr("version", m_onlineAttributeDefinedVersion);
  1437.  
  1438.                                 CCrc32 crc;
  1439.  
  1440.                                 const int attributeCount = xmlData->getChildCount();
  1441.  
  1442.                                 m_onlineAttributeMap.reserve(2 + attributeCount);
  1443.  
  1444.                                 {
  1445.                                         SCryLobbyUserData defaultData;
  1446.                                         defaultData.m_type = eCLUDT_Int32;
  1447.                                         defaultData.m_id = m_onlineDataCount;
  1448.                                         RegisterOnlineAttribute("checksum0", "int", true, defaultData, crc);
  1449.                                         defaultData.m_id = m_onlineDataCount;
  1450.                                         RegisterOnlineAttribute("checksum1", "int", true, defaultData, crc);
  1451.                                         CRY_ASSERT(0 == GetOnlineAttributeIndexByName("checksum0"));
  1452.                                         CRY_ASSERT(1 == GetOnlineAttributeIndexByName("checksum1"));
  1453.                                         CRY_ASSERT(m_onlineDataCount == k_onlineChecksums);
  1454.                                 }
  1455.  
  1456.                                 for (int i = 0; i < attributeCount; i++)
  1457.                                 {
  1458.                                         XmlNodeRef attributeData = xmlData->getChild(i);
  1459.                                         const char* name = attributeData->getAttr("name");
  1460.                                         const char* type = attributeData->getAttr("type");
  1461.                                         bool onlineOnly = true;
  1462.                                         attributeData->getAttr("onlineOnly", onlineOnly);
  1463.  
  1464.                                         SCryLobbyUserData defaultValue;
  1465.                                         GetDefaultValue(type, attributeData, &defaultValue);
  1466.  
  1467.                                         if (!RegisterOnlineAttribute(name, type, onlineOnly, defaultValue, crc))
  1468.                                         {
  1469.                                                 CRY_ASSERT_TRACE(false, ("Fail to register attribute %s - not enough space DataSlots %d/%d and Bytes %d/%d", name, m_onlineDataCount, k_maxOnlineDataCount, m_onlineDataByteCount, k_maxOnlineDataBytes));
  1470.                                                 SetOnlineAttributesState(IOnlineAttributesListener::eOAE_Register, IOnlineAttributesListener::eOAS_Failed);
  1471.                                                 return false;
  1472.                                         }
  1473.                                 }
  1474.  
  1475.                                 CryLog("RegisterOnlineAttributes '%u' values in '%u' bytes", m_onlineDataCount, m_onlineDataByteCount);
  1476.                                 error = stats->StatsRegisterUserData(m_onlineData, m_onlineDataCount, NULL, CPlayerProfileManager::RegisterUserDataCallback, this);
  1477.                                 CRY_ASSERT(error == eCLE_Success);
  1478.  
  1479.                                 m_onlineAttributeAutoGeneratedVersion = crc.Get();
  1480.                         }
  1481.                         else
  1482.                         {
  1483.                                 CryWarning(VALIDATOR_MODULE_GAME, VALIDATOR_ERROR, "Unable to load '%s'", ONLINE_ATTRIBUTES_DEFINITION_FILE);
  1484.                         }
  1485.                 }
  1486.                 else
  1487.                 {
  1488.                         error = eCLE_Success;
  1489.                 }
  1490.         }
  1491.         const bool success = (error == eCLE_Success);
  1492.         if (success)
  1493.         {
  1494.                 SetOnlineAttributesState(IOnlineAttributesListener::eOAE_Register, IOnlineAttributesListener::eOAS_Processing);
  1495.         }
  1496.         else
  1497.         {
  1498.                 SetOnlineAttributesState(IOnlineAttributesListener::eOAE_Register, IOnlineAttributesListener::eOAS_Failed);
  1499.         }
  1500.         return success;
  1501. }
  1502.  
  1503. //------------------------------------------------------------------------
  1504. bool CPlayerProfileManager::RegisterOnlineAttribute(const char* name, const char* type, const bool onlineOnly, const SCryLobbyUserData& defaultValue, CCrc32& crc)
  1505. {
  1506.         m_onlineOnlyData[m_onlineDataCount] = onlineOnly;
  1507.  
  1508.         if (SetUserDataType(&m_onlineData[m_onlineDataCount], type))
  1509.         {
  1510.                 m_defaultOnlineData[m_onlineDataCount] = defaultValue;
  1511.                 m_onlineDataByteCount += UserDataSize(&m_onlineData[m_onlineDataCount]);
  1512.                 if (m_onlineDataCount >= k_maxOnlineDataCount || m_onlineDataByteCount >= k_maxOnlineDataBytes)
  1513.                 {
  1514.                         return false;  // fail because it doesn't fit
  1515.                 }
  1516. #if USE_STEAM // on steam we look up by name not by index
  1517.                 m_onlineData[m_onlineDataCount].m_id = string(name);
  1518. #endif
  1519.                 m_onlineAttributeMap[name] = m_onlineDataCount;
  1520.                 m_onlineDataCount++;
  1521.                 crc.Add(name);
  1522.         }
  1523.  
  1524.         return true;
  1525. }
  1526.  
  1527. //------------------------------------------------------------------------
  1528. bool CPlayerProfileManager::SetUserDataType(SCryLobbyUserData* data, const char* type)
  1529. {
  1530.         if (strcmpi(type, "int") == 0)
  1531.         {
  1532.                 data->m_type = eCLUDT_Int32;
  1533.                 data->m_int32 = 0;
  1534.         }
  1535.         else if (strcmpi(type, "int16") == 0)
  1536.         {
  1537.                 data->m_type = eCLUDT_Int16;
  1538.                 data->m_int16 = 0;
  1539.         }
  1540.         else if (strcmpi(type, "int8") == 0)
  1541.         {
  1542.                 data->m_type = eCLUDT_Int8;
  1543.                 data->m_int8 = 0;
  1544.         }
  1545.         else if (strcmpi(type, "float") == 0)
  1546.         {
  1547.                 data->m_type = eCLUDT_Float32;
  1548.                 data->m_f32 = 0.0f;
  1549.         }
  1550.         else
  1551.         {
  1552.                 CryWarning(VALIDATOR_MODULE_GAME, VALIDATOR_ERROR, "Unrecognized UserDataType - '%s'", type);
  1553.                 return false;
  1554.         }
  1555.  
  1556.         data->m_id = m_onlineDataCount;
  1557.         return true;
  1558. }
  1559.  
  1560. //------------------------------------------------------------------------
  1561. void CPlayerProfileManager::GetDefaultValue(const char* type, XmlNodeRef attributeNode, SCryLobbyUserData* pOutData)
  1562. {
  1563.         if (strcmpi(type, "int") == 0)
  1564.         {
  1565.                 pOutData->m_type = eCLUDT_Int32;
  1566.                 pOutData->m_int32 = 0;
  1567.                 attributeNode->getAttr("defaultValue", pOutData->m_int32);
  1568.         }
  1569.         else if (strcmpi(type, "int16") == 0)
  1570.         {
  1571.                 pOutData->m_type = eCLUDT_Int16;
  1572.                 pOutData->m_int16 = 0;
  1573.                 int iValue = 0;
  1574.                 attributeNode->getAttr("defaultValue", iValue);
  1575.                 pOutData->m_int16 = (int16) iValue;
  1576.         }
  1577.         else if (strcmpi(type, "int8") == 0)
  1578.         {
  1579.                 pOutData->m_type = eCLUDT_Int8;
  1580.                 pOutData->m_int8 = 0;
  1581.                 int iValue = 0;
  1582.                 attributeNode->getAttr("defaultValue", iValue);
  1583.                 pOutData->m_int8 = (int8) iValue;
  1584.         }
  1585.         else if (strcmpi(type, "float") == 0)
  1586.         {
  1587.                 pOutData->m_type = eCLUDT_Float32;
  1588.                 pOutData->m_f32 = 0.0f;
  1589.                 attributeNode->getAttr("defaultValue", pOutData->m_f32);
  1590.         }
  1591.         else
  1592.         {
  1593.                 CryWarning(VALIDATOR_MODULE_GAME, VALIDATOR_ERROR, "Unrecognized UserDataType - '%s'", type);
  1594.         }
  1595.  
  1596.         pOutData->m_id = m_onlineDataCount;
  1597. }
  1598.  
  1599. //------------------------------------------------------------------------
  1600. void CPlayerProfileManager::LoadOnlineAttributes(IPlayerProfile* pProfile)
  1601. {
  1602.         bool success = false;
  1603.  
  1604.         CRY_ASSERT(m_allowedToProcessOnlineAttributes);
  1605.  
  1606.         SetOnlineAttributesState(IOnlineAttributesListener::eOAE_Load, IOnlineAttributesListener::eOAS_Processing);
  1607.  
  1608.         if (m_enableOnlineAttributes)
  1609.         {
  1610.                 if (m_registered && m_pReadingProfile == NULL)
  1611.                 {
  1612.                         ICryStats* pStats = gEnv->pLobby ? gEnv->pLobby->GetStats() : nullptr;
  1613.                         if (pStats)
  1614.                         {
  1615.                                 m_pReadingProfile = pProfile;
  1616.                                 ECryLobbyError error = pStats->StatsReadUserData(GetExclusiveControllerDeviceIndex(), &m_lobbyTaskId, CPlayerProfileManager::ReadUserDataCallback, this);
  1617.                                 success = (error == eCLE_Success);
  1618.                         }
  1619. #if !defined(_RELEASE) && !defined(DEDICATED_SERVER) && !defined(PURE_CLIENT)
  1620.                         else
  1621.                         {
  1622.                                 CryLog("[profile] no stats module, defaulting to success");
  1623.                                 success = true;
  1624.                                 SetOnlineAttributesState(IOnlineAttributesListener::eOAE_Load, IOnlineAttributesListener::eOAS_Success);
  1625.                         }
  1626. #endif
  1627.                 }
  1628.         }
  1629.  
  1630.         if (!success)
  1631.         {
  1632.                 SetOnlineAttributesState(IOnlineAttributesListener::eOAE_Load, IOnlineAttributesListener::eOAS_Failed);
  1633.                 m_pReadingProfile = NULL;
  1634.                 m_lobbyTaskId = CryLobbyInvalidTaskID;
  1635.         }
  1636. }
  1637.  
  1638. //------------------------------------------------------------------------
  1639. void CPlayerProfileManager::SaveOnlineAttributes(IPlayerProfile* pProfile)
  1640. {
  1641.         CRY_ASSERT(m_allowedToProcessOnlineAttributes);
  1642.  
  1643.         if (m_enableOnlineAttributes)
  1644.         {
  1645.                 if (m_registered)
  1646.                 {
  1647.                         TFlowInputData versionData(GetOnlineAttributesVersion());
  1648.                         pProfile->SetAttribute(ONLINE_VERSION_ATTRIBUTE_NAME, versionData);
  1649.  
  1650.                         const int listenerSize = m_listeners.size();
  1651.                         for (int i = 0; i < listenerSize; i++)
  1652.                         {
  1653.                                 m_listeners[i]->SaveToProfile(pProfile, true, ePR_All); // TODO: perhaps this wants to only be ePR_Options, or needs an extra check?
  1654.                         }
  1655.  
  1656.                         //update online attributes from current profile
  1657.                         TOnlineAttributeMap::const_iterator end = m_onlineAttributeMap.end();
  1658.                         TOnlineAttributeMap::const_iterator iter = m_onlineAttributeMap.begin();
  1659.                         while (iter != end)
  1660.                         {
  1661.                                 if (iter->second >= k_onlineChecksums)
  1662.                                 {
  1663.                                         TFlowInputData data;
  1664.                                         bool hasAttr = pProfile->GetAttribute(iter->first.c_str(), data);
  1665.                                         CRY_ASSERT_MESSAGE(hasAttr, ("Expected %s to be set by SavingOnlineAttributes but wasn't", iter->first.c_str()));
  1666.                                         SetUserData(&m_onlineData[iter->second], data);
  1667.                                 }
  1668.  
  1669.                                 ++iter;
  1670.                         }
  1671.  
  1672.                         ApplyChecksums(m_onlineData, m_onlineDataCount);
  1673.  
  1674.                         //upload results
  1675.                         ICryStats* pStats = gEnv->pLobby ? gEnv->pLobby->GetStats() : nullptr;
  1676.                         if (pStats && pStats->GetLeaderboardType() == eCLLT_P2P)
  1677.                         {
  1678.                                 ECryLobbyError error = pStats->StatsWriteUserData(GetExclusiveControllerDeviceIndex(), m_onlineData, m_onlineDataCount, NULL, CPlayerProfileManager::WriteUserDataCallback, this);
  1679.                                 CRY_ASSERT(error == eCLE_Success);
  1680.                         }
  1681.                 }
  1682.         }
  1683. }
  1684.  
  1685. void CPlayerProfileManager::ClearOnlineAttributes()
  1686. {
  1687.         // network cleanup
  1688.         if (m_lobbyTaskId != CryLobbyInvalidTaskID)
  1689.         {
  1690.                 ICryStats* pStats = gEnv->pLobby ? gEnv->pLobby->GetStats() : nullptr;
  1691.                 if (pStats)
  1692.                 {
  1693.                         pStats->CancelTask(m_lobbyTaskId);
  1694.                 }
  1695.  
  1696.                 m_lobbyTaskId = CryLobbyInvalidTaskID;
  1697.         }
  1698.  
  1699.         m_pReadingProfile = NULL;
  1700.         m_onlineAttributesState[IOnlineAttributesListener::eOAE_Load] = IOnlineAttributesListener::eOAS_None;
  1701. }
  1702.  
  1703. void CPlayerProfileManager::LoadGamerProfileDefaults(IPlayerProfile* pProfile)
  1704. {
  1705.         CPlayerProfile* pDefaultProfile = m_pDefaultProfile;
  1706.         m_pDefaultProfile = NULL;
  1707.         pProfile->LoadGamerProfileDefaults();
  1708.         m_pDefaultProfile = pDefaultProfile;
  1709. }
  1710.  
  1711. void CPlayerProfileManager::ReloadProfile(IPlayerProfile* pProfile, unsigned int reason)
  1712. {
  1713.         TListeners::const_iterator it = m_listeners.begin(), itend = m_listeners.end();
  1714.         for (; it != itend; ++it)
  1715.         {
  1716.                 (*it)->LoadFromProfile(pProfile, false, reason);
  1717.         }
  1718. }
  1719.  
  1720. void CPlayerProfileManager::SetOnlineAttributes(IPlayerProfile* pProfile, const SCryLobbyUserData* pData, const int32 onlineDataCount)
  1721. {
  1722.         CRY_ASSERT(pProfile);
  1723.  
  1724.         if (pProfile)
  1725.         {
  1726.                 ReadOnlineAttributes(pProfile, pData, onlineDataCount);
  1727.         }
  1728. }
  1729.  
  1730. //------------------------------------------------------------------------
  1731. uint32 CPlayerProfileManager::GetOnlineAttributes(SCryLobbyUserData* pData, uint32 numData)
  1732. {
  1733.         uint32 numCopied = 0;
  1734.  
  1735.         if (pData && numData > 0)
  1736.         {
  1737.                 numCopied = (numData > m_onlineDataCount) ? m_onlineDataCount : numData;
  1738.                 memcpy(pData, m_onlineData, (sizeof(SCryLobbyUserData) * numCopied));
  1739.         }
  1740.  
  1741.         return numCopied;
  1742. }
  1743.  
  1744. //------------------------------------------------------------------------
  1745. uint32 CPlayerProfileManager::GetDefaultOnlineAttributes(SCryLobbyUserData* pData, uint32 numData)
  1746. {
  1747.         uint32 numCopied = 0;
  1748.  
  1749.         if (pData && numData > 0)
  1750.         {
  1751.                 numCopied = (numData > m_onlineDataCount) ? m_onlineDataCount : numData;
  1752.                 memcpy(pData, m_defaultOnlineData, (sizeof(SCryLobbyUserData) * numCopied));
  1753.         }
  1754.  
  1755.         return numCopied;
  1756. }
  1757.  
  1758. //------------------------------------------------------------------------
  1759. bool CPlayerProfileManager::SetUserData(SCryLobbyUserData* data, const TFlowInputData& value)
  1760. {
  1761.         switch (data->m_type)
  1762.         {
  1763.         case eCLUDT_Int8:
  1764.         case eCLUDT_Int16:
  1765.         case eCLUDT_Int32:
  1766.                 {
  1767.                         const int* pInt = NULL;
  1768.                         int stringValue = 0;
  1769.                         if (const string* pString = value.GetPtr<string>())
  1770.                         {
  1771.                                 stringValue = atoi(pString->c_str());
  1772.                                 pInt = &stringValue;
  1773.                         }
  1774.                         else
  1775.                         {
  1776.                                 pInt = value.GetPtr<int>();
  1777.                         }
  1778.  
  1779.                         if (pInt)
  1780.                         {
  1781.                                 if (data->m_type == eCLUDT_Int32)
  1782.                                 {
  1783.                                         data->m_int32 = (*pInt);
  1784.                                 }
  1785.                                 else if (data->m_type == eCLUDT_Int16)
  1786.                                 {
  1787.                                         data->m_int16 = (*pInt);
  1788.                                 }
  1789.                                 else if (data->m_type == eCLUDT_Int8)
  1790.                                 {
  1791.                                         data->m_int8 = (*pInt);
  1792.                                 }
  1793.                                 else
  1794.                                 {
  1795.                                         CRY_ASSERT_MESSAGE(false, "TFlowInputData int didn't match UserData types");
  1796.                                         return false;
  1797.                                 }
  1798.                                 return true;
  1799.                         }
  1800.                         //This can be removed when CryNetwork adds support for bools in user data
  1801.                         else if (const bool* pBool = value.GetPtr<bool>())
  1802.                         {
  1803.                                 if (data->m_type == eCLUDT_Int8)
  1804.                                 {
  1805.                                         data->m_int8 = (*pBool);
  1806.                                 }
  1807.                                 else
  1808.                                 {
  1809.                                         CRY_ASSERT_MESSAGE(false, "TFlowInputData int didn't match UserData types");
  1810.                                         return false;
  1811.                                 }
  1812.                                 return true;
  1813.                         }
  1814.                         else
  1815.                         {
  1816.                                 CRY_ASSERT_MESSAGE(false, "TFlowInputData didn't contain expected int/bool");
  1817.                                 return false;
  1818.                         }
  1819.                 }
  1820.                 break;
  1821.         case eCLUDT_Float32:
  1822.                 {
  1823.                         const float* pFloat = NULL;
  1824.                         float stringValue = 0.0f;
  1825.                         if (const string* pString = value.GetPtr<string>())
  1826.                         {
  1827.                                 stringValue = (float) atof(pString->c_str());
  1828.                                 pFloat = &stringValue;
  1829.                         }
  1830.                         else
  1831.                         {
  1832.                                 pFloat = value.GetPtr<float>();
  1833.                         }
  1834.  
  1835.                         if (pFloat)
  1836.                         {
  1837.                                 data->m_f32 = (*pFloat);
  1838.                                 return true;
  1839.                         }
  1840.                         else
  1841.                         {
  1842.                                 CRY_ASSERT_MESSAGE(false, "TFlowInputData didn't contain expected float");
  1843.                                 return false;
  1844.                         }
  1845.                 }
  1846.                 break;
  1847.         }
  1848.  
  1849.         CRY_ASSERT_MESSAGE(false, "Unable to store data size");
  1850.         return false;
  1851. }
  1852.  
  1853. //------------------------------------------------------------------------
  1854. bool CPlayerProfileManager::ReadUserData(const SCryLobbyUserData* data, TFlowInputData& val)
  1855. {
  1856.         switch (data->m_type)
  1857.         {
  1858.         case eCLUDT_Int32:
  1859.                 {
  1860.                         val.Set(data->m_int32);
  1861.                         return true;
  1862.                 }
  1863.                 break;
  1864.         case eCLUDT_Int16:
  1865.                 {
  1866.                         val.Set((int) data->m_int16);
  1867.                         return true;
  1868.                 }
  1869.                 break;
  1870.         case eCLUDT_Int8:
  1871.                 {
  1872.                         val.Set((int) data->m_int8);
  1873.                         return true;
  1874.                 }
  1875.                 break;
  1876.         case eCLUDT_Float32:
  1877.                 {
  1878.                         val.Set(data->m_f32);
  1879.                         return true;
  1880.                 }
  1881.                 break;
  1882.         }
  1883.  
  1884.         CRY_ASSERT_MESSAGE(false, "Unable to read data size");
  1885.         return false;
  1886. }
  1887.  
  1888. //------------------------------------------------------------------------
  1889. uint32 CPlayerProfileManager::UserDataSize(const SCryLobbyUserData* data)
  1890. {
  1891.         switch (data->m_type)
  1892.         {
  1893.         case eCLUDT_Int32:
  1894.                 {
  1895.                         return sizeof(data->m_int32);
  1896.                 }
  1897.         case eCLUDT_Int16:
  1898.                 {
  1899.                         return sizeof(data->m_int16);
  1900.                 }
  1901.         case eCLUDT_Int8:
  1902.                 {
  1903.                         return sizeof(data->m_int8);
  1904.                 }
  1905.         case eCLUDT_Float32:
  1906.                 {
  1907.                         return sizeof(data->m_f32);
  1908.                 }
  1909.         }
  1910.  
  1911.         CRY_ASSERT_MESSAGE(0, "Unsupported LobbyUserData type");
  1912.         return 0;
  1913. }
  1914.  
  1915. //static------------------------------------------------------------------------
  1916. void CPlayerProfileManager::ReadUserDataCallback(CryLobbyTaskID taskID, ECryLobbyError error, SCryLobbyUserData* pData, uint32 numData, void* pArg)
  1917. {
  1918.         CPlayerProfileManager* pManager = static_cast<CPlayerProfileManager*>(pArg);
  1919.         CRY_ASSERT(pManager);
  1920.  
  1921.         if (error == eCLE_Success && pManager->m_pReadingProfile)
  1922.         {
  1923.                 pManager->ReadOnlineAttributes(pManager->m_pReadingProfile, pData, numData);
  1924.                 pManager->SetOnlineAttributesState(IOnlineAttributesListener::eOAE_Load, IOnlineAttributesListener::eOAS_Success);
  1925.  
  1926. #if PROFILE_DEBUG_COMMANDS
  1927.                 if (pManager->m_testingPhase == 2)
  1928.                 {
  1929.                         DbgTestOnlineAttributes(NULL);
  1930.                 }
  1931. #endif
  1932.         }
  1933.         else if ((error == eCLE_ReadDataNotWritten) || (error == eCLE_ReadDataCorrupt))
  1934.         {
  1935.                 CryWarning(VALIDATOR_MODULE_GAME, VALIDATOR_COMMENT, "OnlineAttributes - ReadDataNotWritten");
  1936.                 if (pManager->m_pReadingProfile)
  1937.                 {
  1938.                         TOnlineAttributeMap::const_iterator iter = pManager->m_onlineAttributeMap.begin();
  1939.                         TOnlineAttributeMap::const_iterator end = pManager->m_onlineAttributeMap.end();
  1940.                         TFlowInputData blankData;
  1941.                         while (iter != end)
  1942.                         {
  1943.                                 pManager->m_pReadingProfile->DeleteAttribute(iter->first);
  1944.                                 ++iter;
  1945.                         }
  1946.  
  1947.                         pManager->ReloadProfile(pManager->m_pReadingProfile, ePR_All);
  1948.                 }
  1949.                 pManager->SetOnlineAttributesState(IOnlineAttributesListener::eOAE_Load, IOnlineAttributesListener::eOAS_Success);
  1950.         }
  1951.         else
  1952.         {
  1953.                 pManager->SetOnlineAttributesState(IOnlineAttributesListener::eOAE_Load, IOnlineAttributesListener::eOAS_Failed);
  1954.         }
  1955.  
  1956.         pManager->m_pReadingProfile = NULL;
  1957.         pManager->m_lobbyTaskId = CryLobbyInvalidTaskID;
  1958. }
  1959.  
  1960. //-----------------------------------------------------------------------------
  1961. void CPlayerProfileManager::ReadOnlineAttributes(IPlayerProfile* pProfile, const SCryLobbyUserData* pData, const uint32 numData)
  1962. {
  1963.         CRY_ASSERT(numData == m_onlineDataCount);
  1964.  
  1965. #if PROFILE_DEBUG_COMMANDS
  1966.         if (m_testingPhase == 2)
  1967.         {
  1968.                 memcpy(m_onlineData, pData, sizeof(m_onlineData));
  1969.         }
  1970. #endif
  1971.  
  1972.         if (sLoadOnlineAttributes)
  1973.         {
  1974.                 TOnlineAttributeMap::const_iterator end = m_onlineAttributeMap.end();
  1975.  
  1976.                 TOnlineAttributeMap::const_iterator versionIter = m_onlineAttributeMap.find(ONLINE_VERSION_ATTRIBUTE_NAME);
  1977.                 if (versionIter != end)
  1978.                 {
  1979.                         TFlowInputData versionData;
  1980.                         ReadUserData(&pData[versionIter->second], versionData);
  1981.  
  1982.                         const int* pInt = versionData.GetPtr<int>();
  1983.                         if (pInt)
  1984.                         {
  1985.                                 const int version = *pInt;
  1986.                                 if (version == GetOnlineAttributesVersion())
  1987.                                 {
  1988.  
  1989.                                         if (ValidChecksums(pData, m_onlineDataCount))
  1990.                                         {
  1991.                                                 TOnlineAttributeMap::const_iterator iter = m_onlineAttributeMap.begin();
  1992.  
  1993.                                                 while (iter != end)
  1994.                                                 {
  1995.                                                         TFlowInputData data;
  1996.                                                         ReadUserData(&pData[iter->second], data);
  1997.                                                         pProfile->SetAttribute(iter->first, data);
  1998.                                                         ++iter;
  1999.                                                 }
  2000.  
  2001.                                                 const int listenerSize = m_listeners.size();
  2002.                                                 for (int i = 0; i < listenerSize; i++)
  2003.                                                 {
  2004.                                                         m_listeners[i]->LoadFromProfile(pProfile, true, ePR_All); // TODO: perhaps this only wants to be ePR_Options or needs an extra check?
  2005.                                                 }
  2006.                                         }
  2007.                                         else
  2008.                                         {
  2009.                                                 CryWarning(VALIDATOR_MODULE_GAME, VALIDATOR_ERROR, "OnlineAttributes - Checksum was invalid (Not reading online attributes)");
  2010.                                         }
  2011.                                 }
  2012.                                 else
  2013.                                 {
  2014.                                         CryWarning(VALIDATOR_MODULE_GAME, VALIDATOR_ERROR, "OnlineAttributes - version mismatch (Not reading online attributes)");
  2015.                                 }
  2016.                         }
  2017.                         else
  2018.                         {
  2019.                                 CryWarning(VALIDATOR_MODULE_GAME, VALIDATOR_ERROR, "OnlineAttributes - version data invalid (Not reading online attributes)");
  2020.                         }
  2021.                 }
  2022.                 else
  2023.                 {
  2024.                         CryWarning(VALIDATOR_MODULE_GAME, VALIDATOR_ERROR, "OnlineAttributes - version missing (Not reading online attributes)");
  2025.                 }
  2026.         }
  2027.         else
  2028.         {
  2029.                 CryWarning(VALIDATOR_MODULE_GAME, VALIDATOR_COMMENT, "OnlineAttributes - not loading by request!");
  2030.         }
  2031. }
  2032.  
  2033. //------------------------------------------------------------------------
  2034. int CPlayerProfileManager::GetOnlineAttributesVersion() const
  2035. {
  2036.         return m_onlineAttributeAutoGeneratedVersion + m_onlineAttributeDefinedVersion;
  2037. }
  2038.  
  2039. //------------------------------------------------------------------------
  2040. int CPlayerProfileManager::GetOnlineAttributeIndexByName(const char* name)
  2041. {
  2042.         TOnlineAttributeMap::const_iterator end = m_onlineAttributeMap.end();
  2043.         TOnlineAttributeMap::const_iterator versionIter = m_onlineAttributeMap.find(name);
  2044.         int index = -1;
  2045.  
  2046.         if (versionIter != end)
  2047.         {
  2048.                 index = versionIter->second;
  2049.         }
  2050.  
  2051.         return index;
  2052. }
  2053.  
  2054. //------------------------------------------------------------------------
  2055. void CPlayerProfileManager::GetOnlineAttributesDataFormat(SCryLobbyUserData* pData, uint32 numData)
  2056. {
  2057.         uint32 numToGet = (numData > m_onlineDataCount) ? m_onlineDataCount : numData;
  2058.  
  2059.         for (int i = 0; i < numToGet; i++)
  2060.         {
  2061.                 pData[i].m_id = m_onlineData[i].m_id;
  2062.                 pData[i].m_type = m_onlineData[i].m_type;
  2063.         }
  2064. }
  2065.  
  2066. //------------------------------------------------------------------------
  2067. uint32 CPlayerProfileManager::GetOnlineAttributeCount()
  2068. {
  2069.         return m_onlineDataCount;
  2070. }
  2071.  
  2072. //------------------------------------------------------------------------
  2073. int CPlayerProfileManager::ChecksumConvertValueToInt(const SCryLobbyUserData* pData)
  2074. {
  2075.         int value = 0;
  2076.  
  2077.         switch (pData->m_type)
  2078.         {
  2079.         case eCLUDT_Int8:
  2080.                 value = (int)pData->m_int8;
  2081.                 break;
  2082.         case eCLUDT_Int16:
  2083.                 value = (int)pData->m_int16;
  2084.                 break;
  2085.         case eCLUDT_Int32:
  2086.                 value = (int)pData->m_int32;
  2087.                 break;
  2088.         case eCLUDT_Float32:
  2089.                 value = (int)pData->m_f32;
  2090.                 break;
  2091.         default:
  2092.                 CRY_ASSERT_MESSAGE(0, string().Format("Unknown data type in online attribute data", pData->m_type));
  2093.                 break;
  2094.         }
  2095.  
  2096.         return value;
  2097. }
  2098.  
  2099. //------------------------------------------------------------------------
  2100. void CPlayerProfileManager::ApplyChecksums(SCryLobbyUserData* pData, uint32 numData)
  2101. {
  2102.         for (int i = 0; i < k_onlineChecksums; i++)
  2103.         {
  2104.                 pData[i].m_int32 = Checksum(i, pData, numData);
  2105.         }
  2106. }
  2107.  
  2108. //------------------------------------------------------------------------
  2109. bool CPlayerProfileManager::ValidChecksums(const SCryLobbyUserData* pData, uint32 numData)
  2110. {
  2111.         for (int i = 0; i < k_onlineChecksums; i++)
  2112.         {
  2113.                 if (pData[i].m_int32 != Checksum(i, pData, numData))
  2114.                 {
  2115.                         return false;
  2116.                 }
  2117.         }
  2118.  
  2119.         return true;
  2120. }
  2121.  
  2122. //------------------------------------------------------------------------
  2123. int CPlayerProfileManager::Checksum(const int checksum, const SCryLobbyUserData* pData, uint32 numData)
  2124. {
  2125.         switch (checksum)
  2126.         {
  2127.         case 0:
  2128.                 {
  2129.                         int hash = 40503;
  2130.  
  2131.                         for (int i = k_onlineChecksums; i < numData; i++)
  2132.                         {
  2133.                                 int value = ChecksumConvertValueToInt(&pData[i]);
  2134.                                 hash = ChecksumHash(hash, value);
  2135.                         }
  2136.  
  2137.                         return hash;
  2138.                 }
  2139.         case 1:
  2140.                 {
  2141.                         int hash = 514229;
  2142.  
  2143.                         for (int i = k_onlineChecksums; i < numData - 4; i += 4)
  2144.                         {
  2145.                                 int value = ChecksumConvertValueToInt(&pData[i]);
  2146.                                 int value1 = ChecksumConvertValueToInt(&pData[i + 1]);
  2147.                                 int value2 = ChecksumConvertValueToInt(&pData[i + 2]);
  2148.                                 int value3 = ChecksumConvertValueToInt(&pData[i + 3]);
  2149.  
  2150.                                 hash = ChecksumHash(hash, value, value1, value2, value3);
  2151.                         }
  2152.  
  2153.                         return hash;
  2154.                 }
  2155.         default:
  2156.                 CRY_ASSERT(0);
  2157.                 return 0;
  2158.         }
  2159. }
  2160.  
  2161. //------------------------------------------------------------------------
  2162. int CPlayerProfileManager::ChecksumHash(const int seed, const int value) const
  2163. {
  2164.         int hash = seed + value;
  2165.         hash += (hash << 10);
  2166.         hash ^= (hash >> 6);
  2167.         hash += (hash << 3);
  2168.  
  2169.         return hash;
  2170. }
  2171.  
  2172. //------------------------------------------------------------------------
  2173. int CPlayerProfileManager::ChecksumHash(const int value0, const int value1, const int value2, const int value3, const int value4) const
  2174. {
  2175.         uint32 a = (uint32) value0;
  2176.         uint32 b = (uint32) value1;
  2177.         uint32 c = (uint32) value2;
  2178.         uint32 d = (uint32) value3;
  2179.         uint32 e = (uint32) value4;
  2180.         for (int i = 0; i < 16; i++)
  2181.         {
  2182.                 a += (e >> 11);
  2183.                 b += (a ^ d);
  2184.                 c += (b << 3);
  2185.                 d ^= (c >> 5);
  2186.                 e += (d + 233);
  2187.         }
  2188.  
  2189.         return a + b + c + d + e;
  2190. }
  2191.  
  2192. //static------------------------------------------------------------------------
  2193. void CPlayerProfileManager::RegisterUserDataCallback(CryLobbyTaskID taskID, ECryLobbyError error, void* pArg)
  2194. {
  2195.         CPlayerProfileManager* pManager = static_cast<CPlayerProfileManager*>(pArg);
  2196.         CRY_ASSERT(pManager);
  2197.  
  2198.         CRY_ASSERT(error == eCLE_Success);
  2199.         if (error == eCLE_Success)
  2200.         {
  2201.                 pManager->m_registered = true;
  2202.                 pManager->SetOnlineAttributesState(IOnlineAttributesListener::eOAE_Register, IOnlineAttributesListener::eOAS_Success);
  2203.         }
  2204.         else
  2205.         {
  2206.                 pManager->SetOnlineAttributesState(IOnlineAttributesListener::eOAE_Register, IOnlineAttributesListener::eOAS_Failed);
  2207.         }
  2208. }
  2209.  
  2210. //static------------------------------------------------------------------------
  2211. void CPlayerProfileManager::WriteUserDataCallback(CryLobbyTaskID taskID, ECryLobbyError error, void* pArg)
  2212. {
  2213.         CRY_ASSERT(error == eCLE_Success);
  2214.  
  2215. #if PROFILE_DEBUG_COMMANDS
  2216.         CPlayerProfileManager* pManager = static_cast<CPlayerProfileManager*>(pArg);
  2217.         CRY_ASSERT(pManager);
  2218.  
  2219.         if (pManager->m_testingPhase == 1)
  2220.         {
  2221.                 DbgTestOnlineAttributes(NULL);
  2222.         }
  2223. #endif
  2224. }
  2225.  
  2226. #if PROFILE_DEBUG_COMMANDS
  2227. //static------------------------------------------------------------------------
  2228. void CPlayerProfileManager::DbgLoadProfile(IConsoleCmdArgs* args)
  2229. {
  2230.         CPlayerProfileManager* pPlayerProfMan = (CPlayerProfileManager*) CCryAction::GetCryAction()->GetIPlayerProfileManager();
  2231.         CryLogAlways("Loading profile '%s'", pPlayerProfMan->GetCurrentUser());
  2232.  
  2233.         SUserEntry* pEntry = pPlayerProfMan->FindEntry(pPlayerProfMan->GetCurrentUser());
  2234.  
  2235.         CPlayerProfile* pProfile = (CPlayerProfile*) pPlayerProfMan->GetCurrentProfile(pPlayerProfMan->GetCurrentUser());
  2236.  
  2237.         pPlayerProfMan->LoadProfile(pEntry, pProfile, pPlayerProfMan->GetCurrentUser());
  2238. }
  2239.  
  2240. //static------------------------------------------------------------------------
  2241. void CPlayerProfileManager::DbgSaveProfile(IConsoleCmdArgs* args)
  2242. {
  2243.         CPlayerProfileManager* pPlayerProfMan = (CPlayerProfileManager*) CCryAction::GetCryAction()->GetIPlayerProfileManager();
  2244.         CryLogAlways("Saving profile '%s'", pPlayerProfMan->GetCurrentUser());
  2245.  
  2246.         EProfileOperationResult result;
  2247.         pPlayerProfMan->SaveProfile(pPlayerProfMan->GetCurrentUser(), result, ePR_All);
  2248.         CryLogAlways("Result %d", result);
  2249. }
  2250.  
  2251. //static------------------------------------------------------------------------
  2252. void CPlayerProfileManager::DbgLoadOnlineAttributes(IConsoleCmdArgs* args)
  2253. {
  2254.         CPlayerProfileManager* pPlayerProfMan = (CPlayerProfileManager*) CCryAction::GetCryAction()->GetIPlayerProfileManager();
  2255.         CPlayerProfile* pProfile = (CPlayerProfile*) pPlayerProfMan->GetCurrentProfile(pPlayerProfMan->GetCurrentUser());
  2256.         CryLogAlways("%s", pProfile->GetName());
  2257.         pPlayerProfMan->LoadOnlineAttributes(pProfile);
  2258. }
  2259.  
  2260. //static------------------------------------------------------------------------
  2261. void CPlayerProfileManager::DbgSaveOnlineAttributes(IConsoleCmdArgs* args)
  2262. {
  2263.         CPlayerProfileManager* pPlayerProfMan = (CPlayerProfileManager*) CCryAction::GetCryAction()->GetIPlayerProfileManager();
  2264.         CPlayerProfile* pProfile = (CPlayerProfile*) pPlayerProfMan->GetCurrentProfile(pPlayerProfMan->GetCurrentUser());
  2265.         CryLogAlways("%s", pProfile->GetName());
  2266.         pPlayerProfMan->SaveOnlineAttributes(pProfile);
  2267. }
  2268.  
  2269. //static------------------------------------------------------------------------
  2270. void CPlayerProfileManager::DbgTestOnlineAttributes(IConsoleCmdArgs* args)
  2271. {
  2272.         CPlayerProfileManager* pPlayerProfMan = (CPlayerProfileManager*) CCryAction::GetCryAction()->GetIPlayerProfileManager();
  2273.  
  2274.         if (pPlayerProfMan->m_enableOnlineAttributes)
  2275.         {
  2276.                 if (pPlayerProfMan->m_registered)
  2277.                 {
  2278.                         CryLogAlways("---Testing Phase %d---", pPlayerProfMan->m_testingPhase);
  2279.                         switch (pPlayerProfMan->m_testingPhase)
  2280.                         {
  2281.                         case 0:
  2282.                                 {
  2283.                                         CryLogAlways("Version %d", pPlayerProfMan->GetOnlineAttributesVersion());
  2284.                                         CryLogAlways("DefinedVersion %d", pPlayerProfMan->m_onlineAttributeDefinedVersion);
  2285.                                         CryLogAlways("AutoVersion %u", pPlayerProfMan->m_onlineAttributeAutoGeneratedVersion);
  2286.                                         CryLogAlways("OnlineDataCount %u/%d", pPlayerProfMan->m_onlineDataCount, pPlayerProfMan->k_maxOnlineDataCount);
  2287.                                         CryLogAlways("OnlineDataBytes %u/%d", pPlayerProfMan->m_onlineDataByteCount, pPlayerProfMan->k_maxOnlineDataBytes);
  2288.  
  2289.                                         memset(pPlayerProfMan->m_testData, 0, sizeof(pPlayerProfMan->m_testData));
  2290.  
  2291.                                         pPlayerProfMan->m_testingPhase = 1;
  2292.                                         DbgSaveOnlineAttributes(args);
  2293.                                 }
  2294.                                 break;
  2295.  
  2296.                         case 1:
  2297.                                 {
  2298.                                         CryLogAlways("Saved Online Data!");
  2299.  
  2300.                                         CryLogAlways("Copying Original Data!");
  2301.                                         memcpy(pPlayerProfMan->m_testData, pPlayerProfMan->m_onlineData, sizeof(pPlayerProfMan->m_testData));
  2302.  
  2303.                                         CryLogAlways("Memset Original Data!");
  2304.                                         memset(pPlayerProfMan->m_onlineData, -1, sizeof(pPlayerProfMan->m_onlineData));
  2305.  
  2306.                                         CryLogAlways("Copying Profile FlowData");
  2307.                                         int arrayIndex = 0;
  2308.                                         CPlayerProfile* pProfile = (CPlayerProfile*) pPlayerProfMan->GetCurrentProfile(pPlayerProfMan->GetCurrentUser());
  2309.  
  2310.                                         TOnlineAttributeMap::const_iterator end = pPlayerProfMan->m_onlineAttributeMap.end();
  2311.                                         TOnlineAttributeMap::const_iterator iter = pPlayerProfMan->m_onlineAttributeMap.begin();
  2312.                                         while (iter != end)
  2313.                                         {
  2314.                                                 TFlowInputData inputData;
  2315.                                                 pProfile->GetAttribute(iter->first.c_str(), inputData);
  2316.                                                 int inputIntData;
  2317.                                                 inputData.GetValueWithConversion(inputIntData);
  2318.  
  2319.                                                 pPlayerProfMan->m_testFlowData[arrayIndex] = inputIntData;
  2320.  
  2321.                                                 arrayIndex++;
  2322.                                                 ++iter;
  2323.                                         }
  2324.  
  2325.                                         pPlayerProfMan->m_testingPhase = 2;
  2326.                                         DbgLoadOnlineAttributes(args);
  2327.                                 }
  2328.                                 break;
  2329.  
  2330.                         case 2:
  2331.                                 {
  2332.                                         CryLogAlways("Loaded Online Data!");
  2333.  
  2334.                                         int returned = memcmp(pPlayerProfMan->m_testData, pPlayerProfMan->m_onlineData, pPlayerProfMan->m_onlineDataCount * sizeof(SCryLobbyUserData));
  2335.                                         CryLogAlways("memcmp returned %d", returned);
  2336.                                         if (returned == 0)
  2337.                                         {
  2338.                                                 CryLogAlways("Online Data Returned SUCCESSFULLY!!!!!!!!!");
  2339.                                         }
  2340.                                         else
  2341.                                         {
  2342.                                                 for (int i = 0; i < k_maxOnlineDataCount; i++)
  2343.                                                 {
  2344.                                                         if (pPlayerProfMan->m_testData[i].m_int32 != pPlayerProfMan->m_onlineData[i].m_int32)
  2345.                                                         {
  2346.                                                                 CryLogAlways("Expected %d (got %d) at %d", pPlayerProfMan->m_testData[i].m_int32, pPlayerProfMan->m_onlineData[i].m_int32, i);
  2347.                                                         }
  2348.                                                 }
  2349.  
  2350.                                                 CryLogAlways("Online Data Returned FAILED!!!!!!!!!!!!!!!!!!");
  2351.                                                 pPlayerProfMan->m_testingPhase = 0;
  2352.                                                 return;
  2353.                                         }
  2354.  
  2355.                                         CryLogAlways("Checking Profile FlowData");
  2356.                                         int arrayIndex = 0;
  2357.                                         CPlayerProfile* pProfile = (CPlayerProfile*) pPlayerProfMan->GetCurrentProfile(pPlayerProfMan->GetCurrentUser());
  2358.  
  2359.                                         TOnlineAttributeMap::const_iterator end = pPlayerProfMan->m_onlineAttributeMap.end();
  2360.                                         TOnlineAttributeMap::const_iterator iter = pPlayerProfMan->m_onlineAttributeMap.begin();
  2361.                                         while (iter != end)
  2362.                                         {
  2363.                                                 if (iter->second >= k_onlineChecksums)
  2364.                                                 {
  2365.                                                         TFlowInputData data;
  2366.                                                         pProfile->GetAttribute(iter->first.c_str(), data);
  2367.                                                         int intValue = -1;
  2368.                                                         data.GetValueWithConversion(intValue);
  2369.                                                         if (pPlayerProfMan->m_testFlowData[arrayIndex] != intValue)
  2370.                                                         {
  2371.                                                                 CryLogAlways("Non-matching Flow Data! FAILED!!!!!");
  2372.                                                                 pPlayerProfMan->m_testingPhase = 0;
  2373.                                                                 return;
  2374.                                                         }
  2375.                                                 }
  2376.                                                 arrayIndex++;
  2377.                                                 ++iter;
  2378.                                         }
  2379.  
  2380.                                         CryLogAlways("Complete Success!!!!!");
  2381.  
  2382.                                         pPlayerProfMan->m_testingPhase = 0;
  2383.                                         return;
  2384.                                 }
  2385.                                 break;
  2386.                         }
  2387.                 }
  2388.                 else
  2389.                 {
  2390.                         CryLogAlways("Online Attributes aren't not registered");
  2391.                 }
  2392.         }
  2393.         else
  2394.         {
  2395.                 CryLogAlways("Online Attributes aren't not enabled");
  2396.         }
  2397. }
  2398.  
  2399. #endif
  2400.  
  2401. //-----------------------------------------------------------------------------
  2402. // FIXME: need something in crysystem or crypak to move files or directories
  2403. #if CRY_PLATFORM_WINDOWS
  2404. bool CPlayerProfileManager::MoveFileHelper(const char* existingFileName, const char* newFileName)
  2405. {
  2406.         char oldPath[ICryPak::g_nMaxPath];
  2407.         char newPath[ICryPak::g_nMaxPath];
  2408.         // need to adjust aliases and paths (use FLAGS_FOR_WRITING)
  2409.         gEnv->pCryPak->AdjustFileName(existingFileName, oldPath, ICryPak::FLAGS_FOR_WRITING);
  2410.         gEnv->pCryPak->AdjustFileName(newFileName, newPath, ICryPak::FLAGS_FOR_WRITING);
  2411.         return ::MoveFile(oldPath, newPath) != 0;
  2412. }
  2413. #else
  2414. // on all other platforms, just a warning
  2415. bool CPlayerProfileManager::MoveFileHelper(const char* existingFileName, const char* newFileName)
  2416. {
  2417.         char oldPath[ICryPak::g_nMaxPath];
  2418.         gEnv->pCryPak->AdjustFileName(existingFileName, oldPath, ICryPak::FLAGS_FOR_WRITING);
  2419.         string msg;
  2420.         msg.Format("CPlayerProfileManager::MoveFileHelper for this Platform not implemented yet.\nOriginal '%s' will be lost!", oldPath);
  2421.         CRY_ASSERT_MESSAGE(0, msg.c_str());
  2422.         GameWarning("%s", msg.c_str());
  2423.         return false;
  2424. }
  2425. #endif
  2426.  
  2427. void CPlayerProfileManager::GetMemoryStatistics(ICrySizer* s)
  2428. {
  2429.         SIZER_SUBCOMPONENT_NAME(s, "PlayerProfiles");
  2430.         s->Add(*this);
  2431.         if (m_pDefaultProfile)
  2432.                 m_pDefaultProfile->GetMemoryStatistics(s);
  2433.         s->AddContainer(m_userVec);
  2434.         m_pImpl->GetMemoryStatistics(s);
  2435.         s->AddObject(m_curUserID);
  2436. }
  2437.  
downloadPlayerProfileManager.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