use indexmap::{IndexMap, IndexSet};
use crate::{
Entity,
component::{Bundle, Component, ComponentBox, ComponentKey},
};
pub struct World {
pub(crate) entities: IndexSet<Entity>,
pub(crate) components: IndexMap<Entity, IndexMap<ComponentKey, ComponentBox>>,
pub(crate) resources: IndexMap<ComponentKey, ComponentBox>,
}
impl World {
pub fn new() -> Self {
let entities = 100;
Self {
entities: IndexSet::with_capacity(entities),
components: IndexMap::with_capacity(entities),
resources: IndexMap::with_capacity(5),
}
}
pub fn spawn(&mut self) -> Entity {
let id = self.entities.len();
self.entities.insert(id);
self.components.insert(id, IndexMap::with_capacity(1000));
id
}
pub fn despawn(&mut self, entity: Entity) {
self.entities.swap_remove(&entity);
self.components.swap_remove(&entity);
}
pub fn add<B: Bundle>(&mut self, entity: Entity, bundle: B) {
let boxes = bundle.into_boxes();
for (key, boxed) in boxes {
if !self.has_key(entity, &key) {
self.components
.entry(entity)
.or_default()
.insert(key, boxed);
}
}
}
pub fn has<C: Component>(&self, entity: Entity) -> bool {
self.has_key(entity, &ComponentKey::of::<C>())
}
pub fn has_key(&self, entity: Entity, key: &ComponentKey) -> bool {
let Some(components) = self.components.get(&entity) else {
return false;
};
components.contains_key(key)
}
pub fn get<C: Component>(&self, entity: Entity) -> Option<&C> {
let c = self
.components
.get(&entity)?
.get(&ComponentKey::of::<C>())?;
c.downcast_ref::<C>()
}
pub fn get_mut<C: Component>(&mut self, entity: Entity) -> Option<&mut C> {
let c = self
.components
.get_mut(&entity)?
.get_mut(&ComponentKey::of::<C>())?;
c.downcast_mut::<C>()
}
pub fn del<C: Component>(&mut self, entity: Entity) -> Option<Box<C>> {
let c = self
.components
.get_mut(&entity)?
.swap_remove(&ComponentKey::of::<C>())?;
c.downcast().ok()
}
pub fn add_res<C: Component>(&mut self, resource: C) {
if !self.has_res::<C>() {
self.resources
.insert(ComponentKey::of::<C>(), Box::new(resource));
}
}
pub fn has_res<C: Component>(&self) -> bool {
self.has_res_key(&ComponentKey::of::<C>())
}
pub fn has_res_key(&self, key: &ComponentKey) -> bool {
self.resources.contains_key(key)
}
pub fn get_res<C: Component>(&self) -> Option<&C> {
self.resources.get(&ComponentKey::of::<C>())?.downcast_ref()
}
pub fn get_res_mut<C: Component>(&mut self) -> Option<&mut C> {
self.resources
.get_mut(&ComponentKey::of::<C>())?
.downcast_mut()
}
pub fn del_res<C: Component>(&mut self) -> Option<Box<C>> {
self.resources
.swap_remove(&ComponentKey::of::<C>())
.map(|c| c.downcast().ok())
.flatten()
}
}
impl Default for World {
fn default() -> Self {
World::new()
}
}