Wasvy - WASI Integration for Bevy (Just hatched! 🪺)
🪺 Just hatched: This project in in the process of stabilization. Some features are still missing and breaking API changes are likely to happen as we approach a 1.0 release. Use at your own risk!
🎯 Community Feedback: Your ideas, suggestions, and contributions are highly valued! Come and talk with us in the Bevy Discord. Report bugs and discuss new features on Github. Together, we can shape this into something great!
💡 TIP: Check out the
justfilefor useful commands and as a reference for common operations in the project.
Wasvy is an experimental Bevy modding engine, enabling the execution of WebAssembly (WASM) binaries within Bevy applications. It's powered by WebAssembly System Interface (WASI), enabling full access to the Bevy ECS, network, filesystem, system clock and more!
- 🪶 Easy integration with your game (see the example below)
- 🔥 Hot reloading
- 🛠️ Devtools (soon) via wasvy-cli
- 🧩 WASI support powered by wasmtime
The ultimate goal of Wasvy is to create a vibrant ecosystem where:
- Game developers can easily make their games moddable with just a few lines of code
- The developer experience is fantastic (Hot reloading, live debugging tools, etc)
- Modders can write mods in their language of choice (Rust, Python, etc.)
- Performance is close to native
- Mods are sandboxed and safe to run
- The ecosystem is vibrant with shared components and tools
Run the following command in your project directory:
cargo add wasvyuse bevy::prelude::*;
use bevy::{DefaultPlugins, app::App};
// Get started by importing the prelude
use wasvy::prelude::*;
fn main() {
App::new()
.add_plugins(DefaultPlugins)
// Adding the [`ModloaderPlugin`] is all you need 😉
.add_plugins(ModloaderPlugin::default())
.add_systems(Startup, startup)
.run();
}
/// Access the modloader's api through the Mods interface 🪄
fn startup(mut mods: Mods) {
// Load one (or several) mods at once from the asset directory!
mods.load("mods/my-mod.wasm");
}Mods are WebAssembly binaries coded in any language of choice. We're working on a way to streamline mod creation with wasvy-cli, but until that hatches, you can reference the examples in the repo.
To create a WASM component that works with Wasvy, you'll need to use the WebAssembly Component Model and define your interfaces using WIT (WebAssembly Interface Types). Here's how to get started with a new mod written in rust:
- Add the
wasm32-wasip2target for rust
rustup target add wasm32-wasip2- Install
wkg(WebAssembly Kit Generator from wasm-pkg-tools):
cargo install wkgAnd then configure wkg:
wkg config --default-registry wa.devThis will make wkg use wa.dev as the default registry, which is where the latest version of wasvy:ecs is hosted.
- Create a new crate:
cargo new my-mod --lib
cd my-mod- Update your
cargo.toml:
[package]
name = "my-mod"
version = "0.1.0"
edition = "2024"
[dependencies]
# Hassle-less codegen for wit
wit-bindgen = "0.46"
# Wasvy uses json for serializing components. We use serde instead
# of bevy_reflect since at the moment bevy-reflect bloats the wasm binary considerably
serde = "1.0"
serde_json = "1.0"
# Import any bevy-sub crates for any components you will be using
# Note: enable the serialize feature to allow using serde
bevy_transform = { version = "0.17.2", features = ["serialize"], default-features = false }
bevy_math = { version = "0.17.2", features = ["serialize"], default-features = false }
[lib]
crate-type = ["cdylib"] # necessary for wasm- Define your WIT interface in
wit/world.wit. Here's a basic example:
package component:my-mod;
/// An example world for the component to target.
world example {
/// This is the wit definition for wasvy's ecs access interface
use wasvy:ecs/app.commands;
/// An example system with a Commands system params
export my-system: func(commands: commands);
/// This is important.
/// This makes it so the WASM module must implement the guest required functions by the Bevy host.
include wasvy:ecs/guest;
}- Fetch the Wasvy WIT files from the registry:
wkg wit fetchThis will automatically fetch the latest version of wasvy:ecs from wa.dev and add it to your wit folder. You can also copy them directly from the source.
- Modify
my-mod/src/lib.rsas shown:
wit_bindgen::generate!({
path: ["./wit"],
world: "component:my-mod/example",
with: {
"wasvy:ecs/app": generate,
}
});
use wasvy::ecs::app::{App, Commands, Schedule, System};
struct MyMod;
impl Guest for MyMod {
fn setup() {
// This must match the system we have defined in world.wit
// If you want more systems, just define more in wit
let system = System::new("my-system");
system.add_commands();
// Register the system, similarly as you would in a Bevy App
let app = App::new();
app.add_systems(&Schedule::ModStartup, vec![system]);
}
fn my_system(commands: Commands) {
println!("Hello from my mod!");
commands.spawn(&[
("example::Component".to_string(), "{}".to_string())
]);
}
}
export!(MyMod);- Build your mod:
cargo build --target wasm32-wasip2 --releaseThe resulting .wasm file will be in target/wasm32-wasip2/release/my-mod.wasm.
Hint: The binary must be in your game's assets library for it to be visible to Bevy. By default this is assets in the same directory as src. Then, make sure to load it via Mods::load as shown above (e.g. mods.load("mods/my-mod.wasm")).
- You can enable hot reloading for assets (including wasm files) simply by enabling Bevy's
file_watcherfeature. Try running your game with the commandcargo run --features bevy/file_watcher - The WIT registry at WebAssembly Components Registry contains many useful interfaces
Check out the examples directory for more detailed usage:
examples/host_example: Basic example on how to use theModloaderPluginto enable modding with bevy.examples/simple: Basic WASM component in Rust.examples/python_example: Basic WASM component in Python.
Contributions come in many forms, and we welcome all kinds of help! Here's how you can contribute:
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add some amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
We're actively looking for:
- Feature suggestions and ideas
- Use case examples
- Documentation improvements
- Bug reports
- Design discussions
- Feedback on the API
- Modding workflow suggestions
You don't need to write code to help out! If you have an idea or suggestion, please:
- Open an issue to discuss it
- Share your thoughts in the discussions
- Create a feature request
Please make sure to:
- Follow Rust coding standards (for code contributions)
- Add tests for new features (Not required for now, but will be appreciated)
- Update documentation as needed
- Keep the alpha status in mind when proposing changes
- Basic WASM component loading
- WASI support
- Parallel WASM system execution
- Mutable query data in systems
- System ordering
- Entity/Component lifecycle management
- Panic-free error handling
- Hot reloading wasm files
- Seamless dev experience building mods (See wasvy-cli)
- Mod permissions
- Improved rust modding experience (See wasvy-rust)
- Improved python modding experience
- Add more languages + examples
- Test suite
- Cross-component communication
- Performance optimizations
- Comprehensive documentation
- Benchmarking suite
- Stable API
- WASM Component Model Documentation - The best resource on WIT and how the WASM component model works in practicality.
- Wasmtime Examples
- Component Model Examples
- Cargo Component - I used that for making the WASM component examples.
- WASM Package Tools - How to publish and retreive WIT files for use in projects.
- WebAssembly Coponents Registry - The WIT registry I'm using.
- WASI.dev
This project is dual-licensed under either:
- MIT License (LICENSE-MIT)
- Apache License, Version 2.0 (LICENSE-APACHE)
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.
- Bevy for the amazing game engine
- Bytecode Alliance for all the amazing WASM tools
- WebAssembly Coponents Registry - for providing a simple way to publish WIT components
