use std::{ any::TypeId, collections::HashMap, time::{Duration, Instant}, }; use anyhow::{Result, bail}; use indexmap::IndexMap; use utilities::prelude::{remove_life_time, remove_life_time_mut}; use crate::{entity_object_manager::EntityObjectManager, *}; pub struct WorldBuilder { pub(crate) updates: Updates, pub events: Events, pub resources: Resources, systems: Vec Result<()> + Send + Sync + 'static>>, } impl WorldBuilder { pub fn add_system(&mut self, f: F) where F: Fn(&mut World) -> Result<()> + Send + Sync + 'static, { self.systems.push(Box::new(f)); } } impl WorldBuilder { pub fn build(self) -> World { World { updates: self.updates, events: self.events, resources: self.resources, entities: Default::default(), entities_to_remove: Default::default(), entities_to_add: Default::default(), entities_updates: Default::default(), entity_object_manager: Default::default(), start_time: Instant::now(), systems: self.systems, } } } enum ComponentChange { Added(TypeId, Box), Removed(TypeId), } pub struct World { pub(crate) updates: Updates, pub events: Events, pub resources: Resources, pub(crate) entities: IndexMap, entities_to_remove: Vec, entities_to_add: Vec, entities_updates: HashMap>, entity_object_manager: EntityObjectManager, start_time: Instant, systems: Vec Result<()> + Send + Sync + 'static>>, } impl World { pub fn builder() -> WorldBuilder { WorldBuilder { updates: Default::default(), events: Default::default(), resources: Default::default(), systems: Default::default(), } } pub fn now(&self) -> Duration { self.start_time.elapsed() } pub fn new_entity(&mut self) -> EntityObject { self.entity_object_manager.create_entity() } pub fn entities(&self) -> impl Iterator { self.entities.values() } pub fn entity( &self, entity: Entity, ) -> std::result::Result<&EntityObject, EntityNotFoundError> { self.entities .get(&entity) .ok_or_else(|| EntityNotFoundError::new(entity)) } pub unsafe fn entity_unchecked<'a>( &self, entity: Entity, ) -> std::result::Result<&'a EntityObject, EntityNotFoundError> { self.entity(entity).map(|e| unsafe { remove_life_time(e) }) } pub fn entity_mut( &mut self, entity: Entity, ) -> std::result::Result<&mut EntityObject, EntityNotFoundError> { self.entities .get_mut(&entity) .ok_or_else(|| EntityNotFoundError::new(entity)) } pub unsafe fn entity_mut_unchecked<'a>( &mut self, entity: Entity, ) -> std::result::Result<&'a mut EntityObject, EntityNotFoundError> { self.entity_mut(entity) .map(|e| unsafe { remove_life_time_mut(e) }) } pub fn entities_multi_mut(&mut self) -> EntityMultiMut<'_> { EntityMultiMut::new(&mut self.entities) } pub fn add_entity(&mut self, entity_object: EntityObject) -> Result { let entity = entity_object.as_entity(); self.entities_to_add.push(entity_object); Ok(entity) } pub fn insert_component( &mut self, entity: Entity, component: T, ) -> Result<()> { println!("insert component {}", T::debug_name()); let change = ComponentChange::Added(TypeId::of::(), Box::new(component)); match self.entities_updates.get_mut(&entity) { Some(changes) => { changes.push(change); } None => { self.entities_updates.insert(entity, vec![change]); } } Ok(()) } pub fn remove_component( &mut self, entity: Entity, ) -> Result<()> { println!("remove component {}", T::debug_name()); let change = ComponentChange::Removed(TypeId::of::()); match self.entities_updates.get_mut(&entity) { Some(changes) => { changes.push(change); } None => { self.entities_updates.insert(entity, vec![change]); } } Ok(()) } pub fn remove_entity(&mut self, entity: Entity) -> Result> { self.entities_to_remove.push(entity); Ok(None) } } // async application of changes impl World { fn _add_entity(&mut self, mut entity: EntityObject) -> Result { // call enable event for all components for (_, component) in entity.components.iter_mut() { component.enable(self)?; } entity.activation_state.apply_change(); let e = entity.as_entity(); self.updates.add_entity(&mut entity, &self.entities)?; assert!(self.entities.insert(e, entity).is_none()); Ok(e) } fn _remove_entity(&mut self, entity: Entity) -> Result> { if let Some(mut entity_object) = self.entities.swap_remove(&entity) { for (_, component) in entity_object.components.iter_mut() { component.disable(self)?; } entity_object.activation_state.apply_change(); self.updates.remove_entity(entity); return Ok(Some(entity_object)); } Ok(None) } fn _insert_component( &mut self, entity: Entity, mut component: T, ) -> Result<()> { let entities = unsafe { remove_life_time_mut(&mut self.entities) }; let entity_object = entities .get_mut(&entity) .ok_or_else(|| EntityNotFoundError::new(entity))?; self.updates.remove_entity(entity); entity_object.activation_state.apply_change(); component.enable(self)?; if entity_object.insert_component(component).is_some() { bail!("component {} already present", T::debug_name()); } entity_object.activation_state.apply_change(); self.updates.add_entity(entity_object, &self.entities)?; Ok(()) } fn _remove_component( &mut self, entity: Entity, ) -> Result<()> { let entities = unsafe { remove_life_time_mut(&mut self.entities) }; let entity_object = entities .get_mut(&entity) .ok_or_else(|| EntityNotFoundError::new(entity))?; self.updates.remove_entity(entity); entity_object.activation_state.apply_change(); if let Some(mut component) = entity_object.remove_component_by_id(TypeId::of::()) { component.disable(self)?; } entity_object.activation_state.apply_change(); self.updates.add_entity(entity_object, &self.entities)?; Ok(()) } fn commit_entity_changes(&mut self) -> Result<()> { if !self.entities_to_remove.is_empty() { println!("entities to remove {}", self.entities_to_remove.len()); } for entity in core::mem::take(&mut self.entities_to_remove) { self._remove_entity(entity)?; } if !self.entities_to_add.is_empty() { println!("entities to add {}", self.entities_to_add.len()); } for entity_object in core::mem::take(&mut self.entities_to_add) { self._add_entity(entity_object)?; } if !self.entities_updates.is_empty() { println!("entities to update {}", self.entities_updates.len()); } for (entity, changes) in core::mem::take(&mut self.entities_updates) { self.updates.remove_entity(entity); if let Some(entity_object) = unsafe { self.entity_mut_unchecked(entity).ok() } { entity_object.activation_state.apply_change(); for change in changes { match change { ComponentChange::Added(type_id, mut component) => { component.enable(self)?; let name = component.name().to_string(); if entity_object .insert_component_by_id(type_id, component) .is_some() { bail!("component {name} already present"); } } ComponentChange::Removed(type_id) => { if let Some(mut component) = entity_object.remove_component_by_id(type_id) { component.disable(self)?; } } } } entity_object.activation_state.apply_change(); self.updates.add_entity(entity_object, &self.entities)?; } } Ok(()) } } impl World { pub fn run(&mut self) -> Result<()> { let systems = std::mem::take(&mut self.systems); loop { // we need to take all events because of borrowing rules let mut events = self.events.take_events(); events.fire_events(self)?; { // actually safe: // - updates can't be altered on a running world // - entity changes are processed afterwards let w = unsafe { remove_life_time_mut(self) }; self.updates.update(w)?; } self.commit_entity_changes()?; for system in systems.iter() { system(self)?; } } } }