PoC for spawning entities with components and querying them
This commit is contained in:
parent
1c5a24c320
commit
57539df4e7
|
@ -0,0 +1,3 @@
|
||||||
|
[submodule "lyra-engine"]
|
||||||
|
path = lyra-engine
|
||||||
|
url = git@git.seanomik.net:SeanOMik/lyra-engine.git
|
|
@ -67,6 +67,12 @@ dependencies = [
|
||||||
"syn",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "atomic_refcell"
|
||||||
|
version = "0.1.13"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "41e67cd8309bbd06cd603a9e693a784ac2e5d1e955f11286e355089fcab3047c"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "autocfg"
|
name = "autocfg"
|
||||||
version = "1.2.0"
|
version = "1.2.0"
|
||||||
|
@ -655,6 +661,12 @@ dependencies = [
|
||||||
"stable_deref_trait",
|
"stable_deref_trait",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "glam"
|
||||||
|
version = "0.24.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b5418c17512bdf42730f9032c74e1ae39afc408745ebb2acf72fbc4691c17945"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hashbrown"
|
name = "hashbrown"
|
||||||
version = "0.13.2"
|
version = "0.13.2"
|
||||||
|
@ -854,6 +866,36 @@ version = "0.4.21"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c"
|
checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "lyra-ecs"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"anyhow",
|
||||||
|
"atomic_refcell",
|
||||||
|
"lyra-ecs-derive",
|
||||||
|
"lyra-math",
|
||||||
|
"paste",
|
||||||
|
"rand",
|
||||||
|
"thiserror",
|
||||||
|
"tracing",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "lyra-ecs-derive"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "lyra-math"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"glam",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "mach"
|
name = "mach"
|
||||||
version = "0.3.2"
|
version = "0.3.2"
|
||||||
|
@ -2228,6 +2270,7 @@ name = "wittest"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"async-trait",
|
"async-trait",
|
||||||
|
"lyra-ecs",
|
||||||
"tokio",
|
"tokio",
|
||||||
"wasmtime",
|
"wasmtime",
|
||||||
"wasmtime-wasi",
|
"wasmtime-wasi",
|
||||||
|
|
|
@ -11,3 +11,4 @@ async-trait = "0.1.80"
|
||||||
tokio = { version = "1.37.0", features = ["full"] }
|
tokio = { version = "1.37.0", features = ["full"] }
|
||||||
wasmtime = "19.0.2"
|
wasmtime = "19.0.2"
|
||||||
wasmtime-wasi = "19.0.2"
|
wasmtime-wasi = "19.0.2"
|
||||||
|
lyra-ecs = { path = "./lyra-engine/lyra-ecs" }
|
|
@ -0,0 +1 @@
|
||||||
|
Subproject commit 60ec62c55828a4ea273a10e5614e7cc589b005cf
|
146
src/main.rs
146
src/main.rs
|
@ -1,6 +1,25 @@
|
||||||
|
use std::alloc::Layout;
|
||||||
|
use std::any::TypeId;
|
||||||
|
use std::mem;
|
||||||
|
use std::ptr::NonNull;
|
||||||
|
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
|
use component::witguest::{ecs_world, math};
|
||||||
|
use ecs::query::dynamic::QueryDynamicType;
|
||||||
|
use lyra_ecs::{Component, World};
|
||||||
|
|
||||||
|
use lyra_ecs as ecs;
|
||||||
|
|
||||||
|
use lyra_engine::ecs::component::witguest::ecs_world::WasmTypeId;
|
||||||
use wasmtime_wasi::WasiView;
|
use wasmtime_wasi::WasiView;
|
||||||
|
|
||||||
|
#[allow(unused_imports)]
|
||||||
|
pub(crate) mod lyra_engine {
|
||||||
|
pub(crate) mod ecs {
|
||||||
|
pub use super::super::*;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
wasmtime::component::bindgen!({
|
wasmtime::component::bindgen!({
|
||||||
world: "example",
|
world: "example",
|
||||||
path: "witguest/wit/world.wit",
|
path: "witguest/wit/world.wit",
|
||||||
|
@ -8,8 +27,50 @@ wasmtime::component::bindgen!({
|
||||||
async: true,
|
async: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
struct Imports {
|
impl WasmTypeId {
|
||||||
|
pub fn of<T: 'static>() -> Self {
|
||||||
|
Self {
|
||||||
|
inner: unsafe { mem::transmute(TypeId::of::<T>()) },
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Into<ecs::DynTypeId> for WasmTypeId {
|
||||||
|
fn into(self) -> ecs::DynTypeId {
|
||||||
|
// SAFETY: the memory layout of (u64, u64) is the same as u128
|
||||||
|
ecs::DynTypeId::Unknown(unsafe { mem::transmute(self.inner) })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Into<ecs::ComponentInfo> for ecs_world::ComponentInfo {
|
||||||
|
fn into(self) -> ecs::ComponentInfo {
|
||||||
|
ecs::ComponentInfo::new_unknown(
|
||||||
|
None,
|
||||||
|
self.type_id,
|
||||||
|
Layout::from_size_align(self.size as _, self.alignment as _).unwrap(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<ecs::Entity> for ecs_world::Entity {
|
||||||
|
fn from(value: ecs::Entity) -> Self {
|
||||||
|
Self {
|
||||||
|
id: ecs_world::EntityId { id: value.id().0 },
|
||||||
|
generation: value.generation(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Component)]
|
||||||
|
struct Vec3 {
|
||||||
|
x: f32,
|
||||||
|
y: f32,
|
||||||
|
z: f32,
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Imports {
|
||||||
|
world: lyra_ecs::World,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WasiView for Imports {
|
impl WasiView for Imports {
|
||||||
|
@ -24,12 +85,68 @@ impl WasiView for Imports {
|
||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl ExampleImports for Imports {
|
impl ExampleImports for Imports {
|
||||||
async fn host_test(&mut self,) -> wasmtime::Result<()> {
|
async fn host_print(&mut self, msg: String) -> wasmtime::Result<()> {
|
||||||
println!("This is the host saying hi from the guest!");
|
println!("{}", msg);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl math::Host for Imports {}
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
|
impl ecs_world::Host for Imports {
|
||||||
|
async fn spawn(
|
||||||
|
&mut self,
|
||||||
|
mut components: Vec<u8>,
|
||||||
|
infos: Vec<ecs_world::ComponentInfo>,
|
||||||
|
) -> wasmtime::Result<ecs_world::Entity> {
|
||||||
|
// add the components in the tightly packed `components` buffer into the dynamic bundle
|
||||||
|
let mut bundle = ecs::DynamicBundle::new();
|
||||||
|
let mut offset = 0;
|
||||||
|
for info in infos {
|
||||||
|
// SAFETY: The components are tightly packed, adding the offset to the pointer will
|
||||||
|
// get the next component in the buffer.
|
||||||
|
let data_ptr = unsafe { NonNull::new_unchecked(components.as_mut_ptr().add(offset)) };
|
||||||
|
bundle.push_unknown(data_ptr, info.into());
|
||||||
|
|
||||||
|
offset += info.size as usize;
|
||||||
|
}
|
||||||
|
|
||||||
|
let en = self.world.spawn(bundle);
|
||||||
|
Ok(en.into())
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn view(&mut self, infos: Vec<ecs_world::ComponentInfo>) -> wasmtime::Result<Vec<u8>> {
|
||||||
|
// Create a dynamic view for querying for the components
|
||||||
|
let mut view = self.world.dynamic_view();
|
||||||
|
for info in infos.clone() {
|
||||||
|
view.push(QueryDynamicType::from_info(info.into()));
|
||||||
|
}
|
||||||
|
|
||||||
|
// allocate the row of components
|
||||||
|
let total_len = infos.iter().map(|i| i.size as usize).sum();
|
||||||
|
let mut components = Vec::with_capacity(total_len);
|
||||||
|
|
||||||
|
// copy each row of the query into the set of components. could get pretty big, but its a PoC so :shrug:
|
||||||
|
for row in view.into_iter() {
|
||||||
|
let first = row.iter().next().unwrap();
|
||||||
|
|
||||||
|
let mut comp = Vec::<u8>::with_capacity(first.info.layout().size());
|
||||||
|
unsafe {
|
||||||
|
std::ptr::copy_nonoverlapping(
|
||||||
|
first.ptr.as_ptr(),
|
||||||
|
comp.as_mut_ptr(),
|
||||||
|
first.info.layout().size(),
|
||||||
|
);
|
||||||
|
comp.set_len(first.info.layout().size());
|
||||||
|
}
|
||||||
|
components.extend(comp.into_iter());
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(components)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() -> wasmtime::Result<()> {
|
async fn main() -> wasmtime::Result<()> {
|
||||||
// Instantiate the engine and store
|
// Instantiate the engine and store
|
||||||
|
@ -37,22 +154,29 @@ async fn main() -> wasmtime::Result<()> {
|
||||||
config.async_support(true);
|
config.async_support(true);
|
||||||
|
|
||||||
let engine = wasmtime::Engine::new(&config)?;
|
let engine = wasmtime::Engine::new(&config)?;
|
||||||
let mut store = wasmtime::Store::new(&engine, Imports {});
|
|
||||||
|
|
||||||
// Load the component from disk
|
|
||||||
let bytes = std::fs::read("target/wasm32-wasi/debug/witguest.wasm")?;
|
|
||||||
let component = wasmtime::component::Component::new(&engine, bytes)?;
|
|
||||||
|
|
||||||
// Configure the linker
|
// Configure the linker
|
||||||
let mut linker = wasmtime::component::Linker::new(&engine);
|
let mut linker = wasmtime::component::Linker::new(&engine);
|
||||||
wasmtime_wasi::bindings::Imports::add_to_linker(&mut linker, |s| s)?;
|
wasmtime_wasi::bindings::Imports::add_to_linker(&mut linker, |s| s)?;
|
||||||
Example::add_to_linker(&mut linker, |s| s)?;
|
Example::add_to_linker(&mut linker, |s| s)?;
|
||||||
|
|
||||||
|
// memory per instance
|
||||||
|
let mut store = wasmtime::Store::new(
|
||||||
|
&engine,
|
||||||
|
Imports {
|
||||||
|
world: World::new(),
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
// Load the component from disk
|
||||||
|
let bytes = std::fs::read("target/wasm32-wasi/debug/witguest.wasm")?;
|
||||||
|
let component = wasmtime::component::Component::new(&engine, bytes)?;
|
||||||
|
|
||||||
// Instantiate the component
|
// Instantiate the component
|
||||||
println!("creating example");
|
println!("creating example");
|
||||||
let (example, _instance) = Example::instantiate_async(&mut store, &component, &linker).await?;
|
let (example, _instance) = Example::instantiate_async(&mut store, &component, &linker).await?;
|
||||||
let result = example.call_hello_world(&mut store).await?;
|
let result = example.call_on_init(&mut store).await?.unwrap();
|
||||||
println!("Guest says: {}", result);
|
println!("Guest returned: {}", result);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,29 +1,32 @@
|
||||||
// Generated by `wit-bindgen` 0.18.0. DO NOT EDIT!
|
// Generated by `wit-bindgen` 0.18.0. DO NOT EDIT!
|
||||||
#[allow(unused_unsafe, clippy::all)]
|
#[allow(unused_unsafe, clippy::all)]
|
||||||
pub fn host_test(){
|
pub fn host_print(msg: &str,){
|
||||||
|
|
||||||
#[allow(unused_imports)]
|
#[allow(unused_imports)]
|
||||||
use wit_bindgen::rt::{alloc, vec::Vec, string::String};
|
use wit_bindgen::rt::{alloc, vec::Vec, string::String};
|
||||||
unsafe {
|
unsafe {
|
||||||
|
let vec0 = msg;
|
||||||
|
let ptr0 = vec0.as_ptr() as i32;
|
||||||
|
let len0 = vec0.len() as i32;
|
||||||
|
|
||||||
#[cfg(target_arch = "wasm32")]
|
#[cfg(target_arch = "wasm32")]
|
||||||
#[link(wasm_import_module = "$root")]
|
#[link(wasm_import_module = "$root")]
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#[link_name = "host-test"]
|
#[link_name = "host-print"]
|
||||||
fn wit_import();
|
fn wit_import(_: i32, _: i32, );
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
fn wit_import(){ unreachable!() }
|
fn wit_import(_: i32, _: i32, ){ unreachable!() }
|
||||||
wit_import();
|
wit_import(ptr0, len0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const _: () = {
|
const _: () = {
|
||||||
|
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
#[export_name = "hello-world"]
|
#[export_name = "on-init"]
|
||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
unsafe extern "C" fn __export_hello_world() -> i32 {
|
unsafe extern "C" fn __export_on_init() -> i32 {
|
||||||
#[allow(unused_imports)]
|
#[allow(unused_imports)]
|
||||||
use wit_bindgen::rt::{alloc, vec::Vec, string::String};
|
use wit_bindgen::rt::{alloc, vec::Vec, string::String};
|
||||||
|
|
||||||
|
@ -41,44 +44,171 @@ const _: () = {
|
||||||
#[cfg(target_arch="wasm32")]
|
#[cfg(target_arch="wasm32")]
|
||||||
wit_bindgen::rt::run_ctors_once();
|
wit_bindgen::rt::run_ctors_once();
|
||||||
|
|
||||||
let result0 = <_GuestImpl as Guest>::hello_world();
|
let result0 = <_GuestImpl as Guest>::on_init();
|
||||||
let ptr1 = _RET_AREA.0.as_mut_ptr() as i32;
|
let ptr1 = _RET_AREA.0.as_mut_ptr() as i32;
|
||||||
let vec2 = (result0.into_bytes()).into_boxed_slice();
|
match result0 {
|
||||||
let ptr2 = vec2.as_ptr() as i32;
|
Ok(e) => { {
|
||||||
let len2 = vec2.len() as i32;
|
*((ptr1 + 0) as *mut u8) = (0i32) as u8;
|
||||||
::core::mem::forget(vec2);
|
*((ptr1 + 1) as *mut u8) = (wit_bindgen::rt::as_i32(e)) as u8;
|
||||||
*((ptr1 + 4) as *mut i32) = len2;
|
} },
|
||||||
*((ptr1 + 0) as *mut i32) = ptr2;
|
Err(_) => { {
|
||||||
ptr1
|
*((ptr1 + 0) as *mut u8) = (1i32) as u8;
|
||||||
|
} },
|
||||||
|
};ptr1
|
||||||
}
|
}
|
||||||
|
|
||||||
const _: () = {
|
|
||||||
#[doc(hidden)]
|
|
||||||
#[export_name = "cabi_post_hello-world"]
|
|
||||||
#[allow(non_snake_case)]
|
|
||||||
unsafe extern "C" fn __post_return_hello_world(arg0: i32,) {
|
|
||||||
let l0 = *((arg0 + 0) as *const i32);
|
|
||||||
let l1 = *((arg0 + 4) as *const i32);
|
|
||||||
wit_bindgen::rt::dealloc(l0, (l1) as usize, 1);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
use super::Component as _GuestImpl;
|
use super::Component as _GuestImpl;
|
||||||
pub trait Guest {
|
pub trait Guest {
|
||||||
fn hello_world() -> wit_bindgen::rt::string::String;
|
fn on_init() -> Result<u8,()>;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(unused_imports)]
|
#[allow(unused_imports)]
|
||||||
use wit_bindgen::rt::{alloc, vec::Vec, string::String};
|
use wit_bindgen::rt::{alloc, vec::Vec, string::String};
|
||||||
|
|
||||||
#[repr(align(4))]
|
#[repr(align(1))]
|
||||||
struct _RetArea([u8; 8]);
|
struct _RetArea([u8; 2]);
|
||||||
static mut _RET_AREA: _RetArea = _RetArea([0; 8]);
|
static mut _RET_AREA: _RetArea = _RetArea([0; 2]);
|
||||||
|
pub mod component {
|
||||||
|
pub mod witguest {
|
||||||
|
|
||||||
|
#[allow(clippy::all)]
|
||||||
|
pub mod math {
|
||||||
|
#[used]
|
||||||
|
#[doc(hidden)]
|
||||||
|
#[cfg(target_arch = "wasm32")]
|
||||||
|
static __FORCE_SECTION_REF: fn() = super::super::super::__link_section;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[allow(clippy::all)]
|
||||||
|
pub mod ecs_world {
|
||||||
|
#[used]
|
||||||
|
#[doc(hidden)]
|
||||||
|
#[cfg(target_arch = "wasm32")]
|
||||||
|
static __FORCE_SECTION_REF: fn() = super::super::super::__link_section;
|
||||||
|
/// use math.{vec3};
|
||||||
|
#[repr(C)]
|
||||||
|
#[derive(Clone, Copy)]
|
||||||
|
pub struct EntityId {
|
||||||
|
pub id: u64,
|
||||||
|
}
|
||||||
|
impl ::core::fmt::Debug for EntityId {
|
||||||
|
fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
|
||||||
|
f.debug_struct("EntityId").field("id", &self.id).finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#[repr(C)]
|
||||||
|
#[derive(Clone, Copy)]
|
||||||
|
pub struct Entity {
|
||||||
|
pub id: EntityId,
|
||||||
|
pub generation: u64,
|
||||||
|
}
|
||||||
|
impl ::core::fmt::Debug for Entity {
|
||||||
|
fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
|
||||||
|
f.debug_struct("Entity").field("id", &self.id).field("generation", &self.generation).finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#[repr(C)]
|
||||||
|
#[derive(Clone, Copy)]
|
||||||
|
pub struct WasmTypeId {
|
||||||
|
pub inner: (u64,u64,),
|
||||||
|
}
|
||||||
|
impl ::core::fmt::Debug for WasmTypeId {
|
||||||
|
fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
|
||||||
|
f.debug_struct("WasmTypeId").field("inner", &self.inner).finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#[repr(C)]
|
||||||
|
#[derive(Clone, Copy)]
|
||||||
|
pub struct ComponentInfo {
|
||||||
|
pub size: u64,
|
||||||
|
pub alignment: u64,
|
||||||
|
pub type_id: WasmTypeId,
|
||||||
|
}
|
||||||
|
impl ::core::fmt::Debug for ComponentInfo {
|
||||||
|
fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
|
||||||
|
f.debug_struct("ComponentInfo").field("size", &self.size).field("alignment", &self.alignment).field("type-id", &self.type_id).finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#[allow(unused_unsafe, clippy::all)]
|
||||||
|
/// expects components to be tightly packed in the same order of component-infos
|
||||||
|
pub fn spawn(components: &[u8],component_infos: &[ComponentInfo],) -> Entity{
|
||||||
|
|
||||||
|
#[allow(unused_imports)]
|
||||||
|
use wit_bindgen::rt::{alloc, vec::Vec, string::String};
|
||||||
|
unsafe {
|
||||||
|
|
||||||
|
#[repr(align(8))]
|
||||||
|
struct RetArea([u8; 16]);
|
||||||
|
let mut ret_area = ::core::mem::MaybeUninit::<RetArea>::uninit();
|
||||||
|
let vec0 = components;
|
||||||
|
let ptr0 = vec0.as_ptr() as i32;
|
||||||
|
let len0 = vec0.len() as i32;
|
||||||
|
let vec1 = component_infos;
|
||||||
|
let ptr1 = vec1.as_ptr() as i32;
|
||||||
|
let len1 = vec1.len() as i32;
|
||||||
|
let ptr2 = ret_area.as_mut_ptr() as i32;
|
||||||
|
#[cfg(target_arch = "wasm32")]
|
||||||
|
#[link(wasm_import_module = "component:witguest/ecs-world")]
|
||||||
|
extern "C" {
|
||||||
|
#[link_name = "spawn"]
|
||||||
|
fn wit_import(_: i32, _: i32, _: i32, _: i32, _: i32, );
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
|
fn wit_import(_: i32, _: i32, _: i32, _: i32, _: i32, ){ unreachable!() }
|
||||||
|
wit_import(ptr0, len0, ptr1, len1, ptr2);
|
||||||
|
let l3 = *((ptr2 + 0) as *const i64);
|
||||||
|
let l4 = *((ptr2 + 8) as *const i64);
|
||||||
|
Entity{
|
||||||
|
id: EntityId{
|
||||||
|
id: l3 as u64,
|
||||||
|
},
|
||||||
|
generation: l4 as u64,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#[allow(unused_unsafe, clippy::all)]
|
||||||
|
pub fn view(component_infos: &[ComponentInfo],) -> wit_bindgen::rt::vec::Vec::<u8>{
|
||||||
|
|
||||||
|
#[allow(unused_imports)]
|
||||||
|
use wit_bindgen::rt::{alloc, vec::Vec, string::String};
|
||||||
|
unsafe {
|
||||||
|
|
||||||
|
#[repr(align(4))]
|
||||||
|
struct RetArea([u8; 8]);
|
||||||
|
let mut ret_area = ::core::mem::MaybeUninit::<RetArea>::uninit();
|
||||||
|
let vec0 = component_infos;
|
||||||
|
let ptr0 = vec0.as_ptr() as i32;
|
||||||
|
let len0 = vec0.len() as i32;
|
||||||
|
let ptr1 = ret_area.as_mut_ptr() as i32;
|
||||||
|
#[cfg(target_arch = "wasm32")]
|
||||||
|
#[link(wasm_import_module = "component:witguest/ecs-world")]
|
||||||
|
extern "C" {
|
||||||
|
#[link_name = "view"]
|
||||||
|
fn wit_import(_: i32, _: i32, _: i32, );
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
|
fn wit_import(_: i32, _: i32, _: i32, ){ unreachable!() }
|
||||||
|
wit_import(ptr0, len0, ptr1);
|
||||||
|
let l2 = *((ptr1 + 0) as *const i32);
|
||||||
|
let l3 = *((ptr1 + 4) as *const i32);
|
||||||
|
let len4 = l3 as usize;
|
||||||
|
Vec::from_raw_parts(l2 as *mut _, len4, len4)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(target_arch = "wasm32")]
|
#[cfg(target_arch = "wasm32")]
|
||||||
#[link_section = "component-type:example"]
|
#[link_section = "component-type:example"]
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
pub static __WIT_BINDGEN_COMPONENT_TYPE: [u8; 201] = [0, 97, 115, 109, 13, 0, 1, 0, 0, 25, 22, 119, 105, 116, 45, 99, 111, 109, 112, 111, 110, 101, 110, 116, 45, 101, 110, 99, 111, 100, 105, 110, 103, 4, 0, 7, 77, 1, 65, 2, 1, 65, 4, 1, 64, 0, 1, 0, 3, 0, 9, 104, 111, 115, 116, 45, 116, 101, 115, 116, 1, 0, 1, 64, 0, 0, 115, 4, 0, 11, 104, 101, 108, 108, 111, 45, 119, 111, 114, 108, 100, 1, 1, 4, 1, 26, 99, 111, 109, 112, 111, 110, 101, 110, 116, 58, 119, 105, 116, 103, 117, 101, 115, 116, 47, 101, 120, 97, 109, 112, 108, 101, 4, 0, 11, 13, 1, 0, 7, 101, 120, 97, 109, 112, 108, 101, 3, 0, 0, 0, 70, 9, 112, 114, 111, 100, 117, 99, 101, 114, 115, 1, 12, 112, 114, 111, 99, 101, 115, 115, 101, 100, 45, 98, 121, 2, 13, 119, 105, 116, 45, 99, 111, 109, 112, 111, 110, 101, 110, 116, 6, 48, 46, 50, 49, 46, 48, 16, 119, 105, 116, 45, 98, 105, 110, 100, 103, 101, 110, 45, 114, 117, 115, 116, 6, 48, 46, 49, 56, 46, 48];
|
pub static __WIT_BINDGEN_COMPONENT_TYPE: [u8; 514] = [0, 97, 115, 109, 13, 0, 1, 0, 0, 25, 22, 119, 105, 116, 45, 99, 111, 109, 112, 111, 110, 101, 110, 116, 45, 101, 110, 99, 111, 100, 105, 110, 103, 4, 0, 7, 133, 3, 1, 65, 2, 1, 65, 9, 1, 66, 2, 1, 114, 3, 1, 120, 118, 1, 121, 118, 1, 122, 118, 4, 0, 4, 118, 101, 99, 51, 3, 0, 0, 3, 1, 23, 99, 111, 109, 112, 111, 110, 101, 110, 116, 58, 119, 105, 116, 103, 117, 101, 115, 116, 47, 109, 97, 116, 104, 5, 0, 1, 66, 15, 1, 114, 1, 2, 105, 100, 119, 4, 0, 9, 101, 110, 116, 105, 116, 121, 45, 105, 100, 3, 0, 0, 1, 114, 2, 2, 105, 100, 1, 10, 103, 101, 110, 101, 114, 97, 116, 105, 111, 110, 119, 4, 0, 6, 101, 110, 116, 105, 116, 121, 3, 0, 2, 1, 111, 2, 119, 119, 1, 114, 1, 5, 105, 110, 110, 101, 114, 4, 4, 0, 12, 119, 97, 115, 109, 45, 116, 121, 112, 101, 45, 105, 100, 3, 0, 5, 1, 114, 3, 4, 115, 105, 122, 101, 119, 9, 97, 108, 105, 103, 110, 109, 101, 110, 116, 119, 7, 116, 121, 112, 101, 45, 105, 100, 6, 4, 0, 14, 99, 111, 109, 112, 111, 110, 101, 110, 116, 45, 105, 110, 102, 111, 3, 0, 7, 1, 112, 125, 1, 112, 8, 1, 64, 2, 10, 99, 111, 109, 112, 111, 110, 101, 110, 116, 115, 9, 15, 99, 111, 109, 112, 111, 110, 101, 110, 116, 45, 105, 110, 102, 111, 115, 10, 0, 3, 4, 0, 5, 115, 112, 97, 119, 110, 1, 11, 1, 64, 1, 15, 99, 111, 109, 112, 111, 110, 101, 110, 116, 45, 105, 110, 102, 111, 115, 10, 0, 9, 4, 0, 4, 118, 105, 101, 119, 1, 12, 3, 1, 28, 99, 111, 109, 112, 111, 110, 101, 110, 116, 58, 119, 105, 116, 103, 117, 101, 115, 116, 47, 101, 99, 115, 45, 119, 111, 114, 108, 100, 5, 1, 1, 64, 1, 3, 109, 115, 103, 115, 1, 0, 3, 0, 10, 104, 111, 115, 116, 45, 112, 114, 105, 110, 116, 1, 2, 1, 106, 1, 125, 0, 1, 64, 0, 0, 3, 4, 0, 7, 111, 110, 45, 105, 110, 105, 116, 1, 4, 4, 1, 26, 99, 111, 109, 112, 111, 110, 101, 110, 116, 58, 119, 105, 116, 103, 117, 101, 115, 116, 47, 101, 120, 97, 109, 112, 108, 101, 4, 0, 11, 13, 1, 0, 7, 101, 120, 97, 109, 112, 108, 101, 3, 0, 0, 0, 70, 9, 112, 114, 111, 100, 117, 99, 101, 114, 115, 1, 12, 112, 114, 111, 99, 101, 115, 115, 101, 100, 45, 98, 121, 2, 13, 119, 105, 116, 45, 99, 111, 109, 112, 111, 110, 101, 110, 116, 6, 48, 46, 50, 49, 46, 48, 16, 119, 105, 116, 45, 98, 105, 110, 100, 103, 101, 110, 45, 114, 117, 115, 116, 6, 48, 46, 49, 56, 46, 48];
|
||||||
|
|
||||||
#[inline(never)]
|
#[inline(never)]
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
|
|
|
@ -1,13 +1,63 @@
|
||||||
|
#[allow(warnings)]
|
||||||
mod bindings;
|
mod bindings;
|
||||||
|
|
||||||
use bindings::Guest;
|
use bindings::{component::witguest::ecs_world::{self, ComponentInfo, WasmTypeId}, Guest};
|
||||||
|
|
||||||
|
use std::{alloc::Layout, any::TypeId, mem};
|
||||||
|
|
||||||
|
impl WasmTypeId {
|
||||||
|
pub fn of<T: 'static>() -> Self {
|
||||||
|
Self {
|
||||||
|
inner: unsafe { mem::transmute(TypeId::of::<T>()) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||||
|
struct Vec3 {
|
||||||
|
x: f32,
|
||||||
|
y: f32,
|
||||||
|
z: f32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Vec3 {
|
||||||
|
pub fn new(x: f32, y: f32, z: f32) -> Self {
|
||||||
|
Self {
|
||||||
|
x, y, z
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn component_info() -> ComponentInfo {
|
||||||
|
let layout = Layout::new::<Vec3>();
|
||||||
|
ComponentInfo {
|
||||||
|
size: layout.size() as u64,
|
||||||
|
alignment: layout.align() as u64,
|
||||||
|
type_id: WasmTypeId::of::<Vec3>(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
struct Component;
|
struct Component;
|
||||||
|
|
||||||
impl Guest for Component {
|
impl Guest for Component {
|
||||||
/// Say hello!
|
fn on_init() -> Result<u8, ()> {
|
||||||
fn hello_world() -> String {
|
let comps = &mut [Vec3::new(7.0, 30.0, 18.0),];
|
||||||
bindings::host_test();
|
let info = &[Vec3::component_info()];
|
||||||
"Hello, World!".to_string()
|
|
||||||
|
// no fucking clue if this will work, but lets try and it see
|
||||||
|
let comps = comps.as_mut_ptr().cast::<u8>();
|
||||||
|
let comps = unsafe { Vec::from_raw_parts(comps, mem::size_of::<Vec3>(), 1) };
|
||||||
|
|
||||||
|
let en = ecs_world::spawn(&comps, info);
|
||||||
|
|
||||||
|
bindings::host_print(&format!("Spawned entity: {}", en.id.id));
|
||||||
|
|
||||||
|
let mut buffer = ecs_world::view(&[Vec3::component_info()]);
|
||||||
|
bindings::host_print(&format!("Retrieved vec3 of {} bytes long", buffer.len()));
|
||||||
|
let fetched_vec = unsafe { std::ptr::read(buffer.as_mut_ptr().cast::<Vec3>()) };
|
||||||
|
bindings::host_print(&format!("Retrieved vec3: {:?}", fetched_vec));
|
||||||
|
|
||||||
|
Ok(0)
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,7 +1,45 @@
|
||||||
package component:witguest;
|
package component:witguest;
|
||||||
|
|
||||||
|
interface math {
|
||||||
|
record vec3 {
|
||||||
|
x: f32,
|
||||||
|
y: f32,
|
||||||
|
z: f32,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ecs-world {
|
||||||
|
//use math.{vec3};
|
||||||
|
|
||||||
|
record entity-id {
|
||||||
|
id: u64,
|
||||||
|
}
|
||||||
|
|
||||||
|
record entity {
|
||||||
|
id: entity-id,
|
||||||
|
generation: u64,
|
||||||
|
}
|
||||||
|
|
||||||
|
record wasm-type-id {
|
||||||
|
inner: tuple<u64, u64>,
|
||||||
|
}
|
||||||
|
|
||||||
|
record component-info {
|
||||||
|
size: u64,
|
||||||
|
alignment: u64,
|
||||||
|
type-id: wasm-type-id, // a u128
|
||||||
|
}
|
||||||
|
|
||||||
|
// expects components to be tightly packed in the same order of component-infos
|
||||||
|
spawn: func(components: list<u8>, component-infos: list<component-info>) -> entity;
|
||||||
|
view: func(component-infos: list<component-info>) -> list<u8>;
|
||||||
|
}
|
||||||
|
|
||||||
/// An example world for the component to target.
|
/// An example world for the component to target.
|
||||||
world example {
|
world example {
|
||||||
import host-test: func();
|
import math;
|
||||||
export hello-world: func() -> string;
|
import ecs-world;
|
||||||
|
|
||||||
|
import host-print: func(msg: string);
|
||||||
|
export on-init: func() -> result<u8>;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue