mod iterator;
pub use iterator::EntitiesIter;
use crate::add_component::AddComponent;
use crate::add_distinct_component::AddDistinctComponent;
use crate::add_entity::AddEntity;
use crate::entity_id::EntityId;
use crate::error;
use crate::memory_usage::StorageMemoryUsage;
use crate::reserve::{BulkEntityIter, BulkReserve};
use crate::storage::Storage;
use alloc::vec::Vec;
use core::iter::repeat_with;
pub struct Entities {
pub(crate) data: Vec<EntityId>,
list: Option<(usize, usize)>,
}
impl Entities {
#[inline]
pub(crate) fn new() -> Self {
Entities {
data: Vec::new(),
list: None,
}
}
#[inline]
pub fn is_alive(&self, entity: EntityId) -> bool {
if let Some(&self_entity) = self.data.get(entity.uindex()) {
entity == self_entity
} else {
false
}
}
#[track_caller]
#[inline]
pub fn add_component<S: AddComponent>(
&self,
entity: EntityId,
mut storages: S,
component: S::Component,
) {
if self.is_alive(entity) {
storages.add_component_unchecked(entity, component);
} else {
panic!("{:?}", error::AddComponent::EntityIsNotAlive);
}
}
#[track_caller]
#[inline]
pub fn add_distinct_component<S: AddDistinctComponent>(
&self,
entity: EntityId,
mut storages: S,
component: S::Component,
) -> bool {
if self.is_alive(entity) {
storages.add_distinct_component_unchecked(entity, component)
} else {
panic!("{:?}", error::AddComponent::EntityIsNotAlive);
}
}
pub(crate) fn generate(&mut self) -> EntityId {
if let Some((new, ref mut old)) = self.list {
let old_index = *old;
if new == *old {
self.list = None;
} else {
*old = unsafe { self.data.get_unchecked(old_index).uindex() };
}
unsafe {
self.data
.get_unchecked_mut(old_index)
.set_index(old_index as u64);
*self.data.get_unchecked(old_index)
}
} else {
let entity_id = EntityId::new(self.data.len() as u64);
self.data.push(entity_id);
entity_id
}
}
pub(crate) fn bulk_generate(&mut self, count: usize) -> &[EntityId] {
self.data
.extend((self.data.len() as u64..(self.data.len() + count) as u64).map(EntityId::new));
&self.data[self.data.len() - count..self.data.len()]
}
pub fn delete_unchecked(&mut self, entity_id: EntityId) -> bool {
if self.is_alive(entity_id) {
if unsafe {
self.data
.get_unchecked_mut(entity_id.uindex())
.bump_gen()
.is_ok()
} {
if let Some((ref mut new, _)) = self.list {
unsafe {
self.data
.get_unchecked_mut(*new)
.set_index(entity_id.index())
};
unsafe {
self.data
.get_unchecked_mut(entity_id.uindex())
.set_index(EntityId::max_index())
};
*new = entity_id.uindex();
} else {
unsafe {
self.data
.get_unchecked_mut(entity_id.uindex())
.set_index(EntityId::max_index())
};
self.list = Some((entity_id.uindex(), entity_id.uindex()));
}
}
true
} else {
false
}
}
#[inline]
pub fn add_entity<T: AddEntity>(
&mut self,
mut storages: T,
component: T::Component,
) -> EntityId {
let entity_id = self.generate();
AddEntity::add_entity(&mut storages, entity_id, component);
entity_id
}
pub fn bulk_add_entity<T: AddEntity + BulkReserve, I: IntoIterator<Item = T::Component>>(
&mut self,
mut storages: T,
component: I,
) -> BulkEntityIter<'_> {
let mut iter = component.into_iter();
let len = iter.size_hint().0;
let entities_len = self.data.len();
let new_entities = self.bulk_generate(len);
storages.bulk_reserve(new_entities);
for (component, id) in (&mut iter).zip(new_entities.iter().copied()) {
AddEntity::add_entity(&mut storages, id, component);
}
for (component, id) in iter.zip(repeat_with(|| self.generate())) {
AddEntity::add_entity(&mut storages, id, component);
}
BulkEntityIter {
iter: self.data[entities_len..].iter().copied(),
slice: &self.data[entities_len..],
}
}
#[inline]
pub fn iter(&self) -> EntitiesIter<'_> {
self.into_iter()
}
pub fn spawn(&mut self, entity: EntityId) -> bool {
if let Some(&old_entity) = self.data.get(entity.index() as usize) {
if self.is_alive(old_entity) {
if old_entity.gen() <= entity.gen() {
self.data[entity.uindex()] = entity;
true
} else {
false
}
} else if let Some((new, old)) = self.list {
if old_entity.gen() <= entity.gen() + 1 {
if entity.uindex() == old {
if new == old {
self.list = None;
} else {
self.list = Some((new, self.data[entity.uindex()].uindex()));
}
} else {
let mut current_index = old;
while self.data[current_index].index() != entity.index()
&& self.data[current_index].uindex() != new
{
current_index = self.data[current_index].uindex();
}
if self.data[current_index].uindex() == new {
self.data[current_index].set_index(EntityId::max_index());
self.list = Some((current_index, old));
} else {
let next_index = self.data[self.data[current_index].uindex()].index();
self.data[current_index].set_index(next_index);
}
}
self.data[entity.uindex()] = entity;
true
} else {
false
}
} else {
false
}
} else {
let old_len = self.data.len();
self.data.resize(entity.uindex() + 1, EntityId::new(0));
if self.data.len() - old_len > 1 {
if let Some((new, _)) = &mut self.list {
self.data[*new].set_index(old_len as u64);
*new = entity.uindex() - 1;
} else {
self.list = Some((entity.uindex() - 1, old_len));
}
for (e, index) in self.data[old_len..entity.uindex() - 1]
.iter_mut()
.zip(old_len as u64 + 1..)
{
e.set_index(index);
}
self.data[entity.uindex() - 1].set_index(EntityId::max_index());
}
self.data[entity.uindex()] = entity;
true
}
}
}
impl Storage for Entities {
fn clear(&mut self, _current: u32) {
if self.data.is_empty() {
return;
}
let mut last_alive = self.data.len() as u64 - 1;
for (i, id) in self.data.iter_mut().enumerate().rev() {
let target = last_alive;
if id.bump_gen().is_ok() {
last_alive = i as u64;
}
id.set_index(target);
}
let begin = self
.data
.iter()
.position(|id| id.gen() < EntityId::max_gen())
.unwrap();
let end = self
.data
.iter()
.rev()
.position(|id| id.gen() < EntityId::max_gen())
.unwrap();
self.list = Some((self.data.len() - end - 1, begin));
}
fn memory_usage(&self) -> Option<StorageMemoryUsage> {
Some(StorageMemoryUsage {
storage_name: core::any::type_name::<Self>().into(),
allocated_memory_bytes: (self.data.capacity() * core::mem::size_of::<EntityId>())
+ core::mem::size_of::<Entities>(),
used_memory_bytes: (self.data.len() * core::mem::size_of::<EntityId>())
+ core::mem::size_of::<Entities>(),
component_count: self.data.len(),
})
}
fn is_empty(&self) -> bool {
self.data.is_empty()
}
}
#[test]
fn entities() {
let mut entities = Entities::new();
let key00 = entities.generate();
let key10 = entities.generate();
assert_eq!(key00.index(), 0);
assert_eq!(key00.gen(), 0);
assert_eq!(key10.index(), 1);
assert_eq!(key10.gen(), 0);
assert!(entities.delete_unchecked(key00));
assert!(!entities.delete_unchecked(key00));
let key01 = entities.generate();
assert_eq!(key01.index(), 0);
assert_eq!(key01.gen(), 1);
assert!(entities.delete_unchecked(key10));
assert!(entities.delete_unchecked(key01));
let key11 = entities.generate();
let key02 = entities.generate();
assert_eq!(key11.index(), 1);
assert_eq!(key11.gen(), 1);
assert_eq!(key02.index(), 0);
assert_eq!(key02.gen(), 2);
let last_key = EntityId::new_from_index_and_gen(0, EntityId::max_gen());
entities.data[0] = last_key;
assert!(entities.delete_unchecked(last_key));
assert_eq!(entities.list, None);
let dead = entities.generate();
assert_eq!(dead.index(), 2);
assert_eq!(dead.gen(), 0);
}
#[test]
fn iterator() {
let mut entities = Entities::new();
entities.add_entity((), ());
entities.add_entity((), ());
entities.add_entity((), ());
let mut iter = entities.iter();
let id0 = iter.next().unwrap();
assert_eq!(id0.index(), 0);
assert_eq!(id0.gen(), 0);
let id1 = iter.next().unwrap();
assert_eq!(id1.index(), 1);
assert_eq!(id1.gen(), 0);
let id2 = iter.next().unwrap();
assert_eq!(id2.index(), 2);
assert_eq!(id2.gen(), 0);
assert!(iter.next().is_none());
entities.delete_unchecked(id0);
entities.delete_unchecked(id1);
entities.add_entity((), ());
let mut iter = entities.iter();
let id = iter.next().unwrap();
assert_eq!(id.index(), 0);
assert_eq!(id.gen(), 1);
let id = iter.next().unwrap();
assert_eq!(id.index(), 2);
assert_eq!(id.gen(), 0);
assert!(iter.next().is_none());
}