| Crates.io | wasvy |
| lib.rs | wasvy |
| version | 0.0.6 |
| created_at | 2025-05-02 23:07:06.546145+00 |
| updated_at | 2026-01-18 14:50:46.596945+00 |
| description | Bevy WASM |
| homepage | https://crates.io/crates/wasvy |
| repository | https://github.com/wasvy-org/wasvy |
| max_upload_size | |
| id | 1658311 |
| size | 465,504 |
🪺 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!
The ultimate goal of Wasvy is to create a vibrant ecosystem where:
Run the following command in your project directory:
cargo add wasvy
use 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:
wasm32-wasip2 target for rustrustup target add wasm32-wasip2
wkg (WebAssembly Kit Generator from wasm-pkg-tools):cargo install wkg
And then configure wkg:
wkg config --default-registry wa.dev
This will make wkg use wa.dev as the default registry, which is where the latest version of wasvy:ecs is hosted.
cargo new my-mod --lib
cd my-mod
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.18.0", features = ["serialize"], default-features = false }
bevy_math = { version = "0.18.0", features = ["serialize"], default-features = false }
[lib]
crate-type = ["cdylib"] # necessary for wasm
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;
}
wkg wit fetch
This 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.
my-mod/src/lib.rs as 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);
cargo build --target wasm32-wasip2 --release
The 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")).
file_watcher feature. Try running your game with the command cargo run --features bevy/file_watcherCheck out the examples directory for more detailed usage:
examples/host_example: Basic example on how to use the ModloaderPlugin to 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:
git checkout -b feature/amazing-feature)git commit -m 'Add some amazing feature')git push origin feature/amazing-feature)We're actively looking for:
You don't need to write code to help out! If you have an idea or suggestion, please:
Please make sure to:
This project is dual-licensed under either:
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.