Browse Source

Merge pull request #5140 from IvanSavenko/crashfixes

Fixes for crashes discovered via Google Play
Ivan Savenko 10 months ago
parent
commit
ec25eb557b

+ 10 - 2
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();
 }

+ 3 - 2
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;
 		});
 		

+ 1 - 1
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

+ 10 - 4
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);

+ 11 - 2
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<TModID> & 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);
 }

+ 15 - 2
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);
 	}