diff --git a/common/src/link.rs b/common/src/link.rs index 2575be4973..10dfe44d0f 100644 --- a/common/src/link.rs +++ b/common/src/link.rs @@ -6,13 +6,13 @@ pub trait Link: Sized + Send + Sync + 'static { type Error; type CreateData<'a>: SystemData<'a>; - fn create(this: &LinkHandle, data: Self::CreateData<'_>) -> Result<(), Self::Error>; + fn create(this: &LinkHandle, data: &mut Self::CreateData<'_>) -> Result<(), Self::Error>; type PersistData<'a>: SystemData<'a>; - fn persist(this: &LinkHandle, data: Self::PersistData<'_>) -> bool; + fn persist(this: &LinkHandle, data: &mut Self::PersistData<'_>) -> bool; type DeleteData<'a>: SystemData<'a>; - fn delete(this: &LinkHandle, data: Self::DeleteData<'_>); + fn delete(this: &LinkHandle, data: &mut Self::DeleteData<'_>); } pub trait Role { @@ -27,7 +27,9 @@ pub struct Is { } impl Is { - pub fn delete(&self, data: ::DeleteData<'_>) { Link::delete(&self.link, data) } + pub fn delete(&self, data: &mut ::DeleteData<'_>) { + Link::delete(&self.link, data) + } } impl Clone for Is { diff --git a/common/src/mounting.rs b/common/src/mounting.rs index e9184185da..2230b41059 100644 --- a/common/src/mounting.rs +++ b/common/src/mounting.rs @@ -67,7 +67,7 @@ impl Link for Mounting { fn create( this: &LinkHandle, - (uid_allocator, mut is_mounts, mut is_riders, is_volume_rider): Self::CreateData<'_>, + (uid_allocator, is_mounts, is_riders, is_volume_rider): &mut Self::CreateData<'_>, ) -> Result<(), Self::Error> { let entity = |uid: Uid| uid_allocator.retrieve_entity_internal(uid.into()); @@ -94,7 +94,7 @@ impl Link for Mounting { fn persist( this: &LinkHandle, - (uid_allocator, entities, healths, bodies, is_mounts, is_riders, character_states): Self::PersistData<'_>, + (uid_allocator, entities, healths, bodies, is_mounts, is_riders, character_states): &mut Self::PersistData<'_>, ) -> bool { let entity = |uid: Uid| uid_allocator.retrieve_entity_internal(uid.into()); @@ -123,7 +123,7 @@ impl Link for Mounting { fn delete( this: &LinkHandle, - (uid_allocator, mut is_mounts, mut is_riders, mut positions, mut force_update, terrain): Self::DeleteData<'_>, + (uid_allocator, is_mounts, is_riders, positions, force_update, terrain): &mut Self::DeleteData<'_>, ) { let entity = |uid: Uid| uid_allocator.retrieve_entity_internal(uid.into()); @@ -311,14 +311,14 @@ impl Link for VolumeMounting { fn create( this: &LinkHandle, ( - mut terrain_riders, - mut volume_riders, - mut is_volume_riders, + terrain_riders, + volume_riders, + is_volume_riders, is_riders, terrain_grid, uid_allocator, colliders, - ): Self::CreateData<'_>, + ): &mut Self::CreateData<'_>, ) -> Result<(), Self::Error> { let entity = |uid: Uid| uid_allocator.retrieve_entity_internal(uid.into()); @@ -337,7 +337,7 @@ impl Link for VolumeMounting { { let block = this .pos - .get_block(&terrain_grid, &uid_allocator, &colliders) + .get_block(terrain_grid, uid_allocator, colliders) .ok_or(MountingError::NoSuchEntity)?; if block == this.block { @@ -363,7 +363,7 @@ impl Link for VolumeMounting { terrain_grid, uid_allocator, colliders, - ): Self::PersistData<'_>, + ): &mut Self::PersistData<'_>, ) -> bool { let entity = |uid: Uid| uid_allocator.retrieve_entity_internal(uid.into()); let is_alive = @@ -387,7 +387,7 @@ impl Link for VolumeMounting { let block_exists = this .pos - .get_block(&terrain_grid, &uid_allocator, &colliders) + .get_block(terrain_grid, uid_allocator, colliders) .map_or(false, |block| block == this.block); rider_exists && mount_spot_exists && block_exists @@ -395,12 +395,12 @@ impl Link for VolumeMounting { fn delete( this: &LinkHandle, - (mut terrain_riders, mut volume_riders, mut is_rider, uid_allocator): Self::DeleteData<'_>, + (terrain_riders, volume_riders, is_rider, uid_allocator): &mut Self::DeleteData<'_>, ) { let entity = |uid: Uid| uid_allocator.retrieve_entity_internal(uid.into()); let riders = match this.pos.kind { - Volume::Terrain => Some(&mut *terrain_riders), + Volume::Terrain => Some(&mut **terrain_riders), Volume::Entity(uid) => { entity(uid).and_then(|entity| volume_riders.get_mut_or_default(entity)) }, diff --git a/server/src/state_ext.rs b/server/src/state_ext.rs index 8cce24a2c3..83100eca1e 100644 --- a/server/src/state_ext.rs +++ b/server/src/state_ext.rs @@ -1074,7 +1074,7 @@ impl StateExt for State { fn link(&mut self, link: L) -> Result<(), L::Error> { let linker = LinkHandle::from_link(link); - L::create(&linker, self.ecs().system_data())?; + L::create(&linker, &mut self.ecs().system_data())?; self.ecs_mut() .entry::>>() @@ -1087,11 +1087,18 @@ impl StateExt for State { fn maintain_links(&mut self) { fn maintain_link(state: &State) { if let Some(mut handles) = state.ecs().try_fetch_mut::>>() { + let mut persist_data = None; handles.retain(|link| { - if L::persist(link, state.ecs().system_data()) { + if L::persist( + link, + persist_data.get_or_insert_with(|| state.ecs().system_data()), + ) { true } else { - L::delete(link, state.ecs().system_data()); + // Make sure to drop persist data before running deletion to avoid potential + // access violations + persist_data.take(); + L::delete(link, &mut state.ecs().system_data()); false } });