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:
@ -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> {
|
||||||
|
@ -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,
|
||||||
}
|
}
|
||||||
|
@ -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!(
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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(
|
||||||
|
@ -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
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;
|
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(),
|
||||||
|
Reference in New Issue
Block a user