{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "title": "Petafab level v1/v2",
  "type": "object",
  "additionalProperties": false,
  "required": ["version", "player", "brushes", "fluids", "gates", "waves"],
  "allOf": [{
    "if": {"properties": {"version": {"const": 2}}},
    "then": {"required": ["materials"], "properties": {"textures": false, "brushes": {"items": {
      "if": {"properties": {"op": {"const": "add"}}}, "then": {"required": ["material"]}
    }}}},
    "else": {"properties": {"materials": false, "botMaterials": false, "brushes": {"items": {
      "properties": {"material": {"$ref": "#/$defs/builtin"}}
    }}}}
  }],
  "properties": {
    "$schema": {"type": "string"},
    "version": {"enum": [1, 2]},
    "player": {
      "type": "object", "additionalProperties": false, "required": ["position"],
      "properties": {"position": {"$ref": "#/$defs/playerPosition"}, "yaw": {"$ref": "#/$defs/yaw"}, "pitch": {"type": "number", "minimum": -89, "maximum": 89}}
    },
    "brushes": {"type": "array", "maxItems": 65536, "items": {"$ref": "#/$defs/brush"}},
    "fluidDamagePerSecond": {"type": "number", "minimum": 0, "default": 40},
    "fluidMaterial": {
      "type": "object", "additionalProperties": false,
      "dependentRequired": {"color": ["normal"], "normal": ["color"]},
      "properties": {
        "color": {"type": "string", "pattern": "[.]dds$"}, "normal": {"type": "string", "pattern": "[.]dds$"},
        "tint": {"type": "array", "minItems": 3, "maxItems": 3, "items": {"type": "number", "minimum": 0, "maximum": 64}},
        "roughness": {"type": "number", "minimum": 0, "maximum": 1}, "metallic": {"type": "number", "minimum": 0, "maximum": 1},
        "emission": {"type": "number", "minimum": 0, "maximum": 64}
      }
    },
    "fluids": {"type": "array", "maxItems": 208, "items": {"$ref": "#/$defs/fluid"}},
    "gates": {"type": "array", "maxItems": 4, "items": {"$ref": "#/$defs/gate"}},
    "waves": {"type": "array", "maxItems": 32, "items": {"$ref": "#/$defs/wave"}},
    "music": {"type": "integer", "minimum": 1, "maximum": 3, "default": 1},
    "boss": {"type": "object", "additionalProperties": false, "required": ["type", "position"],
      "properties": {"type": {"enum": ["barrage", "saw", "laser"]}, "position": true, "announcement": {"$ref": "#/$defs/announcement"},
        "afterDefeats": {"type": "integer", "minimum": 0, "description": "Regular defeats required for the boss. Defaults to the total scheduled enemy count."},
        "afterSeconds": {"type": "number", "minimum": 0, "maximum": 600, "default": 0}},
      "if": {"properties": {"type": {"const": "laser"}}},
      "then": {"properties": {"position": {"type": "array", "minItems": 3, "maxItems": 3,
        "prefixItems": [{"$ref": "#/$defs/xz"}, {"type": "number", "minimum": 0, "maximum": 59}, {"$ref": "#/$defs/xz"}]}}},
      "else": {"properties": {"position": {"$ref": "#/$defs/point"}}}},
    "pickups": {"type": "array", "maxItems": 22, "items": {"$ref": "#/$defs/pickup"}},
    "materials": {"type": "array", "maxItems": 32, "items": {"$ref": "#/$defs/material"}},
    "botMaterials": {"type": "object", "propertyNames": {"enum": ["constructor","runner","rocketeer","shock_trooper"]},
      "additionalProperties": {"type": "object", "propertyNames": {"$ref": "#/$defs/builtin"}, "additionalProperties": {"$ref": "#/$defs/id"}}},
    "textures": {"type": "array", "maxItems": 32, "items": {"$ref": "#/$defs/texture"}},
    "skybox": {"type": "object", "additionalProperties": false, "required": ["sky", "diffuse", "specular"],
      "properties": {"sky": {"$ref": "#/$defs/dds"}, "diffuse": {"$ref": "#/$defs/dds"}, "specular": {"$ref": "#/$defs/dds"}}},
    "sun": {"type": "object", "additionalProperties": false, "properties": {
      "direction": {"$ref": "#/$defs/vector"}, "radiance": {"$ref": "#/$defs/radiance"}, "ambient": {"type": "number", "minimum": 0, "maximum": 16},
      "motion": {"enum": ["orbit", "fixed"]},
      "color": {"type":"array","minItems":3,"maxItems":3,"items":{"type":"number","minimum":0,"maximum":1}},
      "brightness": {"type":"number","minimum":0,"maximum":1024}, "azimuth": {"type":"number","minimum":-180,"maximum":180},
      "elevation": {"type":"number","minimum":-90,"maximum":90}, "rotationSpeed": {"type":"number","minimum":-90,"maximum":90}
    }},
    "render": {"$ref": "#/$defs/render"},
    "lights": {"type": "array", "maxItems": 1024, "items": {"type": "object", "additionalProperties": false,
      "required": ["position", "radius", "radiance"], "properties": {
        "position": {"$ref": "#/$defs/vector"}, "radius": {"type": "number", "minimum": 0.125, "maximum": 128}, "radiance": {"$ref": "#/$defs/radiance"}
      }}}
  },
  "$defs": {
    "announcement": {"type": "string", "default": "auto", "description": "Selects the arrival banner, alarm and voice together. Use none for a silent arrival.",
      "enum": ["auto", "none", "constructors", "constructors_confirmed", "runners", "swarm", "rocketeers", "shock_troopers",
        "bee_carrier", "bee_swarm", "barrage", "saw", "laser"]},
    "dds": {"type": "string", "pattern": "^(?!/)(?!.*[. ]/)(?!.*//)[^\\\\:*?\"<>|]+[.]dds$"},
    "vector": {"type": "array", "minItems": 3, "maxItems": 3, "items": {"type": "number", "minimum": -64, "maximum": 64}},
    "radiance": {"type": "array", "minItems": 3, "maxItems": 3, "items": {"type": "number", "minimum": 0, "maximum": 1024}},
    "builtin": {"enum": ["concrete", "steel", "teal", "hazard", "corpse", "pavement", "ivory", "trim", "robot_joint", "robot_boss", "robot_visor", "robot_panel", "robot_boss_panel", "foam", "foam_turquoise", "foam_pink", "safety", "lamp_amber", "lamp_red", "rubber", "graybox", "bee_yellow", "bee_black", "bee_wing", "porcelain", "aluminium", "upholstery", "foliage", "bark", "display", "lounge_fabric", "robot_rocketeer"]},
    "builtinMaterial": {"anyOf": [{"$ref": "#/$defs/builtin"}, {"type": "string", "pattern": "^(yard|factory|rooftop):(concrete|steel|teal|hazard|corpse|pavement|ivory|trim|robot_joint|robot_boss|robot_visor|robot_panel|robot_boss_panel|foam|foam_turquoise|foam_pink|safety|lamp_amber|lamp_red|rubber|graybox|bee_yellow|bee_black|bee_wing|porcelain|aluminium|upholstery|foliage|bark|display|lounge_fabric|robot_rocketeer)$"}]},
    "material": {"type": "object", "required": ["id"], "additionalProperties": false,
      "properties": {"id": {"$ref": "#/$defs/id"}, "slot": {"$ref": "#/$defs/builtin"}, "builtin": {"$ref": "#/$defs/builtinMaterial"},
        "color": {"$ref": "#/$defs/dds"}, "normal": {"$ref": "#/$defs/dds"}, "roughness": {"type": "number", "minimum": 0, "maximum": 1},
        "metallic": {"type": "number", "minimum": 0, "maximum": 1}, "emission": {"type": "number", "minimum": 0, "maximum": 64}},
      "if": {"required": ["builtin"]}, "then": {"properties": {"color": false, "normal": false, "roughness": false, "metallic": false, "emission": false}},
      "else": {"required": ["color", "normal"]}},
    "texture": {"type": "object", "additionalProperties": false, "required": ["slot", "color", "normal"], "properties": {
      "slot": {"$ref": "#/$defs/builtin"}, "color": {"$ref": "#/$defs/dds"}, "normal": {"$ref": "#/$defs/dds"},
      "roughness": {"type": "number", "minimum": 0, "maximum": 1}, "metallic": {"type": "number", "minimum": 0, "maximum": 1},
      "emission": {"type": "number", "minimum": 0, "maximum": 64}
    }},
    "render": {
      "type": "object", "additionalProperties": false,
      "properties": {
        "exposure": {"type": "number", "minimum": 0.25, "maximum": 3},
        "brightness": {"type": "number", "minimum": -0.5, "maximum": 0.5},
        "contrast": {"type": "number", "minimum": -0.5, "maximum": 0.5},
        "saturation": {"type": "number", "minimum": -1, "maximum": 1},
        "shadows": {"type": "number", "minimum": -1, "maximum": 1},
        "highlights": {"type": "number", "minimum": -1, "maximum": 1},
        "ssao_radius": {"type": "number", "minimum": 0.1, "maximum": 3},
        "ssao_gain": {"type": "number", "minimum": 0, "maximum": 4},
        "ssao_power": {"type": "number", "minimum": 0.25, "maximum": 3},
        "sdf_power": {"type": "number", "minimum": 0.25, "maximum": 3},
        "ambient_floor": {"type": "number", "minimum": 0, "maximum": 0.5},
        "sky_brightness": {"type": "number", "minimum": 0, "maximum": 4},
        "ambient_multiplier": {"type": "number", "minimum": 0, "maximum": 4},
        "sky_ao_multiplier": {"type": "number", "minimum": 0, "maximum": 4},
        "fog_density": {"type": "number", "minimum": 0, "maximum": 0.05},
        "fog_height_falloff": {"type": "number", "minimum": 0, "maximum": 0.2},
        "fog_reference_height": {"type": "number", "minimum": -16, "maximum": 64},
        "bloom_strength": {"type": "number", "minimum": 0, "maximum": 3},
        "bloom_threshold": {"type": "number", "minimum": 0, "maximum": 8},
        "bloom_knee": {"type": "number", "minimum": 0, "maximum": 4},
        "bloom_downsample_radius": {"type": "number", "minimum": 0, "maximum": 4},
        "bloom_upsample_radius": {"type": "number", "minimum": 0, "maximum": 4}
      }
    },
    "xz": {"type": "number", "minimum": -32, "maximum": 32},
    "point": {
      "type": "array", "minItems": 3, "maxItems": 3,
      "prefixItems": [{"$ref": "#/$defs/xz"}, {"type": "number", "minimum": 0, "maximum": 32}, {"$ref": "#/$defs/xz"}]
    },
    "playerPosition": {
      "type": "array", "minItems": 3, "maxItems": 3,
      "prefixItems": [
        {"type": "number", "minimum": -31, "maximum": 31}, {"type": "number", "minimum": 0.55, "maximum": 30},
        {"type": "number", "minimum": -31, "maximum": 31}
      ]
    },
    "yaw": {"type": "number", "minimum": -360, "maximum": 360},
    "id": {"type": "string", "pattern": "^[A-Za-z0-9_-]{1,32}$"},
    "brush": {
      "type": "object", "additionalProperties": false, "required": ["op", "shape", "center"],
      "properties": {
        "op": {"enum": ["add", "subtract"]}, "shape": {"enum": ["box", "sphere", "cylinder", "torus"]}, "center": {"$ref": "#/$defs/point"},
        "material": {"$ref": "#/$defs/id"},
        "size": {"type": "array", "minItems": 3, "maxItems": 3, "items": {"type": "number", "minimum": 0.0625, "maximum": 64}},
        "yaw": {"$ref": "#/$defs/yaw"}, "radius": {"type": "number", "minimum": 0.0625, "maximum": 32},
        "height": {"type": "number", "minimum": 0.0625, "maximum": 64},
        "rounding": {"type": "number", "minimum": 0, "maximum": 32}, "pitch": {"$ref": "#/$defs/yaw"},
        "tubeRadius": {"type": "number", "minimum": 0.0625, "maximum": 32},
        "topRadius": {"type": "number", "minimum": 0, "maximum": 32}
      },
      "oneOf": [
        {"properties": {"shape": {"const": "torus"}, "size": false, "height": false, "rounding": false, "topRadius": false}, "required": ["radius", "tubeRadius"]},
        {"properties": {"shape": {"const": "box"}, "tubeRadius": false, "radius": false, "height": false, "topRadius": false}, "required": ["size"]},
        {"properties": {"shape": {"const": "sphere"}, "tubeRadius": false, "size": false, "yaw": false, "height": false, "pitch": false, "rounding": false, "topRadius": false}, "required": ["radius"]},
        {"properties": {"shape": {"const": "cylinder"}, "tubeRadius": false, "size": false, "yaw": false, "pitch": false, "rounding": false}, "required": ["radius", "height"]}
      ]
    },
    "fluid": {
      "type": "object", "additionalProperties": false, "required": ["shape", "radius"],
      "properties": {
        "shape": {"enum": ["cylinder", "pipe"]}, "radius": {"type": "number", "minimum": 0.25, "maximum": 32},
        "bottom": {"$ref": "#/$defs/point"}, "height": {"type": "number", "minimum": 0.25, "maximum": 32},
        "start": {"$ref": "#/$defs/point"}, "end": {"$ref": "#/$defs/point"},
        "overpressure": {"type": "number", "minimum": 0, "maximum": 0.25, "default": 0},
        "maxParticles": {"type": "integer", "minimum": 1, "maximum": 65536}
      },
      "oneOf": [
        {"properties": {"shape": {"const": "cylinder"}, "start": false, "end": false}, "required": ["bottom", "height"]},
        {"properties": {"shape": {"const": "pipe"}, "bottom": false, "height": false, "maxParticles": false}, "required": ["start", "end"]}
      ]
    },
    "gate": {
      "type": "object", "additionalProperties": false, "required": ["id", "floor", "size", "yaw"],
      "properties": {
        "id": {"$ref": "#/$defs/id"}, "floor": {"$ref": "#/$defs/point"}, "yaw": {"$ref": "#/$defs/yaw"},
        "obstructions": {"enum": ["wait", "clear"], "deprecated": true, "description": "Ignored. All spawn gates clear blocked lanes automatically."},
        "size": {"type": "array", "minItems": 3, "maxItems": 3, "items": {"type": "number", "minimum": 1, "maximum": 16}}
      }
    },
    "wave": {
      "type": "object", "additionalProperties": false, "required": ["groups"],
      "properties": {
        "afterDefeats": {"type": "integer", "minimum": 0}, "afterSeconds": {"type": "number", "minimum": 0, "maximum": 600},
        "delayTicks": {"type": "integer", "minimum": 0, "maximum": 72000},
        "announcement": {"$ref": "#/$defs/announcement"},
        "groups": {"type": "array", "minItems": 1, "maxItems": 4, "items": {"$ref": "#/$defs/group"}}
      }
    },
    "group": {
      "type": "object", "additionalProperties": false, "required": ["gate", "enemy", "count"],
      "oneOf": [{"required": ["intervalTicks"]}, {"required": ["intervalSeconds"]}],
      "properties": {
        "gate": {"$ref": "#/$defs/id"}, "enemy": {"enum": ["constructor", "runner", "rocketeer", "shock_trooper"]},
        "count": {"type": "integer", "minimum": 1, "maximum": 1000}, "intervalTicks": {"type": "integer", "minimum": 1, "maximum": 72000},
        "intervalSeconds": {"type": "number", "exclusiveMinimum": 0, "maximum": 600}
      }
    },
    "pickup": {
      "type": "object", "additionalProperties": false, "required": ["kind", "position"],
      "properties": {
        "kind": {"enum": ["ammo", "health", "energy", "mine", "grenade", "foam", "lure", "bfg", "black_hole", "micro_missiles"]},
        "position": {"$ref": "#/$defs/point"}
      }
    }
  }
}
