//! A space on a server for objects to occupy. 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; /// A container for all [`World`]s on a [`Server`](crate::server::Server). pub struct Worlds { slab: VersionedSlab>, shared: SharedServer, } /// An identifier for a [`World`] on the server. /// /// World IDs are either _valid_ or _invalid_. Valid world IDs point to /// worlds that have not been deleted, while invalid IDs point to those that /// have. Once an ID becomes invalid, it will never become valid again. /// /// The [`Ord`] instance on this type is correct but otherwise unspecified. This /// is useful for storing IDs in containers such as /// [`BTreeMap`](std::collections::BTreeMap). #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default, Debug)] pub struct WorldId(Key); impl WorldId { /// The value of the default world ID which is always invalid. pub const NULL: Self = Self(Key::NULL); } impl Worlds { pub(crate) fn new(shared: SharedServer) -> Self { Self { slab: VersionedSlab::new(), shared, } } /// Creates a new world on the server with the provided dimension. A /// reference to the world along with its ID is returned. pub fn insert( &mut self, dimension: DimensionId, state: C::WorldState, ) -> (WorldId, &mut World) { let dim = self.shared.dimension(dimension); let (id, world) = self.slab.insert(World { state, spatial_index: SpatialIndex::new(), chunks: Chunks::new(dim.height, dim.min_y), meta: WorldMeta { dimension }, }); (WorldId(id), world) } /// Deletes a world from the server. /// /// Note that any entities located in the world are not deleted. /// Additionally, clients that are still in the deleted world at the end /// of the tick are disconnected. /// /// Returns `true` if the world was deleted. Otherwise, `false` is returned /// and the function has no effect. pub fn remove(&mut self, world: WorldId) -> bool { self.slab.remove(world.0).is_some() } /// Removes all worlds from the server for which `f` returns `false`. /// /// All worlds are visited in an unspecified order. pub fn retain(&mut self, mut f: impl FnMut(WorldId, &mut World) -> bool) { self.slab.retain(|k, v| f(WorldId(k), v)) } /// Returns the number of worlds on the server. pub fn len(&self) -> usize { self.slab.len() } /// Returns `true` if there are no worlds on the server. pub fn is_empty(&self) -> bool { self.slab.len() == 0 } /// Returns a shared reference to the world with the given ID. If /// the ID is invalid, then `None` is returned. pub fn get(&self, world: WorldId) -> Option<&World> { self.slab.get(world.0) } /// Returns an exclusive reference to the world with the given ID. If the /// ID is invalid, then `None` is returned. pub fn get_mut(&mut self, world: WorldId) -> Option<&mut World> { self.slab.get_mut(world.0) } /// Returns an iterator over all worlds on the server in an unspecified /// order. pub fn iter( &self, ) -> impl ExactSizeIterator)> + FusedIterator + Clone + '_ { self.slab.iter().map(|(k, v)| (WorldId(k), v)) } /// Returns a mutable iterator over all worlds on the server in an /// unspecified order. pub fn iter_mut( &mut self, ) -> impl ExactSizeIterator)> + FusedIterator + '_ { self.slab.iter_mut().map(|(k, v)| (WorldId(k), v)) } /// Returns a parallel iterator over all worlds on the server in an /// unspecified order. pub fn par_iter(&self) -> impl ParallelIterator)> + Clone + '_ { self.slab.par_iter().map(|(k, v)| (WorldId(k), v)) } /// Returns a parallel mutable iterator over all worlds on the server in an /// unspecified order. pub fn par_iter_mut(&mut self) -> impl ParallelIterator)> + '_ { self.slab.par_iter_mut().map(|(k, v)| (WorldId(k), v)) } } /// A space for chunks, entities, and clients to occupy. pub struct World { /// Custom state. pub state: C::WorldState, /// Contains all of the entities in this world. pub spatial_index: SpatialIndex, /// All of the chunks in this world. pub chunks: Chunks, /// This world's metadata. pub meta: WorldMeta, } /// Contains miscellaneous data about the world. pub struct WorldMeta { dimension: DimensionId, } impl WorldMeta { /// Gets the dimension the world was created with. pub fn dimension(&self) -> DimensionId { self.dimension } }