manifold:game 0.1.0
Contract reference · Payloads · contract.json (crates/manifold-wasm-abi/wit/contract.json)
Status: legacy contract 0.1: linked by the mod’s [caps] until migration steps M2 and M3 move its interfaces into the contract packages.
| Interface | Kind |
|---|---|
asset-source | import |
clock | import |
persistent-storage | import |
plugin | export |
text | types-only |
ui | import |
Interface asset-source
import · since 0.1.0
AssetSource capability: host-provided file read for bundled mod assets. Covers 18 std::fs::read_* violations from the audit. Sync (no async) — assets are small RON/WGSL/JSONL files read at startup. In dev mode the host reads loose files; in prod reads from .mod archive.
Functions
read
read: func(mod-id: string, path: string) -> result<list<u8>, asset-error>
Read a mod asset by path. The mod-id scopes the read to this mod’s asset bundle; future third-party mods get their own isolated scope. Path uses forward slashes and must not contain parent-dir components; the host validates this to prevent bundle escape. Returns the raw bytes of the file.
result: opaque bytesasset-file.
Types
asset-error (enum)
Error returned when an asset path cannot be resolved.
| Index | Case | About |
|---|---|---|
| 0 | not-found | The file does not exist in this mod’s asset bundle. |
| 1 | io-error | The file exists but could not be decoded (permissions, corrupt, etc.). |
Interface clock
import · since 0.1.0
Clock capability: host-provided time access. Covers 12 wall-clock violations from the audit. Two methods to cover both use cases found in the codebase:
- monotonic nanos for profiling (Instant::now replacement)
- wallclock millis for log timestamps and double-tap detection
Functions
now-instant
now-instant: func() -> u64
Monotonic nanoseconds since an unspecified epoch (wasm-host construction). Replaces Instant::now(). Not guaranteed to be wall-clock aligned. The epoch is consistent within one host process lifetime.
now-system-millis
now-system-millis: func() -> u64
Wallclock milliseconds since UNIX epoch. Replaces SystemTime::now(). Not monotonically guaranteed across system clock adjustments, but matches the semantics callers expect for log timestamps and double-tap detection (where sub-second precision matters but cross-session monotonicity does not).
Interface persistent-storage
import · since 0.1.0
PersistentStorage capability: host-provided scoped persistent writes. Covers 4 std::fs::write/create_dir_all violations from the audit. Scope is per-mod (host validates paths cannot escape the mod’s directory). This is intentionally separate from the save-stack (redb+postcard+zstd); game_settings, keybinds, and console history are user config, not save data.
Functions
append-history
append-history: func(line: string) -> result<_, storage-error>
Append one history line (without trailing newline; host adds ‘\n’).
append-log
append-log: func(bytes: list<u8>) -> result<_, storage-error>
Append bytes to the session log. Does not add newline separators; callers are responsible for framing (typically line-delimited JSON).
bytes: opaque bytesmod-log.
read-config
read-config: func(scope: string, key: string) -> result<option<list<u8>>, storage-error>
Read a config value for this mod. scope identifies the config domain (e.g., “settings”, “keybinds”); key names the entry within that domain. Returns None if the entry does not exist.
result: opaque bytesmod-config.
read-history
read-history: func() -> result<list<u8>, storage-error>
Read the console history file (line-delimited JSONL).
result: opaque bytesconsole-history.
read-log
read-log: func() -> result<list<u8>, storage-error>
Read the entire session log accumulated so far. Returns an empty list if no log exists yet.
result: opaque bytesmod-log.
write-config
write-config: func(scope: string, key: string, bytes: list<u8>) -> result<_, storage-error>
Write a config value. Creates or overwrites the entry.
bytes: opaque bytesmod-config.
Types
storage-error (enum)
Error returned by storage operations.
| Index | Case | About |
|---|---|---|
| 0 | invalid-path | The key path contains illegal characters or escapes the mod scope. |
| 1 | io-error | The underlying storage backend failed (disk full, permissions, etc.). |
Interface plugin
export · since 0.1.0
The UI half of the contract 0.1 plugin export, until migration step M2
moves it to manifold:ui/plugin-ui (contract foundation spec §6.1). The
lifecycle and system calls moved to manifold:core/plugin-lifecycle and
manifold:ecs/plugin-systems (M1b). Optional: only a mod that authors UI
exports it.
Functions
build-ui-state
build-ui-state: func(ui-key: u64, entity: u64, bundle: borrow<ui-read-bundle>) -> result<list<u8>, ui-error>
build-ui-state: called by the server BUI phase (dirty-gated) to produce a UiStateMap for the given ui-key and subscription entity. ui-key: u64 identifying which registered UI to build state for. entity: u64 identifying the subscription entity (bundle’s entity target). bundle: read-only snapshot of the entity’s declared components + resources. Returns postcard-encoded UiStateMap bytes, or ui-error on failure.
result: schema payloadui-state-map.
handle-ui-event
handle-ui-event: func(ui-key: u64, entity: u64, event: list<u8>, bundle: borrow<ui-rw-bundle>) -> result<_, ui-error>
handle-ui-event: called by the server when a client emits a UiEvent. ui-key: u64 identifying which registered UI received the action. entity: u64 identifying the subscription entity. event: postcard-encoded UiEvent bytes. bundle: read+write snapshot; guest validates the event and writes mutations. Writes land in the host only if this returns ok(_).
event: schema payloadui-event.
ui-manifest
ui-manifest: func() -> list<u8>
ui-manifest: called once at mod load to declare all UI registrations. Returns postcard-encoded Vec<UiRegistration>. The host allocates the mod’s NamespaceId, resolves tree bindings, and caches the schema + tree. A broken binding fails this specific UiKey at load time (fail-soft: mod keeps running).
result: schema payloadui-registrations.
Types
ui-error (alias)
= game/ui.ui-error
ui-read-bundle (alias)
= game/ui.ui-read-bundle
ui-rw-bundle (alias)
= game/ui.ui-rw-bundle
Interface text
types-only · since 0.1.0
Player-facing text: a message key plus typed arguments, never a finished
sentence. Each client resolves it through the catalogs of its player’s
language, so players on one server each read their own language. Mirrors
manifold_l10n_types::LocalizedText. Keys are <mod-id>.<segment>...;
a mod’s catalogs live at locales/<bcp47>/*.ftl in its package.
Types
currency-amount (record)
A currency amount in minor units (cents) with its ISO 4217 code.
| Field | Type | About |
|---|---|---|
minor | s64 | |
code | string |
loc-arg (variant)
| Index | Case | Payload | About |
|---|---|---|---|
| 0 | str | string | Untranslated text (bidi-isolated when substituted). |
| 1 | int | s64 | |
| 2 | float | f64 | |
| 3 | key | string | Another message key, resolved without arguments. |
| 4 | item | string | A namespaced item or block id; resolves to its display name. |
| 5 | player | string | A player’s display name (user text, isolated). |
| 6 | duration-ms | u64 | |
| 7 | timestamp-ms | s64 | Milliseconds since the Unix epoch, UTC. |
| 8 | currency | currency-amount |
loc-entry (record)
| Field | Type | About |
|---|---|---|
name | string | |
value | loc-arg |
localized-text (record)
| Field | Type | About |
|---|---|---|
key | string | |
args | list<loc-entry> |
Interface ui
import · since 0.1.0
Ui capability: per-UI-key entity-component + resource snapshot. Coarse-grained crossing: host stages the subscription entity’s declared read-components and declared read-resources before calling build-ui-state; the guest accumulates writes in the rw-bundle which the host applies after handle-ui-event returns.
Two bundle resources: ui-read-bundle — read-only snapshot passed to build-ui-state. ui-rw-bundle — read+write snapshot passed to handle-ui-event.
The guest-exported entry points (ui-manifest, build-ui-state,
handle-ui-event) are declared in the plugin interface, which uses
these resource types via use ui.{...} — mirroring how run-system
uses resource-bundle-handle.
Resources: ui-read-bundle, ui-rw-bundle.
Functions
[method]ui-read-bundle.read-entity-component
[method]ui-read-bundle.read-entity-component: func(self: borrow<ui-read-bundle>, type-id: u64) -> option<list<u8>>
Read an entity component from the bundle by its type-id. type-id is the u64 FNV-1a hash of the fully-qualified Rust type name. Returns None if the component was not included in the declared read-set or is not present on the entity. Returned bytes are postcard-encoded.
result: opaque bytescomponent-value.
[method]ui-read-bundle.read-resource
[method]ui-read-bundle.read-resource: func(self: borrow<ui-read-bundle>, type-id: u64) -> option<list<u8>>
Read a resource from the bundle by its type-id. Returns None if the resource was not declared in the read-set or is absent. Returned bytes are postcard-encoded.
result: opaque bytescomponent-value.
[method]ui-rw-bundle.read-entity-component
[method]ui-rw-bundle.read-entity-component: func(self: borrow<ui-rw-bundle>, type-id: u64) -> option<list<u8>>
Read an entity component from the bundle by its type-id.
result: opaque bytescomponent-value.
[method]ui-rw-bundle.read-resource
[method]ui-rw-bundle.read-resource: func(self: borrow<ui-rw-bundle>, type-id: u64) -> option<list<u8>>
Read a resource from the bundle by its type-id.
result: opaque bytescomponent-value.
[method]ui-rw-bundle.write-entity-component
[method]ui-rw-bundle.write-entity-component: func(self: borrow<ui-rw-bundle>, type-id: u64, bytes: list<u8>)
Write a component back to the bundle by its type-id. The bytes must be postcard-encoded. Writing a type not declared in the UI’s write_components set causes a host trap. Bounded to the subscription entity; cross-entity writes are rejected.
bytes: opaque bytescomponent-value.
[method]ui-rw-bundle.write-resource
[method]ui-rw-bundle.write-resource: func(self: borrow<ui-rw-bundle>, type-id: u64, bytes: list<u8>)
Write a resource back to the bundle by its type-id. The bytes must be postcard-encoded. Writing a type not declared in the UI’s write_resources set causes a host trap.
bytes: opaque bytescomponent-value.
Types
ui-error (record)
Error returned when a UI call fails gracefully.
| Field | Type | About |
|---|---|---|
message | string |
ui-read-bundle (resource)
Read-only bundle: snapshot of the subscription entity’s declared read-components and read-resources for one build-ui-state invocation. The host drops it after build-ui-state returns.
resource
ui-rw-bundle (resource)
Read+write bundle: snapshot passed to handle-ui-event. The guest may read staged bytes and write back mutations; the host applies declared writes after handle-ui-event returns.
resource