mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
added basic retreive
This commit is contained in:
parent
72bd0f42fc
commit
a067a20b69
@ -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> {
|
||||
|
@ -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,
|
||||
}
|
||||
|
@ -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!(
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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(
|
||||
|
@ -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
12
plugin/rt/src/retreive.rs
Normal 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")
|
||||
}
|
||||
}
|
@ -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(),
|
||||
|
Loading…
Reference in New Issue
Block a user