Bevy
A Bevy game compiled to wasm, with the mugon-sdk-bevy crate.
Bevy is the main SDK. Start a project with mugon init and pick
the bevy template (see what you need installed).
It gives you a Bevy app, a small Vite entry and build commands. Two pieces have to work together:
The entry (src/index.js) imports the SDK first and starts the wasm from inside
Mugon.start, which publishes the context as window.mugon. Vite bundles it, the SDK and the
wasm into your distribution folder; you don't ship any SDK file yourself:
import { Mugon } from "@mugon/sdk";
import init from "../pkg/game.js";
Mugon.start(async () => {
try {
await init(); // downloads game_bg.wasm through the file proxy and runs main
} catch (error) {
// Bevy's web event loop unwinds `main` with this exception on purpose.
if (!String(error).includes("control flow")) throw error;
}
// Keep the callback pending, see below.
await new Promise(() => {});
});The crate mugon-sdk-bevy reads that context:
use bevy::prelude::*;
use mugon_sdk_bevy::prelude::*;
fn main() {
App::new()
.add_plugins((DefaultPlugins, MugonPlugin))
.add_systems(Startup, setup)
.run();
}
fn setup(bridge: NonSend<Bridge>) {
info!("{:?} {}", bridge.network_mode(), bridge.own_id());
bridge.loaded(); // the game is playable: close the loading overlay
}MugonPlugin panics with a clear message if window.mugon is missing, i.e. if the wasm isn't
started from inside the Mugon.start callback.
Loading progress
The entry keeps the Mugon.start callback pending because App::run returns immediately on
the web, and a returning callback closes the overlay before your assets are loaded. Close it
from Rust instead:
Bridge::loaded()when the game is ready, and optionallyBridge::set_progress(fraction, label)while loading; or- enable the
loadingfeature, addMugonLoadingPluginand track assets: the overlay showsloaded/totaland closes when they are all loaded.
fn setup(asset_server: Res<AssetServer>, mut loading: ResMut<MugonLoading>) {
loading.track(asset_server.load::<Image>("sprite.png"));
}Track everything the game needs before it's playable in one go; assets tracked after the overlay closed are not waited for.
The bridge
Bridge is a NonSend resource with network_mode(), own_id(), server_id(),
pop_connect(), pop_disconnect(), pop_recv(), send(peer, bytes, channel),
disconnect(peer), show_invite() and toggle_fullscreen(). On a server the connect queue starts
with the peers that were connected already. For Lightyear games, the
lightyear_mugon crate builds on this.
Building
The template has two build commands. Both run cargo build --target wasm32-unknown-unknown,
wasm-bindgen --target web into pkg/, and npm run build (Vite):
mugon devuses the plain--releaseprofile, which compiles quickly on every save.mugon publishuses therelease-ltoprofile (full LTO, one codegen unit): a much slower compile for a smaller and faster wasm.
Install the wasm-bindgen CLI in the same version as the wasm-bindgen crate in your
Cargo.lock. Debug builds of Bevy are very large (hundreds of megabytes), so the template
never uses them.