diff --git a/src/Profile/Profile.cpp b/src/Profile/Profile.cpp index 46a1819..d5286c2 100644 --- a/src/Profile/Profile.cpp +++ b/src/Profile/Profile.cpp @@ -17,24 +17,25 @@ #include #include +#include #include #include #include +#include "../UESaveFile/Types/ArrayProperty.h" +#include "../UESaveFile/Types/ResourceItemValue.h" +#include "../UESaveFile/Types/IntProperty.h" +#include "../UESaveFile/Types/StringProperty.h" + #include "Profile.h" #include "Locators.h" using namespace Corrade; -Profile::Profile(const std::string& path) { - auto map = Utility::Directory::mapRead(path); - - if(!map) { - _lastError = "Couldn't memory-map " + Utility::Directory::filename(path); - return; - } - +Profile::Profile(const std::string& path): + _profile(path) +{ _profileDirectory = Utility::Directory::path(path); _filename = Utility::Directory::filename(path); @@ -47,16 +48,7 @@ Profile::Profile(const std::string& path) { _steamId = Utility::String::ltrim(Utility::String::rtrim(_filename, ".sav"), (_type == ProfileType::Demo ? "Demo" : "") + std::string{"Profile"}); - auto it = std::search(map.begin(), map.end(), &company_name_locator[0], &company_name_locator[27]); - - if(it == map.end()) { - _lastError = "Couldn't find a company name in " + _filename; - return; - } - - _companyName = std::string{it + 41}; - - _valid = true; + _valid = _profile.valid(); } auto Profile::valid() const -> bool { @@ -80,924 +72,281 @@ auto Profile::steamId() const -> std::string const& { } void Profile::refreshValues() { - getCompanyName(); - getActiveFrameSlot(); - getCredits(); - getStoryProgress(); - getLastMissionId(); - - getVerseSteel(); - getUndinium(); - getNecriumAlloy(); - getLunarite(); - getAsterite(); - - getEdnil(); - getNuflalt(); - getAurelene(); - getSoldus(); - getSynthesizedN(); - - getAlcarbonite(); - getKeriphene(); - getNitinolCM(); - getQuarkium(); - getAlterene(); - - getMixedComposition(); - getVoidResidue(); - getMuscularConstruction(); - getMineralExoskeletology(); - getCarbonizedSkin(); + _profile.reloadData(); } -auto Profile::companyName() const -> std::string const& { - return _companyName; -} - -auto Profile::getCompanyName() -> std::string const& { - auto mmap = Utility::Directory::mapRead(Utility::Directory::join(_profileDirectory, _filename)); - - auto it = std::search(mmap.begin(), mmap.end(), &company_name_locator[0], &company_name_locator[27]); - - if(it == mmap.end()) { - _lastError = "Couldn't find a company name in " + _filename; - _companyName = ""; - } - else { - _companyName = std::string{it + 41}; - } - - return _companyName; +auto Profile::companyName() -> std::string const& { + return _profile.at("CompanyName")->value; } auto Profile::renameCompany(const std::string& new_name) -> bool { - char length_difference = static_cast(_companyName.length() - new_name.length()); + auto name_prop = _profile.at("CompanyName"); - std::string profile_data = Utility::Directory::readString(Utility::Directory::join(_profileDirectory, _filename)); - - auto iter = std::search(profile_data.begin(), profile_data.end(), &company_name_locator[0], &company_name_locator[27]); - - if(iter != profile_data.end()) { - - *(iter + 0x1C) = *(iter + 0x1C) - length_difference; - *(iter + 0x25) = *(iter + 0x25) - length_difference; - - while(*(iter + 0x29) != '\0') { - profile_data.erase(iter + 0x29); - } - - profile_data.insert(iter + 0x29, new_name.cbegin(), new_name.cend()); - - if(!Utility::Directory::writeString(Utility::Directory::join(_profileDirectory, _filename), profile_data)) { - _lastError = "The file" + _filename + " couldn't be written to."; - return false; - } - - _companyName = new_name; - - return true; - } - else { - _lastError = "Couldn't find the company name in " + _filename; + name_prop->value = new_name; + if(!_profile.saveToFile()) { + _lastError = "Couldn't save the profile."; return false; } + + return true; } -auto Profile::activeFrameSlot() const -> Int { - return _activeFrameSlot; +auto Profile::activeFrameSlot() -> Int { + auto active_frame_slot_prop = _profile.at("ActiveFrameSlot"); + return active_frame_slot_prop ? active_frame_slot_prop->value : 0; } -auto Profile::getActiveFrameSlot() -> Int { - auto mmap = Utility::Directory::mapRead(Utility::Directory::join(_profileDirectory, _filename)); - - auto iter = std::search(mmap.begin(), mmap.end(), &active_slot_locator[0], &active_slot_locator[31]); - - if(iter == mmap.end()) { - if(std::search(mmap.begin(), mmap.end(), &credits_locator[0], &credits_locator[22]) != mmap.end()) { - _activeFrameSlot = 0; - } - else { - _lastError = "The profile save seems to be corrupted or the game didn't release the handle on the file."; - _activeFrameSlot = -1; - } - } - else { - _activeFrameSlot = *(iter + 41); - } - - return _activeFrameSlot; -} - -auto Profile::credits() const -> Int { - return _credits; -} - -auto Profile::getCredits() -> Int { - auto mmap = Utility::Directory::mapRead(Utility::Directory::join(_profileDirectory, _filename)); - - auto iter = std::search(mmap.begin(), mmap.end(), &credits_locator[0], &credits_locator[22]); - - if(iter != mmap.end()) { - _credits = *reinterpret_cast(iter + 0x20); - } - else { - _lastError = "The profile save seems to be corrupted or the game didn't release the handle on the file."; - _credits = -1; - } - - return _credits; +auto Profile::credits() -> Int { + auto credits_prop = _profile.at("Credit"); + return credits_prop ? credits_prop->value : 0; } auto Profile::setCredits(Int amount) -> bool { - auto mmap = Utility::Directory::map(Utility::Directory::join(_profileDirectory, _filename)); + auto credits_prop = _profile.at("Credit"); - auto iter = std::search(mmap.begin(), mmap.end(), &credits_locator[0], &credits_locator[22]); - - if(iter != mmap.end()) { - *reinterpret_cast(iter + 0x20) = amount; - _credits = amount; - return true; + if(!credits_prop) { + credits_prop = new IntProperty; + _profile.appendProperty(IntProperty::ptr{credits_prop}); } - else { - _lastError = "The profile save seems to be corrupted or the game didn't release the handle on the file."; + + credits_prop->value = amount; + + if(!_profile.saveToFile()) { + _lastError = "Couldn't save the profile."; return false; } + + return true; } -auto Profile::storyProgress() const -> Int { - return _storyProgress; -} - -auto Profile::getStoryProgress() -> Int { - auto mmap = Utility::Directory::mapRead(Utility::Directory::join(_profileDirectory, _filename)); - - auto iter = std::search(mmap.begin(), mmap.end(), &story_progress_locator[0], &story_progress_locator[29]); - - if(iter != mmap.end()) { - _storyProgress = *reinterpret_cast(iter + 0x27); - } - else { - _lastError = "The profile save seems to be corrupted or the game didn't release the handle on the file."; - _storyProgress = -1; - } - - return _storyProgress; +auto Profile::storyProgress() -> Int { + auto story_progress_prop = _profile.at("StoryProgress"); + return story_progress_prop ? story_progress_prop->value : 0; } auto Profile::setStoryProgress(Int progress) -> bool { - auto mmap = Utility::Directory::map(Utility::Directory::join(_profileDirectory, _filename)); + auto story_progress_prop = _profile.at("StoryProgress"); - auto iter = std::search(mmap.begin(), mmap.end(), &story_progress_locator[0], &story_progress_locator[29]); - - if(iter != mmap.end()) { - *reinterpret_cast(iter + 0x27) = progress; - _storyProgress = progress; - return true; + if(!story_progress_prop) { + story_progress_prop = new IntProperty; + _profile.appendProperty(IntProperty::ptr{story_progress_prop}); } - else { - _lastError = "The profile save seems to be corrupted or the game didn't release the handle on the file."; + + story_progress_prop->value = progress; + + if(!_profile.saveToFile()) { + _lastError = "Couldn't save the profile."; return false; } + + return true; } -auto Profile::lastMissionId() const -> Int { - return _lastMissionId; +auto Profile::lastMissionId() -> Int { + auto last_mission_id_prop = _profile.at("LastMissionID"); + return last_mission_id_prop ? last_mission_id_prop->value : 0; } -auto Profile::getLastMissionId() -> Int { - auto mmap = Utility::Directory::mapRead(Utility::Directory::join(_profileDirectory, _filename)); - - auto iter = std::search(mmap.begin(), mmap.end(), &last_mission_id_locator[0], &last_mission_id_locator[29]); - - if(iter != mmap.end()) { - _lastMissionId = *reinterpret_cast(iter + 0x27); - } - else { - _lastError = "The profile save seems to be corrupted or the game didn't release the handle on the file."; - _lastMissionId = -1; - } - - return _lastMissionId; -} - -auto Profile::verseSteel() const -> Int { - return _verseSteel; -} - -auto Profile::getVerseSteel() -> Int { - auto mmap = Utility::Directory::mapRead(Utility::Directory::join(_profileDirectory, _filename)); - - auto iter = std::search(mmap.begin(), mmap.end(), &verse_steel_locator[0], &verse_steel_locator[129]); - - if(iter != mmap.end()) { - _verseSteel = *reinterpret_cast(iter + 0x8C); - } - else { - _lastError = "The profile save seems to be corrupted or the game didn't release the handle on the file."; - _verseSteel = -1; - } - - return _verseSteel; +auto Profile::verseSteel() -> Int { + return resource("ResourceMaterial", 0xC3500); } auto Profile::setVerseSteel(Int amount) -> bool { - auto mmap = Utility::Directory::map(Utility::Directory::join(_profileDirectory, _filename)); - - auto iter = std::search(mmap.begin(), mmap.end(), &verse_steel_locator[0], &verse_steel_locator[129]); - - if(iter != mmap.end()) { - *reinterpret_cast(iter + 0x8C) = amount; - _verseSteel = amount; - return true; - } - else { - _lastError = "The profile save seems to be corrupted or the game didn't release the handle on the file."; - return false; - } + return setResource("ResourceMaterial", 0xC3500, amount); } -auto Profile::undinium() const -> Int { - return _undinium; -} - -auto Profile::getUndinium() -> Int { - auto mmap = Utility::Directory::mapRead(Utility::Directory::join(_profileDirectory, _filename)); - - auto iter = std::search(mmap.begin(), mmap.end(), &undinium_locator[0], &undinium_locator[129]); - - if(iter != mmap.end()) { - _undinium = *reinterpret_cast(iter + 0x8C); - } - else { - _lastError = "The profile save seems to be corrupted or the game didn't release the handle on the file."; - _undinium = -1; - } - - return _undinium; +auto Profile::undinium() -> Int { + return resource("ResourceMaterial", 0xC3501); } auto Profile::setUndinium(Int amount) -> bool { - auto mmap = Utility::Directory::map(Utility::Directory::join(_profileDirectory, _filename)); - - auto iter = std::search(mmap.begin(), mmap.end(), &undinium_locator[0], &undinium_locator[129]); - - if(iter != mmap.end()) { - *reinterpret_cast(iter + 0x8C) = amount; - _undinium = amount; - return true; - } - else { - _lastError = "The profile save seems to be corrupted or the game didn't release the handle on the file."; - return false; - } + return setResource("ResourceMaterial", 0xC3501, amount); } -auto Profile::necriumAlloy() const -> Int { - return _necriumAlloy; -} - -auto Profile::getNecriumAlloy() -> Int { - auto mmap = Utility::Directory::mapRead(Utility::Directory::join(_profileDirectory, _filename)); - - auto iter = std::search(mmap.begin(), mmap.end(), &necrium_alloy_locator[0], &necrium_alloy_locator[129]); - - if(iter != mmap.end()) { - _necriumAlloy = *reinterpret_cast(iter + 0x8C); - } - else { - _lastError = "The profile save seems to be corrupted or the game didn't release the handle on the file."; - _necriumAlloy = -1; - } - - return _necriumAlloy; +auto Profile::necriumAlloy() -> Int { + return resource("ResourceMaterial", 0xC3502); } auto Profile::setNecriumAlloy(Int amount) -> bool { - auto mmap = Utility::Directory::map(Utility::Directory::join(_profileDirectory, _filename)); - - auto iter = std::search(mmap.begin(), mmap.end(), &necrium_alloy_locator[0], &necrium_alloy_locator[129]); - - if(iter != mmap.end()) { - *reinterpret_cast(iter + 0x8C) = amount; - _necriumAlloy = amount; - return true; - } - else { - _lastError = "The profile save seems to be corrupted or the game didn't release the handle on the file."; - return false; - } + return setResource("ResourceMaterial", 0xC3502, amount); } -auto Profile::lunarite() const -> Int { - return _lunarite; -} - -auto Profile::getLunarite() -> Int { - auto mmap = Utility::Directory::mapRead(Utility::Directory::join(_profileDirectory, _filename)); - - auto iter = std::search(mmap.begin(), mmap.end(), &lunarite_locator[0], &lunarite_locator[129]); - - if(iter != mmap.end()) { - _lunarite = *reinterpret_cast(iter + 0x8C); - } - else { - _lastError = "The profile save seems to be corrupted or the game didn't release the handle on the file."; - _lunarite = -1; - } - - return _lunarite; +auto Profile::lunarite() -> Int { + return resource("ResourceMaterial", 0xC3503); } auto Profile::setLunarite(Int amount) -> bool { - auto mmap = Utility::Directory::map(Utility::Directory::join(_profileDirectory, _filename)); - - auto iter = std::search(mmap.begin(), mmap.end(), &lunarite_locator[0], &lunarite_locator[129]); - - if(iter != mmap.end()) { - *reinterpret_cast(iter + 0x8C) = amount; - _lunarite = amount; - return true; - } - else { - _lastError = "The profile save seems to be corrupted or the game didn't release the handle on the file."; - return false; - } + return setResource("ResourceMaterial", 0xC3503, amount); } -auto Profile::asterite() const -> Int { - return _asterite; -} - -auto Profile::getAsterite() -> Int { - auto mmap = Utility::Directory::mapRead(Utility::Directory::join(_profileDirectory, _filename)); - - auto iter = std::search(mmap.begin(), mmap.end(), &asterite_locator[0], &asterite_locator[129]); - - if(iter != mmap.end()) { - _asterite = *reinterpret_cast(iter + 0x8C); - } - else { - _lastError = "The profile save seems to be corrupted or the game didn't release the handle on the file."; - _asterite = -1; - } - - return _asterite; +auto Profile::asterite() -> Int { + return resource("ResourceMaterial", 0xC3504); } auto Profile::setAsterite(Int amount) -> bool { - auto mmap = Utility::Directory::map(Utility::Directory::join(_profileDirectory, _filename)); - - auto iter = std::search(mmap.begin(), mmap.end(), &asterite_locator[0], &asterite_locator[129]); - - if(iter != mmap.end()) { - *reinterpret_cast(iter + 0x8C) = amount; - _asterite = amount; - return true; - } - else { - _lastError = "The profile save seems to be corrupted or the game didn't release the handle on the file."; - return false; - } + return setResource("ResourceMaterial", 0xC3504, amount); } -auto Profile::ednil() const -> Int { - return _ednil; -} - -auto Profile::getEdnil() -> Int { - auto mmap = Utility::Directory::mapRead(Utility::Directory::join(_profileDirectory, _filename)); - - auto iter = std::search(mmap.begin(), mmap.end(), &ednil_locator[0], &ednil_locator[129]); - - if(iter != mmap.end()) { - _ednil = *reinterpret_cast(iter + 0x8C); - } - else { - _lastError = "The profile save seems to be corrupted or the game didn't release the handle on the file."; - _ednil = -1; - } - - return _ednil; +auto Profile::ednil() -> Int { + return resource("ResourceMaterial", 0xC350A); } auto Profile::setEdnil(Int amount) -> bool { - auto mmap = Utility::Directory::map(Utility::Directory::join(_profileDirectory, _filename)); - - auto iter = std::search(mmap.begin(), mmap.end(), &ednil_locator[0], &ednil_locator[129]); - - if(iter != mmap.end()) { - *reinterpret_cast(iter + 0x8C) = amount; - _ednil = amount; - return true; - } - else { - _lastError = "The profile save seems to be corrupted or the game didn't release the handle on the file."; - return false; - } + return setResource("ResourceMaterial", 0xC350A, amount); } -auto Profile::nuflalt() const -> Int { - return _nuflalt; -} - -auto Profile::getNuflalt() -> Int { - auto mmap = Utility::Directory::mapRead(Utility::Directory::join(_profileDirectory, _filename)); - - auto iter = std::search(mmap.begin(), mmap.end(), &nuflalt_locator[0], &nuflalt_locator[129]); - - if(iter != mmap.end()) { - _nuflalt = *reinterpret_cast(iter + 0x8C); - } - else { - _lastError = "The profile save seems to be corrupted or the game didn't release the handle on the file."; - _nuflalt = -1; - } - - return _nuflalt; +auto Profile::nuflalt() -> Int { + return resource("ResourceMaterial", 0xC350B); } auto Profile::setNuflalt(Int amount) -> bool { - auto mmap = Utility::Directory::map(Utility::Directory::join(_profileDirectory, _filename)); - - auto iter = std::search(mmap.begin(), mmap.end(), &nuflalt_locator[0], &nuflalt_locator[129]); - - if(iter != mmap.end()) { - *reinterpret_cast(iter + 0x8C) = amount; - _nuflalt = amount; - return true; - } - else { - _lastError = "The profile save seems to be corrupted or the game didn't release the handle on the file."; - return false; - } + return setResource("ResourceMaterial", 0xC350B, amount); } -auto Profile::aurelene() const -> Int { - return _aurelene; -} - -auto Profile::getAurelene() -> Int { - auto mmap = Utility::Directory::mapRead(Utility::Directory::join(_profileDirectory, _filename)); - - auto iter = std::search(mmap.begin(), mmap.end(), &aurelene_locator[0], &aurelene_locator[129]); - - if(iter != mmap.end()) { - _aurelene = *reinterpret_cast(iter + 0x8C); - } - else { - _lastError = "The profile save seems to be corrupted or the game didn't release the handle on the file."; - _aurelene = -1; - } - - return _aurelene; +auto Profile::aurelene() -> Int { + return resource("ResourceMaterial", 0xC350C); } auto Profile::setAurelene(Int amount) -> bool { - auto mmap = Utility::Directory::map(Utility::Directory::join(_profileDirectory, _filename)); - - auto iter = std::search(mmap.begin(), mmap.end(), &aurelene_locator[0], &aurelene_locator[129]); - - if(iter != mmap.end()) { - *reinterpret_cast(iter + 0x8C) = amount; - _aurelene = amount; - return true; - } - else { - _lastError = "The profile save seems to be corrupted or the game didn't release the handle on the file."; - return false; - } + return setResource("ResourceMaterial", 0xC350C, amount); } -auto Profile::soldus() const -> Int { - return _soldus; -} - -auto Profile::getSoldus() -> Int { - auto mmap = Utility::Directory::mapRead(Utility::Directory::join(_profileDirectory, _filename)); - - auto iter = std::search(mmap.begin(), mmap.end(), &soldus_locator[0], &soldus_locator[129]); - - if(iter != mmap.end()) { - _soldus = *reinterpret_cast(iter + 0x8C); - } - else { - _lastError = "The profile save seems to be corrupted or the game didn't release the handle on the file."; - _soldus = -1; - } - - return _soldus; +auto Profile::soldus() -> Int { + return resource("ResourceMaterial", 0xC350D); } auto Profile::setSoldus(Int amount) -> bool { - auto mmap = Utility::Directory::map(Utility::Directory::join(_profileDirectory, _filename)); - - auto iter = std::search(mmap.begin(), mmap.end(), &soldus_locator[0], &soldus_locator[129]); - - if(iter != mmap.end()) { - *reinterpret_cast(iter + 0x8C) = amount; - _soldus = amount; - return true; - } - else { - _lastError = "The profile save seems to be corrupted or the game didn't release the handle on the file."; - return false; - } + return setResource("ResourceMaterial", 0xC350D, amount); } -auto Profile::synthesizedN() const -> Int { - return _synthesizedN; -} - -auto Profile::getSynthesizedN() -> Int { - auto mmap = Utility::Directory::mapRead(Utility::Directory::join(_profileDirectory, _filename)); - - auto iter = std::search(mmap.begin(), mmap.end(), &synthesized_n_locator[0], &synthesized_n_locator[129]); - - if(iter != mmap.end()) { - _synthesizedN = *reinterpret_cast(iter + 0x8C); - } - else { - _lastError = "The profile save seems to be corrupted or the game didn't release the handle on the file."; - _synthesizedN = -1; - } - - return _synthesizedN; +auto Profile::synthesizedN() -> Int { + return resource("ResourceMaterial", 0xC350E); } auto Profile::setSynthesizedN(Int amount) -> bool { - auto mmap = Utility::Directory::map(Utility::Directory::join(_profileDirectory, _filename)); - - auto iter = std::search(mmap.begin(), mmap.end(), &synthesized_n_locator[0], &synthesized_n_locator[129]); - - if(iter != mmap.end()) { - *reinterpret_cast(iter + 0x8C) = amount; - _synthesizedN = amount; - return true; - } - else { - _lastError = "The profile save seems to be corrupted or the game didn't release the handle on the file."; - return false; - } + return setResource("ResourceMaterial", 0xC350E, amount); } -auto Profile::alcarbonite() const -> Int { - return _alcarbonite; -} - -auto Profile::getAlcarbonite() -> Int { - auto mmap = Utility::Directory::mapRead(Utility::Directory::join(_profileDirectory, _filename)); - - auto iter = std::search(mmap.begin(), mmap.end(), &alcarbonite_locator[0], &alcarbonite_locator[129]); - - if(iter != mmap.end()) { - _alcarbonite = *reinterpret_cast(iter + 0x8C); - } - else { - _lastError = "The profile save seems to be corrupted or the game didn't release the handle on the file."; - _alcarbonite = -1; - } - - return _alcarbonite; +auto Profile::alcarbonite() -> Int { + return resource("ResourceMaterial", 0xC3514); } auto Profile::setAlcarbonite(Int amount) -> bool { - auto mmap = Utility::Directory::map(Utility::Directory::join(_profileDirectory, _filename)); - - auto iter = std::search(mmap.begin(), mmap.end(), &alcarbonite_locator[0], &alcarbonite_locator[129]); - - if(iter != mmap.end()) { - *reinterpret_cast(iter + 0x8C) = amount; - _alcarbonite = amount; - return true; - } - else { - _lastError = "The profile save seems to be corrupted or the game didn't release the handle on the file."; - return false; - } + return setResource("ResourceMaterial", 0xC3514, amount); } -auto Profile::keriphene() const -> Int { - return _keriphene; -} - -auto Profile::getKeriphene() -> Int { - auto mmap = Utility::Directory::mapRead(Utility::Directory::join(_profileDirectory, _filename)); - - auto iter = std::search(mmap.begin(), mmap.end(), &keriphene_locator[0], &keriphene_locator[129]); - - if(iter != mmap.end()) { - _keriphene = *reinterpret_cast(iter + 0x8C); - } - else { - _lastError = "The profile save seems to be corrupted or the game didn't release the handle on the file."; - _keriphene= -1; - } - - return _keriphene; +auto Profile::keriphene() -> Int { + return resource("ResourceMaterial", 0xC3515); } auto Profile::setKeriphene(Int amount) -> bool { - auto mmap = Utility::Directory::map(Utility::Directory::join(_profileDirectory, _filename)); - - auto iter = std::search(mmap.begin(), mmap.end(), &keriphene_locator[0], &keriphene_locator[129]); - - if(iter != mmap.end()) { - *reinterpret_cast(iter + 0x8C) = amount; - _keriphene = amount; - return true; - } - else { - _lastError = "The profile save seems to be corrupted or the game didn't release the handle on the file."; - return false; - } + return setResource("ResourceMaterial", 0xC3515, amount); } -auto Profile::nitinolCM() const -> Int { - return _nitinolCM; -} - -auto Profile::getNitinolCM() -> Int { - auto mmap = Utility::Directory::mapRead(Utility::Directory::join(_profileDirectory, _filename)); - - auto iter = std::search(mmap.begin(), mmap.end(), &nitinol_cm_locator[0], &nitinol_cm_locator[129]); - - if(iter != mmap.end()) { - _nitinolCM = *reinterpret_cast(iter + 0x8C); - } - else { - _lastError = "The profile save seems to be corrupted or the game didn't release the handle on the file."; - _nitinolCM = -1; - } - - return _nitinolCM; +auto Profile::nitinolCM() -> Int { + return resource("ResourceMaterial", 0xC3516); } auto Profile::setNitinolCM(Int amount) -> bool { - auto mmap = Utility::Directory::map(Utility::Directory::join(_profileDirectory, _filename)); - - auto iter = std::search(mmap.begin(), mmap.end(), &nitinol_cm_locator[0], &nitinol_cm_locator[129]); - - if(iter != mmap.end()) { - *reinterpret_cast(iter + 0x8C) = amount; - _nitinolCM = amount; - return true; - } - else { - _lastError = "The profile save seems to be corrupted or the game didn't release the handle on the file."; - return false; - } + return setResource("ResourceMaterial", 0xC3516, amount); } -auto Profile::quarkium() const -> Int { - return _quarkium; -} - -auto Profile::getQuarkium() -> Int { - auto mmap = Utility::Directory::mapRead(Utility::Directory::join(_profileDirectory, _filename)); - - auto iter = std::search(mmap.begin(), mmap.end(), &quarkium_locator[0], &quarkium_locator[129]); - - if(iter != mmap.end()) { - _quarkium = *reinterpret_cast(iter + 0x8C); - } - else { - _lastError = "The profile save seems to be corrupted or the game didn't release the handle on the file."; - _quarkium = -1; - } - - return _quarkium; +auto Profile::quarkium() -> Int { + return resource("ResourceMaterial", 0xC3517); } auto Profile::setQuarkium(Int amount) -> bool { - auto mmap = Utility::Directory::map(Utility::Directory::join(_profileDirectory, _filename)); - - auto iter = std::search(mmap.begin(), mmap.end(), &quarkium_locator[0], &quarkium_locator[129]); - - if(iter != mmap.end()) { - *reinterpret_cast(iter + 0x8C) = amount; - _quarkium = amount; - return true; - } - else { - _lastError = "The profile save seems to be corrupted or the game didn't release the handle on the file."; - return false; - } + return setResource("ResourceMaterial", 0xC3517, amount); } -auto Profile::alterene() const -> Int { - return _alterene; -} - -auto Profile::getAlterene() -> Int { - auto mmap = Utility::Directory::mapRead(Utility::Directory::join(_profileDirectory, _filename)); - - auto iter = std::search(mmap.begin(), mmap.end(), &alterene_locator[0], &alterene_locator[129]); - - if(iter != mmap.end()) { - _alterene = *reinterpret_cast(iter + 0x8C); - } - else { - _lastError = "The profile save seems to be corrupted or the game didn't release the handle on the file."; - _alterene = -1; - } - - return _alterene; +auto Profile::alterene() -> Int { + return resource("ResourceMaterial", 0xC3518); } auto Profile::setAlterene(Int amount) -> bool { - auto mmap = Utility::Directory::map(Utility::Directory::join(_profileDirectory, _filename)); - - auto iter = std::search(mmap.begin(), mmap.end(), &alterene_locator[0], &alterene_locator[129]); - - if(iter != mmap.end()) { - *reinterpret_cast(iter + 0x8C) = amount; - _alterene = amount; - return true; - } - else { - _lastError = "The profile save seems to be corrupted or the game didn't release the handle on the file."; - return false; - } + return setResource("ResourceMaterial", 0xC3518, amount); } -auto Profile::mixedComposition() const -> Int { - return _mixedComposition; -} - -auto Profile::getMixedComposition() -> Int { - auto mmap = Utility::Directory::mapRead(Utility::Directory::join(_profileDirectory, _filename)); - - auto iter = std::search(mmap.begin(), mmap.end(), &mixed_composition_locator[0], &mixed_composition_locator[129]); - - if(iter != mmap.end()) { - _mixedComposition = *reinterpret_cast(iter + 0x8C); - } - else { - _lastError = "The profile save seems to be corrupted or the game didn't release the handle on the file."; - _mixedComposition = -1; - } - - return _mixedComposition; +auto Profile::mixedComposition() -> Int { + return resource("ResourceQuarkData", 0xDBBA0); } auto Profile::setMixedComposition(Int amount) -> bool { - auto mmap = Utility::Directory::map(Utility::Directory::join(_profileDirectory, _filename)); - - auto iter = std::search(mmap.begin(), mmap.end(), &mixed_composition_locator[0], &mixed_composition_locator[129]); - - if(iter != mmap.end()) { - *reinterpret_cast(iter + 0x8C) = amount; - _mixedComposition = amount; - return true; - } - else { - _lastError = "The profile save seems to be corrupted or the game didn't release the handle on the file."; - return false; - } + return setResource("ResourceQuarkData", 0xDBBA0, amount); } -auto Profile::voidResidue() const -> Int { - return _voidResidue; -} - -auto Profile::getVoidResidue() -> Int { - auto mmap = Utility::Directory::mapRead(Utility::Directory::join(_profileDirectory, _filename)); - - auto iter = std::search(mmap.begin(), mmap.end(), &void_residue_locator[0], &void_residue_locator[129]); - - if(iter != mmap.end()) { - _voidResidue = *reinterpret_cast(iter + 0x8C); - } - else { - _lastError = "The profile save seems to be corrupted or the game didn't release the handle on the file."; - _voidResidue = -1; - } - - return _voidResidue; +auto Profile::voidResidue() -> Int { + return resource("ResourceQuarkData", 0xDBBA1); } auto Profile::setVoidResidue(Int amount) -> bool { - auto mmap = Utility::Directory::map(Utility::Directory::join(_profileDirectory, _filename)); - - auto iter = std::search(mmap.begin(), mmap.end(), &void_residue_locator[0], &void_residue_locator[129]); - - if(iter != mmap.end()) { - *reinterpret_cast(iter + 0x8C) = amount; - _voidResidue = amount; - return true; - } - else { - _lastError = "The profile save seems to be corrupted or the game didn't release the handle on the file."; - return false; - } + return setResource("ResourceQuarkData", 0xDBBA1, amount); } -auto Profile::muscularConstruction() const -> Int { - return _muscularConstruction; -} - -auto Profile::getMuscularConstruction() -> Int { - auto mmap = Utility::Directory::mapRead(Utility::Directory::join(_profileDirectory, _filename)); - - auto iter = std::search(mmap.begin(), mmap.end(), &muscular_construction_locator[0], &muscular_construction_locator[129]); - - if(iter != mmap.end()) { - _muscularConstruction = *reinterpret_cast(iter + 0x8C); - } - else { - _lastError = "The profile save seems to be corrupted or the game didn't release the handle on the file."; - _muscularConstruction = -1; - } - - return _muscularConstruction; +auto Profile::muscularConstruction() -> Int { + return resource("ResourceQuarkData", 0xDBBA2); } auto Profile::setMuscularConstruction(Int amount) -> bool { - auto mmap = Utility::Directory::map(Utility::Directory::join(_profileDirectory, _filename)); - - auto iter = std::search(mmap.begin(), mmap.end(), &muscular_construction_locator[0], &muscular_construction_locator[129]); - - if(iter != mmap.end()) { - *reinterpret_cast(iter + 0x8C) = amount; - _muscularConstruction = amount; - return true; - } - else { - _lastError = "The profile save seems to be corrupted or the game didn't release the handle on the file."; - return false; - } + return setResource("ResourceQuarkData", 0xDBBA2, amount); } -auto Profile::mineralExoskeletology() const -> Int { - return _mineralExoskeletology; -} - -auto Profile::getMineralExoskeletology() -> Int { - auto mmap = Utility::Directory::mapRead(Utility::Directory::join(_profileDirectory, _filename)); - - auto iter = std::search(mmap.begin(), mmap.end(), &mineral_exoskeletology_locator[0], &mineral_exoskeletology_locator[129]); - - if(iter != mmap.end()) { - _mineralExoskeletology = *reinterpret_cast(iter + 0x8C); - } - else { - _lastError = "The profile save seems to be corrupted or the game didn't release the handle on the file."; - _mineralExoskeletology = -1; - } - - return _mineralExoskeletology; +auto Profile::mineralExoskeletology() -> Int { + return resource("ResourceQuarkData", 0xDBBA3); } auto Profile::setMineralExoskeletology(Int amount) -> bool { - auto mmap = Utility::Directory::map(Utility::Directory::join(_profileDirectory, _filename)); - - auto iter = std::search(mmap.begin(), mmap.end(), &mineral_exoskeletology_locator[0], &mineral_exoskeletology_locator[129]); - - if(iter != mmap.end()) { - *reinterpret_cast(iter + 0x8C) = amount; - _mineralExoskeletology = amount; - return true; - } - else { - _lastError = "The profile save seems to be corrupted or the game didn't release the handle on the file."; - return false; - } + return setResource("ResourceQuarkData", 0xDBBA3, amount); } -auto Profile::carbonizedSkin() const -> Int { - return _carbonizedSkin; -} - -auto Profile::getCarbonizedSkin() -> Int { - auto mmap = Utility::Directory::mapRead(Utility::Directory::join(_profileDirectory, _filename)); - - auto iter = std::search(mmap.begin(), mmap.end(), &carbonized_skin_locator[0], &carbonized_skin_locator[129]); - - if(iter != mmap.end()) { - _carbonizedSkin = *reinterpret_cast(iter + 0x8C); - } - else { - _lastError = "The profile save seems to be corrupted or the game didn't release the handle on the file."; - _carbonizedSkin = -1; - } - - return _carbonizedSkin; +auto Profile::carbonizedSkin() -> Int { + return resource("ResourceQuarkData", 0xDBBA4); } auto Profile::setCarbonizedSkin(Int amount) -> bool { - auto mmap = Utility::Directory::map(Utility::Directory::join(_profileDirectory, _filename)); + return setResource("ResourceQuarkData", 0xDBBA4, amount); +} - auto iter = std::search(mmap.begin(), mmap.end(), &carbonized_skin_locator[0], &carbonized_skin_locator[129]); +auto Profile::resource(const char* container, Int id) -> Int { + auto mats_prop = _profile.at(container); - if(iter != mmap.end()) { - *reinterpret_cast(iter + 0x8C) = amount; - _carbonizedSkin = amount; - return true; + static auto predicate = [&id](UnrealPropertyBase::ptr& prop){ + auto res_prop = static_cast(prop.get()); + return res_prop->id == id; + }; + + auto it = std::find_if(mats_prop->items.begin(), mats_prop->items.end(), predicate); + return it != mats_prop->items.end() ? static_cast(it->get())->quantity : 0; +} + +auto Profile::setResource(const char* container, Int id, Int amount) -> bool { + auto mats_prop = _profile.at(container); + + static auto predicate = [&id](UnrealPropertyBase::ptr& prop){ + auto res_prop = static_cast(prop.get()); + return res_prop->id == id; + }; + + auto it = std::find_if(mats_prop->items.begin(), mats_prop->items.end(), predicate); + + ResourceItemValue* res_prop; + if(it == mats_prop->items.end()) { + res_prop = new ResourceItemValue; + res_prop->id = id; + ResourceItemValue::ptr prop{res_prop}; + arrayAppend(mats_prop->items, std::move(prop)); } else { - _lastError = "The profile save seems to be corrupted or the game didn't release the handle on the file."; + res_prop = static_cast(it->get()); + } + + res_prop->quantity = amount; + + if(!_profile.saveToFile()) { + _lastError = _profile.lastError(); return false; } + + return _profile.saveToFile(); } diff --git a/src/Profile/Profile.h b/src/Profile/Profile.h index 63cf5bc..513e817 100644 --- a/src/Profile/Profile.h +++ b/src/Profile/Profile.h @@ -20,6 +20,8 @@ #include +#include "../UESaveFile/UESaveFile.h" + using namespace Magnum; enum class ProfileType : UnsignedByte { @@ -43,144 +45,92 @@ class Profile { void refreshValues(); - auto companyName() const -> std::string const&; - auto getCompanyName() -> std::string const&; + auto companyName() -> std::string const&; auto renameCompany(const std::string& new_name) -> bool; - auto activeFrameSlot() const -> Int; - auto getActiveFrameSlot() -> Int; + auto activeFrameSlot() -> Int; - auto credits() const -> Int; - auto getCredits() -> Int; + auto credits() -> Int; auto setCredits(Int credits) -> bool; - auto storyProgress() const -> Int; - auto getStoryProgress() -> Int; + auto storyProgress() -> Int; auto setStoryProgress(Int progress) -> bool; - auto lastMissionId() const -> Int; - auto getLastMissionId() -> Int; + auto lastMissionId() -> Int; - auto verseSteel() const -> Int; - auto getVerseSteel() -> Int; + auto verseSteel() -> Int; auto setVerseSteel(Int amount) -> bool; - auto undinium() const -> Int; - auto getUndinium() -> Int; + auto undinium() -> Int; auto setUndinium(Int amount) -> bool; - auto necriumAlloy() const -> Int; - auto getNecriumAlloy() -> Int; + auto necriumAlloy() -> Int; auto setNecriumAlloy(Int amount) -> bool; - auto lunarite() const -> Int; - auto getLunarite() -> Int; + auto lunarite() -> Int; auto setLunarite(Int amount) -> bool; - auto asterite() const -> Int; - auto getAsterite() -> Int; + auto asterite() -> Int; auto setAsterite(Int amount) -> bool; - auto ednil() const -> Int; - auto getEdnil() -> Int; + auto ednil() -> Int; auto setEdnil(Int amount) -> bool; - auto nuflalt() const -> Int; - auto getNuflalt() -> Int; + auto nuflalt() -> Int; auto setNuflalt(Int amount) -> bool; - auto aurelene() const -> Int; - auto getAurelene() -> Int; + auto aurelene() -> Int; auto setAurelene(Int amount) -> bool; - auto soldus() const -> Int; - auto getSoldus() -> Int; + auto soldus() -> Int; auto setSoldus(Int amount) -> bool; - auto synthesizedN() const -> Int; - auto getSynthesizedN() -> Int; + auto synthesizedN() -> Int; auto setSynthesizedN(Int amount) -> bool; - auto alcarbonite() const -> Int; - auto getAlcarbonite() -> Int; + auto alcarbonite() -> Int; auto setAlcarbonite(Int amount) -> bool; - auto keriphene() const -> Int; - auto getKeriphene() -> Int; + auto keriphene() -> Int; auto setKeriphene(Int amount) -> bool; - auto nitinolCM() const -> Int; - auto getNitinolCM() -> Int; + auto nitinolCM() -> Int; auto setNitinolCM(Int amount) -> bool; - auto quarkium() const -> Int; - auto getQuarkium() -> Int; + auto quarkium() -> Int; auto setQuarkium(Int amount) -> bool; - auto alterene() const -> Int; - auto getAlterene() -> Int; + auto alterene() -> Int; auto setAlterene(Int amount) -> bool; - auto mixedComposition() const -> Int; - auto getMixedComposition() -> Int; + auto mixedComposition() -> Int; auto setMixedComposition(Int amount) -> bool; - auto voidResidue() const -> Int; - auto getVoidResidue() -> Int; + auto voidResidue() -> Int; auto setVoidResidue(Int amount) -> bool; - auto muscularConstruction() const -> Int; - auto getMuscularConstruction() -> Int; + auto muscularConstruction() -> Int; auto setMuscularConstruction(Int amount) -> bool; - auto mineralExoskeletology() const -> Int; - auto getMineralExoskeletology() -> Int; + auto mineralExoskeletology() -> Int; auto setMineralExoskeletology(Int amount) -> bool; - auto carbonizedSkin() const -> Int; - auto getCarbonizedSkin() -> Int; + auto carbonizedSkin() -> Int; auto setCarbonizedSkin(Int amount) -> bool; private: + auto resource(const char* container, Int id) -> Int; + auto setResource(const char* container, Int id, Int amount) -> bool; + std::string _profileDirectory; std::string _filename; ProfileType _type; + UESaveFile _profile; + std::string _steamId; bool _valid = false; std::string _lastError; - - std::string _companyName; - - Int _activeFrameSlot = 0; - - Int _credits; - - Int _storyProgress; - - Int _lastMissionId; - - Int _verseSteel; - Int _undinium; - Int _necriumAlloy; - Int _lunarite; - Int _asterite; - Int _ednil; - Int _nuflalt; - Int _aurelene; - Int _soldus; - Int _synthesizedN; - Int _alcarbonite; - Int _keriphene; - Int _nitinolCM; - Int _quarkium; - Int _alterene; - - Int _mixedComposition; - Int _voidResidue; - Int _muscularConstruction; - Int _mineralExoskeletology; - Int _carbonizedSkin; }; diff --git a/src/ProfileManager/ProfileManager.cpp b/src/ProfileManager/ProfileManager.cpp index b7124e7..57da93a 100644 --- a/src/ProfileManager/ProfileManager.cpp +++ b/src/ProfileManager/ProfileManager.cpp @@ -31,8 +31,6 @@ #include "ProfileManager.h" -using namespace Corrade; - ProfileManager::ProfileManager(const std::string& save_dir, const std::string& backup_dir): _saveDirectory{save_dir}, _backupsDirectory{backup_dir} @@ -48,12 +46,12 @@ auto ProfileManager::lastError() -> std::string const& { return _lastError; } -auto ProfileManager::profiles() -> std::vector const& { +auto ProfileManager::profiles() -> Containers::ArrayView { return _profiles; } auto ProfileManager::refreshProfiles() -> bool { - _profiles.clear(); + _profiles = Containers::Array{}; using Utility::Directory::Flag; std::vector files = Utility::Directory::list(_saveDirectory, Flag::SkipSpecial|Flag::SkipDirectories|Flag::SkipDotAndDotDot); @@ -74,7 +72,7 @@ auto ProfileManager::refreshProfiles() -> bool { continue; } - _profiles.push_back(std::move(profile)); + arrayAppend(_profiles, std::move(profile)); } if(_profiles.empty()) { @@ -86,14 +84,14 @@ auto ProfileManager::refreshProfiles() -> bool { } auto ProfileManager::getProfile(std::size_t index) -> Profile* { - return &(_profiles.at(index)); + return index <= _profiles.size() ? &(_profiles[index]) : nullptr; } auto ProfileManager::deleteProfile(std::size_t index, bool delete_builds) -> bool { - if(!Utility::Directory::rm(Utility::Directory::join(_saveDirectory, _profiles.at(index).filename()))) { + if(!Utility::Directory::rm(Utility::Directory::join(_saveDirectory, _profiles[index].filename()))) { _lastError = Utility::formatString("Couldn't delete {} (filename: {}).", - _profiles.at(index).companyName(), - _profiles.at(index).filename()); + _profiles[index].companyName(), + _profiles[index].filename()); refreshProfiles(); return false; } @@ -101,13 +99,18 @@ auto ProfileManager::deleteProfile(std::size_t index, bool delete_builds) -> boo if(delete_builds) { for(UnsignedByte i = 0; i < 32; ++i) { std::string filename = Utility::formatString("{}Unit{:.2d}{}.sav", - _profiles.at(index).type() == ProfileType::Demo ? "Demo": "", - i, _profiles.at(index).steamId()); + _profiles[index].type() == ProfileType::Demo ? "Demo": "", + i, _profiles[index].steamId()); Utility::Directory::rm(Utility::Directory::join(_saveDirectory, filename)); } } - _profiles.erase(_profiles.cbegin() + index); + std::string file = _profiles[index].filename(); + auto it = std::remove_if(_profiles.begin(), _profiles.end(), [&file](Profile& profile){return profile.filename() == file;}); + + if(it != _profiles.end()) { + arrayRemoveSuffix(_profiles, 1); + } return true; } @@ -117,7 +120,7 @@ auto ProfileManager::backupProfile(std::size_t index, bool backup_builds) -> boo std::tm* time = std::localtime(×tamp); std::string filename = Utility::formatString("{}_{}{:.2d}{:.2d}_{:.2d}{:.2d}{:.2d}.mbprofbackup", - Utility::String::replaceAll(_profiles.at(index).companyName(), " ", "_"), + Utility::String::replaceAll(_profiles[index].companyName(), " ", "_"), time->tm_year + 1900, time->tm_mon + 1, time->tm_mday, time->tm_hour, time->tm_min, time->tm_sec); @@ -130,21 +133,21 @@ auto ProfileManager::backupProfile(std::size_t index, bool backup_builds) -> boo return false; } - zip_source_t* profile_source = zip_source_file(zip, Utility::Directory::toNativeSeparators(Utility::Directory::join(_saveDirectory, _profiles.at(index).filename())).c_str(), 0, 0); + zip_source_t* profile_source = zip_source_file(zip, Utility::Directory::toNativeSeparators(Utility::Directory::join(_saveDirectory, _profiles[index].filename())).c_str(), 0, 0); if(profile_source == nullptr) { _lastError = zip_strerror(zip); zip_source_free(profile_source); return false; } - if(zip_file_add(zip, _profiles.at(index).filename().c_str(), profile_source, ZIP_FL_ENC_UTF_8) == -1) { + if(zip_file_add(zip, _profiles[index].filename().c_str(), profile_source, ZIP_FL_ENC_UTF_8) == -1) { _lastError = zip_strerror(zip); zip_source_free(profile_source); return false; } - std::string comment = Utility::String::join({_profiles.at(index).companyName(), - _profiles.at(index).type() == ProfileType::Demo ? "demo" : "full", + std::string comment = Utility::String::join({_profiles[index].companyName(), + _profiles[index].type() == ProfileType::Demo ? "demo" : "full", Utility::formatString("{}-{:.2d}-{:.2d}-{:.2d}-{:.2d}-{:.2d}", time->tm_year + 1900, time->tm_mon + 1, time->tm_mday, time->tm_hour, time->tm_min, time->tm_sec) @@ -154,8 +157,8 @@ auto ProfileManager::backupProfile(std::size_t index, bool backup_builds) -> boo if(backup_builds) { for(UnsignedByte i = 0; i < 32; ++i) { std::string build_filename = Utility::formatString("{}Unit{:.2d}{}.sav", - _profiles.at(index).type() == ProfileType::Demo ? "Demo": "", - i, _profiles.at(index).steamId()); + _profiles[index].type() == ProfileType::Demo ? "Demo": "", + i, _profiles[index].steamId()); if(!Utility::Directory::exists(Utility::Directory::join(_saveDirectory, build_filename))) { continue; @@ -184,12 +187,12 @@ auto ProfileManager::backupProfile(std::size_t index, bool backup_builds) -> boo return true; } -auto ProfileManager::backups() -> std::vector const& { +auto ProfileManager::backups() -> Containers::ArrayView { return _backups; } void ProfileManager::refreshBackups() { - _backups.clear(); + _backups = Containers::Array{}; using Utility::Directory::Flag; std::vector files = Utility::Directory::list(_backupsDirectory, Flag::SkipSpecial|Flag::SkipDirectories|Flag::SkipDotAndDotDot); @@ -255,29 +258,34 @@ void ProfileManager::refreshBackups() { continue; } - backup.includedFiles.reserve(num_entries); + arrayReserve(backup.includedFiles, num_entries); for(Long i = 0; i < num_entries; i++) { - backup.includedFiles.emplace_back(zip_get_name(zip, i, ZIP_FL_UNCHANGED)); + arrayAppend(backup.includedFiles, InPlaceInit, zip_get_name(zip, i, ZIP_FL_UNCHANGED)); } - _backups.push_back(std::move(backup)); + arrayAppend(_backups, std::move(backup)); } } auto ProfileManager::deleteBackup(std::size_t index) -> bool { - if(!Utility::Directory::rm(Utility::Directory::join(_backupsDirectory, _backups.at(index).filename))) { - _lastError = "Couldn't delete " + _backups.at(index).filename; + if(!Utility::Directory::rm(Utility::Directory::join(_backupsDirectory, _backups[index].filename))) { + _lastError = "Couldn't delete " + _backups[index].filename; return false; } - _backups.erase(_backups.begin() + index); + std::string file = _backups[index].filename; + auto it = std::remove_if(_backups.begin(), _backups.end(), [&file](Backup& backup){return backup.filename == file;}); + + if(it != _backups.end()) { + arrayRemoveSuffix(_backups, 1); + } return true; } auto ProfileManager::restoreBackup(std::size_t index) -> bool { - const Backup& backup = _backups.at(index); + const Backup& backup = _backups[index]; static const char* error_format = "Extraction of file {} failed: {}"; diff --git a/src/ProfileManager/ProfileManager.h b/src/ProfileManager/ProfileManager.h index d1d47b6..aeb91ae 100644 --- a/src/ProfileManager/ProfileManager.h +++ b/src/ProfileManager/ProfileManager.h @@ -17,10 +17,13 @@ // along with this program. If not, see . #include -#include + +#include #include "../Profile/Profile.h" +using namespace Corrade; + struct Backup { std::string filename; std::string company; @@ -33,7 +36,7 @@ struct Backup { int minute; int second; } timestamp; - std::vector includedFiles; + Containers::Array includedFiles; }; class ProfileManager { @@ -43,14 +46,14 @@ class ProfileManager { auto ready() const -> bool; auto lastError() -> std::string const&; - auto profiles() -> std::vector const&; + auto profiles() -> Containers::ArrayView; auto refreshProfiles() -> bool; auto getProfile(std::size_t index) -> Profile*; auto deleteProfile(std::size_t index, bool delete_builds) -> bool; auto backupProfile(std::size_t index, bool backup_builds) -> bool; - auto backups() -> std::vector const&; + auto backups() -> Containers::ArrayView; void refreshBackups(); auto deleteBackup(std::size_t index) -> bool; @@ -63,6 +66,6 @@ class ProfileManager { const std::string& _saveDirectory; const std::string& _backupsDirectory; - std::vector _profiles; - std::vector _backups; + Containers::Array _profiles; + Containers::Array _backups; }; diff --git a/src/SaveTool/SaveTool_ProfileManager.cpp b/src/SaveTool/SaveTool_ProfileManager.cpp index 490d9ee..9bdf20c 100644 --- a/src/SaveTool/SaveTool_ProfileManager.cpp +++ b/src/SaveTool/SaveTool_ProfileManager.cpp @@ -81,7 +81,7 @@ void SaveTool::drawProfileManager() { ImGui::TableSetColumnIndex(0); ImGui::PushID(i); - if(ImGui::Selectable(_profileManager->profiles().at(i).companyName().c_str(), false, + if(ImGui::Selectable(_profileManager->profiles()[i].companyName().c_str(), false, ImGuiSelectableFlags_SpanAllColumns|ImGuiSelectableFlags_AllowItemOverlap)) { _currentProfile = _profileManager->getProfile(i); @@ -90,7 +90,7 @@ void SaveTool::drawProfileManager() { } ImGui::TableSetColumnIndex(1); - ImGui::TextUnformatted(_profileManager->profiles().at(i).type() == ProfileType::Demo ? "Demo" : "Full"); + ImGui::TextUnformatted(_profileManager->profiles()[i].type() == ProfileType::Demo ? "Demo" : "Full"); ImGui::TableSetColumnIndex(2); if(ImGui::SmallButton(ICON_FA_FILE_ARCHIVE)) { @@ -132,13 +132,13 @@ auto SaveTool::drawBackupListPopup() -> ImGuiID { { ImGui::PushTextWrapPos(windowSize().x() * 0.40f); ImGui::Text("Are you sure you want to restore the %s backup from %.4i-%.2i-%.2i %.2i:%.2i:%.2i ? Any existing data will be overwritten.", - _profileManager->backups().at(backup_index).company.c_str(), - _profileManager->backups().at(backup_index).timestamp.year, - _profileManager->backups().at(backup_index).timestamp.month, - _profileManager->backups().at(backup_index).timestamp.day, - _profileManager->backups().at(backup_index).timestamp.hour, - _profileManager->backups().at(backup_index).timestamp.minute, - _profileManager->backups().at(backup_index).timestamp.second); + _profileManager->backups()[backup_index].company.c_str(), + _profileManager->backups()[backup_index].timestamp.year, + _profileManager->backups()[backup_index].timestamp.month, + _profileManager->backups()[backup_index].timestamp.day, + _profileManager->backups()[backup_index].timestamp.hour, + _profileManager->backups()[backup_index].timestamp.minute, + _profileManager->backups()[backup_index].timestamp.second); ImGui::PopTextWrapPos(); if(ImGui::BeginTable("##RestoreBackupLayout", 2)) { @@ -172,13 +172,13 @@ auto SaveTool::drawBackupListPopup() -> ImGuiID { { ImGui::PushTextWrapPos(windowSize().x() * 0.40f); ImGui::Text("Are you sure you want to delete the %s backup from %.4i-%.2i-%.2i %.2i:%.2i:%.2i ? This operation is irreversible.", - _profileManager->backups().at(backup_index).company.c_str(), - _profileManager->backups().at(backup_index).timestamp.year, - _profileManager->backups().at(backup_index).timestamp.month, - _profileManager->backups().at(backup_index).timestamp.day, - _profileManager->backups().at(backup_index).timestamp.hour, - _profileManager->backups().at(backup_index).timestamp.minute, - _profileManager->backups().at(backup_index).timestamp.second); + _profileManager->backups()[backup_index].company.c_str(), + _profileManager->backups()[backup_index].timestamp.year, + _profileManager->backups()[backup_index].timestamp.month, + _profileManager->backups()[backup_index].timestamp.day, + _profileManager->backups()[backup_index].timestamp.hour, + _profileManager->backups()[backup_index].timestamp.minute, + _profileManager->backups()[backup_index].timestamp.second); ImGui::PopTextWrapPos(); if(ImGui::BeginTable("##DeleteBackupLayout", 2)) { @@ -251,10 +251,10 @@ auto SaveTool::drawBackupListPopup() -> ImGuiID { ImGui::TableNextRow(); ImGui::TableSetColumnIndex(0); - ImGui::TextUnformatted(_profileManager->backups().at(i).company.c_str()); + ImGui::TextUnformatted(_profileManager->backups()[i].company.c_str()); if(ImGui::IsItemHovered()) { ImGui::BeginTooltip(); - for(const auto& file : _profileManager->backups().at(i).includedFiles) { + for(const auto& file : _profileManager->backups()[i].includedFiles) { ImGui::TextUnformatted(file.c_str()); } ImGui::EndTooltip(); @@ -262,15 +262,15 @@ auto SaveTool::drawBackupListPopup() -> ImGuiID { ImGui::TableSetColumnIndex(1); ImGui::Text("%.4i-%.2i-%.2i %.2i:%.2i:%.2i", - _profileManager->backups().at(i).timestamp.year, - _profileManager->backups().at(i).timestamp.month, - _profileManager->backups().at(i).timestamp.day, - _profileManager->backups().at(i).timestamp.hour, - _profileManager->backups().at(i).timestamp.minute, - _profileManager->backups().at(i).timestamp.second); + _profileManager->backups()[i].timestamp.year, + _profileManager->backups()[i].timestamp.month, + _profileManager->backups()[i].timestamp.day, + _profileManager->backups()[i].timestamp.hour, + _profileManager->backups()[i].timestamp.minute, + _profileManager->backups()[i].timestamp.second); ImGui::TableSetColumnIndex(2); - ImGui::TextUnformatted(_profileManager->backups().at(i).type == ProfileType::Demo ? "Demo" : "Full"); + ImGui::TextUnformatted(_profileManager->backups()[i].type == ProfileType::Demo ? "Demo" : "Full"); ImGui::TableSetColumnIndex(3); ImGui::PushID(i); @@ -363,8 +363,8 @@ auto SaveTool::drawDeleteProfilePopup(std::size_t profile_index) -> ImGuiID { ImGui::PushTextWrapPos(windowSize().x() * 0.40f); ImGui::Text("Are you sure you want to delete the %s %s profile ? This operation is irreversible.", - _profileManager->profiles().at(profile_index).companyName().c_str(), - _profileManager->profiles().at(profile_index).type() == ProfileType::Demo ? "demo" : "full game"); + _profileManager->profiles()[profile_index].companyName().c_str(), + _profileManager->profiles()[profile_index].type() == ProfileType::Demo ? "demo" : "full game"); ImGui::PopTextWrapPos(); if(ImGui::BeginTable("##DeleteProfileLayout", 2)) {