change how bindings are generated, make it easier to call functions on the guest
This commit is contained in:
parent
f6933de559
commit
4deed47b3d
|
@ -1 +1,2 @@
|
|||
/target
|
||||
wasi_snapshot_preview1.reactor.wasm
|
|
@ -46,9 +46,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "anyhow"
|
||||
version = "1.0.82"
|
||||
version = "1.0.86"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f538837af36e6f6a9be0faa67f9a314f8119e4e4b5867c6ab40ed60360142519"
|
||||
checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da"
|
||||
|
||||
[[package]]
|
||||
name = "api-derive"
|
||||
|
@ -2470,6 +2470,7 @@ version = "0.1.0"
|
|||
dependencies = [
|
||||
"bytemuck",
|
||||
"common-api",
|
||||
"wit-bindgen",
|
||||
"wit-bindgen-rt",
|
||||
]
|
||||
|
||||
|
@ -2477,6 +2478,7 @@ dependencies = [
|
|||
name = "wittest"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-trait",
|
||||
"common-api",
|
||||
"lyra-ecs",
|
||||
|
|
|
@ -16,4 +16,5 @@ lyra-ecs = { path = "./lyra-engine/lyra-ecs" }
|
|||
slab = "0.4.9"
|
||||
thiserror = "1.0.58"
|
||||
|
||||
common-api = { path = "./common-api" }
|
||||
common-api = { path = "./common-api" }
|
||||
anyhow = "1.0.86"
|
||||
|
|
|
@ -19,8 +19,8 @@ Install [`cargo-component`](https://github.com/bytecodealliance/cargo-component)
|
|||
cargo install wasm-tools
|
||||
```
|
||||
|
||||
Build the `witguest` project:
|
||||
Download [`wasi_snapshot_preview1.reactor.wasm`](https://github.com/bytecodealliance/wasmtime/releases/download/v17.0.0/wasi_snapshot_preview1.reactor.wasm) in the `witguest` folder. Build the `witguest` project then use an adapter to convert the WASM module to a component:
|
||||
```
|
||||
cd witguest
|
||||
cargo component build
|
||||
cargo build --target wasm32-wasip1 && wasm-tools component new ../target/wasm32-wasip1/debug/witguest.wasm -o ../target/wasm32-wasip1/debug/witguest-component.wasm --adapt ../wasi_snapshot_preview1.reactor.wasm
|
||||
```
|
|
@ -12,4 +12,9 @@ thiserror = "1.0.58"
|
|||
#wasmtime = "19.0.2"
|
||||
wit-bindgen = "0.28.0"
|
||||
#wit-bindgen = { version = "0.24.0", default-features = false, features = ["realloc"] }
|
||||
api-derive = { path = "./api-derive" }
|
||||
api-derive = { path = "./api-derive" }
|
||||
|
||||
[package.metadata.component]
|
||||
package = "lyra:api"
|
||||
|
||||
[package.metadata.component.dependencies]
|
|
@ -1,4 +1,4 @@
|
|||
use std::{any::TypeId, marker::PhantomData, mem};
|
||||
use std::{any::TypeId, marker::PhantomData, mem, ops::Deref};
|
||||
|
||||
pub use bytemuck;
|
||||
|
||||
|
@ -14,7 +14,7 @@ pub use api_derive as macros;
|
|||
|
||||
pub mod bindings {
|
||||
wit_bindgen::generate!({
|
||||
world: "api",
|
||||
world: "imports",
|
||||
path: "wit",
|
||||
});
|
||||
}
|
||||
|
@ -31,14 +31,46 @@ impl WasmTypeId {
|
|||
}
|
||||
}
|
||||
|
||||
pub struct World {
|
||||
inner: EcsWorld,
|
||||
enum OwnedBorrow<'a, T> {
|
||||
Borrowed(&'a T),
|
||||
Owned(T),
|
||||
}
|
||||
|
||||
impl World {
|
||||
impl<'a, T> Deref for OwnedBorrow<'a, T> {
|
||||
type Target = T;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
match self {
|
||||
OwnedBorrow::Borrowed(v) => *v,
|
||||
OwnedBorrow::Owned(v) => &v,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct World<'a> {
|
||||
inner: OwnedBorrow<'a, EcsWorld>,
|
||||
}
|
||||
|
||||
impl<'a> From<EcsWorld> for World<'a> {
|
||||
fn from(value: EcsWorld) -> Self {
|
||||
Self {
|
||||
inner: OwnedBorrow::Owned(value),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<&'a EcsWorld> for World<'a> {
|
||||
fn from(value: &'a EcsWorld) -> Self {
|
||||
Self {
|
||||
inner: OwnedBorrow::Borrowed(value),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> World<'a> {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
inner: EcsWorld::new(),
|
||||
inner: OwnedBorrow::Owned(EcsWorld::new()),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -56,5 +56,7 @@ interface ecs {
|
|||
///
|
||||
/// Returns: an iterator that returns the byte buffers of each row.
|
||||
view: func(component-infos: list<component-info>) -> ecs-dynamic-view;
|
||||
|
||||
//with_system: func(stage: string, component-infos: list<component-info>, system: func(components: list<u8>));
|
||||
}
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
package lyra:api;
|
||||
|
||||
world api {
|
||||
world imports {
|
||||
import ecs;
|
||||
}
|
127
src/main.rs
127
src/main.rs
|
@ -1,10 +1,12 @@
|
|||
use std::alloc::Layout;
|
||||
use std::borrow::Borrow;
|
||||
use std::ptr::NonNull;
|
||||
|
||||
use anyhow::{anyhow, Context};
|
||||
use async_trait::async_trait;
|
||||
use component::witguest::math;
|
||||
use ecs::query::dynamic::{DynamicViewState, DynamicViewStateIter, QueryDynamicType};
|
||||
use lyra_ecs::Component;
|
||||
use lyra_ecs::{Component, World};
|
||||
|
||||
use lyra_ecs as ecs;
|
||||
|
||||
|
@ -12,13 +14,57 @@ use slab::Slab;
|
|||
use thiserror::Error;
|
||||
use wasmtime_wasi::{ResourceTable, WasiCtx, WasiCtxBuilder, WasiView};
|
||||
|
||||
use wasmtime::component::Resource as WasmResource;
|
||||
use wasmtime::component::{Resource as WasmResource, ResourceAny};
|
||||
|
||||
use wasmtime::component::Val as ComponentVal;
|
||||
|
||||
#[allow(unused_imports)]
|
||||
pub(crate) mod lyra_engine {
|
||||
pub use lyra_ecs as ecs;
|
||||
}
|
||||
|
||||
/* mod bindings {
|
||||
wasmtime::component::bindgen!({
|
||||
world: "imports",
|
||||
path: "common-api/wit",
|
||||
//tracing: true,
|
||||
async: true,
|
||||
});
|
||||
|
||||
mod component {
|
||||
wasmtime::component::bindgen!({
|
||||
world: "example",
|
||||
path: "witguest/wit",
|
||||
//tracing: true,
|
||||
async: true,
|
||||
|
||||
with: {
|
||||
"lyra:api": super::lyra::api,
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
use bindings::lyra::api::ecs as wasm_ecs; */
|
||||
|
||||
/* wasmtime::component::bindgen!({
|
||||
world: "imports",
|
||||
path: "common-api/wit",
|
||||
//tracing: true,
|
||||
async: true,
|
||||
}); */
|
||||
|
||||
wasmtime::component::bindgen!({
|
||||
world: "example",
|
||||
path: "witguest/wit",
|
||||
//tracing: true,
|
||||
async: true,
|
||||
|
||||
with: {
|
||||
//"lyra:api": lyra::api,
|
||||
}
|
||||
});
|
||||
|
||||
use lyra::api::ecs as wasm_ecs;
|
||||
|
||||
impl Into<ecs::DynTypeId> for wasm_ecs::WasmTypeId {
|
||||
|
@ -50,24 +96,6 @@ impl Into<ecs::Entity> for wasm_ecs::Entity {
|
|||
}
|
||||
}
|
||||
|
||||
wasmtime::component::bindgen!({
|
||||
world: "api",
|
||||
path: "common-api/wit",
|
||||
//tracing: true,
|
||||
async: true,
|
||||
});
|
||||
|
||||
wasmtime::component::bindgen!({
|
||||
world: "example",
|
||||
path: "witguest/wit",
|
||||
//tracing: true,
|
||||
async: true,
|
||||
|
||||
with: {
|
||||
//"lyra:api": lyra::api,
|
||||
}
|
||||
});
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Component)]
|
||||
struct Vec3 {
|
||||
|
@ -220,10 +248,7 @@ impl wasm_ecs::HostEcsDynamicView for Imports {
|
|||
WasmResource::new_own(view_index as _)
|
||||
}
|
||||
|
||||
async fn next(
|
||||
&mut self,
|
||||
view: WasmResource<wasm_ecs::EcsDynamicView>,
|
||||
) -> Option<Vec<u8>> {
|
||||
async fn next(&mut self, view: WasmResource<wasm_ecs::EcsDynamicView>) -> Option<Vec<u8>> {
|
||||
let view_entry = self.world_views_slab.get_mut(view.rep() as _).unwrap();
|
||||
let world_entry = self.world_slab.get(view_entry.world_index).unwrap();
|
||||
let view = &mut view_entry.view;
|
||||
|
@ -246,7 +271,7 @@ impl wasm_ecs::HostEcsDynamicView for Imports {
|
|||
dst,
|
||||
comp.info.layout().size(),
|
||||
);
|
||||
|
||||
|
||||
// make sure to tell the vec that it now has the bytes of this component
|
||||
row_buf.set_len(row_buf.len() + comp_size);
|
||||
}
|
||||
|
@ -291,12 +316,13 @@ async fn main() -> wasmtime::Result<()> {
|
|||
|
||||
// Configure the linker
|
||||
let mut linker = wasmtime::component::Linker::new(&engine);
|
||||
|
||||
|
||||
//wasmtime_wasi::preview0::add_to_linker_sync(&mut linker, |s| s)?;
|
||||
//wasmtime_wasi::bindings::Imports::add_to_linker(&mut linker, |s| s)?;
|
||||
wasmtime_wasi::add_to_linker_async(&mut linker)?;
|
||||
Example::add_to_linker(&mut linker, |s| s)?;
|
||||
Api::add_to_linker(&mut linker, |s| s)?;
|
||||
//lyra::api::ecs::add_to_linker(&mut linker, |s| s)?;
|
||||
//Api::add_to_linker(&mut linker, |s| s)?;
|
||||
|
||||
let mut builder = WasiCtxBuilder::new();
|
||||
builder.inherit_stdio();
|
||||
|
@ -314,14 +340,53 @@ async fn main() -> wasmtime::Result<()> {
|
|||
);
|
||||
|
||||
// Load the component from disk
|
||||
let bytes = std::fs::read("target/wasm32-wasip1/debug/witguest.wasm")?;
|
||||
let bytes = std::fs::read("target/wasm32-wasip1/debug/witguest-component.wasm")?;
|
||||
let component = wasmtime::component::Component::new(&engine, bytes)?;
|
||||
|
||||
let (script_en, (world_res_a, world_res_b)) = {
|
||||
let mut world = World::new();
|
||||
let script_en = world.spawn(());
|
||||
|
||||
let data = store.data_mut();
|
||||
let world_idx = data.world_slab.insert(WorldEntry {
|
||||
world,
|
||||
views: Slab::with_capacity(10),
|
||||
});
|
||||
let resa = WasmResource::<EcsWorld>::new_borrow(world_idx as _);
|
||||
let resb = WasmResource::<EcsWorld>::new_borrow(world_idx as _);
|
||||
|
||||
(script_en, (resa, resb))
|
||||
};
|
||||
|
||||
// Instantiate the component
|
||||
println!("creating example");
|
||||
let example = Example::instantiate_async(&mut store, &component, &linker).await?;
|
||||
example.call_on_init(&mut store).await?.unwrap();
|
||||
println!("creating example component");
|
||||
let instance = linker.instantiate_async(&mut store, &component).await?;
|
||||
|
||||
call_script_stage_async(&mut store, &instance, "init", world_res_a, script_en.into()).await?;
|
||||
call_script_stage_async(&mut store, &instance, "update", world_res_b, script_en.into()).await?;
|
||||
|
||||
println!("Guest is done");
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn call_script_stage_async(mut store: &mut wasmtime::Store<Imports>, instance: &wasmtime::component::Instance, stage_name: &str, world_res: wasmtime::component::Resource<EcsWorld>, script_entity: Entity) -> anyhow::Result<()> {
|
||||
let func_name = format!("on-{}", stage_name);
|
||||
let func = instance
|
||||
.get_func(&mut store, &func_name)
|
||||
.expect("Could not find on_init");
|
||||
|
||||
let typed_func = unsafe {
|
||||
wasmtime::component::TypedFunc::<
|
||||
(wasmtime::component::Resource<EcsWorld>, Entity),
|
||||
(Result<(), ()>,),
|
||||
>::new_unchecked(func)
|
||||
};
|
||||
|
||||
let (ret,) = typed_func.call_async(&mut store, (world_res, script_entity.into())).await
|
||||
.with_context(|| format!("failed to call guest function {func_name}"))?;
|
||||
typed_func.post_return_async(&mut store).await
|
||||
.with_context(|| format!("failed to call post-return function of guest after calling {func_name}"))?;
|
||||
|
||||
ret.map_err(|_| anyhow!("unknown error returned from guest when calling function {func_name}"))
|
||||
}
|
||||
|
|
|
@ -3,10 +3,11 @@ name = "witguest"
|
|||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
#build = "build.rs"
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
#wit-bindgen = { version = "0.28.0", default-features = false, features = ["realloc"] }
|
||||
wit-bindgen = { version = "0.28.0", default-features = false, features = ["realloc"] }
|
||||
wit-bindgen-rt = { version = "0.28.0", features = ["bitflags"] }
|
||||
common-api = { path = "../common-api" }
|
||||
bytemuck = { version = "1.15.0", features = ["derive"] }
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
use std::{fs, io, path::Path};
|
||||
|
||||
|
||||
// Example custom build script.
|
||||
fn main() {
|
||||
// Tell Cargo that if the given file changes, to rerun this build script.
|
||||
println!("cargo::rerun-if-changed=../common-api/wit/");
|
||||
|
||||
fs::remove_dir_all("./wit/deps/lyraapi").unwrap();
|
||||
copy_dir_all("../common-api/wit", "./wit/deps/lyraapi").unwrap();
|
||||
}
|
||||
|
||||
fn copy_dir_all(src: impl AsRef<Path>, dst: impl AsRef<Path>) -> io::Result<()> {
|
||||
fs::create_dir_all(&dst)?;
|
||||
|
||||
for entry in fs::read_dir(src)? {
|
||||
let entry = entry?;
|
||||
let ty = entry.file_type()?;
|
||||
if ty.is_dir() {
|
||||
copy_dir_all(entry.path(), dst.as_ref().join(entry.file_name()))?;
|
||||
} else {
|
||||
fs::copy(entry.path(), dst.as_ref().join(entry.file_name()))?;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
|
@ -1,118 +0,0 @@
|
|||
// Generated by `wit-bindgen` 0.25.0. DO NOT EDIT!
|
||||
// Options used:
|
||||
#[allow(unused_unsafe, clippy::all)]
|
||||
pub fn host_print(msg: &str) {
|
||||
unsafe {
|
||||
let vec0 = msg;
|
||||
let ptr0 = vec0.as_ptr().cast::<u8>();
|
||||
let len0 = vec0.len();
|
||||
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
#[link(wasm_import_module = "$root")]
|
||||
extern "C" {
|
||||
#[link_name = "host-print"]
|
||||
fn wit_import(_: *mut u8, _: usize);
|
||||
}
|
||||
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
fn wit_import(_: *mut u8, _: usize) {
|
||||
unreachable!()
|
||||
}
|
||||
wit_import(ptr0.cast_mut(), len0);
|
||||
}
|
||||
}
|
||||
#[doc(hidden)]
|
||||
#[allow(non_snake_case)]
|
||||
pub unsafe fn _export_on_init_cabi<T: Guest>() -> i32 {
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
_rt::run_ctors_once();
|
||||
let result0 = T::on_init();
|
||||
let result1 = match result0 {
|
||||
Ok(_) => 0i32,
|
||||
Err(_) => 1i32,
|
||||
};
|
||||
result1
|
||||
}
|
||||
pub trait Guest {
|
||||
fn on_init() -> Result<(), ()>;
|
||||
}
|
||||
#[doc(hidden)]
|
||||
|
||||
macro_rules! __export_world_example_cabi{
|
||||
($ty:ident with_types_in $($path_to_types:tt)*) => (const _: () = {
|
||||
|
||||
#[export_name = "on-init"]
|
||||
unsafe extern "C" fn export_on_init() -> i32 {
|
||||
$($path_to_types)*::_export_on_init_cabi::<$ty>()
|
||||
}
|
||||
};);
|
||||
}
|
||||
#[doc(hidden)]
|
||||
pub(crate) use __export_world_example_cabi;
|
||||
#[allow(dead_code)]
|
||||
pub mod component {
|
||||
#[allow(dead_code)]
|
||||
pub mod witguest {
|
||||
#[allow(dead_code, clippy::all)]
|
||||
pub mod math {
|
||||
#[used]
|
||||
#[doc(hidden)]
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
static __FORCE_SECTION_REF: fn() =
|
||||
super::super::super::__link_custom_section_describing_imports;
|
||||
}
|
||||
}
|
||||
}
|
||||
mod _rt {
|
||||
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
pub fn run_ctors_once() {
|
||||
wit_bindgen_rt::run_ctors_once();
|
||||
}
|
||||
}
|
||||
|
||||
/// Generates `#[no_mangle]` functions to export the specified type as the
|
||||
/// root implementation of all generated traits.
|
||||
///
|
||||
/// For more information see the documentation of `wit_bindgen::generate!`.
|
||||
///
|
||||
/// ```rust
|
||||
/// # macro_rules! export{ ($($t:tt)*) => (); }
|
||||
/// # trait Guest {}
|
||||
/// struct MyType;
|
||||
///
|
||||
/// impl Guest for MyType {
|
||||
/// // ...
|
||||
/// }
|
||||
///
|
||||
/// export!(MyType);
|
||||
/// ```
|
||||
#[allow(unused_macros)]
|
||||
#[doc(hidden)]
|
||||
|
||||
macro_rules! __export_example_impl {
|
||||
($ty:ident) => (self::export!($ty with_types_in self););
|
||||
($ty:ident with_types_in $($path_to_types_root:tt)*) => (
|
||||
$($path_to_types_root)*::__export_world_example_cabi!($ty with_types_in $($path_to_types_root)*);
|
||||
)
|
||||
}
|
||||
#[doc(inline)]
|
||||
pub(crate) use __export_example_impl as export;
|
||||
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
#[link_section = "component-type:wit-bindgen:0.25.0:example:encoded world"]
|
||||
#[doc(hidden)]
|
||||
pub static __WIT_BINDGEN_COMPONENT_TYPE: [u8; 262] = *b"\
|
||||
\0asm\x0d\0\x01\0\0\x19\x16wit-component-encoding\x04\0\x07\x88\x01\x01A\x02\x01\
|
||||
A\x07\x01B\x02\x01r\x03\x01xv\x01yv\x01zv\x04\0\x04vec3\x03\0\0\x03\x01\x17compo\
|
||||
nent:witguest/math\x05\0\x01@\x01\x03msgs\x01\0\x03\0\x0ahost-print\x01\x01\x01j\
|
||||
\0\0\x01@\0\0\x02\x04\0\x07on-init\x01\x03\x04\x01\x1acomponent:witguest/example\
|
||||
\x04\0\x0b\x0d\x01\0\x07example\x03\0\0\0G\x09producers\x01\x0cprocessed-by\x02\x0d\
|
||||
wit-component\x070.208.1\x10wit-bindgen-rust\x060.25.0";
|
||||
|
||||
#[inline(never)]
|
||||
#[doc(hidden)]
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
pub fn __link_custom_section_describing_imports() {
|
||||
wit_bindgen_rt::maybe_link_cabi_realloc();
|
||||
}
|
|
@ -1,18 +1,28 @@
|
|||
#[allow(warnings)]
|
||||
mod bindings;
|
||||
use common_api::{math::{Vec3, Vec4}, World};
|
||||
|
||||
use bindings::Guest;
|
||||
use common_api::{World, math::{Vec3, Vec4}};
|
||||
wit_bindgen::generate!({
|
||||
world: "example",
|
||||
|
||||
with: {
|
||||
"lyra:api/ecs": common_api::bindings::lyra::api::ecs,
|
||||
},
|
||||
});
|
||||
|
||||
struct Component;
|
||||
|
||||
impl Guest for Component {
|
||||
fn on_init() -> Result<(), ()> {
|
||||
let world = World::new();
|
||||
fn on_init(world: &EcsWorld, _owning_entity: Entity) -> Result<(), ()> {
|
||||
let world = World::from(world);
|
||||
let en = world.spawn((Vec3::new(7.0, 30.0, 18.0), Vec4::new(10.0, 332.35, 329.0, 95.0)));
|
||||
|
||||
println!("guest spawned {:?}", en);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn on_update(world: &EcsWorld, _owning_entity: Entity) -> Result<(), ()> {
|
||||
let world = World::from(world);
|
||||
|
||||
let view = world.view::<(Vec3, Vec4)>();
|
||||
for pos in view {
|
||||
let (p3, p4) = pos.unwrap();
|
||||
|
@ -24,4 +34,4 @@ impl Guest for Component {
|
|||
}
|
||||
}
|
||||
|
||||
bindings::export!(Component with_types_in bindings);
|
||||
export!(Component);
|
|
@ -0,0 +1,62 @@
|
|||
package lyra:api;
|
||||
|
||||
interface ecs {
|
||||
record entity-id {
|
||||
id: u64,
|
||||
}
|
||||
|
||||
record entity {
|
||||
id: entity-id,
|
||||
generation: u64,
|
||||
}
|
||||
|
||||
record wasm-type-id {
|
||||
// represents a u128, can be converted into that with mem::transmute
|
||||
inner: tuple<u64, u64>,
|
||||
}
|
||||
|
||||
record component-info {
|
||||
host-name: option<string>,
|
||||
/// The size of the component in memory.
|
||||
size: u64,
|
||||
/// The alignment of the component in memory.
|
||||
alignment: u64,
|
||||
/// The type id of the component.
|
||||
///
|
||||
/// This must be unique between component types since its used to identify the components
|
||||
/// in spawning and querying.
|
||||
type-id: wasm-type-id,
|
||||
}
|
||||
|
||||
resource ecs-dynamic-view {
|
||||
constructor(wrld: borrow<ecs-world>, component-infos: list<component-info>);
|
||||
|
||||
/// Get the bytes of the next row in the view.
|
||||
///
|
||||
/// A row contains multiple component serialized as bytes. The buffer is tighly packed.
|
||||
next: func() -> option<list<u8>>;
|
||||
}
|
||||
|
||||
resource ecs-world {
|
||||
constructor();
|
||||
|
||||
/// Spawn an entity.
|
||||
///
|
||||
/// Parameters:
|
||||
/// * `components`: A tightly packed byte buffer containing the components to spawn
|
||||
/// with the entity. This expects the components in the same order of `component-infos`.
|
||||
/// * `component-infos`: A list of `component-infos` uses to identify the components
|
||||
/// and specify the layouts of them.
|
||||
spawn: func(components: list<u8>, component-infos: list<component-info>) -> entity;
|
||||
|
||||
/// Query for a list of entities and their components.
|
||||
///
|
||||
/// Parameters:
|
||||
/// * `component-infos`: The `component-info`'s of the components that you are querying.
|
||||
///
|
||||
/// Returns: an iterator that returns the byte buffers of each row.
|
||||
view: func(component-infos: list<component-info>) -> ecs-dynamic-view;
|
||||
|
||||
//with_system: func(stage: string, component-infos: list<component-info>, system: func(components: list<u8>));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
package lyra:api;
|
||||
|
||||
world imports {
|
||||
import ecs;
|
||||
}
|
|
@ -11,7 +11,10 @@ interface math {
|
|||
/// An example world for the component to target.
|
||||
world example {
|
||||
import math;
|
||||
use lyra:api/ecs.{ecs-world, entity};
|
||||
|
||||
import host-print: func(msg: string);
|
||||
export on-init: func() -> result;
|
||||
|
||||
export on-init: func(game-world: borrow<ecs-world>, owning-entity: entity) -> result;
|
||||
export on-update: func(game-world: borrow<ecs-world>, owning-entity: entity) -> result;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue