{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "title": "Scenario",
  "description": "A whole scenario file.",
  "type": "object",
  "properties": {
    "block": {
      "type": "array",
      "default": [],
      "items": {
        "$ref": "#/$defs/BlockUse"
      }
    },
    "device": {
      "description": "Devices placed in the world (BUILD.md step 4.4): Lua templates with settings.",
      "type": "array",
      "items": {
        "$ref": "#/$defs/DeviceUse"
      }
    },
    "experience": {
      "description": "What makes it an Experience (BUILD.md step 4.9): a title screen, goals, an ending, the\nstart, and what the player can't change.",
      "anyOf": [
        {
          "$ref": "#/$defs/Experience"
        },
        {
          "type": "null"
        }
      ]
    },
    "scenario": {
      "$ref": "#/$defs/ScenarioInfo"
    },
    "wire": {
      "type": "array",
      "items": {
        "$ref": "#/$defs/WireSpec"
      }
    }
  },
  "additionalProperties": false,
  "required": [
    "scenario"
  ],
  "$defs": {
    "BlockUse": {
      "description": "One block placed in the scenario.",
      "type": "object",
      "properties": {
        "instance": {
          "description": "Name of this copy, if the same block is used twice. Defaults to the id.",
          "type": [
            "string",
            "null"
          ]
        },
        "screen": {
          "description": "Show this block's game on a screen in the world instead of around the player (a game\non an arcade cabinet): it draws its own view, and the player uses it by walking up and\npressing E.",
          "anyOf": [
            {
              "$ref": "#/$defs/Screen"
            },
            {
              "type": "null"
            }
          ]
        },
        "settings": {
          "description": "The player's choices for the block's settings (`[[block.setting]]` in its router); the\nothers keep their defaults.",
          "type": "object",
          "additionalProperties": {
            "$ref": "#/$defs/SettingValue"
          }
        },
        "use": {
          "description": "Block id, e.g. \"skyrim.npcs\".",
          "type": "string"
        }
      },
      "additionalProperties": false,
      "required": [
        "use"
      ]
    },
    "DeviceUse": {
      "description": "One Device in the scenario: which template (`godot/devices/<type>.lua`), where, and the\nsettings that differ from the template's defaults.",
      "type": "object",
      "properties": {
        "at": {
          "description": "Where it stands, in meters (Fusion's space).",
          "type": "array",
          "items": {
            "type": "number",
            "format": "float"
          },
          "maxItems": 3,
          "minItems": 3
        },
        "settings": {
          "description": "The template's settings that differ from its defaults (names and values as the template\ndeclares them).",
          "type": "object",
          "additionalProperties": true
        },
        "type": {
          "type": "string"
        }
      },
      "additionalProperties": false,
      "required": [
        "type",
        "at"
      ]
    },
    "Experience": {
      "description": "The `[experience]` table.",
      "type": "object",
      "properties": {
        "goal": {
          "description": "What the player has to do. Each one is ticked off when its signal arrives.",
          "type": "array",
          "items": {
            "$ref": "#/$defs/Goal"
          }
        },
        "intro": {
          "description": "What the title screen says under the title.",
          "type": "string"
        },
        "locks": {
          "description": "What the player can't change: see [`LOCKS`].",
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "lose_on": {
          "description": "The signal that loses (a Timer's, for example).",
          "type": "string"
        },
        "lose_text": {
          "type": "string"
        },
        "play_as": {
          "description": "The Character block (its instance) the player plays as, when there are several.",
          "type": "string"
        },
        "start": {
          "description": "Where the player starts, in meters (Fusion's space). The World's spawn point if not set.",
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "number",
            "format": "float"
          },
          "maxItems": 3,
          "minItems": 3
        },
        "title": {
          "description": "The name on its cover and title screen (the scenario's name if empty).",
          "type": "string"
        },
        "tools": {
          "description": "The sandbox tools the player gets (M3): any of [`SANDBOX_TOOLS`] and addons' tool ids.\nEmpty: no sandbox at all (the Experience decides everything).",
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "win_on": {
          "description": "The signal that wins. Empty: finishing every goal wins (with no goals, only Lua's\n`Experience.win()` does).",
          "type": "string"
        },
        "win_text": {
          "description": "What the ending screen says when the player wins.",
          "type": "string"
        }
      },
      "additionalProperties": false
    },
    "Goal": {
      "description": "One goal of an Experience.",
      "type": "object",
      "properties": {
        "done_on": {
          "description": "The signal that marks it done (`Fusion.signal(name)` in Lua, or a Device's signal).",
          "type": "string"
        },
        "text": {
          "type": "string"
        }
      },
      "additionalProperties": false,
      "required": [
        "text",
        "done_on"
      ]
    },
    "ScenarioInfo": {
      "type": "object",
      "properties": {
        "addons": {
          "description": "Lua addons it uses (folders in the addons folder). Packages carry them; an Experience\nruns only these (step 4.9).",
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "description": {
          "type": "string"
        },
        "name": {
          "type": "string"
        }
      },
      "additionalProperties": false,
      "required": [
        "name"
      ]
    },
    "Screen": {
      "description": "Where a game's screen stands in the world.",
      "type": "object",
      "properties": {
        "at": {
          "description": "The middle of its bottom edge, in meters.",
          "type": "array",
          "items": {
            "type": "number",
            "format": "float"
          },
          "maxItems": 3,
          "minItems": 3
        },
        "width": {
          "description": "Its width in meters (the height follows the game's picture).",
          "type": "number",
          "format": "float",
          "default": 2.4000000953674316
        },
        "yaw": {
          "description": "Which way it faces, in degrees around up (0: toward +Z, the player's start).",
          "type": "number",
          "format": "float",
          "default": 0.0
        }
      },
      "additionalProperties": false,
      "required": [
        "at"
      ]
    },
    "SettingValue": {
      "description": "A setting's value as a scenario stores it.",
      "anyOf": [
        {
          "type": "boolean"
        },
        {
          "type": "number",
          "format": "double"
        },
        {
          "type": "string"
        }
      ]
    },
    "WireSpec": {
      "description": "An explicit choice: `to`'s need `port` comes from `from` (an instance, or\n\"fusion\" for Fusion's own services).",
      "type": "object",
      "properties": {
        "from": {
          "type": "string"
        },
        "port": {
          "type": "string"
        },
        "to": {
          "type": "string"
        }
      },
      "additionalProperties": false,
      "required": [
        "port",
        "from",
        "to"
      ]
    }
  }
}
