ソースを参照

Provide more information in thrown exceptions for unfixed crashes

Ivan Savenko 1 年間 前
コミット
5454d01316

+ 2 - 2
lib/mapObjectConstructors/CObjectClassesHandler.cpp

@@ -351,12 +351,12 @@ TObjectTypeHandler CObjectClassesHandler::getHandlerFor(MapObjectID type, MapObj
 	}
 	catch (std::out_of_range & e)
 	{
-		// Leave catch block silently
+		// Leave catch block silently and handle error in block outside of try ... catch - all valid values should use 'return' in try block
 	}
 
 	std::string errorString = "Failed to find object of type " + std::to_string(type.getNum()) + "::" + std::to_string(subtype.getNum());
 	logGlobal->error(errorString);
-	throw std::runtime_error(errorString);
+	throw std::out_of_range(errorString);
 }
 
 TObjectTypeHandler CObjectClassesHandler::getHandlerFor(const std::string & scope, const std::string & type, const std::string & subtype) const

+ 13 - 0
lib/mapObjects/CGCreature.cpp

@@ -16,6 +16,7 @@
 #include "../CConfigHandler.h"
 #include "../GameSettings.h"
 #include "../IGameCallback.h"
+#include "../mapObjectConstructors/CObjectClassesHandler.h"
 #include "../networkPacks/PacksForClient.h"
 #include "../networkPacks/PacksForClientBattle.h"
 #include "../networkPacks/StackLocation.h"
@@ -217,6 +218,18 @@ void CGCreature::pickRandomObject(CRandomGenerator & rand)
 			subID = VLC->creh->pickRandomMonster(rand, 7);
 			break;
 	}
+
+	try {
+		// sanity check
+		VLC->objtypeh->getHandlerFor(ID, subID);
+	}
+	catch (const std::out_of_range & )
+	{
+		// Try to generate some debug information if sanity check failed
+		CreatureID creatureID(subID.getNum());
+		throw std::out_of_range("Failed to find handler for creature " + std::to_string(creatureID.getNum()) + ", identifer:" + creatureID.toEntity(VLC)->getJsonKey());
+	}
+
 	ID = MapObjectID::MONSTER;
 	setType(ID, subID);
 }

+ 1 - 5
lib/mapObjects/CGObjectInstance.cpp

@@ -133,11 +133,7 @@ void CGObjectInstance::setType(MapObjectID newID, MapObjectSubID newSubID)
 	//recalculate blockvis tiles - new appearance might have different blockmap than before
 	cb->gameState()->map->removeBlockVisTiles(this, true);
 	auto handler = VLC->objtypeh->getHandlerFor(newID, newSubID);
-	if(!handler)
-	{
-		logGlobal->error("Unknown object type %d:%d at %s", newID, newSubID, visitablePos().toString());
-		return;
-	}
+
 	if(!handler->getTemplates(tile.terType->getId()).empty())
 	{
 		appearance = handler->getTemplates(tile.terType->getId())[0];

+ 1 - 1
lib/mapObjects/MiscObjects.cpp

@@ -1257,7 +1257,7 @@ void CGObelisk::setPropertyDer(ObjProperty what, ObjPropertyID identifier)
 				if(progress > cb->gameState()->map->obeliskCount)
 				{
 					logGlobal->error("Visited %d of %d", static_cast<int>(progress), cb->gameState()->map->obeliskCount);
-					throw std::runtime_error("Player visited more obelisks than present on map!");
+					throw std::runtime_error("Player visited " + std::to_string(progress) + " obelisks out of " + std::to_string(cb->gameState()->map->obeliskCount) + " present on map!");
 				}
 
 				break;