mirror of
https://github.com/vcmi/vcmi.git
synced 2024-12-26 22:57:00 +02:00
- fixed handling of incorrect configuration in settings.json
- more compact schema for siege node
This commit is contained in:
parent
0307639c32
commit
52e56693ea
@ -1,347 +1,130 @@
|
|||||||
{
|
{
|
||||||
"type":"object",
|
"type":"object",
|
||||||
"$schema": "http://json-schema.org/draft-04/schema",
|
"$schema": "http://json-schema.org/draft-04/schema",
|
||||||
"title" : "VCMI town building format",
|
"title" : "VCMI siege screen format",
|
||||||
"description" : "Format used to define town buildings in VCMI",
|
"description" : "Format used to define town siege screen in VCMI",
|
||||||
"id": "#",
|
"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":{
|
"properties":{
|
||||||
"gate": {
|
"gate": {
|
||||||
"type":"object",
|
"type":"object",
|
||||||
"id": "gate",
|
"description" : "Town gates",
|
||||||
"properties":{
|
"properties":{
|
||||||
"arch": {
|
"arch": {
|
||||||
"type":"object",
|
"description" : "Static, top part of gates",
|
||||||
"id": "arch",
|
"$ref" : "#/definitions/point"
|
||||||
"properties":{
|
|
||||||
"x": {
|
|
||||||
"type":"number",
|
|
||||||
"id": "x"
|
|
||||||
},
|
|
||||||
"y": {
|
|
||||||
"type":"number",
|
|
||||||
"id": "y"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
"gate": {
|
"gate": {
|
||||||
"type":"object",
|
"description" : "Main section of gates",
|
||||||
"id": "gate",
|
"$ref" : "#/definitions/point"
|
||||||
"properties":{
|
|
||||||
"x": {
|
|
||||||
"type":"number",
|
|
||||||
"id": "x"
|
|
||||||
},
|
|
||||||
"y": {
|
|
||||||
"type":"number",
|
|
||||||
"id": "y"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"imagePrefix": {
|
"imagePrefix": {
|
||||||
"type":"string",
|
"type":"string",
|
||||||
"id": "imagePrefix"
|
"description" : "Prefix to all images related to siege screen"
|
||||||
},
|
},
|
||||||
"moat": {
|
"moat": {
|
||||||
"type":"object",
|
"type":"object",
|
||||||
"id": "moat",
|
"description" : "Castle moat description",
|
||||||
"properties":{
|
"properties":{
|
||||||
"bank": {
|
"bank": {
|
||||||
"type":"object",
|
"description" : "Small section with bank of the moat",
|
||||||
"id": "bank",
|
"$ref" : "#/definitions/point"
|
||||||
"properties":{
|
|
||||||
"x": {
|
|
||||||
"type":"number",
|
|
||||||
"id": "x"
|
|
||||||
},
|
|
||||||
"y": {
|
|
||||||
"type":"number",
|
|
||||||
"id": "y"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
"moat": {
|
"moat": {
|
||||||
"type":"object",
|
"description" : "Main section of the moat",
|
||||||
"id": "moat",
|
"$ref" : "#/definitions/point"
|
||||||
"properties":{
|
|
||||||
"x": {
|
|
||||||
"type":"number",
|
|
||||||
"id": "x"
|
|
||||||
},
|
|
||||||
"y": {
|
|
||||||
"type":"number",
|
|
||||||
"id": "y"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"shooterHeight": {
|
"shooterHeight": {
|
||||||
"type":"number",
|
"type":"number",
|
||||||
"id": "shooterHeight"
|
"description" : "Height at which shooter image will be cropped"
|
||||||
},
|
},
|
||||||
"shooter": {
|
"shooter": {
|
||||||
"type":"string",
|
"type":"string",
|
||||||
"id": "shooter"
|
"description" : "Identifier of creature that will be used as tower shooter"
|
||||||
},
|
},
|
||||||
"static": {
|
"static": {
|
||||||
"type":"object",
|
"type":"object",
|
||||||
"id": "static",
|
"description" : "Static sections of walls",
|
||||||
"properties":{
|
"properties":{
|
||||||
"background": {
|
"background": {
|
||||||
"type":"object",
|
"description" : "Very top section of the wall located above hero",
|
||||||
"id": "background",
|
"$ref" : "#/definitions/point"
|
||||||
"properties":{
|
|
||||||
"x": {
|
|
||||||
"type":"number",
|
|
||||||
"id": "x"
|
|
||||||
},
|
|
||||||
"y": {
|
|
||||||
"type":"number",
|
|
||||||
"id": "y"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
"bottom": {
|
"bottom": {
|
||||||
"type":"object",
|
"description" : "Bottom section located between destructible sections",
|
||||||
"id": "bottom",
|
"$ref" : "#/definitions/point"
|
||||||
"properties":{
|
|
||||||
"x": {
|
|
||||||
"type":"number",
|
|
||||||
"id": "x"
|
|
||||||
},
|
|
||||||
"y": {
|
|
||||||
"type":"number",
|
|
||||||
"id": "y"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
"top": {
|
"top": {
|
||||||
"type":"object",
|
"description" : "Top section located between destructible sections",
|
||||||
"id": "top",
|
"$ref" : "#/definitions/point"
|
||||||
"properties":{
|
|
||||||
"x": {
|
|
||||||
"type":"number",
|
|
||||||
"id": "x"
|
|
||||||
},
|
|
||||||
"y": {
|
|
||||||
"type":"number",
|
|
||||||
"id": "y"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"towers": {
|
"towers": {
|
||||||
"type":"object",
|
"type":"object",
|
||||||
"id": "towers",
|
"description" : "Decription of towers",
|
||||||
"properties":{
|
"properties":{
|
||||||
"bottom": {
|
"bottom": { "$ref" : "#/definitions/tower", "description" : "Bottom tower" },
|
||||||
"type":"object",
|
"keep": { "$ref" : "#/definitions/tower", "description" : "Central keep" },
|
||||||
"id": "bottom",
|
"top": { "$ref" : "#/definitions/tower", "description" : "Top tower" }
|
||||||
"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"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"walls": {
|
"walls": {
|
||||||
"type":"object",
|
"type":"object",
|
||||||
"id": "walls",
|
"description" : "Destructible sections of the walls",
|
||||||
"properties":{
|
"properties":{
|
||||||
"bottomMid": {
|
"bottomMid": {
|
||||||
"type":"object",
|
"description" : "Second from bottom section located near gates",
|
||||||
"id": "bottomMid",
|
"$ref" : "#/definitions/point"
|
||||||
"properties":{
|
|
||||||
"x": {
|
|
||||||
"type":"number",
|
|
||||||
"id": "x"
|
|
||||||
},
|
|
||||||
"y": {
|
|
||||||
"type":"number",
|
|
||||||
"id": "y"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
"bottom": {
|
"bottom": {
|
||||||
"type":"object",
|
"description" : "Bottommost section located near bottom tower",
|
||||||
"id": "bottom",
|
"$ref" : "#/definitions/point"
|
||||||
"properties":{
|
|
||||||
"x": {
|
|
||||||
"type":"number",
|
|
||||||
"id": "x"
|
|
||||||
},
|
|
||||||
"y": {
|
|
||||||
"type":"number",
|
|
||||||
"id": "y"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
"upperMid": {
|
"upperMid": {
|
||||||
"type":"object",
|
"description" : "Second from top section located near gates",
|
||||||
"id": "upperMid",
|
"$ref" : "#/definitions/point"
|
||||||
"properties":{
|
|
||||||
"x": {
|
|
||||||
"type":"number",
|
|
||||||
"id": "x"
|
|
||||||
},
|
|
||||||
"y": {
|
|
||||||
"type":"number",
|
|
||||||
"id": "y"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
"upper": {
|
"upper": {
|
||||||
"type":"object",
|
"description" : "Topmost section located near top tower",
|
||||||
"id": "upper",
|
"$ref" : "#/definitions/point"
|
||||||
"properties":{
|
|
||||||
"x": {
|
|
||||||
"type":"number",
|
|
||||||
"id": "x"
|
|
||||||
},
|
|
||||||
"y": {
|
|
||||||
"type":"number",
|
|
||||||
"id": "y"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1367,13 +1367,15 @@ void JsonUtils::unparseBonus( JsonNode &node, const Bonus * bonus )
|
|||||||
|
|
||||||
void minimizeNode(JsonNode & node, const JsonNode & schema)
|
void minimizeNode(JsonNode & node, const JsonNode & schema)
|
||||||
{
|
{
|
||||||
assert(schema["type"].String() == "object");
|
if (schema["type"].String() == "object")
|
||||||
|
{
|
||||||
|
std::set<std::string> foundEntries;
|
||||||
|
|
||||||
BOOST_FOREACH(auto & entry, schema["required"].Vector())
|
BOOST_FOREACH(auto & entry, schema["required"].Vector())
|
||||||
{
|
{
|
||||||
std::string name = entry.String();
|
std::string name = entry.String();
|
||||||
|
foundEntries.insert(name);
|
||||||
|
|
||||||
if (node[name].getType() == JsonNode::DATA_STRUCT)
|
|
||||||
minimizeNode(node[name], schema["properties"][name]);
|
minimizeNode(node[name], schema["properties"][name]);
|
||||||
|
|
||||||
if (vstd::contains(node.Struct(), name) &&
|
if (vstd::contains(node.Struct(), name) &&
|
||||||
@ -1382,6 +1384,16 @@ void minimizeNode(JsonNode & node, const JsonNode & schema)
|
|||||||
node.Struct().erase(name);
|
node.Struct().erase(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++;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void JsonUtils::minimize(JsonNode & node, std::string schemaName)
|
void JsonUtils::minimize(JsonNode & node, std::string schemaName)
|
||||||
@ -1389,22 +1401,37 @@ void JsonUtils::minimize(JsonNode & node, std::string schemaName)
|
|||||||
minimizeNode(node, getSchema(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)
|
void maximizeNode(JsonNode & node, const JsonNode & schema)
|
||||||
{
|
{
|
||||||
assert(schema["type"].String() == "object");
|
// "required" entry can only be found in object/struct
|
||||||
|
if (schema["type"].String() == "object")
|
||||||
|
{
|
||||||
|
std::set<std::string> foundEntries;
|
||||||
|
|
||||||
|
// check all required entries that have default version
|
||||||
BOOST_FOREACH(auto & entry, schema["required"].Vector())
|
BOOST_FOREACH(auto & entry, schema["required"].Vector())
|
||||||
{
|
{
|
||||||
std::string name = entry.String();
|
std::string name = entry.String();
|
||||||
|
foundEntries.insert(name);
|
||||||
|
|
||||||
if (node[name].isNull() &&
|
if (node[name].isNull() &&
|
||||||
!schema["properties"][name]["default"].isNull())
|
!schema["properties"][name]["default"].isNull())
|
||||||
{
|
{
|
||||||
node[name] = schema["properties"][name]["default"];
|
node[name] = schema["properties"][name]["default"];
|
||||||
}
|
}
|
||||||
if (node[name].getType() == JsonNode::DATA_STRUCT)
|
|
||||||
maximizeNode(node[name], schema["properties"][name]);
|
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++;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void JsonUtils::maximize(JsonNode & node, std::string schemaName)
|
void JsonUtils::maximize(JsonNode & node, std::string schemaName)
|
||||||
@ -1434,7 +1461,7 @@ const JsonNode & getSchemaByName(std::string name)
|
|||||||
return loadedSchemas[name];
|
return loadedSchemas[name];
|
||||||
}
|
}
|
||||||
|
|
||||||
tlog0 << "Error: missing schema with name " << name << "!\n";
|
tlog1 << "Error: missing schema with name " << name << "!\n";
|
||||||
assert(0);
|
assert(0);
|
||||||
return nullNode;
|
return nullNode;
|
||||||
}
|
}
|
||||||
@ -1449,7 +1476,7 @@ const JsonNode & JsonUtils::getSchema(std::string URI)
|
|||||||
|
|
||||||
if (segments[0] != "vcmi")
|
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;
|
return nullNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user