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 serde::{Deserialize, Serialize};
use specs::World;
use std::{
collections::{HashMap, HashSet},
fs,
@ -80,6 +81,7 @@ impl Plugin {
pub fn execute_prepared<T>(
&self,
ecs: &World,
event_name: &str,
event: &PreparedEventQuery<T>,
) -> Result<Vec<T::Response>, 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<T>(
&self,
ecs: &World,
event_name: &str,
event: &PreparedEventQuery<T>,
) -> Result<Vec<T::Response>, 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::<Result<Vec<_>, _>>()?
.into_iter()
.flatten()
@ -136,13 +139,14 @@ impl PluginMgr {
pub fn execute_event<T>(
&self,
ecs: &World,
event_name: &str,
event: &T,
) -> Result<Vec<T::Response>, 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<P: AsRef<Path>>(path: P) -> Result<Self, PluginError> {

View File

@ -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<AtomicI32>,
wasm_state: Arc<Mutex<WasmState>>,
events: HashSet<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.
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<T>(
&self,
ecs: &World,
event_name: &str,
request: &PreparedEventQuery<T>,
) -> Option<Result<T::Response, PluginModuleError>>
@ -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<AtomicI32>,
memory: LazyInit<Memory>,
name: String,
}
impl EmitActionEnv {
fn new(name: String) -> Self {
fn new(name: String,ecs: Arc<AtomicI32>) -> Self {
Self {
ecs,
memory: LazyInit::new(),
name,
}

View File

@ -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!(

View File

@ -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;
}

View File

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

View File

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

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;
let plugin_manager = self.state.ecs().read_resource::<PluginMgr>();
let rs = plugin_manager.execute_event(
self.state.ecs(),
&format!("on_command_{}", &kwd),
&plugin_api::event::ChatCommandEvent {
command: kwd.clone(),