mirror of
https://github.com/italicsjenga/valence.git
synced 2025-01-11 15:21:31 +11:00
Clean up docs and fix clippy issues
This commit is contained in:
parent
c5f0f6024c
commit
4b83801066
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
//! Biome definitions.
|
//! Biome configuration and identification.
|
||||||
|
|
||||||
use crate::ident;
|
use crate::ident;
|
||||||
use crate::ident::Ident;
|
use crate::ident::Ident;
|
||||||
|
|
|
@ -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};
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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(_) => {}
|
||||||
|
|
|
@ -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};
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
12
src/ident.rs
12
src/ident.rs
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
23
src/lib.rs
23
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
|
//! 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;
|
|
||||||
|
|
|
@ -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()
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,
|
||||||
}
|
}
|
||||||
|
|
|
@ -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>);
|
||||||
|
|
||||||
|
|
|
@ -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,
|
||||||
})
|
})
|
||||||
|
|
|
@ -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.
|
||||||
|
|
||||||
|
|
|
@ -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)?;
|
||||||
|
|
||||||
|
|
13
src/text.rs
13
src/text.rs
|
@ -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 }
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in a new issue