use std::collections::{HashMap, VecDeque}; use crate::{archetype::{ArchetypeId, Archetype}, bundle::Bundle, component::Component, query::{ViewIter, View, DefaultQuery}}; #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] pub struct EntityId(pub u64); /// The id of the entity for the Archetype. /// The Archetype struct uses this as the index in the component columns #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] pub struct ArchetypeEntityId(pub u64); #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] pub struct Entity { id: EntityId, generation: u64, } pub struct Record { id: ArchetypeId, index: ArchetypeEntityId, } pub struct World { pub(crate) archetypes: HashMap, next_archetype_id: ArchetypeId, entity_index: HashMap, dead_entities: VecDeque, next_entity_id: EntityId, } impl World { pub fn new() -> Self { Self { archetypes: HashMap::new(), next_archetype_id: ArchetypeId(0), entity_index: HashMap::new(), dead_entities: VecDeque::new(), next_entity_id: EntityId(0), } } fn get_new_entity(&mut self) -> Entity { match self.dead_entities.pop_front() { Some(e) => e, None => { let new_id = self.next_entity_id; self.next_entity_id.0 += 1; Entity { id: new_id, generation: 0, } } } } pub fn spawn(&mut self, bundle: B) -> Entity where B: Bundle { let bundle_types = bundle.type_ids(); let new_entity = self.get_new_entity(); // try to find an archetype let archetype = self.archetypes .values_mut() .find(|a| a.is_archetype_for(bundle_types.clone())); if let Some(archetype) = archetype { let arche_idx = archetype.add_entity(new_entity, bundle); // Create entity record and store it let record = Record { id: archetype.id, index: arche_idx, }; self.entity_index.insert(new_entity.id, record); } // create a new archetype if one isn't found else { // create archetype let new_arch_id = self.next_archetype_id.increment(); let mut archetype = Archetype::from_bundle_info(new_arch_id, bundle.info()); let entity_arch_id = archetype.add_entity(new_entity, bundle); // store archetype self.archetypes.insert(new_arch_id, archetype); // Create entity record and store it let record = Record { id: new_arch_id, // this is the first entity in the archetype index: entity_arch_id, }; self.entity_index.insert(new_entity.id, record); } new_entity } pub fn view<'a, T: 'static + Component + DefaultQuery>(&'a self) -> ViewIter<'a, T::Query> { let archetypes = self.archetypes.values().collect(); let v = View::new(T::default_query(), archetypes); v.into_iter() } } #[cfg(test)] mod tests { use crate::tests::Vec2; use super::World; #[test] fn spawning_entity() { let mut world = World::new(); let _e = world.spawn((Vec2 { x: 10.0, y: 15.0, }, )); } #[test] fn world_view_entities() { let mut world = World::new(); world.spawn((Vec2 { x: 10.0, y: 15.0, }, )); world.spawn((Vec2 { x: 152.0, y: 3585.0, }, )); world.spawn((Vec2 { x: 235.0, y: 734.0, }, )); let mut count = 0; for pos in world.view::<&Vec2>() { println!("Found entity at {:?}", pos); count += 1; } assert!(count == 3); } }