added basic retreive

This commit is contained in:
ccgauche
2021-02-15 17:38:55 +01:00
committed by Marcel Märtens
parent 72bd0f42fc
commit a067a20b69
8 changed files with 89 additions and 12 deletions

View File

@ -3,6 +3,7 @@ pub mod module;
use common::assets::ASSETS_PATH; use common::assets::ASSETS_PATH;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use specs::World;
use std::{ use std::{
collections::{HashMap, HashSet}, collections::{HashMap, HashSet},
fs, fs,
@ -80,6 +81,7 @@ impl Plugin {
pub fn execute_prepared<T>( pub fn execute_prepared<T>(
&self, &self,
ecs: &World,
event_name: &str, event_name: &str,
event: &PreparedEventQuery<T>, event: &PreparedEventQuery<T>,
) -> Result<Vec<T::Response>, PluginError> ) -> Result<Vec<T::Response>, PluginError>
@ -89,7 +91,7 @@ impl Plugin {
self.modules self.modules
.iter() .iter()
.flat_map(|module| { .flat_map(|module| {
module.try_execute(event_name, event).map(|x| { module.try_execute(ecs, event_name, event).map(|x| {
x.map_err(|e| { x.map_err(|e| {
PluginError::PluginModuleError( PluginError::PluginModuleError(
self.data.name.to_owned(), self.data.name.to_owned(),
@ -118,6 +120,7 @@ impl PluginMgr {
pub fn execute_prepared<T>( pub fn execute_prepared<T>(
&self, &self,
ecs: &World,
event_name: &str, event_name: &str,
event: &PreparedEventQuery<T>, event: &PreparedEventQuery<T>,
) -> Result<Vec<T::Response>, PluginError> ) -> Result<Vec<T::Response>, PluginError>
@ -127,7 +130,7 @@ impl PluginMgr {
Ok(self Ok(self
.plugins .plugins
.par_iter() .par_iter()
.map(|plugin| plugin.execute_prepared(event_name, event)) .map(|plugin| plugin.execute_prepared(ecs, event_name, event))
.collect::<Result<Vec<_>, _>>()? .collect::<Result<Vec<_>, _>>()?
.into_iter() .into_iter()
.flatten() .flatten()
@ -136,13 +139,14 @@ impl PluginMgr {
pub fn execute_event<T>( pub fn execute_event<T>(
&self, &self,
ecs: &World,
event_name: &str, event_name: &str,
event: &T, event: &T,
) -> Result<Vec<T::Response>, PluginError> ) -> Result<Vec<T::Response>, PluginError>
where where
T: Event, T: Event,
{ {
self.execute_prepared(event_name, &PreparedEventQuery::new(event)?) self.execute_prepared(ecs, event_name, &PreparedEventQuery::new(event)?)
} }
pub fn from_dir<P: AsRef<Path>>(path: P) -> Result<Self, PluginError> { pub fn from_dir<P: AsRef<Path>>(path: P) -> Result<Self, PluginError> {

View File

@ -1,10 +1,6 @@
use std::{ use std::{cell::{Cell, RefCell}, cmp::Ordering, collections::HashSet, marker::PhantomData, rc::Rc, sync::{self, Arc, Mutex, atomic::AtomicI32}};
cell::Cell,
collections::HashSet,
marker::PhantomData,
sync::{Arc, Mutex},
};
use specs::World;
use wasmer::{ use wasmer::{
imports, Cranelift, Function, HostEnvInitError, Instance, LazyInit, Memory, MemoryView, Module, imports, Cranelift, Function, HostEnvInitError, Instance, LazyInit, Memory, MemoryView, Module,
Store, Value, WasmerEnv, JIT, Store, Value, WasmerEnv, JIT,
@ -17,6 +13,7 @@ use plugin_api::{Action, Event};
#[derive(Clone)] #[derive(Clone)]
// This structure represent the WASM State of the plugin. // This structure represent the WASM State of the plugin.
pub struct PluginModule { pub struct PluginModule {
ecs: Arc<AtomicI32>,
wasm_state: Arc<Mutex<WasmState>>, wasm_state: Arc<Mutex<WasmState>>,
events: HashSet<String>, events: HashSet<String>,
name: String, 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<u8> = memory.view();
let str_slice = &memory[ptr as usize..(ptr + len) as usize];
let bytes: Vec<u8> = 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. // Create an import object.
let import_object = imports! { let import_object = imports! {
"env" => { "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) let instance = Instance::new(&module, &import_object)
.map_err(PluginModuleError::InstantiationError)?; .map_err(PluginModuleError::InstantiationError)?;
Ok(Self { Ok(Self {
ecs,
events: instance events: instance
.exports .exports
.iter() .iter()
@ -81,6 +110,7 @@ impl PluginModule {
// None if the event doesn't exists // None if the event doesn't exists
pub fn try_execute<T>( pub fn try_execute<T>(
&self, &self,
ecs: &World,
event_name: &str, event_name: &str,
request: &PreparedEventQuery<T>, request: &PreparedEventQuery<T>,
) -> Option<Result<T::Response, PluginModuleError>> ) -> Option<Result<T::Response, PluginModuleError>>
@ -90,6 +120,7 @@ impl PluginModule {
if !self.events.contains(event_name) { if !self.events.contains(event_name) {
return None; return None;
} }
self.ecs.store((&ecs) as *const _ as i32, std::sync::atomic::Ordering::SeqCst);
let bytes = { let bytes = {
let mut state = self.wasm_state.lock().unwrap(); let mut state = self.wasm_state.lock().unwrap();
match execute_raw(&mut state, event_name, &request.bytes) { match execute_raw(&mut state, event_name, &request.bytes) {
@ -97,6 +128,7 @@ impl PluginModule {
Err(e) => return Some(Err(e)), Err(e) => return Some(Err(e)),
} }
}; };
self.ecs.store(i32::MAX, std::sync::atomic::Ordering::SeqCst);
Some(bincode::deserialize(&bytes).map_err(PluginModuleError::Encoding)) Some(bincode::deserialize(&bytes).map_err(PluginModuleError::Encoding))
} }
} }
@ -105,13 +137,15 @@ impl PluginModule {
/// emit_action function is called /// emit_action function is called
#[derive(Clone)] #[derive(Clone)]
struct EmitActionEnv { struct EmitActionEnv {
ecs: Arc<AtomicI32>,
memory: LazyInit<Memory>, memory: LazyInit<Memory>,
name: String, name: String,
} }
impl EmitActionEnv { impl EmitActionEnv {
fn new(name: String) -> Self { fn new(name: String,ecs: Arc<AtomicI32>) -> Self {
Self { Self {
ecs,
memory: LazyInit::new(), memory: LazyInit::new(),
name, name,
} }

View File

@ -209,7 +209,7 @@ impl State {
ecs.insert(match PluginMgr::from_assets() { ecs.insert(match PluginMgr::from_assets() {
Ok(plugin_mgr) => { Ok(plugin_mgr) => {
if let Err(e) = 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::error!(?e, "Failed to run plugin init");
tracing::info!( tracing::info!(

View File

@ -9,6 +9,11 @@ pub enum Action {
KillEntity(Uid), KillEntity(Uid),
} }
#[derive(Deserialize, Serialize, Debug)]
pub enum Retreive {
GetEntityName(Uid),
}
pub trait Event: Serialize + DeserializeOwned + Send + Sync { pub trait Event: Serialize + DeserializeOwned + Send + Sync {
type Response: Serialize + DeserializeOwned + Send + Sync; type Response: Serialize + DeserializeOwned + Send + Sync;
} }

View File

@ -20,6 +20,8 @@ pub fn on_command_testplugin(command: ChatCommandEvent) -> Result<Vec<String>, S
)]) )])
} }
#[event_handler] #[event_handler]
pub fn on_player_join(input: PlayerJoinEvent) -> PlayerJoinResult { pub fn on_player_join(input: PlayerJoinEvent) -> PlayerJoinResult {
emit_action(Action::PlayerSendMessage( emit_action(Action::PlayerSendMessage(

View File

@ -2,6 +2,10 @@
pub extern crate plugin_derive; pub extern crate plugin_derive;
pub mod retreive;
pub use retreive::*;
pub use plugin_api as api; pub use plugin_api as api;
pub use plugin_derive::*; pub use plugin_derive::*;
@ -10,6 +14,21 @@ use serde::{de::DeserializeOwned, Serialize};
#[cfg(target_arch = "wasm32")] #[cfg(target_arch = "wasm32")]
extern "C" { extern "C" {
fn raw_emit_actions(ptr: *const u8, len: usize); fn raw_emit_actions(ptr: *const u8, len: usize);
fn raw_retreive_action(ptr: *const u8, len: usize) -> (i32, u32);
}
pub fn retreive_action<T: DeserializeOwned>(_actions: &api::Retreive) -> Result<T,bincode::Error> {
#[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]) } pub fn emit_action(action: api::Action) { emit_actions(vec![action]) }

12
plugin/rt/src/retreive.rs Normal file
View File

@ -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")
}
}

View File

@ -1031,6 +1031,7 @@ impl Server {
use common::uid::Uid; use common::uid::Uid;
let plugin_manager = self.state.ecs().read_resource::<PluginMgr>(); let plugin_manager = self.state.ecs().read_resource::<PluginMgr>();
let rs = plugin_manager.execute_event( let rs = plugin_manager.execute_event(
self.state.ecs(),
&format!("on_command_{}", &kwd), &format!("on_command_{}", &kwd),
&plugin_api::event::ChatCommandEvent { &plugin_api::event::ChatCommandEvent {
command: kwd.clone(), command: kwd.clone(),