mirror of
				https://github.com/vcmi/vcmi.git
				synced 2025-10-31 00:07:39 +02:00 
			
		
		
		
	- fixed handling of incorrect configuration in settings.json
- more compact schema for siege node
This commit is contained in:
		| @@ -1,347 +1,130 @@ | ||||
| { | ||||
| 	"type":"object", | ||||
| 	"$schema": "http://json-schema.org/draft-04/schema", | ||||
| 	"title" : "VCMI town building format", | ||||
| 	"description" : "Format used to define town buildings in VCMI", | ||||
| 	"id": "#", | ||||
| 	"title" : "VCMI siege screen format", | ||||
| 	"description" : "Format used to define town siege screen in VCMI", | ||||
| 	"required" : [ | ||||
| 		"gate", "imagePrefix", "moat", "shooterHeight", "shooter", | ||||
| 		"static", "towers", "walls" | ||||
| 	 ], | ||||
| 	 | ||||
| 	"definitions" : | ||||
| 	{ | ||||
| 		"point" : { | ||||
| 			"type" : "object", | ||||
| 			"required" : [ "x", "y" ], | ||||
| 			"properties":{ | ||||
| 				"x": { "type":"number" }, | ||||
| 				"y": { "type":"number" } | ||||
| 			} | ||||
| 		}, | ||||
| 		"tower" : { | ||||
| 			"type" : "object", | ||||
| 			"required" : [ "battlement", "creature", "tower" ], | ||||
| 			"properties":{ | ||||
| 				"battlement": { | ||||
| 					"description" : "Location of battlement, part of tower that covers shooter", | ||||
| 					"$ref" : "#/definitions/point" | ||||
| 				}, | ||||
| 				"creature": { | ||||
| 					"description" : "Location of shooter in tower", | ||||
| 					"$ref" : "#/definitions/point" | ||||
| 				}, | ||||
| 				"tower": { | ||||
| 					"description" : "Location of main segment of tower", | ||||
| 					"$ref" : "#/definitions/point" | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 	}, | ||||
|  | ||||
| 	"properties":{ | ||||
| 		"gate": { | ||||
| 			"type":"object", | ||||
| 			"id": "gate", | ||||
| 			"description" : "Town gates", | ||||
| 			"properties":{ | ||||
| 				"arch": { | ||||
| 					"type":"object", | ||||
| 					"id": "arch", | ||||
| 					"properties":{ | ||||
| 						"x": { | ||||
| 							"type":"number", | ||||
| 							"id": "x" | ||||
| 						}, | ||||
| 						"y": { | ||||
| 							"type":"number", | ||||
| 							"id": "y" | ||||
| 						} | ||||
| 					} | ||||
| 					"description" : "Static, top part of gates", | ||||
| 					"$ref" : "#/definitions/point" | ||||
| 				}, | ||||
| 				"gate": { | ||||
| 					"type":"object", | ||||
| 					"id": "gate", | ||||
| 					"properties":{ | ||||
| 						"x": { | ||||
| 							"type":"number", | ||||
| 							"id": "x" | ||||
| 						}, | ||||
| 						"y": { | ||||
| 							"type":"number", | ||||
| 							"id": "y" | ||||
| 						} | ||||
| 					} | ||||
| 					"description" : "Main section of gates", | ||||
| 					"$ref" : "#/definitions/point" | ||||
| 				} | ||||
| 			} | ||||
| 		}, | ||||
| 		"imagePrefix": { | ||||
| 			"type":"string", | ||||
| 			"id": "imagePrefix" | ||||
| 			"description" : "Prefix to all images related to siege screen" | ||||
| 		}, | ||||
| 		"moat": { | ||||
| 			"type":"object", | ||||
| 			"id": "moat", | ||||
| 			"description" : "Castle moat description", | ||||
| 			"properties":{ | ||||
| 				"bank": { | ||||
| 					"type":"object", | ||||
| 					"id": "bank", | ||||
| 					"properties":{ | ||||
| 						"x": { | ||||
| 							"type":"number", | ||||
| 							"id": "x" | ||||
| 						}, | ||||
| 						"y": { | ||||
| 							"type":"number", | ||||
| 							"id": "y" | ||||
| 						} | ||||
| 					} | ||||
| 					"description" : "Small section with bank of the moat", | ||||
| 					"$ref" : "#/definitions/point" | ||||
| 				}, | ||||
| 				"moat": { | ||||
| 					"type":"object", | ||||
| 					"id": "moat", | ||||
| 					"properties":{ | ||||
| 						"x": { | ||||
| 							"type":"number", | ||||
| 							"id": "x" | ||||
| 						}, | ||||
| 						"y": { | ||||
| 							"type":"number", | ||||
| 							"id": "y" | ||||
| 						} | ||||
| 					} | ||||
| 					"description" : "Main section of the moat", | ||||
| 					"$ref" : "#/definitions/point" | ||||
| 				} | ||||
| 			} | ||||
| 		}, | ||||
| 		"shooterHeight": { | ||||
| 			"type":"number", | ||||
| 			"id": "shooterHeight" | ||||
| 			"description" : "Height at which shooter image will be cropped" | ||||
| 		}, | ||||
| 		"shooter": { | ||||
| 			"type":"string", | ||||
| 			"id": "shooter" | ||||
| 			"description" : "Identifier of creature that will be used as tower shooter" | ||||
| 		}, | ||||
| 		"static": { | ||||
| 			"type":"object", | ||||
| 			"id": "static", | ||||
| 			"description" : "Static sections of walls", | ||||
| 			"properties":{ | ||||
| 				"background": { | ||||
| 					"type":"object", | ||||
| 					"id": "background", | ||||
| 					"properties":{ | ||||
| 						"x": { | ||||
| 							"type":"number", | ||||
| 							"id": "x" | ||||
| 						}, | ||||
| 						"y": { | ||||
| 							"type":"number", | ||||
| 							"id": "y" | ||||
| 						} | ||||
| 					} | ||||
| 					"description" : "Very top section of the wall located above hero", | ||||
| 					"$ref" : "#/definitions/point" | ||||
| 				}, | ||||
| 				"bottom": { | ||||
| 					"type":"object", | ||||
| 					"id": "bottom", | ||||
| 					"properties":{ | ||||
| 						"x": { | ||||
| 							"type":"number", | ||||
| 							"id": "x" | ||||
| 						}, | ||||
| 						"y": { | ||||
| 							"type":"number", | ||||
| 							"id": "y" | ||||
| 						} | ||||
| 					} | ||||
| 					"description" : "Bottom section located between destructible sections", | ||||
| 					"$ref" : "#/definitions/point" | ||||
| 				}, | ||||
| 				"top": { | ||||
| 					"type":"object", | ||||
| 					"id": "top", | ||||
| 					"properties":{ | ||||
| 						"x": { | ||||
| 							"type":"number", | ||||
| 							"id": "x" | ||||
| 						}, | ||||
| 						"y": { | ||||
| 							"type":"number", | ||||
| 							"id": "y" | ||||
| 						} | ||||
| 					} | ||||
| 					"description" : "Top section located between destructible sections", | ||||
| 					"$ref" : "#/definitions/point" | ||||
| 				} | ||||
| 			} | ||||
| 		}, | ||||
| 		"towers": { | ||||
| 			"type":"object", | ||||
| 			"id": "towers", | ||||
| 			"description" : "Decription of towers", | ||||
| 			"properties":{ | ||||
| 				"bottom": { | ||||
| 					"type":"object", | ||||
| 					"id": "bottom", | ||||
| 					"properties":{ | ||||
| 						"battlement": { | ||||
| 							"type":"object", | ||||
| 							"id": "battlement", | ||||
| 							"properties":{ | ||||
| 								"x": { | ||||
| 									"type":"number", | ||||
| 									"id": "x" | ||||
| 								}, | ||||
| 								"y": { | ||||
| 									"type":"number", | ||||
| 									"id": "y" | ||||
| 								} | ||||
| 							} | ||||
| 						}, | ||||
| 						"creature": { | ||||
| 							"type":"object", | ||||
| 							"id": "creature", | ||||
| 							"properties":{ | ||||
| 								"x": { | ||||
| 									"type":"number", | ||||
| 									"id": "x" | ||||
| 								}, | ||||
| 								"y": { | ||||
| 									"type":"number", | ||||
| 									"id": "y" | ||||
| 								} | ||||
| 							} | ||||
| 						}, | ||||
| 						"tower": { | ||||
| 							"type":"object", | ||||
| 							"id": "tower", | ||||
| 							"properties":{ | ||||
| 								"x": { | ||||
| 									"type":"number", | ||||
| 									"id": "x" | ||||
| 								}, | ||||
| 								"y": { | ||||
| 									"type":"number", | ||||
| 									"id": "y" | ||||
| 								} | ||||
| 							} | ||||
| 						} | ||||
| 					} | ||||
| 				}, | ||||
| 				"keep": { | ||||
| 					"type":"object", | ||||
| 					"id": "keep", | ||||
| 					"properties":{ | ||||
| 						"battlement": { | ||||
| 							"type":"object", | ||||
| 							"id": "battlement", | ||||
| 							"properties":{ | ||||
| 								"x": { | ||||
| 									"type":"number", | ||||
| 									"id": "x" | ||||
| 								}, | ||||
| 								"y": { | ||||
| 									"type":"number", | ||||
| 									"id": "y" | ||||
| 								} | ||||
| 							} | ||||
| 						}, | ||||
| 						"creature": { | ||||
| 							"type":"object", | ||||
| 							"id": "creature", | ||||
| 							"properties":{ | ||||
| 								"x": { | ||||
| 									"type":"number", | ||||
| 									"id": "x" | ||||
| 								}, | ||||
| 								"y": { | ||||
| 									"type":"number", | ||||
| 									"id": "y" | ||||
| 								} | ||||
| 							} | ||||
| 						}, | ||||
| 						"tower": { | ||||
| 							"type":"object", | ||||
| 							"id": "tower", | ||||
| 							"properties":{ | ||||
| 								"x": { | ||||
| 									"type":"number", | ||||
| 									"id": "x" | ||||
| 								}, | ||||
| 								"y": { | ||||
| 									"type":"number", | ||||
| 									"id": "y" | ||||
| 								} | ||||
| 							} | ||||
| 						} | ||||
| 					} | ||||
| 				}, | ||||
| 				"top": { | ||||
| 					"type":"object", | ||||
| 					"id": "top", | ||||
| 					"properties":{ | ||||
| 						"battlement": { | ||||
| 							"type":"object", | ||||
| 							"id": "battlement", | ||||
| 							"properties":{ | ||||
| 								"x": { | ||||
| 									"type":"number", | ||||
| 									"id": "x" | ||||
| 								}, | ||||
| 								"y": { | ||||
| 									"type":"number", | ||||
| 									"id": "y" | ||||
| 								} | ||||
| 							} | ||||
| 						}, | ||||
| 						"creature": { | ||||
| 							"type":"object", | ||||
| 							"id": "creature", | ||||
| 							"properties":{ | ||||
| 								"x": { | ||||
| 									"type":"number", | ||||
| 									"id": "x" | ||||
| 								}, | ||||
| 								"y": { | ||||
| 									"type":"number", | ||||
| 									"id": "y" | ||||
| 								} | ||||
| 							} | ||||
| 						}, | ||||
| 						"tower": { | ||||
| 							"type":"object", | ||||
| 							"id": "tower", | ||||
| 							"properties":{ | ||||
| 								"x": { | ||||
| 									"type":"number", | ||||
| 									"id": "x" | ||||
| 								}, | ||||
| 								"y": { | ||||
| 									"type":"number", | ||||
| 									"id": "y" | ||||
| 								} | ||||
| 							} | ||||
| 						} | ||||
| 					} | ||||
| 				} | ||||
| 				"bottom": { "$ref" : "#/definitions/tower", "description" : "Bottom tower" }, | ||||
| 				"keep":   { "$ref" : "#/definitions/tower", "description" : "Central keep" }, | ||||
| 				"top":    { "$ref" : "#/definitions/tower", "description" : "Top tower" } | ||||
| 			} | ||||
| 		}, | ||||
| 		"walls": { | ||||
| 			"type":"object", | ||||
| 			"id": "walls", | ||||
| 			"description" : "Destructible sections of the walls", | ||||
| 			"properties":{ | ||||
| 				"bottomMid": { | ||||
| 					"type":"object", | ||||
| 					"id": "bottomMid", | ||||
| 					"properties":{ | ||||
| 						"x": { | ||||
| 							"type":"number", | ||||
| 							"id": "x" | ||||
| 						}, | ||||
| 						"y": { | ||||
| 							"type":"number", | ||||
| 							"id": "y" | ||||
| 						} | ||||
| 					} | ||||
| 					"description" : "Second from bottom section located near gates", | ||||
| 					"$ref" : "#/definitions/point" | ||||
| 				}, | ||||
| 				"bottom": { | ||||
| 					"type":"object", | ||||
| 					"id": "bottom", | ||||
| 					"properties":{ | ||||
| 						"x": { | ||||
| 							"type":"number", | ||||
| 							"id": "x" | ||||
| 						}, | ||||
| 						"y": { | ||||
| 							"type":"number", | ||||
| 							"id": "y" | ||||
| 						} | ||||
| 					} | ||||
| 					"description" : "Bottommost section located near bottom tower", | ||||
| 					"$ref" : "#/definitions/point" | ||||
| 				}, | ||||
| 				"upperMid": { | ||||
| 					"type":"object", | ||||
| 					"id": "upperMid", | ||||
| 					"properties":{ | ||||
| 						"x": { | ||||
| 							"type":"number", | ||||
| 							"id": "x" | ||||
| 						}, | ||||
| 						"y": { | ||||
| 							"type":"number", | ||||
| 							"id": "y" | ||||
| 						} | ||||
| 					} | ||||
| 					"description" : "Second from top section located near gates", | ||||
| 					"$ref" : "#/definitions/point" | ||||
| 				}, | ||||
| 				"upper": { | ||||
| 					"type":"object", | ||||
| 					"id": "upper", | ||||
| 					"properties":{ | ||||
| 						"x": { | ||||
| 							"type":"number", | ||||
| 							"id": "x" | ||||
| 						}, | ||||
| 						"y": { | ||||
| 							"type":"number", | ||||
| 							"id": "y" | ||||
| 						} | ||||
| 					} | ||||
| 					"description" : "Topmost section located near top tower", | ||||
| 					"$ref" : "#/definitions/point" | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
|   | ||||
| @@ -1367,19 +1367,31 @@ void JsonUtils::unparseBonus( JsonNode &node, const Bonus * bonus ) | ||||
|  | ||||
| void minimizeNode(JsonNode & node, const JsonNode & schema) | ||||
| { | ||||
| 	assert(schema["type"].String() == "object"); | ||||
|  | ||||
| 	BOOST_FOREACH(auto & entry, schema["required"].Vector()) | ||||
| 	if (schema["type"].String() == "object") | ||||
| 	{ | ||||
| 		std::string name = entry.String(); | ||||
| 		std::set<std::string> foundEntries; | ||||
|  | ||||
| 		BOOST_FOREACH(auto & entry, schema["required"].Vector()) | ||||
| 		{ | ||||
| 			std::string name = entry.String(); | ||||
| 			foundEntries.insert(name); | ||||
|  | ||||
| 		if (node[name].getType() == JsonNode::DATA_STRUCT) | ||||
| 			minimizeNode(node[name], schema["properties"][name]); | ||||
|  | ||||
| 		if (vstd::contains(node.Struct(), name) && | ||||
| 		    node[name] == schema["properties"][name]["default"]) | ||||
| 			if (vstd::contains(node.Struct(), name) && | ||||
| 				node[name] == schema["properties"][name]["default"]) | ||||
| 			{ | ||||
| 				node.Struct().erase(name); | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		// erase all unhandled entries | ||||
| 		for (auto it = node.Struct().begin(); it != node.Struct().end();) | ||||
| 		{ | ||||
| 			node.Struct().erase(name); | ||||
| 			if (!vstd::contains(foundEntries, it->first)) | ||||
| 				it = node.Struct().erase(it); | ||||
| 			else | ||||
| 				it++; | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| @@ -1389,21 +1401,36 @@ void JsonUtils::minimize(JsonNode & node, std::string schemaName) | ||||
| 	minimizeNode(node, getSchema(schemaName)); | ||||
| } | ||||
|  | ||||
| // FIXME: except for several lines function is identical to minimizeNode. Some way to reduce duplication? | ||||
| void maximizeNode(JsonNode & node, const JsonNode & schema) | ||||
| { | ||||
| 	assert(schema["type"].String() == "object"); | ||||
|  | ||||
| 	BOOST_FOREACH(auto & entry, schema["required"].Vector()) | ||||
| 	// "required" entry can only be found in object/struct | ||||
| 	if (schema["type"].String() == "object") | ||||
| 	{ | ||||
| 		std::string name = entry.String(); | ||||
| 		std::set<std::string> foundEntries; | ||||
|  | ||||
| 		if (node[name].isNull() && | ||||
| 		    !schema["properties"][name]["default"].isNull()) | ||||
| 		// check all required entries that have default version | ||||
| 		BOOST_FOREACH(auto & entry, schema["required"].Vector()) | ||||
| 		{ | ||||
| 			node[name] = schema["properties"][name]["default"]; | ||||
| 		} | ||||
| 		if (node[name].getType() == JsonNode::DATA_STRUCT) | ||||
| 			std::string name = entry.String(); | ||||
| 			foundEntries.insert(name); | ||||
|  | ||||
| 			if (node[name].isNull() && | ||||
| 				!schema["properties"][name]["default"].isNull()) | ||||
| 			{ | ||||
| 				node[name] = schema["properties"][name]["default"]; | ||||
| 			} | ||||
| 			maximizeNode(node[name], schema["properties"][name]); | ||||
| 		} | ||||
|  | ||||
| 		// erase all unhandled entries | ||||
| 		for (auto it = node.Struct().begin(); it != node.Struct().end();) | ||||
| 		{ | ||||
| 			if (!vstd::contains(foundEntries, it->first)) | ||||
| 				it = node.Struct().erase(it); | ||||
| 			else | ||||
| 				it++; | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @@ -1434,7 +1461,7 @@ const JsonNode & getSchemaByName(std::string name) | ||||
| 		return loadedSchemas[name]; | ||||
| 	} | ||||
|  | ||||
| 	tlog0 << "Error: missing schema with name " << name << "!\n"; | ||||
| 	tlog1 << "Error: missing schema with name " << name << "!\n"; | ||||
| 	assert(0); | ||||
| 	return nullNode; | ||||
| } | ||||
| @@ -1449,7 +1476,7 @@ const JsonNode & JsonUtils::getSchema(std::string URI) | ||||
|  | ||||
| 	if (segments[0] != "vcmi") | ||||
| 	{ | ||||
| 		tlog0 << "Error: unsupported URI protocol for schema: " << segments[0] << "\n"; | ||||
| 		tlog1 << "Error: unsupported URI protocol for schema: " << segments[0] << "\n"; | ||||
| 		return nullNode; | ||||
| 	} | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user