Browse Source

Add debug information for crash on object randomization

Ivan Savenko 9 months ago
parent
commit
ca4227ba9d

+ 19 - 1
lib/json/JsonRandom.cpp

@@ -35,6 +35,21 @@
 
 VCMI_LIB_NAMESPACE_BEGIN
 
+std::string JsonRandomizationException::cleanupJson(const JsonNode & value)
+{
+	std::string result = value.toCompactString();
+	for (size_t i = 0; i < result.size(); ++i)
+		if (result[i] == '\n')
+			result[i] = ' ';
+
+	return result;
+}
+
+JsonRandomizationException::JsonRandomizationException(const std::string & message, const JsonNode & input)
+	: std::runtime_error(message + " Input was: " + cleanupJson(input))
+{}
+
+
 	si32 JsonRandom::loadVariable(const std::string & variableGroup, const std::string & value, const Variables & variables, si32 defaultValue)
 	{
 		if (value.empty() || value[0] != '@')
@@ -483,7 +498,10 @@ VCMI_LIB_NAMESPACE_BEGIN
 		if (!potentialPicks.empty())
 			pickedCreature = *RandomGeneratorUtil::nextItem(potentialPicks, rng);
 		else
-			logMod->warn("Failed to select suitable random creature!");
+			throw JsonRandomizationException("No potential creatures to pick!", value);
+
+		if (!pickedCreature.hasValue())
+			throw JsonRandomizationException("Invalid creature picked!", value);
 
 		stack.setType(pickedCreature.toCreature());
 		stack.count = loadValue(value, rng, variables);

+ 7 - 0
lib/json/JsonRandom.h

@@ -27,6 +27,13 @@ struct Bonus;
 struct Component;
 class CStackBasicDescriptor;
 
+class JsonRandomizationException : public std::runtime_error
+{
+	std::string cleanupJson(const JsonNode & value);
+public:
+	JsonRandomizationException(const std::string & message, const JsonNode & input);
+};
+
 class JsonRandom : public GameCallbackHolder
 {
 public:

+ 9 - 1
lib/mapObjectConstructors/CRewardableConstructor.cpp

@@ -11,6 +11,7 @@
 #include "CRewardableConstructor.h"
 
 #include "../json/JsonUtils.h"
+#include "../json/JsonRandom.h"
 #include "../mapObjects/CRewardableObject.h"
 #include "../texts/CGeneralTextHandler.h"
 #include "../IGameCallback.h"
@@ -49,7 +50,14 @@ Rewardable::Configuration CRewardableConstructor::generateConfiguration(IGameCal
 {
 	Rewardable::Configuration result;
 	result.variables.preset = presetVariables;
-	objectInfo.configureObject(result, rand, cb);
+
+	try {
+		objectInfo.configureObject(result, rand, cb);
+	}
+	catch (const JsonRandomizationException & e)
+	{
+		throw std::runtime_error("Failed to generate configuration for object '" + getJsonKey() + "'! Reason: " + e.what());
+	}
 
 	for(auto & rewardInfo : result.info)
 	{