mirror of
https://github.com/italicsjenga/valence.git
synced 2025-01-11 07:11:30 +11:00
Update rust docs
This commit is contained in:
parent
5d8f7a49da
commit
f7a35f356e
|
@ -37,7 +37,7 @@ sha2 = "0.10"
|
||||||
thiserror = "1"
|
thiserror = "1"
|
||||||
url = { version = "2.2.2", features = ["serde"] }
|
url = { version = "2.2.2", features = ["serde"] }
|
||||||
uuid = "1"
|
uuid = "1"
|
||||||
valence_nbt = { path = "valence_nbt" }
|
serde_nbt = { path = "serde_nbt" }
|
||||||
vek = "0.15"
|
vek = "0.15"
|
||||||
|
|
||||||
[dependencies.tokio]
|
[dependencies.tokio]
|
||||||
|
@ -68,4 +68,4 @@ num = "0.4"
|
||||||
protocol = []
|
protocol = []
|
||||||
|
|
||||||
[workspace]
|
[workspace]
|
||||||
members = ["valence_nbt", "packet_inspector"]
|
members = ["serde_nbt", "packet_inspector"]
|
||||||
|
|
78
src/chunk.rs
78
src/chunk.rs
|
@ -23,7 +23,7 @@ use crate::protocol::packets::s2c::play::{
|
||||||
use crate::protocol::{Encode, NbtBridge, VarInt, VarLong};
|
use crate::protocol::{Encode, NbtBridge, VarInt, VarLong};
|
||||||
use crate::server::SharedServer;
|
use crate::server::SharedServer;
|
||||||
|
|
||||||
/// A container for all [`Chunks`]s in a [`World`](crate::world::World).
|
/// A container for all [`Chunk`]s in a [`World`](crate::world::World).
|
||||||
pub struct Chunks<C: Config> {
|
pub struct Chunks<C: Config> {
|
||||||
chunks: HashMap<ChunkPos, Chunk<C>>,
|
chunks: HashMap<ChunkPos, Chunk<C>>,
|
||||||
shared: SharedServer<C>,
|
shared: SharedServer<C>,
|
||||||
|
@ -65,8 +65,8 @@ impl<C: Config> Chunks<C> {
|
||||||
|
|
||||||
/// Removes a chunk at the provided position.
|
/// Removes a chunk at the provided position.
|
||||||
///
|
///
|
||||||
/// If a chunk exists at the position, then it is deleted and `true` is
|
/// If a chunk exists at the position, then it is deleted and its
|
||||||
/// returned. Otherwise, `false` is returned.
|
/// `ChunkState` is returned. Otherwise, `None` is returned.
|
||||||
pub fn remove(&mut self, pos: impl Into<ChunkPos>) -> Option<C::ChunkState> {
|
pub fn remove(&mut self, pos: impl Into<ChunkPos>) -> Option<C::ChunkState> {
|
||||||
self.chunks.remove(&pos.into()).map(|c| c.state)
|
self.chunks.remove(&pos.into()).map(|c| c.state)
|
||||||
}
|
}
|
||||||
|
@ -90,6 +90,9 @@ impl<C: Config> Chunks<C> {
|
||||||
self.chunks.get_mut(&pos.into())
|
self.chunks.get_mut(&pos.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Removes all chunks for which `f` returns `true`.
|
||||||
|
///
|
||||||
|
/// All chunks are visited in an unspecified order.
|
||||||
pub fn retain(&mut self, mut f: impl FnMut(ChunkPos, &mut Chunk<C>) -> bool) {
|
pub fn retain(&mut self, mut f: impl FnMut(ChunkPos, &mut Chunk<C>) -> bool) {
|
||||||
self.chunks.retain(|&pos, chunk| f(pos, chunk))
|
self.chunks.retain(|&pos, chunk| f(pos, chunk))
|
||||||
}
|
}
|
||||||
|
@ -99,8 +102,8 @@ impl<C: Config> Chunks<C> {
|
||||||
self.chunks.clear();
|
self.chunks.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns an immutable iterator over all chunks in the world in an
|
/// Returns an iterator over all chunks in the world in an unspecified
|
||||||
/// unspecified order.
|
/// order.
|
||||||
pub fn iter(
|
pub fn iter(
|
||||||
&self,
|
&self,
|
||||||
) -> impl ExactSizeIterator<Item = (ChunkPos, &Chunk<C>)> + FusedIterator + Clone + '_ {
|
) -> impl ExactSizeIterator<Item = (ChunkPos, &Chunk<C>)> + FusedIterator + Clone + '_ {
|
||||||
|
@ -115,7 +118,7 @@ impl<C: Config> Chunks<C> {
|
||||||
self.chunks.iter_mut().map(|(&pos, chunk)| (pos, chunk))
|
self.chunks.iter_mut().map(|(&pos, chunk)| (pos, chunk))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a parallel immutable iterator over all chunks in the world in an
|
/// Returns a parallel iterator over all chunks in the world in an
|
||||||
/// unspecified order.
|
/// unspecified order.
|
||||||
pub fn par_iter(&self) -> impl ParallelIterator<Item = (ChunkPos, &Chunk<C>)> + Clone + '_ {
|
pub fn par_iter(&self) -> impl ParallelIterator<Item = (ChunkPos, &Chunk<C>)> + Clone + '_ {
|
||||||
self.chunks.par_iter().map(|(&pos, chunk)| (pos, chunk))
|
self.chunks.par_iter().map(|(&pos, chunk)| (pos, chunk))
|
||||||
|
@ -131,9 +134,8 @@ impl<C: Config> Chunks<C> {
|
||||||
///
|
///
|
||||||
/// If the position is not inside of a chunk, then `None` is returned.
|
/// If the position is not inside of a chunk, then `None` is returned.
|
||||||
///
|
///
|
||||||
/// Note: if you need to get a large number of blocks, it may be more
|
/// Note: if you need to get a large number of blocks, it is more efficient
|
||||||
/// efficient to read from the chunks directly with
|
/// to read from the chunks directly with [`Chunk::get_block_state`].
|
||||||
/// [`Chunk::get_block_state`].
|
|
||||||
pub fn get_block_state(&self, pos: impl Into<BlockPos>) -> Option<BlockState> {
|
pub fn get_block_state(&self, pos: impl Into<BlockPos>) -> Option<BlockState> {
|
||||||
let pos = pos.into();
|
let pos = pos.into();
|
||||||
let chunk_pos = ChunkPos::from(pos);
|
let chunk_pos = ChunkPos::from(pos);
|
||||||
|
@ -243,28 +245,41 @@ impl<C: Config> Chunk<C> {
|
||||||
chunk
|
chunk
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns `true` if this chunk was created during the current tick.
|
||||||
pub fn created_this_tick(&self) -> bool {
|
pub fn created_this_tick(&self) -> bool {
|
||||||
self.created_this_tick
|
self.created_this_tick
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the height of this chunk in blocks.
|
||||||
pub fn height(&self) -> usize {
|
pub fn height(&self) -> usize {
|
||||||
self.sections.len() * 16
|
self.sections.len() * 16
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Gets the block state at the provided offsets in the chunk.
|
||||||
|
///
|
||||||
|
/// # Panics
|
||||||
|
///
|
||||||
|
/// Panics if the offsets are outside the bounds of the chunk.
|
||||||
pub fn get_block_state(&self, x: usize, y: usize, z: usize) -> BlockState {
|
pub fn get_block_state(&self, x: usize, y: usize, z: usize) -> BlockState {
|
||||||
if x < 16 && y < self.height() && z < 16 {
|
assert!(
|
||||||
BlockState::from_raw_unchecked(
|
x < 16 && y < self.height() && z < 16,
|
||||||
self.sections[y / 16].blocks[x + z * 16 + y % 16 * 16 * 16] & BLOCK_STATE_MASK,
|
"chunk block offsets must be within bounds"
|
||||||
)
|
);
|
||||||
} else {
|
|
||||||
BlockState::AIR
|
BlockState::from_raw_unchecked(
|
||||||
}
|
self.sections[y / 16].blocks[x + z * 16 + y % 16 * 16 * 16] & BLOCK_STATE_MASK,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Sets the block state at the provided offsets in the chunk.
|
||||||
|
///
|
||||||
|
/// # Panics
|
||||||
|
///
|
||||||
|
/// Panics if the offsets are outside the bounds of the chunk.
|
||||||
pub fn set_block_state(&mut self, x: usize, y: usize, z: usize, block: BlockState) {
|
pub fn set_block_state(&mut self, x: usize, y: usize, z: usize, block: BlockState) {
|
||||||
assert!(
|
assert!(
|
||||||
x < 16 && y < self.height() && z < 16,
|
x < 16 && y < self.height() && z < 16,
|
||||||
"the chunk block coordinates must be within bounds"
|
"chunk block offsets must be within bounds"
|
||||||
);
|
);
|
||||||
|
|
||||||
let sect = &mut self.sections[y / 16];
|
let sect = &mut self.sections[y / 16];
|
||||||
|
@ -282,18 +297,35 @@ impl<C: Config> Chunk<C> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Gets the biome at the provided biome offsets in the chunk.
|
||||||
|
///
|
||||||
|
/// Note: the arguments are **not** block positions. Biomes are 4x4x4
|
||||||
|
/// segments of a chunk, so `x` and `z` are in `0..=4`.
|
||||||
|
///
|
||||||
|
/// # Panics
|
||||||
|
///
|
||||||
|
/// Panics if the offsets are outside the bounds of the chunk.
|
||||||
pub fn get_biome(&self, x: usize, y: usize, z: usize) -> BiomeId {
|
pub fn get_biome(&self, x: usize, y: usize, z: usize) -> BiomeId {
|
||||||
if x < 4 && y < self.height() / 4 && z < 4 {
|
assert!(
|
||||||
self.sections[y / 4].biomes[x + z * 4 + y % 4 * 4 * 4]
|
x < 4 && y < self.height() / 4 && z < 4,
|
||||||
} else {
|
"chunk biome offsets must be within bounds"
|
||||||
BiomeId::default()
|
);
|
||||||
}
|
|
||||||
|
self.sections[y / 4].biomes[x + z * 4 + y % 4 * 4 * 4]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Sets the biome at the provided biome offsets in the chunk.
|
||||||
|
///
|
||||||
|
/// Note: the arguments are **not** block positions. Biomes are 4x4x4
|
||||||
|
/// segments of a chunk, so `x` and `z` are in `0..=4`.
|
||||||
|
///
|
||||||
|
/// # Panics
|
||||||
|
///
|
||||||
|
/// Panics if the offsets are outside the bounds of the chunk.
|
||||||
pub fn set_biome(&mut self, x: usize, y: usize, z: usize, b: BiomeId) {
|
pub fn set_biome(&mut self, x: usize, y: usize, z: usize, b: BiomeId) {
|
||||||
assert!(
|
assert!(
|
||||||
x < 4 && y < self.height() / 4 && z < 4,
|
x < 4 && y < self.height() / 4 && z < 4,
|
||||||
"the chunk biome coordinates must be within bounds"
|
"chunk biome offsets must be within bounds"
|
||||||
);
|
);
|
||||||
|
|
||||||
self.sections[y / 4].biomes[x + z * 4 + y % 4 * 4 * 4] = b;
|
self.sections[y / 4].biomes[x + z * 4 + y % 4 * 4 * 4] = b;
|
||||||
|
|
|
@ -70,22 +70,22 @@ impl<C: Config> Clients<C> {
|
||||||
|
|
||||||
/// Removes a client from the server.
|
/// Removes a client from the server.
|
||||||
///
|
///
|
||||||
/// If the given client ID is valid, `true` is returned and the client is
|
/// If the given client ID is valid, the client's `ClientState` is returned
|
||||||
/// deleted. Otherwise, `false` is returned and the function has no effect.
|
/// and the client is deleted. Otherwise, `None` is returned and the
|
||||||
|
/// function has no effect.
|
||||||
pub fn remove(&mut self, client: ClientId) -> Option<C::ClientState> {
|
pub fn remove(&mut self, client: ClientId) -> Option<C::ClientState> {
|
||||||
self.slab.remove(client.0).map(|c| c.state)
|
self.slab.remove(client.0).map(|c| c.state)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Deletes all clients from the server for
|
/// Deletes all clients from the server for which `f` returns `true`.
|
||||||
/// which `f` returns `true`.
|
|
||||||
///
|
///
|
||||||
/// All clients are visited in an unspecified order.
|
/// All clients are visited in an unspecified order.
|
||||||
pub fn retain(&mut self, mut f: impl FnMut(ClientId, &mut Client<C>) -> bool) {
|
pub fn retain(&mut self, mut f: impl FnMut(ClientId, &mut Client<C>) -> bool) {
|
||||||
self.slab.retain(|k, v| f(ClientId(k), v))
|
self.slab.retain(|k, v| f(ClientId(k), v))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the number of clients on the server. This includes clients
|
/// Returns the number of clients on the server. This includes clients for
|
||||||
/// which may be disconnected.
|
/// which [`Client::is_disconnected`] returns true.
|
||||||
pub fn len(&self) -> usize {
|
pub fn len(&self) -> usize {
|
||||||
self.slab.len()
|
self.slab.len()
|
||||||
}
|
}
|
||||||
|
@ -102,8 +102,8 @@ impl<C: Config> Clients<C> {
|
||||||
self.slab.get_mut(client.0)
|
self.slab.get_mut(client.0)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns an immutable iterator over all clients on the server in an
|
/// Returns an iterator over all clients on the server in an unspecified
|
||||||
/// unspecified order.
|
/// order.
|
||||||
pub fn iter(
|
pub fn iter(
|
||||||
&self,
|
&self,
|
||||||
) -> impl ExactSizeIterator<Item = (ClientId, &Client<C>)> + FusedIterator + Clone + '_ {
|
) -> impl ExactSizeIterator<Item = (ClientId, &Client<C>)> + FusedIterator + Clone + '_ {
|
||||||
|
@ -118,8 +118,8 @@ impl<C: Config> Clients<C> {
|
||||||
self.slab.iter_mut().map(|(k, v)| (ClientId(k), v))
|
self.slab.iter_mut().map(|(k, v)| (ClientId(k), v))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a parallel immutable iterator over all clients on the server in
|
/// Returns a parallel iterator over all clients on the server in an
|
||||||
/// an unspecified order.
|
/// unspecified order.
|
||||||
pub fn par_iter(&self) -> impl ParallelIterator<Item = (ClientId, &Client<C>)> + Clone + '_ {
|
pub fn par_iter(&self) -> impl ParallelIterator<Item = (ClientId, &Client<C>)> + Clone + '_ {
|
||||||
self.slab.par_iter().map(|(k, v)| (ClientId(k), v))
|
self.slab.par_iter().map(|(k, v)| (ClientId(k), v))
|
||||||
}
|
}
|
||||||
|
@ -170,7 +170,9 @@ impl ClientId {
|
||||||
/// simply a subtype of the entity base class backed by a remote connection.
|
/// simply a subtype of the entity base class backed by a remote connection.
|
||||||
///
|
///
|
||||||
/// In Valence however, clients and players are decoupled. This separation
|
/// In Valence however, clients and players are decoupled. This separation
|
||||||
/// allows for greater flexibility and parallelism.
|
/// allows for greater flexibility and enables parallelism.
|
||||||
|
///
|
||||||
|
/// [`Entity`]: crate::entity::Entity
|
||||||
pub struct Client<C: Config> {
|
pub struct Client<C: Config> {
|
||||||
/// Custom state.
|
/// Custom state.
|
||||||
pub state: C::ClientState,
|
pub state: C::ClientState,
|
||||||
|
@ -301,7 +303,7 @@ impl<C: Config> Client<C> {
|
||||||
self.uuid
|
self.uuid
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Gets the username of this client, which is always valid.
|
/// Gets the username of this client.
|
||||||
pub fn username(&self) -> &str {
|
pub fn username(&self) -> &str {
|
||||||
&self.username
|
&self.username
|
||||||
}
|
}
|
||||||
|
@ -317,18 +319,22 @@ impl<C: Config> Client<C> {
|
||||||
self.world
|
self.world
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Gets the player list this client sees.
|
||||||
pub fn player_list(&self) -> Option<&PlayerListId> {
|
pub fn player_list(&self) -> Option<&PlayerListId> {
|
||||||
self.new_player_list.as_ref()
|
self.new_player_list.as_ref()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_player_list(&mut self, id: Option<PlayerListId>) -> Option<PlayerListId> {
|
/// Sets the player list this client sees.
|
||||||
mem::replace(&mut self.new_player_list, id)
|
///
|
||||||
|
/// The previous player list ID is returned.
|
||||||
|
pub fn set_player_list(&mut self, id: impl Into<Option<PlayerListId>>) -> Option<PlayerListId> {
|
||||||
|
mem::replace(&mut self.new_player_list, id.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sets if this client sees the world as superflat. Superflat worlds have
|
/// Sets if this client sees the world as superflat. Superflat worlds have
|
||||||
/// a horizon line lower than normal worlds.
|
/// a horizon line lower than normal worlds.
|
||||||
///
|
///
|
||||||
/// The player must be spawned for changes to take effect.
|
/// The player must be (re)spawned for changes to take effect.
|
||||||
pub fn set_flat(&mut self, flat: bool) {
|
pub fn set_flat(&mut self, flat: bool) {
|
||||||
self.bits.set_flat(flat);
|
self.bits.set_flat(flat);
|
||||||
}
|
}
|
||||||
|
@ -349,7 +355,8 @@ impl<C: Config> Client<C> {
|
||||||
self.bits.set_spawn(true);
|
self.bits.set_spawn(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sends a system message to the player which is visible in the chat.
|
/// Sends a system message to the player which is visible in the chat. The
|
||||||
|
/// message is only visible to this client.
|
||||||
pub fn send_message(&mut self, msg: impl Into<Text>) {
|
pub fn send_message(&mut self, msg: impl Into<Text>) {
|
||||||
// We buffer messages because weird things happen if we send them before the
|
// We buffer messages because weird things happen if we send them before the
|
||||||
// login packet.
|
// login packet.
|
||||||
|
@ -512,6 +519,8 @@ impl<C: Config> Client<C> {
|
||||||
self.send.is_none()
|
self.send.is_none()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns an iterator over all pending client events in the order they
|
||||||
|
/// will be removed from the queue.
|
||||||
pub fn events(
|
pub fn events(
|
||||||
&self,
|
&self,
|
||||||
) -> impl DoubleEndedIterator<Item = &ClientEvent> + ExactSizeIterator + FusedIterator + Clone + '_
|
) -> impl DoubleEndedIterator<Item = &ClientEvent> + ExactSizeIterator + FusedIterator + Clone + '_
|
||||||
|
@ -519,7 +528,7 @@ impl<C: Config> Client<C> {
|
||||||
self.events.iter()
|
self.events.iter()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Removes an [`Event`] from the event queue.
|
/// Removes a [`ClientEvent`] from the event queue.
|
||||||
///
|
///
|
||||||
/// If there are no remaining events, `None` is returned.
|
/// If there are no remaining events, `None` is returned.
|
||||||
///
|
///
|
||||||
|
@ -529,6 +538,7 @@ impl<C: Config> Client<C> {
|
||||||
self.events.pop_front()
|
self.events.pop_front()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Pushes an entity event to the queue.
|
||||||
pub fn push_entity_event(&mut self, event: EntityEvent) {
|
pub fn push_entity_event(&mut self, event: EntityEvent) {
|
||||||
self.entity_events.push(event);
|
self.entity_events.push(event);
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,12 +15,13 @@ use crate::{Ticks, STANDARD_TPS};
|
||||||
/// A trait for the configuration of a server.
|
/// A trait for the configuration of a server.
|
||||||
///
|
///
|
||||||
/// This trait uses the [async_trait] attribute macro. It is exported at the
|
/// This trait uses the [async_trait] attribute macro. It is exported at the
|
||||||
/// root of this crate.
|
/// root of this crate. async_trait will be removed once async fns in traits
|
||||||
|
/// are stabilized.
|
||||||
///
|
///
|
||||||
/// [async_trait]: https://docs.rs/async-trait/latest/async_trait/
|
/// [async_trait]: https://docs.rs/async-trait/latest/async_trait/
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
#[allow(unused_variables)]
|
#[allow(unused_variables)]
|
||||||
pub trait Config: 'static + Sized + Send + Sync + UnwindSafe + RefUnwindSafe {
|
pub trait Config: Sized + Send + Sync + UnwindSafe + RefUnwindSafe + 'static {
|
||||||
/// Custom state to store with the [`Server`].
|
/// Custom state to store with the [`Server`].
|
||||||
type ServerState: Send + Sync;
|
type ServerState: Send + Sync;
|
||||||
/// Custom state to store with every [`Client`](crate::client::Client).
|
/// Custom state to store with every [`Client`](crate::client::Client).
|
||||||
|
@ -93,22 +94,22 @@ pub trait Config: 'static + Sized + Send + Sync + UnwindSafe + RefUnwindSafe {
|
||||||
/// Called once at startup to get the capacity of the buffer used to
|
/// Called once at startup to get the capacity of the buffer used to
|
||||||
/// hold incoming packets.
|
/// hold incoming packets.
|
||||||
///
|
///
|
||||||
/// A larger capacity reduces the chance of packet loss but increases
|
/// A larger capacity reduces the chance that a client needs to be
|
||||||
/// potential memory usage.
|
/// disconnected due to a full buffer, but increases potential memory usage.
|
||||||
///
|
///
|
||||||
/// # Default Implementation
|
/// # Default Implementation
|
||||||
///
|
///
|
||||||
/// An unspecified value is returned that should be adequate in most
|
/// An unspecified value is returned that should be adequate in most
|
||||||
/// situations.
|
/// situations.
|
||||||
fn incoming_packet_capacity(&self) -> usize {
|
fn incoming_packet_capacity(&self) -> usize {
|
||||||
32
|
64
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Called once at startup to get the capacity of the buffer used to
|
/// Called once at startup to get the capacity of the buffer used to
|
||||||
/// hold outgoing packets.
|
/// hold outgoing packets.
|
||||||
///
|
///
|
||||||
/// A larger capacity reduces the chance of packet loss due to a full buffer
|
/// A larger capacity reduces the chance that a client needs to be
|
||||||
/// but increases potential memory usage.
|
/// disconnected due to a full buffer, but increases potential memory usage.
|
||||||
///
|
///
|
||||||
/// # Default Implementation
|
/// # Default Implementation
|
||||||
///
|
///
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
//! Dynamic actors in a world.
|
//! Entities in a world.
|
||||||
|
|
||||||
use std::collections::hash_map::Entry;
|
use std::collections::hash_map::Entry;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
@ -26,7 +26,7 @@ pub mod types;
|
||||||
|
|
||||||
include!(concat!(env!("OUT_DIR"), "/entity_event.rs"));
|
include!(concat!(env!("OUT_DIR"), "/entity_event.rs"));
|
||||||
|
|
||||||
/// A container for all [`Entity`]s on a [`Server`](crate::server::Server).
|
/// A container for all [`Entity`]s on a server.
|
||||||
///
|
///
|
||||||
/// # Spawning Player Entities
|
/// # Spawning Player Entities
|
||||||
///
|
///
|
||||||
|
@ -34,7 +34,7 @@ include!(concat!(env!("OUT_DIR"), "/entity_event.rs"));
|
||||||
/// entity to be visible to clients, the player's UUID must be added to the
|
/// entity to be visible to clients, the player's UUID must be added to the
|
||||||
/// [`PlayerList`] _before_ being loaded by the client.
|
/// [`PlayerList`] _before_ being loaded by the client.
|
||||||
///
|
///
|
||||||
/// [`Player`]: crate::entity::types::Player
|
/// [`Player`]: crate::entity::data::Player
|
||||||
/// [`PlayerList`]: crate::player_list::PlayerList
|
/// [`PlayerList`]: crate::player_list::PlayerList
|
||||||
pub struct Entities<C: Config> {
|
pub struct Entities<C: Config> {
|
||||||
slab: VersionedSlab<Entity<C>>,
|
slab: VersionedSlab<Entity<C>>,
|
||||||
|
@ -62,7 +62,7 @@ impl<C: Config> Entities<C> {
|
||||||
.expect("UUID collision")
|
.expect("UUID collision")
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Like [`Self::create`], but requires specifying the new
|
/// Like [`Self::insert`], but requires specifying the new
|
||||||
/// entity's UUID.
|
/// entity's UUID.
|
||||||
///
|
///
|
||||||
/// The provided UUID must not conflict with an existing entity UUID. If it
|
/// The provided UUID must not conflict with an existing entity UUID. If it
|
||||||
|
@ -103,8 +103,9 @@ impl<C: Config> Entities<C> {
|
||||||
|
|
||||||
/// Removes an entity from the server.
|
/// Removes an entity from the server.
|
||||||
///
|
///
|
||||||
/// If the given entity ID is valid, `true` is returned and the entity is
|
/// If the given entity ID is valid, the entity's `EntityState` is returned
|
||||||
/// deleted. Otherwise, `false` is returned and the function has no effect.
|
/// and the entity is deleted. Otherwise, `None` is returned and the
|
||||||
|
/// function has no effect.
|
||||||
pub fn remove(&mut self, entity: EntityId) -> Option<C::EntityState> {
|
pub fn remove(&mut self, entity: EntityId) -> Option<C::EntityState> {
|
||||||
self.slab.remove(entity.0).map(|e| {
|
self.slab.remove(entity.0).map(|e| {
|
||||||
self.uuid_to_entity
|
self.uuid_to_entity
|
||||||
|
@ -173,8 +174,8 @@ impl<C: Config> Entities<C> {
|
||||||
Some(EntityId(Key::new(index, version)))
|
Some(EntityId(Key::new(index, version)))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns an immutable iterator over all entities on the server in an
|
/// Returns an iterator over all entities on the server in an unspecified
|
||||||
/// unspecified order.
|
/// order.
|
||||||
pub fn iter(
|
pub fn iter(
|
||||||
&self,
|
&self,
|
||||||
) -> impl ExactSizeIterator<Item = (EntityId, &Entity<C>)> + FusedIterator + Clone + '_ {
|
) -> impl ExactSizeIterator<Item = (EntityId, &Entity<C>)> + FusedIterator + Clone + '_ {
|
||||||
|
@ -189,8 +190,8 @@ impl<C: Config> Entities<C> {
|
||||||
self.slab.iter_mut().map(|(k, v)| (EntityId(k), v))
|
self.slab.iter_mut().map(|(k, v)| (EntityId(k), v))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a parallel immutable iterator over all entities on the server in
|
/// Returns a parallel iterator over all entities on the server in an
|
||||||
/// an unspecified order.
|
/// unspecified order.
|
||||||
pub fn par_iter(&self) -> impl ParallelIterator<Item = (EntityId, &Entity<C>)> + Clone + '_ {
|
pub fn par_iter(&self) -> impl ParallelIterator<Item = (EntityId, &Entity<C>)> + Clone + '_ {
|
||||||
self.slab.par_iter().map(|(k, v)| (EntityId(k), v))
|
self.slab.par_iter().map(|(k, v)| (EntityId(k), v))
|
||||||
}
|
}
|
||||||
|
@ -239,7 +240,7 @@ impl EntityId {
|
||||||
|
|
||||||
/// Represents an entity on the server.
|
/// Represents an entity on the server.
|
||||||
///
|
///
|
||||||
/// In essence, an entity is anything in a world that isn't a block or client.
|
/// An entity is mostly anything in a world that isn't a block or client.
|
||||||
/// Entities include paintings, falling blocks, zombies, fireballs, and more.
|
/// Entities include paintings, falling blocks, zombies, fireballs, and more.
|
||||||
///
|
///
|
||||||
/// Every entity has common state which is accessible directly from
|
/// Every entity has common state which is accessible directly from
|
||||||
|
@ -277,10 +278,12 @@ impl<C: Config> Entity<C> {
|
||||||
self.bits
|
self.bits
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns a shared reference to this entity's tracked data.
|
||||||
pub fn data(&self) -> &TrackedData {
|
pub fn data(&self) -> &TrackedData {
|
||||||
&self.variants
|
&self.variants
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns an exclusive reference to this entity's tracked data.
|
||||||
pub fn data_mut(&mut self) -> &mut TrackedData {
|
pub fn data_mut(&mut self) -> &mut TrackedData {
|
||||||
&mut self.variants
|
&mut self.variants
|
||||||
}
|
}
|
||||||
|
@ -290,6 +293,7 @@ impl<C: Config> Entity<C> {
|
||||||
self.variants.kind()
|
self.variants.kind()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Triggers an entity event for this entity.
|
||||||
pub fn push_event(&mut self, event: EntityEvent) {
|
pub fn push_event(&mut self, event: EntityEvent) {
|
||||||
self.events.push(event);
|
self.events.push(event);
|
||||||
}
|
}
|
||||||
|
@ -411,7 +415,7 @@ impl<C: Config> Entity<C> {
|
||||||
/// The hitbox of an entity is determined by its position, entity type, and
|
/// The hitbox of an entity is determined by its position, entity type, and
|
||||||
/// other state specific to that type.
|
/// other state specific to that type.
|
||||||
///
|
///
|
||||||
/// [interact event]: crate::client::EntityEvent::InteractWithEntity
|
/// [interact event]: crate::client::ClientEvent::InteractWithEntity
|
||||||
pub fn hitbox(&self) -> Aabb<f64> {
|
pub fn hitbox(&self) -> Aabb<f64> {
|
||||||
let dims = match &self.variants {
|
let dims = match &self.variants {
|
||||||
TrackedData::Allay(_) => [0.6, 0.35, 0.6],
|
TrackedData::Allay(_) => [0.6, 0.35, 0.6],
|
||||||
|
|
16
src/ident.rs
16
src/ident.rs
|
@ -11,13 +11,14 @@ use thiserror::Error;
|
||||||
|
|
||||||
use crate::protocol::{encode_string_bounded, BoundedString, Decode, Encode};
|
use crate::protocol::{encode_string_bounded, BoundedString, Decode, Encode};
|
||||||
|
|
||||||
/// An identifier is a string split into a "namespace" part and a "name" part.
|
/// An identifier is a string split into a "namespace" part and a "path" part.
|
||||||
/// For instance `minecraft:apple` and `apple` are both valid identifiers.
|
/// For instance `minecraft:apple` and `apple` are both valid identifiers.
|
||||||
///
|
///
|
||||||
/// If the namespace part is left off (the part before and including the colon)
|
/// If the namespace part is left off (the part before and including the colon)
|
||||||
/// the namespace is considered to be "minecraft" for the purposes of equality.
|
/// the namespace is considered to be "minecraft" for the purposes of equality.
|
||||||
///
|
///
|
||||||
/// The identifier must match the regex `^([a-z0-9_-]+:)?[a-z0-9_\/.-]+$`.
|
/// A string must match the regex `^([a-z0-9_-]+:)?[a-z0-9_\/.-]+$` to be a
|
||||||
|
/// valid identifier.
|
||||||
#[derive(Clone, Eq)]
|
#[derive(Clone, Eq)]
|
||||||
pub struct Ident {
|
pub struct Ident {
|
||||||
ident: Cow<'static, AsciiStr>,
|
ident: Cow<'static, AsciiStr>,
|
||||||
|
@ -90,6 +91,7 @@ impl Ident {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the namespace part of this namespaced identifier.
|
/// Returns the namespace part of this namespaced identifier.
|
||||||
|
///
|
||||||
/// If this identifier was constructed from a string without a namespace,
|
/// If this identifier was constructed from a string without a namespace,
|
||||||
/// then `None` is returned.
|
/// then `None` is returned.
|
||||||
pub fn namespace(&self) -> Option<&str> {
|
pub fn namespace(&self) -> Option<&str> {
|
||||||
|
@ -100,8 +102,8 @@ impl Ident {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the name part of this namespaced identifier.
|
/// Returns the path part of this namespaced identifier.
|
||||||
pub fn name(&self) -> &str {
|
pub fn path(&self) -> &str {
|
||||||
if self.colon_idx == usize::MAX {
|
if self.colon_idx == usize::MAX {
|
||||||
self.ident.as_str()
|
self.ident.as_str()
|
||||||
} else {
|
} else {
|
||||||
|
@ -188,14 +190,14 @@ impl std::fmt::Display for Ident {
|
||||||
impl PartialEq for Ident {
|
impl PartialEq for Ident {
|
||||||
fn eq(&self, other: &Self) -> bool {
|
fn eq(&self, other: &Self) -> bool {
|
||||||
self.namespace().unwrap_or("minecraft") == other.namespace().unwrap_or("minecraft")
|
self.namespace().unwrap_or("minecraft") == other.namespace().unwrap_or("minecraft")
|
||||||
&& self.name() == other.name()
|
&& self.path() == other.path()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl std::hash::Hash for Ident {
|
impl std::hash::Hash for Ident {
|
||||||
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
|
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
|
||||||
self.namespace().unwrap_or("minecraft").hash(state);
|
self.namespace().unwrap_or("minecraft").hash(state);
|
||||||
self.name().hash(state);
|
self.path().hash(state);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -261,7 +263,7 @@ impl<'de> Visitor<'de> for IdentifierVisitor {
|
||||||
/// let apple = ident!("{namespace}:apple");
|
/// let apple = ident!("{namespace}:apple");
|
||||||
///
|
///
|
||||||
/// assert_eq!(apple.namespace(), Some("my_namespace"));
|
/// assert_eq!(apple.namespace(), Some("my_namespace"));
|
||||||
/// assert_eq!(apple.name(), "apple");
|
/// assert_eq!(apple.path(), "apple");
|
||||||
/// ```
|
/// ```
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! ident {
|
macro_rules! ident {
|
||||||
|
|
65
src/lib.rs
65
src/lib.rs
|
@ -1,21 +1,20 @@
|
||||||
//! A Rust framework for building Minecraft servers.
|
//! A Rust framework for building Minecraft servers.
|
||||||
//!
|
//!
|
||||||
//! Valence is a Rust library which provides the necessary abstractions over
|
|
||||||
//! Minecraft's protocol to build servers. Very few assumptions about the
|
|
||||||
//! desired server are made, which allows for greater flexibility in its design.
|
|
||||||
//!
|
|
||||||
//! At a high level, a Valence [`Server`] is a collection of [`Clients`],
|
//! At a high level, a Valence [`Server`] is a collection of [`Clients`],
|
||||||
//! [`Entities`], and [`Worlds`]. When a client connects to the server, they are
|
//! [`Entities`], and [`Worlds`]. When a client connects to the server they are
|
||||||
//! added to the server's [`Clients`]. After connecting, clients are assigned to
|
//! added to the collection of `Clients`. After connecting, clients should
|
||||||
//! a [`World`] where they are able to interact with the entities and
|
//! be assigned to a [`World`] where they can interact with the entities
|
||||||
//! [`Chunks`] that are a part of it.
|
//! and [`Chunks`] that are a part of it.
|
||||||
//!
|
//!
|
||||||
//! The Valence documentation assumes some familiarity with Minecraft and its
|
//! The Valence documentation assumes some familiarity with Minecraft and its
|
||||||
//! mechanics. See the [Minecraft Wiki] for general information and [wiki.vg]
|
//! mechanics. See the [Minecraft Wiki] for general information and [wiki.vg]
|
||||||
//! for protocol documentation.
|
//! for protocol documentation.
|
||||||
//!
|
//!
|
||||||
|
//! For more information, see the repository [README].
|
||||||
|
//!
|
||||||
//! [Minecraft Wiki]: https://minecraft.fandom.com/wiki/Minecraft_Wiki
|
//! [Minecraft Wiki]: https://minecraft.fandom.com/wiki/Minecraft_Wiki
|
||||||
//! [wiki.vg]: https://wiki.vg/Main_Page
|
//! [wiki.vg]: https://wiki.vg/Main_Page
|
||||||
|
//! [README]: https://github.com/rj00a/valence
|
||||||
//!
|
//!
|
||||||
//! # Logging
|
//! # Logging
|
||||||
//!
|
//!
|
||||||
|
@ -35,58 +34,16 @@
|
||||||
//! **You must not call [`mem::swap`] on these references (or any other
|
//! **You must not call [`mem::swap`] on these references (or any other
|
||||||
//! function that would move their location in memory).** Doing so breaks
|
//! function that would move their location in memory).** Doing so breaks
|
||||||
//! invariants within the library and the resulting behavior is safe but
|
//! invariants within the library and the resulting behavior is safe but
|
||||||
//! unspecified. These types should be considered [pinned](std::pin).
|
//! unspecified. You can think of these types as being [pinned](std::pin).
|
||||||
//!
|
//!
|
||||||
//! Preventing this illegal behavior using Rust's type system was considered too
|
//! Preventing this illegal behavior using Rust's type system was considered too
|
||||||
//! cumbersome, so a note has been left here instead.
|
//! cumbersome, so this note has been left here instead.
|
||||||
//!
|
//!
|
||||||
//! [`mem::swap`]: std::mem::swap
|
//! [`mem::swap`]: std::mem::swap
|
||||||
//!
|
//!
|
||||||
//! # Examples
|
//! # Examples
|
||||||
//!
|
//!
|
||||||
//! The following is a minimal server implementation. You should be able to
|
//! See the [examples] directory in the source repository.
|
||||||
//! connect to the server at `localhost`.
|
|
||||||
//!
|
|
||||||
//! ```
|
|
||||||
//! use valence::config::Config;
|
|
||||||
//! use valence::server::{Server, ShutdownResult};
|
|
||||||
//!
|
|
||||||
//! pub fn main() -> ShutdownResult {
|
|
||||||
//! valence::start_server(Game, ())
|
|
||||||
//! }
|
|
||||||
//!
|
|
||||||
//! struct Game;
|
|
||||||
//!
|
|
||||||
//! impl Config for Game {
|
|
||||||
//! type ServerState = ();
|
|
||||||
//! type ClientState = ();
|
|
||||||
//! type EntityState = ();
|
|
||||||
//! type WorldState = ();
|
|
||||||
//! type ChunkState = ();
|
|
||||||
//!
|
|
||||||
//! fn max_connections(&self) -> usize {
|
|
||||||
//! 256
|
|
||||||
//! }
|
|
||||||
//!
|
|
||||||
//! fn update(&self, server: &mut Server<Self>) {
|
|
||||||
//! server.clients.retain(|_, client| {
|
|
||||||
//! if client.created_tick() == server.shared.current_tick() {
|
|
||||||
//! println!("{} joined!", client.username());
|
|
||||||
//! }
|
|
||||||
//!
|
|
||||||
//! if client.is_disconnected() {
|
|
||||||
//! println!("{} left!", client.username());
|
|
||||||
//! false
|
|
||||||
//! } else {
|
|
||||||
//! true
|
|
||||||
//! }
|
|
||||||
//! });
|
|
||||||
//! # server.shared.shutdown::<_, std::convert::Infallible>(Ok(()));
|
|
||||||
//! }
|
|
||||||
//! }
|
|
||||||
//! ```
|
|
||||||
//!
|
|
||||||
//! For more complete examples, see the [examples] in the source repository.
|
|
||||||
//!
|
//!
|
||||||
//! [examples]: https://github.com/rj00a/valence/tree/main/examples
|
//! [examples]: https://github.com/rj00a/valence/tree/main/examples
|
||||||
//!
|
//!
|
||||||
|
@ -122,7 +79,7 @@ pub use async_trait::async_trait;
|
||||||
#[doc(inline)]
|
#[doc(inline)]
|
||||||
pub use server::start_server;
|
pub use server::start_server;
|
||||||
#[doc(inline)]
|
#[doc(inline)]
|
||||||
pub use {uuid, valence_nbt as nbt, vek};
|
pub use {serde_nbt as nbt, uuid, vek};
|
||||||
|
|
||||||
pub mod biome;
|
pub mod biome;
|
||||||
pub mod block;
|
pub mod block;
|
||||||
|
|
|
@ -17,10 +17,19 @@ use crate::protocol::VarInt;
|
||||||
use crate::slab_rc::{Key, SlabRc};
|
use crate::slab_rc::{Key, SlabRc};
|
||||||
use crate::text::Text;
|
use crate::text::Text;
|
||||||
|
|
||||||
|
/// A container for all [`PlayerList`]s on a server.
|
||||||
pub struct PlayerLists<C: Config> {
|
pub struct PlayerLists<C: Config> {
|
||||||
slab: SlabRc<PlayerList<C>>,
|
slab: SlabRc<PlayerList<C>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// An identifier for a [`PlayerList`] on the server.
|
||||||
|
///
|
||||||
|
/// Player list IDs are refcounted. Once all IDs referring to the same player
|
||||||
|
/// list are dropped, the player list is automatically deleted.
|
||||||
|
///
|
||||||
|
/// 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, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
|
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
|
||||||
pub struct PlayerListId(Key);
|
pub struct PlayerListId(Key);
|
||||||
|
|
||||||
|
@ -31,6 +40,7 @@ impl<C: Config> PlayerLists<C> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
pub fn insert(&mut self, state: C::PlayerListState) -> (PlayerListId, &mut PlayerList<C>) {
|
pub fn insert(&mut self, state: C::PlayerListState) -> (PlayerListId, &mut PlayerList<C>) {
|
||||||
let (key, pl) = self.slab.insert(PlayerList {
|
let (key, pl) = self.slab.insert(PlayerList {
|
||||||
state,
|
state,
|
||||||
|
@ -199,8 +209,7 @@ impl<C: Config> PlayerList<C> {
|
||||||
self.entries.iter().map(|(k, v)| (*k, v))
|
self.entries.iter().map(|(k, v)| (*k, v))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns an iterator which allows modifications over all entries. The
|
/// Returns a mutable iterator over all entries in an unspecified order.
|
||||||
/// entries are visited in an unspecified order.
|
|
||||||
pub fn entries_mut(&mut self) -> impl Iterator<Item = (Uuid, &mut PlayerListEntry)> + '_ {
|
pub fn entries_mut(&mut self) -> impl Iterator<Item = (Uuid, &mut PlayerListEntry)> + '_ {
|
||||||
self.entries.iter_mut().map(|(k, v)| (*k, v))
|
self.entries.iter_mut().map(|(k, v)| (*k, v))
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
//! Provides low-level access to the Minecraft protocol.
|
//! Provides low-level access to the Minecraft protocol.
|
||||||
//!
|
//!
|
||||||
//! Hopefully you will not need to use this module.
|
//! You should avoid this module if possible.
|
||||||
|
|
||||||
use std::io::{Read, Write};
|
use std::io::{Read, Write};
|
||||||
use std::mem;
|
use std::mem;
|
||||||
|
|
|
@ -49,9 +49,6 @@ pub trait DecodePacket: Sized + fmt::Debug {
|
||||||
///
|
///
|
||||||
/// The fields of the struct are encoded and decoded in the order they are
|
/// The fields of the struct are encoded and decoded in the order they are
|
||||||
/// defined.
|
/// defined.
|
||||||
///
|
|
||||||
/// If a packet ID is provided after the struct name, then this struct will
|
|
||||||
/// implement [`EncodePacket`] and [`DecodePacket`].
|
|
||||||
macro_rules! def_struct {
|
macro_rules! def_struct {
|
||||||
(
|
(
|
||||||
$(#[$struct_attrs:meta])*
|
$(#[$struct_attrs:meta])*
|
||||||
|
@ -110,9 +107,6 @@ macro_rules! def_struct {
|
||||||
///
|
///
|
||||||
/// The enum tag is encoded and decoded first, followed by the appropriate
|
/// The enum tag is encoded and decoded first, followed by the appropriate
|
||||||
/// variant.
|
/// variant.
|
||||||
///
|
|
||||||
/// If a packet ID is provided after the struct name, then this struct will
|
|
||||||
/// implement [`EncodePacket`] and [`DecodePacket`].
|
|
||||||
macro_rules! def_enum {
|
macro_rules! def_enum {
|
||||||
(
|
(
|
||||||
$(#[$enum_attrs:meta])*
|
$(#[$enum_attrs:meta])*
|
||||||
|
@ -195,6 +189,7 @@ macro_rules! if_typ_is_empty_pat {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Defines a bitfield struct which implements [`Encode`] and [`Decode`].
|
||||||
macro_rules! def_bitfield {
|
macro_rules! def_bitfield {
|
||||||
(
|
(
|
||||||
$(#[$struct_attrs:meta])*
|
$(#[$struct_attrs:meta])*
|
||||||
|
@ -273,6 +268,10 @@ macro_rules! def_bitfield {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Defines an enum of packets.
|
||||||
|
///
|
||||||
|
/// An impl for [`EncodePacket`] and [`DecodePacket`] is defined for each
|
||||||
|
/// supplied packet.
|
||||||
macro_rules! def_packet_group {
|
macro_rules! def_packet_group {
|
||||||
(
|
(
|
||||||
$(#[$attrs:meta])*
|
$(#[$attrs:meta])*
|
||||||
|
|
|
@ -36,9 +36,7 @@ use crate::player_list::PlayerLists;
|
||||||
use crate::player_textures::SignedPlayerTextures;
|
use crate::player_textures::SignedPlayerTextures;
|
||||||
use crate::protocol::codec::{Decoder, Encoder};
|
use crate::protocol::codec::{Decoder, Encoder};
|
||||||
use crate::protocol::packets::c2s::handshake::{Handshake, HandshakeNextState};
|
use crate::protocol::packets::c2s::handshake::{Handshake, HandshakeNextState};
|
||||||
use crate::protocol::packets::c2s::login::{
|
use crate::protocol::packets::c2s::login::{EncryptionResponse, LoginStart, VerifyTokenOrMsgSig};
|
||||||
EncryptionResponse, LoginStart, VerifyTokenOrMsgSig,
|
|
||||||
};
|
|
||||||
use crate::protocol::packets::c2s::play::C2sPlayPacket;
|
use crate::protocol::packets::c2s::play::C2sPlayPacket;
|
||||||
use crate::protocol::packets::c2s::status::{QueryPing, QueryRequest};
|
use crate::protocol::packets::c2s::status::{QueryPing, QueryRequest};
|
||||||
use crate::protocol::packets::s2c::login::{
|
use crate::protocol::packets::s2c::login::{
|
||||||
|
@ -59,13 +57,13 @@ pub struct Server<C: Config> {
|
||||||
pub state: C::ServerState,
|
pub state: C::ServerState,
|
||||||
/// A handle to this server's [`SharedServer`].
|
/// A handle to this server's [`SharedServer`].
|
||||||
pub shared: SharedServer<C>,
|
pub shared: SharedServer<C>,
|
||||||
/// All of the clients in the server.
|
/// All of the clients on the server.
|
||||||
pub clients: Clients<C>,
|
pub clients: Clients<C>,
|
||||||
/// All of entities in the server.
|
/// All of entities on the server.
|
||||||
pub entities: Entities<C>,
|
pub entities: Entities<C>,
|
||||||
/// All of the worlds in the server.
|
/// All of the worlds on the server.
|
||||||
pub worlds: Worlds<C>,
|
pub worlds: Worlds<C>,
|
||||||
/// All of the player lists in the server.
|
/// All of the player lists on the server.
|
||||||
pub player_lists: PlayerLists<C>,
|
pub player_lists: PlayerLists<C>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -221,6 +219,10 @@ impl<C: Config> SharedServer<C> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Obtains a [`Biome`] by using its corresponding [`BiomeId`].
|
/// Obtains a [`Biome`] by using its corresponding [`BiomeId`].
|
||||||
|
///
|
||||||
|
/// It is safe but unspecified behavior to call this function using a
|
||||||
|
/// [`BiomeId`] not originating from the configuration used to construct
|
||||||
|
/// the server.
|
||||||
pub fn biome(&self, id: BiomeId) -> &Biome {
|
pub fn biome(&self, id: BiomeId) -> &Biome {
|
||||||
self.0.biomes.get(id.0 as usize).expect("invalid biome ID")
|
self.0.biomes.get(id.0 as usize).expect("invalid biome ID")
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,7 @@ use crate::world::WorldId;
|
||||||
///
|
///
|
||||||
/// The spatial index is only updated at the end of each tick. Any modification
|
/// The spatial index is only updated at the end of each tick. Any modification
|
||||||
/// to an entity that would change its hitbox is not reflected in the spatial
|
/// to an entity that would change its hitbox is not reflected in the spatial
|
||||||
/// index until the end of the tick.
|
/// index until the next tick.
|
||||||
///
|
///
|
||||||
/// [hitboxes]: crate::entity::Entity::hitbox
|
/// [hitboxes]: crate::entity::Entity::hitbox
|
||||||
pub struct SpatialIndex {
|
pub struct SpatialIndex {
|
||||||
|
@ -28,9 +28,9 @@ impl SpatialIndex {
|
||||||
Self { bvh: Bvh::new() }
|
Self { bvh: Bvh::new() }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// This is for tests only! Not part of the public API.
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
#[deprecated = "This is for documentation tests only!"]
|
pub fn test_new() -> Self {
|
||||||
pub fn example_new() -> Self {
|
|
||||||
dbg!("Don't call me from outside tests!");
|
dbg!("Don't call me from outside tests!");
|
||||||
Self::new()
|
Self::new()
|
||||||
}
|
}
|
||||||
|
@ -50,8 +50,7 @@ impl SpatialIndex {
|
||||||
/// Visit all entities intersecting a 10x10x10 cube centered at the origin.
|
/// Visit all entities intersecting a 10x10x10 cube centered at the origin.
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// # #[allow(deprecated)]
|
/// # let si = valence::spatial_index::SpatialIndex::test_new();
|
||||||
/// # let si = valence::spatial_index::SpatialIndex::example_new();
|
|
||||||
/// use valence::vek::*;
|
/// use valence::vek::*;
|
||||||
///
|
///
|
||||||
/// let cube = Aabb {
|
/// let cube = Aabb {
|
||||||
|
@ -104,9 +103,9 @@ impl SpatialIndex {
|
||||||
/// Casts a ray defined by `origin` and `direction` through entity hitboxes
|
/// Casts a ray defined by `origin` and `direction` through entity hitboxes
|
||||||
/// and returns the closest intersection for which `f` returns `true`.
|
/// and returns the closest intersection for which `f` returns `true`.
|
||||||
///
|
///
|
||||||
/// `f` is a predicate which can be used to filter intersections. For
|
/// `f` is a predicate used to filter intersections. For instance, if a ray
|
||||||
/// instance, if a ray is shot from a player's eye position, you probably
|
/// is shot from a player's eye position, you probably don't want the
|
||||||
/// don't want the ray to intersect with the player's own hitbox.
|
/// ray to intersect with the player's own hitbox.
|
||||||
///
|
///
|
||||||
/// If no intersections are found or if `f` never returns `true` then `None`
|
/// If no intersections are found or if `f` never returns `true` then `None`
|
||||||
/// is returned. Additionally, the given ray direction must be
|
/// is returned. Additionally, the given ray direction must be
|
||||||
|
@ -115,8 +114,7 @@ impl SpatialIndex {
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// # #[allow(deprecated)]
|
/// # let si = valence::spatial_index::SpatialIndex::test_new();
|
||||||
/// # let si = valence::spatial_index::SpatialIndex::example_new();
|
|
||||||
/// use valence::vek::*;
|
/// use valence::vek::*;
|
||||||
///
|
///
|
||||||
/// let origin = Vec3::new(0.0, 0.0, 0.0);
|
/// let origin = Vec3::new(0.0, 0.0, 0.0);
|
||||||
|
|
|
@ -17,7 +17,7 @@ use crate::protocol::{BoundedString, Decode, Encode};
|
||||||
///
|
///
|
||||||
/// For more information, see the relevant [Minecraft Wiki article].
|
/// For more information, see the relevant [Minecraft Wiki article].
|
||||||
///
|
///
|
||||||
/// Note that the current `Deserialize` implementation on this type recognizes
|
/// Note that the current [`Deserialize`] implementation on this type recognizes
|
||||||
/// only a subset of the full JSON chat component format.
|
/// only a subset of the full JSON chat component format.
|
||||||
///
|
///
|
||||||
/// [Minecraft Wiki article]: https://minecraft.fandom.com/wiki/Raw_JSON_text_format
|
/// [Minecraft Wiki article]: https://minecraft.fandom.com/wiki/Raw_JSON_text_format
|
||||||
|
|
20
src/world.rs
20
src/world.rs
|
@ -57,15 +57,17 @@ impl<C: Config> Worlds<C> {
|
||||||
|
|
||||||
/// Deletes a world from the server.
|
/// Deletes a world from the server.
|
||||||
///
|
///
|
||||||
/// Note that entities located in the world are not deleted themselves.
|
/// Note that any entities located in the world are not deleted.
|
||||||
/// Additionally, any clients that are still in the deleted world at the end
|
/// Additionally, clients that are still in the deleted world at the end
|
||||||
/// of the tick are disconnected.
|
/// 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 {
|
pub fn remove(&mut self, world: WorldId) -> bool {
|
||||||
self.slab.remove(world.0).is_some()
|
self.slab.remove(world.0).is_some()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Deletes all worlds from the server (as if by [`Self::delete`]) for which
|
/// Removes all worlds from the server for which `f` returns `true`.
|
||||||
/// `f` returns `true`.
|
|
||||||
///
|
///
|
||||||
/// All worlds are visited in an unspecified order.
|
/// All worlds are visited in an unspecified order.
|
||||||
pub fn retain(&mut self, mut f: impl FnMut(WorldId, &mut World<C>) -> bool) {
|
pub fn retain(&mut self, mut f: impl FnMut(WorldId, &mut World<C>) -> bool) {
|
||||||
|
@ -89,8 +91,8 @@ impl<C: Config> Worlds<C> {
|
||||||
self.slab.get_mut(world.0)
|
self.slab.get_mut(world.0)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns an immutable iterator over all worlds on the server in an
|
/// Returns an iterator over all worlds on the server in an unspecified
|
||||||
/// unspecified order.
|
/// order.
|
||||||
pub fn iter(
|
pub fn iter(
|
||||||
&self,
|
&self,
|
||||||
) -> impl ExactSizeIterator<Item = (WorldId, &World<C>)> + FusedIterator + Clone + '_ {
|
) -> impl ExactSizeIterator<Item = (WorldId, &World<C>)> + FusedIterator + Clone + '_ {
|
||||||
|
@ -105,8 +107,8 @@ impl<C: Config> Worlds<C> {
|
||||||
self.slab.iter_mut().map(|(k, v)| (WorldId(k), v))
|
self.slab.iter_mut().map(|(k, v)| (WorldId(k), v))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a parallel immutable iterator over all worlds on the server in
|
/// Returns a parallel iterator over all worlds on the server in an
|
||||||
/// an unspecified order.
|
/// unspecified order.
|
||||||
pub fn par_iter(&self) -> impl ParallelIterator<Item = (WorldId, &World<C>)> + Clone + '_ {
|
pub fn par_iter(&self) -> impl ParallelIterator<Item = (WorldId, &World<C>)> + Clone + '_ {
|
||||||
self.slab.par_iter().map(|(k, v)| (WorldId(k), v))
|
self.slab.par_iter().map(|(k, v)| (WorldId(k), v))
|
||||||
}
|
}
|
||||||
|
@ -130,7 +132,7 @@ pub struct World<C: Config> {
|
||||||
pub meta: WorldMeta,
|
pub meta: WorldMeta,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Contains miscellaneous world state.
|
/// Contains miscellaneous data about the world.
|
||||||
pub struct WorldMeta {
|
pub struct WorldMeta {
|
||||||
dimension: DimensionId,
|
dimension: DimensionId,
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue