use std::iter::FusedIterator;
use rayon::iter::ParallelIterator;
use crate::chunk::Chunks;
use crate::config::Config;
use crate::dimension::DimensionId;
use crate::server::SharedServer;
use crate::slab_versioned::{Key, VersionedSlab};
use crate::spatial_index::SpatialIndex;
pub struct Worlds<C: Config> {
slab: VersionedSlab<World<C>>,
shared: SharedServer<C>,
}
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default, Debug)]
pub struct WorldId(Key);
impl WorldId {
pub const NULL: Self = Self(Key::NULL);
}
impl<C: Config> Worlds<C> {
pub(crate) fn new(shared: SharedServer<C>) -> Self {
Self {
slab: VersionedSlab::new(),
shared,
}
}
pub fn insert(&mut self, dim: DimensionId, state: C::WorldState) -> (WorldId, &mut World<C>) {
let (id, world) = self.slab.insert(World {
state,
spatial_index: SpatialIndex::new(),
chunks: Chunks::new(self.shared.clone(), dim),
meta: WorldMeta { dimension: dim },
});
(WorldId(id), world)
}
pub fn remove(&mut self, world: WorldId) -> bool {
self.slab.remove(world.0).is_some()
}
pub fn retain(&mut self, mut f: impl FnMut(WorldId, &mut World<C>) -> bool) {
self.slab.retain(|k, v| f(WorldId(k), v))
}
pub fn len(&self) -> usize {
self.slab.len()
}
pub fn is_empty(&self) -> bool {
self.slab.len() == 0
}
pub fn get(&self, world: WorldId) -> Option<&World<C>> {
self.slab.get(world.0)
}
pub fn get_mut(&mut self, world: WorldId) -> Option<&mut World<C>> {
self.slab.get_mut(world.0)
}
pub fn iter(
&self,
) -> impl ExactSizeIterator<Item = (WorldId, &World<C>)> + FusedIterator + Clone + '_ {
self.slab.iter().map(|(k, v)| (WorldId(k), v))
}
pub fn iter_mut(
&mut self,
) -> impl ExactSizeIterator<Item = (WorldId, &mut World<C>)> + FusedIterator + '_ {
self.slab.iter_mut().map(|(k, v)| (WorldId(k), v))
}
pub fn par_iter(&self) -> impl ParallelIterator<Item = (WorldId, &World<C>)> + Clone + '_ {
self.slab.par_iter().map(|(k, v)| (WorldId(k), v))
}
pub fn par_iter_mut(&mut self) -> impl ParallelIterator<Item = (WorldId, &mut World<C>)> + '_ {
self.slab.par_iter_mut().map(|(k, v)| (WorldId(k), v))
}
}
pub struct World<C: Config> {
pub state: C::WorldState,
pub spatial_index: SpatialIndex,
pub chunks: Chunks<C>,
pub meta: WorldMeta,
}
pub struct WorldMeta {
dimension: DimensionId,
}
impl WorldMeta {
pub fn dimension(&self) -> DimensionId {
self.dimension
}
}