Properly handle exceptions when saving the game

Add message boxes when an exception occurs while loading or saving the game
deque
scrawl 11 years ago
parent 5df9ff8e2c
commit 8b33c087e0

@ -149,91 +149,105 @@ void MWState::StateManager::endGame()
void MWState::StateManager::saveGame (const std::string& description, const Slot *slot)
{
ESM::SavedGame profile;
try
{
ESM::SavedGame profile;
MWBase::World& world = *MWBase::Environment::get().getWorld();
MWBase::World& world = *MWBase::Environment::get().getWorld();
MWWorld::Ptr player = world.getPlayerPtr();
MWWorld::Ptr player = world.getPlayerPtr();
profile.mContentFiles = world.getContentFiles();
profile.mContentFiles = world.getContentFiles();
profile.mPlayerName = player.getClass().getName (player);
profile.mPlayerLevel = player.getClass().getNpcStats (player).getLevel();
profile.mPlayerName = player.getClass().getName (player);
profile.mPlayerLevel = player.getClass().getNpcStats (player).getLevel();
std::string classId = player.get<ESM::NPC>()->mBase->mClass;
if (world.getStore().get<ESM::Class>().isDynamic(classId))
profile.mPlayerClassName = world.getStore().get<ESM::Class>().find(classId)->mName;
else
profile.mPlayerClassId = classId;
profile.mPlayerCell = world.getCellName();
profile.mInGameTime.mGameHour = world.getTimeStamp().getHour();
profile.mInGameTime.mDay = world.getDay();
profile.mInGameTime.mMonth = world.getMonth();
profile.mInGameTime.mYear = world.getYear();
profile.mTimePlayed = mTimePlayed;
profile.mDescription = description;
int screenshotW = 259*2, screenshotH = 133*2; // *2 to get some nice antialiasing
Ogre::Image screenshot;
world.screenshot(screenshot, screenshotW, screenshotH);
Ogre::DataStreamPtr encoded = screenshot.encode("jpg");
profile.mScreenshot.resize(encoded->size());
encoded->read(&profile.mScreenshot[0], encoded->size());
if (!slot)
slot = mCharacterManager.getCurrentCharacter()->createSlot (profile);
else
slot = mCharacterManager.getCurrentCharacter()->updateSlot (slot, profile);
std::string classId = player.get<ESM::NPC>()->mBase->mClass;
if (world.getStore().get<ESM::Class>().isDynamic(classId))
profile.mPlayerClassName = world.getStore().get<ESM::Class>().find(classId)->mName;
else
profile.mPlayerClassId = classId;
profile.mPlayerCell = world.getCellName();
profile.mInGameTime.mGameHour = world.getTimeStamp().getHour();
profile.mInGameTime.mDay = world.getDay();
profile.mInGameTime.mMonth = world.getMonth();
profile.mInGameTime.mYear = world.getYear();
profile.mTimePlayed = mTimePlayed;
profile.mDescription = description;
int screenshotW = 259*2, screenshotH = 133*2; // *2 to get some nice antialiasing
Ogre::Image screenshot;
world.screenshot(screenshot, screenshotW, screenshotH);
Ogre::DataStreamPtr encoded = screenshot.encode("jpg");
profile.mScreenshot.resize(encoded->size());
encoded->read(&profile.mScreenshot[0], encoded->size());
if (!slot)
slot = mCharacterManager.getCurrentCharacter()->createSlot (profile);
else
slot = mCharacterManager.getCurrentCharacter()->updateSlot (slot, profile);
boost::filesystem::ofstream stream (slot->mPath, std::ios::binary);
boost::filesystem::ofstream stream (slot->mPath, std::ios::binary);
ESM::ESMWriter writer;
ESM::ESMWriter writer;
const std::vector<std::string>& current =
MWBase::Environment::get().getWorld()->getContentFiles();
const std::vector<std::string>& current =
MWBase::Environment::get().getWorld()->getContentFiles();
for (std::vector<std::string>::const_iterator iter (current.begin()); iter!=current.end();
++iter)
writer.addMaster (*iter, 0); // not using the size information anyway -> use value of 0
writer.setFormat (ESM::Header::CurrentFormat);
int recordCount = 1 // saved game header
+MWBase::Environment::get().getJournal()->countSavedGameRecords()
+MWBase::Environment::get().getWorld()->countSavedGameRecords()
+MWBase::Environment::get().getScriptManager()->getGlobalScripts().countSavedGameRecords()
+MWBase::Environment::get().getDialogueManager()->countSavedGameRecords()
+MWBase::Environment::get().getWindowManager()->countSavedGameRecords();
writer.setRecordCount (recordCount);
for (std::vector<std::string>::const_iterator iter (current.begin()); iter!=current.end();
++iter)
writer.addMaster (*iter, 0); // not using the size information anyway -> use value of 0
writer.save (stream);
writer.setFormat (ESM::Header::CurrentFormat);
int recordCount = 1 // saved game header
+MWBase::Environment::get().getJournal()->countSavedGameRecords()
+MWBase::Environment::get().getWorld()->countSavedGameRecords()
+MWBase::Environment::get().getScriptManager()->getGlobalScripts().countSavedGameRecords()
+MWBase::Environment::get().getDialogueManager()->countSavedGameRecords()
+MWBase::Environment::get().getWindowManager()->countSavedGameRecords();
writer.setRecordCount (recordCount);
Loading::Listener& listener = *MWBase::Environment::get().getWindowManager()->getLoadingScreen();
listener.setProgressRange(recordCount);
listener.setLabel("#{sNotifyMessage4}");
writer.save (stream);
Loading::ScopedLoad load(&listener);
Loading::Listener& listener = *MWBase::Environment::get().getWindowManager()->getLoadingScreen();
listener.setProgressRange(recordCount);
listener.setLabel("#{sNotifyMessage4}");
writer.startRecord (ESM::REC_SAVE);
slot->mProfile.save (writer);
writer.endRecord (ESM::REC_SAVE);
listener.increaseProgress();
Loading::ScopedLoad load(&listener);
MWBase::Environment::get().getJournal()->write (writer, listener);
MWBase::Environment::get().getDialogueManager()->write (writer, listener);
MWBase::Environment::get().getWorld()->write (writer, listener);
MWBase::Environment::get().getScriptManager()->getGlobalScripts().write (writer, listener);
MWBase::Environment::get().getWindowManager()->write(writer, listener);
writer.startRecord (ESM::REC_SAVE);
slot->mProfile.save (writer);
writer.endRecord (ESM::REC_SAVE);
listener.increaseProgress();
// Ensure we have written the number of records that was estimated
if (writer.getRecordCount() != recordCount+1) // 1 extra for TES3 record
std::cerr << "Warning: number of written savegame records does not match. Estimated: " << recordCount+1 << ", written: " << writer.getRecordCount() << std::endl;
MWBase::Environment::get().getJournal()->write (writer, listener);
MWBase::Environment::get().getDialogueManager()->write (writer, listener);
MWBase::Environment::get().getWorld()->write (writer, listener);
MWBase::Environment::get().getScriptManager()->getGlobalScripts().write (writer, listener);
MWBase::Environment::get().getWindowManager()->write(writer, listener);
writer.close();
// Ensure we have written the number of records that was estimated
if (writer.getRecordCount() != recordCount+1) // 1 extra for TES3 record
std::cerr << "Warning: number of written savegame records does not match. Estimated: " << recordCount+1 << ", written: " << writer.getRecordCount() << std::endl;
Settings::Manager::setString ("character", "Saves",
slot->mPath.parent_path().filename().string());
}
catch (const std::exception& e)
{
std::stringstream error;
error << "Failed to save game: " << e.what();
writer.close();
std::cerr << error.str() << std::endl;
Settings::Manager::setString ("character", "Saves",
slot->mPath.parent_path().filename().string());
std::vector<std::string> buttons;
buttons.push_back("#{sOk}");
MWBase::Environment::get().getWindowManager()->messageBox(error.str(), buttons);
}
}
void MWState::StateManager::quickSave (std::string name)
@ -371,10 +385,17 @@ void MWState::StateManager::loadGame (const Character *character, const Slot *sl
}
catch (const std::exception& e)
{
std::cerr << "failed to load saved game: " << e.what() << std::endl;
std::stringstream error;
error << "Failed to load saved game: " << e.what();
std::cerr << error.str() << std::endl;
cleanup (true);
MWBase::Environment::get().getWindowManager()->pushGuiMode (MWGui::GM_MainMenu);
std::vector<std::string> buttons;
buttons.push_back("#{sOk}");
MWBase::Environment::get().getWindowManager()->messageBox(error.str(), buttons);
}
}

Loading…
Cancel
Save