diff --git a/src/world/entity.rs b/src/world/entity.rs index 2c18cc09f..03ea8d388 100644 --- a/src/world/entity.rs +++ b/src/world/entity.rs @@ -60,12 +60,16 @@ pub(crate) struct Allocator { impl Allocator { /// Kills a list of entities immediately. - pub fn kill(&mut self, delete: &[Entity]) -> Result<(), WrongGeneration> { - for &entity in delete { + /// + /// If an entity with an outdated generation is encountered, the index of + /// that entity within the provided slice is returned (entities after this + /// index are not killed). + pub fn kill(&mut self, delete: &[Entity]) -> Result<(), (WrongGeneration, usize)> { + for (index, &entity) in delete.iter().enumerate() { let id = entity.id() as usize; if !self.is_alive(entity) { - return self.del_err(entity); + return Err((self.del_err(entity), index)); } self.alive.remove(entity.id()); @@ -89,7 +93,7 @@ impl Allocator { /// maintained). pub fn kill_atomic(&self, e: Entity) -> Result<(), WrongGeneration> { if !self.is_alive(e) { - return self.del_err(e); + return Err(self.del_err(e)); } self.killed.add_atomic(e.id()); @@ -97,14 +101,14 @@ impl Allocator { Ok(()) } - pub(crate) fn del_err(&self, e: Entity) -> Result<(), WrongGeneration> { - Err(WrongGeneration { + pub(crate) fn del_err(&self, e: Entity) -> WrongGeneration { + WrongGeneration { action: "delete", actual_gen: self.generations[e.id() as usize] .0 .unwrap_or_else(Generation::one), entity: e, - }) + } } /// Return `true` if the entity is alive. diff --git a/src/world/world_ext.rs b/src/world/world_ext.rs index 49f667734..2d11ac73e 100644 --- a/src/world/world_ext.rs +++ b/src/world/world_ext.rs @@ -259,7 +259,11 @@ pub trait WorldExt { fn delete_entity(&mut self, entity: Entity) -> Result<(), WrongGeneration>; /// Deletes the specified entities and their components. - fn delete_entities(&mut self, delete: &[Entity]) -> Result<(), WrongGeneration>; + /// + /// If an entity with an outdated generation is encountered, the index of + /// that entity within the provided slice is returned (entities after this + /// index are not deleted). + fn delete_entities(&mut self, delete: &[Entity]) -> Result<(), (WrongGeneration, usize)>; /// Deletes all entities and their components. fn delete_all(&mut self); @@ -315,8 +319,6 @@ impl WorldExt for World { { self.entry() .or_insert_with(move || MaskedStorage::::new(storage())); - self.entry::>() - .or_insert_with(Default::default); self.fetch_mut::>() .register(&*self.fetch::>()); } @@ -369,12 +371,18 @@ impl WorldExt for World { fn delete_entity(&mut self, entity: Entity) -> Result<(), WrongGeneration> { self.delete_entities(&[entity]) + .map_err(|(wrong_gen, _)| wrong_gen) } - fn delete_entities(&mut self, delete: &[Entity]) -> Result<(), WrongGeneration> { - self.delete_components(delete); - - self.entities_mut().alloc.kill(delete) + fn delete_entities(&mut self, delete: &[Entity]) -> Result<(), (WrongGeneration, usize)> { + let res = self.entities_mut().alloc.kill(delete); + if let Err((wrong_gen, failed_index)) = res { + self.delete_components(&delete[..failed_index]); + Err((wrong_gen, failed_index)) + } else { + self.delete_components(delete); + Ok(()) + } } fn delete_all(&mut self) { @@ -406,8 +414,6 @@ impl WorldExt for World { } fn delete_components(&mut self, delete: &[Entity]) { - self.entry::>() - .or_insert_with(Default::default); for storage in self.fetch_mut::>().iter_mut(self) { storage.drop(delete); }