From efc3fe0dc73427d917f8d164b3a0d3051c86ca96 Mon Sep 17 00:00:00 2001 From: Guillaume Jacquemin Date: Sat, 9 Mar 2024 18:09:27 +0100 Subject: [PATCH] Application: move folder management to Configuration. Also, add new folders for the upcoming weapon/armour/style export/import mechanism. --- src/Application/Application.cpp | 14 --- src/Application/Application.h | 14 --- .../Application_Initialisation.cpp | 112 +----------------- src/Application/Application_MainManager.cpp | 2 +- src/Application/Application_drawMainMenu.cpp | 32 +++-- src/Configuration/Configuration.cpp | 101 ++++++++++++++++ src/Configuration/Configuration.h | 22 ++++ src/main.cpp | 7 ++ 8 files changed, 157 insertions(+), 147 deletions(-) diff --git a/src/Application/Application.cpp b/src/Application/Application.cpp index c066d29..b868c93 100644 --- a/src/Application/Application.cpp +++ b/src/Application/Application.cpp @@ -103,20 +103,6 @@ Application::Application(const Arguments& arguments): initialiseGui(); - if(!initialiseToolDirectories()) { - SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Error initialising the app", - _lastError.data(), window()); - exit(EXIT_FAILURE); - return; - } - - if(!findGameDataDirectory()) { - SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Error initialising the app", - _lastError.data(), window()); - exit(EXIT_FAILURE); - return; - } - checkGameState(); _gameCheckTimerId = SDL_AddTimer(2000, [](std::uint32_t interval, void* param)->std::uint32_t{ diff --git a/src/Application/Application.h b/src/Application/Application.h index bb3190a..c997776 100644 --- a/src/Application/Application.h +++ b/src/Application/Application.h @@ -102,8 +102,6 @@ class Application: public Platform::Sdl2Application, public efsw::FileWatchListe void initialiseConfiguration(); void initialiseGui(); void initialiseManager(); - bool initialiseToolDirectories(); - bool findGameDataDirectory(); void initialiseMassManager(); void initialiseFileWatcher(); @@ -230,18 +228,6 @@ class Application: public Platform::Sdl2Application, public efsw::FileWatchListe Containers::String _lastError; - Containers::String _gameDataDir; - Containers::String _configDir; - Containers::String _saveDir; - Containers::String _screenshotsDir; - - Containers::String _backupsDir; - Containers::String _stagingDir; - //Containers::String _armouryDir; - //Containers::String _armoursDir; - //Containers::String _weaponsDir; - //Containers::String _stylesDir; - enum class GameState : std::uint8_t { Unknown, NotRunning, Running } _gameState{GameState::Unknown}; diff --git a/src/Application/Application_Initialisation.cpp b/src/Application/Application_Initialisation.cpp index 87621ce..31f68e8 100644 --- a/src/Application/Application_Initialisation.cpp +++ b/src/Application/Application_Initialisation.cpp @@ -14,15 +14,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 -#include - #include "../Configuration/Configuration.h" #include "../FontAwesome/IconsFontAwesome5.h" #include "../FontAwesome/IconsFontAwesome5Brands.h" @@ -115,7 +109,7 @@ Application::initialiseManager() { SDL_zero(event); event.type = _initEventId; - _profileManager.emplace(_saveDir, _backupsDir); + _profileManager.emplace(conf().directories().gameSaves, conf().directories().backups); if(!_profileManager->ready()) { event.user.code = ProfileManagerFailure; SDL_PushEvent(&event); @@ -126,115 +120,19 @@ Application::initialiseManager() { SDL_PushEvent(&event); } -auto -Application::initialiseToolDirectories() -> bool { - LOG_INFO("Initialising Save Tool directories."); - - _backupsDir = Utility::Path::join(Utility::Path::split(*Utility::Path::executableLocation()).first(), "backups"); - _stagingDir = Utility::Path::join(Utility::Path::split(*Utility::Path::executableLocation()).first(), "staging"); - //_armouryDir = Utility::Directory::join(Utility::Directory::path(Utility::Directory::executableLocation()), "armoury"); - //_armoursDir = Utility::Directory::join(_armouryDir, "armours"); - //_weaponsDir = Utility::Directory::join(_armouryDir, "weapons"); - //_stylesDir = Utility::Directory::join(_armouryDir, "styles"); - - if(!Utility::Path::exists(_backupsDir)) { - LOG_WARNING("Backups directory not found, creating..."); - if(!Utility::Path::make(_backupsDir)) { - LOG_ERROR(_lastError = "Couldn't create the backups directory."); - return false; - } - } - - if(!Utility::Path::exists(_stagingDir)) { - LOG_WARNING("Staging directory not found, creating..."); - if(!Utility::Path::make(_stagingDir)) { - LOG_ERROR(_lastError = "Couldn't create the staging directory."); - return false; - } - } - - //if(!Utility::Directory::exists(_armouryDir)) { - // Utility::Debug{} << "Armoury directory not found, creating..."; - // if(!Utility::Path::make(_armouryDir)) { - // Utility::Error{} << (_lastError = "Couldn't create the armoury directory."); - // return false; - // } - //} - - //if(!Utility::Directory::exists(_armoursDir)) { - // Utility::Debug{} << "Armours directory not found, creating..."; - // if(!Utility::Path::make(_armoursDir)) { - // Utility::Error{} << (_lastError = "Couldn't create the armours directory."); - // return false; - // } - //} - - //if(!Utility::Directory::exists(_weaponsDir)) { - // Utility::Debug{} << "Weapons directory not found, creating..."; - // if(!Utility::Path::make(_weaponsDir)) { - // Utility::Error{} << (_lastError = "Couldn't create the weapons directory."); - // return false; - // } - //} - - //if(!Utility::Directory::exists(_stylesDir)) { - // Utility::Debug{} << "Styles directory not found, creating..."; - // if(!Utility::Path::make(_stylesDir)) { - // Utility::Error{} << (_lastError = "Couldn't create the styles directory."); - // return false; - // } - //} - - return true; -} - -auto -Application::findGameDataDirectory() -> bool { - LOG_INFO("Searching for the game's save directory."); - - wchar_t* localappdata_path = nullptr; - Containers::ScopeGuard guard{localappdata_path, CoTaskMemFree}; - auto result = SHGetKnownFolderPath(FOLDERID_LocalAppData, KF_FLAG_DEFAULT, nullptr, &localappdata_path); - if(result != S_OK) - { - char* message_buffer = nullptr; - auto size = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS, - nullptr, result, MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), - reinterpret_cast(&message_buffer), 0, nullptr); - String message{message_buffer, size}; - LocalFree(message_buffer); - - _lastError = Utility::format("SHGetKnownFolderPath() failed with error code {}: {}", result, message); - LOG_ERROR(_lastError); - return false; - } - - _gameDataDir = Utility::Path::join(Utility::Path::fromNativeSeparators(Utility::Unicode::narrow(localappdata_path)), "MASS_Builder"_s); - - if(!Utility::Path::exists(_gameDataDir)) { - LOG_ERROR(_lastError = _gameDataDir + " wasn't found. Make sure to play the game at least once."_s); - return false; - } - - _configDir = Utility::Path::join(_gameDataDir, "Saved/Config/WindowsNoEditor"_s); - _saveDir = Utility::Path::join(_gameDataDir, "Saved/SaveGames"_s); - _screenshotsDir = Utility::Path::join(_gameDataDir, "Saved/Screenshots/WindowsNoEditor"_s); - - return true; -} - void Application::initialiseMassManager() { LOG_INFO("Initialising the M.A.S.S. manager."); - _massManager.emplace(_saveDir, _currentProfile->account(), _currentProfile->isDemo(), _stagingDir); + _massManager.emplace(conf().directories().gameSaves, _currentProfile->account(), _currentProfile->isDemo(), + conf().directories().staging); } void Application::initialiseFileWatcher() { LOG_INFO("Initialising the file watcher."); _fileWatcher.emplace(); - _watchIDs[SaveDir] = _fileWatcher->addWatch(_saveDir, this, false); - _watchIDs[StagingDir] = _fileWatcher->addWatch(_stagingDir, this, false); + _watchIDs[SaveDir] = _fileWatcher->addWatch(conf().directories().gameSaves, this, false); + _watchIDs[StagingDir] = _fileWatcher->addWatch(conf().directories().staging, this, false); _fileWatcher->watch(); } diff --git a/src/Application/Application_MainManager.cpp b/src/Application/Application_MainManager.cpp index e3fb5e7..a5d56cf 100644 --- a/src/Application/Application_MainManager.cpp +++ b/src/Application/Application_MainManager.cpp @@ -538,7 +538,7 @@ Application::drawMassManager() { ImGui::TextUnformatted("Staging area"); ImGui::SameLine(); if(ImGui::SmallButton(ICON_FA_FOLDER_OPEN " Open staging folder")) { - openUri(Utility::Path::toNativeSeparators(_stagingDir)); + openUri(Utility::Path::toNativeSeparators(conf().directories().staging)); } for(const auto& pair : _massManager->stagedMasses()) { diff --git a/src/Application/Application_drawMainMenu.cpp b/src/Application/Application_drawMainMenu.cpp index de66c4b..dc7ddb9 100644 --- a/src/Application/Application_drawMainMenu.cpp +++ b/src/Application/Application_drawMainMenu.cpp @@ -31,29 +31,39 @@ Application::drawMainMenu() { } if(ImGui::BeginMenu("Save Tool##SaveToolMenu")) { - if(ImGui::BeginMenu(ICON_FA_FOLDER_OPEN " Open game data directory", Utility::Path::exists(_gameDataDir))) { - if(ImGui::MenuItem(ICON_FA_COG " Configuration", nullptr, false, Utility::Path::exists(_configDir))) { - openUri(Utility::Path::toNativeSeparators(_configDir)); + if(ImGui::BeginMenu(ICON_FA_FOLDER_OPEN " Open game data directory")) { + if(ImGui::MenuItem(ICON_FA_COG " Configuration", nullptr, false, + Utility::Path::exists(conf().directories().gameConfig))) + { + openUri(Utility::Path::toNativeSeparators(conf().directories().gameConfig)); } - if(ImGui::MenuItem(ICON_FA_SAVE " Saves", nullptr, false, Utility::Path::exists(_saveDir))) { - openUri(Utility::Path::toNativeSeparators(_saveDir)); + if(ImGui::MenuItem(ICON_FA_SAVE " Saves", nullptr, false, + Utility::Path::exists(conf().directories().gameSaves))) + { + openUri(Utility::Path::toNativeSeparators(conf().directories().gameSaves)); } - if(ImGui::MenuItem(ICON_FA_IMAGE " Screenshots", nullptr, false, Utility::Path::exists(_screenshotsDir))) { - openUri(Utility::Path::toNativeSeparators(_screenshotsDir)); + if(ImGui::MenuItem(ICON_FA_IMAGE " Screenshots", nullptr, false, + Utility::Path::exists(conf().directories().gameScreenshots))) + { + openUri(Utility::Path::toNativeSeparators(conf().directories().gameScreenshots)); } ImGui::EndMenu(); } if(ImGui::BeginMenu(ICON_FA_FOLDER_OPEN " Open manager directory")) { - if(ImGui::MenuItem(ICON_FA_FILE_ARCHIVE " Profile backups", nullptr, false, Utility::Path::exists(_backupsDir))) { - openUri(Utility::Path::toNativeSeparators(_backupsDir)); + if(ImGui::MenuItem(ICON_FA_FILE_ARCHIVE " Profile backups", nullptr, false, + Utility::Path::exists(conf().directories().backups))) + { + openUri(Utility::Path::toNativeSeparators(conf().directories().backups)); } - if(ImGui::MenuItem(ICON_FA_EXCHANGE_ALT " Staging area", nullptr, false, Utility::Path::exists(_stagingDir))) { - openUri(Utility::Path::toNativeSeparators(_stagingDir)); + if(ImGui::MenuItem(ICON_FA_EXCHANGE_ALT " Staging area", nullptr, false, + Utility::Path::exists(conf().directories().staging))) + { + openUri(Utility::Path::toNativeSeparators(conf().directories().staging)); } ImGui::EndMenu(); diff --git a/src/Configuration/Configuration.cpp b/src/Configuration/Configuration.cpp index bb9b182..62a6a62 100644 --- a/src/Configuration/Configuration.cpp +++ b/src/Configuration/Configuration.cpp @@ -16,7 +16,15 @@ #include #include +#include #include +#include + +#include +#include +#include + +#include "../Logger/Logger.h" #include "Configuration.h" @@ -75,12 +83,100 @@ Configuration::Configuration() { else { _conf.setValue("skip_disclaimer", _skipDisclaimer); } + + LOG_INFO("Searching for the game's save directory."); + wchar_t* localappdata_path = nullptr; + Containers::ScopeGuard guard{localappdata_path, CoTaskMemFree}; + auto result = SHGetKnownFolderPath(FOLDERID_LocalAppData, KF_FLAG_DEFAULT, nullptr, &localappdata_path); + if(result != S_OK) + { + char* message_buffer = nullptr; + auto size = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS, + nullptr, result, MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), + reinterpret_cast(&message_buffer), 0, nullptr); + String message{message_buffer, size}; + LocalFree(message_buffer); + + _lastError = Utility::format("SHGetKnownFolderPath() failed with error code {}: {}", result, message); + LOG_ERROR(_lastError); + return; + } + + auto game_data_dir = Utility::Path::join( + Utility::Path::fromNativeSeparators(Utility::Unicode::narrow(localappdata_path)), + "MASS_Builder/Saved"_s + ); + if(!Utility::Path::exists(game_data_dir)) { + LOG_ERROR(_lastError = game_data_dir + " wasn't found. Make sure to play the game at least once."_s); + return; + } + + _directories.gameConfig = Utility::Path::join(game_data_dir, "Config/WindowsNoEditor"_s); + _directories.gameSaves = Utility::Path::join(game_data_dir, "SaveGames"_s); + _directories.gameScreenshots = Utility::Path::join(game_data_dir, "Screenshots/WindowsNoEditor"_s); + + LOG_INFO("Initialising Save Tool directories."); + Containers::String executable_location = Utility::Path::split(*Utility::Path::executableLocation()).first(); + _directories.backups = Utility::Path::join(executable_location, "backups"); + _directories.staging = Utility::Path::join(executable_location, "staging"); + auto armoury_dir = Utility::Path::join(executable_location, "armoury"); + _directories.armours = Utility::Path::join(armoury_dir, "armours"); + _directories.weapons = Utility::Path::join(armoury_dir, "weapons"); + _directories.styles = Utility::Path::join(armoury_dir, "styles"); + + if(!Utility::Path::exists(_directories.backups)) { + LOG_WARNING("Backups directory not found, creating..."); + if(!Utility::Path::make(_directories.backups)) { + LOG_ERROR(_lastError = "Couldn't create the backups directory."); + return; + } + } + if(!Utility::Path::exists(_directories.staging)) { + LOG_WARNING("Staging directory not found, creating..."); + if(!Utility::Path::make(_directories.staging)) { + LOG_ERROR(_lastError = "Couldn't create the staging directory."); + return; + } + } + if(!Utility::Path::exists(_directories.armours)) { + LOG_WARNING("Armours directory not found, creating..."); + if(!Utility::Path::make(_directories.armours)) { + LOG_ERROR(_lastError = "Couldn't create the armours directory."); + return; + } + } + if(!Utility::Path::exists(_directories.weapons)) { + LOG_WARNING("Weapons directory not found, creating..."); + if(!Utility::Path::make(_directories.weapons)) { + LOG_ERROR(_lastError = "Couldn't create the weapons directory."); + return; + } + } + if(!Utility::Path::exists(_directories.styles)) { + LOG_WARNING("Styles directory not found, creating..."); + if(!Utility::Path::make(_directories.styles)) { + LOG_ERROR(_lastError = "Couldn't create the styles directory."); + return; + } + } + + _valid = true; } Configuration::~Configuration() { save(); } +bool +Configuration::valid() const { + return _valid; +} + +Containers::StringView +Configuration::lastError() const { + return _lastError; +} + void Configuration::save() { _conf.save(); @@ -168,6 +264,11 @@ Configuration::setRunningInWine(bool wine) { _isRunningInWine = wine; } +Configuration::Directories const& +Configuration::directories() const { + return _directories; +} + Configuration& Configuration::instance() { static Configuration conf{}; diff --git a/src/Configuration/Configuration.h b/src/Configuration/Configuration.h index dcf4c46..febea45 100644 --- a/src/Configuration/Configuration.h +++ b/src/Configuration/Configuration.h @@ -28,6 +28,10 @@ class Configuration { ~Configuration(); + bool valid() const; + + auto lastError() const -> Containers::StringView; + void save(); auto swapInterval() const -> int; @@ -51,11 +55,25 @@ class Configuration { bool isRunningInWine() const; void setRunningInWine(bool wine); + struct Directories { + Containers::String gameSaves; + Containers::String gameConfig; + Containers::String gameScreenshots; + Containers::String backups; + Containers::String staging; + Containers::String armours; + Containers::String weapons; + Containers::String styles; + }; + auto directories() const -> Directories const&; + private: explicit Configuration(); Utility::Configuration _conf; + Containers::String _lastError; + int _swapInterval = 1; float _fpsCap = 60.0f; bool _cheatMode = false; @@ -64,6 +82,10 @@ class Configuration { bool _skipDisclaimer = false; bool _isRunningInWine = false; + + bool _valid = false; + + Directories _directories; }; Configuration& conf(); diff --git a/src/main.cpp b/src/main.cpp index b31da04..14142cb 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -41,6 +41,13 @@ int main(int argc, char** argv) { LOG_INFO("Initialising M.A.S.S. Builder Save Tool version " SAVETOOL_VERSION_STRING "."); + if(!mbst::conf().valid()) { + LOG_ERROR_FORMAT("There was an error initialising the app: {}", mbst::conf().lastError()); + SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Error", + mbst::conf().lastError().cbegin(), nullptr); + return EXIT_FAILURE; + } + auto str = setlocale(LC_ALL, ".utf-8"); if(str) { Containers::StringView locale{str};