diff options
Diffstat (limited to 'ecs/src/component/storage.rs')
-rw-r--r-- | ecs/src/component/storage.rs | 194 |
1 files changed, 137 insertions, 57 deletions
diff --git a/ecs/src/component/storage.rs b/ecs/src/component/storage.rs index 44addb7..2bd3826 100644 --- a/ecs/src/component/storage.rs +++ b/ecs/src/component/storage.rs @@ -96,8 +96,11 @@ impl Storage ) .expect("Archetype is gone"); - archetype.components.push( - components + let entity_uid = EntityUid::new_unique(); + + archetype.entities.push(ArchetypeEntity { + uid: entity_uid, + components: components .into_iter() .map(|component| EntityComponent { id: component.id(), @@ -105,13 +108,11 @@ impl Storage component: Lock::new(component), }) .collect(), - ); - - let entity_uid = EntityUid::new_unique(); + }); archetype .entity_lookup - .insert(entity_uid, archetype.components.len() - 1); + .insert(entity_uid, archetype.entities.len() - 1); (archetype_id, entity_uid) } @@ -180,7 +181,7 @@ pub struct Archetype { component_ids: HashMap<ComponentId, usize>, entity_lookup: HashMap<EntityUid, usize>, - pub components: Vec<Vec<EntityComponent>>, + entities: Vec<ArchetypeEntity>, } impl Archetype @@ -194,7 +195,7 @@ impl Archetype .map(|(index, component_id)| (component_id, index)) .collect(), entity_lookup: HashMap::new(), - components: Vec::new(), + entities: Vec::new(), } } @@ -212,11 +213,16 @@ impl Archetype } } - pub fn get_entity(&self, entity_uid: EntityUid) -> Option<&[EntityComponent]> + pub fn get_entity(&self, entity_uid: EntityUid) -> Option<&ArchetypeEntity> { let entity_index = *self.entity_lookup.get(&entity_uid)?; - Some(&self.components.get(entity_index)?) + self.entities.get(entity_index) + } + + pub fn entities(&self) -> EntityIter<'_> + { + EntityIter { iter: self.entities.iter() } } pub fn get_index_for_component(&self, component_id: &ComponentId) -> Option<usize> @@ -226,6 +232,31 @@ impl Archetype } #[derive(Debug)] +pub struct ArchetypeEntity +{ + uid: EntityUid, + components: Vec<EntityComponent>, +} + +impl ArchetypeEntity +{ + pub fn uid(&self) -> EntityUid + { + self.uid + } + + pub fn components(&self) -> &[EntityComponent] + { + &self.components + } + + pub fn get_component(&self, index: usize) -> Option<&EntityComponent> + { + self.components.get(index) + } +} + +#[derive(Debug)] pub struct ArchetypeRefIter<'component_storage> { inner: SliceIter<'component_storage, usize>, @@ -256,6 +287,22 @@ impl<'component_storage> Iterator for ArchetypeRefIter<'component_storage> } } +#[derive(Debug)] +pub struct EntityIter<'archetype> +{ + iter: SliceIter<'archetype, ArchetypeEntity>, +} + +impl<'archetype> Iterator for EntityIter<'archetype> +{ + type Item = &'archetype ArchetypeEntity; + + fn next(&mut self) -> Option<Self::Item> + { + self.iter.next() + } +} + #[cfg(test)] mod tests { @@ -265,6 +312,7 @@ mod tests use super::{Archetype, Storage}; use crate::archetype::Id as ArchetypeId; + use crate::component::storage::ArchetypeEntity; use crate::component::{ Id as ComponentId, IsOptional as ComponentIsOptional, @@ -321,14 +369,14 @@ mod tests assert_eq!(archetype.component_ids.len(), 2); // One entity - assert_eq!(archetype.components.len(), 1); + assert_eq!(archetype.entities.len(), 1); let entity_components = archetype - .components + .entities .first() .expect("Expected a entity in archetype"); - assert_eq!(entity_components.len(), 2); + assert_eq!(entity_components.components.len(), 2); assert_eq!(component_storage.archetype_lookup.len(), 1); @@ -362,6 +410,10 @@ mod tests { let mut component_storage = Storage::default(); + let entity_uid_a = EntityUid::new_unique(); + let entity_uid_b = EntityUid::new_unique(); + let entity_uid_c = EntityUid::new_unique(); + component_storage.archetypes.push(Archetype { component_ids: HashMap::from([ (ComponentId::of::<IronBoots>(), 0), @@ -369,29 +421,45 @@ mod tests (ComponentId::of::<Hookshot>(), 2), ]), entity_lookup: HashMap::from([ - (EntityUid::new_unique(), 0), - (EntityUid::new_unique(), 1), - (EntityUid::new_unique(), 2), + (entity_uid_a, 0), + (entity_uid_b, 1), + (entity_uid_c, 2), ]), - components: vec![ - vec![EntityComponent { - id: ComponentId::of::<IronBoots>(), - name: "Iron boots", - component: Lock::new(Box::new(IronBoots)), - }], - vec![EntityComponent { - id: ComponentId::of::<HealthPotion>(), - name: "Health potion", - component: Lock::new(Box::new(HealthPotion { _hp_restoration: 20 })), - }], - vec![EntityComponent { - id: ComponentId::of::<Hookshot>(), - name: "Hookshot", - component: Lock::new(Box::new(Hookshot { _range: 67 })), - }], + entities: vec![ + ArchetypeEntity { + uid: entity_uid_a, + components: vec![EntityComponent { + id: ComponentId::of::<IronBoots>(), + name: "Iron boots", + component: Lock::new(Box::new(IronBoots)), + }], + }, + ArchetypeEntity { + uid: entity_uid_b, + components: vec![EntityComponent { + id: ComponentId::of::<HealthPotion>(), + name: "Health potion", + component: Lock::new(Box::new(HealthPotion { + _hp_restoration: 20, + })), + }], + }, + ArchetypeEntity { + uid: entity_uid_c, + components: vec![EntityComponent { + id: ComponentId::of::<Hookshot>(), + name: "Hookshot", + component: Lock::new(Box::new(Hookshot { _range: 67 })), + }], + }, ], }); + let entity_uid_d = EntityUid::new_unique(); + let entity_uid_e = EntityUid::new_unique(); + let entity_uid_f = EntityUid::new_unique(); + let entity_uid_g = EntityUid::new_unique(); + component_storage.archetypes.push(Archetype { component_ids: HashMap::from([ (ComponentId::of::<DekuNut>(), 0), @@ -400,32 +468,44 @@ mod tests (ComponentId::of::<Hookshot>(), 3), ]), entity_lookup: HashMap::from([ - (EntityUid::new_unique(), 0), - (EntityUid::new_unique(), 1), - (EntityUid::new_unique(), 2), - (EntityUid::new_unique(), 3), + (entity_uid_d, 0), + (entity_uid_e, 1), + (entity_uid_f, 2), + (entity_uid_g, 3), ]), - components: vec![ - vec![EntityComponent { - id: ComponentId::of::<DekuNut>(), - name: "Deku nut", - component: Lock::new(Box::new(DekuNut { _throwing_damage: 5 })), - }], - vec![EntityComponent { - id: ComponentId::of::<IronBoots>(), - name: "Iron boots", - component: Lock::new(Box::new(IronBoots)), - }], - vec![EntityComponent { - id: ComponentId::of::<Bow>(), - name: "Bow", - component: Lock::new(Box::new(Bow { _damage: 20 })), - }], - vec![EntityComponent { - id: ComponentId::of::<Hookshot>(), - name: "Hookshot", - component: Lock::new(Box::new(Hookshot { _range: 67 })), - }], + entities: vec![ + ArchetypeEntity { + uid: entity_uid_d, + components: vec![EntityComponent { + id: ComponentId::of::<DekuNut>(), + name: "Deku nut", + component: Lock::new(Box::new(DekuNut { _throwing_damage: 5 })), + }], + }, + ArchetypeEntity { + uid: entity_uid_e, + components: vec![EntityComponent { + id: ComponentId::of::<IronBoots>(), + name: "Iron boots", + component: Lock::new(Box::new(IronBoots)), + }], + }, + ArchetypeEntity { + uid: entity_uid_f, + components: vec![EntityComponent { + id: ComponentId::of::<Bow>(), + name: "Bow", + component: Lock::new(Box::new(Bow { _damage: 20 })), + }], + }, + ArchetypeEntity { + uid: entity_uid_g, + components: vec![EntityComponent { + id: ComponentId::of::<Hookshot>(), + name: "Hookshot", + component: Lock::new(Box::new(Hookshot { _range: 67 })), + }], + }, ], }); |