Skip to content

Commit

Permalink
Merge branch 'savegame_error' into 'master'
Browse files Browse the repository at this point in the history
Fix error message about savegame format

See merge request OpenMW/openmw!3796
  • Loading branch information
jvoisin committed Jan 23, 2024
2 parents ec6ac80 + a6ca726 commit 9616b03
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 26 deletions.
93 changes: 67 additions & 26 deletions apps/openmw/mwstate/statemanagerimp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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<int, int> contentFileMap = buildContentFileIndexMap(reader);
reader.setContentFileMapping(&contentFileMap);
Expand Down Expand Up @@ -625,21 +640,47 @@ 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();
std::string error = "#{OMWEngine:LoadingFailed}: " + std::string(e.what());
printSavegameFormatError(e.what(), error);
}
}

cleanup(true);
void MWState::StateManager::printSavegameFormatError(
const std::string& exceptionText, const std::string& messageBoxText)
{
Log(Debug::Error) << "Failed to load saved game: " << exceptionText;

MWBase::Environment::get().getWindowManager()->pushGuiMode(MWGui::GM_MainMenu);
cleanup(true);

std::vector<std::string> buttons;
buttons.emplace_back("#{Interface:OK}");
MWBase::Environment::get().getWindowManager()->pushGuiMode(MWGui::GM_MainMenu);

std::string error = "#{OMWEngine:LoadingFailed}: " + std::string(e.what());
std::vector<std::string> buttons;
buttons.emplace_back("#{Interface:OK}");

MWBase::Environment::get().getWindowManager()->interactiveMessageBox(error, buttons);
}
MWBase::Environment::get().getWindowManager()->interactiveMessageBox(messageBoxText, buttons);
}

void MWState::StateManager::quickLoad()
Expand Down
2 changes: 2 additions & 0 deletions apps/openmw/mwstate/statemanagerimp.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<std::string_view>& missingFiles) const;

void writeScreenshot(std::vector<char>& imageData) const;
Expand Down

0 comments on commit 9616b03

Please sign in to comment.