use super::{
comp::Component,
entity::{Allocator, EntitiesRes, Entity},
CreateIter, EntityBuilder, LazyUpdate,
};
use crate::{
error::WrongGeneration,
storage::{AnyStorage, MaskedStorage},
ReadStorage, WriteStorage,
};
use shred::{Fetch, FetchMut, MetaTable, Read, Resource, SystemData, World};
pub trait WorldExt {
fn new() -> Self;
fn register<T: Component>(&mut self)
where
T::Storage: Default;
fn register_with_storage<F, T>(&mut self, storage: F)
where
F: FnOnce() -> T::Storage,
T: Component;
#[deprecated(since = "0.15.0", note = "use `World::insert` instead")]
fn add_resource<T: Resource>(&mut self, res: T);
fn read_component<T: Component>(&self) -> ReadStorage<T>;
fn write_component<T: Component>(&self) -> WriteStorage<T>;
fn read_storage<T: Component>(&self) -> ReadStorage<T> {
self.read_component()
}
fn write_storage<T: Component>(&self) -> WriteStorage<T> {
self.write_component()
}
fn read_resource<T: Resource>(&self) -> Fetch<T>;
fn write_resource<T: Resource>(&self) -> FetchMut<T>;
fn entities(&self) -> Read<EntitiesRes>;
fn entities_mut(&self) -> FetchMut<EntitiesRes>;
fn create_entity(&mut self) -> EntityBuilder;
fn create_entity_unchecked(&self) -> EntityBuilder;
fn create_iter(&mut self) -> CreateIter;
fn delete_entity(&mut self, entity: Entity) -> Result<(), WrongGeneration>;
fn delete_entities(&mut self, delete: &[Entity]) -> Result<(), (WrongGeneration, usize)>;
fn delete_all(&mut self);
fn is_alive(&self, e: Entity) -> bool;
fn maintain(&mut self);
#[doc(hidden)]
fn delete_components(&mut self, delete: &[Entity]);
}
impl WorldExt for World {
fn new() -> Self {
let mut world = Self::default();
world.insert(EntitiesRes::default());
world.insert(MetaTable::<dyn AnyStorage>::default());
world.insert(LazyUpdate::default());
world
}
fn register<T: Component>(&mut self)
where
T::Storage: Default,
{
self.register_with_storage::<_, T>(Default::default);
}
fn register_with_storage<F, T>(&mut self, storage: F)
where
F: FnOnce() -> T::Storage,
T: Component,
{
self.entry()
.or_insert_with(move || MaskedStorage::<T>::new(storage()));
self.fetch_mut::<MetaTable<dyn AnyStorage>>()
.register::<MaskedStorage<T>>();
}
fn add_resource<T: Resource>(&mut self, res: T) {
self.insert(res);
}
fn read_component<T: Component>(&self) -> ReadStorage<T> {
self.system_data()
}
fn write_component<T: Component>(&self) -> WriteStorage<T> {
self.system_data()
}
fn read_resource<T: Resource>(&self) -> Fetch<T> {
self.fetch()
}
fn write_resource<T: Resource>(&self) -> FetchMut<T> {
self.fetch_mut()
}
fn entities(&self) -> Read<EntitiesRes> {
Read::fetch(self)
}
fn entities_mut(&self) -> FetchMut<EntitiesRes> {
self.write_resource()
}
fn create_entity(&mut self) -> EntityBuilder {
self.create_entity_unchecked()
}
fn create_entity_unchecked(&self) -> EntityBuilder {
let entity = self.entities_mut().alloc.allocate();
EntityBuilder {
entity,
world: self,
built: false,
}
}
fn create_iter(&mut self) -> CreateIter {
CreateIter(self.entities_mut())
}
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, 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) {
use crate::join::Join;
let entities: Vec<_> = self.entities().join().collect();
self.delete_entities(&entities).expect(
"Bug: previously collected entities are not valid \
even though access should be exclusive",
);
}
fn is_alive(&self, e: Entity) -> bool {
assert!(e.gen().is_alive(), "Generation is dead");
let alloc: &Allocator = &self.entities().alloc;
alloc.generation(e.id()) == Some(e.gen())
}
fn maintain(&mut self) {
let deleted = self.entities_mut().alloc.merge();
if !deleted.is_empty() {
self.delete_components(&deleted);
}
let lazy = self.write_resource::<LazyUpdate>().clone();
lazy.maintain(self);
}
fn delete_components(&mut self, delete: &[Entity]) {
for mut storage in self.fetch_mut::<MetaTable<dyn AnyStorage>>().iter_mut(self) {
(*storage).drop(delete);
}
}
}