diff --git a/launcher/mainwindow_moc.cpp b/launcher/mainwindow_moc.cpp index 01d483176..e7adb1b10 100644 --- a/launcher/mainwindow_moc.cpp +++ b/launcher/mainwindow_moc.cpp @@ -18,6 +18,7 @@ #include "../lib/filesystem/Filesystem.h" #include "../lib/logging/CBasicLogConfigurator.h" #include "../lib/texts/Languages.h" +#include "../lib/ExceptionsCommon.h" #include "updatedialog_moc.h" #include "main.h" @@ -35,8 +36,15 @@ void MainWindow::load() CBasicLogConfigurator logConfig(VCMIDirs::get().userLogsPath() / "VCMI_Launcher_log.txt", console); logConfig.configureDefault(); - CResourceHandler::initialize(); - CResourceHandler::load("config/filesystem.json"); + try + { + CResourceHandler::initialize(); + CResourceHandler::load("config/filesystem.json"); + } + catch (const DataLoadingException & e) + { + QMessageBox::critical(this, tr("Error starting executable"), QString::fromStdString(e.what())); + } Helper::loadSettings(); } diff --git a/launcher/modManager/cmodlistview_moc.cpp b/launcher/modManager/cmodlistview_moc.cpp index a010ef6fa..fe8b1eaef 100644 --- a/launcher/modManager/cmodlistview_moc.cpp +++ b/launcher/modManager/cmodlistview_moc.cpp @@ -561,7 +561,7 @@ QStringList CModListView::getModsToInstall(QString mod) potentialToInstall = modStateModel->getTopParent(potentialToInstall); } - if (modStateModel->isModExists(potentialToInstall) && !modStateModel->isModInstalled(potentialToInstall)) + if (!modStateModel->isModInstalled(potentialToInstall)) result.push_back(potentialToInstall); if (modStateModel->isModExists(potentialToInstall)) @@ -818,7 +818,8 @@ void CModListView::installFiles(QStringList files) ChroniclesExtractor ce(this, [&prog](float progress) { prog = progress; }); ce.installChronicles(exe); reload(); - enableModByName("chronicles"); + if (modStateModel->isModExists("chronicles")) + enableModByName("chronicles"); return true; }); diff --git a/launcher/modManager/modstatemodel.cpp b/launcher/modManager/modstatemodel.cpp index ebbfbae6c..392fbd2fc 100644 --- a/launcher/modManager/modstatemodel.cpp +++ b/launcher/modManager/modstatemodel.cpp @@ -65,7 +65,7 @@ bool ModStateModel::isModExists(QString modName) const bool ModStateModel::isModInstalled(QString modName) const { - return getMod(modName).isInstalled(); + return isModExists(modName) && getMod(modName).isInstalled(); } bool ModStateModel::isModSettingEnabled(QString rootModName, QString modSettingName) const diff --git a/lib/mapObjects/CQuest.cpp b/lib/mapObjects/CQuest.cpp index 9e2e83c47..7bb3302f1 100644 --- a/lib/mapObjects/CQuest.cpp +++ b/lib/mapObjects/CQuest.cpp @@ -149,12 +149,14 @@ void CQuest::completeQuest(IGameCallback * cb, const CGHeroInstance *h) const if(h->hasArt(elem)) { cb->removeArtifact(ArtifactLocation(h->id, h->getArtPos(elem, false))); + continue; } - else + + // perhaps artifact is part of a combined artifact? + const auto * assembly = h->getCombinedArtWithPart(elem); + if (assembly) { - const auto * assembly = h->getCombinedArtWithPart(elem); - assert(assembly); - auto parts = assembly->getPartsInfo(); + auto parts = assembly->getPartsInfo(); // FIXME: causes crashes on Google Play // Remove the assembly cb->removeArtifact(ArtifactLocation(h->id, h->getArtPos(assembly))); @@ -165,7 +167,11 @@ void CQuest::completeQuest(IGameCallback * cb, const CGHeroInstance *h) const if(ci.art->getTypeId() != elem) cb->giveHeroNewArtifact(h, ci.art->getTypeId(), ArtifactPosition::BACKPACK_START); } + + continue; } + + logGlobal->error("Failed to find artifact %s in inventory of hero %s", elem.toEntity(VLC)->getJsonKey(), h->getHeroTypeID()); } cb->takeCreatures(h->id, mission.creatures); diff --git a/lib/modding/ModManager.cpp b/lib/modding/ModManager.cpp index 877518c9b..2566b6862 100644 --- a/lib/modding/ModManager.cpp +++ b/lib/modding/ModManager.cpp @@ -175,6 +175,8 @@ ModsPresetState::ModsPresetState() auto allPresets = getAllPresets(); if (!vstd::contains(allPresets, modConfig["activePreset"].String())) modConfig["activePreset"] = JsonNode(allPresets.front()); + + logGlobal->debug("Loading following mod settings: %s", modConfig.toCompactString()); } void ModsPresetState::createInitialPreset() @@ -454,7 +456,14 @@ ModsStorage::ModsStorage(const std::vector & modsToLoad, const JsonNode const ModDescription & ModsStorage::getMod(const TModID & fullID) const { - return mods.at(fullID); + try { + return mods.at(fullID); + } + catch (const std::out_of_range & ) + { + // rethrow with better error message + throw std::out_of_range("Failed to find mod " + fullID); + } } TModList ModsStorage::getAllMods() const @@ -651,7 +660,7 @@ void ModManager::tryEnableMods(const TModList & modList) for (const auto & modName : modList) if (!vstd::contains(testResolver.getActiveMods(), modName)) - throw std::runtime_error("Failed to enable mod! Mod " + modName + " remains disabled!"); + logGlobal->error("Failed to enable mod '%s'! This may be caused by a recursive dependency!", modName); updatePreset(testResolver); } diff --git a/server/NetPacksLobbyServer.cpp b/server/NetPacksLobbyServer.cpp index 1b45736fb..33cc714ff 100644 --- a/server/NetPacksLobbyServer.cpp +++ b/server/NetPacksLobbyServer.cpp @@ -445,7 +445,14 @@ void ApplyOnServerNetPackVisitor::visitLobbyDelete(LobbyDelete & pack) if(pack.type == LobbyDelete::EType::SAVEGAME || pack.type == LobbyDelete::EType::RANDOMMAP) { auto res = ResourcePath(pack.name, pack.type == LobbyDelete::EType::SAVEGAME ? EResType::SAVEGAME : EResType::MAP); - auto file = boost::filesystem::canonical(*CResourceHandler::get()->getResourceName(res)); + auto name = CResourceHandler::get()->getResourceName(res); + if (!name) + { + logGlobal->error("Failed to find resource with name '%s'", res.getOriginalName()); + return; + } + + auto file = boost::filesystem::canonical(*name); boost::filesystem::remove(file); if(boost::filesystem::is_empty(file.parent_path())) boost::filesystem::remove(file.parent_path()); @@ -453,7 +460,13 @@ void ApplyOnServerNetPackVisitor::visitLobbyDelete(LobbyDelete & pack) else if(pack.type == LobbyDelete::EType::SAVEGAME_FOLDER) { auto res = ResourcePath("Saves/" + pack.name, EResType::DIRECTORY); - auto folder = boost::filesystem::canonical(*CResourceHandler::get()->getResourceName(res)); + auto name = CResourceHandler::get()->getResourceName(res); + if (!name) + { + logGlobal->error("Failed to find folder with name '%s'", res.getOriginalName()); + return; + } + auto folder = boost::filesystem::canonical(*name); boost::filesystem::remove_all(folder); }