use std::{
any::TypeId,
collections::HashMap,
marker::PhantomData,
ops::{Deref, DerefMut},
};
use atomic_refcell::{AtomicRef, AtomicRefMut};
use crate::{
entity::{Allocator, Entity, LiveBitSet, WrongGeneration},
fetch_resources::FetchResources,
join::{Index, IntoJoin},
masked::{GuardedJoin, ModifiedJoin, ModifiedJoinMut},
resource_set::ResourceSet,
resources::{ResourceConflict, RwResources},
storage::DenseStorage,
tracked::{ModifiedBitSet, TrackedStorage},
world_common::{Component, ComponentId, ComponentStorage, ResourceId, WorldResourceId},
};
#[derive(Default)]
pub struct World {
allocator: Allocator,
resources: ResourceSet,
components: ResourceSet,
remove_components: HashMap<TypeId, Box<dyn Fn(&ResourceSet, &[Entity]) + Send + Sync>>,
killed: Vec<Entity>,
}
impl World {
pub fn new() -> Self {
World {
allocator: Allocator::new(),
resources: ResourceSet::new(),
components: ResourceSet::new(),
remove_components: HashMap::new(),
killed: Vec::new(),
}
}
pub fn entities(&self) -> Entities {
Entities(&self.allocator)
}
pub fn create_entity(&mut self) -> Entity {
self.allocator.allocate()
}
pub fn delete_entity(&mut self, e: Entity) -> Result<(), WrongGeneration> {
self.allocator.kill(e)?;
for remove_component in self.remove_components.values() {
remove_component(&self.components, &[e]);
}
Ok(())
}
pub fn insert_resource<R>(&mut self, r: R) -> Option<R>
where
R: Send + 'static,
{
self.resources.insert(r)
}
pub fn remove_resource<R>(&mut self) -> Option<R>
where
R: Send + 'static,
{
self.resources.remove::<R>()
}
pub fn contains_resource<T>(&self) -> bool
where
T: Send + 'static,
{
self.resources.contains::<T>()
}
pub fn read_resource<R>(&self) -> ReadResource<R>
where
R: Send + Sync + 'static,
{
ResourceAccess(self.resources.borrow())
}
pub fn write_resource<R>(&self) -> WriteResource<R>
where
R: Send + 'static,
{
ResourceAccess(self.resources.borrow_mut())
}
pub fn get_resource_mut<R>(&mut self) -> &mut R
where
R: Send + 'static,
{
self.resources.get_mut()
}
pub fn insert_component<C>(&mut self) -> Option<ComponentStorage<C>>
where
C: Component + 'static,
C::Storage: Default + Send,
{
self.remove_components.insert(
TypeId::of::<C>(),
Box::new(|resource_set, entities| {
let mut storage = resource_set.borrow_mut::<ComponentStorage<C>>();
for e in entities {
storage.remove(e.index());
}
}),
);
self.components.insert(ComponentStorage::<C>::default())
}
pub fn remove_component<C>(&mut self) -> Option<ComponentStorage<C>>
where
C: Component + 'static,
C::Storage: Default + Send,
{
self.remove_components.remove(&TypeId::of::<C>());
self.components.remove::<ComponentStorage<C>>()
}
pub fn contains_component<C>(&self) -> bool
where
C: Component + 'static,
C::Storage: Send,
{
self.components.contains::<ComponentStorage<C>>()
}
pub fn read_component<C>(&self) -> ReadComponent<C>
where
C: Component + 'static,
C::Storage: Send + Sync,
{
ComponentAccess {
storage: self.components.borrow(),
entities: self.entities(),
marker: PhantomData,
}
}
pub fn write_component<C>(&self) -> WriteComponent<C>
where
C: Component + 'static,
C::Storage: Send,
{
ComponentAccess {
storage: self.components.borrow_mut(),
entities: self.entities(),
marker: PhantomData,
}
}
pub fn get_component_mut<C>(&mut self) -> ComponentAccess<C, &mut ComponentStorage<C>>
where
C: Component + 'static,
C::Storage: Send,
{
ComponentAccess {
storage: self.components.get_mut(),
entities: Entities(&self.allocator),
marker: PhantomData,
}
}
pub fn fetch<'a, F>(&'a self) -> F
where
F: FetchResources<'a, Source = World, Resources = RwResources<WorldResourceId>>,
{
F::fetch(self)
}
pub fn merge(&mut self) {
self.allocator.merge_atomic(&mut self.killed);
for remove_component in self.remove_components.values() {
remove_component(&self.components, &self.killed);
}
}
}
pub struct Entities<'a>(&'a Allocator);
impl<'a> Entities<'a> {
pub fn delete(&self, e: Entity) -> Result<(), WrongGeneration> {
self.0.kill_atomic(e)
}
pub fn is_alive(&self, e: Entity) -> bool {
self.0.is_alive(e)
}
pub fn entity(&self, index: Index) -> Option<Entity> {
self.0.entity(index)
}
pub fn create(&self) -> Entity {
self.0.allocate_atomic()
}
pub fn live_bitset(&self) -> LiveBitSet {
self.0.live_bitset()
}
}
impl<'a> IntoJoin for &'a Entities<'a> {
type Item = Entity;
type IntoJoin = &'a Allocator;
fn into_join(self) -> Self::IntoJoin {
&*self.0
}
}
impl<'a> FetchResources<'a> for Entities<'a> {
type Source = World;
type Resources = RwResources<WorldResourceId>;
fn check_resources() -> Result<RwResources<WorldResourceId>, ResourceConflict> {
Ok(RwResources::new().read(WorldResourceId::Entities))
}
fn fetch(world: &'a World) -> Self {
world.entities()
}
}
pub struct ResourceAccess<R>(R);
impl<R> Deref for ResourceAccess<R>
where
R: Deref,
{
type Target = R::Target;
fn deref(&self) -> &R::Target {
&*self.0
}
}
impl<R> DerefMut for ResourceAccess<R>
where
R: DerefMut,
{
fn deref_mut(&mut self) -> &mut R::Target {
&mut *self.0
}
}
pub type ReadResource<'a, R> = ResourceAccess<AtomicRef<'a, R>>;
impl<'a, R> FetchResources<'a> for ReadResource<'a, R>
where
R: Send + Sync + 'static,
{
type Source = World;
type Resources = RwResources<WorldResourceId>;
fn check_resources() -> Result<RwResources<WorldResourceId>, ResourceConflict> {
Ok(RwResources::new().read(WorldResourceId::Resource(ResourceId::of::<R>())))
}
fn fetch(world: &'a World) -> Self {
world.read_resource()
}
}
pub type WriteResource<'a, R> = ResourceAccess<AtomicRefMut<'a, R>>;
impl<'a, R> FetchResources<'a> for WriteResource<'a, R>
where
R: Send + 'static,
{
type Source = World;
type Resources = RwResources<WorldResourceId>;
fn check_resources() -> Result<RwResources<WorldResourceId>, ResourceConflict> {
Ok(RwResources::new().write(WorldResourceId::Resource(ResourceId::of::<R>())))
}
fn fetch(world: &'a World) -> Self {
world.write_resource()
}
}
pub struct ComponentAccess<'a, C, R>
where
C: Component,
{
entities: Entities<'a>,
storage: R,
marker: PhantomData<C>,
}
impl<'a, C, R> ComponentAccess<'a, C, R>
where
C: Component,
R: Deref<Target = ComponentStorage<C>>,
{
pub fn entities(&self) -> &Entities {
&self.entities
}
pub fn storage(&self) -> &ComponentStorage<C> {
&self.storage
}
pub fn contains(&self, e: Entity) -> bool {
self.entities.is_alive(e) && self.storage.contains(e.index())
}
pub fn get(&self, e: Entity) -> Option<&C> {
if self.entities.is_alive(e) {
self.storage.get(e.index())
} else {
None
}
}
}
impl<'a, C, R> ComponentAccess<'a, C, R>
where
C: Component,
R: DerefMut<Target = ComponentStorage<C>>,
{
pub fn storage_mut(&mut self) -> &mut ComponentStorage<C> {
&mut self.storage
}
pub fn get_mut(&mut self, e: Entity) -> Option<&mut C> {
if self.entities.is_alive(e) {
self.storage.get_mut(e.index())
} else {
None
}
}
pub fn get_or_insert_with(
&mut self,
e: Entity,
f: impl FnOnce() -> C,
) -> Result<&mut C, WrongGeneration> {
if self.entities.is_alive(e) {
Ok(self.storage.get_or_insert_with(e.index(), f))
} else {
Err(WrongGeneration)
}
}
pub fn insert(&mut self, e: Entity, c: C) -> Result<Option<C>, WrongGeneration> {
if self.entities.is_alive(e) {
Ok(self.storage.insert(e.index(), c))
} else {
Err(WrongGeneration)
}
}
pub fn update(&mut self, e: Entity, c: C) -> Result<Option<C>, WrongGeneration>
where
C: PartialEq,
{
if self.entities.is_alive(e) {
Ok(self.storage.update(e.index(), c))
} else {
Err(WrongGeneration)
}
}
pub fn remove(&mut self, e: Entity) -> Result<Option<C>, WrongGeneration> {
if self.entities.is_alive(e) {
Ok(self.storage.remove(e.index()))
} else {
Err(WrongGeneration)
}
}
pub fn guard(&mut self) -> GuardedJoin<C::Storage> {
self.storage.guard()
}
}
impl<'a, C, R> ComponentAccess<'a, C, R>
where
C: Component,
C::Storage: DenseStorage,
R: Deref<Target = ComponentStorage<C>>,
{
pub fn as_slice(&self) -> &[C] {
self.storage.as_slice()
}
}
impl<'a, C, R> ComponentAccess<'a, C, R>
where
C: Component,
C::Storage: TrackedStorage,
R: Deref<Target = ComponentStorage<C>>,
{
pub fn tracking_modified(&self) -> bool {
self.storage.tracking_modified()
}
pub fn modified_indexes(&self) -> &ModifiedBitSet {
self.storage.modified_indexes()
}
pub fn mark_modified(&self, entity: Entity) -> Result<(), WrongGeneration> {
if self.entities.is_alive(entity) {
self.storage.mark_modified(entity.index());
Ok(())
} else {
Err(WrongGeneration)
}
}
pub fn modified(&self) -> ModifiedJoin<C::Storage> {
self.storage.modified()
}
}
impl<'a, C, R> ComponentAccess<'a, C, R>
where
C: Component,
C::Storage: DenseStorage,
R: DerefMut<Target = ComponentStorage<C>>,
{
pub fn as_mut_slice(&mut self) -> &mut [C] {
self.storage.as_mut_slice()
}
}
impl<'a, C, R> ComponentAccess<'a, C, R>
where
C: Component,
C::Storage: TrackedStorage,
R: DerefMut<Target = ComponentStorage<C>>,
{
pub fn set_track_modified(&mut self, flag: bool) {
self.storage.set_track_modified(flag);
}
pub fn clear_modified(&mut self) {
self.storage.clear_modified();
}
pub fn modified_mut(&mut self) -> ModifiedJoinMut<C::Storage> {
self.storage.modified_mut()
}
}
impl<'a, 'b, C, R> IntoJoin for &'a ComponentAccess<'b, C, R>
where
C: Component,
R: Deref<Target = ComponentStorage<C>> + 'a,
{
type Item = &'a C;
type IntoJoin = &'a ComponentStorage<C>;
fn into_join(self) -> Self::IntoJoin {
(&*self.storage).into_join()
}
}
impl<'a, 'b, C, R> IntoJoin for &'a mut ComponentAccess<'b, C, R>
where
C: Component,
R: DerefMut<Target = ComponentStorage<C>> + 'a,
{
type Item = &'a mut C;
type IntoJoin = &'a mut ComponentStorage<C>;
fn into_join(self) -> Self::IntoJoin {
(&mut *self.storage).into_join()
}
}
pub type ReadComponent<'a, C> = ComponentAccess<'a, C, AtomicRef<'a, ComponentStorage<C>>>;
impl<'a, C> FetchResources<'a> for ReadComponent<'a, C>
where
C: Component + Send + Sync + 'static,
C::Storage: Send + Sync,
{
type Source = World;
type Resources = RwResources<WorldResourceId>;
fn check_resources() -> Result<RwResources<WorldResourceId>, ResourceConflict> {
Ok(RwResources::new()
.read(WorldResourceId::Entities)
.read(WorldResourceId::Component(ComponentId::of::<C>())))
}
fn fetch(world: &'a World) -> Self {
world.read_component()
}
}
pub type WriteComponent<'a, C> = ComponentAccess<'a, C, AtomicRefMut<'a, ComponentStorage<C>>>;
impl<'a, C> FetchResources<'a> for WriteComponent<'a, C>
where
C: Component + Send + 'static,
C::Storage: Send,
{
type Source = World;
type Resources = RwResources<WorldResourceId>;
fn check_resources() -> Result<RwResources<WorldResourceId>, ResourceConflict> {
Ok(RwResources::new()
.read(WorldResourceId::Entities)
.write(WorldResourceId::Component(ComponentId::of::<C>())))
}
fn fetch(world: &'a World) -> Self {
world.write_component()
}
}