/// Wasvy: Wasi interface for the Bevy ecs
package wasvy:ecs;
/// This is the world that the Bevy host (the game/app) implements
/// to give ECS functionality to the WASM guest (the mod).
world host {
import app;
}
/// This is the world that the WASM guest (the mod) implements.
///
/// This is the mandatory interface that a WASM component
/// must implement for it to be called from the Bevy host (the game/app).
world guest {
import app;
use app.{app};
/// This method is called once on startup for each WASM component (Not Bevy component).
///
/// In this method you should register and configure `system`s via the `app` resource
/// passed as a parameter.
export setup: func(app: app);
}
interface app {
resource serialize {
constructor();
get-type: func() -> string;
}
/// This is an interface (similar to bevy::App) through which mods may interact with the Bevy App.
///
/// To access this, make sure to import the 'guest' world and implement `setup`.
resource app {
/// Adds systems to the mod
add-systems: func(
schedule: schedule,
systems: list<borrow<system>>,
);
}
/// An interface with which to define a new system for the host.
///
/// Usage:
/// 1. Construct a new system, giving it a unique name
/// 2. Add system-params by calling 0 or more add-* methods
/// 3. Order the system relative to others
/// 4. Add the system to a schedule
resource system {
/// Constructs a new system. Use the same name as exported in
/// the guest world, otherwise the host won't be able to find it.
constructor(name: string);
/// Adds a commands system-param
add-commands: func();
/// Adds a query system-param
add-query: func(query: list<query-for>);
/// Schedules this system be run after another system
after: func(other: borrow<system>);
/// Schedules this system be run before another system
before: func(other: borrow<system>);
}
/// A `command` queue system param to perform structural changes to the world.
///
/// Since each command requires exclusive access to the world,
/// all queued commands are automatically applied in sequence.
///
/// Each command can be used to modify the world in arbitrary ways:
/// - spawning or despawning entities
/// - inserting components on new or existing entities
/// - etc.
resource commands {
/// Spawns a new empty `entity` and returns its corresponding `entity-commands`.
spawn-empty: func() -> entity-commands;
/// Spawns a new `entity` with the given components
/// and returns the entity's corresponding `entity-commands`.
spawn: func(bundle: bundle) -> entity-commands;
/// Returns the `entity-commands` for the given `entity`.
///
/// This method does not guarantee that commands queued by the returned `entity-commands`
/// will be successful, since the entity could be despawned before they are executed.
entity: func(entity: borrow<entity>) -> entity-commands;
}
/// A list of commands that will be run to modify an `entity`.
resource entity-commands {
/// Returns the identifier for this entity
id: func() -> entity;
/// Adds a `bundle` of components to the entity.
///
/// This will overwrite any previous value(s) of the same component type.
insert: func(bundle: bundle);
/// Removes a Bundle of components from the entity if it exists.
remove: func(bundle: bundle-types);
/// Despawns the entity.
///
/// This will emit a warning if the entity does not exist.
despawn: func();
/// Despawns the entity.
///
/// Unlike `despawn`, this will not emit a warning if the entity does not exist.
try-despawn: func();
}
/// An identifier for an entity.
resource entity {}
/// A query system param
resource query {
/// Evaluates and returns the next query results
iter: func() -> option<query-result>;
}
/// A query system param
resource query-result {
/// Returns the entity id for the query
entity: func() -> entity;
/// Gets the component at the specified index. Order is the same as declared
/// during setup. Query filters do not count as components.
///
/// So for example:
///
/// ```rust,ignore
/// spin_cube.add_query(&[
/// QueryFor::Mut("A"), // component index 0
/// QueryFor::With("B"), // none
/// QueryFor::Ref("C"), // component index 1
/// QueryFor::Without("D"), // none
/// ]);
/// ```
component: func(index: component-index) -> component;
}
resource component {
/// Gets the value of a component
get: func() -> serialized-component;
/// Sets the value of a component
///
/// Traps if this component was not declared as mutable
set: func(value: serialized-component);
/// Invokes a method on this component.
///
/// `params` must be a JSON array string. The return value is JSON.
invoke: func(method: string, params: serialized-component) -> serialized-component;
}
/// A fully-qualified type name
type type-path = string;
/// JSON serialized version of the actual component that is being passed between WASM and Bevy.
/// So for every instance of `component` make sure you deserialize it yourself to the struct that it actually is.
///
/// Note: for components returned by query::optional this is an option<t>
type serialized-component = list<u8>;
/// Just a simple list of tuples composed of the type-path and the serialized component string
type bundle = list<tuple<type-path, serialized-component>>;
/// A bundle without the serialized components
type bundle-types = list<type-path>;
/// Each query supports up to 255 components
type component-index = u8;
variant schedule {
/// A custom schedule that runs the first time a mod is loaded.
///
/// Note this is not the same as Bevy's Startup schedule
mod-startup,
/// Runs during the Bevy PreUpdate schedule
pre-update,
/// Runs during the Bevy Update schedule
update,
/// Runs during the Bevy PostUpdate schedule
post-update,
/// Runs during the Bevy FixedPreUpdate schedule
fixed-pre-update,
/// Runs during the Bevy FixedUpdate schedule
fixed-update,
/// Runs during the Bevy FixedPostUpdate schedule
fixed-post-update,
/// Runs during the Bevy Update schedule
custom(string),
}
variant query-for {
ref(type-path),
mut(type-path),
%with(type-path),
without(type-path),
}
}