Skip to content

Choosing a language

The host loads a WebAssembly component that implements one of two worlds (server-mod, client-mod) declared in host.wit. It does not inspect, and cannot tell, what produced the bytes. Nothing about Ironlark’s modding surface is Rust-specific by design: the contract is a WIT interface, and WIT exists precisely so that many languages can meet the same contract.

Every function in host.wit is an async function — including every function a mod must export. Implementing an async export needs component-model-async support in your language’s bindings generator, and that support is new. Rust’s wit-bindgen has it, and the reference mods use it.

This cascades rather than being a free choice: a mod has to await host calls like entity.spawn, and a synchronous export cannot await an asynchronous import. So async imports imply async exports, which implies a toolchain that can generate them.

The pieces you need are the same ones Rust uses:

  1. host.wit — the contract. Vendor a copy; your generator reads it.
  2. A bindings generator for your language that targets the component model (not classic wasm modules) and can emit async exports.
  3. Output named <mod>_server.wasm / <mod>_client.wasm in the mod’s directory.

Step 2 is where you will find out whether your toolchain is ready. If it is, nothing else about the host stands in your way — and it is worth reporting, because it turns this page’s caveat into a list of supported languages.

Payloads between mods, and between a mod’s halves, are bytes (list<u8>) — never language types. Pick your own encoding; the host neither parses nor cares. That is deliberate, and it is what keeps a mod written in one language usable by a mod written in another.

impl Guest for Component {
fn init() { log(Level::Info, "hello from Rust"); }
fn update(_dt: f32) {}
}

Пример показывает, как выглядят вкладки: syncKey держит все блоки на странице на одном языке, поэтому читатель выбирает один раз.