1.5: Fuckin' UE5... #38
8 changed files with 157 additions and 147 deletions
|
@ -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{
|
||||
|
|
|
@ -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};
|
||||
|
|
|
@ -14,15 +14,9 @@
|
|||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
#include <Corrade/Containers/ScopeGuard.h>
|
||||
#include <Corrade/Utility/Path.h>
|
||||
#include <Corrade/Utility/Unicode.h>
|
||||
|
||||
#include <SDL_events.h>
|
||||
#include <SDL_messagebox.h>
|
||||
|
||||
#include <shlobj.h>
|
||||
|
||||
#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<char*>(&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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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()) {
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -16,7 +16,15 @@
|
|||
|
||||
#include <Corrade/Containers/Optional.h>
|
||||
#include <Corrade/Containers/Pair.h>
|
||||
#include <Corrade/Containers/ScopeGuard.h>
|
||||
#include <Corrade/Utility/Path.h>
|
||||
#include <Corrade/Utility/Unicode.h>
|
||||
|
||||
#include <combaseapi.h>
|
||||
#include <knownfolders.h>
|
||||
#include <shlobj.h>
|
||||
|
||||
#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<char*>(&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{};
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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};
|
||||
|
|
Loading…
Reference in a new issue