use alloc::{vec, vec::Vec};
use core::{
any::type_name,
cell::UnsafeCell,
convert::TryFrom,
fmt::{self, Debug},
ops::{Deref, DerefMut},
sync::atomic::{AtomicU64, Ordering},
};
use crate::{
action::{ActionChannel, ActionSender, LocalActionBuffer, LocalActionEncoder},
archetype::Archetype,
bundle::{BundleDesc, ComponentBundleDesc},
component::{Component, ComponentInfo, ComponentRegistry},
entity::{AliveEntity, Entity, EntityId, EntityLoc, EntityRef, EntitySet},
epoch::{EpochCounter, EpochId},
res::Res,
type_id, NoSuchEntity,
};
use self::edges::Edges;
pub(crate) use self::spawn::iter_reserve_hint;
pub use self::builder::WorldBuilder;
mod builder;
mod edges;
mod get;
mod insert;
mod relation;
mod remove;
mod resource;
mod spawn;
mod view;
static NEXT_ARCHETYPE_SET_ID: AtomicU64 = AtomicU64::new(1);
struct ArchetypeSet {
id: u64,
archetypes: Vec<Archetype>,
}
impl Deref for ArchetypeSet {
type Target = [Archetype];
fn deref(&self) -> &[Archetype] {
&self.archetypes
}
}
impl DerefMut for ArchetypeSet {
fn deref_mut(&mut self) -> &mut [Archetype] {
&mut self.archetypes
}
}
impl ArchetypeSet {
fn new() -> Self {
let null_archetype = Archetype::new(core::iter::empty());
ArchetypeSet {
id: 0,
archetypes: vec![null_archetype],
}
}
fn id(&self) -> u64 {
self.id
}
fn add_with(&mut self, f: impl FnOnce(&[Archetype]) -> Archetype) -> u32 {
let len = match u32::try_from(self.archetypes.len()) {
Ok(u32::MAX) | Err(_) => panic!("Too many archetypes"),
Ok(len) => len,
};
let new_archetype = f(&self.archetypes);
self.archetypes.push(new_archetype);
self.id = NEXT_ARCHETYPE_SET_ID.fetch_add(1, Ordering::Relaxed);
len
}
}
pub struct World {
epoch: EpochCounter,
entities: EntitySet,
archetypes: ArchetypeSet,
edges: Edges,
registry: ComponentRegistry,
res: Res,
action_buffer: UnsafeCell<LocalActionBuffer>,
action_channel: ActionChannel,
}
impl Default for World {
fn default() -> Self {
World::new()
}
}
impl Debug for World {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("World").finish_non_exhaustive()
}
}
impl World {
#[inline(always)]
pub fn archetype_set_id(&self) -> u64 {
self.archetypes.id()
}
#[inline(always)]
pub fn lookup(&self, entity: impl Entity) -> Result<EntityLoc<'_>, NoSuchEntity> {
entity.entity_loc(&self.entities).ok_or(NoSuchEntity)
}
#[inline(always)]
pub fn entity(&mut self, entity: impl Entity) -> Result<EntityRef<'_>, NoSuchEntity> {
self.maintenance();
entity.entity_ref(self).ok_or(NoSuchEntity)
}
#[inline(always)]
pub fn epoch(&self) -> EpochId {
self.epoch.current()
}
#[inline(always)]
pub fn epoch_counter(&self) -> &EpochCounter {
&self.epoch
}
#[inline(always)]
pub fn has_component<T: 'static>(&self, entity: impl AliveEntity) -> bool {
let loc = entity.locate(&self.entities);
if loc.arch == u32::MAX {
return false;
}
self.archetypes[loc.arch as usize].has_component(type_id::<T>())
}
#[inline(always)]
pub fn try_has_component<T: 'static>(&self, entity: impl Entity) -> Result<bool, NoSuchEntity> {
let loc = entity.lookup(&self.entities).ok_or(NoSuchEntity)?;
if loc.arch == u32::MAX {
return Ok(false);
}
Ok(self.archetypes[loc.arch as usize].has_component(type_id::<T>()))
}
#[inline(always)]
pub fn is_alive(&self, id: EntityId) -> bool {
self.entities.get_location(id).is_some()
}
pub fn iter_component_info(&self) -> impl Iterator<Item = &ComponentInfo> {
self.registry.iter_info()
}
pub fn archetypes(&self) -> &[Archetype] {
&self.archetypes
}
pub(crate) fn archetypes_mut(&mut self) -> &mut [Archetype] {
&mut self.archetypes
}
#[inline(always)]
pub fn local(&mut self) -> &mut WorldLocal {
WorldLocal::wrap_mut(self)
}
#[inline(always)]
pub fn into_local(self) -> WorldLocal {
WorldLocal::wrap(self)
}
pub fn new_action_sender(&self) -> ActionSender {
self.action_channel.sender()
}
pub(crate) fn entities(&self) -> &EntitySet {
&self.entities
}
#[inline(always)]
pub(crate) fn maintenance(&mut self) {
let archetype = &mut self.archetypes[0];
self.entities
.spawn_allocated(|id| archetype.spawn_empty(id));
self.execute_local_actions();
}
pub fn execute_received_actions(&mut self) {
self.maintenance();
self.action_channel.fetch();
while let Some(f) = self.action_channel.pop() {
f.call(self);
}
}
#[inline(always)]
fn execute_local_actions(&mut self) {
while let Some(action) = self.action_buffer.get_mut().pop() {
action.call(self);
}
}
pub fn run_deferred(&mut self) {
self.execute_local_actions();
}
}
#[repr(transparent)]
pub struct WorldShare {
inner: World,
}
unsafe impl Sync for WorldShare {}
impl Deref for WorldShare {
type Target = World;
fn deref(&self) -> &World {
&self.inner
}
}
impl DerefMut for WorldShare {
fn deref_mut(&mut self) -> &mut World {
&mut self.inner
}
}
impl Debug for WorldShare {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
<World as Debug>::fmt(&self.inner, f)
}
}
impl From<WorldShare> for World {
#[inline]
fn from(world: WorldShare) -> Self {
world.inner
}
}
impl From<World> for WorldShare {
#[inline]
fn from(world: World) -> Self {
WorldShare { inner: world }
}
}
impl WorldShare {
pub fn new() -> Self {
WorldShare {
inner: World::new(),
}
}
#[inline(always)]
pub fn wrap(world: World) -> Self {
WorldShare { inner: world }
}
}
#[repr(transparent)]
pub struct WorldLocal {
inner: World,
}
impl From<WorldLocal> for World {
#[inline]
fn from(world: WorldLocal) -> Self {
world.inner
}
}
impl From<World> for WorldLocal {
#[inline]
fn from(world: World) -> Self {
WorldLocal { inner: world }
}
}
impl Deref for WorldLocal {
type Target = World;
#[inline(always)]
fn deref(&self) -> &World {
&self.inner
}
}
impl DerefMut for WorldLocal {
#[inline(always)]
fn deref_mut(&mut self) -> &mut World {
&mut self.inner
}
}
impl Debug for WorldLocal {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
<World as Debug>::fmt(&self.inner, f)
}
}
impl WorldLocal {
pub fn new() -> Self {
WorldLocal {
inner: World::new(),
}
}
#[inline(always)]
pub fn wrap(world: World) -> Self {
WorldLocal { inner: world }
}
#[inline(always)]
fn wrap_mut(world: &mut World) -> &mut Self {
unsafe { &mut *(world as *mut World as *mut Self) }
}
pub fn defer(&self, f: impl FnOnce(&mut World) + 'static) {
unsafe {
let action_buffer = &mut *self.inner.action_buffer.get();
let mut action_encoder = LocalActionEncoder::new(action_buffer, &self.inner.entities);
action_encoder.closure(f);
}
}
}
pub(crate) fn register_bundle<B: ComponentBundleDesc>(
registry: &mut ComponentRegistry,
bundle: &B,
) {
bundle.with_components(|infos| {
for info in infos {
registry.get_or_register_raw(info.clone());
}
});
}
pub(crate) fn assert_registered_bundle<B: BundleDesc>(
registry: &mut ComponentRegistry,
bundle: &B,
) {
bundle.with_ids(|ids| {
for (idx, id) in ids.iter().enumerate() {
if registry.get_info(*id).is_none() {
panic!(
"Component {:?} - ({}[{}]) is not registered",
id,
type_name::<B>(),
idx
);
}
}
})
}
pub(crate) fn register_one<T: Component>(registry: &mut ComponentRegistry) -> &ComponentInfo {
registry.get_or_register::<T>()
}
pub(crate) fn assert_registered_one<T: 'static>(
registry: &mut ComponentRegistry,
) -> &ComponentInfo {
match registry.get_info(type_id::<T>()) {
Some(info) => info,
None => panic!(
"Component {}({:?}) is not registered",
type_name::<T>(),
type_id::<T>()
),
}
}