Guides
Your first WebAssembly plugin
A WebAssembly plugin is a core module (not a component) placed in the server's plugins/
directory (getting started says where that is). The server loads
it at start if it was built with --features wasm. To write one in Rust with the guest SDK, start
with getting started instead. Any language that can export
functions and use linear memory works. The motivating case is Kotlin/Wasm, which is why the
ABI never asks the guest to keep memory alive between calls.
The smallest complete plugin is crates/rustmc-plugin-wasm/examples/hello.wat, written by hand
in WebAssembly text. Build it with:
cargo run -p rustmc-plugin-wasm --example wat2wasm -- \
crates/rustmc-plugin-wasm/examples/hello.wat <world>/plugins/hello.wasm
cargo run --release -p rustmc-server --features wasm -- --port 25570 ...
The shape of a guest
- Exports.
memory;rustmc_manifest(): hands over the manifest JSON withemit;rustmc_on_event(len) -> i32: called for events;rustmc_on_hook(len) -> i32: called for hooks, and needed only if the manifest names hooks.
- Imports, from module
rustmc:emit(ptr, len): give the host bytes;take(ptr): copy what is waiting (an event, a hook call, or a call's answer) into your memory;call(ptr, len) -> i32: make a host call and get the answer's length back.
A hook, end to end
The manifest:
{"name": "loud", "version": "1",
"events": ["none"],
"hooks": [{"point": "command.say", "mode": "prepend"}]}
events: ["none"] names an event that does not exist, so the plugin hears no events. An empty
or missing list means all events.
When someone runs /say hello, the server calls rustmc_on_hook(len). Your guest reserves
len bytes, calls take(ptr), and reads:
{"hook": "command.say", "input": {"name": "say", "player": 7, "rest": "hello"}, "mode": "prepend"}
To change the input, emit the replacement and return 1:
{"name": "say", "player": 7, "rest": "HELLO"}
To leave it alone, return 0.
A complete, runnable version of a hook guest is crates/rustmc-plugin-wasm/examples/hook.wat.
It overrides /seed, and a test in that crate loads it and checks its answer.
The full byte-level contract is in the ABI.
From docs/api/guide/wasm-plugin.md in the RustMC repository at bbd81209ad.