diff --git a/lib/json/JsonUtils.cpp b/lib/json/JsonUtils.cpp index f1680e11f..2e0fdd829 100644 --- a/lib/json/JsonUtils.cpp +++ b/lib/json/JsonUtils.cpp @@ -275,4 +275,32 @@ JsonNode JsonUtils::assembleFromFiles(const std::string & filename) return result; } +void JsonUtils::detectConflicts(const JsonNode & left, const JsonNode & right, const std::string & entityName, const std::string & keyName) +{ + if (left == right) + return; + + switch (left.getType()) + { + case JsonNode::JsonType::DATA_NULL: + case JsonNode::JsonType::DATA_BOOL: + case JsonNode::JsonType::DATA_FLOAT: + case JsonNode::JsonType::DATA_INTEGER: + case JsonNode::JsonType::DATA_STRING: + case JsonNode::JsonType::DATA_VECTOR: // NOTE: comparing vectors as whole - since merge will overwrite it in its entirety + { + logMod->warn("Potential confict detected between '%s' and '%s' in object '%s'", left.getModScope(), right.getModScope(), entityName); + logMod->warn("Mod '%s' - value %s set to '%s'", left.getModScope(), keyName, left.toCompactString()); + logMod->warn("Mod '%s' - value %s set to '%s'", right.getModScope(), keyName, right.toCompactString()); + return; + } + case JsonNode::JsonType::DATA_STRUCT: + { + for(auto & node : left.Struct()) + if (!right[node.first].isNull()) + detectConflicts(node.second, right[node.first], entityName, keyName + "/" + node.first); + } + } +} + VCMI_LIB_NAMESPACE_END diff --git a/lib/json/JsonUtils.h b/lib/json/JsonUtils.h index 954ee0b16..bf14ce2d6 100644 --- a/lib/json/JsonUtils.h +++ b/lib/json/JsonUtils.h @@ -72,6 +72,10 @@ namespace JsonUtils /// get schema by json URI: vcmi:# /// example: schema "vcmi:settings" is used to check user settings DLL_LINKAGE const JsonNode & getSchema(const std::string & URI); + + /// detects potential conflicts - json entries present in both nodes + /// any error messages will be printed to error log + DLL_LINKAGE void detectConflicts(const JsonNode & left, const JsonNode & right, const std::string & entityName, const std::string & keyName); } VCMI_LIB_NAMESPACE_END diff --git a/lib/modding/ContentTypeHandler.cpp b/lib/modding/ContentTypeHandler.cpp index 83ae46c1b..43ece3409 100644 --- a/lib/modding/ContentTypeHandler.cpp +++ b/lib/modding/ContentTypeHandler.cpp @@ -79,6 +79,9 @@ bool ContentTypeHandler::preloadModData(const std::string & modName, const std:: logMod->trace("Patching object %s (%s) from %s", objectName, remoteName, modName); JsonNode & remoteConf = modData[remoteName].patches[objectName]; + if (!remoteConf.isNull()) + JsonUtils::detectConflicts(remoteConf, entry.second, objectName, ""); + JsonUtils::merge(remoteConf, entry.second); } }