{
  "format": 1,
  "api": 1,
  "gameVersion": "0.1.0",
  "hostModules": [
    {
      "id": "theonaris.building",
      "version": "1.1.0",
      "description": "Blocks, creations, gears and the building editor."
    },
    {
      "id": "theonaris.core",
      "version": "1.0.0",
      "description": "Lua runtime, storage, settings, events, timers and tasks."
    },
    {
      "id": "theonaris.devtools",
      "version": "1.0.0",
      "description": "The developer console: commands mods can add."
    },
    {
      "id": "theonaris.engine",
      "version": "1.0.0",
      "description": "Pictures, models, interfaces, objects in the world, effects, audio, video, input, the camera, maps and web requests."
    },
    {
      "id": "theonaris.game",
      "version": "0.1.0",
      "description": "Project Avion itself: notifications, the cursor, player highlights and the game's own events."
    },
    {
      "id": "theonaris.net",
      "version": "1.0.0",
      "description": "Mod messages, replicated state, players and mod downloads in multiplayer."
    },
    {
      "id": "theonaris.planets",
      "version": "1.0.0",
      "description": "Planets: a map's planet system, gravity, air and weather."
    }
  ],
  "modules": [
    {
      "name": "assets",
      "description": "Load the pictures and models your mod ships with, and make materials. Everything is freed when your mod stops.",
      "sides": [
        "client"
      ],
      "provider": "theonaris.engine",
      "since": "1.0",
      "permission": null,
      "availability": null,
      "functions": [
        {
          "name": "material",
          "fullName": "assets.material",
          "signature": "assets.material(options?: any): Material",
          "description": "Makes a material of your own.",
          "params": [
            {
              "name": "options",
              "type": "any",
              "optional": true,
              "default": null,
              "description": ""
            }
          ],
          "returns": {
            "type": "Material",
            "description": ""
          },
          "permission": null,
          "sides": [
            "client"
          ],
          "example": "local m = assets.material{ color = color(\"#c04020\"), metallic = 0.2, roughness = 0.6 }",
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "model",
          "fullName": "assets.model",
          "signature": "assets.model(path: string): Model",
          "description": "Loads a model from your mod (.glb, .gltf, .obj or .fbx) and returns what it contains.",
          "params": [
            {
              "name": "path",
              "type": "string",
              "optional": false,
              "default": null,
              "description": ""
            }
          ],
          "returns": {
            "type": "Model",
            "description": ""
          },
          "permission": null,
          "sides": [
            "client"
          ],
          "example": "local sphere = assets.model(\"models/sphere.glb\")\nlog.info(\"triangles:\", sphere.triangles)",
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "texture",
          "fullName": "assets.texture",
          "signature": "assets.texture(path: string, use?: string): Texture",
          "description": "Loads a picture from your mod.",
          "params": [
            {
              "name": "path",
              "type": "string",
              "optional": false,
              "default": null,
              "description": ""
            },
            {
              "name": "use",
              "type": "string",
              "optional": true,
              "default": "color",
              "description": ""
            }
          ],
          "returns": {
            "type": "Texture",
            "description": ""
          },
          "permission": null,
          "sides": [
            "client"
          ],
          "example": "local icon = assets.texture(\"ui/icon.png\")",
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "usage",
          "fullName": "assets.usage",
          "signature": "assets.usage(): any",
          "description": "How much memory this mod's loaded files are using.",
          "params": [],
          "returns": {
            "type": "any",
            "description": ""
          },
          "permission": null,
          "sides": [
            "client"
          ],
          "example": null,
          "since": null,
          "deprecated": null,
          "tryOf": null
        }
      ]
    },
    {
      "name": "audio",
      "description": "Play your mod's sounds and music. Needs the \"audio\" permission. Sounds follow the player's own volume settings.",
      "sides": [
        "client"
      ],
      "provider": "theonaris.engine",
      "since": "1.0",
      "permission": null,
      "availability": null,
      "functions": [
        {
          "name": "music",
          "fullName": "audio.music",
          "signature": "audio.music(path: string, options?: any): Sound",
          "description": "Plays music: looping, not placed in the world, and on the music mixer.",
          "params": [
            {
              "name": "path",
              "type": "string",
              "optional": false,
              "default": null,
              "description": ""
            },
            {
              "name": "options",
              "type": "any",
              "optional": true,
              "default": null,
              "description": ""
            }
          ],
          "returns": {
            "type": "Sound",
            "description": ""
          },
          "permission": "audio",
          "sides": [
            "client"
          ],
          "example": "local theme = audio.music(\"music/theme.ogg\", { volume = 0.5, fadeIn = 2 })",
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "play",
          "fullName": "audio.play",
          "signature": "audio.play(path: string, options?: any): Sound",
          "description": "Plays a sound. Leave out position for a sound you hear wherever you are.",
          "params": [
            {
              "name": "path",
              "type": "string",
              "optional": false,
              "default": null,
              "description": ""
            },
            {
              "name": "options",
              "type": "any",
              "optional": true,
              "default": null,
              "description": ""
            }
          ],
          "returns": {
            "type": "Sound",
            "description": ""
          },
          "permission": "audio",
          "sides": [
            "client"
          ],
          "example": "audio.play(\"sounds/click.wav\")\naudio.play(\"sounds/thruster.wav\", { position = block.position, loop = true, volume = 0.6 })",
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "stopAll",
          "fullName": "audio.stopAll",
          "signature": "audio.stopAll()",
          "description": "Stops every sound this mod is playing.",
          "params": [],
          "returns": {
            "type": "nil",
            "description": ""
          },
          "permission": null,
          "sides": [
            "client"
          ],
          "example": null,
          "since": null,
          "deprecated": null,
          "tryOf": null
        }
      ]
    },
    {
      "name": "building",
      "description": "Blocks, creations and the building editor. Needs the \"building\" permission; changing things needs more (see each function).",
      "sides": [
        "client",
        "server"
      ],
      "provider": "theonaris.building",
      "since": "1.0",
      "permission": "building",
      "availability": null,
      "functions": [
        {
          "name": "addTool",
          "fullName": "building.addTool",
          "signature": "building.addTool(options?: table, onClick: function): BuildTool",
          "description": "Adds a button to the building toolbar. Returns a BuildTool; clicking it calls onClick.",
          "params": [
            {
              "name": "options",
              "type": "table",
              "optional": true,
              "default": null,
              "description": "{ name = string?, tooltip = string? }"
            },
            {
              "name": "onClick",
              "type": "function",
              "optional": false,
              "default": null,
              "description": ""
            }
          ],
          "returns": {
            "type": "BuildTool",
            "description": ""
          },
          "permission": "building",
          "sides": [
            "client"
          ],
          "example": "local tool = building.addTool({ name = \"⚙ Thrusters\", tooltip = \"Tune engines past their limits\" }, function()\n  toggleWindow()\nend)",
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "block",
          "fullName": "building.block",
          "signature": "building.block(id: string): Block?",
          "description": "Finds a block by its id, or nil.",
          "params": [
            {
              "name": "id",
              "type": "string",
              "optional": false,
              "default": null,
              "description": ""
            }
          ],
          "returns": {
            "type": "Block?",
            "description": ""
          },
          "permission": "building",
          "sides": [
            "client",
            "server"
          ],
          "example": null,
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "blockTypes",
          "fullName": "building.blockTypes",
          "signature": "building.blockTypes(): any",
          "description": "Every block type there is, as { id, name, category, mod }.",
          "params": [],
          "returns": {
            "type": "any",
            "description": ""
          },
          "permission": "building",
          "sides": [
            "client",
            "server"
          ],
          "example": null,
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "blocks",
          "fullName": "building.blocks",
          "signature": "building.blocks(type: string, limit?: integer): Block[]",
          "description": "Every block of a type in the world. Pass \"sphere\" for your own block, \"author.mod:sphere\" for another mod's, or a built-in name like \"Thruster\".",
          "params": [
            {
              "name": "type",
              "type": "string",
              "optional": false,
              "default": null,
              "description": ""
            },
            {
              "name": "limit",
              "type": "integer",
              "optional": true,
              "default": 512,
              "description": ""
            }
          ],
          "returns": {
            "type": "Block[]",
            "description": ""
          },
          "permission": "building",
          "sides": [
            "client",
            "server"
          ],
          "example": "for _, sphere in ipairs(building.blocks(\"sphere\")) do log.info(sphere.position) end",
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "limit",
          "fullName": "building.limit",
          "signature": "building.limit(mechanism: string, setting: string): number?",
          "description": "The raised ceiling for a mechanism's setting, or nil when it has its normal limit.",
          "params": [
            {
              "name": "mechanism",
              "type": "string",
              "optional": false,
              "default": null,
              "description": ""
            },
            {
              "name": "setting",
              "type": "string",
              "optional": false,
              "default": null,
              "description": ""
            }
          ],
          "returns": {
            "type": "number?",
            "description": ""
          },
          "permission": "building",
          "sides": [
            "client",
            "server"
          ],
          "example": null,
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "moveInto",
          "fullName": "building.moveInto",
          "signature": "building.moveInto(player: Player, blocks: Block[], offset: vec3): boolean",
          "description": "Moves blocks by an offset in their creation's own directions, allowing them to overlap other blocks. Server scripts only; the player must own the creation.",
          "params": [
            {
              "name": "player",
              "type": "Player",
              "optional": false,
              "default": null,
              "description": ""
            },
            {
              "name": "blocks",
              "type": "Block[]",
              "optional": false,
              "default": null,
              "description": ""
            },
            {
              "name": "offset",
              "type": "vec3",
              "optional": false,
              "default": null,
              "description": ""
            }
          ],
          "returns": {
            "type": "boolean",
            "description": ""
          },
          "permission": "building.overlap",
          "sides": [
            "server"
          ],
          "example": "net.on(\"push-in\", function(player, data)\n  local blocks = {}\n  for _, id in ipairs(data.blocks) do blocks[#blocks + 1] = building.block(id) end\n  building.moveInto(player, blocks, data.offset)\nend)",
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "onPlaced",
          "fullName": "building.onPlaced",
          "signature": "building.onPlaced(type: string, fn: function): Subscription",
          "description": "Calls fn(block) whenever a block of a type appears — placed, loaded, or arriving from the server.",
          "params": [
            {
              "name": "type",
              "type": "string",
              "optional": false,
              "default": null,
              "description": ""
            },
            {
              "name": "fn",
              "type": "function",
              "optional": false,
              "default": null,
              "description": ""
            }
          ],
          "returns": {
            "type": "Subscription",
            "description": ""
          },
          "permission": "building",
          "sides": [
            "client",
            "server"
          ],
          "example": "building.onPlaced(\"sphere\", function(block) effects.burst(\"magic\", block.position) end)",
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "onRemoved",
          "fullName": "building.onRemoved",
          "signature": "building.onRemoved(type: string, fn: function): Subscription",
          "description": "Calls fn(block) just before a block of a type is removed.",
          "params": [
            {
              "name": "type",
              "type": "string",
              "optional": false,
              "default": null,
              "description": ""
            },
            {
              "name": "fn",
              "type": "function",
              "optional": false,
              "default": null,
              "description": ""
            }
          ],
          "returns": {
            "type": "Subscription",
            "description": ""
          },
          "permission": "building",
          "sides": [
            "client",
            "server"
          ],
          "example": null,
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "onSelectionChanged",
          "fullName": "building.onSelectionChanged",
          "signature": "building.onSelectionChanged(fn: function): Subscription",
          "description": "Calls fn(blocks) every time the building-editor selection changes, with the selected blocks (an empty list when nothing is selected). Replaces polling building.selection() on a timer.",
          "params": [
            {
              "name": "fn",
              "type": "function",
              "optional": false,
              "default": null,
              "description": ""
            }
          ],
          "returns": {
            "type": "Subscription",
            "description": ""
          },
          "permission": "building",
          "sides": [
            "client"
          ],
          "example": "building.onSelectionChanged(function(blocks)\n  label:setText(#blocks == 0 and \"Nothing selected\" or (#blocks .. \" selected\"))\nend)",
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "placement",
          "fullName": "building.placement",
          "signature": "building.placement(type: string, fn: function): Subscription",
          "description": "Guides players placing a block type: fn(query) runs every frame of the drag and may return where the block should go and how to show it. query has position, rotation (where the editor would snap), hit { position, normal, block }, ray, scale and — for blocks the game already guides, like gears — suggested. Return { position, rotation, state = \"valid\" | \"neutral\" | \"invalid\", label, settings = { … }, circles, lines, dots }, nil to keep the game's suggestion, or false for none.",
          "params": [
            {
              "name": "type",
              "type": "string",
              "optional": false,
              "default": null,
              "description": ""
            },
            {
              "name": "fn",
              "type": "function",
              "optional": false,
              "default": null,
              "description": ""
            }
          ],
          "returns": {
            "type": "Subscription",
            "description": ""
          },
          "permission": "building",
          "sides": [
            "client"
          ],
          "example": "building.placement(\"crank\", function(q)\n  if not q.hit or not q.hit.block then return nil end\n  return { position = q.position, rotation = q.rotation, state = \"valid\", label = \"On \" .. q.hit.block.name }\nend)",
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "raiseLimit",
          "fullName": "building.raiseLimit",
          "signature": "building.raiseLimit(mechanism: string, setting: string, ceiling: number)",
          "description": "Raises the highest value a setting may take for one kind of mechanism, for everyone on this server. Server scripts only.",
          "params": [
            {
              "name": "mechanism",
              "type": "string",
              "optional": false,
              "default": null,
              "description": ""
            },
            {
              "name": "setting",
              "type": "string",
              "optional": false,
              "default": null,
              "description": ""
            },
            {
              "name": "ceiling",
              "type": "number",
              "optional": false,
              "default": null,
              "description": ""
            }
          ],
          "returns": {
            "type": "nil",
            "description": ""
          },
          "permission": "building.limits",
          "sides": [
            "server"
          ],
          "example": "building.raiseLimit(\"Thruster\", \"Force\", 5000000)\nbuilding.raiseLimit(\"JetEngine\", \"Force\", 8000000)",
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "resetLimit",
          "fullName": "building.resetLimit",
          "signature": "building.resetLimit(mechanism: string, setting: string)",
          "description": "Puts a limit this mod raised back to normal. Server scripts only.",
          "params": [
            {
              "name": "mechanism",
              "type": "string",
              "optional": false,
              "default": null,
              "description": ""
            },
            {
              "name": "setting",
              "type": "string",
              "optional": false,
              "default": null,
              "description": ""
            }
          ],
          "returns": {
            "type": "nil",
            "description": ""
          },
          "permission": "building.limits",
          "sides": [
            "server"
          ],
          "example": null,
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "selection",
          "fullName": "building.selection",
          "signature": "building.selection(): Block[]",
          "description": "The blocks you have selected in the building editor.",
          "params": [],
          "returns": {
            "type": "Block[]",
            "description": ""
          },
          "permission": "building",
          "sides": [
            "client"
          ],
          "example": null,
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "tryMoveInto",
          "fullName": "building.tryMoveInto",
          "signature": "building.tryMoveInto(player: Player, blocks: Block[], offset: vec3): boolean, boolean|string",
          "description": "Like building.moveInto, but a refusal returns false and the reason instead of raising an error. Wrong arguments, side and permission errors still raise.",
          "params": [
            {
              "name": "player",
              "type": "Player",
              "optional": false,
              "default": null,
              "description": ""
            },
            {
              "name": "blocks",
              "type": "Block[]",
              "optional": false,
              "default": null,
              "description": ""
            },
            {
              "name": "offset",
              "type": "vec3",
              "optional": false,
              "default": null,
              "description": ""
            }
          ],
          "returns": {
            "type": "boolean, boolean|string",
            "description": "true and the result on success; false and the reason on a refusal."
          },
          "permission": "building.overlap",
          "sides": [
            "server"
          ],
          "example": "net.on(\"push-in\", function(player, data)\n  local blocks = {}\n  for _, id in ipairs(data.blocks) do blocks[#blocks + 1] = building.block(id) end\n  building.moveInto(player, blocks, data.offset)\nend)",
          "since": null,
          "deprecated": null,
          "tryOf": "moveInto"
        }
      ]
    },
    {
      "name": "camera",
      "description": "Shake the view or change the field of view. The player's comfort settings always win. Needs the \"camera\" permission.",
      "sides": [
        "client"
      ],
      "provider": "theonaris.engine",
      "since": "1.0",
      "permission": null,
      "availability": "in client scripts while there is a camera",
      "functions": [
        {
          "name": "shake",
          "fullName": "camera.shake",
          "signature": "camera.shake(strength?: number, seconds?: number)",
          "description": "Shakes the view. Strength is roughly how far it moves, in metres.",
          "params": [
            {
              "name": "strength",
              "type": "number",
              "optional": true,
              "default": 0.1,
              "description": ""
            },
            {
              "name": "seconds",
              "type": "number",
              "optional": true,
              "default": 0.3,
              "description": ""
            }
          ],
          "returns": {
            "type": "nil",
            "description": ""
          },
          "permission": null,
          "sides": [
            "client"
          ],
          "example": "camera.shake(0.15, 0.4)",
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "zoom",
          "fullName": "camera.zoom",
          "signature": "camera.zoom(degrees: number)",
          "description": "Widens (positive) or narrows (negative) the view by some degrees, until you set it back to 0.",
          "params": [
            {
              "name": "degrees",
              "type": "number",
              "optional": false,
              "default": null,
              "description": ""
            }
          ],
          "returns": {
            "type": "nil",
            "description": ""
          },
          "permission": null,
          "sides": [
            "client"
          ],
          "example": "camera.zoom(-20) -- look closer\ntimer.after(2, function() camera.zoom(0) end)",
          "since": null,
          "deprecated": null,
          "tryOf": null
        }
      ]
    },
    {
      "name": "content",
      "description": "Content definitions: things this mod adds to the game (blocks, maps, effects …). Usually declared as JSON files in mod.json; content.register does the same from a script.",
      "sides": [
        "client",
        "server"
      ],
      "provider": "theonaris.core",
      "since": "1.0",
      "permission": null,
      "availability": null,
      "functions": [
        {
          "name": "get",
          "fullName": "content.get",
          "signature": "content.get(type: string, fullId: string): table?",
          "description": "The definition data for a full id, or nil.",
          "params": [
            {
              "name": "type",
              "type": "string",
              "optional": false,
              "default": null,
              "description": ""
            },
            {
              "name": "fullId",
              "type": "string",
              "optional": false,
              "default": null,
              "description": ""
            }
          ],
          "returns": {
            "type": "table?",
            "description": ""
          },
          "permission": null,
          "sides": [
            "client",
            "server"
          ],
          "example": null,
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "list",
          "fullName": "content.list",
          "signature": "content.list(type: string): string[]",
          "description": "Full ids of every definition of a type, from every mod.",
          "params": [
            {
              "name": "type",
              "type": "string",
              "optional": false,
              "default": null,
              "description": ""
            }
          ],
          "returns": {
            "type": "string[]",
            "description": ""
          },
          "permission": null,
          "sides": [
            "client",
            "server"
          ],
          "example": null,
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "register",
          "fullName": "content.register",
          "signature": "content.register(type: string, definition: any): string",
          "description": "Registers a definition and returns its full id (\"your.mod-id:local-id\").",
          "params": [
            {
              "name": "type",
              "type": "string",
              "optional": false,
              "default": null,
              "description": ""
            },
            {
              "name": "definition",
              "type": "any",
              "optional": false,
              "default": null,
              "description": ""
            }
          ],
          "returns": {
            "type": "string",
            "description": ""
          },
          "permission": null,
          "sides": [
            "client",
            "server"
          ],
          "example": "local id = content.register(\"blocks\", { id = \"heavy-cube\", name = \"Heavy Cube\", base = \"Cube\", mass = 40 })",
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "types",
          "fullName": "content.types",
          "signature": "content.types(): string[]",
          "description": "The content types this game accepts.",
          "params": [],
          "returns": {
            "type": "string[]",
            "description": ""
          },
          "permission": null,
          "sides": [
            "client",
            "server"
          ],
          "example": null,
          "since": null,
          "deprecated": null,
          "tryOf": null
        }
      ]
    },
    {
      "name": "cursor",
      "description": "Show the mouse cursor while your window needs clicks. Needs the \"ui\" permission.",
      "sides": [
        "client"
      ],
      "provider": "theonaris.game",
      "since": "1.0",
      "permission": null,
      "availability": null,
      "functions": [
        {
          "name": "free",
          "fullName": "cursor.free",
          "signature": "cursor.free(free: boolean)",
          "description": "Shows (true) or gives back (false) the mouse cursor.",
          "params": [
            {
              "name": "free",
              "type": "boolean",
              "optional": false,
              "default": null,
              "description": ""
            }
          ],
          "returns": {
            "type": "nil",
            "description": ""
          },
          "permission": "ui",
          "sides": [
            "client"
          ],
          "example": "panel:on(\"enter\", function() cursor.free(true) end)",
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "isFree",
          "fullName": "cursor.isFree",
          "signature": "cursor.isFree(): boolean",
          "description": "True while this mod is holding the cursor visible.",
          "params": [],
          "returns": {
            "type": "boolean",
            "description": ""
          },
          "permission": null,
          "sides": [
            "client"
          ],
          "example": null,
          "since": null,
          "deprecated": null,
          "tryOf": null
        }
      ]
    },
    {
      "name": "devtools",
      "description": "Add commands to the developer console (F1). Needs the \"devtools\" permission.",
      "sides": [
        "client",
        "server"
      ],
      "provider": "theonaris.devtools",
      "since": "1.0",
      "permission": "devtools",
      "availability": null,
      "functions": [
        {
          "name": "command",
          "fullName": "devtools.command",
          "signature": "devtools.command(options: table, run: function): string",
          "description": "Adds a console command and returns the route to type. options: name (letters, digits, '-', '_'), description, level (\"client\", \"admin\" or \"host\"; default \"client\"). run(args) receives the words typed after the command as strings.",
          "params": [
            {
              "name": "options",
              "type": "table",
              "optional": false,
              "default": null,
              "description": "{ name = string, description = string?, level = \"client\"|\"admin\"|\"host\"? }"
            },
            {
              "name": "run",
              "type": "function",
              "optional": false,
              "default": null,
              "description": ""
            }
          ],
          "returns": {
            "type": "string",
            "description": "the route, e.g. \"/rings.spawn\""
          },
          "permission": "devtools",
          "sides": [
            "client",
            "server"
          ],
          "example": "-- mod id \"community.rings\"  →  typed as /rings.spawn 12\ndevtools.command({ name = \"spawn\", description = \"Ring of spheres\", level = \"admin\" }, function(args)\n  spawnRing(tonumber(args[1]) or 8)\nend)",
          "since": null,
          "deprecated": null,
          "tryOf": null
        }
      ]
    },
    {
      "name": "effects",
      "description": "Particle effects — sparks, smoke, fire, glows. Start from a preset and tune it. Needs the \"world\" permission.",
      "sides": [
        "client"
      ],
      "provider": "theonaris.engine",
      "since": "1.0",
      "permission": null,
      "availability": "in client scripts while the game has a world",
      "functions": [
        {
          "name": "burst",
          "fullName": "effects.burst",
          "signature": "effects.burst(preset: string, position: vec3, options?: any)",
          "description": "Plays an effect once at a place and cleans it up afterwards.",
          "params": [
            {
              "name": "preset",
              "type": "string",
              "optional": false,
              "default": null,
              "description": ""
            },
            {
              "name": "position",
              "type": "vec3",
              "optional": false,
              "default": null,
              "description": ""
            },
            {
              "name": "options",
              "type": "any",
              "optional": true,
              "default": null,
              "description": ""
            }
          ],
          "returns": {
            "type": "nil",
            "description": ""
          },
          "permission": "world",
          "sides": [
            "client"
          ],
          "example": "effects.burst(\"sparks\", hit.point)\neffects.burst(\"explosion\", pos, { color = color(\"#80c0ff\"), count = 300 })",
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "presets",
          "fullName": "effects.presets",
          "signature": "effects.presets(): string[]",
          "description": "The effect presets you can start from.",
          "params": [],
          "returns": {
            "type": "string[]",
            "description": ""
          },
          "permission": null,
          "sides": [
            "client"
          ],
          "example": null,
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "start",
          "fullName": "effects.start",
          "signature": "effects.start(preset: string, position: vec3, options?: any): Effect",
          "description": "Starts an effect that keeps going until you stop or destroy it.",
          "params": [
            {
              "name": "preset",
              "type": "string",
              "optional": false,
              "default": null,
              "description": ""
            },
            {
              "name": "position",
              "type": "vec3",
              "optional": false,
              "default": null,
              "description": ""
            },
            {
              "name": "options",
              "type": "any",
              "optional": true,
              "default": null,
              "description": ""
            }
          ],
          "returns": {
            "type": "Effect",
            "description": ""
          },
          "permission": "world",
          "sides": [
            "client"
          ],
          "example": "local flame = effects.start(\"fire\", torch.position)\nflame:follow(torch, vec3(0, 0.4, 0))",
          "since": null,
          "deprecated": null,
          "tryOf": null
        }
      ]
    },
    {
      "name": "events",
      "description": "Publish and subscribe to events. Your own events are namespaced by your mod id automatically; subscribe to another mod's with \"its.mod-id:name\", and to the game's with names like \"player.joined\".",
      "sides": [
        "client",
        "server"
      ],
      "provider": "theonaris.core",
      "since": "1.0",
      "permission": null,
      "availability": null,
      "functions": [
        {
          "name": "emit",
          "fullName": "events.emit",
          "signature": "events.emit(name: string, payload?: any)",
          "description": "Raises one of this mod's events for scripts on the same side. The payload is copied; subscribers run after the current function returns.",
          "params": [
            {
              "name": "name",
              "type": "string",
              "optional": false,
              "default": null,
              "description": ""
            },
            {
              "name": "payload",
              "type": "any",
              "optional": true,
              "default": null,
              "description": ""
            }
          ],
          "returns": {
            "type": "nil",
            "description": ""
          },
          "permission": null,
          "sides": [
            "client",
            "server"
          ],
          "example": "events.emit(\"wave-started\", { number = 3 })",
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "gameEvents",
          "fullName": "events.gameEvents",
          "signature": "events.gameEvents(): string[]",
          "description": "The names of the game events available in this build.",
          "params": [],
          "returns": {
            "type": "string[]",
            "description": ""
          },
          "permission": null,
          "sides": [
            "client",
            "server"
          ],
          "example": null,
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "on",
          "fullName": "events.on",
          "signature": "events.on(name: string, handler: function): Subscription",
          "description": "Calls handler(payload) every time the event is raised.",
          "params": [
            {
              "name": "name",
              "type": "string",
              "optional": false,
              "default": null,
              "description": ""
            },
            {
              "name": "handler",
              "type": "function",
              "optional": false,
              "default": null,
              "description": ""
            }
          ],
          "returns": {
            "type": "Subscription",
            "description": ""
          },
          "permission": null,
          "sides": [
            "client",
            "server"
          ],
          "example": "events.on(\"player.joined\", function(player) log.info(player.name, \"joined\") end)",
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "once",
          "fullName": "events.once",
          "signature": "events.once(name: string, handler: function): Subscription",
          "description": "Like events.on, but only for the next time the event is raised.",
          "params": [
            {
              "name": "name",
              "type": "string",
              "optional": false,
              "default": null,
              "description": ""
            },
            {
              "name": "handler",
              "type": "function",
              "optional": false,
              "default": null,
              "description": ""
            }
          ],
          "returns": {
            "type": "Subscription",
            "description": ""
          },
          "permission": null,
          "sides": [
            "client",
            "server"
          ],
          "example": null,
          "since": null,
          "deprecated": null,
          "tryOf": null
        }
      ]
    },
    {
      "name": "http",
      "description": "Send and receive data from websites over HTTPS. Each site must be named in mod.json as \"http:site.com\" (or \"http:*.site.com\") and the player agrees to it before the mod runs. The site sees the player's IP address. Only public sites, port 443, no redirects; answers are text up to 4 MB.",
      "sides": [
        "client",
        "server"
      ],
      "provider": "theonaris.engine",
      "since": "1.0",
      "permission": null,
      "availability": null,
      "functions": [
        {
          "name": "get",
          "fullName": "http.get",
          "signature": "http.get(url: string, callback: function, headers?: any): HttpRequest",
          "description": "Fetches a page. callback(response) gets { ok, status, body, error, contentType }. headers may set Accept, Authorization, If-None-Match and X-… headers.",
          "params": [
            {
              "name": "url",
              "type": "string",
              "optional": false,
              "default": null,
              "description": ""
            },
            {
              "name": "callback",
              "type": "function",
              "optional": false,
              "default": null,
              "description": ""
            },
            {
              "name": "headers",
              "type": "any",
              "optional": true,
              "default": null,
              "description": ""
            }
          ],
          "returns": {
            "type": "HttpRequest",
            "description": ""
          },
          "permission": null,
          "sides": [
            "client",
            "server"
          ],
          "example": "http.get(\"https://api.example.com/scores?top=10\", function(r)\n  if not r.ok then return log.warn(\"scores:\", r.error) end\n  local scores = json.decode(r.body)\nend)",
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "post",
          "fullName": "http.post",
          "signature": "http.post(url: string, body: string, callback: function, contentType?: string, headers?: any): HttpRequest",
          "description": "Sends data. contentType is \"application/json\" (the default), \"text/plain\" or \"application/x-www-form-urlencoded\"; the body may be up to 1 MB.",
          "params": [
            {
              "name": "url",
              "type": "string",
              "optional": false,
              "default": null,
              "description": ""
            },
            {
              "name": "body",
              "type": "string",
              "optional": false,
              "default": null,
              "description": ""
            },
            {
              "name": "callback",
              "type": "function",
              "optional": false,
              "default": null,
              "description": ""
            },
            {
              "name": "contentType",
              "type": "string",
              "optional": true,
              "default": "application/json",
              "description": ""
            },
            {
              "name": "headers",
              "type": "any",
              "optional": true,
              "default": null,
              "description": ""
            }
          ],
          "returns": {
            "type": "HttpRequest",
            "description": ""
          },
          "permission": null,
          "sides": [
            "client",
            "server"
          ],
          "example": "http.post(\"https://api.example.com/scores\", json.encode({ name = players.me().name, score = 120 }), function(r)\n  log.info(\"saved:\", r.status)\nend)",
          "since": null,
          "deprecated": null,
          "tryOf": null
        }
      ]
    },
    {
      "name": "input",
      "description": "React to keys the player presses. You name the keys you want; your mod never sees anything else. Needs the \"input\" permission.",
      "sides": [
        "client"
      ],
      "provider": "theonaris.engine",
      "since": "1.0",
      "permission": null,
      "availability": "in client scripts once the game has a keyboard (not on dedicated servers)",
      "functions": [
        {
          "name": "bind",
          "fullName": "input.bind",
          "signature": "input.bind(key: string, fn: function): KeyBinding",
          "description": "Calls fn each time a key is pressed.",
          "params": [
            {
              "name": "key",
              "type": "string",
              "optional": false,
              "default": null,
              "description": ""
            },
            {
              "name": "fn",
              "type": "function",
              "optional": false,
              "default": null,
              "description": ""
            }
          ],
          "returns": {
            "type": "KeyBinding",
            "description": ""
          },
          "permission": null,
          "sides": [
            "client"
          ],
          "example": "input.bind(\"F7\", function() panel:set(\"visible\", not panel:get(\"visible\")) end)",
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "bindRelease",
          "fullName": "input.bindRelease",
          "signature": "input.bindRelease(key: string, fn: function): KeyBinding",
          "description": "Calls fn each time a key is let go.",
          "params": [
            {
              "name": "key",
              "type": "string",
              "optional": false,
              "default": null,
              "description": ""
            },
            {
              "name": "fn",
              "type": "function",
              "optional": false,
              "default": null,
              "description": ""
            }
          ],
          "returns": {
            "type": "KeyBinding",
            "description": ""
          },
          "permission": null,
          "sides": [
            "client"
          ],
          "example": null,
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "held",
          "fullName": "input.held",
          "signature": "input.held(key: string): boolean",
          "description": "True while a key is held down. Always false while the player is typing.",
          "params": [
            {
              "name": "key",
              "type": "string",
              "optional": false,
              "default": null,
              "description": ""
            }
          ],
          "returns": {
            "type": "boolean",
            "description": ""
          },
          "permission": null,
          "sides": [
            "client"
          ],
          "example": null,
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "keys",
          "fullName": "input.keys",
          "signature": "input.keys(): string[]",
          "description": "Every key name you can use.",
          "params": [],
          "returns": {
            "type": "string[]",
            "description": ""
          },
          "permission": null,
          "sides": [
            "client"
          ],
          "example": null,
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "typing",
          "fullName": "input.typing",
          "signature": "input.typing(): boolean",
          "description": "True while the player is typing into a text box.",
          "params": [],
          "returns": {
            "type": "boolean",
            "description": ""
          },
          "permission": null,
          "sides": [
            "client"
          ],
          "example": null,
          "since": null,
          "deprecated": null,
          "tryOf": null
        }
      ]
    },
    {
      "name": "json",
      "description": "Encode Lua values as JSON and parse JSON back. vec3/quat become {x,y,z[,w]} objects and colours \"#RRGGBBAA\" strings.",
      "sides": [
        "client",
        "server"
      ],
      "provider": "theonaris.core",
      "since": "1.0",
      "permission": null,
      "availability": null,
      "functions": [
        {
          "name": "decode",
          "fullName": "json.decode",
          "signature": "json.decode(text: string): any",
          "description": "Parses JSON text. Raises an error for invalid JSON, so wrap it in pcall when the text comes from outside.",
          "params": [
            {
              "name": "text",
              "type": "string",
              "optional": false,
              "default": null,
              "description": ""
            }
          ],
          "returns": {
            "type": "any",
            "description": ""
          },
          "permission": null,
          "sides": [
            "client",
            "server"
          ],
          "example": "local ok, data = pcall(json.decode, text)",
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "encode",
          "fullName": "json.encode",
          "signature": "json.encode(value: any, pretty?: boolean): string",
          "description": "Encodes a value as JSON text.",
          "params": [
            {
              "name": "value",
              "type": "any",
              "optional": false,
              "default": null,
              "description": ""
            },
            {
              "name": "pretty",
              "type": "boolean",
              "optional": true,
              "default": false,
              "description": "Indent the output for reading."
            }
          ],
          "returns": {
            "type": "string",
            "description": ""
          },
          "permission": null,
          "sides": [
            "client",
            "server"
          ],
          "example": "local text = json.encode({ score = 10, tags = { \"fast\", \"red\" } }, true)",
          "since": null,
          "deprecated": null,
          "tryOf": null
        }
      ]
    },
    {
      "name": "kinetics",
      "description": "Axles, gear teeth and meshes: make parts of creations turn, mesh and drive each other. Reading needs \"building\"; making and driving needs \"building.kinetics\" (server).",
      "sides": [
        "client",
        "server"
      ],
      "provider": "theonaris.building",
      "since": "1.0",
      "permission": null,
      "availability": null,
      "functions": [
        {
          "name": "available",
          "fullName": "kinetics.available",
          "signature": "kinetics.available(): boolean",
          "description": "True when gears simulate right now. When the game runs without gear simulation, gears are still drawn but do not turn.",
          "params": [],
          "returns": {
            "type": "boolean",
            "description": ""
          },
          "permission": null,
          "sides": [
            "server"
          ],
          "example": null,
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "gear",
          "fullName": "kinetics.gear",
          "signature": "kinetics.gear(block: Block, options?: any): Gear",
          "description": "Puts teeth on a block. Options: shaft (it turns with it; leave out to fix it to the block's part), kind (\"circle\", \"line\" for a rack, \"screw\" for a worm), centre (cells), axis (a circle's axis, a rack's travel, a worm's axis), normal (rack: toward its gear), reference (tooth zero), radius (m) or teeth + module (m, default 0.025), lead (worm, m per turn), internal (ring gear), extent (face width / rack length, m), strength (N), friction.",
          "params": [
            {
              "name": "block",
              "type": "Block",
              "optional": false,
              "default": null,
              "description": ""
            },
            {
              "name": "options",
              "type": "any",
              "optional": true,
              "default": null,
              "description": ""
            }
          ],
          "returns": {
            "type": "Gear",
            "description": ""
          },
          "permission": "building.kinetics",
          "sides": [
            "server"
          ],
          "example": "local teeth = kinetics.gear(block, { shaft = shaft, teeth = 32, axis = \"+y\" })",
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "gearsOn",
          "fullName": "kinetics.gearsOn",
          "signature": "kinetics.gearsOn(block: Block): Gear[]",
          "description": "The teeth on a block: a gear block's own, and any mods put there.",
          "params": [
            {
              "name": "block",
              "type": "Block",
              "optional": false,
              "default": null,
              "description": ""
            }
          ],
          "returns": {
            "type": "Gear[]",
            "description": ""
          },
          "permission": "building",
          "sides": [
            "server"
          ],
          "example": null,
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "mesh",
          "fullName": "kinetics.mesh",
          "signature": "kinetics.mesh(a: Gear, b: Gear, options?: any): GearMesh",
          "description": "Meshes two gears: their teeth drive each other at the ratio their sizes give, wherever they are. Options: strength (N before teeth jump), friction, engage (m they may drift apart and stay meshed; 0 = always).",
          "params": [
            {
              "name": "a",
              "type": "Gear",
              "optional": false,
              "default": null,
              "description": ""
            },
            {
              "name": "b",
              "type": "Gear",
              "optional": false,
              "default": null,
              "description": ""
            },
            {
              "name": "options",
              "type": "any",
              "optional": true,
              "default": null,
              "description": ""
            }
          ],
          "returns": {
            "type": "GearMesh",
            "description": ""
          },
          "permission": "building.kinetics",
          "sides": [
            "server"
          ],
          "example": "kinetics.mesh(teeth, kinetics.gearsOn(otherGear)[1])",
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "onTeethJumped",
          "fullName": "kinetics.onTeethJumped",
          "signature": "kinetics.onTeethJumped(fn: function): Subscription",
          "description": "Calls fn(mesh, teeth) when teeth jump in a mesh — overloaded, or torn apart and re-seated.",
          "params": [
            {
              "name": "fn",
              "type": "function",
              "optional": false,
              "default": null,
              "description": ""
            }
          ],
          "returns": {
            "type": "Subscription",
            "description": ""
          },
          "permission": "building",
          "sides": [
            "server"
          ],
          "example": "kinetics.onTeethJumped(function(mesh, teeth) effects.burst(\"sparks\", mesh.a.block.position) end)",
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "rpm",
          "fullName": "kinetics.rpm",
          "signature": "kinetics.rpm(block: Block): number",
          "description": "How fast a block's spinning parts turn relative to its part, in turns per minute — on any machine, including clients.",
          "params": [
            {
              "name": "block",
              "type": "Block",
              "optional": false,
              "default": null,
              "description": ""
            }
          ],
          "returns": {
            "type": "number",
            "description": ""
          },
          "permission": "building",
          "sides": [
            "client",
            "server"
          ],
          "example": null,
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "shaft",
          "fullName": "kinetics.shaft",
          "signature": "kinetics.shaft(block: Block, options?: any): Shaft",
          "description": "Gives a block an axle: it turns about axis (block-local, like \"+z\") through pivot (block-local cells) relative to its part. Options: axis, pivot, friction (N·m), damping, inertia (kg·m²), gyroscopic.",
          "params": [
            {
              "name": "block",
              "type": "Block",
              "optional": false,
              "default": null,
              "description": ""
            },
            {
              "name": "options",
              "type": "any",
              "optional": true,
              "default": null,
              "description": ""
            }
          ],
          "returns": {
            "type": "Shaft",
            "description": ""
          },
          "permission": "building.kinetics",
          "sides": [
            "server"
          ],
          "example": "local shaft = kinetics.shaft(block, { axis = \"+y\", friction = 0.5 })\nshaft:motor(30, 400)",
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "shaftOf",
          "fullName": "kinetics.shaftOf",
          "signature": "kinetics.shaftOf(block: Block): Shaft?",
          "description": "The shaft a block turns with — yours, another mod's or a gear block's own — or nil.",
          "params": [
            {
              "name": "block",
              "type": "Block",
              "optional": false,
              "default": null,
              "description": ""
            }
          ],
          "returns": {
            "type": "Shaft?",
            "description": ""
          },
          "permission": "building",
          "sides": [
            "server"
          ],
          "example": null,
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "spin",
          "fullName": "kinetics.spin",
          "signature": "kinetics.spin(block: Block): number",
          "description": "How far a block's spinning parts are drawn turned right now, in degrees (-180..180) — on any machine, including clients.",
          "params": [
            {
              "name": "block",
              "type": "Block",
              "optional": false,
              "default": null,
              "description": ""
            }
          ],
          "returns": {
            "type": "number",
            "description": ""
          },
          "permission": "building",
          "sides": [
            "client",
            "server"
          ],
          "example": null,
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "stats",
          "fullName": "kinetics.stats",
          "signature": "kinetics.stats(): any",
          "description": "Counts, for profiling: { shafts, gears, meshes, trains, networks, gearBlocks }.",
          "params": [],
          "returns": {
            "type": "any",
            "description": ""
          },
          "permission": null,
          "sides": [
            "server"
          ],
          "example": null,
          "since": null,
          "deprecated": null,
          "tryOf": null
        }
      ]
    },
    {
      "name": "log",
      "description": "Writes to the mod log, shown in the mod manager, the DevTools console and the game's log file. Values are converted like print does.",
      "sides": [
        "client",
        "server"
      ],
      "provider": "theonaris.core",
      "since": "1.0",
      "permission": null,
      "availability": null,
      "functions": [
        {
          "name": "debug",
          "fullName": "log.debug",
          "signature": "log.debug(...: any)",
          "description": "Writes a debug line.",
          "params": [
            {
              "name": "...",
              "type": "any",
              "optional": true,
              "default": null,
              "description": ""
            }
          ],
          "returns": {
            "type": "nil",
            "description": ""
          },
          "permission": null,
          "sides": [
            "client",
            "server"
          ],
          "example": "log.debug(\"spawned\", count, \"props\")",
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "error",
          "fullName": "log.error",
          "signature": "log.error(...: any)",
          "description": "Writes an error line. This does not stop the script — use error() for that.",
          "params": [
            {
              "name": "...",
              "type": "any",
              "optional": true,
              "default": null,
              "description": ""
            }
          ],
          "returns": {
            "type": "nil",
            "description": ""
          },
          "permission": null,
          "sides": [
            "client",
            "server"
          ],
          "example": null,
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "info",
          "fullName": "log.info",
          "signature": "log.info(...: any)",
          "description": "Writes an informational line.",
          "params": [
            {
              "name": "...",
              "type": "any",
              "optional": true,
              "default": null,
              "description": ""
            }
          ],
          "returns": {
            "type": "nil",
            "description": ""
          },
          "permission": null,
          "sides": [
            "client",
            "server"
          ],
          "example": "log.info(\"Hello from\", mod.name)",
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "warn",
          "fullName": "log.warn",
          "signature": "log.warn(...: any)",
          "description": "Writes a warning.",
          "params": [
            {
              "name": "...",
              "type": "any",
              "optional": true,
              "default": null,
              "description": ""
            }
          ],
          "returns": {
            "type": "nil",
            "description": ""
          },
          "permission": null,
          "sides": [
            "client",
            "server"
          ],
          "example": null,
          "since": null,
          "deprecated": null,
          "tryOf": null
        }
      ]
    },
    {
      "name": "maps",
      "description": "Which map is being played, the spawn points of a mod map, arriving on and leaving a map, and changing map from the server. Maps themselves are declared in mod.json.",
      "sides": [
        "client",
        "server"
      ],
      "provider": "theonaris.engine",
      "since": "1.0",
      "permission": null,
      "availability": "once the game has registered its maps (always in the game; not in tools that run mods without one)",
      "functions": [
        {
          "name": "current",
          "fullName": "maps.current",
          "signature": "maps.current(): string?",
          "description": "The id of the map being played (\"Earth\", or \"author.mod:map\" for a mod map), or nil in the menus.",
          "params": [],
          "returns": {
            "type": "string?",
            "description": ""
          },
          "permission": null,
          "sides": [
            "client",
            "server"
          ],
          "example": null,
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "list",
          "fullName": "maps.list",
          "signature": "maps.list(): any",
          "description": "Every map that can be played, as { id, name, subtitle, mod }.",
          "params": [],
          "returns": {
            "type": "any",
            "description": ""
          },
          "permission": null,
          "sides": [
            "client",
            "server"
          ],
          "example": null,
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "load",
          "fullName": "maps.load",
          "signature": "maps.load(mapId: string)",
          "description": "Chooses the map the host's next session starts on; the game does not change map in the middle of a session. Takes a map id from maps.list, such as \"Earth\" or \"author.mod:map\". Client scripts cannot change map: send a message to your server script instead.",
          "params": [
            {
              "name": "mapId",
              "type": "string",
              "optional": false,
              "default": null,
              "description": ""
            }
          ],
          "returns": {
            "type": "nil",
            "description": ""
          },
          "permission": "scenes",
          "sides": [
            "server"
          ],
          "example": "maps.load(\"theonaris.examples.crater-canyon:crater-canyon\")",
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "onEnter",
          "fullName": "maps.onEnter",
          "signature": "maps.onEnter(mapId: string, handler: function): Subscription",
          "description": "Calls handler({ id }) every time the players arrive on a map — and at once if they are already on it, because a mod can start after its map loaded (after /mods.reload, or on a client joining late). The map id may be a full id (\"author.mod:map\", \"Earth\") or the id of one of this mod's own maps (\"crater-canyon\"). Pair it with maps.onLeave to clean up.",
          "params": [
            {
              "name": "mapId",
              "type": "string",
              "optional": false,
              "default": null,
              "description": ""
            },
            {
              "name": "handler",
              "type": "function",
              "optional": false,
              "default": null,
              "description": ""
            }
          ],
          "returns": {
            "type": "Subscription",
            "description": ""
          },
          "permission": null,
          "sides": [
            "client",
            "server"
          ],
          "example": "maps.onEnter(\"crater-canyon\", function() music = audio.music(\"music/theme.wav\") end)\nmaps.onLeave(\"crater-canyon\", function() music:fadeOut(2) end)",
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "onLeave",
          "fullName": "maps.onLeave",
          "signature": "maps.onLeave(mapId: string, handler: function): Subscription",
          "description": "Calls handler() when the players leave a map they were on (back to the menu, or to another map). Same map ids as maps.onEnter.",
          "params": [
            {
              "name": "mapId",
              "type": "string",
              "optional": false,
              "default": null,
              "description": ""
            },
            {
              "name": "handler",
              "type": "function",
              "optional": false,
              "default": null,
              "description": ""
            }
          ],
          "returns": {
            "type": "Subscription",
            "description": ""
          },
          "permission": null,
          "sides": [
            "client",
            "server"
          ],
          "example": null,
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "resetWater",
          "fullName": "maps.resetWater",
          "signature": "maps.resetWater()",
          "description": "Undoes maps.setWater: the current map gets back the water its file declares.",
          "params": [],
          "returns": {
            "type": "nil",
            "description": ""
          },
          "permission": "world",
          "sides": [
            "server"
          ],
          "example": null,
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "setWater",
          "fullName": "maps.setWater",
          "signature": "maps.setWater(settings: boolean|table)",
          "description": "Adds or removes the sea on the current map for every player, until the map changes. Pass true or false, or { enabled, level } to also move the sea to a height (world Y, metres). Ships float, sails stop and splashes happen on the new water at once.",
          "params": [
            {
              "name": "settings",
              "type": "boolean|table",
              "optional": false,
              "default": null,
              "description": "true, false, or { enabled = boolean?, level = number? }"
            }
          ],
          "returns": {
            "type": "nil",
            "description": ""
          },
          "permission": "world",
          "sides": [
            "server"
          ],
          "example": "maps.setWater(false)                        -- drain the map\nmaps.setWater{ enabled = true, level = 4 }  -- flood it to Y 4",
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "spawnPoints",
          "fullName": "maps.spawnPoints",
          "signature": "maps.spawnPoints(): vec3[]",
          "description": "Where players start on the current mod map, or an empty list on one of the game's own maps.",
          "params": [],
          "returns": {
            "type": "vec3[]",
            "description": ""
          },
          "permission": null,
          "sides": [
            "client",
            "server"
          ],
          "example": null,
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "tryLoad",
          "fullName": "maps.tryLoad",
          "signature": "maps.tryLoad(mapId: string): boolean, string?",
          "description": "Like maps.load, but a refusal returns false and the reason instead of raising an error. Wrong arguments, side and permission errors still raise.",
          "params": [
            {
              "name": "mapId",
              "type": "string",
              "optional": false,
              "default": null,
              "description": ""
            }
          ],
          "returns": {
            "type": "boolean, string?",
            "description": "true and the result on success; false and the reason on a refusal."
          },
          "permission": "scenes",
          "sides": [
            "server"
          ],
          "example": "maps.load(\"theonaris.examples.crater-canyon:crater-canyon\")",
          "since": null,
          "deprecated": null,
          "tryOf": "load"
        },
        {
          "name": "tryResetWater",
          "fullName": "maps.tryResetWater",
          "signature": "maps.tryResetWater(): boolean, string?",
          "description": "Like maps.resetWater, but a refusal returns false and the reason instead of raising an error. Wrong arguments, side and permission errors still raise.",
          "params": [],
          "returns": {
            "type": "boolean, string?",
            "description": "true and the result on success; false and the reason on a refusal."
          },
          "permission": "world",
          "sides": [
            "server"
          ],
          "example": null,
          "since": null,
          "deprecated": null,
          "tryOf": "resetWater"
        },
        {
          "name": "trySetWater",
          "fullName": "maps.trySetWater",
          "signature": "maps.trySetWater(settings: boolean|table): boolean, string?",
          "description": "Like maps.setWater, but a refusal returns false and the reason instead of raising an error. Wrong arguments, side and permission errors still raise.",
          "params": [
            {
              "name": "settings",
              "type": "boolean|table",
              "optional": false,
              "default": null,
              "description": "true, false, or { enabled = boolean?, level = number? }"
            }
          ],
          "returns": {
            "type": "boolean, string?",
            "description": "true and the result on success; false and the reason on a refusal."
          },
          "permission": "world",
          "sides": [
            "server"
          ],
          "example": "maps.setWater(false)                        -- drain the map\nmaps.setWater{ enabled = true, level = 4 }  -- flood it to Y 4",
          "since": null,
          "deprecated": null,
          "tryOf": "setWater"
        },
        {
          "name": "water",
          "fullName": "maps.water",
          "signature": "maps.water(): any",
          "description": "The sea on the current map, as { enabled, level, script }: whether there is water, its height (world Y, metres), and whether a server script set it rather than the map. Maps choose their water in their file (\"water\").",
          "params": [],
          "returns": {
            "type": "any",
            "description": ""
          },
          "permission": null,
          "sides": [
            "client",
            "server"
          ],
          "example": "local w = maps.water()\nif w.enabled then log.info(\"sea level \" .. w.level) end",
          "since": null,
          "deprecated": null,
          "tryOf": null
        }
      ]
    },
    {
      "name": "mod",
      "description": "This mod: identity, lifecycle, exports for other mods, and the text and JSON files it ships with. Fields: mod.id, mod.name, mod.version, mod.side (\"client\" or \"server\"), mod.server, mod.client (booleans), mod.api.",
      "sides": [
        "client",
        "server"
      ],
      "provider": "theonaris.core",
      "since": "1.0",
      "permission": null,
      "availability": null,
      "functions": [
        {
          "name": "exists",
          "fullName": "mod.exists",
          "signature": "mod.exists(path: string): boolean",
          "description": "True when the mod contains the file.",
          "params": [
            {
              "name": "path",
              "type": "string",
              "optional": false,
              "default": null,
              "description": ""
            }
          ],
          "returns": {
            "type": "boolean",
            "description": ""
          },
          "permission": null,
          "sides": [
            "client",
            "server"
          ],
          "example": null,
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "export",
          "fullName": "mod.export",
          "signature": "mod.export(exports: table)",
          "description": "Publishes a table other mods can read with mods.get once they list this mod as a dependency.",
          "params": [
            {
              "name": "exports",
              "type": "table",
              "optional": false,
              "default": null,
              "description": ""
            }
          ],
          "returns": {
            "type": "nil",
            "description": ""
          },
          "permission": null,
          "sides": [
            "client",
            "server"
          ],
          "example": "mod.export({ version = 2, spin = function(speed) return speed * 2 end })",
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "has",
          "fullName": "mod.has",
          "signature": "mod.has(name: string): boolean",
          "description": "True when a module or function exists in this script, e.g. \"ui\", \"net.handle\" or \"building.onSelectionChanged\". API tables are strict — reading a name that does not exist raises an error — so feature tests use this instead of `if ui.something then`. Unavailable modules (ui on a server, net outside a session) are nil globals, so `if ui then` keeps working too.",
          "params": [
            {
              "name": "name",
              "type": "string",
              "optional": false,
              "default": null,
              "description": ""
            }
          ],
          "returns": {
            "type": "boolean",
            "description": ""
          },
          "permission": null,
          "sides": [
            "client",
            "server"
          ],
          "example": "if mod.has(\"building.onSelectionChanged\") then\n  building.onSelectionChanged(refresh)\nelse\n  timer.every(0.25, refresh)\nend",
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "hasPermission",
          "fullName": "mod.hasPermission",
          "signature": "mod.hasPermission(permission: string): boolean",
          "description": "Whether this mod holds a permission, e.g. \"ui.game\" or \"http:api.example.com\".",
          "params": [
            {
              "name": "permission",
              "type": "string",
              "optional": false,
              "default": null,
              "description": ""
            }
          ],
          "returns": {
            "type": "boolean",
            "description": ""
          },
          "permission": null,
          "sides": [
            "client",
            "server"
          ],
          "example": null,
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "isClient",
          "fullName": "mod.isClient",
          "signature": "mod.isClient(): boolean",
          "description": "True in client scripts. Same as the field mod.client.",
          "params": [],
          "returns": {
            "type": "boolean",
            "description": ""
          },
          "permission": null,
          "sides": [
            "client",
            "server"
          ],
          "example": null,
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "isServer",
          "fullName": "mod.isServer",
          "signature": "mod.isServer(): boolean",
          "description": "True in server scripts (including the host's own server). Same as the field mod.server.",
          "params": [],
          "returns": {
            "type": "boolean",
            "description": ""
          },
          "permission": null,
          "sides": [
            "client",
            "server"
          ],
          "example": null,
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "list",
          "fullName": "mod.list",
          "signature": "mod.list(pattern?: string): string[]",
          "description": "Lists the mod's files matching a pattern; * matches within a folder, ** across folders.",
          "params": [
            {
              "name": "pattern",
              "type": "string",
              "optional": true,
              "default": "**",
              "description": ""
            }
          ],
          "returns": {
            "type": "string[]",
            "description": ""
          },
          "permission": null,
          "sides": [
            "client",
            "server"
          ],
          "example": "for _, file in ipairs(mod.list(\"maps/*.json\")) do log.info(file) end",
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "onUnload",
          "fullName": "mod.onUnload",
          "signature": "mod.onUnload(handler: function)",
          "description": "Runs handler when the mod unloads — on reload, when disabled, or when leaving a server. Everything created through the API is removed automatically; use this for your own bookkeeping.",
          "params": [
            {
              "name": "handler",
              "type": "function",
              "optional": false,
              "default": null,
              "description": ""
            }
          ],
          "returns": {
            "type": "nil",
            "description": ""
          },
          "permission": null,
          "sides": [
            "client",
            "server"
          ],
          "example": "mod.onUnload(function() storage.set(\"lastRun\", time.unix()) end)",
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "readJson",
          "fullName": "mod.readJson",
          "signature": "mod.readJson(path: string): any",
          "description": "Reads and parses a JSON file from the mod.",
          "params": [
            {
              "name": "path",
              "type": "string",
              "optional": false,
              "default": null,
              "description": ""
            }
          ],
          "returns": {
            "type": "any",
            "description": ""
          },
          "permission": null,
          "sides": [
            "client",
            "server"
          ],
          "example": "local waves = mod.readJson(\"data/waves.json\")",
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "readText",
          "fullName": "mod.readText",
          "signature": "mod.readText(path: string): string",
          "description": "Reads a text file from the mod (.lua, .json, .txt, .md, .csv, .uxml, .uss).",
          "params": [
            {
              "name": "path",
              "type": "string",
              "optional": false,
              "default": null,
              "description": "Path inside the mod, e.g. \"data/names.txt\"."
            }
          ],
          "returns": {
            "type": "string",
            "description": "The file's text."
          },
          "permission": null,
          "sides": [
            "client",
            "server"
          ],
          "example": null,
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "whyUnavailable",
          "fullName": "mod.whyUnavailable",
          "signature": "mod.whyUnavailable(module: string): string?",
          "description": "Why a module is missing in this script, or nil when it is available (or never existed).",
          "params": [
            {
              "name": "module",
              "type": "string",
              "optional": false,
              "default": null,
              "description": ""
            }
          ],
          "returns": {
            "type": "string?",
            "description": ""
          },
          "permission": null,
          "sides": [
            "client",
            "server"
          ],
          "example": "if not ui then log.info(mod.whyUnavailable(\"ui\")) return end",
          "since": null,
          "deprecated": null,
          "tryOf": null
        }
      ]
    },
    {
      "name": "mod.settings",
      "description": "The settings declared in mod.json, with their defaults. \"user\" settings belong to each player and are changed from client scripts; \"server\" settings are changed from the server script and reach every player. Both sides read every setting.",
      "sides": [
        "client",
        "server"
      ],
      "provider": "theonaris.core",
      "since": "1.0",
      "permission": null,
      "availability": null,
      "functions": [
        {
          "name": "all",
          "fullName": "mod.settings.all",
          "signature": "mod.settings.all(): any",
          "description": "Every declared setting with its current value.",
          "params": [],
          "returns": {
            "type": "any",
            "description": "A table keyed by setting key."
          },
          "permission": null,
          "sides": [
            "client",
            "server"
          ],
          "example": null,
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "get",
          "fullName": "mod.settings.get",
          "signature": "mod.settings.get(key: string): any",
          "description": "The current value of a declared setting.",
          "params": [
            {
              "name": "key",
              "type": "string",
              "optional": false,
              "default": null,
              "description": ""
            }
          ],
          "returns": {
            "type": "any",
            "description": ""
          },
          "permission": null,
          "sides": [
            "client",
            "server"
          ],
          "example": "local volume = mod.settings.get(\"volume\")",
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "onChanged",
          "fullName": "mod.settings.onChanged",
          "signature": "mod.settings.onChanged(handler: function): Subscription",
          "description": "Calls handler(key, value) after any of this mod's settings changes.",
          "params": [
            {
              "name": "handler",
              "type": "function",
              "optional": false,
              "default": null,
              "description": ""
            }
          ],
          "returns": {
            "type": "Subscription",
            "description": ""
          },
          "permission": null,
          "sides": [
            "client",
            "server"
          ],
          "example": "mod.settings.onChanged(function(key, value) log.info(key, \"is now\", value) end)",
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "set",
          "fullName": "mod.settings.set",
          "signature": "mod.settings.set(key: string, value: any)",
          "description": "Changes a setting. User settings can be changed from client scripts; server settings from server scripts.",
          "params": [
            {
              "name": "key",
              "type": "string",
              "optional": false,
              "default": null,
              "description": ""
            },
            {
              "name": "value",
              "type": "any",
              "optional": false,
              "default": null,
              "description": ""
            }
          ],
          "returns": {
            "type": "nil",
            "description": ""
          },
          "permission": null,
          "sides": [
            "client",
            "server"
          ],
          "example": null,
          "since": null,
          "deprecated": null,
          "tryOf": null
        }
      ]
    },
    {
      "name": "mods",
      "description": "Other mods: what is installed and running, and the exports of mods this one depends on.",
      "sides": [
        "client",
        "server"
      ],
      "provider": "theonaris.core",
      "since": "1.0",
      "permission": null,
      "availability": null,
      "functions": [
        {
          "name": "get",
          "fullName": "mods.get",
          "signature": "mods.get(id: string): ModExports?",
          "description": "The table another mod published with mod.export, or nil when it is not running or exports nothing. The mod must be listed in this mod's dependencies or optionalDependencies. Its functions run inside that mod; arguments and results are copied.",
          "params": [
            {
              "name": "id",
              "type": "string",
              "optional": false,
              "default": null,
              "description": ""
            }
          ],
          "returns": {
            "type": "ModExports?",
            "description": ""
          },
          "permission": null,
          "sides": [
            "client",
            "server"
          ],
          "example": "local wheels = mods.get(\"someone.better-wheels\")\nif wheels then wheels.setGrip(1.4) end",
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "isRunning",
          "fullName": "mods.isRunning",
          "signature": "mods.isRunning(id: string): boolean",
          "description": "True when the mod is running on this side.",
          "params": [
            {
              "name": "id",
              "type": "string",
              "optional": false,
              "default": null,
              "description": ""
            }
          ],
          "returns": {
            "type": "boolean",
            "description": ""
          },
          "permission": null,
          "sides": [
            "client",
            "server"
          ],
          "example": null,
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "list",
          "fullName": "mods.list",
          "signature": "mods.list(): any",
          "description": "Every valid mod the game found.",
          "params": [],
          "returns": {
            "type": "any",
            "description": "Array of { id, name, version, running }."
          },
          "permission": null,
          "sides": [
            "client",
            "server"
          ],
          "example": null,
          "since": null,
          "deprecated": null,
          "tryOf": null
        }
      ]
    },
    {
      "name": "net",
      "description": "Messages between the client and server copies of your mod. Server handlers receive the sending Player first, then the data; client handlers receive the data. Data may be tables, strings, numbers, booleans, vec3/quat/color and Player objects. Messages from clients are rate-limited.",
      "sides": [
        "client",
        "server"
      ],
      "provider": "theonaris.core",
      "since": "1.0",
      "permission": null,
      "availability": "while a session is running (single player, hosting or connected), not in the main menu",
      "functions": [
        {
          "name": "broadcast",
          "fullName": "net.broadcast",
          "signature": "net.broadcast(channel: string, data?: any, reliable?: boolean, except?: Player)",
          "description": "Sends data to every player, optionally skipping one.",
          "params": [
            {
              "name": "channel",
              "type": "string",
              "optional": false,
              "default": null,
              "description": ""
            },
            {
              "name": "data",
              "type": "any",
              "optional": true,
              "default": null,
              "description": ""
            },
            {
              "name": "reliable",
              "type": "boolean",
              "optional": true,
              "default": true,
              "description": ""
            },
            {
              "name": "except",
              "type": "Player",
              "optional": true,
              "default": null,
              "description": ""
            }
          ],
          "returns": {
            "type": "nil",
            "description": ""
          },
          "permission": "net",
          "sides": [
            "server"
          ],
          "example": "net.broadcast(\"announce\", { text = \"Round starts!\" })",
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "handle",
          "fullName": "net.handle",
          "signature": "net.handle(channel: string, schema: table<string, string>?, handler: function, options?: table): Subscription",
          "description": "net.on with the checks every handler needs built in. The data must match schema (a table of field = type: \"string\", \"number\", \"integer\", \"boolean\", \"table\", \"vec3\", \"quat\", \"color\", \"Player\" or \"any\"; a trailing ? makes a field optional, [] makes it an array, e.g. \"string[]\"; nil schema = any data). Server: handler(player, data); a message that does not match, or that goes over options.rate messages per second per player, never reaches it — the sender gets a reply on options.deny (default \"denied\") with { reason, channel }. Returning false, reason from the handler sends the same reply. Client: handler(data); bad messages are logged and dropped.",
          "params": [
            {
              "name": "channel",
              "type": "string",
              "optional": false,
              "default": null,
              "description": ""
            },
            {
              "name": "schema",
              "type": "table<string, string>?",
              "optional": false,
              "default": null,
              "description": "Field = type, or nil for any data."
            },
            {
              "name": "handler",
              "type": "function",
              "optional": false,
              "default": null,
              "description": ""
            },
            {
              "name": "options",
              "type": "table",
              "optional": true,
              "default": null,
              "description": "{ rate = messages per second per player, burst = extra allowance (default rate), deny = reply channel }"
            }
          ],
          "returns": {
            "type": "Subscription",
            "description": ""
          },
          "permission": "net",
          "sides": [
            "client",
            "server"
          ],
          "example": "-- server.lua\nnet.handle(\"move\", { blocks = \"string[]\", offset = \"vec3\" }, function(player, data)\n  if #data.blocks > 64 then return false, \"Too many blocks.\" end\n  -- … do the move …\nend, { rate = 20 })",
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "isConnected",
          "fullName": "net.isConnected",
          "signature": "net.isConnected(): boolean",
          "description": "True while in a session (hosting or connected to a server).",
          "params": [],
          "returns": {
            "type": "boolean",
            "description": ""
          },
          "permission": null,
          "sides": [
            "client",
            "server"
          ],
          "example": null,
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "isHost",
          "fullName": "net.isHost",
          "signature": "net.isHost(): boolean",
          "description": "True when this game hosts the session (singleplayer, or hosting for friends).",
          "params": [],
          "returns": {
            "type": "boolean",
            "description": ""
          },
          "permission": null,
          "sides": [
            "client",
            "server"
          ],
          "example": null,
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "isServer",
          "fullName": "net.isServer",
          "signature": "net.isServer(): boolean",
          "description": "True in server scripts.",
          "params": [],
          "returns": {
            "type": "boolean",
            "description": ""
          },
          "permission": null,
          "sides": [
            "client",
            "server"
          ],
          "example": null,
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "on",
          "fullName": "net.on",
          "signature": "net.on(channel: string, handler: function): Subscription",
          "description": "Handles messages on a channel. Server: handler(player, data). Client: handler(data).",
          "params": [
            {
              "name": "channel",
              "type": "string",
              "optional": false,
              "default": null,
              "description": ""
            },
            {
              "name": "handler",
              "type": "function",
              "optional": false,
              "default": null,
              "description": ""
            }
          ],
          "returns": {
            "type": "Subscription",
            "description": ""
          },
          "permission": "net",
          "sides": [
            "client",
            "server"
          ],
          "example": "-- server.lua\nnet.on(\"ping\", function(player, data)\n  net.sendTo(player, \"pong\", { at = time.now() })\nend)",
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "send",
          "fullName": "net.send",
          "signature": "net.send(channel: string, data?: any, reliable?: boolean)",
          "description": "Sends data to the server copy of this mod.",
          "params": [
            {
              "name": "channel",
              "type": "string",
              "optional": false,
              "default": null,
              "description": ""
            },
            {
              "name": "data",
              "type": "any",
              "optional": true,
              "default": null,
              "description": ""
            },
            {
              "name": "reliable",
              "type": "boolean",
              "optional": true,
              "default": true,
              "description": "false for frequent, loss-tolerant updates."
            }
          ],
          "returns": {
            "type": "nil",
            "description": ""
          },
          "permission": "net",
          "sides": [
            "client"
          ],
          "example": "net.send(\"ping\", { hello = true })",
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "sendTo",
          "fullName": "net.sendTo",
          "signature": "net.sendTo(player: Player, channel: string, data?: any, reliable?: boolean)",
          "description": "Sends data to one player's copy of this mod.",
          "params": [
            {
              "name": "player",
              "type": "Player",
              "optional": false,
              "default": null,
              "description": ""
            },
            {
              "name": "channel",
              "type": "string",
              "optional": false,
              "default": null,
              "description": ""
            },
            {
              "name": "data",
              "type": "any",
              "optional": true,
              "default": null,
              "description": ""
            },
            {
              "name": "reliable",
              "type": "boolean",
              "optional": true,
              "default": true,
              "description": ""
            }
          ],
          "returns": {
            "type": "nil",
            "description": ""
          },
          "permission": "net",
          "sides": [
            "server"
          ],
          "example": null,
          "since": null,
          "deprecated": null,
          "tryOf": null
        }
      ]
    },
    {
      "name": "net.state",
      "description": "Values the server sets and every player receives automatically — including players who join later. Clients read; only the server writes.",
      "sides": [
        "client",
        "server"
      ],
      "provider": "theonaris.core",
      "since": "1.0",
      "permission": null,
      "availability": "while a session is running (single player, hosting or connected), not in the main menu",
      "functions": [
        {
          "name": "all",
          "fullName": "net.state.all",
          "signature": "net.state.all(): any",
          "description": "Every key and value.",
          "params": [],
          "returns": {
            "type": "any",
            "description": ""
          },
          "permission": null,
          "sides": [
            "client",
            "server"
          ],
          "example": null,
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "get",
          "fullName": "net.state.get",
          "signature": "net.state.get(key: string): any",
          "description": "The current value of a key, or nil.",
          "params": [
            {
              "name": "key",
              "type": "string",
              "optional": false,
              "default": null,
              "description": ""
            }
          ],
          "returns": {
            "type": "any",
            "description": ""
          },
          "permission": null,
          "sides": [
            "client",
            "server"
          ],
          "example": null,
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "onChanged",
          "fullName": "net.state.onChanged",
          "signature": "net.state.onChanged(handler: function): Subscription",
          "description": "Calls handler(key, value) whenever a value changes (on clients also once per key when the snapshot arrives).",
          "params": [
            {
              "name": "handler",
              "type": "function",
              "optional": false,
              "default": null,
              "description": ""
            }
          ],
          "returns": {
            "type": "Subscription",
            "description": ""
          },
          "permission": null,
          "sides": [
            "client",
            "server"
          ],
          "example": null,
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "set",
          "fullName": "net.state.set",
          "signature": "net.state.set(key: string, value: any)",
          "description": "Sets a replicated value; nil removes it.",
          "params": [
            {
              "name": "key",
              "type": "string",
              "optional": false,
              "default": null,
              "description": ""
            },
            {
              "name": "value",
              "type": "any",
              "optional": false,
              "default": null,
              "description": ""
            }
          ],
          "returns": {
            "type": "nil",
            "description": ""
          },
          "permission": "net",
          "sides": [
            "server"
          ],
          "example": "net.state.set(\"round\", { number = 2, endsAt = time.unix() + 120 })",
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "watch",
          "fullName": "net.state.watch",
          "signature": "net.state.watch(key: string, handler: function): Subscription",
          "description": "Calls handler(value) whenever one key changes.",
          "params": [
            {
              "name": "key",
              "type": "string",
              "optional": false,
              "default": null,
              "description": ""
            },
            {
              "name": "handler",
              "type": "function",
              "optional": false,
              "default": null,
              "description": ""
            }
          ],
          "returns": {
            "type": "Subscription",
            "description": ""
          },
          "permission": null,
          "sides": [
            "client",
            "server"
          ],
          "example": "net.state.watch(\"round\", function(round) showRound(round.number) end)",
          "since": null,
          "deprecated": null,
          "tryOf": null
        }
      ]
    },
    {
      "name": "notify",
      "description": "Show the player a short message, the same way the game does. Needs the \"ui\" permission.",
      "sides": [
        "client"
      ],
      "provider": "theonaris.game",
      "since": "1.0",
      "permission": "ui",
      "availability": null,
      "functions": [
        {
          "name": "message",
          "fullName": "notify.message",
          "signature": "notify.message(message: string)",
          "description": "Shows a message the player has to dismiss. Use sparingly.",
          "params": [
            {
              "name": "message",
              "type": "string",
              "optional": false,
              "default": null,
              "description": ""
            }
          ],
          "returns": {
            "type": "nil",
            "description": ""
          },
          "permission": "ui",
          "sides": [
            "client"
          ],
          "example": "notify.message(\"The race starts in 10 seconds!\")",
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "toast",
          "fullName": "notify.toast",
          "signature": "notify.toast(message: string)",
          "description": "Shows a short message in the corner that goes away by itself.",
          "params": [
            {
              "name": "message",
              "type": "string",
              "optional": false,
              "default": null,
              "description": ""
            }
          ],
          "returns": {
            "type": "nil",
            "description": ""
          },
          "permission": "ui",
          "sides": [
            "client"
          ],
          "example": "notify.toast(\"Teleported everyone to the host\")",
          "since": null,
          "deprecated": null,
          "tryOf": null
        }
      ]
    },
    {
      "name": "planets",
      "description": "The planets of the current map: declare a map's planet system while your scripts load, then ask about gravity, air and weather. Changing the weather is server-only.",
      "sides": [
        "client",
        "server"
      ],
      "provider": "theonaris.planets",
      "since": "1.0",
      "permission": null,
      "availability": null,
      "functions": [
        {
          "name": "airAt",
          "fullName": "planets.airAt",
          "signature": "planets.airAt(position: vec3): number",
          "description": "Air density at a position (absolute), kg/m³: 1.225 at Earth's sea level, 0 in space.",
          "params": [
            {
              "name": "position",
              "type": "vec3",
              "optional": false,
              "default": null,
              "description": ""
            }
          ],
          "returns": {
            "type": "number",
            "description": ""
          },
          "permission": null,
          "sides": [
            "client",
            "server"
          ],
          "example": null,
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "define",
          "fullName": "planets.define",
          "signature": "planets.define(map: string, body: any)",
          "description": "Adds one planet to a map's system (the map file's, or the one planets.system set), with the fields of a \"bodies\" entry. Load phase only, like planets.system.",
          "params": [
            {
              "name": "map",
              "type": "string",
              "optional": false,
              "default": null,
              "description": ""
            },
            {
              "name": "body",
              "type": "any",
              "optional": false,
              "default": null,
              "description": ""
            }
          ],
          "returns": {
            "type": "nil",
            "description": ""
          },
          "permission": null,
          "sides": [
            "client",
            "server"
          ],
          "example": "planets.define(\"twin-worlds\", { name = \"Cinder\", radius = 8000, position = { 60000, -8000, 0 }, atmosphere = false })",
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "gravityAt",
          "fullName": "planets.gravityAt",
          "signature": "planets.gravityAt(position: vec3): vec3",
          "description": "Gravity at a position (absolute), m/s², pointing down. Sums every planet in reach; flat maps return the game's flat gravity.",
          "params": [
            {
              "name": "position",
              "type": "vec3",
              "optional": false,
              "default": null,
              "description": ""
            }
          ],
          "returns": {
            "type": "vec3",
            "description": ""
          },
          "permission": null,
          "sides": [
            "client",
            "server"
          ],
          "example": "local g = planets.gravityAt(maps.spawnPoints()[1])\nlog.info(\"down: \" .. tostring(g))",
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "list",
          "fullName": "planets.list",
          "signature": "planets.list(): any",
          "description": "Every planet of the current map as { name, radius, position, gravity, gravityReach, atmosphereHeight, airDensity } (absolute positions, metres, m/s², kg/m³).",
          "params": [],
          "returns": {
            "type": "any",
            "description": ""
          },
          "permission": null,
          "sides": [
            "client",
            "server"
          ],
          "example": "for _, p in ipairs(planets.list()) do log.info(p.name .. \" \" .. p.radius) end",
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "nearest",
          "fullName": "planets.nearest",
          "signature": "planets.nearest(position: vec3): table?",
          "description": "The planet whose surface is nearest a position (absolute), as planets.list describes it, or nil on a map without planets.",
          "params": [
            {
              "name": "position",
              "type": "vec3",
              "optional": false,
              "default": null,
              "description": ""
            }
          ],
          "returns": {
            "type": "table?",
            "description": ""
          },
          "permission": null,
          "sides": [
            "client",
            "server"
          ],
          "example": null,
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "resetWeather",
          "fullName": "planets.resetWeather",
          "signature": "planets.resetWeather()",
          "description": "Puts the weather back to what the server had before the map (or planets.setWeather) changed it.",
          "params": [],
          "returns": {
            "type": "nil",
            "description": ""
          },
          "permission": "world",
          "sides": [
            "server"
          ],
          "example": null,
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "setWeather",
          "fullName": "planets.setWeather",
          "signature": "planets.setWeather(weather: any)",
          "description": "Sets the world's weather for everyone: a preset (\"temperate\", \"arid\", \"stormy\", \"frozen\", \"clear\") or { preset, …fields } with the map file's weather fields (stormCount, wetness, temperatureOffset, mode, …). Put back when the map is left.",
          "params": [
            {
              "name": "weather",
              "type": "any",
              "optional": false,
              "default": null,
              "description": ""
            }
          ],
          "returns": {
            "type": "nil",
            "description": ""
          },
          "permission": "world",
          "sides": [
            "server"
          ],
          "example": "planets.setWeather({ preset = \"frozen\", stormCount = 2 })",
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "system",
          "fullName": "planets.system",
          "signature": "planets.system(map: string, spec: any)",
          "description": "Sets the planet system of one of this mod's maps, exactly like the map file's \"system\" section (same fields, same checks). Only while the mod's scripts first run (the load phase): the world must be decided before anyone builds it. Call it from a SHARED script (mod.json entry.shared) so the server and every player build the same planets — a server whose system differs from a player's disconnects that player.",
          "params": [
            {
              "name": "map",
              "type": "string",
              "optional": false,
              "default": null,
              "description": ""
            },
            {
              "name": "spec",
              "type": "any",
              "optional": false,
              "default": null,
              "description": ""
            }
          ],
          "returns": {
            "type": "nil",
            "description": ""
          },
          "permission": null,
          "sides": [
            "client",
            "server"
          ],
          "example": "planets.system(\"twin-worlds\", {\n  weather = \"stormy\",\n  bodies = {\n    { name = \"Ember\", radius = 20000, position = { 0, -20000, 0 } },\n  },\n})",
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "trySetWeather",
          "fullName": "planets.trySetWeather",
          "signature": "planets.trySetWeather(weather: any): boolean, string?",
          "description": "Like planets.setWeather, but a refusal returns false and the reason instead of raising an error. Wrong arguments, side and permission errors still raise.",
          "params": [
            {
              "name": "weather",
              "type": "any",
              "optional": false,
              "default": null,
              "description": ""
            }
          ],
          "returns": {
            "type": "boolean, string?",
            "description": "true and the result on success; false and the reason on a refusal."
          },
          "permission": "world",
          "sides": [
            "server"
          ],
          "example": "planets.setWeather({ preset = \"frozen\", stormCount = 2 })",
          "since": null,
          "deprecated": null,
          "tryOf": "setWeather"
        },
        {
          "name": "weather",
          "fullName": "planets.weather",
          "signature": "planets.weather(where: any): table?",
          "description": "The weather on a planet (by name, at its weather focus — where the players are) or at a position, as { planet, rain, snow, temperature, cloud, wind } (mm/h, °C, 0..1 cover, m/s). nil where there is no weather (no air, weather off).",
          "params": [
            {
              "name": "where",
              "type": "any",
              "optional": false,
              "default": null,
              "description": ""
            }
          ],
          "returns": {
            "type": "table?",
            "description": ""
          },
          "permission": null,
          "sides": [
            "client",
            "server"
          ],
          "example": "local w = planets.weather(\"Ember\")\nif w and w.rain > 2 then log.info(\"it is pouring\") end",
          "since": null,
          "deprecated": null,
          "tryOf": null
        }
      ]
    },
    {
      "name": "players",
      "description": "Who is in the session. Also raises the game events \"player.joined\" and \"player.left\" with the Player.",
      "sides": [
        "client",
        "server"
      ],
      "provider": "theonaris.core",
      "since": "1.0",
      "permission": null,
      "availability": "while a session is running (single player, hosting or connected), not in the main menu",
      "functions": [
        {
          "name": "all",
          "fullName": "players.all",
          "signature": "players.all(): Player[]",
          "description": "Every player, host first.",
          "params": [],
          "returns": {
            "type": "Player[]",
            "description": ""
          },
          "permission": "players",
          "sides": [
            "client",
            "server"
          ],
          "example": null,
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "count",
          "fullName": "players.count",
          "signature": "players.count(): integer",
          "description": "Number of players in the session.",
          "params": [],
          "returns": {
            "type": "integer",
            "description": ""
          },
          "permission": "players",
          "sides": [
            "client",
            "server"
          ],
          "example": null,
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "get",
          "fullName": "players.get",
          "signature": "players.get(id: integer): Player?",
          "description": "The player with an id, or nil.",
          "params": [
            {
              "name": "id",
              "type": "integer",
              "optional": false,
              "default": null,
              "description": ""
            }
          ],
          "returns": {
            "type": "Player?",
            "description": ""
          },
          "permission": "players",
          "sides": [
            "client",
            "server"
          ],
          "example": null,
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "host",
          "fullName": "players.host",
          "signature": "players.host(): Player?",
          "description": "The host, or nil on a dedicated server.",
          "params": [],
          "returns": {
            "type": "Player?",
            "description": ""
          },
          "permission": "players",
          "sides": [
            "client",
            "server"
          ],
          "example": null,
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "me",
          "fullName": "players.me",
          "signature": "players.me(): Player?",
          "description": "This machine's player, or nil on a dedicated server.",
          "params": [],
          "returns": {
            "type": "Player?",
            "description": ""
          },
          "permission": "players",
          "sides": [
            "client",
            "server"
          ],
          "example": null,
          "since": null,
          "deprecated": null,
          "tryOf": null
        }
      ]
    },
    {
      "name": "storage",
      "description": "Persistent key/value data that survives restarts, saved automatically every 30 seconds and when the mod unloads. Client scripts and server scripts each have their own storage; the quota is 4 MB per side.",
      "sides": [
        "client",
        "server"
      ],
      "provider": "theonaris.core",
      "since": "1.0",
      "permission": null,
      "availability": null,
      "functions": [
        {
          "name": "clear",
          "fullName": "storage.clear",
          "signature": "storage.clear()",
          "description": "Removes every key.",
          "params": [],
          "returns": {
            "type": "nil",
            "description": ""
          },
          "permission": null,
          "sides": [
            "client",
            "server"
          ],
          "example": null,
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "get",
          "fullName": "storage.get",
          "signature": "storage.get(key: string, fallback?: any): any",
          "description": "The stored value, or fallback when the key is not set.",
          "params": [
            {
              "name": "key",
              "type": "string",
              "optional": false,
              "default": null,
              "description": ""
            },
            {
              "name": "fallback",
              "type": "any",
              "optional": true,
              "default": null,
              "description": ""
            }
          ],
          "returns": {
            "type": "any",
            "description": ""
          },
          "permission": null,
          "sides": [
            "client",
            "server"
          ],
          "example": "local best = storage.get(\"bestTime\", 999)",
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "has",
          "fullName": "storage.has",
          "signature": "storage.has(key: string): boolean",
          "description": "True when the key is set.",
          "params": [
            {
              "name": "key",
              "type": "string",
              "optional": false,
              "default": null,
              "description": ""
            }
          ],
          "returns": {
            "type": "boolean",
            "description": ""
          },
          "permission": null,
          "sides": [
            "client",
            "server"
          ],
          "example": null,
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "keys",
          "fullName": "storage.keys",
          "signature": "storage.keys(): string[]",
          "description": "Every stored key.",
          "params": [],
          "returns": {
            "type": "string[]",
            "description": ""
          },
          "permission": null,
          "sides": [
            "client",
            "server"
          ],
          "example": null,
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "remove",
          "fullName": "storage.remove",
          "signature": "storage.remove(key: string)",
          "description": "Removes a key.",
          "params": [
            {
              "name": "key",
              "type": "string",
              "optional": false,
              "default": null,
              "description": ""
            }
          ],
          "returns": {
            "type": "nil",
            "description": ""
          },
          "permission": null,
          "sides": [
            "client",
            "server"
          ],
          "example": null,
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "save",
          "fullName": "storage.save",
          "signature": "storage.save()",
          "description": "Writes pending changes to disk immediately.",
          "params": [],
          "returns": {
            "type": "nil",
            "description": ""
          },
          "permission": null,
          "sides": [
            "client",
            "server"
          ],
          "example": null,
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "set",
          "fullName": "storage.set",
          "signature": "storage.set(key: string, value: any)",
          "description": "Stores a value (tables, strings, numbers, booleans, vec3/quat/color). Setting nil removes the key.",
          "params": [
            {
              "name": "key",
              "type": "string",
              "optional": false,
              "default": null,
              "description": ""
            },
            {
              "name": "value",
              "type": "any",
              "optional": false,
              "default": null,
              "description": ""
            }
          ],
          "returns": {
            "type": "nil",
            "description": ""
          },
          "permission": null,
          "sides": [
            "client",
            "server"
          ],
          "example": "storage.set(\"bestTime\", 42.5)",
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "usage",
          "fullName": "storage.usage",
          "signature": "storage.usage(): ...",
          "description": "How much of the quota is used.",
          "params": [],
          "returns": {
            "type": "...",
            "description": "bytes used, quota in bytes"
          },
          "permission": null,
          "sides": [
            "client",
            "server"
          ],
          "example": null,
          "since": null,
          "deprecated": null,
          "tryOf": null
        }
      ]
    },
    {
      "name": "task",
      "description": "Work spread over many frames. A task is paused automatically when it has run long enough for one frame, and task.wait pauses it for a while — the game keeps running either way.",
      "sides": [
        "client",
        "server"
      ],
      "provider": "theonaris.core",
      "since": "1.0",
      "permission": null,
      "availability": null,
      "functions": [
        {
          "name": "spawn",
          "fullName": "task.spawn",
          "signature": "task.spawn(fn: function, ...: any): Task",
          "description": "Starts fn as a background task, passing any extra arguments.",
          "params": [
            {
              "name": "fn",
              "type": "function",
              "optional": false,
              "default": null,
              "description": ""
            },
            {
              "name": "...",
              "type": "any",
              "optional": true,
              "default": null,
              "description": ""
            }
          ],
          "returns": {
            "type": "Task",
            "description": ""
          },
          "permission": null,
          "sides": [
            "client",
            "server"
          ],
          "example": "task.spawn(function()\n  for i = 1, 100 do\n    spawnWave(i)\n    task.wait(1)\n  end\nend)",
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "wait",
          "fullName": "task.wait",
          "signature": "task.wait(seconds?: number): any",
          "description": "Pauses the current task for a number of seconds; 0 waits for the next frame. Only valid inside a task.",
          "params": [
            {
              "name": "seconds",
              "type": "number",
              "optional": true,
              "default": 0.0,
              "description": ""
            }
          ],
          "returns": {
            "type": "any",
            "description": ""
          },
          "permission": null,
          "sides": [
            "client",
            "server"
          ],
          "example": null,
          "since": null,
          "deprecated": null,
          "tryOf": null
        }
      ]
    },
    {
      "name": "time",
      "description": "Clocks. For in-game timing use time.now and time.delta; they are real time and keep running while the game is paused.",
      "sides": [
        "client",
        "server"
      ],
      "provider": "theonaris.core",
      "since": "1.0",
      "permission": null,
      "availability": null,
      "functions": [
        {
          "name": "delta",
          "fullName": "time.delta",
          "signature": "time.delta(): number",
          "description": "Seconds the previous frame took.",
          "params": [],
          "returns": {
            "type": "number",
            "description": ""
          },
          "permission": null,
          "sides": [
            "client",
            "server"
          ],
          "example": null,
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "frame",
          "fullName": "time.frame",
          "signature": "time.frame(): integer",
          "description": "Frames rendered since the game started.",
          "params": [],
          "returns": {
            "type": "integer",
            "description": ""
          },
          "permission": null,
          "sides": [
            "client",
            "server"
          ],
          "example": null,
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "now",
          "fullName": "time.now",
          "signature": "time.now(): number",
          "description": "Seconds since the game started.",
          "params": [],
          "returns": {
            "type": "number",
            "description": ""
          },
          "permission": null,
          "sides": [
            "client",
            "server"
          ],
          "example": null,
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "unix",
          "fullName": "time.unix",
          "signature": "time.unix(): number",
          "description": "The current UTC time as Unix seconds, with a fractional part.",
          "params": [],
          "returns": {
            "type": "number",
            "description": ""
          },
          "permission": null,
          "sides": [
            "client",
            "server"
          ],
          "example": null,
          "since": null,
          "deprecated": null,
          "tryOf": null
        }
      ]
    },
    {
      "name": "timer",
      "description": "Run a function later, or repeatedly.",
      "sides": [
        "client",
        "server"
      ],
      "provider": "theonaris.core",
      "since": "1.0",
      "permission": null,
      "availability": null,
      "functions": [
        {
          "name": "after",
          "fullName": "timer.after",
          "signature": "timer.after(seconds: number, fn: function): Timer",
          "description": "Calls fn once, after a delay in seconds.",
          "params": [
            {
              "name": "seconds",
              "type": "number",
              "optional": false,
              "default": null,
              "description": ""
            },
            {
              "name": "fn",
              "type": "function",
              "optional": false,
              "default": null,
              "description": ""
            }
          ],
          "returns": {
            "type": "Timer",
            "description": ""
          },
          "permission": null,
          "sides": [
            "client",
            "server"
          ],
          "example": "timer.after(2, function() log.info(\"two seconds later\") end)",
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "every",
          "fullName": "timer.every",
          "signature": "timer.every(seconds: number, fn: function, times?: integer): Timer",
          "description": "Calls fn every interval seconds; pass times to stop after that many calls. An interval of 0 runs every frame.",
          "params": [
            {
              "name": "seconds",
              "type": "number",
              "optional": false,
              "default": null,
              "description": ""
            },
            {
              "name": "fn",
              "type": "function",
              "optional": false,
              "default": null,
              "description": ""
            },
            {
              "name": "times",
              "type": "integer",
              "optional": true,
              "default": -1,
              "description": ""
            }
          ],
          "returns": {
            "type": "Timer",
            "description": ""
          },
          "permission": null,
          "sides": [
            "client",
            "server"
          ],
          "example": "local blink = timer.every(0.5, function() lamp:toggle() end)\n-- later: blink:cancel()",
          "since": null,
          "deprecated": null,
          "tryOf": null
        }
      ]
    },
    {
      "name": "ui",
      "description": "Windows, panels and buttons — both your own and the game's. Changing the game's own screens needs the \"ui.game\" permission, and everything you change is put back when your mod stops.",
      "sides": [
        "client"
      ],
      "provider": "theonaris.engine",
      "since": "1.0",
      "permission": null,
      "availability": "in client scripts once the game has an interface (not on dedicated servers)",
      "functions": [
        {
          "name": "element",
          "fullName": "ui.element",
          "signature": "ui.element(kind: string, options?: any): UiElement",
          "description": "Creates a single element. Options are the same attributes a .uxml file uses.",
          "params": [
            {
              "name": "kind",
              "type": "string",
              "optional": false,
              "default": null,
              "description": ""
            },
            {
              "name": "options",
              "type": "any",
              "optional": true,
              "default": null,
              "description": ""
            }
          ],
          "returns": {
            "type": "UiElement",
            "description": ""
          },
          "permission": null,
          "sides": [
            "client"
          ],
          "example": "local b = ui.element(\"Button\", { text = \"Go\", tooltip = \"Start the engine\" })",
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "find",
          "fullName": "ui.find",
          "signature": "ui.find(screen: string, selector: string): UiElement?",
          "description": "Finds a part of one of the game's screens, or nil. Needs the \"ui.game\" permission to change what it returns.",
          "params": [
            {
              "name": "screen",
              "type": "string",
              "optional": false,
              "default": null,
              "description": ""
            },
            {
              "name": "selector",
              "type": "string",
              "optional": false,
              "default": null,
              "description": ""
            }
          ],
          "returns": {
            "type": "UiElement?",
            "description": ""
          },
          "permission": null,
          "sides": [
            "client"
          ],
          "example": "local play = ui.find(\"main-menu\", \"#play-button\")\nif play then play:setText(\"Play (modded)\") end",
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "findAll",
          "fullName": "ui.findAll",
          "signature": "ui.findAll(screen: string, selector: string, limit?: integer): UiElement[]",
          "description": "Every part of one of the game's screens matching a selector.",
          "params": [
            {
              "name": "screen",
              "type": "string",
              "optional": false,
              "default": null,
              "description": ""
            },
            {
              "name": "selector",
              "type": "string",
              "optional": false,
              "default": null,
              "description": ""
            },
            {
              "name": "limit",
              "type": "integer",
              "optional": true,
              "default": 64,
              "description": ""
            }
          ],
          "returns": {
            "type": "UiElement[]",
            "description": ""
          },
          "permission": null,
          "sides": [
            "client"
          ],
          "example": null,
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "kinds",
          "fullName": "ui.kinds",
          "signature": "ui.kinds(): string[]",
          "description": "The kinds of element you can create.",
          "params": [],
          "returns": {
            "type": "string[]",
            "description": ""
          },
          "permission": null,
          "sides": [
            "client"
          ],
          "example": null,
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "load",
          "fullName": "ui.load",
          "signature": "ui.load(path: string): UiElement",
          "description": "Builds the elements described by one of your .uxml files and returns the root. It is not on screen until you add it somewhere.",
          "params": [
            {
              "name": "path",
              "type": "string",
              "optional": false,
              "default": null,
              "description": ""
            }
          ],
          "returns": {
            "type": "UiElement",
            "description": ""
          },
          "permission": null,
          "sides": [
            "client"
          ],
          "example": "local tree = ui.load(\"ui/thrusters.uxml\")\nui.panel():add(tree)",
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "panel",
          "fullName": "ui.panel",
          "signature": "ui.panel(options?: table): UiElement",
          "description": "Creates a panel of your own on top of the game and returns it.",
          "params": [
            {
              "name": "options",
              "type": "table",
              "optional": true,
              "default": null,
              "description": "{ anchor = \"top-left\"|\"top\"|\"top-right\"|\"left\"|\"center\"|\"right\"|\"bottom-left\"|\"bottom\"|\"bottom-right\", margin, width, height, padding = number, name, class = string, style = table }"
            }
          ],
          "returns": {
            "type": "UiElement",
            "description": ""
          },
          "permission": null,
          "sides": [
            "client"
          ],
          "example": "local panel = ui.panel{ anchor = \"top-right\", width = 320, padding = 12 }\npanel:addNew(\"Label\", { text = \"Hello\" })",
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "screen",
          "fullName": "ui.screen",
          "signature": "ui.screen(screen: string): UiElement?",
          "description": "The root of one of the game's screens, so you can add to it.",
          "params": [
            {
              "name": "screen",
              "type": "string",
              "optional": false,
              "default": null,
              "description": ""
            }
          ],
          "returns": {
            "type": "UiElement?",
            "description": ""
          },
          "permission": null,
          "sides": [
            "client"
          ],
          "example": null,
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "screens",
          "fullName": "ui.screens",
          "signature": "ui.screens(): any",
          "description": "The game's screens a mod may change, and whether each is open right now.",
          "params": [],
          "returns": {
            "type": "any",
            "description": ""
          },
          "permission": null,
          "sides": [
            "client"
          ],
          "example": "for _, s in ipairs(ui.screens()) do log.info(s.id, s.open) end",
          "since": null,
          "deprecated": null,
          "tryOf": null
        }
      ]
    },
    {
      "name": "video",
      "description": "Play video files your mod ships with, on a panel or on an object in the world. Needs the \"video\" permission.",
      "sides": [
        "client"
      ],
      "provider": "theonaris.engine",
      "since": "1.0",
      "permission": null,
      "availability": null,
      "functions": [
        {
          "name": "onElement",
          "fullName": "video.onElement",
          "signature": "video.onElement(path: string, element: UiElement, options?: any): Video",
          "description": "Plays a video on an interface element; it fills the element's background.",
          "params": [
            {
              "name": "path",
              "type": "string",
              "optional": false,
              "default": null,
              "description": ""
            },
            {
              "name": "element",
              "type": "UiElement",
              "optional": false,
              "default": null,
              "description": ""
            },
            {
              "name": "options",
              "type": "any",
              "optional": true,
              "default": null,
              "description": ""
            }
          ],
          "returns": {
            "type": "Video",
            "description": ""
          },
          "permission": "video",
          "sides": [
            "client"
          ],
          "example": "local screen = panel:addNew(\"VisualElement\", { style = { width = \"480px\", height = \"270px\" } })\nlocal intro = video.onElement(\"video/intro.mp4\", screen, { loop = true })",
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "onObject",
          "fullName": "video.onObject",
          "signature": "video.onObject(path: string, target: Object, options?: any): Video",
          "description": "Plays a video on one of your objects, replacing its surface picture.",
          "params": [
            {
              "name": "path",
              "type": "string",
              "optional": false,
              "default": null,
              "description": ""
            },
            {
              "name": "target",
              "type": "Object",
              "optional": false,
              "default": null,
              "description": ""
            },
            {
              "name": "options",
              "type": "any",
              "optional": true,
              "default": null,
              "description": ""
            }
          ],
          "returns": {
            "type": "Video",
            "description": ""
          },
          "permission": "video",
          "sides": [
            "client"
          ],
          "example": "local tv = world.shape(\"quad\", { position = vec3(0, 2, 5), scale = vec3(3.2, 1.8, 1) })\nvideo.onObject(\"video/loop.webm\", tv, { loop = true })",
          "since": null,
          "deprecated": null,
          "tryOf": null
        }
      ]
    },
    {
      "name": "world",
      "description": "Put your own objects in the world, and ask about what is there. Needs the \"world\" permission.",
      "sides": [
        "client"
      ],
      "provider": "theonaris.engine",
      "since": "1.0",
      "permission": null,
      "availability": "in client scripts while the game has a world",
      "functions": [
        {
          "name": "camera",
          "fullName": "world.camera",
          "signature": "world.camera(): table?",
          "description": "Where the camera is and which way it looks.",
          "params": [],
          "returns": {
            "type": "table?",
            "description": ""
          },
          "permission": null,
          "sides": [
            "client"
          ],
          "example": null,
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "empty",
          "fullName": "world.empty",
          "signature": "world.empty(name?: string, options?: any): Object",
          "description": "Creates an empty object, to attach lights or sounds to, or to follow something.",
          "params": [
            {
              "name": "name",
              "type": "string",
              "optional": true,
              "default": "object",
              "description": ""
            },
            {
              "name": "options",
              "type": "any",
              "optional": true,
              "default": null,
              "description": ""
            }
          ],
          "returns": {
            "type": "Object",
            "description": ""
          },
          "permission": null,
          "sides": [
            "client"
          ],
          "example": "local marker = world.empty(\"host-marker\")",
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "gravity",
          "fullName": "world.gravity",
          "signature": "world.gravity(): vec3",
          "description": "How strong gravity is, in metres per second squared.",
          "params": [],
          "returns": {
            "type": "vec3",
            "description": ""
          },
          "permission": null,
          "sides": [
            "client"
          ],
          "example": null,
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "me",
          "fullName": "world.me",
          "signature": "world.me(): vec3?",
          "description": "Where the player you are is standing, or nil.",
          "params": [],
          "returns": {
            "type": "vec3?",
            "description": ""
          },
          "permission": null,
          "sides": [
            "client"
          ],
          "example": null,
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "raycast",
          "fullName": "world.raycast",
          "signature": "world.raycast(origin: vec3, direction: vec3, distance?: number): table?",
          "description": "Fires a ray and returns what it hit, or nil. Distance is in metres.",
          "params": [
            {
              "name": "origin",
              "type": "vec3",
              "optional": false,
              "default": null,
              "description": ""
            },
            {
              "name": "direction",
              "type": "vec3",
              "optional": false,
              "default": null,
              "description": ""
            },
            {
              "name": "distance",
              "type": "number",
              "optional": true,
              "default": 100.0,
              "description": ""
            }
          ],
          "returns": {
            "type": "table?",
            "description": ""
          },
          "permission": null,
          "sides": [
            "client"
          ],
          "example": "local hit = world.raycast(cam.position, cam.forward, 50)\nif hit then log.info(\"hit at\", hit.point) end",
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "shape",
          "fullName": "world.shape",
          "signature": "world.shape(shape: string, options?: any): Object",
          "description": "Creates a simple shape without needing a model file: \"cube\", \"sphere\", \"capsule\", \"cylinder\" or \"quad\".",
          "params": [
            {
              "name": "shape",
              "type": "string",
              "optional": false,
              "default": null,
              "description": ""
            },
            {
              "name": "options",
              "type": "any",
              "optional": true,
              "default": null,
              "description": ""
            }
          ],
          "returns": {
            "type": "Object",
            "description": ""
          },
          "permission": null,
          "sides": [
            "client"
          ],
          "example": "local marker = world.shape(\"sphere\", { position = vec3(0, 2, 0), color = color(\"#ff4040\") })",
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "spawn",
          "fullName": "world.spawn",
          "signature": "world.spawn(modelPath: string, options?: any): Object",
          "description": "Puts one of your models in the world.",
          "params": [
            {
              "name": "modelPath",
              "type": "string",
              "optional": false,
              "default": null,
              "description": ""
            },
            {
              "name": "options",
              "type": "any",
              "optional": true,
              "default": null,
              "description": ""
            }
          ],
          "returns": {
            "type": "Object",
            "description": ""
          },
          "permission": null,
          "sides": [
            "client"
          ],
          "example": "local ball = world.spawn(\"models/sphere.glb\", { position = vec3(0, 3, 0), scale = vec3(0.5, 0.5, 0.5) })",
          "since": null,
          "deprecated": null,
          "tryOf": null
        }
      ]
    }
  ],
  "handles": [
    {
      "name": "Block",
      "description": "A block in a creation.",
      "methods": [
        {
          "name": "get",
          "fullName": "Block:get",
          "signature": "Block:get(name: string): number|boolean?",
          "description": "One setting's value, or nil.",
          "params": [
            {
              "name": "name",
              "type": "string",
              "optional": false,
              "default": null,
              "description": ""
            }
          ],
          "returns": {
            "type": "number|boolean?",
            "description": ""
          },
          "permission": null,
          "sides": [
            "client",
            "server"
          ],
          "example": null,
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "push",
          "fullName": "Block:push",
          "signature": "Block:push(force: vec3, impulse?: boolean)",
          "description": "Pushes the moving part this block is on. Server scripts only; the creation must be simulating.",
          "params": [
            {
              "name": "force",
              "type": "vec3",
              "optional": false,
              "default": null,
              "description": ""
            },
            {
              "name": "impulse",
              "type": "boolean",
              "optional": true,
              "default": false,
              "description": ""
            }
          ],
          "returns": {
            "type": "nil",
            "description": ""
          },
          "permission": "building.physics",
          "sides": [
            "server"
          ],
          "example": "block:push(vec3(0, 9.81 * mass, 0))",
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "set",
          "fullName": "Block:set",
          "signature": "Block:set(name: string, value: any)",
          "description": "Changes one of the block's settings, exactly as its panel would. Client scripts, on creations you own; the server checks both.",
          "params": [
            {
              "name": "name",
              "type": "string",
              "optional": false,
              "default": null,
              "description": ""
            },
            {
              "name": "value",
              "type": "any",
              "optional": false,
              "default": null,
              "description": ""
            }
          ],
          "returns": {
            "type": "nil",
            "description": ""
          },
          "permission": "building.edit",
          "sides": [
            "client"
          ],
          "example": "for _, b in ipairs(building.selection()) do\n  b:set(\"Force\", 2500000)\nend",
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "settings",
          "fullName": "Block:settings",
          "signature": "Block:settings(): table?",
          "description": "The block's mechanism settings as { name = { value, min, max } }, or nil when it has none.",
          "params": [],
          "returns": {
            "type": "table?",
            "description": ""
          },
          "permission": null,
          "sides": [
            "client",
            "server"
          ],
          "example": null,
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "trySet",
          "fullName": "Block:trySet",
          "signature": "Block:trySet(name: string, value: any): boolean, string?",
          "description": "Like Block:set, but a refusal returns false and the reason instead of raising an error. Wrong arguments, side and permission errors still raise.",
          "params": [
            {
              "name": "name",
              "type": "string",
              "optional": false,
              "default": null,
              "description": ""
            },
            {
              "name": "value",
              "type": "any",
              "optional": false,
              "default": null,
              "description": ""
            }
          ],
          "returns": {
            "type": "boolean, string?",
            "description": "true and the result on success; false and the reason on a refusal."
          },
          "permission": "building.edit",
          "sides": [
            "client"
          ],
          "example": "for _, b in ipairs(building.selection()) do\n  b:set(\"Force\", 2500000)\nend",
          "since": null,
          "deprecated": null,
          "tryOf": "set"
        }
      ],
      "properties": [
        {
          "name": "creation",
          "type": "string",
          "description": "The id of the creation it belongs to.",
          "readOnly": true,
          "writePermission": null,
          "deprecated": null,
          "sides": [
            "client",
            "server"
          ]
        },
        {
          "name": "id",
          "type": "string",
          "description": "The block's unique id, the same on every machine.",
          "readOnly": true,
          "writePermission": null,
          "deprecated": null,
          "sides": [
            "client",
            "server"
          ]
        },
        {
          "name": "mechanism",
          "type": "string",
          "description": "The mechanism the block runs (\"Thruster\", \"Servo\" …), or an empty string for a plain block. This is the name building.raiseLimit takes.",
          "readOnly": true,
          "writePermission": null,
          "deprecated": null,
          "sides": [
            "client",
            "server"
          ]
        },
        {
          "name": "name",
          "type": "string",
          "description": "The block type's display name.",
          "readOnly": true,
          "writePermission": null,
          "deprecated": null,
          "sides": [
            "client",
            "server"
          ]
        },
        {
          "name": "position",
          "type": "vec3",
          "description": "Where the block is, in world coordinates.",
          "readOnly": true,
          "writePermission": null,
          "deprecated": null,
          "sides": [
            "client",
            "server"
          ]
        },
        {
          "name": "rotation",
          "type": "quat",
          "description": "Which way the block faces.",
          "readOnly": true,
          "writePermission": null,
          "deprecated": null,
          "sides": [
            "client",
            "server"
          ]
        },
        {
          "name": "type",
          "type": "string",
          "description": "The block type's id: \"Cube\" for the game's own, \"author.mod:sphere\" for a mod's.",
          "readOnly": true,
          "writePermission": null,
          "deprecated": null,
          "sides": [
            "client",
            "server"
          ]
        },
        {
          "name": "velocity",
          "type": "vec3",
          "description": "How fast the block is moving, in metres per second.",
          "readOnly": true,
          "writePermission": null,
          "deprecated": null,
          "sides": [
            "client",
            "server"
          ]
        }
      ]
    },
    {
      "name": "BuildTool",
      "description": "A button your mod added to the building toolbar.",
      "methods": [
        {
          "name": "setActive",
          "fullName": "BuildTool:setActive",
          "signature": "BuildTool:setActive(active: boolean)",
          "description": "Shows the tool as switched on or off.",
          "params": [
            {
              "name": "active",
              "type": "boolean",
              "optional": false,
              "default": null,
              "description": ""
            }
          ],
          "returns": {
            "type": "nil",
            "description": ""
          },
          "permission": null,
          "sides": [
            "client",
            "server"
          ],
          "example": null,
          "since": null,
          "deprecated": null,
          "tryOf": null
        }
      ],
      "properties": []
    },
    {
      "name": "Effect",
      "description": "A particle effect: sparks, smoke, fire …",
      "methods": [
        {
          "name": "destroy",
          "fullName": "Effect:destroy",
          "signature": "Effect:destroy()",
          "description": "Removes the effect at once.",
          "params": [],
          "returns": {
            "type": "nil",
            "description": ""
          },
          "permission": null,
          "sides": [
            "client",
            "server"
          ],
          "example": null,
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "emit",
          "fullName": "Effect:emit",
          "signature": "Effect:emit(count?: integer): Effect",
          "description": "Emits a number of particles at once.",
          "params": [
            {
              "name": "count",
              "type": "integer",
              "optional": true,
              "default": 10,
              "description": ""
            }
          ],
          "returns": {
            "type": "Effect",
            "description": ""
          },
          "permission": null,
          "sides": [
            "client",
            "server"
          ],
          "example": null,
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "follow",
          "fullName": "Effect:follow",
          "signature": "Effect:follow(target: Object, offset?: vec3): Effect",
          "description": "Makes the effect follow one of your objects.",
          "params": [
            {
              "name": "target",
              "type": "Object",
              "optional": false,
              "default": null,
              "description": ""
            },
            {
              "name": "offset",
              "type": "vec3",
              "optional": true,
              "default": null,
              "description": ""
            }
          ],
          "returns": {
            "type": "Effect",
            "description": ""
          },
          "permission": null,
          "sides": [
            "client",
            "server"
          ],
          "example": null,
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "play",
          "fullName": "Effect:play",
          "signature": "Effect:play(): Effect",
          "description": "Starts emitting again after :stop().",
          "params": [],
          "returns": {
            "type": "Effect",
            "description": ""
          },
          "permission": null,
          "sides": [
            "client",
            "server"
          ],
          "example": null,
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "stop",
          "fullName": "Effect:stop",
          "signature": "Effect:stop(): Effect",
          "description": "Stops emitting; particles already in the air finish their flight.",
          "params": [],
          "returns": {
            "type": "Effect",
            "description": ""
          },
          "permission": null,
          "sides": [
            "client",
            "server"
          ],
          "example": null,
          "since": null,
          "deprecated": null,
          "tryOf": null
        }
      ],
      "properties": [
        {
          "name": "position",
          "type": "vec3",
          "description": "Where the effect is.",
          "readOnly": false,
          "writePermission": null,
          "deprecated": null,
          "sides": [
            "client",
            "server"
          ]
        }
      ]
    },
    {
      "name": "Gear",
      "description": "A set of teeth on a block — a pitch circle, a rack's pitch line or a worm's thread — turning with a shaft or fixed to its part.",
      "methods": [
        {
          "name": "destroy",
          "fullName": "Gear:destroy",
          "signature": "Gear:destroy()",
          "description": "Removes the teeth, and every mesh they were in.",
          "params": [],
          "returns": {
            "type": "nil",
            "description": ""
          },
          "permission": "building.kinetics",
          "sides": [
            "server"
          ],
          "example": null,
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "meshes",
          "fullName": "Gear:meshes",
          "signature": "Gear:meshes(): GearMesh[]",
          "description": "The meshes it is part of.",
          "params": [],
          "returns": {
            "type": "GearMesh[]",
            "description": ""
          },
          "permission": null,
          "sides": [
            "client",
            "server"
          ],
          "example": null,
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "setShaft",
          "fullName": "Gear:setShaft",
          "signature": "Gear:setShaft(shaft?: Shaft)",
          "description": "Moves it onto a shaft (it turns with it), or with nil fixes it to its block's part.",
          "params": [
            {
              "name": "shaft",
              "type": "Shaft",
              "optional": true,
              "default": null,
              "description": ""
            }
          ],
          "returns": {
            "type": "nil",
            "description": ""
          },
          "permission": "building.kinetics",
          "sides": [
            "server"
          ],
          "example": null,
          "since": null,
          "deprecated": null,
          "tryOf": null
        }
      ],
      "properties": [
        {
          "name": "block",
          "type": "Block",
          "description": "The block the teeth are on.",
          "readOnly": true,
          "writePermission": null,
          "deprecated": null,
          "sides": [
            "client",
            "server"
          ]
        },
        {
          "name": "kind",
          "type": "string",
          "description": "\"circle\", \"line\" (a rack) or \"screw\" (a worm).",
          "readOnly": true,
          "writePermission": null,
          "deprecated": null,
          "sides": [
            "client",
            "server"
          ]
        },
        {
          "name": "mine",
          "type": "boolean",
          "description": "True when your mod made it — only then can you change it.",
          "readOnly": true,
          "writePermission": null,
          "deprecated": null,
          "sides": [
            "client",
            "server"
          ]
        },
        {
          "name": "radius",
          "type": "number",
          "description": "Pitch radius, metres (circles and screws).",
          "readOnly": true,
          "writePermission": null,
          "deprecated": null,
          "sides": [
            "client",
            "server"
          ]
        },
        {
          "name": "shaft",
          "type": "Shaft",
          "description": "The shaft it turns with, or nil when it is fixed to its part.",
          "readOnly": true,
          "writePermission": null,
          "deprecated": null,
          "sides": [
            "client",
            "server"
          ]
        },
        {
          "name": "teeth",
          "type": "integer",
          "description": "Its number of teeth (0 when unknown).",
          "readOnly": true,
          "writePermission": null,
          "deprecated": null,
          "sides": [
            "client",
            "server"
          ]
        }
      ]
    },
    {
      "name": "GearMesh",
      "description": "Two gears in mesh.",
      "methods": [
        {
          "name": "destroy",
          "fullName": "GearMesh:destroy",
          "signature": "GearMesh:destroy()",
          "description": "Removes the mesh.",
          "params": [],
          "returns": {
            "type": "nil",
            "description": ""
          },
          "permission": "building.kinetics",
          "sides": [
            "server"
          ],
          "example": null,
          "since": null,
          "deprecated": null,
          "tryOf": null
        }
      ],
      "properties": [
        {
          "name": "a",
          "type": "Gear",
          "description": "One of its gears.",
          "readOnly": true,
          "writePermission": null,
          "deprecated": null,
          "sides": [
            "client",
            "server"
          ]
        },
        {
          "name": "b",
          "type": "Gear",
          "description": "The other gear.",
          "readOnly": true,
          "writePermission": null,
          "deprecated": null,
          "sides": [
            "client",
            "server"
          ]
        },
        {
          "name": "engaged",
          "type": "boolean",
          "description": "Whether the teeth are in mesh right now (a pinion run off the end of its rack is not).",
          "readOnly": true,
          "writePermission": null,
          "deprecated": null,
          "sides": [
            "client",
            "server"
          ]
        },
        {
          "name": "force",
          "type": "number",
          "description": "The force on the teeth last step, N (gears on different parts only; gears on one part share a train and carry no load of their own).",
          "readOnly": true,
          "writePermission": null,
          "deprecated": null,
          "sides": [
            "client",
            "server"
          ]
        },
        {
          "name": "skips",
          "type": "integer",
          "description": "How many teeth have jumped since it was made (overload).",
          "readOnly": true,
          "writePermission": null,
          "deprecated": null,
          "sides": [
            "client",
            "server"
          ]
        },
        {
          "name": "slip",
          "type": "number",
          "description": "How far the teeth have slipped from exact mesh, metres.",
          "readOnly": true,
          "writePermission": null,
          "deprecated": null,
          "sides": [
            "client",
            "server"
          ]
        }
      ]
    },
    {
      "name": "HttpRequest",
      "description": "A web request on its way. The callback runs once, when it finishes, fails or is cancelled.",
      "methods": [
        {
          "name": "cancel",
          "fullName": "HttpRequest:cancel",
          "signature": "HttpRequest:cancel()",
          "description": "Stops the request. The callback runs with ok = false and error = \"cancelled\".",
          "params": [],
          "returns": {
            "type": "nil",
            "description": ""
          },
          "permission": null,
          "sides": [
            "client",
            "server"
          ],
          "example": null,
          "since": null,
          "deprecated": null,
          "tryOf": null
        }
      ],
      "properties": [
        {
          "name": "done",
          "type": "boolean",
          "description": "True once the callback has run (or will not, because the request was cancelled).",
          "readOnly": true,
          "writePermission": null,
          "deprecated": null,
          "sides": [
            "client",
            "server"
          ]
        },
        {
          "name": "url",
          "type": "string",
          "description": "The address being requested.",
          "readOnly": true,
          "writePermission": null,
          "deprecated": null,
          "sides": [
            "client",
            "server"
          ]
        }
      ]
    },
    {
      "name": "KeyBinding",
      "description": "A key your mod is listening for. Call :off() to stop.",
      "methods": [
        {
          "name": "off",
          "fullName": "KeyBinding:off",
          "signature": "KeyBinding:off()",
          "description": "Stops listening. Safe to call more than once.",
          "params": [],
          "returns": {
            "type": "nil",
            "description": ""
          },
          "permission": null,
          "sides": [
            "client",
            "server"
          ],
          "example": null,
          "since": null,
          "deprecated": null,
          "tryOf": null
        }
      ],
      "properties": [
        {
          "name": "name",
          "type": "string",
          "description": "The key this binding listens for.",
          "readOnly": true,
          "writePermission": null,
          "deprecated": null,
          "sides": [
            "client",
            "server"
          ]
        }
      ]
    },
    {
      "name": "Material",
      "description": "A surface: a shader plus its settings. Put one on an object with object:setMaterial.",
      "methods": [
        {
          "name": "setColor",
          "fullName": "Material:setColor",
          "signature": "Material:setColor(property: string, value: color): Material",
          "description": "Sets a colour on the material.",
          "params": [
            {
              "name": "property",
              "type": "string",
              "optional": false,
              "default": null,
              "description": ""
            },
            {
              "name": "value",
              "type": "color",
              "optional": false,
              "default": null,
              "description": ""
            }
          ],
          "returns": {
            "type": "Material",
            "description": ""
          },
          "permission": null,
          "sides": [
            "client",
            "server"
          ],
          "example": "glow:setColor(\"_EmissionColor\", color(\"#40c0ff\"))",
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "setNumber",
          "fullName": "Material:setNumber",
          "signature": "Material:setNumber(property: string, value: number): Material",
          "description": "Sets a number on the material.",
          "params": [
            {
              "name": "property",
              "type": "string",
              "optional": false,
              "default": null,
              "description": ""
            },
            {
              "name": "value",
              "type": "number",
              "optional": false,
              "default": null,
              "description": ""
            }
          ],
          "returns": {
            "type": "Material",
            "description": ""
          },
          "permission": null,
          "sides": [
            "client",
            "server"
          ],
          "example": null,
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "setTexture",
          "fullName": "Material:setTexture",
          "signature": "Material:setTexture(property: string, texture: Texture): Material",
          "description": "Sets a picture on the material.",
          "params": [
            {
              "name": "property",
              "type": "string",
              "optional": false,
              "default": null,
              "description": ""
            },
            {
              "name": "texture",
              "type": "Texture",
              "optional": false,
              "default": null,
              "description": ""
            }
          ],
          "returns": {
            "type": "Material",
            "description": ""
          },
          "permission": null,
          "sides": [
            "client",
            "server"
          ],
          "example": null,
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "setVector",
          "fullName": "Material:setVector",
          "signature": "Material:setVector(property: string, value: vec3, w?: number): Material",
          "description": "Sets a direction or a set of four numbers on the material.",
          "params": [
            {
              "name": "property",
              "type": "string",
              "optional": false,
              "default": null,
              "description": ""
            },
            {
              "name": "value",
              "type": "vec3",
              "optional": false,
              "default": null,
              "description": ""
            },
            {
              "name": "w",
              "type": "number",
              "optional": true,
              "default": 0.0,
              "description": ""
            }
          ],
          "returns": {
            "type": "Material",
            "description": ""
          },
          "permission": null,
          "sides": [
            "client",
            "server"
          ],
          "example": null,
          "since": null,
          "deprecated": null,
          "tryOf": null
        }
      ],
      "properties": [
        {
          "name": "shader",
          "type": "string",
          "description": "The shader this material uses.",
          "readOnly": true,
          "writePermission": null,
          "deprecated": null,
          "sides": [
            "client",
            "server"
          ]
        }
      ]
    },
    {
      "name": "ModExports",
      "description": "Another mod's exports (see mods.get). Read fields and call functions; it cannot be modified.",
      "methods": [],
      "properties": []
    },
    {
      "name": "Model",
      "description": "A model your mod has loaded, with its meshes and materials.",
      "methods": [
        {
          "name": "bounds",
          "fullName": "Model:bounds",
          "signature": "Model:bounds(): any",
          "description": "The size of the model in metres, as { min = vec3, max = vec3, size = vec3 }.",
          "params": [],
          "returns": {
            "type": "any",
            "description": ""
          },
          "permission": null,
          "sides": [
            "client",
            "server"
          ],
          "example": null,
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "materialNames",
          "fullName": "Model:materialNames",
          "signature": "Model:materialNames(): string[]",
          "description": "The names of the materials the model uses.",
          "params": [],
          "returns": {
            "type": "string[]",
            "description": ""
          },
          "permission": null,
          "sides": [
            "client",
            "server"
          ],
          "example": null,
          "since": null,
          "deprecated": null,
          "tryOf": null
        }
      ],
      "properties": [
        {
          "name": "file",
          "type": "string",
          "description": "The file it came from.",
          "readOnly": true,
          "writePermission": null,
          "deprecated": null,
          "sides": [
            "client",
            "server"
          ]
        },
        {
          "name": "meshes",
          "type": "integer",
          "description": "How many separate meshes it has.",
          "readOnly": true,
          "writePermission": null,
          "deprecated": null,
          "sides": [
            "client",
            "server"
          ]
        },
        {
          "name": "triangles",
          "type": "integer",
          "description": "How many triangles it has altogether.",
          "readOnly": true,
          "writePermission": null,
          "deprecated": null,
          "sides": [
            "client",
            "server"
          ]
        }
      ]
    },
    {
      "name": "Object",
      "description": "Something your mod put in the world.",
      "methods": [
        {
          "name": "addLight",
          "fullName": "Object:addLight",
          "signature": "Object:addLight(options?: any): Object",
          "description": "Adds a light to the object.",
          "params": [
            {
              "name": "options",
              "type": "any",
              "optional": true,
              "default": null,
              "description": ""
            }
          ],
          "returns": {
            "type": "Object",
            "description": ""
          },
          "permission": null,
          "sides": [
            "client",
            "server"
          ],
          "example": "lamp:addLight{ color = color(\"#ffd070\"), range = 12, intensity = 3 }",
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "destroy",
          "fullName": "Object:destroy",
          "signature": "Object:destroy()",
          "description": "Removes the object from the world for good.",
          "params": [],
          "returns": {
            "type": "nil",
            "description": ""
          },
          "permission": null,
          "sides": [
            "client",
            "server"
          ],
          "example": null,
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "follow",
          "fullName": "Object:follow",
          "signature": "Object:follow(other: Object, offset?: vec3, matchRotation?: boolean): Object",
          "description": "Makes the object follow another of your objects.",
          "params": [
            {
              "name": "other",
              "type": "Object",
              "optional": false,
              "default": null,
              "description": ""
            },
            {
              "name": "offset",
              "type": "vec3",
              "optional": true,
              "default": null,
              "description": ""
            },
            {
              "name": "matchRotation",
              "type": "boolean",
              "optional": true,
              "default": false,
              "description": ""
            }
          ],
          "returns": {
            "type": "Object",
            "description": ""
          },
          "permission": null,
          "sides": [
            "client",
            "server"
          ],
          "example": null,
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "followPlayer",
          "fullName": "Object:followPlayer",
          "signature": "Object:followPlayer(player: Player, offset?: vec3, faceCamera?: boolean): Object",
          "description": "Makes the object follow a player, keeping an offset in the player's own directions.",
          "params": [
            {
              "name": "player",
              "type": "Player",
              "optional": false,
              "default": null,
              "description": ""
            },
            {
              "name": "offset",
              "type": "vec3",
              "optional": true,
              "default": null,
              "description": ""
            },
            {
              "name": "faceCamera",
              "type": "boolean",
              "optional": true,
              "default": false,
              "description": ""
            }
          ],
          "returns": {
            "type": "Object",
            "description": ""
          },
          "permission": null,
          "sides": [
            "client",
            "server"
          ],
          "example": "marker:followPlayer(host, vec3(0, 2.4, 0))",
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "lookAt",
          "fullName": "Object:lookAt",
          "signature": "Object:lookAt(target: vec3): Object",
          "description": "Points the object at a place.",
          "params": [
            {
              "name": "target",
              "type": "vec3",
              "optional": false,
              "default": null,
              "description": ""
            }
          ],
          "returns": {
            "type": "Object",
            "description": ""
          },
          "permission": null,
          "sides": [
            "client",
            "server"
          ],
          "example": "marker:lookAt(player.position)",
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "setColor",
          "fullName": "Object:setColor",
          "signature": "Object:setColor(color: color): Object",
          "description": "Tints every part of the object.",
          "params": [
            {
              "name": "color",
              "type": "color",
              "optional": false,
              "default": null,
              "description": ""
            }
          ],
          "returns": {
            "type": "Object",
            "description": ""
          },
          "permission": null,
          "sides": [
            "client",
            "server"
          ],
          "example": "marker:setColor(color(\"#40c0ff\"))",
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "setMaterial",
          "fullName": "Object:setMaterial",
          "signature": "Object:setMaterial(material: Material): Object",
          "description": "Draws every part of the object with one of your materials.",
          "params": [
            {
              "name": "material",
              "type": "Material",
              "optional": false,
              "default": null,
              "description": ""
            }
          ],
          "returns": {
            "type": "Object",
            "description": ""
          },
          "permission": null,
          "sides": [
            "client",
            "server"
          ],
          "example": "local glow = assets.material{ color = color(\"#40c0ff\"), emissive = color(\"#40c0ff\") }\nshell:setMaterial(glow)",
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "unfollow",
          "fullName": "Object:unfollow",
          "signature": "Object:unfollow(): Object",
          "description": "Stops the object following anything.",
          "params": [],
          "returns": {
            "type": "Object",
            "description": ""
          },
          "permission": null,
          "sides": [
            "client",
            "server"
          ],
          "example": null,
          "since": null,
          "deprecated": null,
          "tryOf": null
        }
      ],
      "properties": [
        {
          "name": "name",
          "type": "string",
          "description": "The object's name.",
          "readOnly": false,
          "writePermission": null,
          "deprecated": null,
          "sides": [
            "client",
            "server"
          ]
        },
        {
          "name": "position",
          "type": "vec3",
          "description": "Where the object is, in world coordinates that mean the same place on every player's machine.",
          "readOnly": false,
          "writePermission": null,
          "deprecated": null,
          "sides": [
            "client",
            "server"
          ]
        },
        {
          "name": "rotation",
          "type": "quat",
          "description": "Which way the object is facing.",
          "readOnly": false,
          "writePermission": null,
          "deprecated": null,
          "sides": [
            "client",
            "server"
          ]
        },
        {
          "name": "scale",
          "type": "vec3",
          "description": "How big the object is.",
          "readOnly": false,
          "writePermission": null,
          "deprecated": null,
          "sides": [
            "client",
            "server"
          ]
        },
        {
          "name": "visible",
          "type": "boolean",
          "description": "Whether the object is drawn.",
          "readOnly": false,
          "writePermission": null,
          "deprecated": null,
          "sides": [
            "client",
            "server"
          ]
        }
      ]
    },
    {
      "name": "Player",
      "description": "A player in the session. Equal Player objects refer to the same person; a Player stays valid until they leave.",
      "methods": [
        {
          "name": "clearHighlight",
          "fullName": "Player:clearHighlight",
          "signature": "Player:clearHighlight()",
          "description": "Removes your highlight from a player.",
          "params": [],
          "returns": {
            "type": "nil",
            "description": ""
          },
          "permission": null,
          "sides": [
            "client"
          ],
          "example": null,
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "highlight",
          "fullName": "Player:highlight",
          "signature": "Player:highlight(look: any)",
          "description": "Highlights a player with a colour, which draws a soft glow, or with one of your materials, drawn over the player. Only you see it.",
          "params": [
            {
              "name": "look",
              "type": "any",
              "optional": false,
              "default": null,
              "description": ""
            }
          ],
          "returns": {
            "type": "nil",
            "description": ""
          },
          "permission": "world",
          "sides": [
            "client"
          ],
          "example": "players.host():highlight(color(\"#ffcc40\"))\nplayers.host():highlight(assets.material{ emissive = color(\"#40c0ff\"), alpha = \"blend\" })",
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "isHost",
          "fullName": "Player:isHost",
          "signature": "Player:isHost(): boolean",
          "description": "True for the player hosting the session.",
          "params": [],
          "returns": {
            "type": "boolean",
            "description": ""
          },
          "permission": null,
          "sides": [
            "client",
            "server"
          ],
          "example": null,
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "isLocal",
          "fullName": "Player:isLocal",
          "signature": "Player:isLocal(): boolean",
          "description": "True for this machine's own player.",
          "params": [],
          "returns": {
            "type": "boolean",
            "description": ""
          },
          "permission": null,
          "sides": [
            "client",
            "server"
          ],
          "example": null,
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "position",
          "fullName": "Player:position",
          "signature": "Player:position(): vec3",
          "description": "Where the player is.",
          "params": [],
          "returns": {
            "type": "vec3",
            "description": ""
          },
          "permission": "players",
          "sides": [
            "client",
            "server"
          ],
          "example": null,
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "rotation",
          "fullName": "Player:rotation",
          "signature": "Player:rotation(): quat",
          "description": "Which way the player faces.",
          "params": [],
          "returns": {
            "type": "quat",
            "description": ""
          },
          "permission": "players",
          "sides": [
            "client",
            "server"
          ],
          "example": null,
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "teleport",
          "fullName": "Player:teleport",
          "signature": "Player:teleport(position: vec3, rotation?: quat?)",
          "description": "Moves the player. Server scripts only.",
          "params": [
            {
              "name": "position",
              "type": "vec3",
              "optional": false,
              "default": null,
              "description": ""
            },
            {
              "name": "rotation",
              "type": "quat?",
              "optional": true,
              "default": null,
              "description": ""
            }
          ],
          "returns": {
            "type": "nil",
            "description": ""
          },
          "permission": "players.teleport",
          "sides": [
            "server"
          ],
          "example": "for _, p in ipairs(players.all()) do p:teleport(players.host():position() + vec3(2, 0, 0)) end",
          "since": null,
          "deprecated": null,
          "tryOf": null
        }
      ],
      "properties": [
        {
          "name": "id",
          "type": "integer",
          "description": "The player's id: the host is 0.",
          "readOnly": true,
          "writePermission": null,
          "deprecated": null,
          "sides": [
            "client",
            "server"
          ]
        },
        {
          "name": "name",
          "type": "string",
          "description": "Display name.",
          "readOnly": true,
          "writePermission": null,
          "deprecated": null,
          "sides": [
            "client",
            "server"
          ]
        }
      ]
    },
    {
      "name": "Shaft",
      "description": "An axle a block turns on, relative to the part it is on. Everything on it turns together; shafts meshed through gears form a gear train.",
      "methods": [
        {
          "name": "add",
          "fullName": "Shaft:add",
          "signature": "Shaft:add(block: Block)",
          "description": "Makes another block turn with it (it must be on the same part). Its spinning meshes are drawn turning.",
          "params": [
            {
              "name": "block",
              "type": "Block",
              "optional": false,
              "default": null,
              "description": ""
            }
          ],
          "returns": {
            "type": "nil",
            "description": ""
          },
          "permission": "building.kinetics",
          "sides": [
            "server"
          ],
          "example": null,
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "blocks",
          "fullName": "Shaft:blocks",
          "signature": "Shaft:blocks(): Block[]",
          "description": "The blocks turning with it.",
          "params": [],
          "returns": {
            "type": "Block[]",
            "description": ""
          },
          "permission": null,
          "sides": [
            "client",
            "server"
          ],
          "example": null,
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "brake",
          "fullName": "Shaft:brake",
          "signature": "Shaft:brake(torque: number)",
          "description": "Holds it still with up to torque N·m.",
          "params": [
            {
              "name": "torque",
              "type": "number",
              "optional": false,
              "default": null,
              "description": ""
            }
          ],
          "returns": {
            "type": "nil",
            "description": ""
          },
          "permission": "building.kinetics",
          "sides": [
            "server"
          ],
          "example": null,
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "destroy",
          "fullName": "Shaft:destroy",
          "signature": "Shaft:destroy()",
          "description": "Removes the shaft. Gears on it stay, fixed to their blocks' parts.",
          "params": [],
          "returns": {
            "type": "nil",
            "description": ""
          },
          "permission": "building.kinetics",
          "sides": [
            "server"
          ],
          "example": null,
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "free",
          "fullName": "Shaft:free",
          "signature": "Shaft:free()",
          "description": "Lets it turn freely: only its gears and friction act on it.",
          "params": [],
          "returns": {
            "type": "nil",
            "description": ""
          },
          "permission": "building.kinetics",
          "sides": [
            "server"
          ],
          "example": null,
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "motor",
          "fullName": "Shaft:motor",
          "signature": "Shaft:motor(rpm: number, torque: number)",
          "description": "Drives it as a motor: towards rpm (signed), with at most torque N·m.",
          "params": [
            {
              "name": "rpm",
              "type": "number",
              "optional": false,
              "default": null,
              "description": ""
            },
            {
              "name": "torque",
              "type": "number",
              "optional": false,
              "default": null,
              "description": ""
            }
          ],
          "returns": {
            "type": "nil",
            "description": ""
          },
          "permission": "building.kinetics",
          "sides": [
            "server"
          ],
          "example": "shaft:motor(120, 800)",
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "remove",
          "fullName": "Shaft:remove",
          "signature": "Shaft:remove(block: Block)",
          "description": "Stops a block turning with it.",
          "params": [
            {
              "name": "block",
              "type": "Block",
              "optional": false,
              "default": null,
              "description": ""
            }
          ],
          "returns": {
            "type": "nil",
            "description": ""
          },
          "permission": "building.kinetics",
          "sides": [
            "server"
          ],
          "example": null,
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "servo",
          "fullName": "Shaft:servo",
          "signature": "Shaft:servo(degrees: number, rpm: number, torque: number)",
          "description": "Turns it to an angle (degrees since built, not wrapped) at up to rpm, then holds it with at most torque N·m.",
          "params": [
            {
              "name": "degrees",
              "type": "number",
              "optional": false,
              "default": null,
              "description": ""
            },
            {
              "name": "rpm",
              "type": "number",
              "optional": false,
              "default": null,
              "description": ""
            },
            {
              "name": "torque",
              "type": "number",
              "optional": false,
              "default": null,
              "description": ""
            }
          ],
          "returns": {
            "type": "nil",
            "description": ""
          },
          "permission": "building.kinetics",
          "sides": [
            "server"
          ],
          "example": null,
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "setFriction",
          "fullName": "Shaft:setFriction",
          "signature": "Shaft:setFriction(friction: number, damping?: number)",
          "description": "Bearing friction (constant torque against turning, N·m) and damping (N·m per rad/s).",
          "params": [
            {
              "name": "friction",
              "type": "number",
              "optional": false,
              "default": null,
              "description": ""
            },
            {
              "name": "damping",
              "type": "number",
              "optional": true,
              "default": 0.0,
              "description": ""
            }
          ],
          "returns": {
            "type": "nil",
            "description": ""
          },
          "permission": "building.kinetics",
          "sides": [
            "server"
          ],
          "example": null,
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "setInertia",
          "fullName": "Shaft:setInertia",
          "signature": "Shaft:setInertia(inertia: number)",
          "description": "Adds inertia to it (a flywheel), kg·m², on top of what its blocks have.",
          "params": [
            {
              "name": "inertia",
              "type": "number",
              "optional": false,
              "default": null,
              "description": ""
            }
          ],
          "returns": {
            "type": "nil",
            "description": ""
          },
          "permission": "building.kinetics",
          "sides": [
            "server"
          ],
          "example": null,
          "since": null,
          "deprecated": null,
          "tryOf": null
        }
      ],
      "properties": [
        {
          "name": "angle",
          "type": "number",
          "description": "How far it has turned since its creation was built, in degrees. Not wrapped: 720 is two turns.",
          "readOnly": true,
          "writePermission": null,
          "deprecated": null,
          "sides": [
            "client",
            "server"
          ]
        },
        {
          "name": "block",
          "type": "Block",
          "description": "The block whose axle this is.",
          "readOnly": true,
          "writePermission": null,
          "deprecated": null,
          "sides": [
            "client",
            "server"
          ]
        },
        {
          "name": "jammed",
          "type": "boolean",
          "description": "True when the gears it meshes with lock each other and nothing can turn.",
          "readOnly": true,
          "writePermission": null,
          "deprecated": null,
          "sides": [
            "client",
            "server"
          ]
        },
        {
          "name": "mine",
          "type": "boolean",
          "description": "True when your mod made it — only then can you change it.",
          "readOnly": true,
          "writePermission": null,
          "deprecated": null,
          "sides": [
            "client",
            "server"
          ]
        },
        {
          "name": "rpm",
          "type": "number",
          "description": "How fast it turns relative to the part it is on, in turns per minute (signed).",
          "readOnly": true,
          "writePermission": null,
          "deprecated": null,
          "sides": [
            "client",
            "server"
          ]
        },
        {
          "name": "simulated",
          "type": "boolean",
          "description": "True while its gear train is being simulated (a creation in play, with gear simulation running).",
          "readOnly": true,
          "writePermission": null,
          "deprecated": null,
          "sides": [
            "client",
            "server"
          ]
        },
        {
          "name": "torque",
          "type": "number",
          "description": "The torque its drive applied last physics step, N·m.",
          "readOnly": true,
          "writePermission": null,
          "deprecated": null,
          "sides": [
            "client",
            "server"
          ]
        }
      ]
    },
    {
      "name": "Sound",
      "description": "A sound that is playing, or about to.",
      "methods": [
        {
          "name": "fadeOut",
          "fullName": "Sound:fadeOut",
          "signature": "Sound:fadeOut(seconds?: number)",
          "description": "Fades the sound out over a number of seconds, then stops it.",
          "params": [
            {
              "name": "seconds",
              "type": "number",
              "optional": true,
              "default": 1.0,
              "description": ""
            }
          ],
          "returns": {
            "type": "nil",
            "description": ""
          },
          "permission": null,
          "sides": [
            "client",
            "server"
          ],
          "example": null,
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "isPlaying",
          "fullName": "Sound:isPlaying",
          "signature": "Sound:isPlaying(): boolean",
          "description": "True while the sound is playing.",
          "params": [],
          "returns": {
            "type": "boolean",
            "description": ""
          },
          "permission": null,
          "sides": [
            "client",
            "server"
          ],
          "example": null,
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "stop",
          "fullName": "Sound:stop",
          "signature": "Sound:stop()",
          "description": "Stops the sound and frees it. Safe to call more than once.",
          "params": [],
          "returns": {
            "type": "nil",
            "description": ""
          },
          "permission": null,
          "sides": [
            "client",
            "server"
          ],
          "example": null,
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "time",
          "fullName": "Sound:time",
          "signature": "Sound:time(): number",
          "description": "How far through the sound is, in seconds.",
          "params": [],
          "returns": {
            "type": "number",
            "description": ""
          },
          "permission": null,
          "sides": [
            "client",
            "server"
          ],
          "example": null,
          "since": null,
          "deprecated": null,
          "tryOf": null
        }
      ],
      "properties": [
        {
          "name": "pitch",
          "type": "number",
          "description": "Playback speed, where 1 is normal. Changes the pitch too.",
          "readOnly": false,
          "writePermission": null,
          "deprecated": null,
          "sides": [
            "client",
            "server"
          ]
        },
        {
          "name": "position",
          "type": "vec3",
          "description": "Where the sound comes from. Only matters for a sound placed in the world.",
          "readOnly": false,
          "writePermission": null,
          "deprecated": null,
          "sides": [
            "client",
            "server"
          ]
        },
        {
          "name": "ready",
          "type": "boolean",
          "description": "True once the sound is loaded and can play.",
          "readOnly": true,
          "writePermission": null,
          "deprecated": null,
          "sides": [
            "client",
            "server"
          ]
        },
        {
          "name": "volume",
          "type": "number",
          "description": "How loud, from 0 to 1.",
          "readOnly": false,
          "writePermission": null,
          "deprecated": null,
          "sides": [
            "client",
            "server"
          ]
        }
      ]
    },
    {
      "name": "Subscription",
      "description": "An event subscription. Call :off() to stop receiving the event.",
      "methods": [
        {
          "name": "off",
          "fullName": "Subscription:off",
          "signature": "Subscription:off()",
          "description": "Stops the subscription; the handler will not run again, not even for an event raised a moment ago that has not been delivered yet. Safe to call more than once.",
          "params": [],
          "returns": {
            "type": "nil",
            "description": ""
          },
          "permission": null,
          "sides": [
            "client",
            "server"
          ],
          "example": null,
          "since": null,
          "deprecated": null,
          "tryOf": null
        }
      ],
      "properties": []
    },
    {
      "name": "Task",
      "description": "A background task started with task.spawn.",
      "methods": [
        {
          "name": "cancel",
          "fullName": "Task:cancel",
          "signature": "Task:cancel()",
          "description": "Stops the task before its next step. Safe to call more than once.",
          "params": [],
          "returns": {
            "type": "nil",
            "description": ""
          },
          "permission": null,
          "sides": [
            "client",
            "server"
          ],
          "example": null,
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "isRunning",
          "fullName": "Task:isRunning",
          "signature": "Task:isRunning(): boolean",
          "description": "True until the task finishes, fails or is cancelled.",
          "params": [],
          "returns": {
            "type": "boolean",
            "description": ""
          },
          "permission": null,
          "sides": [
            "client",
            "server"
          ],
          "example": null,
          "since": null,
          "deprecated": null,
          "tryOf": null
        }
      ],
      "properties": []
    },
    {
      "name": "Texture",
      "description": "A picture your mod has loaded.",
      "methods": [],
      "properties": [
        {
          "name": "file",
          "type": "string",
          "description": "The file it came from.",
          "readOnly": true,
          "writePermission": null,
          "deprecated": null,
          "sides": [
            "client",
            "server"
          ]
        },
        {
          "name": "height",
          "type": "integer",
          "description": "How tall the picture is, in pixels.",
          "readOnly": true,
          "writePermission": null,
          "deprecated": null,
          "sides": [
            "client",
            "server"
          ]
        },
        {
          "name": "width",
          "type": "integer",
          "description": "How wide the picture is, in pixels.",
          "readOnly": true,
          "writePermission": null,
          "deprecated": null,
          "sides": [
            "client",
            "server"
          ]
        }
      ]
    },
    {
      "name": "Timer",
      "description": "A scheduled callback returned by timer.after or timer.every.",
      "methods": [
        {
          "name": "cancel",
          "fullName": "Timer:cancel",
          "signature": "Timer:cancel()",
          "description": "Stops the timer. Safe to call more than once.",
          "params": [],
          "returns": {
            "type": "nil",
            "description": ""
          },
          "permission": null,
          "sides": [
            "client",
            "server"
          ],
          "example": null,
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "remaining",
          "fullName": "Timer:remaining",
          "signature": "Timer:remaining(): number",
          "description": "Seconds until the timer next fires.",
          "params": [],
          "returns": {
            "type": "number",
            "description": ""
          },
          "permission": null,
          "sides": [
            "client",
            "server"
          ],
          "example": null,
          "since": null,
          "deprecated": null,
          "tryOf": null
        }
      ],
      "properties": []
    },
    {
      "name": "UiElement",
      "description": "A part of an interface: a panel, a button, a slider, a label.",
      "methods": [
        {
          "name": "add",
          "fullName": "UiElement:add",
          "signature": "UiElement:add(child: UiElement): UiElement",
          "description": "Puts another element inside this one.",
          "params": [
            {
              "name": "child",
              "type": "UiElement",
              "optional": false,
              "default": null,
              "description": ""
            }
          ],
          "returns": {
            "type": "UiElement",
            "description": ""
          },
          "permission": null,
          "sides": [
            "client",
            "server"
          ],
          "example": "panel:add(ui.element(\"Button\", { text = \"Apply\" }))",
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "addClass",
          "fullName": "UiElement:addClass",
          "signature": "UiElement:addClass(name: string): UiElement",
          "description": "Adds a style class, the same names a .uss file uses.",
          "params": [
            {
              "name": "name",
              "type": "string",
              "optional": false,
              "default": null,
              "description": ""
            }
          ],
          "returns": {
            "type": "UiElement",
            "description": ""
          },
          "permission": null,
          "sides": [
            "client",
            "server"
          ],
          "example": null,
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "addNew",
          "fullName": "UiElement:addNew",
          "signature": "UiElement:addNew(kind: string, options?: any): UiElement",
          "description": "Creates an element and puts it inside this one, in one step.",
          "params": [
            {
              "name": "kind",
              "type": "string",
              "optional": false,
              "default": null,
              "description": ""
            },
            {
              "name": "options",
              "type": "any",
              "optional": true,
              "default": null,
              "description": ""
            }
          ],
          "returns": {
            "type": "UiElement",
            "description": ""
          },
          "permission": null,
          "sides": [
            "client",
            "server"
          ],
          "example": "local apply = panel:addNew(\"Button\", { text = \"Apply\", class = \"primary\" })",
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "children",
          "fullName": "UiElement:children",
          "signature": "UiElement:children(): UiElement[]",
          "description": "The elements directly inside this one.",
          "params": [],
          "returns": {
            "type": "UiElement[]",
            "description": ""
          },
          "permission": null,
          "sides": [
            "client",
            "server"
          ],
          "example": null,
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "destroy",
          "fullName": "UiElement:destroy",
          "signature": "UiElement:destroy()",
          "description": "Removes the element and everything in it for good. Only for elements this mod made.",
          "params": [],
          "returns": {
            "type": "nil",
            "description": ""
          },
          "permission": null,
          "sides": [
            "client",
            "server"
          ],
          "example": null,
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "find",
          "fullName": "UiElement:find",
          "signature": "UiElement:find(selector: string): UiElement",
          "description": "The first element under this one matching a selector, or nil.",
          "params": [
            {
              "name": "selector",
              "type": "string",
              "optional": false,
              "default": null,
              "description": ""
            }
          ],
          "returns": {
            "type": "UiElement",
            "description": ""
          },
          "permission": null,
          "sides": [
            "client",
            "server"
          ],
          "example": "local power = panel:find(\"#power\")",
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "findAll",
          "fullName": "UiElement:findAll",
          "signature": "UiElement:findAll(selector: string, limit?: integer): UiElement[]",
          "description": "Every element under this one matching a selector.",
          "params": [
            {
              "name": "selector",
              "type": "string",
              "optional": false,
              "default": null,
              "description": ""
            },
            {
              "name": "limit",
              "type": "integer",
              "optional": true,
              "default": 128,
              "description": ""
            }
          ],
          "returns": {
            "type": "UiElement[]",
            "description": ""
          },
          "permission": null,
          "sides": [
            "client",
            "server"
          ],
          "example": null,
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "focus",
          "fullName": "UiElement:focus",
          "signature": "UiElement:focus(): UiElement",
          "description": "Gives the element keyboard focus.",
          "params": [],
          "returns": {
            "type": "UiElement",
            "description": ""
          },
          "permission": null,
          "sides": [
            "client",
            "server"
          ],
          "example": null,
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "get",
          "fullName": "UiElement:get",
          "signature": "UiElement:get(property: string): any",
          "description": "Reads a property: \"value\", \"label\", \"tooltip\", \"enabled\", \"visible\", \"choices\" …",
          "params": [
            {
              "name": "property",
              "type": "string",
              "optional": false,
              "default": null,
              "description": ""
            }
          ],
          "returns": {
            "type": "any",
            "description": ""
          },
          "permission": null,
          "sides": [
            "client",
            "server"
          ],
          "example": null,
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "hasClass",
          "fullName": "UiElement:hasClass",
          "signature": "UiElement:hasClass(name: string): boolean",
          "description": "Whether the element has a style class.",
          "params": [
            {
              "name": "name",
              "type": "string",
              "optional": false,
              "default": null,
              "description": ""
            }
          ],
          "returns": {
            "type": "boolean",
            "description": ""
          },
          "permission": null,
          "sides": [
            "client",
            "server"
          ],
          "example": null,
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "hide",
          "fullName": "UiElement:hide",
          "signature": "UiElement:hide(): UiElement",
          "description": "Hides the element without removing it. The layout closes up around it.",
          "params": [],
          "returns": {
            "type": "UiElement",
            "description": ""
          },
          "permission": null,
          "sides": [
            "client",
            "server"
          ],
          "example": null,
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "on",
          "fullName": "UiElement:on",
          "signature": "UiElement:on(what: string, handler: function): UiSubscription",
          "description": "Runs a function when something happens: \"click\", \"change\", \"input\", \"focus\", \"blur\", \"enter\", \"leave\".",
          "params": [
            {
              "name": "what",
              "type": "string",
              "optional": false,
              "default": null,
              "description": ""
            },
            {
              "name": "handler",
              "type": "function",
              "optional": false,
              "default": null,
              "description": ""
            }
          ],
          "returns": {
            "type": "UiSubscription",
            "description": ""
          },
          "permission": null,
          "sides": [
            "client",
            "server"
          ],
          "example": "apply:on(\"click\", function() applySettings() end)\nslider:on(\"change\", function(value) preview(value) end)",
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "parent",
          "fullName": "UiElement:parent",
          "signature": "UiElement:parent(): UiElement?",
          "description": "The element this one is inside, or nil.",
          "params": [],
          "returns": {
            "type": "UiElement?",
            "description": ""
          },
          "permission": null,
          "sides": [
            "client",
            "server"
          ],
          "example": null,
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "remove",
          "fullName": "UiElement:remove",
          "signature": "UiElement:remove()",
          "description": "Takes the element out of the interface. A game element is put back when the mod stops.",
          "params": [],
          "returns": {
            "type": "nil",
            "description": ""
          },
          "permission": null,
          "sides": [
            "client",
            "server"
          ],
          "example": null,
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "removeClass",
          "fullName": "UiElement:removeClass",
          "signature": "UiElement:removeClass(name: string): UiElement",
          "description": "Removes a style class.",
          "params": [
            {
              "name": "name",
              "type": "string",
              "optional": false,
              "default": null,
              "description": ""
            }
          ],
          "returns": {
            "type": "UiElement",
            "description": ""
          },
          "permission": null,
          "sides": [
            "client",
            "server"
          ],
          "example": null,
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "set",
          "fullName": "UiElement:set",
          "signature": "UiElement:set(property: string, value: any): UiElement",
          "description": "Sets a property: \"value\", \"label\", \"tooltip\", \"enabled\", \"choices\", \"index\".",
          "params": [
            {
              "name": "property",
              "type": "string",
              "optional": false,
              "default": null,
              "description": ""
            },
            {
              "name": "value",
              "type": "any",
              "optional": false,
              "default": null,
              "description": ""
            }
          ],
          "returns": {
            "type": "UiElement",
            "description": ""
          },
          "permission": null,
          "sides": [
            "client",
            "server"
          ],
          "example": "slider:set(\"value\", 42)",
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "setText",
          "fullName": "UiElement:setText",
          "signature": "UiElement:setText(text: string): UiElement",
          "description": "Sets the element's text.",
          "params": [
            {
              "name": "text",
              "type": "string",
              "optional": false,
              "default": null,
              "description": ""
            }
          ],
          "returns": {
            "type": "UiElement",
            "description": ""
          },
          "permission": null,
          "sides": [
            "client",
            "server"
          ],
          "example": "title:setText(\"Thrusters\")",
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "show",
          "fullName": "UiElement:show",
          "signature": "UiElement:show(): UiElement",
          "description": "Shows an element that was hidden.",
          "params": [],
          "returns": {
            "type": "UiElement",
            "description": ""
          },
          "permission": null,
          "sides": [
            "client",
            "server"
          ],
          "example": null,
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "style",
          "fullName": "UiElement:style",
          "signature": "UiElement:style(styles: any): UiElement",
          "description": "Sets styles, written the same way as in a .uss file.",
          "params": [
            {
              "name": "styles",
              "type": "any",
              "optional": false,
              "default": null,
              "description": ""
            }
          ],
          "returns": {
            "type": "UiElement",
            "description": ""
          },
          "permission": null,
          "sides": [
            "client",
            "server"
          ],
          "example": "panel:style{ width = \"320px\", [\"background-color\"] = \"#202024e0\" }",
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "text",
          "fullName": "UiElement:text",
          "signature": "UiElement:text(): string?",
          "description": "The element's text, or nil when it has none.",
          "params": [],
          "returns": {
            "type": "string?",
            "description": ""
          },
          "permission": null,
          "sides": [
            "client",
            "server"
          ],
          "example": null,
          "since": null,
          "deprecated": null,
          "tryOf": null
        }
      ],
      "properties": [
        {
          "name": "isGame",
          "type": "boolean",
          "description": "True when this belongs to the game rather than to a mod.",
          "readOnly": true,
          "writePermission": null,
          "deprecated": null,
          "sides": [
            "client",
            "server"
          ]
        },
        {
          "name": "kind",
          "type": "string",
          "description": "What kind of element this is: \"Button\", \"Label\", \"Slider\" …",
          "readOnly": true,
          "writePermission": null,
          "deprecated": null,
          "sides": [
            "client",
            "server"
          ]
        },
        {
          "name": "name",
          "type": "string",
          "description": "The element's name, as written in name=\"…\".",
          "readOnly": true,
          "writePermission": null,
          "deprecated": null,
          "sides": [
            "client",
            "server"
          ]
        }
      ]
    },
    {
      "name": "Video",
      "description": "A video that is playing on an interface element or on an object.",
      "methods": [
        {
          "name": "isPlaying",
          "fullName": "Video:isPlaying",
          "signature": "Video:isPlaying(): boolean",
          "description": "True while the video is playing.",
          "params": [],
          "returns": {
            "type": "boolean",
            "description": ""
          },
          "permission": null,
          "sides": [
            "client",
            "server"
          ],
          "example": null,
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "onEnd",
          "fullName": "Video:onEnd",
          "signature": "Video:onEnd(fn: function): Video",
          "description": "Calls fn each time the video reaches its end (every loop, when looping).",
          "params": [
            {
              "name": "fn",
              "type": "function",
              "optional": false,
              "default": null,
              "description": ""
            }
          ],
          "returns": {
            "type": "Video",
            "description": ""
          },
          "permission": null,
          "sides": [
            "client",
            "server"
          ],
          "example": "intro:onEnd(function() intro:stop() panel:destroy() end)",
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "pause",
          "fullName": "Video:pause",
          "signature": "Video:pause(): Video",
          "description": "Pauses the video.",
          "params": [],
          "returns": {
            "type": "Video",
            "description": ""
          },
          "permission": null,
          "sides": [
            "client",
            "server"
          ],
          "example": null,
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "resume",
          "fullName": "Video:resume",
          "signature": "Video:resume(): Video",
          "description": "Carries on after :pause().",
          "params": [],
          "returns": {
            "type": "Video",
            "description": ""
          },
          "permission": null,
          "sides": [
            "client",
            "server"
          ],
          "example": null,
          "since": null,
          "deprecated": null,
          "tryOf": null
        },
        {
          "name": "stop",
          "fullName": "Video:stop",
          "signature": "Video:stop()",
          "description": "Stops the video and frees it. Safe to call more than once.",
          "params": [],
          "returns": {
            "type": "nil",
            "description": ""
          },
          "permission": null,
          "sides": [
            "client",
            "server"
          ],
          "example": null,
          "since": null,
          "deprecated": null,
          "tryOf": null
        }
      ],
      "properties": [
        {
          "name": "length",
          "type": "number",
          "description": "How long the video is, in seconds. 0 until it is ready.",
          "readOnly": true,
          "writePermission": null,
          "deprecated": null,
          "sides": [
            "client",
            "server"
          ]
        },
        {
          "name": "ready",
          "type": "boolean",
          "description": "True once the video has been opened and its length is known.",
          "readOnly": true,
          "writePermission": null,
          "deprecated": null,
          "sides": [
            "client",
            "server"
          ]
        },
        {
          "name": "time",
          "type": "number",
          "description": "How far through the video is, in seconds.",
          "readOnly": false,
          "writePermission": null,
          "deprecated": null,
          "sides": [
            "client",
            "server"
          ]
        },
        {
          "name": "volume",
          "type": "number",
          "description": "The video's sound volume, from 0 to 1.",
          "readOnly": false,
          "writePermission": null,
          "deprecated": null,
          "sides": [
            "client",
            "server"
          ]
        }
      ]
    }
  ],
  "handleCommon": [
    {
      "name": "isValid",
      "signature": "isValid(): boolean",
      "description": "False once the thing the handle refers to is gone. Every handle has it."
    }
  ],
  "events": [
    {
      "name": "game.AfterSceneLoadEvent",
      "description": "The game's AfterSceneLoadEvent event, read-only.",
      "payload": "{ sceneName }",
      "sides": [
        "client",
        "server"
      ],
      "provider": "theonaris.game"
    },
    {
      "name": "game.BeforeSceneLoadEvent",
      "description": "The game's BeforeSceneLoadEvent event, read-only.",
      "payload": "{ sceneName }",
      "sides": [
        "client",
        "server"
      ],
      "provider": "theonaris.game"
    },
    {
      "name": "game.BlockAddedEvent",
      "description": "The game's BlockAddedEvent event, read-only. Travels between peers, so positions in it are absolute.",
      "payload": "{ structureId, blockId, position }",
      "sides": [
        "client",
        "server"
      ],
      "provider": "theonaris.game"
    },
    {
      "name": "game.BlockInteractRequest",
      "description": "The game's BlockInteractRequest event, read-only. Travels between peers, so positions in it are absolute.",
      "payload": "{ blockUuid }",
      "sides": [
        "client",
        "server"
      ],
      "provider": "theonaris.game"
    },
    {
      "name": "game.BlockRemovedEvent",
      "description": "The game's BlockRemovedEvent event, read-only. Travels between peers, so positions in it are absolute.",
      "payload": "{ structureId, blockId, position }",
      "sides": [
        "client",
        "server"
      ],
      "provider": "theonaris.game"
    },
    {
      "name": "game.BuildingStructureEvents.Initialization.RequestSpawn",
      "description": "The game's BuildingStructureEvents.Initialization.RequestSpawn event, read-only. Travels between peers, so positions in it are absolute.",
      "payload": "{ ownerUuid, forceNew }",
      "sides": [
        "client",
        "server"
      ],
      "provider": "theonaris.game"
    },
    {
      "name": "game.BuildingStructureEvents.Initialization.SpawnResponse",
      "description": "The game's BuildingStructureEvents.Initialization.SpawnResponse event, read-only. Travels between peers, so positions in it are absolute.",
      "payload": "{ isSuccess, structureUuid, reason }",
      "sides": [
        "client",
        "server"
      ],
      "provider": "theonaris.game"
    },
    {
      "name": "game.BuildingStructureEvents.Ownership.OnOwnershipChanged",
      "description": "The game's BuildingStructureEvents.Ownership.OnOwnershipChanged event, read-only. Travels between peers, so positions in it are absolute.",
      "payload": "{ structure, prevOwner, newOwner }",
      "sides": [
        "client",
        "server"
      ],
      "provider": "theonaris.game"
    },
    {
      "name": "game.BuildingStructureEvents.Ownership.OnOwnershipRecalled",
      "description": "The game's BuildingStructureEvents.Ownership.OnOwnershipRecalled event, read-only. Travels between peers, so positions in it are absolute.",
      "payload": "{ structure, prevOwner }",
      "sides": [
        "client",
        "server"
      ],
      "provider": "theonaris.game"
    },
    {
      "name": "game.BuildingStructureEvents.Ownership.RequestTransfer",
      "description": "The game's BuildingStructureEvents.Ownership.RequestTransfer event, read-only. Travels between peers, so positions in it are absolute.",
      "payload": "{ toPlayer }",
      "sides": [
        "client",
        "server"
      ],
      "provider": "theonaris.game"
    },
    {
      "name": "game.BuildingStructureEvents.Ownership.TransferResponse",
      "description": "The game's BuildingStructureEvents.Ownership.TransferResponse event, read-only. Travels between peers, so positions in it are absolute.",
      "payload": "{ isSuccess, newOwner }",
      "sides": [
        "client",
        "server"
      ],
      "provider": "theonaris.game"
    },
    {
      "name": "game.BuildingStructureEvents.Placement.RequestMoveBesidePlayer",
      "description": "The game's BuildingStructureEvents.Placement.RequestMoveBesidePlayer event, read-only. Travels between peers, so positions in it are absolute.",
      "payload": "{ structureUuid }",
      "sides": [
        "client",
        "server"
      ],
      "provider": "theonaris.game"
    },
    {
      "name": "game.BuildingStructureEvents.Placement.RequestMoveStructure",
      "description": "The game's BuildingStructureEvents.Placement.RequestMoveStructure event, read-only. Travels between peers, so positions in it are absolute.",
      "payload": "{ structureUuid, position, rotation }",
      "sides": [
        "client",
        "server"
      ],
      "provider": "theonaris.game"
    },
    {
      "name": "game.BuildingStructureEvents.Retrieve.RequestDeleteStructure",
      "description": "The game's BuildingStructureEvents.Retrieve.RequestDeleteStructure event, read-only. Travels between peers, so positions in it are absolute.",
      "payload": "{ structureUuid }",
      "sides": [
        "client",
        "server"
      ],
      "provider": "theonaris.game"
    },
    {
      "name": "game.BuildingStructureEvents.Retrieve.RequestOwnedStructures",
      "description": "The game's BuildingStructureEvents.Retrieve.RequestOwnedStructures event, read-only. Travels between peers, so positions in it are absolute.",
      "payload": "{ ownerUuid }",
      "sides": [
        "client",
        "server"
      ],
      "provider": "theonaris.game"
    },
    {
      "name": "game.BuildingStructureEvents.Retrieve.RequestStructureBlocks",
      "description": "The game's BuildingStructureEvents.Retrieve.RequestStructureBlocks event, read-only. Travels between peers, so positions in it are absolute.",
      "payload": "{ structureUuid }",
      "sides": [
        "client",
        "server"
      ],
      "provider": "theonaris.game"
    },
    {
      "name": "game.BuildingStructureEvents.Retrieve.ReturnOwnedStructures",
      "description": "The game's BuildingStructureEvents.Retrieve.ReturnOwnedStructures event, read-only. Travels between peers, so positions in it are absolute.",
      "payload": "{ structureUuids, summaries }",
      "sides": [
        "client",
        "server"
      ],
      "provider": "theonaris.game"
    },
    {
      "name": "game.BuildingStructureEvents.Retrieve.ReturnStructureBlocks",
      "description": "The game's BuildingStructureEvents.Retrieve.ReturnStructureBlocks event, read-only. Travels between peers, so positions in it are absolute.",
      "payload": "{ structureUuid, results }",
      "sides": [
        "client",
        "server"
      ],
      "provider": "theonaris.game"
    },
    {
      "name": "game.BuildingStructureEvents.Retrieve.StructureRemoved",
      "description": "The game's BuildingStructureEvents.Retrieve.StructureRemoved event, read-only. Travels between peers, so positions in it are absolute.",
      "payload": "{ structureUuid }",
      "sides": [
        "client",
        "server"
      ],
      "provider": "theonaris.game"
    },
    {
      "name": "game.ChangeBuildingMode.Approved",
      "description": "The game's ChangeBuildingMode.Approved event, read-only.",
      "payload": "{ open }",
      "sides": [
        "client",
        "server"
      ],
      "provider": "theonaris.game"
    },
    {
      "name": "game.ChangeBuildingMode.Complete",
      "description": "The game's ChangeBuildingMode.Complete event, read-only. Travels between peers, so positions in it are absolute.",
      "payload": "{ open, isSuccess }",
      "sides": [
        "client",
        "server"
      ],
      "provider": "theonaris.game"
    },
    {
      "name": "game.ChangeBuildingMode.Request",
      "description": "The game's ChangeBuildingMode.Request event, read-only. Travels between peers, so positions in it are absolute.",
      "payload": "{ open }",
      "sides": [
        "client",
        "server"
      ],
      "provider": "theonaris.game"
    },
    {
      "name": "game.ChangeBuildingMode.Response",
      "description": "The game's ChangeBuildingMode.Response event, read-only. Travels between peers, so positions in it are absolute.",
      "payload": "{ open, isSuccess }",
      "sides": [
        "client",
        "server"
      ],
      "provider": "theonaris.game"
    },
    {
      "name": "game.ClientCameraViewSyncEvent",
      "description": "The game's ClientCameraViewSyncEvent event, read-only. Travels between peers, so positions in it are absolute.",
      "payload": "{ playerUuid, cameraUuid }",
      "sides": [
        "client",
        "server"
      ],
      "provider": "theonaris.game"
    },
    {
      "name": "game.ClientVehicleInputSyncEvent",
      "description": "The game's ClientVehicleInputSyncEvent event, read-only. Travels between peers, so positions in it are absolute.",
      "payload": "{ playerUuid, pressedKeys, yaw, pitch, hasAim }",
      "sides": [
        "client",
        "server"
      ],
      "provider": "theonaris.game"
    },
    {
      "name": "game.PlayerPlacementEvent",
      "description": "The game's PlayerPlacementEvent event, read-only. Travels between peers, so positions in it are absolute.",
      "payload": "{ playerNetId, position, reason }",
      "sides": [
        "client",
        "server"
      ],
      "provider": "theonaris.game"
    },
    {
      "name": "game.SeatHopRequest",
      "description": "The game's SeatHopRequest event, read-only. Travels between peers, so positions in it are absolute.",
      "payload": "{ backwards }",
      "sides": [
        "client",
        "server"
      ],
      "provider": "theonaris.game"
    },
    {
      "name": "game.SeatInteractionRequest",
      "description": "The game's SeatInteractionRequest event, read-only. Travels between peers, so positions in it are absolute.",
      "payload": "{ playerUuid, blockUuid }",
      "sides": [
        "client",
        "server"
      ],
      "provider": "theonaris.game"
    },
    {
      "name": "game.SeatOccupancyChangedEvent",
      "description": "The game's SeatOccupancyChangedEvent event, read-only. Travels between peers, so positions in it are absolute.",
      "payload": "{ blockUuid, playerNetId, occupied, exitPosition, hasExit }",
      "sides": [
        "client",
        "server"
      ],
      "provider": "theonaris.game"
    },
    {
      "name": "game.StructureBuiltEvent",
      "description": "The game's StructureBuiltEvent event, read-only. Travels between peers, so positions in it are absolute.",
      "payload": "{ structureId, position }",
      "sides": [
        "client",
        "server"
      ],
      "provider": "theonaris.game"
    },
    {
      "name": "game.StructureDesignPoseSyncEvent",
      "description": "The game's StructureDesignPoseSyncEvent event, read-only. Travels between peers, so positions in it are absolute.",
      "payload": "{ structureUuid, position, rotation, subGroups }",
      "sides": [
        "client",
        "server"
      ],
      "provider": "theonaris.game"
    },
    {
      "name": "game.StructureTransformSyncEvent",
      "description": "The game's StructureTransformSyncEvent event, read-only. Travels between peers, so positions in it are absolute.",
      "payload": "{ structureUuid, position, rotation }",
      "sides": [
        "client",
        "server"
      ],
      "provider": "theonaris.game"
    },
    {
      "name": "game.WeaponFiredEvent",
      "description": "The game's WeaponFiredEvent event, read-only. Travels between peers, so positions in it are absolute.",
      "payload": "{ blockUuid, origin, hit, kind, didHit, effectVariant, blockDataId, isOffline }",
      "sides": [
        "client",
        "server"
      ],
      "provider": "theonaris.game"
    },
    {
      "name": "map.loaded",
      "description": "A map finished loading. The payload says which one and whether a mod made it.",
      "payload": "{ id = string, mod = string? }",
      "sides": [
        "client",
        "server"
      ],
      "provider": "theonaris.engine"
    },
    {
      "name": "map.unloading",
      "description": "The current map is about to be left.",
      "payload": "{ id = string }",
      "sides": [
        "client",
        "server"
      ],
      "provider": "theonaris.engine"
    },
    {
      "name": "player.joined",
      "description": "A player joined the session.",
      "payload": "Player",
      "sides": [
        "client",
        "server"
      ],
      "provider": "theonaris.net"
    },
    {
      "name": "player.left",
      "description": "A player left the session. The Player is no longer valid.",
      "payload": "Player",
      "sides": [
        "client",
        "server"
      ],
      "provider": "theonaris.net"
    },
    {
      "name": "ui.screen.closed",
      "description": "One of the game's screens closed.",
      "payload": "{ id = string }",
      "sides": [
        "client"
      ],
      "provider": "theonaris.engine"
    },
    {
      "name": "ui.screen.opened",
      "description": "One of the game's screens opened, so a mod can change it again.",
      "payload": "{ id = string }",
      "sides": [
        "client"
      ],
      "provider": "theonaris.engine"
    }
  ],
  "permissions": [
    {
      "name": "audio",
      "title": "Sound",
      "description": "Play its own sounds and music.",
      "risk": "low",
      "requiresConsent": false,
      "takesArgument": false,
      "argumentHint": "",
      "provider": "theonaris.engine"
    },
    {
      "name": "building",
      "title": "Creations",
      "description": "See the blocks in creations, what you have selected, and add buttons to the building toolbar.",
      "risk": "low",
      "requiresConsent": false,
      "takesArgument": false,
      "argumentHint": "",
      "provider": "theonaris.building"
    },
    {
      "name": "building.edit",
      "title": "Change block settings",
      "description": "Change the settings of blocks on creations you own, as if you had used the block's panel.",
      "risk": "medium",
      "requiresConsent": true,
      "takesArgument": false,
      "argumentHint": "",
      "provider": "theonaris.building"
    },
    {
      "name": "building.kinetics",
      "title": "Make parts turn",
      "description": "Give blocks axles and gear teeth, mesh them and drive them, on a server you host. A mod could make creations' parts spin on their own.",
      "risk": "medium",
      "requiresConsent": true,
      "takesArgument": false,
      "argumentHint": "",
      "provider": "theonaris.building"
    },
    {
      "name": "building.limits",
      "title": "Raise part limits",
      "description": "Let engines, motors and other parts be set beyond their normal ratings — for every player on a server you host. Creations can become far more powerful than the game is balanced for.",
      "risk": "high",
      "requiresConsent": true,
      "takesArgument": false,
      "argumentHint": "",
      "provider": "theonaris.building"
    },
    {
      "name": "building.overlap",
      "title": "Place blocks inside blocks",
      "description": "Move blocks into positions that overlap other blocks, on a server you host.",
      "risk": "medium",
      "requiresConsent": true,
      "takesArgument": false,
      "argumentHint": "",
      "provider": "theonaris.building"
    },
    {
      "name": "building.physics",
      "title": "Push creations",
      "description": "Apply forces to moving creations, on a server you host.",
      "risk": "medium",
      "requiresConsent": true,
      "takesArgument": false,
      "argumentHint": "",
      "provider": "theonaris.building"
    },
    {
      "name": "camera",
      "title": "Camera",
      "description": "Move the camera or change what it sees.",
      "risk": "medium",
      "requiresConsent": true,
      "takesArgument": false,
      "argumentHint": "",
      "provider": "theonaris.engine"
    },
    {
      "name": "devtools",
      "title": "Developer console commands",
      "description": "Add its own commands to the developer console.",
      "risk": "low",
      "requiresConsent": false,
      "takesArgument": false,
      "argumentHint": "",
      "provider": "theonaris.devtools"
    },
    {
      "name": "http",
      "title": "Internet access",
      "description": "Send and receive data from a website over HTTPS. The site is named in the prompt, and it will see your IP address.",
      "risk": "high",
      "requiresConsent": true,
      "takesArgument": true,
      "argumentHint": "domain",
      "provider": "theonaris.core"
    },
    {
      "name": "input",
      "title": "Keys and buttons",
      "description": "React to keys you press. It can only see the keys it asked for by name, never everything you type.",
      "risk": "medium",
      "requiresConsent": true,
      "takesArgument": false,
      "argumentHint": "",
      "provider": "theonaris.engine"
    },
    {
      "name": "net",
      "title": "Network messages",
      "description": "Exchange messages with the same mod running on the server or on other players' games.",
      "risk": "low",
      "requiresConsent": false,
      "takesArgument": false,
      "argumentHint": "",
      "provider": "theonaris.core"
    },
    {
      "name": "players",
      "title": "Player list",
      "description": "See who is playing, their names and where they are.",
      "risk": "low",
      "requiresConsent": false,
      "takesArgument": false,
      "argumentHint": "",
      "provider": "theonaris.core"
    },
    {
      "name": "players.teleport",
      "title": "Teleport players",
      "description": "Move players to another place in the world. Only works on the server you host.",
      "risk": "medium",
      "requiresConsent": true,
      "takesArgument": false,
      "argumentHint": "",
      "provider": "theonaris.core"
    },
    {
      "name": "scenes",
      "title": "Maps",
      "description": "Add its own maps and ask the game to load one.",
      "risk": "medium",
      "requiresConsent": true,
      "takesArgument": false,
      "argumentHint": "",
      "provider": "theonaris.engine"
    },
    {
      "name": "ui",
      "title": "Interface",
      "description": "Show its own windows, panels and buttons.",
      "risk": "low",
      "requiresConsent": false,
      "takesArgument": false,
      "argumentHint": "",
      "provider": "theonaris.engine"
    },
    {
      "name": "ui.game",
      "title": "Change the game's interface",
      "description": "Add to, change or hide parts of the game's own screens. Everything it changes is put back when the mod is turned off.",
      "risk": "medium",
      "requiresConsent": true,
      "takesArgument": false,
      "argumentHint": "",
      "provider": "theonaris.engine"
    },
    {
      "name": "video",
      "title": "Video",
      "description": "Play video files it ships with.",
      "risk": "low",
      "requiresConsent": false,
      "takesArgument": false,
      "argumentHint": "",
      "provider": "theonaris.engine"
    },
    {
      "name": "world",
      "title": "Objects in the world",
      "description": "Create, move and remove objects in the world.",
      "risk": "medium",
      "requiresConsent": true,
      "takesArgument": false,
      "argumentHint": "",
      "provider": "theonaris.engine"
    }
  ],
  "contentTypes": [
    {
      "name": "blocks",
      "description": "Blocks players can build with. Each is based on one of the game's blocks, with your model, picture, sounds and settings — and may redescribe its size and faces, spinning parts, a round footprint, gear teeth (it meshes with every gear) and a whole mechanism of settings, keys, wires and a shaft drive, all run natively.",
      "sides": [
        "client",
        "server"
      ],
      "provider": "theonaris.building",
      "example": "{ \"id\": \"brass-gear\", \"name\": \"Brass Gear 32\", \"base\": \"Cube\", \"model\": \"/models/gear32.glb\", \"gear\": { \"kind\": \"spur\", \"teeth\": 32 }, \"icon\": \"/icons/gear32.png\" }"
    },
    {
      "name": "maps",
      "description": "Maps players can choose, built on one of the game's own maps with your terrain, props, lighting, sounds and effects.",
      "sides": [
        "client",
        "server"
      ],
      "provider": "theonaris.engine",
      "example": "{ \"id\": \"crater-canyon\", \"name\": \"Crater Canyon\", \"base\": \"Empty\", \"spawns\": [{ \"position\": [0, 2, 0] }], \"objects\": [{ \"model\": \"/models/canyon.glb\", \"collider\": \"mesh\" }] }"
    }
  ]
}
