Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Worlds and callbacks

A world names the host imports and guest exports of a component. Included worlds are expanded below. Each imported interface documents its own grants.

extension

Experimental developer contract; no WASI or ambient operating-system access.

Imports

Exports

init

init: func();

Creates the initial retained UI state.

frame

frame: func();

Runs a frame transaction with frozen input, session and clock observations. The host may suspend it without refilling fuel; time only schedules work. Output publishes after successful post-return. Late input actions are dropped. Instances exporting decision handlers keep synchronous frame execution.

filtered-player-mod

Explicit opt-in player-mod world for generic action filtering. Existing player-mod components remain supported and do not claim filter ownership.

Imports

data-source

What a data-changed reports as changed. Closed: changing it would refuse every built data-changed, so a new kind of change arrives as a new optional export instead.

enum data-source {
    items,
    recipes,
}
MemberTypeDescription
items
recipes

Exports

filter-actions

filter-actions: func(frame: action-frame) -> action-verdict;

Optional and explicitly exported by filtering modules; requires controls authority. The earliest active exporting module is the sole owner. Runs after ordinary frame callbacks, before gameplay, with independent ACTION_FILTER_FUEL from mod-api and no host-import calls. Called for transitions and every frame with a retained hold. No callback is needed for an idle physical hold. Suppressing a release retains its hold. Suppressing its following press joins that hold; accepting that press completes the outstanding release before a fresh press. Suppressing a fresh press blocks its gesture until release. Rejected repeats leave the existing hold intact. Native never creates a press without an observed source. Traps or invalid verdicts quarantine the module and complete retained releases; owner loss and input-authority interruptions do the same. Suppressed physical holds stay suppressed until release. No duration or filtering policy is imposed by the host.

Types: action-frame, action-verdict.

screen-changed

screen-changed: func(layout: option<screen-layout>);

A container screen opened, closed (none) or was laid out anew.

Types: screen-layout.

action

action: func(id: string, collection-index: option<u32>);

A primary press on an overlay or view control mapped to a declared action; the index is the control’s row in its nearest collection.

secondary-action

secondary-action: func(id: string, collection-index: option<u32>);

A secondary press (a right click) on a control that maps button.menu_secondary_select to a declared action.

scrolled

scrolled: func(delta: f64, x: f64, y: f64, modifiers: modifiers);

The wheel turned delta notches (one per detent; a pixel-precise wheel reports its pixels / 16) with the pointer at x, y in GUI units, over the overlay’s drawn area or the view, with modifiers held. Positive scrolls down, towards the end.

Types: modifiers.

text-changed

text-changed: func(control: string, text: string);

The text of the edit box named control, a declared action, changed.

key

key: func(id: string, hovered: option<stack>, row: option<tuple<string, u32>>);

A declared key was pressed while a container screen or the view was up and no edit box had focus. hovered is the vanilla slot’s stack under the pointer; row is the collection name and index of the mod’s control under the pointer, overlay or view, by the rule action uses (its nearest collection).

Types: stack.

data-changed

data-changed: func(sources: list<data-source>);

The listed session sources changed revision, each listed once. It gets the load fuel budget, as does init of a component that exports it.

Types: data-source.

view-closed

view-closed: func();

The host closed the view (Escape, or the container closing), not the mod.

init

init: func();

Creates the initial retained UI state.

frame

frame: func();

Runs a frame transaction with frozen input, session and clock observations. The host may suspend it without refilling fuel; time only schedules work. Output publishes after successful post-return. Late input actions are dropped. Instances exporting decision handlers keep synchronous frame execution.

handled-player-mod

A personal component with the action filter, every event handler, and ordinary frame and UI callbacks. A component needing fewer composes its own world from player-mod or filtered-player-mod and the handler worlds it implements.

Imports

data-source

What a data-changed reports as changed. Closed: changing it would refuse every built data-changed, so a new kind of change arrives as a new optional export instead.

enum data-source {
    items,
    recipes,
}
MemberTypeDescription
items
recipes

Exports

filter-actions

filter-actions: func(frame: action-frame) -> action-verdict;

Optional and explicitly exported by filtering modules; requires controls authority. The earliest active exporting module is the sole owner. Runs after ordinary frame callbacks, before gameplay, with independent ACTION_FILTER_FUEL from mod-api and no host-import calls. Called for transitions and every frame with a retained hold. No callback is needed for an idle physical hold. Suppressing a release retains its hold. Suppressing its following press joins that hold; accepting that press completes the outstanding release before a fresh press. Suppressing a fresh press blocks its gesture until release. Rejected repeats leave the existing hold intact. Native never creates a press without an observed source. Traps or invalid verdicts quarantine the module and complete retained releases; owner loss and input-authority interruptions do the same. Suppressed physical holds stay suppressed until release. No duration or filtering policy is imposed by the host.

Types: action-frame, action-verdict.

screen-changed

screen-changed: func(layout: option<screen-layout>);

A container screen opened, closed (none) or was laid out anew.

Types: screen-layout.

action

action: func(id: string, collection-index: option<u32>);

A primary press on an overlay or view control mapped to a declared action; the index is the control’s row in its nearest collection.

secondary-action

secondary-action: func(id: string, collection-index: option<u32>);

A secondary press (a right click) on a control that maps button.menu_secondary_select to a declared action.

scrolled

scrolled: func(delta: f64, x: f64, y: f64, modifiers: modifiers);

The wheel turned delta notches (one per detent; a pixel-precise wheel reports its pixels / 16) with the pointer at x, y in GUI units, over the overlay’s drawn area or the view, with modifiers held. Positive scrolls down, towards the end.

Types: modifiers.

text-changed

text-changed: func(control: string, text: string);

The text of the edit box named control, a declared action, changed.

key

key: func(id: string, hovered: option<stack>, row: option<tuple<string, u32>>);

A declared key was pressed while a container screen or the view was up and no edit box had focus. hovered is the vanilla slot’s stack under the pointer; row is the collection name and index of the mod’s control under the pointer, overlay or view, by the rule action uses (its nearest collection).

Types: stack.

data-changed

data-changed: func(sources: list<data-source>);

The listed session sources changed revision, each listed once. It gets the load fuel budget, as does init of a component that exports it.

Types: data-source.

view-closed

view-closed: func();

The host closed the view (Escape, or the container closing), not the mod.

init

init: func();

Creates the initial retained UI state.

frame

frame: func();

Runs a frame transaction with frozen input, session and clock observations. The host may suspend it without refilling fuel; time only schedules work. Output publishes after successful post-return. Late input actions are dropped. Instances exporting decision handlers keep synchronous frame execution.

handle-sound

handle-sound: func(ctx: sound-context) -> sound-context;

One call per new playback request, at most 256 per audio frame; excess and oversized requests play unhandled. Approved starts waiting for decoding are not offered again. Playing voices are not retroactively stopped; managed loops are offered again when they next need a start.

Types: sound-context.

handle-teleport

handle-teleport: func(ctx: teleport-context) -> teleport-context;

One call per committed local-player MovePlayer with a finite rotation, before it applies. The server’s rotation is reported as sent, even outside -90..90 pitch. Returning the incoming rotation is always valid; a replacement must be finite with pitch in -90..90.

Types: teleport-context.

packet-mod

A trusted mod that relays every session packet. It needs the packets grant; WASI preview 2 is linked only with the wasi grant, without files, environment, arguments or network.

Imports

Exports

start

start: func(identity: session-identity, client-data: string, startup: list<u8>) -> result<list<session-pack>, string>;

Begins a session: the upstream identity, the login client data as the session’s Connect sent it (JSON), and the server’s startup packets through StartGame as one batch body. Returns the resource packs the mod adds.

Types: session-identity, session-pack.

on-batch

on-batch: func(direction: direction, batch: list<u8>) -> result<option<list<u8>>, string>;

Handles one relayed batch: none forwards it unchanged; some replaces it, and an empty body drops it.

Types: direction.

tick

tick: func() -> result<outbound, string>;

Runs timed work about once per client tick (50 ms) and returns packets to send now.

Types: outbound.

stop

stop: func();

Ends the session.

player-mod

extension plus screens beside the container screens, the session’s read-only items and recipes, declared keys and event callbacks. A mod package (mod.toml) targets this world.

Every event export is optional: the host type-checks each one a component exports, refusing one of another signature, and never calls one it lacks. New events arrive as new exports, so a built component keeps working. init and frame stay required.

Imports

data-source

What a data-changed reports as changed. Closed: changing it would refuse every built data-changed, so a new kind of change arrives as a new optional export instead.

enum data-source {
    items,
    recipes,
}
MemberTypeDescription
items
recipes

Exports

screen-changed

screen-changed: func(layout: option<screen-layout>);

A container screen opened, closed (none) or was laid out anew.

Types: screen-layout.

action

action: func(id: string, collection-index: option<u32>);

A primary press on an overlay or view control mapped to a declared action; the index is the control’s row in its nearest collection.

secondary-action

secondary-action: func(id: string, collection-index: option<u32>);

A secondary press (a right click) on a control that maps button.menu_secondary_select to a declared action.

scrolled

scrolled: func(delta: f64, x: f64, y: f64, modifiers: modifiers);

The wheel turned delta notches (one per detent; a pixel-precise wheel reports its pixels / 16) with the pointer at x, y in GUI units, over the overlay’s drawn area or the view, with modifiers held. Positive scrolls down, towards the end.

Types: modifiers.

text-changed

text-changed: func(control: string, text: string);

The text of the edit box named control, a declared action, changed.

key

key: func(id: string, hovered: option<stack>, row: option<tuple<string, u32>>);

A declared key was pressed while a container screen or the view was up and no edit box had focus. hovered is the vanilla slot’s stack under the pointer; row is the collection name and index of the mod’s control under the pointer, overlay or view, by the rule action uses (its nearest collection).

Types: stack.

data-changed

data-changed: func(sources: list<data-source>);

The listed session sources changed revision, each listed once. It gets the load fuel budget, as does init of a component that exports it.

Types: data-source.

view-closed

view-closed: func();

The host closed the view (Escape, or the container closing), not the mod.

init

init: func();

Creates the initial retained UI state.

frame

frame: func();

Runs a frame transaction with frozen input, session and clock observations. The host may suspend it without refilling fuel; time only schedules work. Output publishes after successful post-return. Late input actions are dropped. Instances exporting decision handlers keep synchronous frame execution.

server-bundle

Server-scoped component; optional grants return denial through these imports. A component built against an earlier 1.x (imports at that version, exporting only the callbacks it had) still runs.

Imports

Exports

init

init: func();

Initializes this instance after its signed bundle and capabilities have been admitted.

frame

frame: func();

Runs when the host admits a presentation frame; older components may omit it.

dispatch

dispatch: func(channel: string, record-json: list<u8>);

A typed message or host-owned input edge; no raw packet or keyboard data.

action

action: func(id: string, collection-index: option<u32>);

A declared action fired from a modal screen control while the modal has focus; the index is the control’s row in its nearest collection.

epoch

epoch: func();

The logical world epoch changed (a world notice or dimension change); the runtime and its state live on.

modal-resized: func(size: gui-size);

The open modal was first drawn, or its size changed (a window resize or a GUI scale change); size is what ui.modal-size now returns.

Types: gui-size.

text-changed

text-changed: func(control: string, text: string);

The text of the modal’s edit box whose text_box_name is control changed while the modal had focus; control is a declared action. Text ends editing like vanilla’s text_edit_box: Enter or Escape deselects the box, and Escape closes the modal only when no box was selected.

secondary-action

secondary-action: func(id: string, collection-index: option<u32>);

A secondary press (a right click) on a modal screen control that maps button.menu_secondary_select to a declared action fired, while the modal has focus; the index is the control’s row in its nearest collection. action stays the primary press.

scroll-changed

scroll-changed: func(view: string, range: scroll-range);

The open modal’s scroll view whose scroll_view_name is view, a declared action, now shows range: it scrolled, or its viewport or content changed length. Changes coalesce, so this is the latest range, not each step of a scroll.

Types: scroll-range.

shift-changed

shift-changed: func(held: bool);

Shift was pressed or released while the modal had focus, or the modal gained or lost focus with Shift held: held is whether it is held now. A screen can show what it shows on Shift, as Java screens’ hasShiftDown does.

sound-handler

The optional event handlers. Each receives a context of the event’s facts and changeable values and returns it; the host applies only the changeable values. Handlers run in load order, each receiving the previous handler’s changes. They cannot call host imports and each call has full callback fuel within a shared per-event allowance; handlers without a full allowance are skipped. Denial and absence pass the event through unchanged. Traps and invalid values quarantine the component and keep the context it received. A component exporting a handler world must implement every handler in it; include only the handlers a component uses.

Imports

Exports

handle-sound

handle-sound: func(ctx: sound-context) -> sound-context;

One call per new playback request, at most 256 per audio frame; excess and oversized requests play unhandled. Approved starts waiting for decoding are not offered again. Playing voices are not retroactively stopped; managed loops are offered again when they next need a start.

Types: sound-context.

teleport-handler

See sound-handler for the shared handler contract.

Imports

Exports

handle-teleport

handle-teleport: func(ctx: teleport-context) -> teleport-context;

One call per committed local-player MovePlayer with a finite rotation, before it applies. The server’s rotation is reported as sent, even outside -90..90 pitch. Returning the incoming rotation is always valid; a replacement must be finite with pitch in -90..90.

Types: teleport-context.