diff --git a/src/backend/game.cpp b/src/backend/game.cpp index b66e8343..4561cc8e 100644 --- a/src/backend/game.cpp +++ b/src/backend/game.cpp @@ -237,9 +237,6 @@ namespace loot { espm_settings = espm::Settings("fonv"); _repositoryURL = "https://github.com/loot/falloutnv.git"; _repositoryBranch = "master"; - } else { - BOOST_LOG_TRIVIAL(error) << "Invalid game ID supplied."; - throw error(error::invalid_args, lc::translate("Invalid game ID supplied.").str()); } if (!folder.empty()) @@ -279,6 +276,10 @@ namespace loot { } Game& Game::Init() { + if (id != Game::tes4 && id != Game::tes5 && id != Game::fo3 && id != Game::fonv) { + throw error(error::invalid_args, lc::translate("Invalid game ID supplied.").str()); + } + BOOST_LOG_TRIVIAL(info) << "Initialising filesystem-related data for game: " << _name; //First look for local install, then look for Registry. diff --git a/src/backend/generators.cpp b/src/backend/generators.cpp index 7e9c44db..2800a0f7 100644 --- a/src/backend/generators.cpp +++ b/src/backend/generators.cpp @@ -35,56 +35,6 @@ along with LOOT. If not, see using namespace std; -namespace loot { - bool AreSettingsValid(const YAML::Node& settings) { - if (!settings["language"]) - return false; - if (!settings["game"]) - return false; - if (!settings["lastGame"]) - return false; - if (!settings["debugVerbosity"]) - return false; - if (!settings["updateMasterlist"]) - return false; - if (!settings["games"]) - return false; - - return true; - } - - //Default settings file generation. - void GenerateDefaultSettingsFile(const boost::filesystem::path& file) { - BOOST_LOG_TRIVIAL(info) << "Generating default settings file."; - - YAML::Node root; - std::vector games; - - root["language"] = "en"; - root["game"] = "auto"; - root["lastGame"] = "auto"; - root["debugVerbosity"] = 0; - root["updateMasterlist"] = true; - - games.push_back(Game(Game::tes4)); - games.push_back(Game(Game::tes5)); - games.push_back(Game(Game::fo3)); - games.push_back(Game(Game::fonv)); - games.push_back(Game(Game::tes4, "Nehrim").SetDetails("Nehrim - At Fate's Edge", "Nehrim.esm", "https://github.com/loot/oblivion.git", "master", "", "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\Nehrim - At Fate's Edge_is1\\InstallLocation")); - - root["games"] = games; - - //Save settings. - YAML::Emitter yout; - yout.SetIndent(2); - yout << root; - - loot::ofstream out(file); - out << yout.c_str(); - out.close(); - } -} - namespace YAML { Emitter& operator << (Emitter& out, const loot::PluginDirtyInfo& rhs) { diff --git a/src/backend/generators.h b/src/backend/generators.h index 1493b51a..98234a10 100644 --- a/src/backend/generators.h +++ b/src/backend/generators.h @@ -32,15 +32,6 @@ #include #include -namespace loot { - // Check if the settings file has the right root keys (doesn't check - // their values). - bool AreSettingsValid(const YAML::Node& settings); - - //Default settings file generation. - void GenerateDefaultSettingsFile(const boost::filesystem::path& file); -} - namespace YAML { template Emitter& operator << (Emitter& out, const std::set& rhs) { diff --git a/src/gui/app.cpp b/src/gui/app.cpp index b9d56cce..3cd64f77 100644 --- a/src/gui/app.cpp +++ b/src/gui/app.cpp @@ -25,8 +25,10 @@ #include "app.h" #include "handler.h" +#include "../backend/error.h" #include "../backend/globals.h" #include "../backend/helpers.h" +#include "../backend/parsers.h" #include "../backend/generators.h" #include "../backend/streams.h" @@ -117,40 +119,30 @@ namespace loot { LootState::LootState() : _currentGame(0) {} void LootState::Init(const std::string& cmdLineGame) { - string initError; - - //Load settings. - if (!fs::exists(g_path_settings)) { - BOOST_LOG_TRIVIAL(error) << "Settings file doesn't exist, generating new file."; + // Check if the LOOT local app data folder exists, and create it if not. + if (!fs::exists(g_path_local)) { + BOOST_LOG_TRIVIAL(info) << "Local app data LOOT folder doesn't exist, creating it."; try { - fs::create_directory(g_path_settings.parent_path()); - GenerateDefaultSettingsFile(g_path_settings); + fs::create_directory(g_path_local); } - catch (fs::filesystem_error& /*e*/) { - initError = "Error: Could not create local app data LOOT folder."; + catch (exception& e) { + _initErrors.push_back((format(translate("Error: Could not create LOOT settings file. %1%")) % e.what()).str()); } } - BOOST_LOG_TRIVIAL(info) << "Parsing settings file."; - try { - loot::ifstream in(g_path_settings); - _settings = YAML::Load(in); - in.close(); - } - catch (YAML::ParserException& e) { - initError = (format(translate("Error: Settings parsing failed. %1%")) % e.what()).str(); - } - if (!AreSettingsValid(_settings)) { - BOOST_LOG_TRIVIAL(error) << "Settings file invalid, generating new file."; - GenerateDefaultSettingsFile(g_path_settings); + if (fs::exists(g_path_settings)) { try { loot::ifstream in(g_path_settings); _settings = YAML::Load(in); in.close(); } - catch (YAML::ParserException& e) { - initError = (format(translate("Error: Settings parsing failed. %1%")) % e.what()).str(); + catch (exception& e) { + _initErrors.push_back((format(translate("Error: Settings parsing failed. %1%")) % e.what()).str()); } } + // Check if the settings are valid (or if they don't exist). + if (!AreSettingsValid(_settings)) { + _settings = GetDefaultSettings(); + } //Set up logging. boost::log::add_file_log( @@ -212,33 +204,33 @@ namespace loot { } catch (YAML::Exception& e) { BOOST_LOG_TRIVIAL(error) << "Games' settings parsing failed. " << e.what(); - initError = (format(translate("Error: Games' settings parsing failed. %1%")) % e.what()).str(); - return; + _initErrors.push_back((format(translate("Error: Games' settings parsing failed. %1%")) % e.what()).str()); + // Now redo, but with no games settings, so only the hardcoded defaults get loaded. It means the user can + // at least still then edit them. + _games = GetGames(YAML::Node()); } - catch (std::exception& e) { - BOOST_LOG_TRIVIAL(error) << "Game-specific settings could not be initialised. " << e.what(); - initError = (format(translate("Error: Game-specific settings could not be initialised. %1%")) % e.what()).str(); - return; - } - - BOOST_LOG_TRIVIAL(debug) << "Selecting game."; try { + BOOST_LOG_TRIVIAL(debug) << "Selecting game."; _currentGame = SelectGame(_settings, _games, cmdLineGame); - } - catch (exception &) { - BOOST_LOG_TRIVIAL(error) << "None of the supported games were detected."; - } - BOOST_LOG_TRIVIAL(debug) << "Game selected is " << _games[_currentGame].Name(); - - //Now that game is selected, initialise it. - BOOST_LOG_TRIVIAL(debug) << "Initialising game-specific settings."; - try { + BOOST_LOG_TRIVIAL(debug) << "Initialising game-specific settings."; _games[_currentGame].Init(); } - catch (std::exception& e) { - BOOST_LOG_TRIVIAL(error) << "Game-specific settings could not be initialised. " << e.what(); + catch (loot::error &e) { + if (e.code() == loot::error::no_game_detected) { + BOOST_LOG_TRIVIAL(error) << e.what(); + _initErrors.push_back(e.what()); + } + else { + BOOST_LOG_TRIVIAL(error) << "Game-specific settings could not be initialised. " << e.what(); + _initErrors.push_back((format(translate("Error: Game-specific settings could not be initialised. %1%")) % e.what()).str()); + } } + BOOST_LOG_TRIVIAL(debug) << "Game selected is " << _games[_currentGame].Name(); + } + + const std::vector& LootState::InitErrors() const { + return _initErrors; } void LootState::ChangeGame(const std::string& newGameFolder) { @@ -248,18 +240,14 @@ namespace loot { }); _currentGame = std::distance(_games.begin(), it); - try { _games[_currentGame].Init(); BOOST_LOG_TRIVIAL(debug) << "New game is " << _games[_currentGame].Name(); - } - catch (std::exception& e) { - BOOST_LOG_TRIVIAL(error) << "Game-specific settings could not be initialised." << e.what(); - } } Game& LootState::CurrentGame() { return _games[_currentGame]; } + const std::vector& LootState::InstalledGames() const { return _games; } @@ -290,4 +278,42 @@ namespace loot { BOOST_LOG_TRIVIAL(error) << "Failed to save LOOT's settings. Error: " << e.what(); } } + + bool LootState::AreSettingsValid(const YAML::Node& settings) { + if (!settings["language"]) + return false; + if (!settings["game"]) + return false; + if (!settings["lastGame"]) + return false; + if (!settings["debugVerbosity"]) + return false; + if (!settings["updateMasterlist"]) + return false; + if (!settings["games"]) + return false; + + return true; + } + + YAML::Node LootState::GetDefaultSettings() { + YAML::Node root; + + root["language"] = "en"; + root["game"] = "auto"; + root["lastGame"] = "auto"; + root["debugVerbosity"] = 0; + root["updateMasterlist"] = true; + + std::vector games; + games.push_back(Game(Game::tes4)); + games.push_back(Game(Game::tes5)); + games.push_back(Game(Game::fo3)); + games.push_back(Game(Game::fonv)); + games.push_back(Game(Game::tes4, "Nehrim").SetDetails("Nehrim - At Fate's Edge", "Nehrim.esm", "https://github.com/loot/oblivion.git", "master", "", "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\Nehrim - At Fate's Edge_is1\\InstallLocation")); + + root["games"] = games; + + return root; + } } \ No newline at end of file diff --git a/src/gui/app.h b/src/gui/app.h index ead14ff6..e076dd90 100644 --- a/src/gui/app.h +++ b/src/gui/app.h @@ -66,10 +66,12 @@ namespace loot { public: LootState(); + // Init may fail with no void Init(const std::string& cmdLineGame); - void ChangeGame(const std::string& newGameFolder); + const std::vector& InitErrors() const; Game& CurrentGame(); + void ChangeGame(const std::string& newGameFolder); const std::vector& InstalledGames() const; const YAML::Node& GetSettings() const; @@ -79,6 +81,11 @@ namespace loot { YAML::Node _settings; std::vector _games; size_t _currentGame; + std::vector _initErrors; + + // Check if the settings file has the right root keys (doesn't check their values). + bool AreSettingsValid(const YAML::Node& settings); + YAML::Node GetDefaultSettings(); }; extern LootState g_app_state;