Avoid re-fetching system data on every link persist

This commit is contained in:
Joshua Barretto 2023-05-13 12:31:19 +01:00
parent 451e586aac
commit ec5e3fe716
3 changed files with 28 additions and 19 deletions

View File

@ -6,13 +6,13 @@ pub trait Link: Sized + Send + Sync + 'static {
type Error;
type CreateData<'a>: SystemData<'a>;
fn create(this: &LinkHandle<Self>, data: Self::CreateData<'_>) -> Result<(), Self::Error>;
fn create(this: &LinkHandle<Self>, data: &mut Self::CreateData<'_>) -> Result<(), Self::Error>;
type PersistData<'a>: SystemData<'a>;
fn persist(this: &LinkHandle<Self>, data: Self::PersistData<'_>) -> bool;
fn persist(this: &LinkHandle<Self>, data: &mut Self::PersistData<'_>) -> bool;
type DeleteData<'a>: SystemData<'a>;
fn delete(this: &LinkHandle<Self>, data: Self::DeleteData<'_>);
fn delete(this: &LinkHandle<Self>, data: &mut Self::DeleteData<'_>);
}
pub trait Role {
@ -27,7 +27,9 @@ pub struct Is<R: Role> {
}
impl<R: Role> Is<R> {
pub fn delete(&self, data: <R::Link as Link>::DeleteData<'_>) { Link::delete(&self.link, data) }
pub fn delete(&self, data: &mut <R::Link as Link>::DeleteData<'_>) {
Link::delete(&self.link, data)
}
}
impl<R: Role> Clone for Is<R> {

View File

@ -67,7 +67,7 @@ impl Link for Mounting {
fn create(
this: &LinkHandle<Self>,
(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<Self>,
(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<Self>,
(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<Self>,
(
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<Self>,
(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))
},

View File

@ -1074,7 +1074,7 @@ impl StateExt for State {
fn link<L: 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::<Vec<LinkHandle<L>>>()
@ -1087,11 +1087,18 @@ impl StateExt for State {
fn maintain_links(&mut self) {
fn maintain_link<L: Link>(state: &State) {
if let Some(mut handles) = state.ecs().try_fetch_mut::<Vec<LinkHandle<L>>>() {
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
}
});