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"
|
||||
dependencies = [
|
||||
"serde",
|
||||
"veloren-common",
|
||||
]
|
||||
|
||||
[[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 wasmer::{
|
||||
@ -85,6 +85,7 @@ impl PluginModule {
|
||||
if !self.events.contains(event_name) {
|
||||
return None;
|
||||
}
|
||||
// Store the ECS Pointer for later use in `retreives`
|
||||
self.ecs.store((&ecs) as *const _ as i32, std::sync::atomic::Ordering::SeqCst);
|
||||
let bytes = {
|
||||
let mut state = self.wasm_state.lock().unwrap();
|
||||
@ -93,6 +94,7 @@ impl PluginModule {
|
||||
Err(e) => return Some(Err(e)),
|
||||
}
|
||||
};
|
||||
// Remove the ECS Pointer to avoid UB
|
||||
self.ecs.store(i32::MAX, std::sync::atomic::Ordering::SeqCst);
|
||||
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
|
||||
// an interface to limit unsafe behaviours
|
||||
#[allow(clippy::needless_range_loop)]
|
||||
@ -129,25 +136,33 @@ fn execute_raw(
|
||||
event_name: &str,
|
||||
bytes: &[u8],
|
||||
) -> 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)?;
|
||||
|
||||
// This gets the event function from module exports
|
||||
|
||||
let func = instance
|
||||
.exports
|
||||
.get_function(event_name)
|
||||
.map_err(PluginModuleError::MemoryUninit)?;
|
||||
|
||||
// We call the function with the pointer and the length
|
||||
|
||||
let function_result = func
|
||||
.call(&[Value::I32(mem_position as i32), Value::I32(len as i32)])
|
||||
.map_err(PluginModuleError::RunFunction)?;
|
||||
|
||||
let pointer = function_result[0]
|
||||
.i32()
|
||||
.ok_or_else(PluginModuleError::InvalidArgumentType)?;
|
||||
let length = function_result[1]
|
||||
.i32()
|
||||
.ok_or_else(PluginModuleError::InvalidArgumentType)? as u32;
|
||||
|
||||
// Waiting for `multi-value` to be added to LLVM. So we encode the two i32 as an i64
|
||||
|
||||
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>) {
|
||||
|
@ -209,7 +209,11 @@ impl State {
|
||||
ecs.insert(match PluginMgr::from_assets() {
|
||||
Ok(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::info!(
|
||||
|
@ -5,5 +5,4 @@ authors = ["ccgauche <gaucheron.laurent@gmail.com>"]
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
common = { package = "veloren-common", path = "../../common", features = ["no-assets"] }
|
||||
serde = { version = "1.0.118", features = ["derive"] }
|
||||
|
@ -1,4 +1,6 @@
|
||||
use common::uid::Uid;
|
||||
|
||||
use std::fmt;
|
||||
|
||||
use serde::{de::DeserializeOwned, Deserialize, Serialize};
|
||||
|
||||
#[derive(Deserialize, Serialize, Debug)]
|
||||
@ -18,7 +20,34 @@ pub trait Event: 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 {
|
||||
use super::*;
|
||||
|
@ -16,8 +16,8 @@ pub fn event_handler(_args: TokenStream, item: TokenStream) -> TokenStream {
|
||||
let out: proc_macro2::TokenStream = quote! {
|
||||
#[allow(clippy::unnecessary_wraps)]
|
||||
#[no_mangle]
|
||||
pub fn #fn_name(intern__ptr: i32, intern__len: u32) -> (i32,i32) {
|
||||
let input = ::veloren_plugin_rt::read_input(intern__ptr,intern__len).unwrap();
|
||||
pub fn #fn_name(intern__ptr: i32, intern__len: i32) -> i64 {
|
||||
let input = ::veloren_plugin_rt::read_input(intern__ptr,intern__len as u32).unwrap();
|
||||
#[inline]
|
||||
fn inner(#fn_args) #fn_return {
|
||||
#fn_body
|
||||
|
@ -4,6 +4,8 @@ pub extern crate plugin_derive;
|
||||
|
||||
pub mod retreive;
|
||||
|
||||
use std::convert::TryInto;
|
||||
|
||||
pub use retreive::*;
|
||||
|
||||
pub use plugin_api as api;
|
||||
@ -14,22 +16,22 @@ 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);
|
||||
//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 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]) }
|
||||
|
||||
@ -51,9 +53,15 @@ where
|
||||
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");
|
||||
(ret.as_ptr() as _, ret.len() as _)
|
||||
to_i64(ret.as_ptr() as _, ret.len() as _)
|
||||
}
|
||||
|
||||
static mut BUFFERS: Vec<u8> = Vec::new();
|
||||
|
@ -7,6 +7,7 @@ trait GetEntityName {
|
||||
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")
|
||||
// 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_args: args.split(' ').map(|x| x.to_owned()).collect(),
|
||||
player: plugin_api::event::Player {
|
||||
id: *(self
|
||||
id: plugin_api::Uid((self
|
||||
.state
|
||||
.ecs()
|
||||
.read_storage::<Uid>()
|
||||
.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