From 5878bf48562df4b839a0aa5327e7297153c8ca06 Mon Sep 17 00:00:00 2001 From: William JCM Date: Thu, 16 Jan 2020 00:35:23 +0100 Subject: [PATCH] MassManager: add staging area stuff. --- MassManager/MassManager.cpp | 189 +++++++++++++++++++++++++++++++++++- MassManager/MassManager.h | 18 ++++ 2 files changed, 206 insertions(+), 1 deletion(-) diff --git a/MassManager/MassManager.cpp b/MassManager/MassManager.cpp index 42214d6..26801b8 100644 --- a/MassManager/MassManager.cpp +++ b/MassManager/MassManager.cpp @@ -17,7 +17,6 @@ #include #include -#include #include #include @@ -47,12 +46,18 @@ MassManager::MassManager() { return; } + _executableLocation = Utility::Directory::path(Utility::Directory::executableLocation()); + + _stagingAreaDirectory = Utility::Directory::join(_executableLocation, "staging"); + _profileSaveName = Utility::formatString("Profile{}.sav", _steamId); for(int i = 0; i < 32; ++i) { _hangars[i]._filename = Utility::formatString("Unit{:.2d}{}.sav", i, _steamId); refreshHangar(i); } + + initialiseStagingArea(); } auto MassManager::ready() -> bool { @@ -67,6 +72,10 @@ auto MassManager::saveDirectory() -> std::string const& { return _saveDirectory; } +auto MassManager::stagingAreaDirectory() -> std::string const& { + return _stagingAreaDirectory; +} + auto MassManager::steamId() -> std::string const& { return _steamId; } @@ -170,6 +179,87 @@ auto MassManager::importMass(const std::string& source, int hangar) -> bool { return true; } +auto MassManager::importMass(int staged_index, int hangar) -> bool { + if(hangar < 0 && hangar >= 32) { + _lastError = "Hangar out of range in MassManager::importMass()"; + return false; + } + + int i = 0; + for(const auto& mass_info : _stagedMasses) { + if(i != staged_index) { + ++i; + continue; + } + + std::string source = Utility::Directory::join(_stagingAreaDirectory, mass_info.first); + + Utility::Directory::copy(source, source + ".tmp"); + + { + auto mmap = Utility::Directory::map(source + ".tmp"); + + auto iter = std::search(mmap.begin(), mmap.end(), &steamid_locator[0], &steamid_locator[23]); + + if(iter == mmap.end()) { + _lastError = "The M.A.S.S. file at " + source + " seems to be corrupt."; + Utility::Directory::rm(source + ".tmp"); + return false; + } + + iter += 37; + + if(std::strncmp(iter, _steamId.c_str(), _steamId.length()) != 0) { + for(int i = 0; i < 17; ++i) { + *(iter + i) = _steamId[i]; + } + } + } + + const std::string dest = Utility::Directory::join(_saveDirectory, _hangars[hangar]._filename); + + if(Utility::Directory::exists(dest)) { + Utility::Directory::rm(dest); + } + + Utility::Directory::move(source + ".tmp", dest); + + return true; + } + + _lastError = ""; + return false; +} + +auto MassManager::exportMass(int hangar) -> bool { + if(hangar < 0 && hangar >= 32) { + _lastError = "Hangar out of range in MassManager::exportMass()"; + return false; + } + + if(_hangars[hangar]._state == HangarState::Empty || + _hangars[hangar]._state == HangarState::Invalid) { + _lastError = Utility::formatString("There is no valid data to export in hangar {:.2d}", hangar); + } + + auto name = _hangars[hangar]._massName; + + if(!name) { + _lastError = "There was an unexpected error in MassManager::exportMass()"; + return false; + } + + std::string source = Utility::Directory::join(_saveDirectory, _hangars[hangar]._filename); + std::string dest = Utility::Directory::join(_stagingAreaDirectory, Utility::formatString("{}_{}.sav", _steamId, *(_hangars[hangar]._massName))); + + if(!Utility::Directory::copy(source, dest)) { + _lastError = Utility::formatString("Couldn't export data from hangar {:.2d} to {}", hangar, dest); + return false; + } + + return true; +} + auto MassManager::moveMass(int source, int destination) -> bool { if(source < 0 && source >= 32) { _lastError = "Source hangar out of range in MassManager::moveMass()"; @@ -308,6 +398,103 @@ auto MassManager::getMassName(const std::string& filename) -> Containers::Option return name; } +auto MassManager::initialiseStagingArea() -> std::vector { + if(!Utility::Directory::exists(_stagingAreaDirectory)) { + Utility::Directory::mkpath(_stagingAreaDirectory); + } + + using Utility::Directory::Flag; + std::vector file_list = Utility::Directory::list(_stagingAreaDirectory, Flag::SkipSpecial|Flag::SkipDirectories|Flag::SkipDotAndDotDot); + + auto iter = std::remove_if(file_list.begin(), file_list.end(), [](std::string& file){ + return !Utility::String::endsWith(file, ".sav"); + }); + + file_list.erase(iter, file_list.end()); + + std::vector mass_names; + mass_names.reserve(file_list.size()); + + for(const std::string& file : file_list) { + auto name = getMassName(Utility::Directory::join(_stagingAreaDirectory, file)); + + if(name) { + mass_names.push_back(Utility::formatString("{} ({})", *name, file)); + _stagedMasses[file] = *name; + } + } + + mass_names.shrink_to_fit(); + + return std::move(mass_names); +} + +auto MassManager::updateStagedMass(const std::string& filename) -> int { + std::string file = Utility::Directory::join(_stagingAreaDirectory, filename); + + if(!Utility::Directory::exists(file)) { + return -1; + } + + auto name = getMassName(file); + + if(!name) { + return -1; + } + + _stagedMasses[filename] = *name; + + int index = 0; + + for(const auto& mass: _stagedMasses) { + if(mass.first != filename) { + ++index; + continue; + } + + return index; + } + + return -1; +} + +auto MassManager::removeStagedMass(const std::string& filename) -> int { + int index = 0; + + for(auto it = _stagedMasses.begin(); it != _stagedMasses.end(); ++it, ++index) { + if(it->first == filename) { + _stagedMasses.erase(it); + return index; + } + } + + return -1; +} + +std::string MassManager::stagedMassName(int index) { + int i = 0; + for(const auto& mass_info : _stagedMasses) { + if(i != index) { + ++i; + continue; + } + + return mass_info.second; + } + + return ""; +} + +auto MassManager::stagedMassName(const std::string& filename) -> std::string { + auto iter = _stagedMasses.find(filename); + + if(iter == _stagedMasses.end()) { + return ""; + } + + return iter->second; +} + auto MassManager::findSaveDirectory() -> bool { wchar_t h[MAX_PATH]; if(!SUCCEEDED(SHGetFolderPathW(nullptr, CSIDL_LOCAL_APPDATA, nullptr, 0, h))) { diff --git a/MassManager/MassManager.h b/MassManager/MassManager.h index 9a8e2cf..2698a7e 100644 --- a/MassManager/MassManager.h +++ b/MassManager/MassManager.h @@ -17,7 +17,9 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . +#include #include +#include #include #include @@ -40,6 +42,7 @@ class MassManager { auto lastError() -> std::string const&; auto saveDirectory() -> std::string const&; + auto stagingAreaDirectory() -> std::string const&; auto steamId() -> std::string const&; auto profileSaveName() -> std::string const&; @@ -50,6 +53,9 @@ class MassManager { auto activeSlot() -> char; auto importMass(const std::string& source, int hangar) -> bool; + auto importMass(int staged_index, int hangar) -> bool; + + auto exportMass(int hangar) -> bool; auto moveMass(int source, int destination) -> bool; @@ -63,6 +69,14 @@ class MassManager { auto getMassName(const std::string& filename) -> Containers::Optional; + auto initialiseStagingArea() -> std::vector; + + auto updateStagedMass(const std::string& filename) -> int; + auto removeStagedMass(const std::string& filename) -> int; + + auto stagedMassName(int index) -> std::string; + auto stagedMassName(const std::string& filename) -> std::string; + private: auto findSaveDirectory() -> bool; auto findSteamId() -> bool; @@ -71,6 +85,8 @@ class MassManager { std::string _lastError = ""; + std::string _executableLocation = ""; + std::string _stagingAreaDirectory = ""; std::string _saveDirectory = ""; std::string _steamId = ""; std::string _profileSaveName = ""; @@ -86,6 +102,8 @@ class MassManager { }; Containers::StaticArray<32, Hangar> _hangars{Containers::ValueInit}; + + std::map _stagedMasses; }; #endif //MASSMANAGER_H