2 releases
Uses new Rust 2024
new 0.0.3 | May 4, 2025 |
---|---|
0.0.2 | May 3, 2025 |
0.0.1 |
|
#264 in WebAssembly
297 downloads per month
61KB
630 lines
🚧 Wasvy - Bevy WASM Integration (Alpha) 🚧
⚠️ ALPHA WARNING: This project is currently in a proof of concept stage. The API is unstable and may change significantly in future releases. Use at your own risk.
🎯 Community Feedback: I'm publishing this crate at this very experimental stage to get as much feedback as possible from the community. Together, we can shape this into something great! Your ideas, suggestions, and contributions are highly valued :)
💡 TIP: Check out the
justfile
for useful commands and as a reference for common operations in the project.
Overview
Wasvy is an experimental integration between Bevy and WebAssembly (WASM), enabling the execution of WASM components within Bevy applications. This project aims to provide a seamless way to extend Bevy applications with WASM-based plugins and components.
Vision
The ultimate goal of Wasvy is to create a vibrant ecosystem where:
- Game developers can easily make their games moddable with minimal boilerplate
- Modders can write mods in their language of choice (Rust, Python, etc.)
- Mods are sandboxed and safe to run
- The modding experience is as smooth as native code
- The ecosystem is vibrant with shared components and tools
Features
- 🔌 WASM Component Model integration with Bevy
- 🎮 WASI support for WASM components
- 📦 Easy component loading and management
Installation
Run the following command in your project directory:
cargo add wasvy
Quick Start
use bevy::prelude::*;
use wasvy::prelude::*;
/// Bevy drops assets if there are no active handles
/// so this resource exists to keep the handles alive.
#[derive(Resource)]
struct WasmAssets {
#[allow(dead_code)]
pub assests: Vec<Handle<WasmComponentAsset>>,
}
struct ExamplePlugin;
impl Plugin for ExamplePlugin {
fn build(&self, app: &mut App) {
app.add_systems(Startup, load_wasm_modules);
}
}
fn load_wasm_modules(mut commands: Commands, asset_server: Res<AssetServer>) {
let handle = asset_server.load::<WasmComponentAsset>("path/to/your/component.wasm");
commands.insert_resource(WasmAssets {
assests: vec![handle],
});
}
fn main() {
let mut app = App::new();
app.add_plugins(DefaultPlugins);
// Adding the [`WasvyHostPlugin`] is all you need ;)
app.add_plugins(WasvyHostPlugin);
app.add_plugins(ExamplePlugin);
app.run();
}
Creating Compatible Components
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:
Prerequisites
- Install
cargo-component
:
cargo install cargo-component
- Install
wkg
(WebAssembly Kit Generator):
cargo install wkg
Creating a New WASM Component
- Create a new component project:
cargo component new my-component --lib
cd my-component
- Define your WIT interface in
wit/world.wit
. Here's a basic example:
package component:my-component;
world my-world {
// For having access to ECS functions like register-component
import wasvy:ecs/functions;
/// This is important.
/// This makes it so the WASM module must implement the guest required functions by the Bevy host.
include wasvy:ecs/guest;
use wasvy:ecs/types.{query-result};
/// All systems must only have one argument of type `list<query-result>`
export my_system: func(params: list<query-result>)
}
- Configure
wkg
(Skip this if you already have it configured):
wkg config --edit
Then add the following line to your config:
default_registry = "wa.dev"
This will make wkg
use wa.dev
as the default registry, which is where Wasvy WIT files are stored.
- Fetch the Wasvy WIT files from the registry:
wkg wit fetch
- Build your component (This will also generate a
bindings.rs
file):
cargo component build --release
The resulting .wasm
file will be in target/wasm32-unknown-unknown/release/my_component.wasm
.
- Implement your component in
src/lib.rs
. Checkexamples/simple/src/lib.rs
for a full example:
#[allow(warnings)]
mod bindings;
use serde::{Deserialize, Serialize};
use bindings::Guest;
struct GuestComponent;
impl Guest for GuestComponent {
fn my_system(params: Vec<bindings::QueryResult>) {
println!("Hello from my WASM component!");
}
/// This is a mandatory function that is called once at Bevy `Startup` schedule
fn setup() {}
}
bindings::export!(GuestComponent with_types_in bindings);
Using the Component
- Place your compiled
.wasm
file in your Bevy project's assets directory - Load it using the
WasmComponentAsset
as shown in the Quick Start example
Tips
- Check out the examples in this repository for more detailed usage
- Use
wkg
to generate bindings for any additional Bevy features you need - The WIT registry at WebAssembly Components Registry contains many useful interfaces
- You can use
cargo component
to manage dependencies and build configurations
Examples
Check out the examples directory for more detailed usage:
examples/host_example
: Basic example on how to use the crate to run WASM components.examples/simple
: Basic WASM component in Rust.examples/python_example
: Basic WASM component in Python.
Contributing
Contributions come in many forms, and I welcome all kinds of help! Here's how you can contribute:
Code Contributions
- 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
Non-Code Contributions
I am 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
Roadmap
Phase 1: Core Integration (Current)
- Basic WASM component loading
- WASI support
- Component lifecycle management
- Parallel WASM system execution.
- Macros in Rust WASM components for making registring Bevy compoennts and systems more ergonomic.
- Mutable query data in systems.
- Error handling improvements
Phase 2: Enhanced Features
- Hot reloading support for WASM components
- Test suite
- Cross-component communication
- Performance optimizations
- Add javascript example
- Add go example
Phase 3: Production Ready
- Comprehensive documentation
- Benchmarking suite
- Stable API
Resources
- 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
License
This project is dual-licensed under either:
- MIT License (LICENSE-MIT)
- Apache License, Version 2.0 (LICENSE-APACHE)
Your contributions
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.
Acknowledgments
- 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
Dependencies
~88–130MB
~2.5M SLoC