Files
horizon-airdef/docs/api/mods-reference.md
T

66 KiB
Raw Blame History

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; stability and versions: 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 see your position, health and the time
chat chat show you chat messages
hud hud draw text on your screen
storage storage save its own settings to disk
command command run commands as you, with your permissions
registries data files (assets/, data/), no interface add blocks and items to your worlds
ui ui show its own screens and a settings page
render render draw on your screen, shake and zoom the camera
input input see the keys you hold and your clicks, take over the use button on its own items and the mouse wheel, and add keys
players players see who is on the server and message them
world world read and change the world's blocks
recipes recipes read the game's recipes and items and which recipes you know, place recipes in your crafting grid and, in creative mode, give you items

World horizon-mod

A client mod: runs in the player's game.

  • Imports (what the game offers): log, game, chat, hud, storage, command
  • 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

World horizon-ui-mod

A mod with widgets (capability ui): the SDK builds every mod against this world. Mods built for horizon-mod alone (no ui-events export) still load and simply hear nothing of their widgets.

  • Imports (what the game offers): ui, render, input, recipes, browser, log, game, chat, hud, storage, command
  • Exports (what the mod provides): ui-events, events

World ui-host

The game's side of horizon-ui-mod beyond horizon-mod.

  • Imports (what the game offers): ui
  • Exports (what the mod provides): ui-events

World render-host

The game's side of capability render (imports only).

  • Imports (what the game offers): render, input
  • Exports (what the mod provides):

World recipes-host

The game's side of capability recipes (imports only).

  • Imports (what the game offers): recipes, browser
  • Exports (what the mod provides):

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 <id>] message, at that level.

game

Access: capability game-read.

Capability game-read: the local player, the world clock and the block the player looks at.

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.

record hit

A block along the player's view.

Field Type
block-x s32 The block hit.
block-y s32
block-z s32
x f64 The point on its face where the view meets it.
y f64
z f64
block string minecraft:stone, ...
Function Signature What it does
get-player func() -> option<player> None on the title screen.
get-clock func() -> option<clock> None on the title screen.
world-id func() -> option<string> Which world is open (AirDef fork): world:<folder> for a saved world, server:<address> on a server; none on the title screen. Mods keep their state apart by it.
raycast func(distance: f32) -> option<hit> The first block along the player's view (fluids pass), up to distance blocks (at most 1024; past the loaded chunks, across the distant terrain when LOD Distance is on), as of this tick. None when nothing is hit, and 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<line>) 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<list<u8>> None if key has never been set, or the key is not well-formed.
set func(key: string, value: list<u8>) -> 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.

command

Access: capability command.

Capability command: vanilla commands run as the player, with the player's permissions, after the hook call returns (8 per call). A mod's own commands are not run this way.

variant value-kind

What one word of a command line takes (AirDef fork, level 19).

Case Payload
word list<string> One word, anything up to the next space. The words given are only what the chat box suggests; any word is accepted.
integer tuple<option<s32>, option<s32>> A whole number, within the bounds given (either may be none).
number tuple<option<f64>, option<f64>> A number with or without decimals, within the bounds given.
choice list<string> One of these words and no other.
names string One word, suggested from the list set-suggestions last gave under this name; any word is accepted, so a list that is out of date refuses nothing.
block-pos Three coordinates: whole numbers, each one also ~ or ~n.

record tree-option

One key=value option, or a bare flag (noaudio) when value is none.

Field Type
key string
value option<value-kind>

record tree-options

The words that follow, in any order, to the end of the line.

Field Type
entries list<tree-option> The options and flags that may appear, each at most once.
free option<list<string>> Words that are no option are free words (a name): none refuses them, some accepts them and suggests the words given.

variant node-kind

Case Payload
value value-kind One word, as value-kind says.
text The rest of the line, spaces included: only a last node.
options tree-options

record tree-node

A node of a command's tree. Nodes are listed flat; a node's children come after it in the list (a tree, never a loop).

Field Type
name string A literal's word, or an argument's name (the chat box's hint shows it as <name>).
kind option<node-kind> None: a literal that must be typed as it is.
children list<u32> The nodes that may follow, by their place in the list. A word no literal child is, goes to the argument children, in order.
runs bool The line may end here (a branch with optional words after it runs without them).
Function Signature What it does
run func(line: string) line without its slash; its feedback goes to the chat as if typed.
run-quiet func(lines: list<string>) lines (each without its slash, at most 256 a call) as run does, but with nothing in the chat: no feedback and no failure. In single player and on Horizon's servers, each runs exactly as the player typing it would (the same rights), in order, 64 a tick, and the server logs one line a batch; one that carries a chat message (say, msg) is refused. On any other server they go as chat commands, and there their feedback shows: a mod running many should say so.
set-tree func(name: string, nodes: list<tree-node>) -> result<_, string> Describes the arguments of a command name the mod registered (AirDef fork, level 19), replacing the free text it takes otherwise: the chat box colours the line, shows the error and the next word before Enter, and completes it with Tab; a line that does not parse never reaches the mod's command hook (the player gets the error). A line that parses reaches it as it was typed. nodes[0] is the node right after the command's name (its literal children are the subcommands; runs says whether the bare command runs). At most 512 nodes, 256 words in a list, 64 characters in a word, no loops, no two children of a node with one name. Errs, and changes nothing, on a tree that breaks these rules; a tree for a name the mod did not register in init is ignored. Calling again replaces the tree.
set-suggestions func(topic: string, values: list<string>) Sets the words a names node suggests under topic (at most 256 of 64 characters, kept as given, the rest dropped). Call it again whenever the words change (a saved scenario, a deleted one): the chat box follows.

ui

Access: capability ui.

Capability ui: widgets the game draws with its own menus' widgets, for a screen the mod owns and a settings page in Options > Mods. Layout and drawing are the game's: a mod says what its widgets hold, never where they sit or how they look, and the game clips everything it is handed.

record text-widget

A line of text.

Field Type
id u32 The mod's own name for the widget; ui-events calls echo it.
text string Up to 256 characters.
color u32 0xRRGGBB; 0 is the menus' white.

record item-widget

An item's icon and a name beside it, as recipe viewers show them.

Field Type
id u32 The mod's own name for the widget.
item string minecraft:diamond, <mod>:<path>; an unknown id draws a "?".
name string The name shown beside the icon (empty: the item's own).

record list-widget

Rows the player picks one of, as an options page lists choices: a pick is ui-events::select, selected is the row to mark now.

Field Type
id u32 The mod's own name for the widget; ui-events::select echoes it.
rows list<string> The rows' texts, at most 512, each up to 256 characters.
selected option<u32> The row to mark as the current choice, if any.

record button-widget

A thing on a mod's screen or settings page. A button as the options pages have them (200 × 20): a click is ui-events::select(id, 0). Mods cycle its label for a choice ("Corner: Top Left").

Field Type
id u32 The mod's own name for the widget.
label string Up to 256 characters.

variant widget

Case Payload
text text-widget Text the player reads.
button button-widget A button.
item item-widget An item's icon and name.
list list-widget Rows the player picks from.

record screen

A screen the mod owns: a title over widgets stacked down the middle, the Done button the game adds, and Esc to leave it.

Field Type
title string Its title, up to 256 characters.
widgets list<widget> Its widgets, in order, at most 64.
Function Signature What it does
open-screen func(screen: screen) Show screen over the game; a second call while it is open replaces it. Only the last call of one hook counts.
close-screen func() Close the mod's screen when it is open (the mod hears no closed for this: it was its own doing).
set-settings func(widgets: list<widget>) The mod's page in Options > Mods, reached from a settings button on its row: the widgets it shows, an empty list for no page. The player opening the page is ui-events::settings-opened: push fresh widgets then; later calls update the page while it shows.

ui-events

Access: exported by the mod: the game calls it.

What the game calls on a mod that shows widgets (capability ui): what the player did with them.

Function Signature What it does
select func(id: u32, row: u32) A row of one of the mod's list widgets was picked: the widget's id and the row, on the screen or the settings page that showed it.
closed func() The player left the mod's screen (Esc or Done); not for a screen the mod closed itself or one that went away with the mod.
settings-opened func() The player opened the mod's settings page in Options > Mods: call ui::set-settings now to fill it with fresh widgets.

input

Access: capability input.

Capability input (experimental: the manifest needs experimental = ["input"]): the use button on items the mod claims, and the mod's own keys. Events wait for poll, at most 256.

record held-item

The main hand's stack.

Field Type
id string minecraft:spyglass, <mod>:<path>.
count u32
slot u32 The hotbar slot, 0 to 8.

record item-use

Field Type
item held-item
ticks u32 Game ticks the button was held (0 on use-start).

variant event

Case Payload
use-start item-use The use button went down with a claimed item in the main hand. The game does nothing else with the click: no placing, no eating, no swing.
use-stop item-use It came up again, or the item left the hand, or a screen opened.
key-down string A key register-key named went down or up while playing (no screen open). The game's own mapping on that key still runs. A screen opening lets every held key up.
key-up string
wheel f32 Mouse wheel steps while the mod holds the wheel (claim-wheel): positive away from the player, as the hotbar reads them.

record mapping-state

A mapping as the player has bound it.

Field Type
label string The bound key's name as Controls shows it: W, Space, LMB.
down bool Held down now (as of this frame for a mod with a frame hook, else this tick).
Function Signature What it does
claim-items func(ids: list<string>) The items whose use the mod handles instead of the game, by id (at most 64). Replaces the previous list.
register-key func(name: string, label: string, key: string) -> result<_, string> A key of the mod's: name comes back in key-down and key-up, label says what it does, key is the key as options.txt writes it (key.keyboard.r), the default: the player can bind another one on the mod's page in Options > Mods, and that one wins. At most 16; an unknown key is an error.
held func() -> option<held-item> The main hand's stack, as of this tick; none when it is empty.
poll func() -> list<event> The events since the last call, oldest first.
claim-wheel func(on: bool) Takes the mouse wheel while playing (true) or gives it back: while taken, its steps are the mod's wheel events and the hotbar doesn't move. The game gives it back when the mod stops.
mapping func(name: string) -> option<mapping-state> A movement or click mapping as the player has bound it: key.forward, key.left, key.back, key.right, key.jump, key.sneak, key.sprint, key.attack or key.use. None for another name.
clicks-per-second func() -> tuple<u32, u32> Clicks of the attack and use buttons in the last second.

render

Access: capability render.

Capability render (experimental: the manifest needs experimental = ["render"]): shapes the game draws for the mod with its own renderer, kept until the mod replaces them (no call per frame). A mod never supplies shader code.

enum corner

A corner of the screen, as hud's panels use them.

Case
top-left
top-right
bottom-left
bottom-right

record rect

A rectangle in GUI pixels: the top left corner and the size.

Field Type
x f32
y f32
w f32
h f32

record point

A point in GUI pixels from the screen's top left.

Field Type
x f32
y f32

record fill-shape

Field Type
rect rect
color u32 0xAARRGGBB.

record quad-shape

Any four-cornered shape (a wheel's segment, an arrow): the corners in order round it.

Field Type
corners tuple<point, point, point, point>
color u32 0xAARRGGBB.

record sprite-shape

Field Type
sprite string One of the game's GUI sprites, as gui/sprites/ names them (hud/heart/full, widget/button), the resource packs' versions included. An unknown one draws nothing.
rect rect
color u32 A tint, 0xAARRGGBB: 0xFFFFFFFF draws it as it is.

record item-shape

Field Type
item string minecraft:diamond, <mod>:<path>; an unknown one draws nothing.
at point The icon's top left.
scale f32 1.0 is the hotbar's 16 × 16.

record text-shape

Field Type
text string Up to 256 characters, one line.
at point
color u32 0xRRGGBB, as hud's lines.
centered bool Centred on at.x instead of starting there.
shadow bool

record view-shape

A picture of one of the mod's set-views cameras (AirDef fork).

Field Type
view u32 The camera's id; an unknown one draws nothing.
rect rect
mode u32 0 as seen, 1 thermal (white hot), 2 night vision (green).

record terrain-shape

A square of the world's land seen from above, in the map colours of a map item with its height shading (AirDef fork, API level 24); only in set-canvas's shapes. It is 128 × 128 texels, a texel being blocks-per-texel × blocks-per-texel blocks whose north-west corner is (x, z); the game keeps up to 24 such tiles at a time and draws none of the rest. A mod aligns the corners to multiples of 128 × blocks-per-texel so tiles meet and are reused as the view moves. Where a chunk isn't loaded the tile is transparent (the mod draws its own "unknown" under it); the game scans chunks within a small time budget a frame, so a tile fills in over a few frames.

Field Type
rect rect
x s32
z s32
blocks-per-texel u32 1, 2, 4, 8, 16, 32 or 64; another value is rounded to one.

variant shape

Case Payload
fill fill-shape
quad quad-shape
sprite sprite-shape
item item-shape
text text-shape
view view-shape
terrain terrain-shape

record frame-rate

Field Type
fps u32 Frames drawn in the last second.
min u32 The slowest frame's rate, and the 1% low (the 99th percentile frame time's rate), over the last 5 seconds.
low u32

record zoom

Field Type
factor f32 The field of view is divided by it: 1 is none, at most 10.
smooth bool Ease in and out through the game's field-of-view easing, as the spyglass does, instead of at once.
turn f32 Mouse turning is multiplied by it while zoomed: 1 keeps the player's sensitivity, at least 0.05.

record minimap

Field Type
corner corner
size f32 Its side in GUI pixels, 16 to 256.
blocks-per-pixel f32 World blocks per map pixel, 0.5 to 4; the map is 128 × 128 pixels.
rotate bool The map turns with the player, who faces up, and an N on its rim marks north. Otherwise north is up and the player's arrow turns.
round bool Round, the corners left clear; otherwise square.

record far-terrain

Field Type
distance u32 How far the distant terrain reaches, in chunks: 64 to 1024. On integrated graphics other than Apple's the game caps it lower.
reduced bool Coarser far tiles, as the Far Detail setting's Reduced: 2 to 4 ms less GPU time per frame on integrated graphics.

record model-instance

A block model drawn in the world (AirDef fork).

Field Type
id u32 Stays the same while the object lives: the game moves an id smoothly from where the last set-models put it.
model string A block state as commands write it (airdef:shahed, minecraft:stone, minecraft:furnace[facing=east]): its block model is drawn. An unknown one draws nothing.
x f64 Where the model's centre is, in blocks.
y f64
z f64
rotation tuple<f32, f32, f32, f32> Rotation about the model's centre: a quaternion (x, y, z, w).
scale f32 Uniform scale, 1.0 a block (0 to 64).
glow bool Drawn at full brightness, whatever the light where it is.

record model-instance-id

model-instance with the model as a handle.

Field Type
id u32
model u32 From model-id.
x f64
y f64
z f64
rotation tuple<f32, f32, f32, f32>
scale f32
glow bool

record particle-spawn

Particles to spawn on this client (AirDef fork).

Field Type
particle string As /particle names the type: minecraft:flame, minecraft:dust.
x f64
y f64
z f64
spread tuple<f32, f32, f32> Gaussian spread round the point, per axis, in blocks.
velocity tuple<f32, f32, f32> Every particle's starting velocity, blocks a tick.
speed f32 Gaussian speed added to it per axis.
count u32 1 to 256.
color u32 0xRRGGBB for dust and coloured types (0: white).
scale f32 Dust size (0.01 to 4).

enum source-op-kind

What a sound-sources entry does.

Case
start Starts source id (one that is already running restarts: the old one releases, the new one attacks).
update Sets everything of a running source: pose, velocity, gain, pitch, looping and the rest. An id that is not running is ignored.
stop Releases source id (fading over its release). Only id is read.

record source-op

One change of a persistent sound source (AirDef fork, API level 20): a sound that goes on, follows a pose and has a lifetime, over the game's own mixer. Unlike play-sound events they are not repeated; a source is started, updated as often as the mod likes (a tick) and stopped. The ids are the mod's own numbers (per mod, up to 256 running).

Field Type
kind source-op-kind
id u32
event string The sound event (<mod>:<name>), read by start: the same variant is chosen for the whole life of the source.
x f64 Where it is, in the world as the listener hears it (the listener stays at the player; a mod that shows another place moves the source by the offset itself).
y f64
z f64
vx f32 Blocks a second. The mixer carries the source on along it between calls (at most 0.15 s), so a source updated once a tick moves without steps. Also what Doppler reads.
vy f32
vz f32
gain f32 0 to 16, times the event's volume and the category sliders; above 1 it only widens the distance it is heard from, as in vanilla.
pitch f32 0.5 to 2, the sound's own pitch (Doppler is added by doppler).
looping bool A looping source goes on until stopped; a source that is not looping plays once and is gone.
priority f32 More important sources keep their voice when there are not enough (0.1 to 10, 1 usually). Sources are ranked by priority times what the listener would hear, 24 get a voice; the others stay virtual (silent but alive, a loop only) and are heard when they rank again.
attack f32 Seconds to fade in (0 to 5; 0 is 5 ms, so there is no click).
release f32 Seconds to fade out after stop (0 to 5; 0 is 5 ms).
doppler f32 How much of the Doppler shift of the velocity is applied, 0 (none, the usual choice) to 1, bounded to a change of pitch of 12%. The velocity is taken against a listener at rest. Leave 0 when the pitch already follows the speed.
loop-from f32 A looping source repeats the part of its sound from loop-from to loop-to seconds into it (both 0: all of it), the join crossfaded over 50 ms: for sounds that fade in and die away at their ends.
loop-to f32

record canvas-button

What the player did on the mod's canvas (AirDef fork, API level 24). Points are in GUI pixels from the screen's top left.

Field Type
button u32 0 left, 1 right, 2 middle, 3 and up the side buttons.
at point

record canvas-scroll

Field Type
steps f32 Wheel steps, positive away from the player (up).
at point

variant canvas-event

Case Payload
moved point The pointer moved (one event a frame at most).
pressed canvas-button
released canvas-button
scrolled canvas-scroll
key string A key went down or repeated: key.keyboard.escape, as options.txt writes it. Escape does not close the canvas by itself: the mod does, with close-canvas.
resized tuple<f32, f32> The screen's size changed, or the canvas opened: width, height.

enum policy

What a block is to a query (AirDef fork): the three policies differ on purpose, so a sensor and a missile may disagree about a pane of glass.

Case
collision Projectile collision: every block with a collision shape stops it (stone, leaves, glass, slabs, fences); air, fluids, plants and other shapeless blocks let it pass.
sight Sensor line of sight: opaque blocks (those that stop light) only; glass, leaves and fluids are seen through.
sound Sound occlusion: blocks with a full-cube collision shape.

enum verdict

How a query ended. Never clear for a chunk that isn't loaded.

Case
clear Nothing on the way, everything checked.
hit A block stops it; see the other fields.
unknown A part of the way is in a chunk the game doesn't have (far terrain, not yet loaded) or the budget ran out: no verdict. A hit found before the unknown part still comes back as hit.

record ray

A segment to trace through the loaded blocks.

Field Type
id u32 Echoed in the answer.
start tuple<f64, f64, f64>
end tuple<f64, f64, f64>
policy policy

record ray-answer

Field Type
id u32
verdict verdict
fraction f64 For a hit: how far along the segment, 0 to 1, where it enters the shape.
normal tuple<s32, s32, s32> For a hit: the face normal (the axis it entered along).
block tuple<s32, s32, s32> For a hit: the block hit.
known-to f64 For an unknown: how far along the segment the unknown part begins.

enum section-fill

What a 16 x 16 x 16 section of the world holds, for a policy.

Case
unknown The game has no such chunk loaded: nothing is known.
empty Nothing in it stops a query.
full Every block in it does.
mixed Some do: bits tells which.

record section

Field Type
x s32 Section coordinates: block x, y, z divided by 16, rounded down.
y s32
z s32
fill section-fill
bits list<u8> For mixed: 512 bytes, one bit per block, set where it stops the policy's query. The index is (y & 15) * 256 + (z & 15) * 16 + (x & 15); bit i is bit (i & 7) of byte i / 8. Empty otherwise.

record changes

Changes to the world since the last tick, for a mod's cache.

Field Type
epoch u32 A number that changes when another world or dimension opens: everything cached before is void.
revision u64 Counts block changes in the loaded world, ever (wraps).
overflow bool More sections changed than fit: treat everything as changed.
sections list<tuple<s32, s32, s32>> Sections (as in section) where a block changed, at most 256.

record camera-view

A camera the game renders the world from besides the player's eye (AirDef fork): the land, the sky and the entities near the player.

Field Type
id u32 Stays the same while the camera lives: the game turns it smoothly between the last two set-views.
x f64
y f64
z f64
yaw f32 Degrees, as the player's: yaw 0 looks south (+z), pitch 90 down.
pitch f32
fov f32 Vertical field of view, degrees (1 to 110).
width u32 The picture's size in pixels (16 to 3840 × 16 to 2160).
height u32

record point-light

A light the mod's things give off (AirDef fork): rocket flames, flares, blasts. Drawn by the HD lighting (set-lighting).

Field Type
id u32 Stays the same while the light lives: the game moves it smoothly.
x f64
y f64
z f64
color tuple<f32, f32, f32> Linear RGB, 0 to 1.
intensity f32 Brightness: about what it lights one block away (0 to 100000).
radius f32 Nothing past this many blocks (1 to 256).

record lighting

The HD lighting (AirDef fork): the world lit per pixel by the mods' lights, in high dynamic range, with bloom and tone mapping.

Field Type
hd bool
exposure f32 1 as is; more brightens.
bloom f32 How much bright things glow (0 none, 1 strong).

record smoke-segment

A piece of smoke or exhaust trail (AirDef fork): a tube from a to b (equal ends: a puff) that the HD renderer ray-marches as a volume, lit by the sun, the sky and the mod's lights, and that thins the fog and clouds it passes through. The game derives everything from the age (clock - born): the radius grows from radius-start to radius-end, the density fades to nothing at life, the smoke drifts with the wind and rises by rise, so a segment is sent once per change of the set, not per frame, and a replay that seeks sends the segments of that moment.

Field Type
id u32 Seeds the smoke's noise.
ax f64
ay f64
az f64
bx f64
by f64
bz f64
born f64 When it was made, in the clock of set-smoke (ticks).
life f32 How long it lasts, in the same ticks (1 to 72000).
radius-start f32 Radius of the tube in blocks at birth and at the end of its life.
radius-end f32
density f32 How thick it is at the core at birth: extinction per block (0 to 8).
heat f32 How hot it glows at birth, 0 soot to 1 white hot; it cools in seconds.
soot f32 How dark it is, 0 white vapour to 1 black soot.
rise f32 Blocks per second it floats up (negative sinks).
clear f32 Radius in blocks of the clear tunnel it leaves in fog and cloud, filling back in over life (0 none).

record spot-light

A directional light with a visible beam (AirDef fork): a searchlight, a headlight. The HD lighting lights the surfaces and flying things inside its cone (smoothly from the inner to the outer angle, down to nothing at range) and draws the beam as a translucent volume lit from inside: it scatters in the air (more in fog and smoke, a faint artistic one in clear air), the world hides it where it is in front, and the camera may stand inside it. The light does not look for walls: send range as far as the beam is free (a cast along the axis) so it stops where the land stops it.

Field Type
id u32 Stays the same while the light lives: the game moves it smoothly.
x f64 The apex, in the lens.
y f64
z f64
dx f32 Where it points (any length but zero; it is normalised).
dy f32
dz f32
color tuple<f32, f32, f32> Linear RGB, 0 to 1.
intensity f32 Brightness: about what it lights one block away (0 to 100000).
range f32 Nothing past this many blocks (1 to 1024).
inner-angle f32 Half angle in radians where the light is at full strength (0.005 to 1.2).
outer-angle f32 Half angle in radians where it has faded to nothing (past the inner one, to 1.4).
beam f32 How visible the beam is in the air, 0 (the light only lights things) to 1.

record capture-options

What capture-start records (AirDef fork, API level 17).

Field Type
folder string A folder under the game's home (letters, digits, -, _ and /; no ..); made if missing. The result lands in it.
name string The file name without its extension (letters, digits, -, _, .).
fps u32 Frames a second of the picture (1 to 120).
width u32 The picture's size in pixels; 0 keeps the window's. An offscreen game is resized to it, a window asked to be (what it gets is in the state).
height u32
crf u32 x264 quality, 0 (lossless) to 51; 14 is visually clean.
audio bool Mix the sounds the mod plays (play-sound) into the file's audio track, heard from the main view's camera at the capture's own time.
warmup u32 Frames drawn and thrown away after a cut (a new set-main-view id) so the anti-aliasing and the volumes settle in the new shot (0 to 32).

enum capture-phase

Where a capture is.

Case
idle Nothing running (or never started).
arming Asked; waiting for the picture to reach the size.
recording Frames are being rendered and written.
encoding The frames are written; the encoder is closing the file.
done Finished: file is the result.
failed Stopped by an error or cancelled: message says why.

record capture-state

Field Type
phase capture-phase
frames u32 Frames written so far.
width u32 The size of the frames, once known.
height u32
file string The result: the MP4, or the folder of the PNG sequence when no ffmpeg was found. Empty until done.
message string An error, or a note about the result (no encoder, no audio).
Function Signature What it does
set-hud func(shapes: list<shape>) Replaces the mod's HUD shapes: up to 1024, drawn every frame in order over the HUD (after the hotbar, under chat and screens), hidden with the HUD (F1). An empty list removes them.
gui-size func() -> tuple<f32, f32> The screen's size in GUI pixels (width, height), as of this tick.
shake func(strength: f32, seconds: f32) Shakes the camera: a jolt of strength (0 to 1, 1 the hardest) that fades out over seconds (at most 10). Jolts add up to 1. The view turns, the player doesn't, and the player's Distortion Effects option scales it (0 turns it off).
set-corner func(corner: corner, width: f32, height: f32, shapes: list<shape>) Replaces the mod's corner panel: shapes in GUI pixels from the top left of a width × height box that the game places in corner, stacked with the game's overlays and the other mods' panels (under the status effects at the top right), as hud's panels are.
clear-corner func() Removes the mod's corner panel.
text-width func(text: string) -> f32 The width of one line of text in GUI pixels, in the HUD's font: exact for Latin letters (U+0000 to U+024F), 6 per other character.
frame-stats func() -> frame-rate The game's frame counter, recomputed twice a second.
set-zoom func(zoom: zoom) Zooms the camera until the next call (factor 1 ends it), only while playing: a screen opening or the spyglass's own view (which wins) leave the camera vanilla's. With several mods, the strongest zoom counts.
set-minimap func(minimap: option<minimap>) Shows a map of the world around the player in corner, stacked with the game's overlays and the mods' panels, until the next call (none hides it). It looks like a map item: vanilla's map colours with their height shading and water depth, and the player's arrow. Underground, under a roof and in the Nether it maps the floor around the player's height. The game keeps the map's tiles and refreshes them within its own frame budget; hidden, they are dropped. One map shows at a time: the first loaded mod's.
set-far-terrain func(far-terrain: option<far-terrain>) Draws the world beyond the render distance as distant terrain, out to distance chunks, until the next call (none ends it). The game builds it on its own workers, from the chunks already loaded or saved and, where nobody has been, from the world's generator; the simulation distance doesn't change. Only worlds whose generator the game has (single player and a LAN world you host) show it. The player's own LOD Distance setting, when on, wins. One far terrain shows at a time: the first loaded mod's.
set-models func(models: list<model-instance>) Replaces the mod's models: up to 4096, drawn with the world's entities until replaced. Call it once a tick: the game interpolates each id between its last two positions and rotations every frame. An empty list removes them.
model-id func(model: string) -> option<u32> A handle for a block state name, for set-models-by-id (AirDef fork, API level 11): the name crosses once, not every tick. None for a name that is no block state of the game's registry (nothing is remembered for it). Handles are valid until model-generation changes (the registry changed: a resource reload, another world's data); ask again for every name then.
model-generation func() -> u32 Moves on whenever the handles model-id gave stop being valid. A mod reads it before set-models-by-id and re-asks when it changed.
set-models-by-id func(generation: u32, models: list<model-instance-id>) -> bool set-models with handles instead of names: the same models, limits and interpolation, fewer bytes across the boundary. generation is the model-generation the handles were asked under; if it is not the current one the call is ignored and returns false (re-ask the handles and call again). Handles the game doesn't know draw nothing.
spawn-particles func(particles: list<particle-spawn>) Spawns particles on this client only: no command, no server. At most 512 spawns a call.
play-sound func(event: string, x: f64, y: f64, z: f64, volume: f32, pitch: f32) Plays a sound event (minecraft:entity.generic.explode, <mod>:<name>) at a point on this client.
sound-source-generation func() -> u32 Moves on whenever the game released every source of every mod (the world closed, the session ended, a film began or ended, the sounds reloaded). A mod reads it before sound-sources and starts its sources again when it changed.
acoustics func() -> bool Whether the game muffles sounds by what lies between them and the listener (AirDef fork, API level 21: HORIZON_ACOUSTICS). A mod that muffles by itself (a _far variant for a distant blast) plays the near one instead when this is true, so nothing is muffled twice.
set-acoustics func(on: bool) Turns that on or off (AirDef fork, API level 23), from the next tick: what HORIZON_ACOUSTICS sets at the start. Sounds that play go back to the plain ones smoothly.
sound-sources func(generation: u32, ops: list<source-op>) -> bool Starts, updates and stops persistent sound sources. generation is the sound-source-generation the mod's sources belong to; if it is not the current one the call is ignored and returns false (read the generation, forget the sources, start them again). Stops are never dropped by a limit: only new sources beyond 256 running are, and at most 512 entries a call count. Every source of a mod that stops or is reloaded is released by the game.
query-ground func(columns: list<tuple<s32, s32>>) Asks for the ground height of these columns (x, z): at most 512 a tick, answered by ground from the next tick on.
ground func() -> list<tuple<s32, s32, s32>> The answers to the last tick's query-ground: (x, z, y), y one above the highest block that blocks motion or holds a fluid, as the motion blocking heightmap; -64 where the chunk isn't loaded; -2147483648 (i32::MIN) where it isn't loaded yet but load-chunks has it on its way: ask again in a few ticks.
load-chunks func(chunks: list<tuple<s32, s32>>) Has the game load these chunks (chunk x, chunk z) for a while (AirDef fork, API level 22): generated or read from disk on the game's worker threads, meshed never, and kept loaded for 20 seconds after the last call that named them. At most 64 chunks are wanted at once (the oldest requests fall away first; 64 a call). On a server, in a world the game does not simulate itself, or with nothing running, it does nothing, and ground keeps answering -64 for the unloaded.
open-canvas func() Shows a full-screen canvas over the game (AirDef fork, API level 24): the mod's set-canvas shapes over a dark background, with the pointer free. The world goes on running (no pause), the mouse is released, and every key and button goes to the mod as canvas-events, none to the game. Needs nothing the mod can't do without: when the mod stops the canvas closes. Not on the title screen.
close-canvas func() Closes the canvas when it is open.
set-canvas func(shapes: list<shape>) Replaces the canvas's shapes: up to 8192, drawn in order every frame until the next call.
canvas-events func() -> list<canvas-event> The events since the last call, oldest first, at most 256.
canvas-open func() -> bool Whether the canvas is up (the game never closes it but at the mod's word, or when the world is left).
query-rays func(rays: list<ray>) Traces segments through the loaded blocks (AirDef fork): each is walked block by block on the host, against the real collision shapes (policy), and answered by rays from the next tick on. At most 256 segments a tick, each at most 512 blocks long (longer ones are answered unknown past that); over the budget they are answered unknown too, never clear. A game with no chunk at a place answers unknown for it.
rays func() -> list<ray-answer> The answers to the last tick's query-rays, in the order asked.
query-sections func(policy: policy, sections: list<tuple<s32, s32, s32>>) Asks what these sections hold (AirDef fork), for a mod that traces its own paths against a cache of them: at most 64 a tick, answered by sections from the next tick on. Over the budget they are not answered: ask again.
sections func() -> list<section> The answers to the last tick's query-sections.
world-changes func() -> changes The block changes of the last tick (placed, broken, exploded) and the world's epoch. Only changes in chunks the game has loaded.
set-post func(wgsl: string) A full-screen post pass (AirDef fork): WGSL defining fn post(uv: vec2<f32>, pixel: vec2<f32>) -> vec4<f32>, after a prelude with frame (camera matrices, time, params), the world's colour and depth and helpers (scene, depth-at, view-dir, scene-distance, project). It runs after the world, before the hand and the HUD. Compile errors come back in the chat and the log; the last good pass keeps running.
clear-post func() Removes this mod's post pass: the world is shown as the game draws it.
set-params func(params: list<f32>) The pass's frame.params (up to 1024 floats, as 256 vec4), kept until replaced; call it once a tick (the pass gets the partial tick in frame.time.y).
set-views func(views: list<camera-view>) Replaces the mod's cameras: up to 8. A view shape shows one; the game renders up to three a frame, in turn.
set-main-view func(view: option<u32>) Renders the screen's world from one of the set-views cameras (AirDef fork), with everything the player's own view has: the HD lighting, sky, clouds, fog, smoke, TAA and the post passes, at the window's resolution. The picture size of that camera is ignored, the player's hand, block outline and the game's HUD are not drawn (the mod's own set-hud shapes are); a view shape of that camera draws nothing. For a full-screen replay or a director's camera; the small pictures of monitors stay view shapes. None (or an unknown id) is the player's own view. The chunks stay those round the player.
set-lights func(lights: list<point-light>) Replaces the mod's lights: up to 512, interpolated per id between the last two calls.
set-lighting func(lighting: lighting) Switches the HD lighting on or off for this mod's world, with its exposure and bloom; off, the world is drawn as the game draws it.
set-time-override func(day-time: option<u64>) Shows the world at this time of day (AirDef fork): the sky, the sun and moon, the sky light and the fog, as day-time ticks (24000 a day, as clock). Only what the player sees changes: the world's own clock, its saves and its rules do not. None shows the world's own time.
set-smoke func(clock: f64, segments: list<smoke-segment>) -> bool Replaces the mod's smoke: up to 4096 segments, clock being now in ticks (the game shows the age between the last two calls). Returns whether the HD renderer draws them; when it does not (the effects preset, HD smoke off), the mod draws its own smoke.
set-spot-lights func(lights: list<spot-light>) -> bool Replaces the mod's spot lights: up to 32 (the nearest 16 are drawn), interpolated per id between the last two calls. Returns whether the HD renderer draws them with their beams; when it does not (the effects preset, HD off), the mod draws its own beam if it wants one.
capture-start func(options: capture-options) -> result<_, string> Records the screen frame by frame (AirDef fork), at a fixed time step whatever the speed of the machine: while it records, the game clock advances exactly 1 / fps seconds a frame (ticks, interpolation, the mod's ticks and the sounds with it), so a slow frame is a longer wait and not a skipped one. The frames are read back from the GPU and encoded to H.264 MP4 by ffmpeg (found on the PATH, or named by HORIZON_FFMPEG) through a bounded queue, never held in memory; with no ffmpeg they are written as a PNG sequence. Returns an error for a capture already running, a bad name, or an invalid size. Only the game's own files are written, under its home.
capture-stop func(cancel: bool) Ends the capture: finishes the file, or (cancel) throws it away.
capture-status func() -> capture-state The capture's state; done and failed stay until the next start.
set-film-quality func(on: bool) Asks for the best picture the renderer can give (AirDef fork, level 17): the HD world at the full size of the window (no resolution scale, so no upscaling), and the volumetric clouds and fog marched with more steps. Meant for replays and films; false restores the player's settings. A capture turns it on for its duration.
world-log-start func() -> u32 Starts a log of the world's block changes as the game's client sees them (AirDef fork, level 18): each change keeps its position, the state before and after, and the game tick (the number tick is called with). It is bounded (about a million changes): the oldest go first. Returns the log's id, which stays the same while it runs (a second call returns it). Only the world open now has it: a new world (leaving, rejoining) loses it. Not kept when the world runs in the game's own frame (--in-frame), where world-log-range stays none.
world-log-stop func(id: u32) Ends the log and forgets what it kept (a different id is ignored).
world-log-range func(id: u32) -> option<tuple<u64, u64>> What the log covers, as (the earliest tick whose world it can show, the tick it is at now); none for an unknown id, a log of another world, or one that has not been taken up yet (the tick after world-log-start). Asking for a time before the earliest shows the earliest.
set-world-time-view func(view: option<tuple<u32, u64>>) Shows the world as it stood at a game tick, (log id, tick), to the player's eyes only (AirDef fork, level 18): the changes logged after it are undone in the game's own copy of the blocks, a little each frame, and redone as the tick moves on; none (or the mod stopping, the world changing) puts every block back. The server, the saves, the player's own collision and the blocks next to the player are untouched, and changes that arrive meanwhile are kept and shown when the view ends. Chunks that are not loaded are skipped.

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<string> 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<registration, string> 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<option<string>, 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.

recipes

Access: capability recipes.

Capability recipes (experimental): the recipes and items the game knows, for recipe viewers. In single player and on Horizon's servers they are the world's; on any other server they are vanilla 26.3's (a client is sent no others), while known follows that server's book.

record stack

An item of items, by its index there, with a count and the components it has beyond the item's own, in vanilla's item syntax ([potion_contents={potion:"minecraft:swiftness"}]), or "".

Field Type
item u32
count u32
components string

enum kind

The station a recipe is made at.

Case
crafting-shaped
crafting-shapeless
smelting
blasting
smoking
campfire
stonecutting
smithing
brewing

record recipe

Field Type
id string minecraft:oak_planks.
kind kind
category string The recipe book's tab (crafting_building_blocks, furnace_food), or "".
group string Recipes the book shows on one button share a group, or "".
width u32 A shaped recipe's grid: slots holds its cells row by row. 0 for the other kinds.
height u32
slots list<list<stack>> Each slot's stacks, any one of which fits; an empty list is an empty cell. Cooking and stonecutting: the input. Smithing: the template, the base, the addition. Brewing: the bottle, the reagent.
results list<stack> What it makes; several when that varies (a trim on any armour).
cooking-time u32 Cooking: game ticks and experience; 0 for the other kinds.
experience f32
book-id s32 The recipe book's id for it (one per way the book shows it), as known lists them; -1 for the kinds the book doesn't show (campfire, stonecutting, smithing, brewing).

record item

Field Type
id string minecraft:diamond, <mod>:<path>.
name string In the player's language.
tags list<string> Its item tags, without the #.
Function Signature What it does
items func() -> list<item> Every item, in the registry's order: stack.item indexes this list.
all func() -> list<recipe> Every recipe: the book's in its order, then campfire, stonecutting, smithing and brewing. They don't change while a world is open.
known func() -> list<s32> The book-ids of the recipes the player's recipe book holds now.
place func(book-id: s32, all: bool) -> result<_, string> Places a recipe in the open screen's grid as a click in the recipe book does (ServerboundPlaceRecipePacket): the inventory's grid or a crafting table. all places as many as the items allow, as with Shift. Refused while no such screen is open, for a recipe the player's book doesn't hold and for one that can't be placed; one missing items shows as a ghost in the grid, as in the book.
give func(stack: stack) -> result<_, string> Creative mode only: gives the player the stack, as taking it from the creative inventory does (ServerboundSetCreativeModeSlot): the selected slot first, then the hotbar, then the inventory. The count is cut to one stack of the item (64, 16 or 1).

browser

Access: not granted by any capability.

Capability ui (experimental): a recipe viewer's panel beside the game's inventory and container screens (not the creative inventory), on the right of the screen. The game draws it with its own widgets and slots, pages it and keeps its search box; the mod says what it holds. The first loaded mod with a panel shows.

record stack

An item to show: its id, a count (1 draws none) and its components beyond the item's own, in vanilla's item syntax, or "".

Field Type
item string
count u32
components string

record click

A click on an item of the panel, by its index in set-items's list.

Field Type
index u32
right bool

record item-key

A key the mod registered (input.register-key) went down while the pointer was on an item: a slot of the screen's, or the panel's.

Field Type
key string
stack stack

record slot-click

A click on a slot of a recipe the panel shows (set-recipes).

Field Type
recipe u32 The recipe's index in set-recipes's list and the slot's in it; the results come after the slots.
slot u32
stack stack The stack the slot showed at that moment.
right bool

variant event

Case Payload
clicked click
search string The search box's text, each time the player changes it.
key item-key
slot-clicked slot-click
action u32 The action button of the recipe at this index in set-recipes's list.
page u32 The player turned the recipes' page (set-recipes): the index of the first recipe now shown.
back The back button of set-recipes.
tab u32 The player picked the tab at this index of set-recipes' tabs.

enum layout

How the game lays out a recipe of set-recipes.

Case
grid A crafting grid of width x height slots, an arrow and the result.
cooking One input over a flame, an arrow and the result (furnaces, smokers, campfires).
single One input, an arrow and the result (the stonecutter).
smithing Template, base and addition, an arrow and the result.
brewing A potion and an ingredient, an arrow and the result.

record recipe-view

A recipe to show. Each slot, and the result, cycles through its stacks, one a second; an empty slot shows nothing.

Field Type
layout layout
width u32 The grid's size (grid only), at most 3 x 3.
height u32
slots list<list<stack>>
results list<stack>
note string A short line under the recipe (a cooking time), or "".
action option<bool> The action button beside it: none, enabled, or shown greyed.
Function Signature What it does
set-items func(items: list<stack>) The panel's items, at most 8192 (an empty list hides the panel).
set-recipes func(title: string, tabs: list<stack>, tab: u32, recipes: list<recipe-view>) Shows these recipes in the panel instead of its items, as many as fit a page, under title and a back button, with a row of tabs (each an icon; tab is the selected one) between them; an empty list of recipes shows the items again. At most 256 recipes and 16 tabs.
poll func() -> list<event> What the player did on the panel since the last poll, at most 256 kept.

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<player> 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<string> 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<string> 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<block-change>) -> 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 block-pos

Field Type
x s32
y s32
z s32

variant argument-kind

What an argument of a command takes. The server sends each command and its arguments to players' games, whose chat box completes and colours them as vanilla's; the server parses them before the mod's command hook gets their values.

Case Payload
word One word: letters, digits and _ - . +.
text The rest of the line, spaces included: only last.
integer tuple<option<s32>, option<s32>> A whole number, within the bounds given.
number A number with or without decimals.
boolean true or false.
player One online player: a name, or @s or @p (whoever typed it, as vanilla picks for a player).
block-pos A block position: three whole numbers, each one also ~ or ~n, relative to whoever typed it.

record argument

Field Type
name string Shown in the chat box's hint (<height>) and the key of its value.
kind argument-kind
optional bool Optional arguments come after every required one.

record server-command

Field Type
name string Without the slash. A name vanilla already uses is refused (vanilla's command runs).
arguments list<argument> In order; none: the command takes nothing after its name. Free text is one optional text argument.

variant argument-value

An argument's value, parsed as its kind says.

Case Payload
word string
text string
integer s32
number f64
boolean bool
player player
block-pos block-pos

record registration

Field Type
commands list<server-command> Commands players may type.
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.
Function Signature What it does
init func() -> result<registration, string> 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, values: list<tuple<string, argument-value>>) -> result<option<string>, string> /name args typed by player: ok(some(text)) is their feedback, err(text) their error in red. values holds each argument given, by name, in order (an optional one left out isn't there); a line that doesn't parse never reaches the mod: the player gets vanilla's error.
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.