From 4b838010669dbb1e7aaa93c5d1662ca43433371f Mon Sep 17 00:00:00 2001 From: Ryan Date: Thu, 14 Jul 2022 23:18:20 -0700 Subject: [PATCH] Clean up docs and fix clippy issues --- build/entity.rs | 10 +++++----- examples/cow_sphere.rs | 1 + src/biome.rs | 2 +- src/block.rs | 2 ++ src/chunk.rs | 2 ++ src/chunk_pos.rs | 12 ++++++------ src/client.rs | 15 +++++++++------ src/config.rs | 2 ++ src/dimension.rs | 2 ++ src/entity.rs | 22 ++++++++++++---------- src/ident.rs | 12 ++++++++---- src/lib.rs | 23 ++++++++++++++++------- src/player_list.rs | 3 +++ src/player_textures.rs | 6 +++--- src/protocol_inner.rs | 17 +++++++++-------- src/protocol_inner/codec.rs | 4 +++- src/protocol_inner/packets.rs | 2 +- src/server.rs | 9 ++++++++- src/text.rs | 13 +++++++++++++ src/util.rs | 4 +++- src/world.rs | 5 ++++- 21 files changed, 113 insertions(+), 55 deletions(-) diff --git a/build/entity.rs b/build/entity.rs index b8e7696..7852500 100644 --- a/build/entity.rs +++ b/build/entity.rs @@ -2160,7 +2160,7 @@ pub fn build() -> anyhow::Result<()> { let mut all_classes = BTreeMap::new(); 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 { Some(parent) => class = parent, None => break, @@ -2227,8 +2227,8 @@ pub fn build() -> anyhow::Result<()> { .enumerate() .map(|(field_offset, field)| { let name = ident(field.name.to_snake_case()); - let getter_name = ident(format!("get_{}", name.to_string())); - let setter_name = ident(format!("set_{}", name.to_string())); + let getter_name = ident(format!("get_{name}")); + let setter_name = ident(format!("set_{name}")); let field_offset = field_offset as u32; @@ -2254,8 +2254,8 @@ pub fn build() -> anyhow::Result<()> { .map(|bf| { let bit_name = ident(bf.name.to_snake_case()); - let getter_name = ident(format!("get_{}", bit_name.to_string())); - let setter_name = ident(format!("set_{}", bit_name.to_string())); + let getter_name = ident(format!("get_{bit_name}")); + let setter_name = ident(format!("set_{bit_name}")); let offset = bf.offset; diff --git a/examples/cow_sphere.rs b/examples/cow_sphere.rs index 89d7417..3eb3ff4 100644 --- a/examples/cow_sphere.rs +++ b/examples/cow_sphere.rs @@ -149,6 +149,7 @@ impl Config for Game { // TODO: hardcoded eye pos. 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)) { let cow = server.entities.get_mut(cow_id).expect("missing cow"); let rotated = p * rot; diff --git a/src/biome.rs b/src/biome.rs index c02c0e7..8191860 100644 --- a/src/biome.rs +++ b/src/biome.rs @@ -1,4 +1,4 @@ -//! Biome definitions. +//! Biome configuration and identification. use crate::ident; use crate::ident::Ident; diff --git a/src/block.rs b/src/block.rs index 0b533a3..29a293f 100644 --- a/src/block.rs +++ b/src/block.rs @@ -1,3 +1,5 @@ +//! Blocks and related types. + #![allow(clippy::all, missing_docs)] use std::fmt::{self, Display}; diff --git a/src/chunk.rs b/src/chunk.rs index 4bbd6c6..f6a3348 100644 --- a/src/chunk.rs +++ b/src/chunk.rs @@ -1,3 +1,5 @@ +//! Chunks and related types. + // TODO: https://github.com/rust-lang/rust/issues/88581 for div_ceil use std::collections::hash_map::Entry; diff --git a/src/chunk_pos.rs b/src/chunk_pos.rs index d7ca246..8926d9e 100644 --- a/src/chunk_pos.rs +++ b/src/chunk_pos.rs @@ -28,9 +28,9 @@ impl From<(i32, i32)> for ChunkPos { } } -impl Into<(i32, i32)> for ChunkPos { - fn into(self) -> (i32, i32) { - (self.x, self.z) +impl From for (i32, i32) { + fn from(pos: ChunkPos) -> Self { + (pos.x, pos.z) } } @@ -40,9 +40,9 @@ impl From<[i32; 2]> for ChunkPos { } } -impl Into<[i32; 2]> for ChunkPos { - fn into(self) -> [i32; 2] { - [self.x, self.z] +impl From for [i32; 2] { + fn from(pos: ChunkPos) -> Self { + [pos.x, pos.z] } } diff --git a/src/client.rs b/src/client.rs index 7111b0c..9a3ba3b 100644 --- a/src/client.rs +++ b/src/client.rs @@ -1,3 +1,5 @@ +//! Connections to the server after logging in. + /// Contains the [`Event`] enum and related data types. mod event; 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 /// 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. /// /// Much like an [`Entity`], clients posess a location, rotation, and UUID. -/// Clients are handled separately from entities and are partially -/// controlled by the library. +/// However, clients are handled separately from entities and are partially +/// managed by the library. /// /// By default, clients have no influence over the worlds they reside in. They /// cannot break blocks, hurt entities, or see other clients. Interactions with @@ -475,9 +477,11 @@ impl Client { 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. pub fn pop_event(&mut self) -> Option { self.events.pop_front() @@ -629,7 +633,6 @@ impl Client { self.username() ); self.disconnect_no_reason(); - return; } } C2sPlayPacket::BlockEntityTagQuery(_) => {} diff --git a/src/config.rs b/src/config.rs index 6ef7625..00ae041 100644 --- a/src/config.rs +++ b/src/config.rs @@ -1,3 +1,5 @@ +//! Configuration for the server. + use std::any::Any; use std::net::{Ipv4Addr, SocketAddr, SocketAddrV4}; use std::panic::{RefUnwindSafe, UnwindSafe}; diff --git a/src/dimension.rs b/src/dimension.rs index 1c4e101..7d3f47a 100644 --- a/src/dimension.rs +++ b/src/dimension.rs @@ -1,3 +1,5 @@ +//! Dimension configuration and identification. + use crate::ident; use crate::protocol_inner::packets::play::s2c::DimensionType; diff --git a/src/entity.rs b/src/entity.rs index 1d70318..14a30f0 100644 --- a/src/entity.rs +++ b/src/entity.rs @@ -1,3 +1,5 @@ +//! Dynamic actors in a world. + pub mod data; 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 /// entities that have not been deleted, while invalid IDs point to those that @@ -554,20 +556,20 @@ impl Entity { match &self.data { EntityData::Marker(_) => None, EntityData::ExperienceOrb(_) => { - Some(EntitySpawnPacket::SpawnExperienceOrb(AddExperienceOrb { + Some(EntitySpawnPacket::ExperienceOrb(AddExperienceOrb { entity_id: VarInt(this_id.to_network_id()), position: self.new_position, count: 0, // TODO })) } - EntityData::Player(_) => Some(EntitySpawnPacket::SpawnPlayer(AddPlayer { + EntityData::Player(_) => Some(EntitySpawnPacket::Player(AddPlayer { entity_id: VarInt(this_id.to_network_id()), player_uuid: self.uuid, position: self.new_position, yaw: ByteAngle::from_degrees(self.yaw), pitch: ByteAngle::from_degrees(self.pitch), })), - _ => Some(EntitySpawnPacket::SpawnEntity(AddEntity { + _ => Some(EntitySpawnPacket::Entity(AddEntity { entity_id: VarInt(this_id.to_network_id()), object_uuid: self.uuid, kind: VarInt(self.kind() as i32), @@ -588,17 +590,17 @@ pub(crate) fn velocity_to_packet_units(vel: Vec3) -> Vec3 { } pub(crate) enum EntitySpawnPacket { - SpawnEntity(AddEntity), - SpawnExperienceOrb(AddExperienceOrb), - SpawnPlayer(AddPlayer), + Entity(AddEntity), + ExperienceOrb(AddExperienceOrb), + Player(AddPlayer), } impl From for S2cPlayPacket { fn from(pkt: EntitySpawnPacket) -> Self { match pkt { - EntitySpawnPacket::SpawnEntity(pkt) => pkt.into(), - EntitySpawnPacket::SpawnExperienceOrb(pkt) => pkt.into(), - EntitySpawnPacket::SpawnPlayer(pkt) => pkt.into(), + EntitySpawnPacket::Entity(pkt) => pkt.into(), + EntitySpawnPacket::ExperienceOrb(pkt) => pkt.into(), + EntitySpawnPacket::Player(pkt) => pkt.into(), } } } diff --git a/src/ident.rs b/src/ident.rs index 0f761c0..477388f 100644 --- a/src/ident.rs +++ b/src/ident.rs @@ -1,3 +1,5 @@ +//! Namespaced identifiers. + use std::borrow::Cow; use std::io::{Read, Write}; use std::str::FromStr; @@ -27,7 +29,9 @@ pub struct Ident { 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}\"")] pub struct ParseError { src: Cow<'static, str>, @@ -36,8 +40,7 @@ pub struct ParseError { impl Ident { /// Parses a new identifier from a string. /// - /// The string must match the regex `([a-z0-9_-]+:)?[a-z0-9_\/.-]+`. - /// If not, an error is returned. + /// An error is returned if the string is not a valid identifier. pub fn new(str: impl Into>) -> Result { #![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 { self.ident.as_str() } @@ -120,6 +123,7 @@ fn ascii_cow_to_str_cow(cow: Cow) -> Cow { } impl ParseError { + /// Gets the string that caused the parse error. pub fn into_source(self) -> Cow<'static, str> { self.src } diff --git a/src/lib.rs b/src/lib.rs index 1830f43..3e4fe13 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -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 //! 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 //! function that would move their location in memory).** Doing so breaks -//! invariants within the library and the resulting behavior is unspecified. -//! These types should be considered pinned in memory. +//! invariants within the library and the resulting behavior is safe but +//! unspecified. These types should be considered [pinned](std::pin). //! //! Preventing this illegal behavior using Rust's type system was considered too //! cumbersome, so a note has been left here instead. @@ -107,6 +107,11 @@ unused_lifetimes, unused_import_braces )] +#![allow( + clippy::derive_partial_eq_without_eq, + clippy::unusual_byte_groupings, + clippy::comparison_chain +)] pub mod biome; pub mod block; @@ -130,13 +135,21 @@ pub mod text; pub mod util; pub mod world; +/// Provides low-level access to the Minecraft protocol. #[cfg(feature = "protocol")] pub mod protocol { 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; +#[doc(inline)] pub use server::start_server; +#[doc(inline)] pub use {nbt, uuid, vek}; /// 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 /// may or may not be the same as Minecraft's standard 20 ticks/second. pub type Ticks = i64; - -/// Whatever dude -#[cfg(feature = "whatever")] -pub type Whatever = i64; diff --git a/src/player_list.rs b/src/player_list.rs index cb9e9af..36a0fc9 100644 --- a/src/player_list.rs +++ b/src/player_list.rs @@ -1,3 +1,5 @@ +//! The player list (tab list). + use std::collections::hash_map::Entry; use std::collections::{HashMap, HashSet}; @@ -297,6 +299,7 @@ impl PlayerListEntry { &self.username } + /// Gets the player textures for this entry. pub fn textures(&self) -> Option<&SignedPlayerTextures> { self.textures.as_ref() } diff --git a/src/player_textures.rs b/src/player_textures.rs index c48d1a9..dad4b62 100644 --- a/src/player_textures.rs +++ b/src/player_textures.rs @@ -8,7 +8,7 @@ use url::Url; /// /// This data has been cryptographically signed to ensure it will not be altered /// by the server. -#[derive(Clone, PartialEq, Debug)] +#[derive(Clone, PartialEq, Eq, Debug)] pub struct SignedPlayerTextures { payload: Box<[u8]>, signature: Box<[u8]>, @@ -57,7 +57,7 @@ impl SignedPlayerTextures { } /// Contains URLs to the skin and cape of a player. -#[derive(Clone, PartialEq, Default, Debug)] +#[derive(Clone, PartialEq, Eq, Default, Debug)] pub struct PlayerTextures { /// A URL to the skin of a player. Is `None` if the player does not have a /// skin. @@ -82,7 +82,7 @@ struct PlayerTexturesPayload { cape: Option, } -#[derive(Clone, PartialEq, Debug, Serialize, Deserialize)] +#[derive(Clone, PartialEq, Eq, Debug, Serialize, Deserialize)] struct TextureUrl { url: Url, } diff --git a/src/protocol_inner.rs b/src/protocol_inner.rs index a6baa70..0061a2e 100644 --- a/src/protocol_inner.rs +++ b/src/protocol_inner.rs @@ -269,6 +269,11 @@ impl Decode for Box { } } +/// 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)] pub struct BoundedInt(pub T); @@ -320,8 +325,6 @@ where } } -// TODO: bounded float? - impl Encode for String { fn encode(&self, w: &mut impl Write) -> anyhow::Result<()> { 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. +/// /// 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. -/// -/// When encoded and decoded, the string is VarInt prefixed. #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Default, Hash, Debug)] pub struct BoundedString(pub String); @@ -462,10 +464,9 @@ impl Decode for Vec4 { } /// 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)] pub struct BoundedArray(pub Vec); diff --git a/src/protocol_inner/codec.rs b/src/protocol_inner/codec.rs index c8b73cb..822b400 100644 --- a/src/protocol_inner/codec.rs +++ b/src/protocol_inner/codec.rs @@ -1,3 +1,5 @@ +/// Reading and writing whole packets. + use std::io::Read; use std::time::Duration; @@ -296,7 +298,7 @@ mod tests { async fn send_test_packet(w: &mut Encoder) { w.write_packet(&TestPacket { - first: "abcdefghijklmnopqrstuvwxyz".to_string().into(), + first: "abcdefghijklmnopqrstuvwxyz".into(), second: vec![0x1234, 0xabcd], third: 0x1122334455667788, }) diff --git a/src/protocol_inner/packets.rs b/src/protocol_inner/packets.rs index 3f289e1..9e29d2a 100644 --- a/src/protocol_inner/packets.rs +++ b/src/protocol_inner/packets.rs @@ -1,4 +1,4 @@ -//! Packet definitions and some types contained within them. +//! Packet definitions and related types. //! //! See for more packet documentation. diff --git a/src/server.rs b/src/server.rs index aa29211..99d2cd2 100644 --- a/src/server.rs +++ b/src/server.rs @@ -1,3 +1,5 @@ +//! The heart of the server. + use std::collections::HashSet; use std::error::Error; use std::iter::FusedIterator; @@ -106,9 +108,14 @@ struct SharedServerInner { /// Contains information about a new client. pub struct NewClientData { + /// The UUID of the new client. pub uuid: Uuid, + /// The username of the new client. 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, + /// The remote address of the new client. pub remote_addr: SocketAddr, } @@ -232,7 +239,7 @@ impl SharedServer { /// Consumes the configuration and starts the server. /// /// 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 { let shared = setup_server(config).map_err(Box::::from)?; diff --git a/src/text.rs b/src/text.rs index aaf3dc4..35483bd 100644 --- a/src/text.rs +++ b/src/text.rs @@ -1,3 +1,5 @@ +//! Formatted text. + use std::borrow::Cow; use std::fmt; use std::io::{Read, Write}; @@ -104,6 +106,7 @@ impl Text { /// convert the type into [`Text`]. A blanket implementation exists for all /// `Into` types, including [`Text`] itself. pub trait TextFormat: Into { + /// Converts this type into a [`Text`] object. fn into_text(self) -> Text { self.into() } @@ -305,10 +308,14 @@ enum TextContent { // TODO: nbt } +/// Text color #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] pub struct Color { + /// Red channel pub r: u8, + /// Green channel pub g: u8, + /// Blue channel pub b: u8, } @@ -344,6 +351,7 @@ enum HoverEvent { #[allow(clippy::self_named_constructors)] impl Text { + /// Constructs a new plain text object. pub fn text(plain: impl Into>) -> Self { Self { 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>) -> Self { Self { 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 { let mut res = String::new(); self.write_plain(&mut res) @@ -367,6 +377,7 @@ impl Text { res } + /// Writes this text object as plain text to the provided writer. pub fn write_plain(&self, w: &mut impl fmt::Write) -> fmt::Result { match &self.content { TextContent::Text { text } => w.write_str(text.as_ref())?, @@ -458,6 +469,7 @@ impl Default for TextContent { } } +#[allow(missing_docs)] impl Color { pub const AQUA: Color = Color::new(85, 255, 255); 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 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 { Self { r, g, b } } diff --git a/src/util.rs b/src/util.rs index bd52549..acc7922 100644 --- a/src/util.rs +++ b/src/util.rs @@ -22,7 +22,7 @@ use crate::chunk_pos::ChunkPos; /// assert!(valid_username("jeb_")); /// /// assert!(!valid_username("notavalidusername")); -/// assert!(!valid_username("NotValid!")) +/// assert!(!valid_username("NotValid!")); /// ``` pub fn valid_username(s: &str) -> bool { (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)) } +/// 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 { (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) diff --git a/src/world.rs b/src/world.rs index 76fb420..1fb5530 100644 --- a/src/world.rs +++ b/src/world.rs @@ -1,3 +1,5 @@ +//! A space on a server for objects to occupy. + use std::iter::FusedIterator; use rayon::iter::ParallelIterator; @@ -9,12 +11,13 @@ use crate::server::SharedServer; use crate::slotmap::{Key, SlotMap}; use crate::spatial_index::SpatialIndex; +/// A container for all [`World`]s on a [`Server`](crate::server::Server). pub struct Worlds { sm: SlotMap, 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 /// worlds that have not been deleted, while invalid IDs point to those that