mod query;
mod query_entity;
pub mod auto_query;
mod fn_query;
use std::{any::{Any, TypeId}, rc::Rc, cell::{RefCell}, collections::HashMap};
use eyre::*;
pub use self::query::Query;
pub use self::query_entity::QueryEntity;
pub use self::auto_query::*;
pub use self::fn_query::*;
pub type ComponentType = Rc<RefCell<dyn Any>>;
#[derive(Debug, Default)]
pub struct Entities {
components: HashMap<TypeId, Vec<Option<ComponentType>>>,
entity_count: usize,
bit_masks: HashMap<TypeId, u128>,
map: Vec<u128>,
insert_cursor: usize,
}
impl Entities {
pub fn register_component<T: Any + 'static>(&mut self) {
let typeid = TypeId::of::<T>();
let bitmask = 2_u128.pow(self.components.len() as u32);
self.components.insert(typeid, Vec::new());
self.bit_masks.insert(typeid, bitmask);
}
fn fill_new_component_checked<T: Any>(&mut self) -> Result<()> {
let comps = self.components.get_mut(&TypeId::of::<T>()).ok_or(ComponentError::AutomaticRegistrationError)?;
for _ in 0..self.entity_count { comps.push(None); }
Ok(())
}
pub fn create_entity(&mut self) -> &mut Self {
if let Some((index, _)) = self.map.iter().enumerate().find(|(_index, map_val)| **map_val == 0) {
self.insert_cursor = index;
} else {
self.components.iter_mut().for_each(|(_key, value)| {
value.push(None);
});
self.map.push(0);
self.entity_count += 1;
self.insert_cursor = self.entity_count - 1;
}
self
}
pub fn insert<T: Any>(&mut self, data: T) -> &mut Self {
self.insert_checked(data).unwrap()
}
pub fn insert_checked<T: Any>(&mut self, data: T) -> eyre::Result<&mut Self> {
if !self.bit_masks.contains_key(&TypeId::of::<T>()) {
self.register_component::<T>();
self.fill_new_component_checked::<T>()?;
}
let map_index = self.insert_cursor;
if let Some(components) = self.components.get_mut(&data.type_id()) {
let component = components.get_mut(map_index).ok_or(ComponentError::NonexistentEntity)?;
let typeid = data.type_id();
*component = Some(Rc::new(RefCell::new(data)));
let bitmask = self.bit_masks.get(&typeid).unwrap();
self.map[map_index] |= *bitmask;
} else {
bail!("Attempted to add a component that was not registered to an entity.");
}
Ok(self)
}
pub fn delete_component_by_entity_id_checked<T: Any>(&mut self, index: usize) -> Result<()> {
let typeid = TypeId::of::<T>();
let mask = self.bit_masks.get(&typeid).ok_or(ComponentError::UnregisteredComponentError)?;
if self.map[index] & *mask != 0 {
self.map[index] ^= *mask;
}
Ok(())
}
pub fn delete_component_by_entity_id<T: Any>(&mut self, index: usize) {
self.delete_component_by_entity_id_checked::<T>(index).unwrap()
}
pub fn insert_component_into_entity_by_id<T: Any>(&mut self, data: T, map_index: usize) {
self.insert_component_into_entity_by_id_checked(data, map_index).unwrap()
}
pub fn insert_component_into_entity_by_id_checked<T: Any>(&mut self, data: T, map_index: usize) -> eyre::Result<()> {
if !self.bit_masks.contains_key(&TypeId::of::<T>()) {
self.register_component::<T>();
self.fill_new_component_checked::<T>()?;
}
if let Some(components) = self.components.get_mut(&data.type_id()) {
let replaced_component = components.get_mut(map_index).ok_or(ComponentError::NonexistentEntity)?;
let typeid = data.type_id();
*replaced_component = Some(Rc::new(RefCell::new(data)));
let bitmask = self.bit_masks.get(&typeid).ok_or(ComponentError::UnregisteredComponentError)?;
self.map[map_index] |= *bitmask;
} else {
bail!("Attempted to add a component that was not registered to an entity.");
}
Ok(())
}
pub fn delete_component<T: Any>(&mut self) {
self.delete_component_checked::<T>().unwrap()
}
pub fn delete_component_checked<T: Any>(&mut self) -> eyre::Result<()> {
let (_, bitmask) = self.bit_masks.remove_entry(&TypeId::of::<T>()).ok_or(ComponentError::UnregisteredComponentError)?;
for component_bitmask in &mut self.map {
*component_bitmask ^= bitmask;
}
Ok(())
}
pub fn delete_entity_by_id(&mut self, index: usize) -> eyre::Result<()> {
let len = self.map.len();
*self.map.get_mut(index).ok_or(ComponentError::IndexOutOfBoundsError { expected: len, found: index })? = 0;
Ok(())
}
pub fn get_bitmask(&self, typeid: &TypeId) -> Option<u128> {
self.bit_masks.get(typeid).copied()
}
}
impl std::fmt::Display for Entities {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{self:#?}")
}
}
#[derive(thiserror::Error, Debug)]
enum ComponentError {
#[error("Attempt to add component to nothing.")]
NonexistentEntity,
#[error("This error should never happen. (Failed to fill fields of newly generated component on the fly)")]
AutomaticRegistrationError,
#[error("Attempt to make use of unregistered component.")]
UnregisteredComponentError,
#[error("Index out of bounds when accessing entity id. (Expected range from 0..{expected}, got {found}).")]
IndexOutOfBoundsError { expected: usize, found: usize },
#[error("Attempted to get component data that does not exist. Error in bitmask probably?")]
NonexistentComponentDataError,
}
#[cfg(test)]
mod tests {
use std::{any::TypeId};
use super::*;
#[test]
fn new_entities_fill_deleted_spots() -> eyre::Result<()> {
let mut ents = Entities::default();
ents.create_entity()
.insert_checked(Health(100))?
.insert_checked(Id(String::from("hi")))?;
ents.create_entity()
.insert_checked(Health(50))?
.insert_checked(Id(String::from("hey")))?;
ents.delete_entity_by_id(0)?;
ents.create_entity()
.insert_checked(Health(20))?;
assert_eq!(ents.map[0], 1);
let hp = ents.components.get(&TypeId::of::<Health>()).unwrap()[0]
.as_ref()
.unwrap()
.borrow();
let hp = hp.downcast_ref::<Health>()
.unwrap();
assert_eq!(hp.0, 20);
Ok(())
}
#[test]
fn delete_entities_by_id() -> eyre::Result<()> {
let mut ents = Entities::default();
ents.create_entity()
.insert_checked(Health(100))?
.insert_checked(Id(String::from("hi")))?;
ents.create_entity()
.insert_checked(Unique)?
.insert_checked(Health(50))?
.insert_checked(Id(String::from("hey")))?;
ents.delete_entity_by_id(0)?;
assert_eq!(ents.map[0], 0);
Ok(())
}
#[test]
fn register_entities() {
let mut ents = Entities::default();
ents.register_component::<Health>();
ents.register_component::<Id>();
let hp_component = ents.components.get(&TypeId::of::<Health>()).unwrap();
assert_eq!(hp_component.len(), 0);
dbg!(ents);
}
#[test]
fn bitmask_update_on_register_entities() {
let mut ents = Entities::default();
ents.register_component::<Health>();
ents.register_component::<Id>();
let hp_component = ents.bit_masks.get(&TypeId::of::<Health>()).unwrap();
assert_eq!(*hp_component, 1);
dbg!(ents);
}
#[test]
fn create_entity() {
let mut ents = Entities::default();
ents.register_component::<Health>();
ents.register_component::<Id>();
ents.create_entity();
let hp = ents.components.get(&TypeId::of::<Health>()).unwrap();
let speed = ents.components.get(&TypeId::of::<Id>()).unwrap();
assert!(hp.len() == speed.len() && hp.len() == 1);
assert!(speed[0].is_none());
assert!(hp[0].is_none());
dbg!(ents.components);
}
#[test]
fn with_component() -> Result<()> {
let mut ents = Entities::default();
ents.create_entity()
.insert(Health(100))
.insert(Id(String::from("hi")));
ents.create_entity()
.insert(Unique)
.insert(Health(50))
.insert(Id(String::from("hey")));
let health1 = &ents.components.get(&TypeId::of::<Health>()).unwrap()[0];
let wrapped_health = health1.as_ref().unwrap();
let borrowed_health = wrapped_health.borrow();
let hp = borrowed_health.downcast_ref::<Health>().unwrap();
assert_eq!(hp.0, 100);
dbg!(hp);
let hp = ents.components.get(&TypeId::of::<Health>()).unwrap();
let speed = ents.components.get(&TypeId::of::<Unique>()).unwrap();
assert!(hp.len() == speed.len() && hp.len() == ents.entity_count);
Ok(())
}
#[test]
fn map_is_updated() -> Result<()> {
let mut ents = Entities::default();
ents.create_entity()
.insert(Health(100))
.insert(Id(String::from("hi")));
let entity_map = ents.map[0];
assert_eq!(entity_map, 3);
ents.create_entity()
.insert(Id(String::from("hi")));
let entity_map = ents.map[1];
assert_eq!(entity_map, 2);
Ok(())
}
#[test]
fn delete_component_by_ent_id() -> Result<()> {
let mut ents = Entities::default();
ents.create_entity()
.insert(Health(100))
.insert(Id(String::from("hi")));
ents.create_entity()
.insert(Health(50))
.insert(Id(String::from("hey")));
ents.delete_component_by_entity_id_checked::<Health>(0)?;
assert_eq!(ents.map[0], 2);
Ok(())
}
#[test]
fn add_component_by_ent_id() -> eyre::Result<()> {
let mut ents = Entities::default();
ents.create_entity()
.insert(Health(100))
.insert(Id(String::from("hi")));
ents.create_entity()
.insert(Health(50))
.insert(Id(String::from("hey")));
ents.insert_component_into_entity_by_id(Unique, 0);
assert_eq!(ents.map[0], 7);
Ok(())
}
#[test]
fn remove_component() -> eyre::Result<()> {
let mut ents = Entities::default();
ents.create_entity()
.insert_checked(Health(100))?
.insert_checked(Id(String::from("hi")))?;
ents.create_entity()
.insert_checked(Health(50))?
.insert_checked(Id(String::from("hey")))?;
assert_eq!(ents.map[0], 3_u128);
ents.delete_component_checked::<Health>()?;
assert_eq!(ents.map[0], 2_u128);
Ok(())
}
#[test]
fn double_delete_fix() -> eyre::Result<()> {
let mut ents = Entities::default();
ents.create_entity()
.insert_checked(Health(100))?
.insert_checked(Id(String::from("hi")))?;
ents.delete_component_by_entity_id_checked::<Health>(0)?;
assert_eq!(ents.map[0], 2);
ents.delete_component_by_entity_id_checked::<Health>(0)?;
assert_eq!(ents.map[0], 2);
Ok(())
}
#[derive(Debug)]
struct Health(u16);
struct Id(String);
struct Unique;
}