use std::any::TypeId; use std::collections::{HashMap, HashSet}; use dungeon_cell::bound::bounds; use dungeon_cell::layout_for; use slotmap::{DefaultKey, SlotMap}; type DungeonCore = dungeon_cell::DungeonCore; fn main() { let mut ecs = Ecs::new(); ecs.add_system(print_people); let world = ecs.world_mut(); let a = world.spawn(); world.add_component(a, Person); world.add_component(a, Name("foo".into())); let b = world.spawn(); world.add_component(b, Person); world.add_component(b, Name("bar".into())); ecs.step(); } struct Person; struct Name(String); fn print_people(world: &mut World) { for person in world.query(|entity| entity.has::() && entity.has::()) { println!("Person with name {}", world.get::(person).unwrap().0); } } struct World { map: TypeMap, entities: SlotMap, } struct EntityInfo { components: HashSet<(TypeId, DefaultKey)>, } impl EntityInfo { fn has(&self) -> bool { self.components .iter() .any(|(id, _)| *id == TypeId::of::()) } } impl World { fn spawn(&mut self) -> DefaultKey { self.entities.insert(EntityInfo { components: HashSet::new(), }) } fn add_component( &mut self, entity: DefaultKey, component: T, ) { if let Some(entity) = self.entities.get_mut(entity) { let key = self.map.get_mut::().insert(component); entity.components.insert((TypeId::of::(), key)); } } fn get(&self, entity: DefaultKey) -> Option<&T> { self.entities .get(entity) .and_then(|entity| { entity.components.iter().find(|(component_type, _)| { *component_type == TypeId::of::() }) }) .and_then(|(_, key)| { self.map .get::() .map(|components| components.get(*key).unwrap()) }) } fn query<'a, F: 'a + FnMut(&EntityInfo) -> bool>( &'a self, mut filter: F, ) -> impl Iterator + 'a { self.entities .iter() .filter(move |(_, info)| filter(info)) .map(|(key, _)| key) } } struct Ecs { world: World, systems: Vec, } impl Ecs { fn new() -> Self { Self { world: World { map: TypeMap::new(), entities: SlotMap::new(), }, systems: Vec::new(), } } fn add_system(&mut self, system: fn(&mut World)) { self.systems.push(system); } fn world_mut(&mut self) -> &mut World { &mut self.world } fn world(&self) -> &World { &self.world } fn step(&mut self) { for system in &mut self.systems { (system)(&mut self.world) } } } struct TypeMap { map: HashMap)>>, } impl TypeMap { fn new() -> Self { Self { map: HashMap::new(), } } fn get_mut(&mut self) -> &mut SlotMap { self.map .entry(TypeId::of::()) .or_insert_with(|| DungeonCore::new(SlotMap::<_, T>::new())) .borrow_mut() .unwrap() } fn get(&self) -> Option<&SlotMap> { self.map .get(&TypeId::of::()) .map(|vec| vec.borrow::>().unwrap()) } }