diff --git a/common/src/combat.rs b/common/src/combat.rs index 4bbfc9a546..882dbff97c 100644 --- a/common/src/combat.rs +++ b/common/src/combat.rs @@ -635,7 +635,7 @@ impl CombatBuff { } #[cfg(not(target_arch = "wasm32"))] -fn equipped_item_and_tool(inv: &Inventory, slot: EquipSlot) -> Option<&Tool> { +fn equipped_item_and_tool(inv: &Inventory, slot: EquipSlot) -> Option<(&Item, &Tool)> { inv.equipped(slot).and_then(|i| { if let ItemKind::Tool(tool) = &i.kind() { Some((i, tool)) diff --git a/common/src/comp/mod.rs b/common/src/comp/mod.rs index 7435de6a55..e893baaa39 100644 --- a/common/src/comp/mod.rs +++ b/common/src/comp/mod.rs @@ -76,7 +76,7 @@ pub use self::{ misc::Object, ori::Ori, phys::{ - Collider, ForceUpdate, Gravity, Mass, PhysicsState, Pos, PreviousVelDtCache, Scale, Sticky, + Collider, ForceUpdate, Gravity, Mass, PhysicsState, Pos, PreviousPhysCache, Scale, Sticky, Vel, }, player::Player, @@ -86,4 +86,6 @@ pub use self::{ skills::{Skill, SkillGroup, SkillGroupKind, SkillSet}, stats::Stats, visual::{LightAnimation, LightEmitter}, -}; \ No newline at end of file +}; + +pub use health::{Health, HealthChange, HealthSource}; diff --git a/common/sys/src/plugin/memory_manager.rs b/common/sys/src/plugin/memory_manager.rs index 5afa4bfd15..a5a0f8f6d9 100644 --- a/common/sys/src/plugin/memory_manager.rs +++ b/common/sys/src/plugin/memory_manager.rs @@ -6,7 +6,7 @@ use wasmer::{Function, Memory, Value}; use super::errors::{MemoryAllocationError, PluginModuleError}; -// This structure wraps the ECS pointer to ensure safety +/// This structure wraps the ECS pointer to ensure safety pub struct EcsAccessManager { ecs_pointer: AtomicPtr, } @@ -31,9 +31,21 @@ impl EcsAccessManager { out } - pub fn get(&self) -> Option<&World> { + /// This unsafe function returns a reference to the Ecs World + /// + /// # Safety + /// This function is safe to use if it matches the following requirements + /// - The reference and subreferences like Entities, Components ... aren't + /// leaked out the thread + /// - The reference and subreferences lifetime doesn't exceed the source + /// function lifetime + /// - Always safe when called from `retrieve_action` if you don't pass a + /// reference somewhere else + /// - All that ensure that the reference doesn't exceed the execute_with + /// function scope + pub unsafe fn get(&self) -> Option<&World> { // ptr::as_ref will automatically check for null - unsafe { self.ecs_pointer.load(Ordering::Relaxed).as_ref() } + self.ecs_pointer.load(Ordering::Relaxed).as_ref() } } @@ -52,9 +64,10 @@ impl Default for MemoryManager { } impl MemoryManager { - // This function check if the buffer is wide enough if not it realloc the buffer - // calling the `wasm_prepare_buffer` function Note: There is probably - // optimizations that can be done using less restrictive ordering + /// This function check if the buffer is wide enough if not it realloc the + /// buffer calling the `wasm_prepare_buffer` function Note: There is + /// probably optimizations that can be done using less restrictive + /// ordering pub fn get_pointer( &self, object_length: u32, @@ -74,8 +87,8 @@ impl MemoryManager { Ok(pointer) } - // This function writes an object to WASM memory returning a pointer and a - // length. Will realloc the buffer is not wide enough + /// This function writes an object to WASM memory returning a pointer and a + /// length. Will realloc the buffer is not wide enough pub fn write_data( &self, memory: &Memory, @@ -89,8 +102,8 @@ impl MemoryManager { ) } - // This function writes an raw bytes to WASM memory returning a pointer and a - // length. Will realloc the buffer is not wide enough + /// This function writes an raw bytes to WASM memory returning a pointer and + /// a length. Will realloc the buffer is not wide enough pub fn write_bytes( &self, memory: &Memory, @@ -109,8 +122,8 @@ impl MemoryManager { } } -// This function read data from memory at a position with the array length and -// converts it to an object using bincode +/// This function read data from memory at a position with the array length and +/// converts it to an object using bincode pub fn read_data( memory: &Memory, position: i32, @@ -119,7 +132,7 @@ pub fn read_data( bincode::deserialize(&read_bytes(memory, position, length)) } -// This function read raw bytes from memory at a position with the array length +/// This function read raw bytes from memory at a position with the array length pub fn read_bytes(memory: &Memory, position: i32, length: u32) -> Vec { memory.view()[(position as usize)..(position as usize) + length as usize] .iter() diff --git a/common/sys/src/plugin/module.rs b/common/sys/src/plugin/module.rs index 7d5a531a19..c8b16d613c 100644 --- a/common/sys/src/plugin/module.rs +++ b/common/sys/src/plugin/module.rs @@ -21,7 +21,7 @@ use super::{ use plugin_api::{Action, EcsAccessError, Event, Retrieve, RetrieveError, RetrieveResult}; #[derive(Clone)] -// This structure represent the WASM State of the plugin. +/// This structure represent the WASM State of the plugin. pub struct PluginModule { ecs: Arc, wasm_state: Arc>, @@ -33,7 +33,7 @@ pub struct PluginModule { } impl PluginModule { - // This function takes bytes from a WASM File and compile them + /// This function takes bytes from a WASM File and compile them pub fn new(name: String, wasm_data: &[u8]) -> Result { // This is creating the engine is this case a JIT based on Cranelift let engine = JIT::new(Cranelift::default()).engine(); @@ -107,8 +107,8 @@ impl PluginModule { }) } - // This function tries to execute an event for the current module. Will return - // None if the event doesn't exists + /// This function tries to execute an event for the current module. Will + /// return None if the event doesn't exists pub fn try_execute( &self, ecs: &World, @@ -133,16 +133,17 @@ impl PluginModule { } } -// This structure represent a Pre-encoded event object (Useful to avoid -// reencoding for each module in every plugin) +/// This structure represent a Pre-encoded event object (Useful to avoid +/// reencoding for each module in every plugin) pub struct PreparedEventQuery { bytes: Vec, _phantom: PhantomData, } impl PreparedEventQuery { - // Create a prepared query from an event reference (Encode to bytes the struct) - // This Prepared Query is used by the `try_execute` method in `PluginModule` + /// Create a prepared query from an event reference (Encode to bytes the + /// struct) This Prepared Query is used by the `try_execute` method in + /// `PluginModule` pub fn new(event: &T) -> Result where T: Event, @@ -222,9 +223,12 @@ fn retrieve_action( ) -> Result { match action { Retrieve::GetPlayerName(e) => { - let world = ecs.get().ok_or(RetrieveError::EcsAccessError( - EcsAccessError::EcsPointerNotAvailable, - ))?; + // Safety: No reference is leaked out the function so it is safe. + let world = unsafe { + ecs.get().ok_or(RetrieveError::EcsAccessError( + EcsAccessError::EcsPointerNotAvailable, + ))? + }; let player = world .read_resource::() .retrieve_entity_internal(e.0) @@ -246,9 +250,12 @@ fn retrieve_action( )) }, Retrieve::GetEntityHealth(e) => { - let world = ecs.get().ok_or(RetrieveError::EcsAccessError( - EcsAccessError::EcsPointerNotAvailable, - ))?; + // Safety: No reference is leaked out the function so it is safe. + let world = unsafe { + ecs.get().ok_or(RetrieveError::EcsAccessError( + EcsAccessError::EcsPointerNotAvailable, + ))? + }; let player = world .read_resource::() .retrieve_entity_internal(e.0) diff --git a/common/sys/src/plugin/wasm_env.rs b/common/sys/src/plugin/wasm_env.rs index c166019d13..e383f7f3d5 100644 --- a/common/sys/src/plugin/wasm_env.rs +++ b/common/sys/src/plugin/wasm_env.rs @@ -35,8 +35,8 @@ impl HostFunctionEnvironement { } } - // This function is a safe interface to WASM memory that writes data to the - // memory returning a pointer and length + /// This function is a safe interface to WASM memory that writes data to the + /// memory returning a pointer and length pub fn write_data(&self, object: &T) -> Result<(i32, u32), PluginModuleError> { self.memory_manager.write_data( self.memory.get_ref().unwrap(), @@ -45,8 +45,8 @@ impl HostFunctionEnvironement { ) } - // This function is a safe interface to WASM memory that reads memory from - // pointer and length returning an object + /// This function is a safe interface to WASM memory that reads memory from + /// pointer and length returning an object pub fn read_data( &self, position: i32, diff --git a/common/sys/src/state.rs b/common/sys/src/state.rs index 3f0bad997a..ec3a339f20 100644 --- a/common/sys/src/state.rs +++ b/common/sys/src/state.rs @@ -210,11 +210,7 @@ impl State { Ok(plugin_mgr) => { if let Err(e) = plugin_mgr.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, - }, + game_mode, }) { tracing::error!(?e, "Failed to run plugin init");