# Mod API reference The contract between Horizon and its mods: the WIT package `horizon:mods@0.1.0`, every interface, type, function and hook in it, and the capabilities a manifest may list. The guide is [mods.md](../mods.md); stability and versions: [stability.md](stability.md). Manifest `api` lines this game serves: `0.1`, `0.2`, `0.3`. ## Capabilities | In `capabilities` | Grants | The player reads "May …" | | --- | --- | --- | | `game-read` | [`game`](#game) | see your position, health and the time | | `chat` | [`chat`](#chat) | show you chat messages | | `hud` | [`hud`](#hud) | draw text on your screen | | `storage` | [`storage`](#storage) | save its own settings to disk | | `registries` | data files (`assets/`, `data/`), no interface | add blocks and items to your worlds | | `players` | [`players`](#players) | see who is on the server and message them | | `world` | [`world`](#world) | read and change the world's blocks | ## World `horizon-mod` A client mod: runs in the player's game. - Imports (what the game offers): `log`, `game`, `chat`, `hud`, `storage` - Exports (what the mod provides): `events` ## World `horizon-server-mod` A server mod (manifest `side = "server"`, `api = "0.3"`, experimental): runs where the world is simulated, on the dedicated server, a LAN host and single player's own server. - Imports (what the game offers): `log`, `storage`, `players`, `world` - Exports (what the mod provides): `server-events` ## `log` Access: always granted. The mod's log, in the game's log under the mod's id. Always granted. ### enum `level` | Case | | | --- | --- | | `debug` | | | `info` | | | `warn` | | | `error` | | | Function | Signature | What it does | | --- | --- | --- | | `write` | `func(level: level, message: string)` | One line in the game's log as `[mod ] message`, at that level. | ## `game` Access: capability `game-read`. Capability `game-read`: the local player and the world clock. ### record `player` | Field | Type | | | --- | --- | --- | | `x` | `f64` | Feet position, in blocks. | | `y` | `f64` | | | `z` | `f64` | | | `yaw` | `f32` | Degrees, as F3 shows them. | | `pitch` | `f32` | Degrees: -90 looks straight up, 90 straight down. | | `health` | `f32` | Hit points as vanilla counts them: 20 is full health without effects. | | `food` | `u32` | 0 to 20, as the hunger bar. | | `dimension` | `string` | `minecraft:overworld`, `minecraft:the_nether`, ... | ### record `clock` | Field | Type | | | --- | --- | --- | | `game-time` | `u64` | Ticks since the world was created. | | `day-time` | `u64` | 24000 ticks per day; 0 is 6:00 on the first day. | | Function | Signature | What it does | | --- | --- | --- | | `get-player` | `func() -> option` | None on the title screen. | | `get-clock` | `func() -> option` | None on the title screen. | ## `chat` Access: capability `chat`. Capability `chat`: messages only the local player sees. | Function | Signature | What it does | | --- | --- | --- | | `show` | `func(text: string)` | Shown in chat after the mod's name, like a system message. | ## `hud` Access: capability `hud`. Capability `hud`: one panel of text lines per mod, drawn by the game every frame until the mod changes or clears it (no call per frame). ### enum `corner` | Case | | | --- | --- | | `top-left` | | | `top-right` | | | `bottom-left` | | | `bottom-right` | | ### record `line` | Field | Type | | | --- | --- | --- | | `text` | `string` | Plain text, up to 256 characters. | | `color` | `u32` | 0xRRGGBB. | | Function | Signature | What it does | | --- | --- | --- | | `set-panel` | `func(corner: corner, lines: list)` | Replaces the mod's panel: up to 16 lines in that corner of the screen. | | `clear` | `func()` | Removes the mod's panel. | ## `storage` Access: capability `storage`. Capability `storage`: a per-mod folder of small key/value files, quota'd (docs/mods.md). Keys are `[a-z0-9_.-]{1,64}`, one path segment. | Function | Signature | What it does | | --- | --- | --- | | `get` | `func(key: string) -> option>` | None if `key` has never been `set`, or the key is not well-formed. | | `set` | `func(key: string, value: list) -> result<_, string>` | Errs on a malformed key or over quota (bytes for the whole mod). | | `delete` | `func(key: string)` | No error if `key` was already absent. | ## `events` Access: exported by the mod: the game calls it. What the game calls. Only the hooks `init` asks for are ever called. ### record `registration` | Field | Type | | | --- | --- | --- | | `commands` | `list` | Chat commands, without the slash. A name vanilla already uses is refused (vanilla's command runs). | | `tick` | `bool` | Call `tick` every game tick (20 per second while playing). | | `frame` | `bool` | Call `frame` every rendered frame. Budget: 0.1 ms. | | `chat` | `bool` | Call `chat` for each chat line the player receives. | | Function | Signature | What it does | | --- | --- | --- | | `init` | `func() -> result` | Once, after loading. An error keeps the mod off and is shown. | | `tick` | `func(tick: u64)` | Each game tick while in a world, with the game's tick counter. | | `frame` | `func(seconds: f32)` | Each rendered frame, with the seconds since the last one. | | `command` | `func(name: string, args: string) -> result, string>` | `/name args`: ok(some(text)) is shown as feedback, err(text) in red. | | `chat` | `func(text: string)` | Each chat line the player receives, as plain text. | ## `players` Access: capability `players`. Capability `players`, server mods only (manifest `api = "0.3"`, experimental): the players on the server, and messages to them. ### enum `game-mode` | Case | | | --- | --- | | `survival` | | | `creative` | | | `adventure` | | | `spectator` | | ### record `player` | Field | Type | | | --- | --- | --- | | `id` | `string` | The player's UUID, `xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx`. | | `name` | `string` | | | `x` | `f64` | Feet position, in blocks. | | `y` | `f64` | | | `z` | `f64` | | | `dimension` | `string` | `minecraft:overworld`, `minecraft:the_nether`, ... | | `game-mode` | `game-mode` | | | `health` | `f32` | Hit points as vanilla counts them: 20 is full health without effects. | | Function | Signature | What it does | | --- | --- | --- | | `online` | `func() -> list` | The players online, in the order they joined. | | `tell` | `func(player: string, text: string) -> bool` | A system message to one player, after the mod's name; false when no player with that id is online. Up to 8 messages per call. | | `broadcast` | `func(text: string)` | A system message to every player and the server's log, after the mod's name. Counts toward the same 8 per call. | ## `world` Access: capability `world`. Capability `world`, server mods only (manifest `api = "0.3"`, experimental): the blocks of the server's loaded chunks, and changes to them through the server's own block updates. ### record `block-change` | Field | Type | | | --- | --- | --- | | `x` | `s32` | | | `y` | `s32` | | | `z` | `s32` | | | `state` | `string` | `minecraft:oak_log[axis=y]`; properties left out take the block's defaults, `minecraft:stone` alone is the default state. | | Function | Signature | What it does | | --- | --- | --- | | `get-block` | `func(dimension: string, x: s32, y: s32, z: s32) -> option` | The block state at a position in a dimension (`minecraft:overworld`, ...), as `minecraft:oak_log[axis=y]`, as of this call: none where the server has no chunk loaded there. | | `get-biome` | `func(dimension: string, x: s32, y: s32, z: s32) -> option` | The biome at a position (`minecraft:plains`, ...), as the server stores it (one per 4 x 4 x 4 cell): none where no chunk is loaded. | | `set-blocks` | `func(dimension: string, blocks: list) -> result<_, string>` | Sets blocks as `/setblock` does: the old block entity removed, neighbours and shapes updated, light, and every player told. Every state is checked now (an error queues nothing); the changes are made in order after this call returns, before that dimension's next tick; one in a chunk not loaded then is skipped. At most 4096 per call. | ## `server-events` Access: exported by the mod: the game calls it. What the server calls in a server mod (manifest `api = "0.3"`, experimental). Only the hooks `init` asks for are ever called. The player in each event is as the server saw them when it happened. ### type `player` `type player = player` ### record `registration` | Field | Type | | | --- | --- | --- | | `commands` | `list` | Commands players may type, without the slash. A name vanilla already uses is refused (vanilla's command runs). | | `tick` | `bool` | Call `tick` every server tick (20 per second). | | `joins` | `bool` | Call `player-joined` and `player-left`. | | `chat` | `bool` | Call `chat` for each chat message a player sends. | | `blocks` | `bool` | Call `block-broken` and `block-placed`. | ### record `block-pos` | Field | Type | | | --- | --- | --- | | `x` | `s32` | | | `y` | `s32` | | | `z` | `s32` | | | Function | Signature | What it does | | --- | --- | --- | | `init` | `func() -> result` | Once, after loading. An error keeps the mod off and is logged. | | `tick` | `func(tick: u64)` | Each server tick, with the server's tick counter. | | `player-joined` | `func(player: player)` | A player joined the server; they are in `players.online` already. | | `player-left` | `func(player: player)` | A player left the server; they are no longer in `players.online`. | | `chat` | `func(player: player, text: string)` | A chat message a player sent, as plain text. | | `command` | `func(player: player, name: string, args: string) -> result, string>` | `/name args` typed by `player`: ok(some(text)) is their feedback, err(text) their error in red. | | `block-broken` | `func(player: player, pos: block-pos, state: string)` | A player broke the block at `pos` in their dimension: `state` is what was there, as `minecraft:oak_log[axis=y]`. | | `block-placed` | `func(player: player, pos: block-pos, state: string)` | A player placed `state` at `pos` in their dimension. |