diff --git a/Cargo.lock b/Cargo.lock index cff916f047..460d77bf79 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6009,6 +6009,7 @@ name = "veloren-plugin-rt" version = "0.1.0" dependencies = [ "bincode", + "once_cell", "serde", "veloren-plugin-api", "veloren-plugin-derive", diff --git a/common/state/src/plugin/mod.rs b/common/state/src/plugin/mod.rs index 5617bf96ea..b947c0257e 100644 --- a/common/state/src/plugin/mod.rs +++ b/common/state/src/plugin/mod.rs @@ -38,34 +38,38 @@ pub struct Plugin { } impl Plugin { - pub fn from_path(path: &Path) -> Result { - if !path.is_dir() { + pub fn from_dir(directory: &Path) -> Result { + if !directory.is_dir() { return Err(PluginError::NoConfig); } - let mut toml = PathBuf::from(path); + let mut toml_path = PathBuf::from(directory); - toml.push("plugin.toml"); + toml_path.push("plugin.toml"); - let data = - toml::de::from_slice::(&std::fs::read(toml).map_err(PluginError::Io)?) + let plugin_config = + toml::de::from_slice::(&std::fs::read(toml_path).map_err(PluginError::Io)?) .map_err(PluginError::Toml)?; - let modules = data + let modules = plugin_config .modules .iter() - .map(|path1| { - let mut module_file = PathBuf::from(path); - module_file.push(path1); + .map(|module_path| { + let mut module_file = PathBuf::from(directory); + module_file.push(module_path); let wasm_data = std::fs::read(module_file).map_err(PluginError::Io)?; - PluginModule::new(data.name.to_owned(), &wasm_data).map_err(|e| { - PluginError::PluginModuleError(data.name.to_owned(), "".to_owned(), e) + PluginModule::new(plugin_config.name.to_owned(), &wasm_data).map_err(|e| { + PluginError::PluginModuleError( + plugin_config.name.to_owned(), + "".to_owned(), + e, + ) }) }) .collect::>()?; Ok(Plugin { - data, + data: plugin_config, modules, files: HashMap::new(), }) @@ -198,7 +202,7 @@ impl PluginMgr { Plugin::from_reader(fs::File::open(entry.path()).map_err(PluginError::Io)?) .map(Some) } else { - Plugin::from_path(&entry.path()).map(Some) + Plugin::from_dir(&entry.path()).map(Some) } }) .filter_map(Result::transpose) diff --git a/common/state/src/plugin/module.rs b/common/state/src/plugin/module.rs index 30680552c6..2d6315c07e 100644 --- a/common/state/src/plugin/module.rs +++ b/common/state/src/plugin/module.rs @@ -1,10 +1,5 @@ use hashbrown::HashSet; -use std::{ - borrow::Cow, - convert::TryInto, - marker::PhantomData, - sync::{Arc, RwLock}, -}; +use std::{borrow::Cow, convert::TryInto, marker::PhantomData, sync::Arc}; use specs::saveload::MarkerAllocator; use wasmer::{imports, Cranelift, Function, Instance, Memory, Module, Store, Value, JIT}; @@ -24,7 +19,7 @@ use plugin_api::{ /// This structure represent the WASM State of the plugin. pub struct PluginModule { ecs: Arc, - wasm_state: Arc>, + wasm_state: Instance, memory_manager: Arc, events: HashSet, allocator: Function, @@ -109,7 +104,7 @@ impl PluginModule { .iter() .map(|(name, _)| name.to_string()) .collect(), - wasm_state: Arc::new(RwLock::new(instance)), + wasm_state: instance, name, }) } @@ -129,8 +124,12 @@ impl PluginModule { } // Store the ECS Pointer for later use in `retreives` let bytes = match self.ecs.execute_with(ecs, || { - let state = self.wasm_state.read().unwrap(); - execute_raw(self, &state, &request.function_name, &request.bytes) + execute_raw( + self, + &self.wasm_state, + &request.function_name, + &request.bytes, + ) }) { Ok(e) => e, Err(e) => return Some(Err(e)), diff --git a/plugin/rt/Cargo.toml b/plugin/rt/Cargo.toml index bf45accc12..52d14afc8a 100644 --- a/plugin/rt/Cargo.toml +++ b/plugin/rt/Cargo.toml @@ -9,6 +9,7 @@ plugin-api = { package = "veloren-plugin-api", path = "../api" } plugin-derive = { package = "veloren-plugin-derive", path = "../derive"} serde = {version = "1.0.118", features = ["derive"]} bincode = "1.3.1" +once_cell = "1.7.2" [[example]] name = "hello" diff --git a/plugin/rt/src/lib.rs b/plugin/rt/src/lib.rs index 3afc94444e..dc2e730727 100644 --- a/plugin/rt/src/lib.rs +++ b/plugin/rt/src/lib.rs @@ -8,8 +8,11 @@ use std::{ borrow::{Cow, ToOwned}, convert::TryInto, marker::PhantomData, + sync::Mutex, }; +use once_cell::sync::Lazy; + pub fn __game() -> api::Game { api::Game::__new(|_| todo!()) } #[cfg(target_arch = "wasm32")] @@ -72,7 +75,9 @@ where let slice = unsafe { ::std::slice::from_raw_parts(from_i64(ptr) as _, from_i64(len) as _) }; let output = bincode::deserialize(slice).map_err(|_| "Failed to deserialize function input"); // We free the allocated buffer if it exists. - if let Some((a, b)) = BUFFERS + if let Some((a, _)) = BUFFERS + .lock() + .unwrap() .iter_mut() .find(|(a, b)| !*a && b.as_ptr() as u64 == from_i64(ptr)) { @@ -120,14 +125,15 @@ pub fn write_output(value: impl Serialize) -> i64 { // Synchronisation safety is handled by the bool which enforces the Buffer to be // used once at a time so no problem (is_free_to_use, data) -static mut BUFFERS: Vec<(bool, Vec)> = Vec::new(); +static BUFFERS: Lazy)>>> = Lazy::new(|| Mutex::new(Vec::new())); /// Allocate buffer from wasm linear memory /// # Safety /// This function should never be used only intented to by used by the host #[no_mangle] -pub unsafe fn wasm_prepare_buffer(size: i32) -> i64 { - if let Some((a, x)) = BUFFERS.iter_mut().find(|(x, _)| *x) { +pub fn wasm_prepare_buffer(size: i32) -> i64 { + let mut buf = BUFFERS.lock().unwrap(); + if let Some((a, x)) = buf.iter_mut().find(|(x, _)| *x) { *a = false; if x.len() < size as usize { *x = vec![0u8; size as usize]; @@ -136,7 +142,7 @@ pub unsafe fn wasm_prepare_buffer(size: i32) -> i64 { } else { let vec = vec![0u8; size as usize]; let ptr = vec.as_ptr() as i64; - BUFFERS.push((false, vec)); + buf.push((false, vec)); ptr } }