Clean up docs and fix clippy issues

This commit is contained in:
Ryan 2022-07-14 23:18:20 -07:00
parent c5f0f6024c
commit 4b83801066
21 changed files with 113 additions and 55 deletions

View file

@ -2160,7 +2160,7 @@ pub fn build() -> anyhow::Result<()> {
let mut all_classes = BTreeMap::new(); let mut all_classes = BTreeMap::new();
for mut class in entities.iter().cloned() { for mut class in entities.iter().cloned() {
while let None = all_classes.insert(class.name, class) { while all_classes.insert(class.name, class).is_none() {
match class.inherit { match class.inherit {
Some(parent) => class = parent, Some(parent) => class = parent,
None => break, None => break,
@ -2227,8 +2227,8 @@ pub fn build() -> anyhow::Result<()> {
.enumerate() .enumerate()
.map(|(field_offset, field)| { .map(|(field_offset, field)| {
let name = ident(field.name.to_snake_case()); let name = ident(field.name.to_snake_case());
let getter_name = ident(format!("get_{}", name.to_string())); let getter_name = ident(format!("get_{name}"));
let setter_name = ident(format!("set_{}", name.to_string())); let setter_name = ident(format!("set_{name}"));
let field_offset = field_offset as u32; let field_offset = field_offset as u32;
@ -2254,8 +2254,8 @@ pub fn build() -> anyhow::Result<()> {
.map(|bf| { .map(|bf| {
let bit_name = ident(bf.name.to_snake_case()); let bit_name = ident(bf.name.to_snake_case());
let getter_name = ident(format!("get_{}", bit_name.to_string())); let getter_name = ident(format!("get_{bit_name}"));
let setter_name = ident(format!("set_{}", bit_name.to_string())); let setter_name = ident(format!("set_{bit_name}"));
let offset = bf.offset; let offset = bf.offset;

View file

@ -149,6 +149,7 @@ impl Config for Game {
// TODO: hardcoded eye pos. // TODO: hardcoded eye pos.
let eye_pos = Vec3::new(player_pos.x, player_pos.y + 1.6, player_pos.z); let eye_pos = Vec3::new(player_pos.x, player_pos.y + 1.6, player_pos.z);
#[allow(clippy::significant_drop_in_scrutinee)]
for (cow_id, p) in cows.iter().cloned().zip(fibonacci_spiral(cow_count)) { for (cow_id, p) in cows.iter().cloned().zip(fibonacci_spiral(cow_count)) {
let cow = server.entities.get_mut(cow_id).expect("missing cow"); let cow = server.entities.get_mut(cow_id).expect("missing cow");
let rotated = p * rot; let rotated = p * rot;

View file

@ -1,4 +1,4 @@
//! Biome definitions. //! Biome configuration and identification.
use crate::ident; use crate::ident;
use crate::ident::Ident; use crate::ident::Ident;

View file

@ -1,3 +1,5 @@
//! Blocks and related types.
#![allow(clippy::all, missing_docs)] #![allow(clippy::all, missing_docs)]
use std::fmt::{self, Display}; use std::fmt::{self, Display};

View file

@ -1,3 +1,5 @@
//! Chunks and related types.
// TODO: https://github.com/rust-lang/rust/issues/88581 for div_ceil // TODO: https://github.com/rust-lang/rust/issues/88581 for div_ceil
use std::collections::hash_map::Entry; use std::collections::hash_map::Entry;

View file

@ -28,9 +28,9 @@ impl From<(i32, i32)> for ChunkPos {
} }
} }
impl Into<(i32, i32)> for ChunkPos { impl From<ChunkPos> for (i32, i32) {
fn into(self) -> (i32, i32) { fn from(pos: ChunkPos) -> Self {
(self.x, self.z) (pos.x, pos.z)
} }
} }
@ -40,9 +40,9 @@ impl From<[i32; 2]> for ChunkPos {
} }
} }
impl Into<[i32; 2]> for ChunkPos { impl From<ChunkPos> for [i32; 2] {
fn into(self) -> [i32; 2] { fn from(pos: ChunkPos) -> Self {
[self.x, self.z] [pos.x, pos.z]
} }
} }

View file

@ -1,3 +1,5 @@
//! Connections to the server after logging in.
/// Contains the [`Event`] enum and related data types. /// Contains the [`Event`] enum and related data types.
mod event; mod event;
use std::collections::{HashSet, VecDeque}; use std::collections::{HashSet, VecDeque};
@ -118,7 +120,7 @@ impl Clients {
} }
} }
/// A key for a [`Client`] on the server. /// An identifier for a [`Client`] on the server.
/// ///
/// Client IDs are either _valid_ or _invalid_. Valid client IDs point to /// Client IDs are either _valid_ or _invalid_. Valid client IDs point to
/// clients that have not been deleted, while invalid IDs point to those that /// clients that have not been deleted, while invalid IDs point to those that
@ -138,8 +140,8 @@ impl ClientId {
/// Represents a remote connection to a client after successfully logging in. /// Represents a remote connection to a client after successfully logging in.
/// ///
/// Much like an [`Entity`], clients posess a location, rotation, and UUID. /// Much like an [`Entity`], clients posess a location, rotation, and UUID.
/// Clients are handled separately from entities and are partially /// However, clients are handled separately from entities and are partially
/// controlled by the library. /// managed by the library.
/// ///
/// By default, clients have no influence over the worlds they reside in. They /// By default, clients have no influence over the worlds they reside in. They
/// cannot break blocks, hurt entities, or see other clients. Interactions with /// cannot break blocks, hurt entities, or see other clients. Interactions with
@ -475,9 +477,11 @@ impl Client {
self.send.is_none() self.send.is_none()
} }
/// Removes an [`Event`] from the queue. /// Removes an [`Event`] from the event queue.
/// ///
/// Any remaining client events not popped are deleted at the end of the /// If there are no remaining events, `None` is returned.
///
/// Any remaining client events are deleted at the end of the
/// current tick. /// current tick.
pub fn pop_event(&mut self) -> Option<Event> { pub fn pop_event(&mut self) -> Option<Event> {
self.events.pop_front() self.events.pop_front()
@ -629,7 +633,6 @@ impl Client {
self.username() self.username()
); );
self.disconnect_no_reason(); self.disconnect_no_reason();
return;
} }
} }
C2sPlayPacket::BlockEntityTagQuery(_) => {} C2sPlayPacket::BlockEntityTagQuery(_) => {}

View file

@ -1,3 +1,5 @@
//! Configuration for the server.
use std::any::Any; use std::any::Any;
use std::net::{Ipv4Addr, SocketAddr, SocketAddrV4}; use std::net::{Ipv4Addr, SocketAddr, SocketAddrV4};
use std::panic::{RefUnwindSafe, UnwindSafe}; use std::panic::{RefUnwindSafe, UnwindSafe};

View file

@ -1,3 +1,5 @@
//! Dimension configuration and identification.
use crate::ident; use crate::ident;
use crate::protocol_inner::packets::play::s2c::DimensionType; use crate::protocol_inner::packets::play::s2c::DimensionType;

View file

@ -1,3 +1,5 @@
//! Dynamic actors in a world.
pub mod data; pub mod data;
pub mod types; pub mod types;
@ -198,7 +200,7 @@ impl Entities {
} }
} }
/// A key for an [`Entity`] on the server. /// An identifier for an [`Entity`] on the server.
/// ///
/// Entity IDs are either _valid_ or _invalid_. Valid entity IDs point to /// Entity IDs are either _valid_ or _invalid_. Valid entity IDs point to
/// entities that have not been deleted, while invalid IDs point to those that /// entities that have not been deleted, while invalid IDs point to those that
@ -554,20 +556,20 @@ impl Entity {
match &self.data { match &self.data {
EntityData::Marker(_) => None, EntityData::Marker(_) => None,
EntityData::ExperienceOrb(_) => { EntityData::ExperienceOrb(_) => {
Some(EntitySpawnPacket::SpawnExperienceOrb(AddExperienceOrb { Some(EntitySpawnPacket::ExperienceOrb(AddExperienceOrb {
entity_id: VarInt(this_id.to_network_id()), entity_id: VarInt(this_id.to_network_id()),
position: self.new_position, position: self.new_position,
count: 0, // TODO count: 0, // TODO
})) }))
} }
EntityData::Player(_) => Some(EntitySpawnPacket::SpawnPlayer(AddPlayer { EntityData::Player(_) => Some(EntitySpawnPacket::Player(AddPlayer {
entity_id: VarInt(this_id.to_network_id()), entity_id: VarInt(this_id.to_network_id()),
player_uuid: self.uuid, player_uuid: self.uuid,
position: self.new_position, position: self.new_position,
yaw: ByteAngle::from_degrees(self.yaw), yaw: ByteAngle::from_degrees(self.yaw),
pitch: ByteAngle::from_degrees(self.pitch), pitch: ByteAngle::from_degrees(self.pitch),
})), })),
_ => Some(EntitySpawnPacket::SpawnEntity(AddEntity { _ => Some(EntitySpawnPacket::Entity(AddEntity {
entity_id: VarInt(this_id.to_network_id()), entity_id: VarInt(this_id.to_network_id()),
object_uuid: self.uuid, object_uuid: self.uuid,
kind: VarInt(self.kind() as i32), kind: VarInt(self.kind() as i32),
@ -588,17 +590,17 @@ pub(crate) fn velocity_to_packet_units(vel: Vec3<f32>) -> Vec3<i16> {
} }
pub(crate) enum EntitySpawnPacket { pub(crate) enum EntitySpawnPacket {
SpawnEntity(AddEntity), Entity(AddEntity),
SpawnExperienceOrb(AddExperienceOrb), ExperienceOrb(AddExperienceOrb),
SpawnPlayer(AddPlayer), Player(AddPlayer),
} }
impl From<EntitySpawnPacket> for S2cPlayPacket { impl From<EntitySpawnPacket> for S2cPlayPacket {
fn from(pkt: EntitySpawnPacket) -> Self { fn from(pkt: EntitySpawnPacket) -> Self {
match pkt { match pkt {
EntitySpawnPacket::SpawnEntity(pkt) => pkt.into(), EntitySpawnPacket::Entity(pkt) => pkt.into(),
EntitySpawnPacket::SpawnExperienceOrb(pkt) => pkt.into(), EntitySpawnPacket::ExperienceOrb(pkt) => pkt.into(),
EntitySpawnPacket::SpawnPlayer(pkt) => pkt.into(), EntitySpawnPacket::Player(pkt) => pkt.into(),
} }
} }
} }

View file

@ -1,3 +1,5 @@
//! Namespaced identifiers.
use std::borrow::Cow; use std::borrow::Cow;
use std::io::{Read, Write}; use std::io::{Read, Write};
use std::str::FromStr; use std::str::FromStr;
@ -27,7 +29,9 @@ pub struct Ident {
colon_idx: usize, colon_idx: usize,
} }
#[derive(Clone, Error, PartialEq, Eq, Debug)] /// The error type which is created when an [`Ident`] cannot be parsed from a
/// string.
#[derive(Clone, Debug, Error)]
#[error("invalid identifier \"{src}\"")] #[error("invalid identifier \"{src}\"")]
pub struct ParseError { pub struct ParseError {
src: Cow<'static, str>, src: Cow<'static, str>,
@ -36,8 +40,7 @@ pub struct ParseError {
impl Ident { impl Ident {
/// Parses a new identifier from a string. /// Parses a new identifier from a string.
/// ///
/// The string must match the regex `([a-z0-9_-]+:)?[a-z0-9_\/.-]+`. /// An error is returned if the string is not a valid identifier.
/// If not, an error is returned.
pub fn new(str: impl Into<Cow<'static, str>>) -> Result<Ident, ParseError> { pub fn new(str: impl Into<Cow<'static, str>>) -> Result<Ident, ParseError> {
#![allow(bindings_with_variant_name)] #![allow(bindings_with_variant_name)]
@ -106,7 +109,7 @@ impl Ident {
} }
} }
/// Returns the identifier as a `str`. /// Returns the original string as a `str`.
pub fn as_str(&self) -> &str { pub fn as_str(&self) -> &str {
self.ident.as_str() self.ident.as_str()
} }
@ -120,6 +123,7 @@ fn ascii_cow_to_str_cow(cow: Cow<AsciiStr>) -> Cow<str> {
} }
impl ParseError { impl ParseError {
/// Gets the string that caused the parse error.
pub fn into_source(self) -> Cow<'static, str> { pub fn into_source(self) -> Cow<'static, str> {
self.src self.src
} }

View file

@ -1,4 +1,4 @@
//! A Rust framework for building efficient Minecraft servers. //! A Rust framework for building Minecraft servers.
//! //!
//! Valence is a Rust library which provides the necessary abstractions over //! Valence is a Rust library which provides the necessary abstractions over
//! Minecraft's protocol to build servers. Very few assumptions about the //! Minecraft's protocol to build servers. Very few assumptions about the
@ -34,8 +34,8 @@
//! //!
//! **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 unspecified. //! invariants within the library and the resulting behavior is safe but
//! These types should be considered pinned in memory. //! unspecified. These types should be considered [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 a note has been left here instead.
@ -107,6 +107,11 @@
unused_lifetimes, unused_lifetimes,
unused_import_braces unused_import_braces
)] )]
#![allow(
clippy::derive_partial_eq_without_eq,
clippy::unusual_byte_groupings,
clippy::comparison_chain
)]
pub mod biome; pub mod biome;
pub mod block; pub mod block;
@ -130,13 +135,21 @@ pub mod text;
pub mod util; pub mod util;
pub mod world; pub mod world;
/// Provides low-level access to the Minecraft protocol.
#[cfg(feature = "protocol")] #[cfg(feature = "protocol")]
pub mod protocol { pub mod protocol {
pub use crate::protocol_inner::*; pub use crate::protocol_inner::*;
} }
/// Used on [`Config`](config::Config) to allow for async methods in traits.
///
/// For more information see the [async_trait] crate.
///
/// [async_trait]: https://docs.rs/async-trait/latest/async_trait/
pub use async_trait::async_trait; pub use async_trait::async_trait;
#[doc(inline)]
pub use server::start_server; pub use server::start_server;
#[doc(inline)]
pub use {nbt, uuid, vek}; pub use {nbt, uuid, vek};
/// The Minecraft protocol version this library currently targets. /// The Minecraft protocol version this library currently targets.
@ -157,7 +170,3 @@ const LIBRARY_NAMESPACE: &str = "valence";
/// The duration of a game update depends on the current configuration, which /// The duration of a game update depends on the current configuration, which
/// may or may not be the same as Minecraft's standard 20 ticks/second. /// may or may not be the same as Minecraft's standard 20 ticks/second.
pub type Ticks = i64; pub type Ticks = i64;
/// Whatever dude
#[cfg(feature = "whatever")]
pub type Whatever = i64;

View file

@ -1,3 +1,5 @@
//! The player list (tab list).
use std::collections::hash_map::Entry; use std::collections::hash_map::Entry;
use std::collections::{HashMap, HashSet}; use std::collections::{HashMap, HashSet};
@ -297,6 +299,7 @@ impl PlayerListEntry {
&self.username &self.username
} }
/// Gets the player textures for this entry.
pub fn textures(&self) -> Option<&SignedPlayerTextures> { pub fn textures(&self) -> Option<&SignedPlayerTextures> {
self.textures.as_ref() self.textures.as_ref()
} }

View file

@ -8,7 +8,7 @@ use url::Url;
/// ///
/// This data has been cryptographically signed to ensure it will not be altered /// This data has been cryptographically signed to ensure it will not be altered
/// by the server. /// by the server.
#[derive(Clone, PartialEq, Debug)] #[derive(Clone, PartialEq, Eq, Debug)]
pub struct SignedPlayerTextures { pub struct SignedPlayerTextures {
payload: Box<[u8]>, payload: Box<[u8]>,
signature: Box<[u8]>, signature: Box<[u8]>,
@ -57,7 +57,7 @@ impl SignedPlayerTextures {
} }
/// Contains URLs to the skin and cape of a player. /// Contains URLs to the skin and cape of a player.
#[derive(Clone, PartialEq, Default, Debug)] #[derive(Clone, PartialEq, Eq, Default, Debug)]
pub struct PlayerTextures { pub struct PlayerTextures {
/// A URL to the skin of a player. Is `None` if the player does not have a /// A URL to the skin of a player. Is `None` if the player does not have a
/// skin. /// skin.
@ -82,7 +82,7 @@ struct PlayerTexturesPayload {
cape: Option<TextureUrl>, cape: Option<TextureUrl>,
} }
#[derive(Clone, PartialEq, Debug, Serialize, Deserialize)] #[derive(Clone, PartialEq, Eq, Debug, Serialize, Deserialize)]
struct TextureUrl { struct TextureUrl {
url: Url, url: Url,
} }

View file

@ -269,6 +269,11 @@ impl Decode for Box<str> {
} }
} }
/// An integer with a minimum and maximum value known at compile time. `T` is
/// the underlying integer type.
///
/// If the value is not in bounds, an error is generated while
/// encoding or decoding.
#[derive(Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] #[derive(Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
pub struct BoundedInt<T, const MIN: i64, const MAX: i64>(pub T); pub struct BoundedInt<T, const MIN: i64, const MAX: i64>(pub T);
@ -320,8 +325,6 @@ where
} }
} }
// TODO: bounded float?
impl Encode for String { impl Encode for String {
fn encode(&self, w: &mut impl Write) -> anyhow::Result<()> { fn encode(&self, w: &mut impl Write) -> anyhow::Result<()> {
encode_string_bounded(self, 0, 32767, w) encode_string_bounded(self, 0, 32767, w)
@ -335,12 +338,11 @@ impl Decode for String {
} }
/// A string with a minimum and maximum character length known at compile time. /// A string with a minimum and maximum character length known at compile time.
///
/// If the string is not in bounds, an error is generated while /// If the string is not in bounds, an error is generated while
/// encoding/decoding. /// encoding or decoding.
/// ///
/// Note that the length is a count of the characters in the string, not bytes. /// Note that the length is a count of the characters in the string, not bytes.
///
/// When encoded and decoded, the string is VarInt prefixed.
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Default, Hash, Debug)] #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Default, Hash, Debug)]
pub struct BoundedString<const MIN: usize, const MAX: usize>(pub String); pub struct BoundedString<const MIN: usize, const MAX: usize>(pub String);
@ -462,10 +464,9 @@ impl<T: Decode> Decode for Vec4<T> {
} }
/// An array with a minimum and maximum character length known at compile time. /// An array with a minimum and maximum character length known at compile time.
/// If the array is not in bounds, an error is generated while
/// encoding/decoding.
/// ///
/// When encoding/decoding, the array is VarInt prefixed. /// If the array is not in bounds, an error is generated while
/// encoding or decoding.
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Default, Hash, Debug)] #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Default, Hash, Debug)]
pub struct BoundedArray<T, const MIN: usize = 0, const MAX: usize = { usize::MAX }>(pub Vec<T>); pub struct BoundedArray<T, const MIN: usize = 0, const MAX: usize = { usize::MAX }>(pub Vec<T>);

View file

@ -1,3 +1,5 @@
/// Reading and writing whole packets.
use std::io::Read; use std::io::Read;
use std::time::Duration; use std::time::Duration;
@ -296,7 +298,7 @@ mod tests {
async fn send_test_packet(w: &mut Encoder<TcpStream>) { async fn send_test_packet(w: &mut Encoder<TcpStream>) {
w.write_packet(&TestPacket { w.write_packet(&TestPacket {
first: "abcdefghijklmnopqrstuvwxyz".to_string().into(), first: "abcdefghijklmnopqrstuvwxyz".into(),
second: vec![0x1234, 0xabcd], second: vec![0x1234, 0xabcd],
third: 0x1122334455667788, third: 0x1122334455667788,
}) })

View file

@ -1,4 +1,4 @@
//! Packet definitions and some types contained within them. //! Packet definitions and related types.
//! //!
//! See <https://wiki.vg/Protocol> for more packet documentation. //! See <https://wiki.vg/Protocol> for more packet documentation.

View file

@ -1,3 +1,5 @@
//! The heart of the server.
use std::collections::HashSet; use std::collections::HashSet;
use std::error::Error; use std::error::Error;
use std::iter::FusedIterator; use std::iter::FusedIterator;
@ -106,9 +108,14 @@ struct SharedServerInner {
/// Contains information about a new client. /// Contains information about a new client.
pub struct NewClientData { pub struct NewClientData {
/// The UUID of the new client.
pub uuid: Uuid, pub uuid: Uuid,
/// The username of the new client.
pub username: String, pub username: String,
/// The new client's player textures. May be `None` if the client does not
/// have a skin or cape.
pub textures: Option<SignedPlayerTextures>, pub textures: Option<SignedPlayerTextures>,
/// The remote address of the new client.
pub remote_addr: SocketAddr, pub remote_addr: SocketAddr,
} }
@ -232,7 +239,7 @@ impl SharedServer {
/// Consumes the configuration and starts the server. /// Consumes the configuration and starts the server.
/// ///
/// The function returns once the server has shut down, a runtime error /// The function returns once the server has shut down, a runtime error
/// occurs, or the configuration is invalid. /// occurs, or the configuration is found to be invalid.
pub fn start_server(config: impl Config) -> ShutdownResult { pub fn start_server(config: impl Config) -> ShutdownResult {
let shared = setup_server(config).map_err(Box::<dyn Error + Send + Sync + 'static>::from)?; let shared = setup_server(config).map_err(Box::<dyn Error + Send + Sync + 'static>::from)?;

View file

@ -1,3 +1,5 @@
//! Formatted text.
use std::borrow::Cow; use std::borrow::Cow;
use std::fmt; use std::fmt;
use std::io::{Read, Write}; use std::io::{Read, Write};
@ -104,6 +106,7 @@ impl Text {
/// convert the type into [`Text`]. A blanket implementation exists for all /// convert the type into [`Text`]. A blanket implementation exists for all
/// `Into<Text>` types, including [`Text`] itself. /// `Into<Text>` types, including [`Text`] itself.
pub trait TextFormat: Into<Text> { pub trait TextFormat: Into<Text> {
/// Converts this type into a [`Text`] object.
fn into_text(self) -> Text { fn into_text(self) -> Text {
self.into() self.into()
} }
@ -305,10 +308,14 @@ enum TextContent {
// TODO: nbt // TODO: nbt
} }
/// Text color
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
pub struct Color { pub struct Color {
/// Red channel
pub r: u8, pub r: u8,
/// Green channel
pub g: u8, pub g: u8,
/// Blue channel
pub b: u8, pub b: u8,
} }
@ -344,6 +351,7 @@ enum HoverEvent {
#[allow(clippy::self_named_constructors)] #[allow(clippy::self_named_constructors)]
impl Text { impl Text {
/// Constructs a new plain text object.
pub fn text(plain: impl Into<Cow<'static, str>>) -> Self { pub fn text(plain: impl Into<Cow<'static, str>>) -> Self {
Self { Self {
content: TextContent::Text { text: plain.into() }, content: TextContent::Text { text: plain.into() },
@ -351,6 +359,7 @@ impl Text {
} }
} }
/// Create translated text based on the given translation key.
pub fn translate(key: impl Into<Cow<'static, str>>) -> Self { pub fn translate(key: impl Into<Cow<'static, str>>) -> Self {
Self { Self {
content: TextContent::Translate { content: TextContent::Translate {
@ -360,6 +369,7 @@ impl Text {
} }
} }
/// Gets this text object as plain text without any formatting.
pub fn to_plain(&self) -> String { pub fn to_plain(&self) -> String {
let mut res = String::new(); let mut res = String::new();
self.write_plain(&mut res) self.write_plain(&mut res)
@ -367,6 +377,7 @@ impl Text {
res res
} }
/// Writes this text object as plain text to the provided writer.
pub fn write_plain(&self, w: &mut impl fmt::Write) -> fmt::Result { pub fn write_plain(&self, w: &mut impl fmt::Write) -> fmt::Result {
match &self.content { match &self.content {
TextContent::Text { text } => w.write_str(text.as_ref())?, TextContent::Text { text } => w.write_str(text.as_ref())?,
@ -458,6 +469,7 @@ impl Default for TextContent {
} }
} }
#[allow(missing_docs)]
impl Color { impl Color {
pub const AQUA: Color = Color::new(85, 255, 255); pub const AQUA: Color = Color::new(85, 255, 255);
pub const BLACK: Color = Color::new(0, 0, 0); pub const BLACK: Color = Color::new(0, 0, 0);
@ -476,6 +488,7 @@ impl Color {
pub const WHITE: Color = Color::new(255, 255, 255); pub const WHITE: Color = Color::new(255, 255, 255);
pub const YELLOW: Color = Color::new(255, 255, 85); pub const YELLOW: Color = Color::new(255, 255, 85);
/// Constructs a new color from red, green, and blue components.
pub const fn new(r: u8, g: u8, b: u8) -> Self { pub const fn new(r: u8, g: u8, b: u8) -> Self {
Self { r, g, b } Self { r, g, b }
} }

View file

@ -22,7 +22,7 @@ use crate::chunk_pos::ChunkPos;
/// assert!(valid_username("jeb_")); /// assert!(valid_username("jeb_"));
/// ///
/// assert!(!valid_username("notavalidusername")); /// assert!(!valid_username("notavalidusername"));
/// assert!(!valid_username("NotValid!")) /// assert!(!valid_username("NotValid!"));
/// ``` /// ```
pub fn valid_username(s: &str) -> bool { pub fn valid_username(s: &str) -> bool {
(3..=16).contains(&s.len()) (3..=16).contains(&s.len())
@ -44,6 +44,8 @@ pub fn chunks_in_view_distance(
.filter(move |&p| is_chunk_in_view_distance(center, p, distance)) .filter(move |&p| is_chunk_in_view_distance(center, p, distance))
} }
/// Checks if two chunks are within a view distance of each other such that a
/// client standing in one chunk would be able to see the other.
pub fn is_chunk_in_view_distance(p0: ChunkPos, p1: ChunkPos, distance: u8) -> bool { pub fn is_chunk_in_view_distance(p0: ChunkPos, p1: ChunkPos, distance: u8) -> bool {
(p0.x as f64 - p1.x as f64).powi(2) + (p0.z as f64 - p1.z as f64).powi(2) (p0.x as f64 - p1.x as f64).powi(2) + (p0.z as f64 - p1.z as f64).powi(2)
<= (distance as f64 + EXTRA_RADIUS as f64).powi(2) <= (distance as f64 + EXTRA_RADIUS as f64).powi(2)

View file

@ -1,3 +1,5 @@
//! A space on a server for objects to occupy.
use std::iter::FusedIterator; use std::iter::FusedIterator;
use rayon::iter::ParallelIterator; use rayon::iter::ParallelIterator;
@ -9,12 +11,13 @@ use crate::server::SharedServer;
use crate::slotmap::{Key, SlotMap}; use crate::slotmap::{Key, SlotMap};
use crate::spatial_index::SpatialIndex; use crate::spatial_index::SpatialIndex;
/// A container for all [`World`]s on a [`Server`](crate::server::Server).
pub struct Worlds { pub struct Worlds {
sm: SlotMap<World>, sm: SlotMap<World>,
server: SharedServer, server: SharedServer,
} }
/// A key for a [`World`] on the server. /// An identifier for a [`World`] on the server.
/// ///
/// World IDs are either _valid_ or _invalid_. Valid world IDs point to /// 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 /// worlds that have not been deleted, while invalid IDs point to those that