From 12ab2c72981643661168ea489db051005f902c4d Mon Sep 17 00:00:00 2001 From: Snowiiii Date: Mon, 21 Oct 2024 15:07:05 +0200 Subject: [PATCH] Clippy: warn clippy::pedantic --- pumpkin/src/client/authentication.rs | 4 +- pumpkin/src/client/client_packet.rs | 23 +++++------ pumpkin/src/client/container.rs | 19 ++++----- pumpkin/src/client/mod.rs | 53 +++++++++----------------- pumpkin/src/client/player_packet.rs | 38 +++++++++--------- pumpkin/src/commands/arg_player.rs | 11 +++--- pumpkin/src/commands/cmd_gamemode.rs | 2 +- pumpkin/src/commands/cmd_help.rs | 2 +- pumpkin/src/commands/dispatcher.rs | 14 +++---- pumpkin/src/commands/mod.rs | 25 ++++-------- pumpkin/src/commands/tree.rs | 8 ++-- pumpkin/src/commands/tree_builder.rs | 18 ++++----- pumpkin/src/commands/tree_format.rs | 12 +++--- pumpkin/src/entity/mod.rs | 2 +- pumpkin/src/entity/player.rs | 27 +++++++------ pumpkin/src/error.rs | 10 ++++- pumpkin/src/main.rs | 25 ++++++++---- pumpkin/src/proxy/velocity.rs | 9 +++-- pumpkin/src/rcon/mod.rs | 14 +++---- pumpkin/src/rcon/packet.rs | 14 +++---- pumpkin/src/server/connection_cache.rs | 4 +- pumpkin/src/server/mod.rs | 7 ++-- pumpkin/src/server/ticker.rs | 1 + pumpkin/src/world/mod.rs | 18 ++++----- pumpkin/src/world/player_chunker.rs | 12 +++--- pumpkin/src/world/scoreboard.rs | 3 ++ 26 files changed, 181 insertions(+), 194 deletions(-) diff --git a/pumpkin/src/client/authentication.rs b/pumpkin/src/client/authentication.rs index 097a6a891..c231fbe22 100644 --- a/pumpkin/src/client/authentication.rs +++ b/pumpkin/src/client/authentication.rs @@ -96,12 +96,12 @@ pub fn validate_textures(property: &Property, config: &TextureConfig) -> Result< for texture in textures.textures { let url = Url::parse(&texture.1.url).map_err(|e| TextureError::InvalidURL(e.to_string()))?; - is_texture_url_valid(url, config)? + is_texture_url_valid(&url, config)?; } Ok(()) } -pub fn is_texture_url_valid(url: Url, config: &TextureConfig) -> Result<(), TextureError> { +pub fn is_texture_url_valid(url: &Url, config: &TextureConfig) -> Result<(), TextureError> { let scheme = url.scheme(); if !config .allowed_url_schemes diff --git a/pumpkin/src/client/client_packet.rs b/pumpkin/src/client/client_packet.rs index 04b00506e..d2fdad21c 100644 --- a/pumpkin/src/client/client_packet.rs +++ b/pumpkin/src/client/client_packet.rs @@ -192,15 +192,11 @@ impl Client { let profile = authentication::authenticate(username, &hash, &ip, auth_client).await?; // Check if player should join if let Some(actions) = &profile.profile_actions { - if !ADVANCED_CONFIG + if ADVANCED_CONFIG .authentication .player_profile .allow_banned_players { - if !actions.is_empty() { - return Err(AuthError::Banned); - } - } else { for allowed in &ADVANCED_CONFIG .authentication .player_profile @@ -210,6 +206,11 @@ impl Client { return Err(AuthError::DisallowedAction); } } + if !actions.is_empty() { + return Err(AuthError::Banned); + } + } else if !actions.is_empty() { + return Err(AuthError::Banned); } } // validate textures @@ -234,7 +235,7 @@ impl Client { Ok((profile, new_address)) => { self.finish_login(&profile).await; *self.gameprofile.lock().await = Some(profile); - *address = new_address + *address = new_address; } Err(error) => self.kick(&error.to_string()).await, } @@ -259,10 +260,10 @@ impl Client { &resource_config.resource_pack_url, &resource_config.resource_pack_sha1, resource_config.force, - if !resource_config.prompt_message.is_empty() { - Some(TextComponent::text(&resource_config.prompt_message)) - } else { + if resource_config.prompt_message.is_empty() { None + } else { + Some(TextComponent::text(&resource_config.prompt_message)) }, ); @@ -298,7 +299,7 @@ impl Client { server_listing: client_information.server_listing, }); } else { - self.kick("Invalid hand or chat type").await + self.kick("Invalid hand or chat type").await; } } @@ -328,7 +329,7 @@ impl Client { self.send_packet(&CFinishConfig::new()).await; } - pub async fn handle_config_acknowledged(&self, _config_acknowledged: SAcknowledgeFinishConfig) { + pub fn handle_config_acknowledged(&self, _config_acknowledged: &SAcknowledgeFinishConfig) { dbg!("config acknowledged"); self.connection_state.store(ConnectionState::Play); self.make_player diff --git a/pumpkin/src/client/container.rs b/pumpkin/src/client/container.rs index ac9b72470..6892f9029 100644 --- a/pumpkin/src/client/container.rs +++ b/pumpkin/src/client/container.rs @@ -71,7 +71,7 @@ impl Player { .carried_item .load() .as_ref() - .map_or_else(Slot::empty, |item| item.into()); + .map_or_else(Slot::empty, std::convert::Into::into); // Gets the previous value let i = inventory @@ -92,7 +92,7 @@ impl Player { inventory.total_opened_containers += 1; self.client .send_packet(&CCloseContainer::new(inventory.total_opened_containers)) - .await + .await; } pub async fn set_container_property( @@ -270,7 +270,7 @@ impl Player { slots.skip(36).rev().find_map(find_condition) }; if let Some(slot) = slots { - let mut item_slot = container.all_slots()[slot].map(|i| i.to_owned()); + let mut item_slot = container.all_slots()[slot].map(|i| i); container.handle_item_change(&mut item_slot, slot, MouseClick::Left)?; *container.all_slots()[slot] = item_slot; } @@ -363,13 +363,14 @@ impl Player { let player_id = self.entity_id(); let container_id = opened_container .as_ref() - .map(|container| container.internal_pumpkin_id()) - .unwrap_or(player_id as u64); + .map_or(player_id as u64, |container| { + container.internal_pumpkin_id() + }); match mouse_drag_state { MouseDragState::Start(drag_type) => { if drag_type == MouseDragType::Middle && self.gamemode.load() != GameMode::Creative { - Err(InventoryError::PermissionError)? + Err(InventoryError::PermissionError)?; } drag_handler .new_drag(container_id, player_id, drag_type) @@ -417,15 +418,15 @@ impl Player { .await .iter() .filter_map(|(token, player)| { - if *token != player_token { + if *token == player_token { + None + } else { let entity_id = player.entity_id(); if player_ids.contains(&entity_id) { Some(player.clone()) } else { None } - } else { - None } }) .collect_vec(); diff --git a/pumpkin/src/client/mod.rs b/pumpkin/src/client/mod.rs index 91aa294dc..f7f0fd587 100644 --- a/pumpkin/src/client/mod.rs +++ b/pumpkin/src/client/mod.rs @@ -125,7 +125,7 @@ impl Client { gameprofile: Mutex::new(None), config: Mutex::new(None), brand: Mutex::new(None), - server_address: Mutex::new("".to_string()), + server_address: Mutex::new(String::new()), id, address: Mutex::new(address), connection_state: AtomicCell::new(ConnectionState::HandShake), @@ -211,9 +211,9 @@ impl Client { while let Some(mut packet) = self.client_packets_queue.lock().await.pop_front() { if let Err(error) = self.handle_packet(server, &mut packet).await { dbg!("{:?}", packet.id); - let text = format!("Error while reading incoming packet {}", error); + let text = format!("Error while reading incoming packet {error}"); log::error!("{}", text); - self.kick(&text).await + self.kick(&text).await; }; } } @@ -239,7 +239,7 @@ impl Client { pumpkin_protocol::ConnectionState::Config => { self.handle_config_packet(server, packet).await } - _ => { + pumpkin_protocol::ConnectionState::Play => { log::error!("Invalid Connection state {:?}", self.connection_state); Ok(()) } @@ -251,19 +251,15 @@ impl Client { packet: &mut RawPacket, ) -> Result<(), DeserializerError> { let bytebuf = &mut packet.bytebuf; - match packet.id.0 { - SHandShake::PACKET_ID => { - self.handle_handshake(SHandShake::read(bytebuf)?).await; - Ok(()) - } - _ => { - log::error!( - "Failed to handle packet id {} while in Handshake state", - packet.id.0 - ); - Ok(()) - } + if packet.id.0 == SHandShake::PACKET_ID { + self.handle_handshake(SHandShake::read(bytebuf)?).await; + } else { + log::error!( + "Failed to handle packet id {} while in Handshake state", + packet.id.0 + ); } + Ok(()) } async fn handle_status_packet( @@ -276,21 +272,19 @@ impl Client { SStatusRequest::PACKET_ID => { self.handle_status_request(server, SStatusRequest::read(bytebuf)?) .await; - Ok(()) } SStatusPingRequest::PACKET_ID => { self.handle_ping_request(SStatusPingRequest::read(bytebuf)?) .await; - Ok(()) } _ => { log::error!( "Failed to handle packet id {} while in Status state", packet.id.0 ); - Ok(()) } } + Ok(()) } async fn handle_login_packet( @@ -303,31 +297,27 @@ impl Client { SLoginStart::PACKET_ID => { self.handle_login_start(server, SLoginStart::read(bytebuf)?) .await; - Ok(()) } SEncryptionResponse::PACKET_ID => { self.handle_encryption_response(server, SEncryptionResponse::read(bytebuf)?) .await; - Ok(()) } SLoginPluginResponse::PACKET_ID => { self.handle_plugin_response(SLoginPluginResponse::read(bytebuf)?) .await; - Ok(()) } SLoginAcknowledged::PACKET_ID => { self.handle_login_acknowledged(server, SLoginAcknowledged::read(bytebuf)?) .await; - Ok(()) } _ => { log::error!( "Failed to handle packet id {} while in Login state", packet.id.0 ); - Ok(()) } } + Ok(()) } async fn handle_config_packet( @@ -340,31 +330,26 @@ impl Client { SClientInformationConfig::PACKET_ID => { self.handle_client_information_config(SClientInformationConfig::read(bytebuf)?) .await; - Ok(()) } SPluginMessage::PACKET_ID => { self.handle_plugin_message(SPluginMessage::read(bytebuf)?) .await; - Ok(()) } SAcknowledgeFinishConfig::PACKET_ID => { - self.handle_config_acknowledged(SAcknowledgeFinishConfig::read(bytebuf)?) - .await; - Ok(()) + self.handle_config_acknowledged(&SAcknowledgeFinishConfig::read(bytebuf)?); } SKnownPacks::PACKET_ID => { self.handle_known_packs(server, SKnownPacks::read(bytebuf)?) .await; - Ok(()) } _ => { log::error!( "Failed to handle packet id {} while in Config state", packet.id.0 ); - Ok(()) } } + Ok(()) } /// Reads the connection until our buffer of len 4096 is full, then decode @@ -406,7 +391,7 @@ impl Client { match self.connection_state.load() { ConnectionState::Login => { self.try_send_packet(&CLoginDisconnect::new( - &serde_json::to_string_pretty(&reason).unwrap_or_else(|_| "".into()), + &serde_json::to_string_pretty(&reason).unwrap_or_else(|_| String::new()), )) .await .unwrap_or_else(|_| self.close()); @@ -423,10 +408,10 @@ impl Client { .unwrap_or_else(|_| self.close()); } _ => { - log::warn!("Can't kick in {:?} State", self.connection_state) + log::warn!("Can't kick in {:?} State", self.connection_state); } } - self.close() + self.close(); } /// You should prefer to use `kick` when you can diff --git a/pumpkin/src/client/player_packet.rs b/pumpkin/src/client/player_packet.rs index d51ff8a2a..1299d95c6 100644 --- a/pumpkin/src/client/player_packet.rs +++ b/pumpkin/src/client/player_packet.rs @@ -52,13 +52,13 @@ impl Player { *awaiting_teleport = None; } else { - self.kick(TextComponent::text("Wrong teleport id")).await + self.kick(TextComponent::text("Wrong teleport id")).await; } } else { self.kick(TextComponent::text( "Send Teleport confirm, but we did not teleport", )) - .await + .await; } } @@ -255,7 +255,7 @@ impl Player { } } - pub fn handle_player_ground(&self, ground: SSetPlayerGround) { + pub fn handle_player_ground(&self, ground: &SSetPlayerGround) { self.living_entity .entity .on_ground @@ -272,23 +272,23 @@ impl Player { match action { pumpkin_protocol::server::play::Action::StartSneaking => { if !entity.sneaking.load(std::sync::atomic::Ordering::Relaxed) { - entity.set_sneaking(true).await + entity.set_sneaking(true).await; } } pumpkin_protocol::server::play::Action::StopSneaking => { if entity.sneaking.load(std::sync::atomic::Ordering::Relaxed) { - entity.set_sneaking(false).await + entity.set_sneaking(false).await; } } pumpkin_protocol::server::play::Action::LeaveBed => todo!(), pumpkin_protocol::server::play::Action::StartSprinting => { if !entity.sprinting.load(std::sync::atomic::Ordering::Relaxed) { - entity.set_sprinting(true).await + entity.set_sprinting(true).await; } } pumpkin_protocol::server::play::Action::StopSprinting => { if entity.sprinting.load(std::sync::atomic::Ordering::Relaxed) { - entity.set_sprinting(false).await + entity.set_sprinting(false).await; } } pumpkin_protocol::server::play::Action::StartHorseJump => todo!(), @@ -307,7 +307,7 @@ impl Player { } } else { self.kick(TextComponent::text("Invalid player command")) - .await + .await; } } @@ -325,7 +325,7 @@ impl Player { &[self.client.id], &CEntityAnimation::new(id.into(), animation as u8), ) - .await + .await; } None => { self.kick(TextComponent::text("Invalid hand")).await; @@ -362,7 +362,7 @@ impl Player { TextComponent::text(&gameprofile.name), None, )) - .await + .await; /* server.broadcast_packet( self, @@ -392,7 +392,7 @@ impl Player { }; } else { self.kick(TextComponent::text("Invalid hand or chat type")) - .await + .await; } } @@ -425,8 +425,8 @@ impl Player { let saved_velo = victem_entity.velocity.load(); victem_entity.knockback( strength * 0.5, - (yaw * (PI / 180.0)).sin() as f64, - -(yaw * (PI / 180.0)).cos() as f64, + f64::from((yaw * (PI / 180.0)).sin()), + f64::from(-(yaw * (PI / 180.0)).cos()), ); let victem_velocity = victem_entity.velocity.load(); let packet = &CEntityVelocity::new( @@ -447,12 +447,12 @@ impl Player { &entity_id, entity.yaw.load(), )) - .await + .await; } if config.swing {} } else { self.kick(TextComponent::text("Interacted with invalid entity id")) - .await + .await; } } } @@ -552,7 +552,7 @@ impl Player { self.wait_for_keep_alive .store(false, std::sync::atomic::Ordering::Relaxed); } else { - self.kick(TextComponent::text("Timeout")).await + self.kick(TextComponent::text("Timeout")).await; } } @@ -605,11 +605,11 @@ impl Player { .send_packet(&CAcknowledgeBlockChange::new(use_item_on.sequence)) .await; } else { - self.kick(TextComponent::text("Invalid block face")).await + self.kick(TextComponent::text("Invalid block face")).await; } } - pub fn handle_use_item(&self, _use_item: SUseItem) { + pub fn handle_use_item(&self, _use_item: &SUseItem) { // TODO: handle packet correctly log::error!("An item was used(SUseItem), but the packet is not implemented yet"); } @@ -651,7 +651,7 @@ impl Player { if let Some(id) = open_container { let mut open_containers = server.open_containers.write().await; if let Some(container) = open_containers.get_mut(&id) { - container.remove_player(self.entity_id()) + container.remove_player(self.entity_id()); } self.open_container.store(None); } diff --git a/pumpkin/src/commands/arg_player.rs b/pumpkin/src/commands/arg_player.rs index 316e152cc..b232b8253 100644 --- a/pumpkin/src/commands/arg_player.rs +++ b/pumpkin/src/commands/arg_player.rs @@ -17,9 +17,8 @@ pub fn consume_arg_player( "@s" => { if src.is_player() { return Ok(arg.into()); - } else { - return Err(Some("You are not a Player".into())); } + return Err(Some("You are not a Player".into())); } "@p" if src.is_player() => return Ok(arg.into()), "@r" => todo!(), // todo: implement random player target selector @@ -31,7 +30,7 @@ pub fn consume_arg_player( return Ok(name.into()); } } - return Err(Some(format!("Player not found: {}", arg))); + return Err(Some(format!("Player not found: {arg}"))); } } } @@ -52,9 +51,9 @@ pub fn parse_arg_player( match s { "@s" if src.is_player() => Ok(src.as_mut_player().unwrap()), - "@p" if src.is_player() => Ok(src.as_mut_player().unwrap()), - "@r" => Err(InvalidConsumptionError(Some(s.into()))), // todo: implement random player target selector - "@a" | "@e" => Err(InvalidConsumptionError(Some(s.into()))), // todo: implement all players target selector + "@p" => todo!(), + "@r" => todo!(), // todo: implement random player target selector + "@a" | "@e" => todo!(), // todo: implement all players target selector name => { for world in &server.worlds { if let Some(player) = world.get_player_by_name(name) { diff --git a/pumpkin/src/commands/cmd_gamemode.rs b/pumpkin/src/commands/cmd_gamemode.rs index f81a01c47..86d377497 100644 --- a/pumpkin/src/commands/cmd_gamemode.rs +++ b/pumpkin/src/commands/cmd_gamemode.rs @@ -37,7 +37,7 @@ pub fn consume_arg_gamemode( match GameMode::from_str(arg) { Err(_) | Ok(GameMode::Undefined) => { - return Err(Some(format!("Gamemode not found: {}", arg))) + return Err(Some(format!("Gamemode not found: {arg}"))) } Ok(_) => return Ok(arg.into()), } diff --git a/pumpkin/src/commands/cmd_help.rs b/pumpkin/src/commands/cmd_help.rs index 9b6ed222c..e37a6ff76 100644 --- a/pumpkin/src/commands/cmd_help.rs +++ b/pumpkin/src/commands/cmd_help.rs @@ -56,7 +56,7 @@ pub fn init_command_tree<'a>() -> CommandTree<'a> { ) .execute(&|sender, server, _args| { let mut keys: Vec<&str> = server.command_dispatcher.commands.keys().copied().collect(); - keys.sort(); + keys.sort_unstable(); for key in keys { let Command::Tree(tree) = &server.command_dispatcher.commands[key] else { diff --git a/pumpkin/src/commands/dispatcher.rs b/pumpkin/src/commands/dispatcher.rs index 304ae50e8..1577e3c53 100644 --- a/pumpkin/src/commands/dispatcher.rs +++ b/pumpkin/src/commands/dispatcher.rs @@ -15,7 +15,7 @@ pub(crate) enum InvalidTreeError { /// never fail. InvalidConsumptionError(Option), - /// Return this if a condition that a [Node::Require] should ensure is met is not met. + /// Return this if a condition that a [`Node::Require`] should ensure is met is not met. InvalidRequirementError, } @@ -24,7 +24,7 @@ pub struct CommandDispatcher<'a> { pub(crate) commands: HashMap<&'a str, Command<'a>>, } -/// Stores registered [CommandTree]s and dispatches commands to them. +/// Stores registered [`CommandTree`]s and dispatches commands to them. impl<'a> CommandDispatcher<'a> { pub async fn handle_command(&self, sender: &mut CommandSender<'a>, server: &Server, cmd: &str) { if let Err(err) = self.dispatch(sender, server, cmd) { @@ -37,7 +37,7 @@ impl<'a> CommandDispatcher<'a> { } } - /// Execute a command using its corresponding [CommandTree]. + /// Execute a command using its corresponding [`CommandTree`]. pub(crate) fn dispatch( &'a self, src: &mut CommandSender, @@ -52,7 +52,7 @@ impl<'a> CommandDispatcher<'a> { // try paths until fitting path is found for path in tree.iter_paths() { - match Self::try_is_fitting_path(src, server, path, tree, raw_args.clone()) { + match Self::try_is_fitting_path(src, server, &path, tree, raw_args.clone()) { Err(InvalidConsumptionError(s)) => { println!("Error while parsing command \"{cmd}\": {s:?} was consumed, but couldn't be parsed"); return Err("Internal Error (See logs for details)".into()); @@ -62,7 +62,7 @@ impl<'a> CommandDispatcher<'a> { return Err("Internal Error (See logs for details)".into()); } Ok(is_fitting_path) => match is_fitting_path { - Ok(_) => return Ok(()), + Ok(()) => return Ok(()), Err(error) => { // Custom error message or not ? if let Some(error) = error { @@ -72,7 +72,7 @@ impl<'a> CommandDispatcher<'a> { }, } } - Err(format!("Invalid Syntax. Usage: {}", tree)) + Err(format!("Invalid Syntax. Usage: {tree}")) } pub(crate) fn get_tree(&'a self, key: &str) -> Result<&'a CommandTree<'a>, String> { @@ -93,7 +93,7 @@ impl<'a> CommandDispatcher<'a> { fn try_is_fitting_path( src: &mut CommandSender, server: &Server, - path: Vec, + path: &[usize], tree: &CommandTree, mut raw_args: RawArgs, ) -> Result>, InvalidTreeError> { diff --git a/pumpkin/src/commands/mod.rs b/pumpkin/src/commands/mod.rs index 53f270ba3..01dcac893 100644 --- a/pumpkin/src/commands/mod.rs +++ b/pumpkin/src/commands/mod.rs @@ -35,39 +35,30 @@ impl<'a> CommandSender<'a> { } } + #[must_use] pub const fn is_player(&self) -> bool { - match self { - CommandSender::Console => false, - CommandSender::Player(_) => true, - CommandSender::Rcon(_) => false, - } + matches!(self, CommandSender::Player(_)) } + #[must_use] pub const fn is_console(&self) -> bool { - match self { - CommandSender::Console => true, - CommandSender::Player(_) => false, - CommandSender::Rcon(_) => true, - } + matches!(self, CommandSender::Console) } pub fn as_mut_player(&mut self) -> Option> { match self { CommandSender::Player(player) => Some(player.clone()), - CommandSender::Console => None, - CommandSender::Rcon(_) => None, + _ => None, } } /// todo: implement + #[must_use] pub const fn permission_lvl(&self) -> i32 { - match self { - CommandSender::Rcon(_) => 4, - CommandSender::Console => 4, - CommandSender::Player(_) => 4, - } + 4 } } +#[must_use] pub fn default_dispatcher<'a>() -> CommandDispatcher<'a> { let mut dispatcher = CommandDispatcher::default(); diff --git a/pumpkin/src/commands/tree.rs b/pumpkin/src/commands/tree.rs index ffadee1c4..393008509 100644 --- a/pumpkin/src/commands/tree.rs +++ b/pumpkin/src/commands/tree.rs @@ -2,13 +2,13 @@ use super::RunFunctionType; use crate::{commands::CommandSender, server::Server}; use std::collections::{HashMap, VecDeque}; -/// see [crate::commands::tree_builder::argument] +/// see [`crate::commands::tree_builder::argument`] pub type RawArgs<'a> = Vec<&'a str>; -/// see [crate::commands::tree_builder::argument] and [CommandTree::execute]/[crate::commands::tree_builder::NonLeafNodeBuilder::execute] +/// see [`crate::commands::tree_builder::argument`] and [`CommandTree::execute`]/[`crate::commands::tree_builder::NonLeafNodeBuilder::execute`] pub type ConsumedArgs<'a> = HashMap<&'a str, String>; -/// see [crate::commands::tree_builder::argument] +/// see [`crate::commands::tree_builder::argument`] /// Provide value or an Optional error message, If no Error message provided the default will be used pub type ArgumentConsumer<'a> = fn(&CommandSender, &Server, &mut RawArgs) -> Result>; @@ -48,7 +48,7 @@ pub struct CommandTree<'a> { } impl<'a> CommandTree<'a> { - /// iterate over all possible paths that end in a [NodeType::ExecuteLeaf] + /// iterate over all possible paths that end in a [`NodeType::ExecuteLeaf`] pub(crate) fn iter_paths(&'a self) -> impl Iterator> + 'a { let mut todo = VecDeque::<(usize, usize)>::new(); diff --git a/pumpkin/src/commands/tree_builder.rs b/pumpkin/src/commands/tree_builder.rs index ecb79880e..1ef1416b3 100644 --- a/pumpkin/src/commands/tree_builder.rs +++ b/pumpkin/src/commands/tree_builder.rs @@ -4,7 +4,7 @@ use crate::commands::CommandSender; use super::RunFunctionType; impl<'a> CommandTree<'a> { - /// Add a child [Node] to the root of this [CommandTree]. + /// Add a child [Node] to the root of this [`CommandTree`]. pub fn with_child(mut self, child: impl NodeBuilder<'a>) -> Self { let node = child.build(&mut self); self.children.push(self.nodes.len()); @@ -35,11 +35,11 @@ impl<'a> CommandTree<'a> { /// Executes if a command terminates at this [Node], i.e. without any arguments. /// - /// [ConsumedArgs] maps the names of all + /// [`ConsumedArgs`] maps the names of all /// arguments to the result of their consumption, i.e. a string that can be parsed to the /// desired type. /// - /// Also see [NonLeafNodeBuilder::execute]. + /// Also see [`NonLeafNodeBuilder::execute`]. pub fn execute(mut self, run: &'a RunFunctionType) -> Self { let node = Node { node_type: NodeType::ExecuteLeaf { run }, @@ -108,11 +108,11 @@ impl<'a> NonLeafNodeBuilder<'a> { /// Executes if a command terminates at this [Node]. /// - /// [ConsumedArgs] maps the names of all + /// [`ConsumedArgs`] maps the names of all /// arguments to the result of their consumption, i.e. a string that can be parsed to the /// desired type. /// - /// Also see [CommandTree::execute]. + /// Also see [`CommandTree::execute`]. pub fn execute(mut self, run: &'a RunFunctionType) -> Self { self.leaf_nodes.push(LeafNodeBuilder { node_type: NodeType::ExecuteLeaf { run }, @@ -132,14 +132,14 @@ pub const fn literal(string: &str) -> NonLeafNodeBuilder { } } -/// ```name``` identifies this argument in [ConsumedArgs]. +/// ```name``` identifies this argument in [`ConsumedArgs`]. /// /// ```consumer: ArgumentConsumer``` has the purpose of validating arguments. Conversion may start /// here, as long as the result remains a [String] (e.g. convert offset to absolute position actual /// coordinates), because the result of this function will be passed to following -/// [NonLeafNodeBuilder::execute] nodes in a [ConsumedArgs] instance. It must remove consumed arg(s) -/// from [RawArgs] and return them. It must return None if [RawArgs] are invalid. [RawArgs] is -/// reversed, so [Vec::pop] can be used to obtain args in ltr order. +/// [`NonLeafNodeBuilder::execute`] nodes in a [`ConsumedArgs`] instance. It must remove consumed arg(s) +/// from [`RawArgs`] and return them. It must return None if [`RawArgs`] are invalid. [`RawArgs`] is +/// reversed, so [`Vec::pop`] can be used to obtain args in ltr order. pub fn argument<'a>(name: &'a str, consumer: ArgumentConsumer) -> NonLeafNodeBuilder<'a> { NonLeafNodeBuilder { node_type: NodeType::Argument { name, consumer }, diff --git a/pumpkin/src/commands/tree_format.rs b/pumpkin/src/commands/tree_format.rs index b13b0e1fe..afed1c982 100644 --- a/pumpkin/src/commands/tree_format.rs +++ b/pumpkin/src/commands/tree_format.rs @@ -9,12 +9,10 @@ trait IsVisible { impl<'a> IsVisible for Node<'a> { fn is_visible(&self) -> bool { - match self.node_type { - NodeType::ExecuteLeaf { .. } => false, - NodeType::Literal { .. } => true, - NodeType::Argument { .. } => true, - NodeType::Require { .. } => false, - } + matches!( + self.node_type, + NodeType::Literal { .. } | NodeType::Argument { .. } + ) } } @@ -43,7 +41,7 @@ fn flatten_require_nodes(nodes: &[Node], children: &[usize]) -> Vec { let node = &nodes[i]; match &node.node_type { NodeType::Require { .. } => { - new_children.extend(flatten_require_nodes(nodes, node.children.as_slice())) + new_children.extend(flatten_require_nodes(nodes, node.children.as_slice())); } _ => new_children.push(i), } diff --git a/pumpkin/src/entity/mod.rs b/pumpkin/src/entity/mod.rs index d2d0447af..ad1b639b2 100644 --- a/pumpkin/src/entity/mod.rs +++ b/pumpkin/src/entity/mod.rs @@ -201,7 +201,7 @@ impl Entity { self.entity_id.into(), Metadata::new(6, 20.into(), (pose).into()), ); - self.world.broadcast_packet_all(&packet).await + self.world.broadcast_packet_all(&packet).await; } } diff --git a/pumpkin/src/entity/player.rs b/pumpkin/src/entity/player.rs index ad8834795..dd8c23b41 100644 --- a/pumpkin/src/entity/player.rs +++ b/pumpkin/src/entity/player.rs @@ -76,7 +76,7 @@ pub struct Player { /// This field represents the various abilities that the player possesses, such as flight, invulnerability, and other special effects. /// /// **Note:** When the `abilities` field is updated, the server should send a `send_abilities_update` packet to the client to notify them of the changes. - pub abilities: Mutex, + pub abilities: Mutex, /// The player's last known position. /// /// This field is used to calculate the player's movement delta for network synchronization and other purposes. @@ -110,7 +110,7 @@ impl Player { log::error!("No gameprofile?. Impossible"); GameProfile { id: uuid::Uuid::new_v4(), - name: "".to_string(), + name: String::new(), properties: vec![], profile_actions: None, } @@ -137,7 +137,7 @@ impl Player { open_container: AtomicCell::new(None), carried_item: AtomicCell::new(None), teleport_id_count: AtomicI32::new(0), - abilities: Mutex::new(PlayerAbilities::default()), + abilities: Mutex::new(Abilities::default()), gamemode: AtomicCell::new(gamemode), watched_section: AtomicCell::new(Vector3::new(0, 0, 0)), last_position: AtomicCell::new(Vector3::new(0.0, 0.0, 0.0)), @@ -152,7 +152,7 @@ impl Player { self.living_entity.entity.world.remove_player(self).await; let watched = chunk_section_from_pos(&self.living_entity.entity.block_pos.load()); - let view_distance = get_view_distance(self).await as i32; + let view_distance = i32::from(get_view_distance(self).await); let cylindrical = Cylindrical::new(Vector2::new(watched.x, watched.z), view_distance); self.living_entity .entity @@ -256,7 +256,7 @@ impl Player { let standing_eye_height = self.living_entity.entity.standing_eye_height; box_pos.squared_magnitude(Vector3 { x: entity_pos.x, - y: entity_pos.y + standing_eye_height as f64, + y: entity_pos.y + f64::from(standing_eye_height), z: entity_pos.z, }) < d * d } @@ -277,7 +277,7 @@ impl Player { self.gameprofile.name, reason.to_pretty_console() ); - self.client.close() + self.client.close(); } pub async fn set_health(&self, health: f32, food: i32, food_saturation: f32) { @@ -330,15 +330,14 @@ impl Player { let mut packets = self.client.client_packets_queue.lock().await; while let Some(mut packet) = packets.pop_back() { match self.handle_play_packet(server, &mut packet).await { - Ok(_) => {} + Ok(()) => {} Err(e) => { if e.is_kick() { if let Some(kick_reason) = e.client_kick_reason() { - self.kick(TextComponent::text(&kick_reason)).await + self.kick(TextComponent::text(&kick_reason)).await; } else { self.kick(TextComponent::text(&format!( - "Error while reading incoming packet {}", - e + "Error while reading incoming packet {e}" ))) .await; } @@ -380,7 +379,7 @@ impl Player { Ok(()) } SSetPlayerGround::PACKET_ID => { - self.handle_player_ground(SSetPlayerGround::read(bytebuf)?); + self.handle_player_ground(&SSetPlayerGround::read(bytebuf)?); Ok(()) } SPlayerCommand::PACKET_ID => { @@ -421,7 +420,7 @@ impl Player { Ok(()) } SUseItem::PACKET_ID => { - self.handle_use_item(SUseItem::read(bytebuf)?); + self.handle_use_item(&SUseItem::read(bytebuf)?); Ok(()) } SSetHeldItem::PACKET_ID => { @@ -464,7 +463,7 @@ impl Player { /// Represents a player's abilities and special powers. /// /// This struct contains information about the player's current abilities, such as flight, invulnerability, and creative mode. -pub struct PlayerAbilities { +pub struct Abilities { /// Indicates whether the player is invulnerable to damage. pub invulnerable: bool, /// Indicates whether the player is currently flying. @@ -479,7 +478,7 @@ pub struct PlayerAbilities { pub walk_speed_fov: f32, } -impl Default for PlayerAbilities { +impl Default for Abilities { fn default() -> Self { Self { invulnerable: false, diff --git a/pumpkin/src/error.rs b/pumpkin/src/error.rs index 74fb5c0e7..d83e9a3e1 100644 --- a/pumpkin/src/error.rs +++ b/pumpkin/src/error.rs @@ -22,14 +22,20 @@ impl From for Box bool { - use InventoryError::*; + use InventoryError::{ + ClosedContainerInteract, InvalidPacket, InvalidSlot, LockError, + MultiplePlayersDragging, OutOfOrderDragging, PermissionError, + }; match self { InvalidSlot | ClosedContainerInteract(..) | InvalidPacket | PermissionError => true, LockError | OutOfOrderDragging | MultiplePlayersDragging => false, } } fn severity(&self) -> log::Level { - use InventoryError::*; + use InventoryError::{ + ClosedContainerInteract, InvalidPacket, InvalidSlot, LockError, + MultiplePlayersDragging, OutOfOrderDragging, PermissionError, + }; match self { LockError | InvalidSlot diff --git a/pumpkin/src/main.rs b/pumpkin/src/main.rs index 6d52e9197..a25ed3a4d 100644 --- a/pumpkin/src/main.rs +++ b/pumpkin/src/main.rs @@ -1,9 +1,9 @@ #![deny(clippy::all)] -// #![warn(clippy::pedantic)] +#![warn(clippy::pedantic)] // #![warn(clippy::restriction)] #![warn(clippy::nursery)] #![warn(clippy::cargo)] -// expect +// REMOVE SOME WHEN RELEASE #![expect(clippy::cargo_common_metadata)] #![expect(clippy::multiple_crate_versions)] #![expect(clippy::while_float)] @@ -11,6 +11,16 @@ #![expect(clippy::significant_drop_tightening)] #![expect(clippy::future_not_send)] #![expect(clippy::single_call_fn)] +#![expect(clippy::cast_sign_loss)] +#![expect(clippy::cast_possible_truncation)] +#![expect(clippy::cast_possible_wrap)] +#![expect(clippy::too_many_lines)] +#![expect(clippy::missing_panics_doc)] +#![expect(clippy::missing_errors_doc)] +#![expect(clippy::module_name_repetitions)] +#![expect(clippy::struct_excessive_bools)] +#![expect(clippy::many_single_char_names)] +#![expect(clippy::float_cmp)] #[cfg(target_os = "wasi")] compile_error!("Compiling for WASI targets is not supported!"); @@ -60,7 +70,7 @@ fn init_logger() { logger = logger.with_colors(ADVANCED_CONFIG.logging.color); logger = logger.with_threads(ADVANCED_CONFIG.logging.threads); - logger.init().unwrap() + logger.init().unwrap(); } } @@ -82,6 +92,7 @@ async fn main() -> io::Result<()> { use pumpkin_config::{ADVANCED_CONFIG, BASIC_CONFIG}; use pumpkin_core::text::{color::NamedColor, TextComponent}; use rcon::RCONServer; + use std::time::Instant; init_logger(); @@ -109,8 +120,6 @@ async fn main() -> io::Result<()> { std::process::exit(1); })); - use std::time::Instant; - let time = Instant::now(); // Setup the TCP server socket. @@ -173,7 +182,7 @@ async fn main() -> io::Result<()> { log::info!( "Accepted connection from: {} (id: {})", - scrub_address(&format!("{}", address)), + scrub_address(&format!("{address}")), id ); @@ -188,7 +197,7 @@ async fn main() -> io::Result<()> { { let open = client.poll().await; if open { - client.process_packets(&server).await + client.process_packets(&server).await; }; } if client @@ -206,7 +215,7 @@ async fn main() -> io::Result<()> { { let open = player.client.poll().await; if open { - player.process_packets(&server).await + player.process_packets(&server).await; }; } player.remove().await; diff --git a/pumpkin/src/proxy/velocity.rs b/pumpkin/src/proxy/velocity.rs index 37099bddc..fc5467fff 100644 --- a/pumpkin/src/proxy/velocity.rs +++ b/pumpkin/src/proxy/velocity.rs @@ -13,9 +13,9 @@ use thiserror::Error; use crate::client::{authentication::GameProfile, Client}; -/// Proxy implementation for Velocity by PaperMC -/// Sadly PaperMC does not care about 3th Parties providing support for Velocity, There is no documentation. -/// I had to understand the Code logic by looking at PaperMC's Velocity implementation: +/// Proxy implementation for Velocity by `PaperMC` +/// Sadly `PaperMC` does not care about 3th Parties providing support for Velocity, There is no documentation. +/// I had to understand the Code logic by looking at `PaperMC`'s Velocity implementation: type HmacSha256 = Hmac; @@ -59,6 +59,7 @@ pub async fn velocity_login(client: &Client) { .await; } +#[must_use] pub fn check_integrity(data: (&[u8], &[u8]), secret: &str) -> bool { let (signature, data_without_signature) = data; // Our fault, We can panic/expect ? @@ -80,7 +81,7 @@ fn read_game_profile(buf: &mut ByteBuffer) -> Result .get_list(|data| { let name = data.get_string()?; let value = data.get_string()?; - let signature = data.get_option(|data| data.get_string())?; + let signature = data.get_option(pumpkin_protocol::bytebuf::ByteBuffer::get_string)?; Ok(Property { name, diff --git a/pumpkin/src/rcon/mod.rs b/pumpkin/src/rcon/mod.rs index ce8aa4d3f..e8c18f0a1 100644 --- a/pumpkin/src/rcon/mod.rs +++ b/pumpkin/src/rcon/mod.rs @@ -95,15 +95,14 @@ impl RCONClient { } async fn poll(&mut self, server: &Server, password: &str) -> Result<(), PacketError> { - let packet = match self.receive_packet().await? { - Some(p) => p, - None => return Ok(()), + let Some(packet) = self.receive_packet().await? else { + return Ok(()); }; let config = &ADVANCED_CONFIG.rcon; match packet.get_type() { ServerboundPacket::Auth => { if packet.get_body() == password { - self.send(ClientboundPacket::AuthResponse, packet.get_id(), "".into()) + self.send(ClientboundPacket::AuthResponse, packet.get_id(), "") .await?; if config.logging.log_logged_successfully { log::info!("RCON ({}): Client logged in successfully", self.address); @@ -113,8 +112,7 @@ impl RCONClient { if config.logging.log_wrong_password { log::info!("RCON ({}): Client has tried wrong password", self.address); } - self.send(ClientboundPacket::AuthResponse, -1, "".into()) - .await?; + self.send(ClientboundPacket::AuthResponse, -1, "").await?; self.closed = true; } } @@ -133,7 +131,7 @@ impl RCONClient { if config.logging.log_commands { log::info!("RCON ({}): {}", self.address, line); } - self.send(ClientboundPacket::Output, packet.get_id(), line) + self.send(ClientboundPacket::Output, packet.get_id(), &line) .await?; } } @@ -156,7 +154,7 @@ impl RCONClient { &mut self, packet: ClientboundPacket, id: i32, - body: String, + body: &str, ) -> Result<(), PacketError> { let buf = packet.write_buf(id, body); self.connection diff --git a/pumpkin/src/rcon/packet.rs b/pumpkin/src/rcon/packet.rs index f4cdc7925..eb685bec2 100644 --- a/pumpkin/src/rcon/packet.rs +++ b/pumpkin/src/rcon/packet.rs @@ -13,7 +13,7 @@ use tokio::io::AsyncReadExt; pub enum ServerboundPacket { /// Typically, the first packet sent by the client, which is used to authenticate the connection with the server. Auth = 2, - /// This packet type represents a command issued to the server by a client. This can be a ConCommand such as kill or weather clear. + /// This packet type represents a command issued to the server by a client. This can be a `ConCommand` such as kill or weather clear. /// The response will vary depending on the command issued. ExecCommand = 3, } @@ -21,7 +21,7 @@ pub enum ServerboundPacket { impl ServerboundPacket { pub const fn from_i32(n: i32) -> Self { match n { - 3 => Self::Auth, + // 3 => Self::Auth, 2 => Self::ExecCommand, _ => Self::Auth, } @@ -32,21 +32,21 @@ impl ServerboundPacket { #[repr(i32)] /// Server -> Client pub enum ClientboundPacket { - /// This packet is a notification of the connection's current auth status. When the server receives an auth request, it will respond with an empty SERVERDATA_RESPONSE_VALUE, - /// followed immediately by a SERVERDATA_AUTH_RESPONSE indicating whether authentication succeeded or failed. Note that the status code is returned in the packet id field, so when pairing the response with the original auth request, you may need to look at the packet id of the preceeding SERVERDATA_RESPONSE_VALUE. + /// This packet is a notification of the connection's current auth status. When the server receives an auth request, it will respond with an empty `SERVERDATA_RESPONSE_VALUE`, + /// followed immediately by a `SERVERDATA_AUTH_RESPONSE` indicating whether authentication succeeded or failed. Note that the status code is returned in the packet id field, so when pairing the response with the original auth request, you may need to look at the packet id of the preceeding `SERVERDATA_RESPONSE_VALUE`. AuthResponse = 2, - /// A SERVERDATA_RESPONSE packet is the response to a SERVERDATA_EXECCOMMAND request. + /// A `SERVERDATA_RESPONSE` packet is the response to a `SERVERDATA_EXECCOMMAND` request. Output = 0, } impl ClientboundPacket { - pub fn write_buf(&self, id: i32, body: String) -> BytesMut { + pub fn write_buf(self, id: i32, body: &str) -> BytesMut { // let len = outgoing.len() as u64; let mut buf = BytesMut::new(); // 10 is for 4 bytes ty, 4 bytes id, and 2 terminating nul bytes. buf.put_i32_le(10 + body.len() as i32); buf.put_i32_le(id); - buf.put_i32_le(*self as i32); + buf.put_i32_le(self as i32); let bytes = body.as_bytes(); buf.put_slice(bytes); buf.put_u8(0); diff --git a/pumpkin/src/server/connection_cache.rs b/pumpkin/src/server/connection_cache.rs index b90a7d16b..0dd34b61a 100644 --- a/pumpkin/src/server/connection_cache.rs +++ b/pumpkin/src/server/connection_cache.rs @@ -113,8 +113,8 @@ impl CachedStatus { max: config.max_players, online: 0, sample: vec![Sample { - name: "".into(), - id: "".into(), + name: String::new(), + id: String::new(), }], }), description: config.motd.clone(), diff --git a/pumpkin/src/server/mod.rs b/pumpkin/src/server/mod.rs index 7d92064e8..5a72102c4 100644 --- a/pumpkin/src/server/mod.rs +++ b/pumpkin/src/server/mod.rs @@ -56,6 +56,7 @@ pub struct Server { impl Server { #[allow(clippy::new_without_default)] + #[must_use] pub fn new() -> Self { // TODO: only create when needed @@ -126,13 +127,13 @@ impl Server { P: ClientPacket, { for world in &self.worlds { - world.broadcast_packet_all(packet).await + world.broadcast_packet_all(packet).await; } } /// Searches every world for a player by name - pub async fn get_player_by_name(&self, name: &str) -> Option> { - for world in self.worlds.iter() { + pub fn get_player_by_name(&self, name: &str) -> Option> { + for world in &self.worlds { if let Some(player) = world.get_player_by_name(name) { return Some(player); } diff --git a/pumpkin/src/server/ticker.rs b/pumpkin/src/server/ticker.rs index 291b77777..a8395b6a6 100644 --- a/pumpkin/src/server/ticker.rs +++ b/pumpkin/src/server/ticker.rs @@ -8,6 +8,7 @@ pub struct Ticker { } impl Ticker { + #[must_use] pub fn new(tps: f32) -> Self { Self { tick_interval: Duration::from_millis((1000.0 / tps) as u64), diff --git a/pumpkin/src/world/mod.rs b/pumpkin/src/world/mod.rs index 9a422b49c..1fb6ec71f 100644 --- a/pumpkin/src/world/mod.rs +++ b/pumpkin/src/world/mod.rs @@ -43,6 +43,7 @@ pub struct World { } impl World { + #[must_use] pub fn load(level: Level) -> Self { Self { level: Arc::new(Mutex::new(level)), @@ -174,7 +175,7 @@ impl World { }, PlayerAction::UpdateListed(true), ], - }) + }); } player .client @@ -234,7 +235,7 @@ impl World { 0.0, 0.0, )) - .await + .await; } // entity meta data // set skin parts @@ -243,7 +244,7 @@ impl World { entity_id.into(), Metadata::new(17, VarInt(0), config.skin_parts), ); - self.broadcast_packet_all(&packet).await + self.broadcast_packet_all(&packet).await; } // Start waiting for level chunks, Sets the "Loading Terrain" screen @@ -266,12 +267,7 @@ impl World { level.mark_chunk_as_newly_watched(chunks); } - async fn spawn_world_chunks( - &self, - client: Arc, - chunks: Vec>, - distance: i32, - ) { + fn spawn_world_chunks(&self, client: Arc, chunks: Vec>, distance: i32) { if client.closed.load(std::sync::atomic::Ordering::Relaxed) { log::info!( "The connection with {} has closed before world chunks were spawned", @@ -286,7 +282,7 @@ impl World { let chunks = Arc::new(chunks); tokio::spawn(async move { let level = level.lock().await; - level.fetch_chunks(&chunks, sender) + level.fetch_chunks(&chunks, sender); }); tokio::spawn(async move { @@ -358,6 +354,6 @@ impl World { pub async fn remove_entity(&self, entity: &Entity) { self.broadcast_packet_all(&CRemoveEntities::new(&[entity.entity_id.into()])) - .await + .await; } } diff --git a/pumpkin/src/world/player_chunker.rs b/pumpkin/src/world/player_chunker.rs index 3e17def7f..4bff01998 100644 --- a/pumpkin/src/world/player_chunker.rs +++ b/pumpkin/src/world/player_chunker.rs @@ -32,7 +32,7 @@ pub async fn player_join(world: &World, player: Arc) { chunk_z: chunk_pos.z.into(), }) .await; - let view_distance = get_view_distance(&player).await as i32; + let view_distance = i32::from(get_view_distance(&player).await); dbg!(view_distance); let old_cylindrical = Cylindrical::new( Vector2::new(watched_section.x, watched_section.z), @@ -57,9 +57,7 @@ pub async fn player_join(world: &World, player: Arc) { ); if !loading_chunks.is_empty() { world.mark_chunks_as_watched(&loading_chunks).await; - world - .spawn_world_chunks(player.client.clone(), loading_chunks, view_distance) - .await; + world.spawn_world_chunks(player.client.clone(), loading_chunks, view_distance); } if !unloading_chunks.is_empty() { @@ -93,7 +91,7 @@ pub async fn update_position(player: &Player) { }) .await; - let view_distance = get_view_distance(player).await as i32; + let view_distance = i32::from(get_view_distance(player).await); let old_cylindrical = Cylindrical::new( Vector2::new(current_watched.x, current_watched.z), view_distance, @@ -119,8 +117,7 @@ pub async fn update_position(player: &Player) { entity.world.mark_chunks_as_watched(&loading_chunks).await; entity .world - .spawn_world_chunks(player.client.clone(), loading_chunks, view_distance) - .await; + .spawn_world_chunks(player.client.clone(), loading_chunks, view_distance); } if !unloading_chunks.is_empty() { @@ -145,6 +142,7 @@ pub async fn update_position(player: &Player) { } } +#[must_use] pub const fn chunk_section_from_pos(block_pos: &WorldPosition) -> Vector3 { let block_pos = block_pos.0; Vector3::new( diff --git a/pumpkin/src/world/scoreboard.rs b/pumpkin/src/world/scoreboard.rs index f82759548..a24f8396f 100644 --- a/pumpkin/src/world/scoreboard.rs +++ b/pumpkin/src/world/scoreboard.rs @@ -20,6 +20,7 @@ impl Default for Scoreboard { } impl Scoreboard { + #[must_use] pub fn new() -> Self { Self { objectives: HashMap::new(), @@ -87,6 +88,7 @@ pub struct ScoreboardObjective<'a> { } impl<'a> ScoreboardObjective<'a> { + #[must_use] pub const fn new( name: &'a str, display_name: TextComponent<'a>, @@ -111,6 +113,7 @@ pub struct ScoreboardScore<'a> { } impl<'a> ScoreboardScore<'a> { + #[must_use] pub const fn new( entity_name: &'a str, objective_name: &'a str,