From a6ca726c3aa91d1fa564cf08bd444c67b08a5f9d Mon Sep 17 00:00:00 2001 From: Andrei Kortunov Date: Sun, 21 Jan 2024 12:54:33 +0400 Subject: [PATCH] Fix error message about savegame format --- apps/openmw/mwstate/statemanagerimp.cpp | 99 +++++++++++++++++-------- apps/openmw/mwstate/statemanagerimp.hpp | 2 + 2 files changed, 72 insertions(+), 29 deletions(-) diff --git a/apps/openmw/mwstate/statemanagerimp.cpp b/apps/openmw/mwstate/statemanagerimp.cpp index 631ef9a112..8d3b84df13 100644 --- a/apps/openmw/mwstate/statemanagerimp.cpp +++ b/apps/openmw/mwstate/statemanagerimp.cpp @@ -409,9 +409,38 @@ void MWState::StateManager::loadGame(const std::filesystem::path& filepath) loadGame(character, filepath); } -struct VersionMismatchError : public std::runtime_error +struct SaveFormatVersionError : public std::exception { - using std::runtime_error::runtime_error; + using std::exception::exception; + + SaveFormatVersionError(ESM::FormatVersion savegameFormat, const std::string& message) + : mSavegameFormat(savegameFormat) + , mErrorMessage(message) + { + } + + const char* what() const noexcept override { return mErrorMessage.c_str(); } + ESM::FormatVersion getFormatVersion() const { return mSavegameFormat; } + +protected: + ESM::FormatVersion mSavegameFormat = ESM::DefaultFormatVersion; + std::string mErrorMessage; +}; + +struct SaveVersionTooOldError : SaveFormatVersionError +{ + SaveVersionTooOldError(ESM::FormatVersion savegameFormat) + : SaveFormatVersionError(savegameFormat, "format version " + std::to_string(savegameFormat) + " is too old") + { + } +}; + +struct SaveVersionTooNewError : SaveFormatVersionError +{ + SaveVersionTooNewError(ESM::FormatVersion savegameFormat) + : SaveFormatVersionError(savegameFormat, "format version " + std::to_string(savegameFormat) + " is too new") + { + } }; void MWState::StateManager::loadGame(const Character* character, const std::filesystem::path& filepath) @@ -427,23 +456,9 @@ void MWState::StateManager::loadGame(const Character* character, const std::file ESM::FormatVersion version = reader.getFormatVersion(); if (version > ESM::CurrentSaveGameFormatVersion) - throw VersionMismatchError("#{OMWEngine:LoadingRequiresNewVersionError}"); + throw SaveVersionTooNewError(version); else if (version < ESM::MinSupportedSaveGameFormatVersion) - { - const char* release; - // Report the last version still capable of reading this save - if (version <= ESM::OpenMW0_48SaveGameFormatVersion) - release = "OpenMW 0.48.0"; - else - { - // Insert additional else if statements above to cover future releases - static_assert(ESM::MinSupportedSaveGameFormatVersion <= ESM::OpenMW0_49SaveGameFormatVersion); - release = "OpenMW 0.49.0"; - } - auto l10n = MWBase::Environment::get().getL10nManager()->getContext("OMWEngine"); - std::string message = l10n->formatMessage("LoadingRequiresOldVersionError", { "version" }, { release }); - throw VersionMismatchError(message); - } + throw SaveVersionTooOldError(version); std::map contentFileMap = buildContentFileIndexMap(reader); reader.setContentFileMapping(&contentFileMap); @@ -625,23 +640,49 @@ void MWState::StateManager::loadGame(const Character* character, const std::file MWBase::Environment::get().getLuaManager()->gameLoaded(); } + catch (const SaveVersionTooNewError& e) + { + std::string error = "#{OMWEngine:LoadingRequiresNewVersionError}"; + printSavegameFormatError(e.what(), error); + } + catch (const SaveVersionTooOldError& e) + { + const char* release; + // Report the last version still capable of reading this save + if (e.getFormatVersion() <= ESM::OpenMW0_48SaveGameFormatVersion) + release = "OpenMW 0.48.0"; + else + { + // Insert additional else if statements above to cover future releases + static_assert(ESM::MinSupportedSaveGameFormatVersion <= ESM::OpenMW0_49SaveGameFormatVersion); + release = "OpenMW 0.49.0"; + } + auto l10n = MWBase::Environment::get().getL10nManager()->getContext("OMWEngine"); + std::string error = l10n->formatMessage("LoadingRequiresOldVersionError", { "version" }, { release }); + printSavegameFormatError(e.what(), error); + } catch (const std::exception& e) { - Log(Debug::Error) << "Failed to load saved game: " << e.what(); - - cleanup(true); - - MWBase::Environment::get().getWindowManager()->pushGuiMode(MWGui::GM_MainMenu); - - std::vector buttons; - buttons.emplace_back("#{Interface:OK}"); - std::string error = "#{OMWEngine:LoadingFailed}: " + std::string(e.what()); - - MWBase::Environment::get().getWindowManager()->interactiveMessageBox(error, buttons); + printSavegameFormatError(e.what(), error); } } +void MWState::StateManager::printSavegameFormatError( + const std::string& exceptionText, const std::string& messageBoxText) +{ + Log(Debug::Error) << "Failed to load saved game: " << exceptionText; + + cleanup(true); + + MWBase::Environment::get().getWindowManager()->pushGuiMode(MWGui::GM_MainMenu); + + std::vector buttons; + buttons.emplace_back("#{Interface:OK}"); + + MWBase::Environment::get().getWindowManager()->interactiveMessageBox(messageBoxText, buttons); +} + void MWState::StateManager::quickLoad() { if (Character* currentCharacter = getCurrentCharacter()) diff --git a/apps/openmw/mwstate/statemanagerimp.hpp b/apps/openmw/mwstate/statemanagerimp.hpp index a76b829e38..c25e43cc23 100644 --- a/apps/openmw/mwstate/statemanagerimp.hpp +++ b/apps/openmw/mwstate/statemanagerimp.hpp @@ -22,6 +22,8 @@ namespace MWState private: void cleanup(bool force = false); + void printSavegameFormatError(const std::string& exceptionText, const std::string& messageBoxText); + bool confirmLoading(const std::vector& missingFiles) const; void writeScreenshot(std::vector& imageData) const;