From fa594799a8a4c43253ee693a18b6c0fa037f822e Mon Sep 17 00:00:00 2001 From: kyled Date: Fri, 6 Dec 2024 18:03:10 -0500 Subject: [PATCH] Fixs issues @Commandcracker found in review - Move PermissionLvl to core and removed OpLevel - Move ops.json to /data/ops.json - Fix permissions issue with /op command - Shorten /op command description --- pumpkin-config/src/lib.rs | 7 +-- pumpkin-config/src/op.rs | 62 +++++++------------- pumpkin-core/src/lib.rs | 1 + pumpkin-core/src/permission.rs | 55 +++++++++++++++++ pumpkin/src/command/commands/cmd_fill.rs | 3 +- pumpkin/src/command/commands/cmd_gamemode.rs | 2 +- pumpkin/src/command/commands/cmd_give.rs | 2 +- pumpkin/src/command/commands/cmd_op.rs | 29 +++++---- pumpkin/src/command/commands/cmd_say.rs | 14 ++--- pumpkin/src/command/commands/cmd_seed.rs | 2 +- pumpkin/src/command/commands/cmd_setblock.rs | 2 +- pumpkin/src/command/commands/cmd_stop.rs | 2 +- pumpkin/src/command/commands/cmd_teleport.rs | 2 +- pumpkin/src/command/commands/cmd_time.rs | 10 ++-- pumpkin/src/command/commands/cmd_transfer.rs | 2 +- pumpkin/src/command/mod.rs | 3 +- pumpkin/src/entity/player.rs | 30 ++-------- pumpkin/src/server/json_config.rs | 2 +- 18 files changed, 121 insertions(+), 109 deletions(-) create mode 100644 pumpkin-core/src/permission.rs diff --git a/pumpkin-config/src/lib.rs b/pumpkin-config/src/lib.rs index 6370af32f..18f0d7d37 100644 --- a/pumpkin-config/src/lib.rs +++ b/pumpkin-config/src/lib.rs @@ -1,7 +1,6 @@ use log::warn; use logging::LoggingConfig; -use op::OpLevel; -use pumpkin_core::{Difficulty, GameMode}; +use pumpkin_core::{permission::PermissionLvl, Difficulty, GameMode}; use query::QueryConfig; use serde::{de::DeserializeOwned, Deserialize, Serialize}; @@ -79,7 +78,7 @@ pub struct BasicConfiguration { /// The default game difficulty. pub default_difficulty: Difficulty, /// The op level assign by the /op command - pub op_permission_level: OpLevel, + pub op_permission_level: PermissionLvl, /// Whether the Nether dimension is enabled. pub allow_nether: bool, /// Whether the server is in hardcore mode. @@ -110,7 +109,7 @@ impl Default for BasicConfiguration { view_distance: 10, simulation_distance: 10, default_difficulty: Difficulty::Normal, - op_permission_level: OpLevel::Owner, + op_permission_level: PermissionLvl::Four, allow_nether: true, hardcore: false, online_mode: true, diff --git a/pumpkin-config/src/op.rs b/pumpkin-config/src/op.rs index 077654531..edbd71bca 100644 --- a/pumpkin-config/src/op.rs +++ b/pumpkin-config/src/op.rs @@ -1,49 +1,27 @@ -use serde::{Deserialize, Deserializer, Serialize, Serializer}; +use pumpkin_core::permission::PermissionLvl; +use serde::{Deserialize, Serialize}; use uuid::Uuid; -#[derive(Clone, Copy)] -#[repr(u8)] -pub enum OpLevel { - None = 0, - Basic = 1, - Moderator = 2, - Admin = 3, - Owner = 4, -} - -impl Serialize for OpLevel { - fn serialize(&self, serializer: S) -> Result<::Ok, ::Error> - where - S: Serializer, - { - serializer.serialize_u8(*self as u8) - } -} - -impl<'de> Deserialize<'de> for OpLevel { - fn deserialize(deserializer: D) -> Result - where - D: Deserializer<'de>, - { - let value = u8::deserialize(deserializer)?; - match value { - 0 => Ok(OpLevel::None), - 1 => Ok(OpLevel::Basic), - 2 => Ok(OpLevel::Moderator), - 3 => Ok(OpLevel::Admin), - 4 => Ok(OpLevel::Owner), - _ => Err(serde::de::Error::custom(format!( - "Invalid value for OpLevel: {}", - value - ))), - } - } -} - -#[derive(Serialize, Deserialize, Clone)] +#[derive(Serialize, Deserialize, Clone, Default)] pub struct Op { pub uuid: Uuid, pub name: String, - pub level: OpLevel, + pub level: PermissionLvl, pub bypasses_player_limit: bool, } + +impl Op { + pub fn new( + uuid: Uuid, + name: String, + level: PermissionLvl, + bypasses_player_limit: bool, + ) -> Self { + Self { + uuid, + name, + level, + bypasses_player_limit, + } + } +} diff --git a/pumpkin-core/src/lib.rs b/pumpkin-core/src/lib.rs index f566404df..35feb51a7 100644 --- a/pumpkin-core/src/lib.rs +++ b/pumpkin-core/src/lib.rs @@ -1,5 +1,6 @@ pub mod gamemode; pub mod math; +pub mod permission; pub mod random; pub mod text; diff --git a/pumpkin-core/src/permission.rs b/pumpkin-core/src/permission.rs new file mode 100644 index 000000000..0a3d1abbd --- /dev/null +++ b/pumpkin-core/src/permission.rs @@ -0,0 +1,55 @@ +use num_derive::{FromPrimitive, ToPrimitive}; +use serde::{Deserialize, Deserializer, Serialize, Serializer}; + +/// Represents the player's permission level +/// +/// Permission levels determine the player's access to commands and server operations. +/// Each numeric level corresponds to a specific role: +/// - `Zero`: None +/// - `One`: Basic +/// - `Two`: Moderator +/// - `Three`: Admin +/// - `Four`: Owner +#[derive(FromPrimitive, ToPrimitive, Clone, Copy, Default, PartialEq, Eq)] +#[repr(i8)] +pub enum PermissionLvl { + #[default] + Zero = 0, + Two = 2, + Three = 3, + Four = 4, +} + +impl PartialOrd for PermissionLvl { + fn partial_cmp(&self, other: &Self) -> Option { + (*self as u8).partial_cmp(&(*other as u8)) + } +} + +impl Serialize for PermissionLvl { + fn serialize(&self, serializer: S) -> Result<::Ok, ::Error> + where + S: Serializer, + { + serializer.serialize_u8(*self as u8) + } +} + +impl<'de> Deserialize<'de> for PermissionLvl { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + let value = u8::deserialize(deserializer)?; + match value { + 0 => Ok(PermissionLvl::Zero), + 2 => Ok(PermissionLvl::Two), + 3 => Ok(PermissionLvl::Three), + 4 => Ok(PermissionLvl::Four), + _ => Err(serde::de::Error::custom(format!( + "Invalid value for OpLevel: {}", + value + ))), + } + } +} diff --git a/pumpkin/src/command/commands/cmd_fill.rs b/pumpkin/src/command/commands/cmd_fill.rs index 031ba1143..596ddbe0a 100644 --- a/pumpkin/src/command/commands/cmd_fill.rs +++ b/pumpkin/src/command/commands/cmd_fill.rs @@ -4,10 +4,11 @@ use crate::command::args::{ConsumedArgs, FindArg}; use crate::command::tree::CommandTree; use crate::command::tree_builder::{argument, literal, require}; use crate::command::{CommandError, CommandExecutor, CommandSender}; -use crate::entity::player::PermissionLvl; + use async_trait::async_trait; use pumpkin_core::math::position::WorldPosition; use pumpkin_core::math::vector3::Vector3; +use pumpkin_core::permission::PermissionLvl; use pumpkin_core::text::TextComponent; const NAMES: [&str; 1] = ["fill"]; diff --git a/pumpkin/src/command/commands/cmd_gamemode.rs b/pumpkin/src/command/commands/cmd_gamemode.rs index faab95375..9112b170c 100644 --- a/pumpkin/src/command/commands/cmd_gamemode.rs +++ b/pumpkin/src/command/commands/cmd_gamemode.rs @@ -3,8 +3,8 @@ use async_trait::async_trait; use crate::command::args::arg_gamemode::GamemodeArgumentConsumer; use crate::command::args::GetCloned; -use crate::entity::player::PermissionLvl; use crate::TextComponent; +use pumpkin_core::permission::PermissionLvl; use crate::command::args::arg_players::PlayersArgumentConsumer; diff --git a/pumpkin/src/command/commands/cmd_give.rs b/pumpkin/src/command/commands/cmd_give.rs index 36edb640c..f306e114e 100644 --- a/pumpkin/src/command/commands/cmd_give.rs +++ b/pumpkin/src/command/commands/cmd_give.rs @@ -9,7 +9,7 @@ use crate::command::args::{ConsumedArgs, FindArg, FindArgDefaultName}; use crate::command::tree::CommandTree; use crate::command::tree_builder::{argument, argument_default_name, require}; use crate::command::{CommandError, CommandExecutor, CommandSender}; -use crate::entity::player::PermissionLvl; +use pumpkin_core::permission::PermissionLvl; const NAMES: [&str; 1] = ["give"]; diff --git a/pumpkin/src/command/commands/cmd_op.rs b/pumpkin/src/command/commands/cmd_op.rs index d8d2fea71..ed830fa51 100644 --- a/pumpkin/src/command/commands/cmd_op.rs +++ b/pumpkin/src/command/commands/cmd_op.rs @@ -5,16 +5,16 @@ use crate::{ tree_builder::{argument, require}, CommandError, CommandExecutor, CommandSender, }, - entity::player::PermissionLvl, server::json_config::{SaveJSONConfiguration, OPERATOR_CONFIG}, }; use async_trait::async_trait; use pumpkin_config::{op::Op, BASIC_CONFIG}; +use pumpkin_core::permission::PermissionLvl; use pumpkin_core::text::TextComponent; use CommandError::InvalidConsumption; const NAMES: [&str; 1] = ["op"]; -const DESCRIPTION: &str = "Specifies one or more game profiles (player profiles). Must be a player name (should be a real one if the server is in online mode) or a player-type target selector"; +const DESCRIPTION: &str = "Grants operator status to a player."; const ARG_TARGET: &str = "player"; struct OpExecutor; @@ -35,28 +35,31 @@ impl CommandExecutor for OpExecutor { // log each player to the console. for player in targets { - let op_entry = Op { - uuid: player.gameprofile.id, - name: player.gameprofile.name.clone(), - level: BASIC_CONFIG.op_permission_level, - bypasses_player_limit: false, + let new_level = if BASIC_CONFIG.op_permission_level > sender.permission_lvl() { + sender.permission_lvl() + } else { + BASIC_CONFIG.op_permission_level }; + + let op_entry = Op::new( + player.gameprofile.id, + player.gameprofile.name.clone(), + new_level, + false, + ); if let Some(op) = config .ops .iter_mut() .find(|o| o.uuid == player.gameprofile.id) { - op.level = BASIC_CONFIG.op_permission_level; + op.level = new_level; } else { config.ops.push(op_entry); } config.save(); player - .set_permission_lvl( - BASIC_CONFIG.op_permission_level.into(), - &server.command_dispatcher, - ) + .set_permission_lvl(new_level, &server.command_dispatcher) .await; let player_name = player.gameprofile.name.clone(); @@ -71,7 +74,7 @@ impl CommandExecutor for OpExecutor { pub fn init_command_tree<'a>() -> CommandTree<'a> { CommandTree::new(NAMES, DESCRIPTION).with_child( - require(&|sender| sender.has_permission_lvl(PermissionLvl::Four)) + require(&|sender| sender.has_permission_lvl(PermissionLvl::Three)) .with_child(argument(ARG_TARGET, &PlayersArgumentConsumer).execute(&OpExecutor)), ) } diff --git a/pumpkin/src/command/commands/cmd_say.rs b/pumpkin/src/command/commands/cmd_say.rs index 66b743385..7ced92b6d 100644 --- a/pumpkin/src/command/commands/cmd_say.rs +++ b/pumpkin/src/command/commands/cmd_say.rs @@ -2,15 +2,13 @@ use async_trait::async_trait; use pumpkin_core::text::TextComponent; use pumpkin_protocol::client::play::CSystemChatMessage; -use crate::{ - command::{ - args::{arg_message::MsgArgConsumer, Arg, ConsumedArgs}, - tree::CommandTree, - tree_builder::{argument, require}, - CommandError, CommandExecutor, CommandSender, - }, - entity::player::PermissionLvl, +use crate::command::{ + args::{arg_message::MsgArgConsumer, Arg, ConsumedArgs}, + tree::CommandTree, + tree_builder::{argument, require}, + CommandError, CommandExecutor, CommandSender, }; +use pumpkin_core::permission::PermissionLvl; use CommandError::InvalidConsumption; const NAMES: [&str; 1] = ["say"]; diff --git a/pumpkin/src/command/commands/cmd_seed.rs b/pumpkin/src/command/commands/cmd_seed.rs index 653697aa7..d3ed719d5 100644 --- a/pumpkin/src/command/commands/cmd_seed.rs +++ b/pumpkin/src/command/commands/cmd_seed.rs @@ -2,8 +2,8 @@ use crate::command::tree_builder::require; use crate::command::{ args::ConsumedArgs, tree::CommandTree, CommandError, CommandExecutor, CommandSender, }; -use crate::entity::player::PermissionLvl; use async_trait::async_trait; +use pumpkin_core::permission::PermissionLvl; use pumpkin_core::text::click::ClickEvent; use pumpkin_core::text::hover::HoverEvent; use pumpkin_core::text::{color::NamedColor, TextComponent}; diff --git a/pumpkin/src/command/commands/cmd_setblock.rs b/pumpkin/src/command/commands/cmd_setblock.rs index 4bd3b2644..b17c961c9 100644 --- a/pumpkin/src/command/commands/cmd_setblock.rs +++ b/pumpkin/src/command/commands/cmd_setblock.rs @@ -8,7 +8,7 @@ use crate::command::args::{ConsumedArgs, FindArg}; use crate::command::tree::CommandTree; use crate::command::tree_builder::{argument, literal, require}; use crate::command::{CommandError, CommandExecutor, CommandSender}; -use crate::entity::player::PermissionLvl; +use pumpkin_core::permission::PermissionLvl; const NAMES: [&str; 1] = ["setblock"]; diff --git a/pumpkin/src/command/commands/cmd_stop.rs b/pumpkin/src/command/commands/cmd_stop.rs index 0f1bc7afa..a15b6184b 100644 --- a/pumpkin/src/command/commands/cmd_stop.rs +++ b/pumpkin/src/command/commands/cmd_stop.rs @@ -6,7 +6,7 @@ use crate::command::args::ConsumedArgs; use crate::command::tree::CommandTree; use crate::command::tree_builder::require; use crate::command::{CommandError, CommandExecutor, CommandSender}; -use crate::entity::player::PermissionLvl; +use pumpkin_core::permission::PermissionLvl; const NAMES: [&str; 1] = ["stop"]; diff --git a/pumpkin/src/command/commands/cmd_teleport.rs b/pumpkin/src/command/commands/cmd_teleport.rs index fc368db16..ff6819ea9 100644 --- a/pumpkin/src/command/commands/cmd_teleport.rs +++ b/pumpkin/src/command/commands/cmd_teleport.rs @@ -12,7 +12,7 @@ use crate::command::tree::CommandTree; use crate::command::tree_builder::{argument, literal, require}; use crate::command::CommandError; use crate::command::{CommandExecutor, CommandSender}; -use crate::entity::player::PermissionLvl; +use pumpkin_core::permission::PermissionLvl; const NAMES: [&str; 2] = ["teleport", "tp"]; const DESCRIPTION: &str = "Teleports entities, including players."; // todo diff --git a/pumpkin/src/command/commands/cmd_time.rs b/pumpkin/src/command/commands/cmd_time.rs index ad2894018..eefc582e5 100644 --- a/pumpkin/src/command/commands/cmd_time.rs +++ b/pumpkin/src/command/commands/cmd_time.rs @@ -5,13 +5,11 @@ use pumpkin_core::text::TextComponent; use crate::command::args::arg_bounded_num::BoundedNumArgumentConsumer; use crate::command::args::FindArgDefaultName; use crate::command::tree_builder::{argument_default_name, literal}; -use crate::{ - command::{ - tree::CommandTree, tree_builder::require, CommandError, CommandExecutor, CommandSender, - ConsumedArgs, - }, - entity::player::PermissionLvl, +use crate::command::{ + tree::CommandTree, tree_builder::require, CommandError, CommandExecutor, CommandSender, + ConsumedArgs, }; +use pumpkin_core::permission::PermissionLvl; const NAMES: [&str; 1] = ["time"]; diff --git a/pumpkin/src/command/commands/cmd_transfer.rs b/pumpkin/src/command/commands/cmd_transfer.rs index b73f2418b..0d97f1eba 100644 --- a/pumpkin/src/command/commands/cmd_transfer.rs +++ b/pumpkin/src/command/commands/cmd_transfer.rs @@ -13,7 +13,7 @@ use crate::command::tree_builder::{argument, argument_default_name, require}; use crate::command::{ args::ConsumedArgs, tree::CommandTree, CommandError, CommandExecutor, CommandSender, }; -use crate::entity::player::PermissionLvl; +use pumpkin_core::permission::PermissionLvl; const NAMES: [&str; 1] = ["transfer"]; diff --git a/pumpkin/src/command/mod.rs b/pumpkin/src/command/mod.rs index c0aa849f9..b7e81aea0 100644 --- a/pumpkin/src/command/mod.rs +++ b/pumpkin/src/command/mod.rs @@ -4,7 +4,7 @@ use std::sync::Arc; use crate::command::commands::cmd_seed; use crate::command::commands::{cmd_bossbar, cmd_transfer}; use crate::command::dispatcher::CommandDispatcher; -use crate::entity::player::{PermissionLvl, Player}; +use crate::entity::player::Player; use crate::server::Server; use crate::world::World; use args::ConsumedArgs; @@ -17,6 +17,7 @@ use commands::{ }; use dispatcher::CommandError; use pumpkin_core::math::vector3::Vector3; +use pumpkin_core::permission::PermissionLvl; use pumpkin_core::text::TextComponent; pub mod args; diff --git a/pumpkin/src/entity/player.rs b/pumpkin/src/entity/player.rs index 952995b5f..e4ccb13f0 100644 --- a/pumpkin/src/entity/player.rs +++ b/pumpkin/src/entity/player.rs @@ -9,8 +9,8 @@ use std::{ use crossbeam::atomic::AtomicCell; use itertools::Itertools; -use num_derive::{FromPrimitive, ToPrimitive}; -use pumpkin_config::{op::OpLevel, ADVANCED_CONFIG}; +use num_derive::FromPrimitive; +use pumpkin_config::ADVANCED_CONFIG; use pumpkin_core::{ math::{ boundingbox::{BoundingBox, BoundingBoxSize}, @@ -18,6 +18,7 @@ use pumpkin_core::{ vector2::Vector2, vector3::Vector3, }, + permission::PermissionLvl, text::TextComponent, GameMode, }; @@ -230,7 +231,7 @@ impl Player { .iter() .find(|op| op.uuid == gameprofile_clone.id) .map_or(parking_lot::Mutex::new(PermissionLvl::Zero), |op| { - parking_lot::Mutex::new(op.level.into()) + parking_lot::Mutex::new(op.level) }), } } @@ -873,26 +874,3 @@ pub enum ChatMode { /// All messages should be hidden Hidden, } - -/// the player's permission level -#[derive(FromPrimitive, ToPrimitive, Clone, Copy)] -#[repr(i8)] -pub enum PermissionLvl { - Zero = 0, - One = 1, - Two = 2, - Three = 3, - Four = 4, -} - -impl From for PermissionLvl { - fn from(op: OpLevel) -> Self { - match op { - OpLevel::None => PermissionLvl::Zero, - OpLevel::Basic => PermissionLvl::One, - OpLevel::Moderator => PermissionLvl::Two, - OpLevel::Admin => PermissionLvl::Three, - OpLevel::Owner => PermissionLvl::Four, - } - } -} diff --git a/pumpkin/src/server/json_config.rs b/pumpkin/src/server/json_config.rs index c756a1d65..ecd65607e 100644 --- a/pumpkin/src/server/json_config.rs +++ b/pumpkin/src/server/json_config.rs @@ -82,7 +82,7 @@ pub trait SaveJSONConfiguration: LoadJSONConfiguration { impl LoadJSONConfiguration for OperatorConfig { fn get_path() -> &'static Path { - Path::new("ops.json") + Path::new("data/ops.json") } fn validate(&self) { // TODO: Validate the operator configuration