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