diff --git a/common/sys/src/plugin/mod.rs b/common/sys/src/plugin/mod.rs index 31f548cb7a..383c1192e2 100644 --- a/common/sys/src/plugin/mod.rs +++ b/common/sys/src/plugin/mod.rs @@ -3,6 +3,7 @@ pub mod module; use common::assets::ASSETS_PATH; use serde::{Deserialize, Serialize}; +use specs::World; use std::{ collections::{HashMap, HashSet}, fs, @@ -80,6 +81,7 @@ impl Plugin { pub fn execute_prepared( &self, + ecs: &World, event_name: &str, event: &PreparedEventQuery, ) -> Result, PluginError> @@ -89,7 +91,7 @@ impl Plugin { self.modules .iter() .flat_map(|module| { - module.try_execute(event_name, event).map(|x| { + module.try_execute(ecs, event_name, event).map(|x| { x.map_err(|e| { PluginError::PluginModuleError( self.data.name.to_owned(), @@ -118,6 +120,7 @@ impl PluginMgr { pub fn execute_prepared( &self, + ecs: &World, event_name: &str, event: &PreparedEventQuery, ) -> Result, PluginError> @@ -127,7 +130,7 @@ impl PluginMgr { Ok(self .plugins .par_iter() - .map(|plugin| plugin.execute_prepared(event_name, event)) + .map(|plugin| plugin.execute_prepared(ecs, event_name, event)) .collect::, _>>()? .into_iter() .flatten() @@ -136,13 +139,14 @@ impl PluginMgr { pub fn execute_event( &self, + ecs: &World, event_name: &str, event: &T, ) -> Result, PluginError> where T: Event, { - self.execute_prepared(event_name, &PreparedEventQuery::new(event)?) + self.execute_prepared(ecs, event_name, &PreparedEventQuery::new(event)?) } pub fn from_dir>(path: P) -> Result { diff --git a/common/sys/src/plugin/module.rs b/common/sys/src/plugin/module.rs index 2acb3f4899..1a780911a2 100644 --- a/common/sys/src/plugin/module.rs +++ b/common/sys/src/plugin/module.rs @@ -1,10 +1,6 @@ -use std::{ - cell::Cell, - collections::HashSet, - marker::PhantomData, - sync::{Arc, Mutex}, -}; +use std::{cell::{Cell, RefCell}, cmp::Ordering, collections::HashSet, marker::PhantomData, rc::Rc, sync::{self, Arc, Mutex, atomic::AtomicI32}}; +use specs::World; use wasmer::{ imports, Cranelift, Function, HostEnvInitError, Instance, LazyInit, Memory, MemoryView, Module, Store, Value, WasmerEnv, JIT, @@ -17,6 +13,7 @@ use plugin_api::{Action, Event}; #[derive(Clone)] // This structure represent the WASM State of the plugin. pub struct PluginModule { + ecs: Arc, wasm_state: Arc>, events: HashSet, name: String, @@ -55,11 +52,42 @@ impl PluginModule { }, }); } + + fn raw_retreive_action(env: &EmitActionEnv, ptr: u32, len: u32) { + let memory: &Memory = if let Some(e) = env.memory.get_ref() { + e + } else { + // This should not be possible but I prefer be safer! + tracing::error!("Can't get memory from: `{}` plugin", env.name); + return; + }; + let memory: MemoryView = memory.view(); + + let str_slice = &memory[ptr as usize..(ptr + len) as usize]; + + let bytes: Vec = str_slice.iter().map(|x| x.get()).collect(); + + let r = env.ecs.load(std::sync::atomic::Ordering::SeqCst); + if r == i32::MAX { + println!("No ECS availible 1"); + return; + } + unsafe { + if let Some(t) = (r as *const World).as_ref() { + println!("We have a pointer there"); + } else { + println!("No ECS availible 2"); + } + } + } + + let ecs = Arc::new(AtomicI32::new(i32::MAX)); // Create an import object. let import_object = imports! { "env" => { - "raw_emit_actions" => Function::new_native_with_env(&store, EmitActionEnv::new(name.clone()), raw_emit_actions), + "raw_emit_actions" => Function::new_native_with_env(&store, EmitActionEnv::new(name.clone(), ecs.clone()), raw_emit_actions), + "raw_retreive_action" => Function::new_native_with_env(&store, EmitActionEnv::new(name.clone(), ecs.clone()), raw_retreive_action), } }; @@ -67,6 +95,7 @@ impl PluginModule { let instance = Instance::new(&module, &import_object) .map_err(PluginModuleError::InstantiationError)?; Ok(Self { + ecs, events: instance .exports .iter() @@ -81,6 +110,7 @@ impl PluginModule { // None if the event doesn't exists pub fn try_execute( &self, + ecs: &World, event_name: &str, request: &PreparedEventQuery, ) -> Option> @@ -90,6 +120,7 @@ impl PluginModule { if !self.events.contains(event_name) { return None; } + self.ecs.store((&ecs) as *const _ as i32, std::sync::atomic::Ordering::SeqCst); let bytes = { let mut state = self.wasm_state.lock().unwrap(); match execute_raw(&mut state, event_name, &request.bytes) { @@ -97,6 +128,7 @@ impl PluginModule { Err(e) => return Some(Err(e)), } }; + self.ecs.store(i32::MAX, std::sync::atomic::Ordering::SeqCst); Some(bincode::deserialize(&bytes).map_err(PluginModuleError::Encoding)) } } @@ -105,13 +137,15 @@ impl PluginModule { /// emit_action function is called #[derive(Clone)] struct EmitActionEnv { + ecs: Arc, memory: LazyInit, name: String, } impl EmitActionEnv { - fn new(name: String) -> Self { + fn new(name: String,ecs: Arc) -> Self { Self { + ecs, memory: LazyInit::new(), name, } diff --git a/common/sys/src/state.rs b/common/sys/src/state.rs index e60b63d2aa..22bded5950 100644 --- a/common/sys/src/state.rs +++ b/common/sys/src/state.rs @@ -209,7 +209,7 @@ impl State { ecs.insert(match PluginMgr::from_assets() { Ok(plugin_mgr) => { if let Err(e) = plugin_mgr - .execute_event("on_load", &plugin_api::event::PluginLoadEvent { game_mode }) + .execute_event(&ecs,"on_load", &plugin_api::event::PluginLoadEvent { game_mode }) { tracing::error!(?e, "Failed to run plugin init"); tracing::info!( diff --git a/plugin/api/src/lib.rs b/plugin/api/src/lib.rs index 3974b53f3a..bb094c73e9 100644 --- a/plugin/api/src/lib.rs +++ b/plugin/api/src/lib.rs @@ -9,6 +9,11 @@ pub enum Action { KillEntity(Uid), } +#[derive(Deserialize, Serialize, Debug)] +pub enum Retreive { + GetEntityName(Uid), +} + pub trait Event: Serialize + DeserializeOwned + Send + Sync { type Response: Serialize + DeserializeOwned + Send + Sync; } diff --git a/plugin/rt/examples/hello.rs b/plugin/rt/examples/hello.rs index 2de3c512ed..2f596f1a02 100644 --- a/plugin/rt/examples/hello.rs +++ b/plugin/rt/examples/hello.rs @@ -20,6 +20,8 @@ pub fn on_command_testplugin(command: ChatCommandEvent) -> Result, S )]) } + + #[event_handler] pub fn on_player_join(input: PlayerJoinEvent) -> PlayerJoinResult { emit_action(Action::PlayerSendMessage( diff --git a/plugin/rt/src/lib.rs b/plugin/rt/src/lib.rs index f0e962524b..f9ac93dc58 100644 --- a/plugin/rt/src/lib.rs +++ b/plugin/rt/src/lib.rs @@ -2,6 +2,10 @@ pub extern crate plugin_derive; +pub mod retreive; + +pub use retreive::*; + pub use plugin_api as api; pub use plugin_derive::*; @@ -10,6 +14,21 @@ use serde::{de::DeserializeOwned, Serialize}; #[cfg(target_arch = "wasm32")] extern "C" { fn raw_emit_actions(ptr: *const u8, len: usize); + fn raw_retreive_action(ptr: *const u8, len: usize) -> (i32, u32); +} + +pub fn retreive_action(_actions: &api::Retreive) -> Result { + #[cfg(target_arch = "wasm32")] + { + let ret = bincode::serialize(&actions).expect("Can't serialize action in emit"); + unsafe { + let (ptr,len) = raw_retreive_action(ret.as_ptr(), ret.len()); + let a = ::std::slice::from_raw_parts(ptr as _, len as _); + bincode::deserialize(&a) + } + } + #[cfg(not(target_arch = "wasm32"))] + unreachable!() } pub fn emit_action(action: api::Action) { emit_actions(vec![action]) } diff --git a/plugin/rt/src/retreive.rs b/plugin/rt/src/retreive.rs new file mode 100644 index 0000000000..049f32e999 --- /dev/null +++ b/plugin/rt/src/retreive.rs @@ -0,0 +1,12 @@ +use crate::api::Retreive; + +trait GetEntityName { + fn get_entity_name(&self) -> String; +} + +impl GetEntityName for crate::api::event::Player { + + fn get_entity_name(&self) -> String { + crate::retreive_action(&Retreive::GetEntityName(self.id)).expect("Can't get entity name") + } +} \ No newline at end of file diff --git a/server/src/lib.rs b/server/src/lib.rs index da261fab5c..2f4d792e72 100644 --- a/server/src/lib.rs +++ b/server/src/lib.rs @@ -1031,6 +1031,7 @@ impl Server { use common::uid::Uid; let plugin_manager = self.state.ecs().read_resource::(); let rs = plugin_manager.execute_event( + self.state.ecs(), &format!("on_command_{}", &kwd), &plugin_api::event::ChatCommandEvent { command: kwd.clone(),