mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Fixed the plugin compilation and added comments
TODO: Remove compilation errors on WASM side (while using common).
This commit is contained in:
parent
8a693d9fde
commit
1597fcc79e
1
Cargo.lock
generated
1
Cargo.lock
generated
@ -5699,7 +5699,6 @@ name = "veloren-plugin-api"
|
|||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"serde",
|
"serde",
|
||||||
"veloren-common",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
BIN
assets/plugins/plugin1.plugin.tar
(Stored with Git LFS)
Normal file
BIN
assets/plugins/plugin1.plugin.tar
(Stored with Git LFS)
Normal file
Binary file not shown.
@ -1,4 +1,4 @@
|
|||||||
use std::{collections::HashSet, marker::PhantomData, sync::{Arc, Mutex, atomic::AtomicI32}};
|
use std::{collections::HashSet, convert::TryInto, marker::PhantomData, sync::{Arc, Mutex, atomic::AtomicI32}};
|
||||||
|
|
||||||
use specs::World;
|
use specs::World;
|
||||||
use wasmer::{
|
use wasmer::{
|
||||||
@ -85,6 +85,7 @@ impl PluginModule {
|
|||||||
if !self.events.contains(event_name) {
|
if !self.events.contains(event_name) {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
// Store the ECS Pointer for later use in `retreives`
|
||||||
self.ecs.store((&ecs) as *const _ as i32, std::sync::atomic::Ordering::SeqCst);
|
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();
|
||||||
@ -93,6 +94,7 @@ impl PluginModule {
|
|||||||
Err(e) => return Some(Err(e)),
|
Err(e) => return Some(Err(e)),
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
// Remove the ECS Pointer to avoid UB
|
||||||
self.ecs.store(i32::MAX, std::sync::atomic::Ordering::SeqCst);
|
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))
|
||||||
}
|
}
|
||||||
@ -120,6 +122,11 @@ impl<T: Event> PreparedEventQuery<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn from_i64(i: i64) -> (i32,i32) {
|
||||||
|
let i = i.to_le_bytes();
|
||||||
|
(i32::from_le_bytes(i[0..4].try_into().unwrap()),i32::from_le_bytes(i[4..8].try_into().unwrap()))
|
||||||
|
}
|
||||||
|
|
||||||
// This function is not public because this function should not be used without
|
// This function is not public because this function should not be used without
|
||||||
// an interface to limit unsafe behaviours
|
// an interface to limit unsafe behaviours
|
||||||
#[allow(clippy::needless_range_loop)]
|
#[allow(clippy::needless_range_loop)]
|
||||||
@ -129,25 +136,33 @@ fn execute_raw(
|
|||||||
event_name: &str,
|
event_name: &str,
|
||||||
bytes: &[u8],
|
bytes: &[u8],
|
||||||
) -> Result<Vec<u8>, PluginModuleError> {
|
) -> Result<Vec<u8>, PluginModuleError> {
|
||||||
|
|
||||||
|
// This write into memory `bytes` using allocation if necessary returning a pointer and a length
|
||||||
|
|
||||||
let (mem_position,len) = module.memory_manager.write_bytes(&module.memory, &module.allocator, bytes)?;
|
let (mem_position,len) = module.memory_manager.write_bytes(&module.memory, &module.allocator, bytes)?;
|
||||||
|
|
||||||
|
// This gets the event function from module exports
|
||||||
|
|
||||||
let func = instance
|
let func = instance
|
||||||
.exports
|
.exports
|
||||||
.get_function(event_name)
|
.get_function(event_name)
|
||||||
.map_err(PluginModuleError::MemoryUninit)?;
|
.map_err(PluginModuleError::MemoryUninit)?;
|
||||||
|
|
||||||
|
// We call the function with the pointer and the length
|
||||||
|
|
||||||
let function_result = func
|
let function_result = func
|
||||||
.call(&[Value::I32(mem_position as i32), Value::I32(len as i32)])
|
.call(&[Value::I32(mem_position as i32), Value::I32(len as i32)])
|
||||||
.map_err(PluginModuleError::RunFunction)?;
|
.map_err(PluginModuleError::RunFunction)?;
|
||||||
|
|
||||||
let pointer = function_result[0]
|
// Waiting for `multi-value` to be added to LLVM. So we encode the two i32 as an i64
|
||||||
.i32()
|
|
||||||
.ok_or_else(PluginModuleError::InvalidArgumentType)?;
|
|
||||||
let length = function_result[1]
|
|
||||||
.i32()
|
|
||||||
.ok_or_else(PluginModuleError::InvalidArgumentType)? as u32;
|
|
||||||
|
|
||||||
Ok(memory_manager::read_bytes(&module.memory, pointer, length))
|
let (pointer,length) = from_i64(function_result[0]
|
||||||
|
.i64()
|
||||||
|
.ok_or_else(PluginModuleError::InvalidArgumentType)?);
|
||||||
|
|
||||||
|
// We read the return object and deserialize it
|
||||||
|
|
||||||
|
Ok(memory_manager::read_bytes(&module.memory, pointer, length as u32))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_actions(actions: Vec<Action>) {
|
fn handle_actions(actions: Vec<Action>) {
|
||||||
|
@ -209,7 +209,11 @@ 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(&ecs,"on_load", &plugin_api::event::PluginLoadEvent { game_mode })
|
.execute_event(&ecs,"on_load", &plugin_api::event::PluginLoadEvent { game_mode: match game_mode {
|
||||||
|
resources::GameMode::Server => plugin_api::GameMode::Server,
|
||||||
|
resources::GameMode::Client => plugin_api::GameMode::Client,
|
||||||
|
resources::GameMode::Singleplayer => plugin_api::GameMode::Singleplayer,
|
||||||
|
} })
|
||||||
{
|
{
|
||||||
tracing::error!(?e, "Failed to run plugin init");
|
tracing::error!(?e, "Failed to run plugin init");
|
||||||
tracing::info!(
|
tracing::info!(
|
||||||
|
@ -5,5 +5,4 @@ authors = ["ccgauche <gaucheron.laurent@gmail.com>"]
|
|||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
common = { package = "veloren-common", path = "../../common", features = ["no-assets"] }
|
|
||||||
serde = { version = "1.0.118", features = ["derive"] }
|
serde = { version = "1.0.118", features = ["derive"] }
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
use common::uid::Uid;
|
|
||||||
|
use std::fmt;
|
||||||
|
|
||||||
use serde::{de::DeserializeOwned, Deserialize, Serialize};
|
use serde::{de::DeserializeOwned, Deserialize, Serialize};
|
||||||
|
|
||||||
#[derive(Deserialize, Serialize, Debug)]
|
#[derive(Deserialize, Serialize, Debug)]
|
||||||
@ -18,7 +20,34 @@ pub trait Event: Serialize + DeserializeOwned + Send + Sync {
|
|||||||
type Response: Serialize + DeserializeOwned + Send + Sync;
|
type Response: Serialize + DeserializeOwned + Send + Sync;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub use common::resources::GameMode;
|
#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)]
|
||||||
|
pub struct Uid(pub u64);
|
||||||
|
|
||||||
|
impl Into<u64> for Uid {
|
||||||
|
fn into(self) -> u64 { self.0 }
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<u64> for Uid {
|
||||||
|
fn from(uid: u64) -> Self { Self(uid) }
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for Uid {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{}", self.0) }
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
|
||||||
|
pub enum GameMode {
|
||||||
|
/// The game is being played in server mode (i.e: the code is running
|
||||||
|
/// server-side)
|
||||||
|
Server,
|
||||||
|
/// The game is being played in client mode (i.e: the code is running
|
||||||
|
/// client-side)
|
||||||
|
Client,
|
||||||
|
/// The game is being played in singleplayer mode (i.e: both client and
|
||||||
|
/// server at once)
|
||||||
|
// To be used later when we no longer start up an entirely new server for singleplayer
|
||||||
|
Singleplayer,
|
||||||
|
}
|
||||||
|
|
||||||
pub mod event {
|
pub mod event {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
@ -16,8 +16,8 @@ pub fn event_handler(_args: TokenStream, item: TokenStream) -> TokenStream {
|
|||||||
let out: proc_macro2::TokenStream = quote! {
|
let out: proc_macro2::TokenStream = quote! {
|
||||||
#[allow(clippy::unnecessary_wraps)]
|
#[allow(clippy::unnecessary_wraps)]
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub fn #fn_name(intern__ptr: i32, intern__len: u32) -> (i32,i32) {
|
pub fn #fn_name(intern__ptr: i32, intern__len: i32) -> i64 {
|
||||||
let input = ::veloren_plugin_rt::read_input(intern__ptr,intern__len).unwrap();
|
let input = ::veloren_plugin_rt::read_input(intern__ptr,intern__len as u32).unwrap();
|
||||||
#[inline]
|
#[inline]
|
||||||
fn inner(#fn_args) #fn_return {
|
fn inner(#fn_args) #fn_return {
|
||||||
#fn_body
|
#fn_body
|
||||||
|
@ -4,6 +4,8 @@ pub extern crate plugin_derive;
|
|||||||
|
|
||||||
pub mod retreive;
|
pub mod retreive;
|
||||||
|
|
||||||
|
use std::convert::TryInto;
|
||||||
|
|
||||||
pub use retreive::*;
|
pub use retreive::*;
|
||||||
|
|
||||||
pub use plugin_api as api;
|
pub use plugin_api as api;
|
||||||
@ -14,22 +16,22 @@ 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);
|
//fn raw_retreive_action(ptr: *const u8, len: usize) -> (i32, u32);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn retreive_action<T: DeserializeOwned>(_actions: &api::Retreive) -> Result<T,bincode::Error> {
|
// pub fn retreive_action<T: DeserializeOwned>(_actions: &api::Retreive) -> Result<T,bincode::Error> {
|
||||||
#[cfg(target_arch = "wasm32")]
|
// #[cfg(target_arch = "wasm32")]
|
||||||
{
|
// {
|
||||||
let ret = bincode::serialize(&actions).expect("Can't serialize action in emit");
|
// let ret = bincode::serialize(&_actions).expect("Can't serialize action in emit");
|
||||||
unsafe {
|
// unsafe {
|
||||||
let (ptr,len) = raw_retreive_action(ret.as_ptr(), ret.len());
|
// let (ptr,len) = raw_retreive_action(ret.as_ptr(), ret.len());
|
||||||
let a = ::std::slice::from_raw_parts(ptr as _, len as _);
|
// let a = ::std::slice::from_raw_parts(ptr as _, len as _);
|
||||||
bincode::deserialize(&a)
|
// bincode::deserialize(&a)
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
// #[cfg(not(target_arch = "wasm32"))]
|
||||||
unreachable!()
|
// unreachable!()
|
||||||
}
|
// }
|
||||||
|
|
||||||
pub fn emit_action(action: api::Action) { emit_actions(vec![action]) }
|
pub fn emit_action(action: api::Action) { emit_actions(vec![action]) }
|
||||||
|
|
||||||
@ -51,9 +53,15 @@ where
|
|||||||
bincode::deserialize(slice).map_err(|_| "Failed to deserialize function input")
|
bincode::deserialize(slice).map_err(|_| "Failed to deserialize function input")
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn write_output(value: impl Serialize) -> (i32,i32) {
|
pub fn to_i64(a: i32, b: i32) -> i64 {
|
||||||
|
let a = a.to_le_bytes();
|
||||||
|
let b = b.to_le_bytes();
|
||||||
|
i64::from_le_bytes([a[0],a[1],a[2],a[3],b[0],b[1],b[2],b[3]])
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn write_output(value: impl Serialize) -> i64 {
|
||||||
let ret = bincode::serialize(&value).expect("Can't serialize event output");
|
let ret = bincode::serialize(&value).expect("Can't serialize event output");
|
||||||
(ret.as_ptr() as _, ret.len() as _)
|
to_i64(ret.as_ptr() as _, ret.len() as _)
|
||||||
}
|
}
|
||||||
|
|
||||||
static mut BUFFERS: Vec<u8> = Vec::new();
|
static mut BUFFERS: Vec<u8> = Vec::new();
|
||||||
|
@ -7,6 +7,7 @@ trait GetEntityName {
|
|||||||
impl GetEntityName for crate::api::event::Player {
|
impl GetEntityName for crate::api::event::Player {
|
||||||
|
|
||||||
fn get_entity_name(&self) -> String {
|
fn get_entity_name(&self) -> String {
|
||||||
crate::retreive_action(&Retreive::GetEntityName(self.id)).expect("Can't get entity name")
|
// crate::retreive_action(&Retreive::GetEntityName(self.id)).expect("Can't get entity name")
|
||||||
|
String::new()
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1037,12 +1037,12 @@ impl Server {
|
|||||||
command: kwd.clone(),
|
command: kwd.clone(),
|
||||||
command_args: args.split(' ').map(|x| x.to_owned()).collect(),
|
command_args: args.split(' ').map(|x| x.to_owned()).collect(),
|
||||||
player: plugin_api::event::Player {
|
player: plugin_api::event::Player {
|
||||||
id: *(self
|
id: plugin_api::Uid((self
|
||||||
.state
|
.state
|
||||||
.ecs()
|
.ecs()
|
||||||
.read_storage::<Uid>()
|
.read_storage::<Uid>()
|
||||||
.get(entity)
|
.get(entity)
|
||||||
.expect("Can't get player UUID [This should never appen]")),
|
.expect("Can't get player UUID [This should never appen]")).0),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
Loading…
Reference in New Issue
Block a user