mirror of
https://github.com/Pumpkin-MC/Pumpkin.git
synced 2026-08-30 20:14:23 +00:00
chore(command): reimplemented /difficulty (#1924)
This commit is contained in:
@@ -25,6 +25,32 @@ pub enum Difficulty {
|
||||
Hard = 3,
|
||||
}
|
||||
|
||||
impl Difficulty {
|
||||
/// Gets the lowercase name of this difficulty.
|
||||
/// For example, [`Difficulty::Peaceful`] will yield `"peaceful"`.
|
||||
#[must_use]
|
||||
pub const fn name(self) -> &'static str {
|
||||
match self {
|
||||
Self::Peaceful => "peaceful",
|
||||
Self::Easy => "easy",
|
||||
Self::Normal => "normal",
|
||||
Self::Hard => "hard",
|
||||
}
|
||||
}
|
||||
|
||||
/// Gets the translation key of this difficulty.
|
||||
/// For example, [`Difficulty::Peaceful`] will yield `"options.difficulty.peaceful"`.
|
||||
#[must_use]
|
||||
pub const fn translation_key(self) -> &'static str {
|
||||
match self {
|
||||
Self::Peaceful => "options.difficulty.peaceful",
|
||||
Self::Easy => "options.difficulty.easy",
|
||||
Self::Normal => "options.difficulty.normal",
|
||||
Self::Hard => "options.difficulty.hard",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl FromStr for Difficulty {
|
||||
type Err = ParseDifficultyError;
|
||||
|
||||
|
||||
@@ -98,15 +98,19 @@ pub async fn send_c_commands_packet(
|
||||
.map(|i| i.try_into().expect("i32 limit reached for ids"));
|
||||
|
||||
// TODO:
|
||||
//
|
||||
// As stated in the previous TODO, after
|
||||
// we can get a reference to an Arc of Server,
|
||||
// we can add the permission checking.
|
||||
//
|
||||
// Luckily, for now the new dispatcher
|
||||
// only has the /help commands which
|
||||
// is accessible to everyone by default.
|
||||
let satisfies_requirements = true;
|
||||
// Right now, we incorrectly assume that
|
||||
// requirements are always satisfied. Hopefully
|
||||
// this can be fixed once the `/op` and `/deop` commands
|
||||
// are reimplemented with the Arcs, after which we can uncomment
|
||||
// the following line instead of the current one:
|
||||
//
|
||||
// let satisfies_requirements = node.requirements().evaluate(&source).await;
|
||||
let satisfies_requirements = true;
|
||||
|
||||
match node {
|
||||
AttachedNode::Root(_) => {
|
||||
|
||||
@@ -1,37 +1,35 @@
|
||||
use crate::command::CommandResult;
|
||||
use crate::command::args::difficulty::DifficultyArgumentConsumer;
|
||||
use crate::command::args::{Arg, GetCloned};
|
||||
use crate::command::dispatcher::CommandError::{self, InvalidConsumption};
|
||||
use crate::command::tree::builder::argument;
|
||||
use crate::command::{CommandExecutor, CommandSender, args::ConsumedArgs, tree::CommandTree};
|
||||
use crate::command::argument_builder::{ArgumentBuilder, command, literal};
|
||||
use crate::command::context::command_context::CommandContext;
|
||||
use crate::command::errors::error_types::CommandErrorType;
|
||||
use crate::command::node::dispatcher::CommandDispatcher;
|
||||
use crate::command::node::{CommandExecutor, CommandExecutorResult};
|
||||
|
||||
use pumpkin_util::permission::{Permission, PermissionDefault, PermissionRegistry};
|
||||
use pumpkin_util::text::TextComponent;
|
||||
use pumpkin_util::{Difficulty, PermissionLvl};
|
||||
|
||||
const NAMES: [&str; 1] = ["difficulty"];
|
||||
const DESCRIPTION: &str = "Query or change the difficulty of the world.";
|
||||
const PERMISSION: &str = "minecraft:command.difficulty";
|
||||
|
||||
const DESCRIPTION: &str = "Change the difficulty of the world.";
|
||||
|
||||
pub const ARG_DIFFICULTY: &str = "difficulty";
|
||||
const FAILURE_ERROR_TYPE: CommandErrorType<1> =
|
||||
CommandErrorType::new("commands.difficulty.failure");
|
||||
|
||||
struct DifficultyQueryExecutor;
|
||||
|
||||
impl CommandExecutor for DifficultyQueryExecutor {
|
||||
fn execute<'a>(
|
||||
&'a self,
|
||||
sender: &'a CommandSender,
|
||||
server: &'a crate::server::Server,
|
||||
_args: &'a ConsumedArgs<'a>,
|
||||
) -> CommandResult<'a> {
|
||||
fn execute<'a>(&'a self, context: &'a CommandContext) -> CommandExecutorResult<'a> {
|
||||
Box::pin(async move {
|
||||
let difficulty = server.get_difficulty();
|
||||
let difficulty_string = format!("{difficulty:?}").to_lowercase();
|
||||
let translation_key = format!("options.difficulty.{difficulty_string}");
|
||||
let difficulty = context.server().get_difficulty();
|
||||
|
||||
sender
|
||||
.send_message(TextComponent::translate(
|
||||
"commands.difficulty.query",
|
||||
[TextComponent::translate(translation_key, [])],
|
||||
))
|
||||
context
|
||||
.source
|
||||
.send_feedback(
|
||||
TextComponent::translate(
|
||||
"commands.difficulty.query",
|
||||
[TextComponent::translate(difficulty.translation_key(), [])],
|
||||
),
|
||||
false,
|
||||
)
|
||||
.await;
|
||||
|
||||
Ok(difficulty as i32)
|
||||
@@ -39,41 +37,34 @@ impl CommandExecutor for DifficultyQueryExecutor {
|
||||
}
|
||||
}
|
||||
|
||||
struct DifficultySetExecutor;
|
||||
struct DifficultySetExecutor(Difficulty);
|
||||
|
||||
impl CommandExecutor for DifficultySetExecutor {
|
||||
fn execute<'a>(
|
||||
&'a self,
|
||||
sender: &'a CommandSender,
|
||||
server: &'a crate::server::Server,
|
||||
args: &'a ConsumedArgs<'a>,
|
||||
) -> CommandResult<'a> {
|
||||
fn execute<'a>(&'a self, context: &'a CommandContext) -> CommandExecutorResult<'a> {
|
||||
Box::pin(async move {
|
||||
let Some(Arg::Difficulty(difficulty)) = args.get_cloned(&ARG_DIFFICULTY) else {
|
||||
return Err(InvalidConsumption(Some(ARG_DIFFICULTY.into())));
|
||||
};
|
||||
|
||||
let difficulty_string = format!("{difficulty:?}").to_lowercase();
|
||||
let translation_key = format!("options.difficulty.{difficulty_string}");
|
||||
let difficulty = self.0;
|
||||
let server = context.server();
|
||||
|
||||
{
|
||||
let level_info = server.level_info.load();
|
||||
|
||||
if level_info.difficulty == difficulty {
|
||||
return Err(CommandError::CommandFailed(TextComponent::translate(
|
||||
"commands.difficulty.failure",
|
||||
[TextComponent::translate(translation_key, [])],
|
||||
)));
|
||||
return Err(FAILURE_ERROR_TYPE
|
||||
.create_without_context(TextComponent::text(difficulty.name())));
|
||||
}
|
||||
}
|
||||
|
||||
server.set_difficulty(difficulty, true).await;
|
||||
|
||||
sender
|
||||
.send_message(TextComponent::translate(
|
||||
"commands.difficulty.success",
|
||||
[TextComponent::translate(translation_key, [])],
|
||||
))
|
||||
context
|
||||
.source
|
||||
.send_feedback(
|
||||
TextComponent::translate(
|
||||
"commands.difficulty.success",
|
||||
[TextComponent::translate(difficulty.translation_key(), [])],
|
||||
),
|
||||
true,
|
||||
)
|
||||
.await;
|
||||
|
||||
Ok(0)
|
||||
@@ -81,9 +72,22 @@ impl CommandExecutor for DifficultySetExecutor {
|
||||
}
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn init_command_tree() -> CommandTree {
|
||||
CommandTree::new(NAMES, DESCRIPTION)
|
||||
.execute(DifficultyQueryExecutor)
|
||||
.then(argument(ARG_DIFFICULTY, DifficultyArgumentConsumer).execute(DifficultySetExecutor))
|
||||
pub fn register(dispatcher: &mut CommandDispatcher, registry: &mut PermissionRegistry) {
|
||||
registry
|
||||
.register_permission(Permission::new(
|
||||
PERMISSION,
|
||||
DESCRIPTION,
|
||||
PermissionDefault::Op(PermissionLvl::Two),
|
||||
))
|
||||
.expect("Permission should have registered successfully");
|
||||
|
||||
dispatcher.register(
|
||||
command("difficulty", DESCRIPTION)
|
||||
.requires(PERMISSION)
|
||||
.then(literal("peaceful").executes(DifficultySetExecutor(Difficulty::Peaceful)))
|
||||
.then(literal("easy").executes(DifficultySetExecutor(Difficulty::Easy)))
|
||||
.then(literal("normal").executes(DifficultySetExecutor(Difficulty::Normal)))
|
||||
.then(literal("hard").executes(DifficultySetExecutor(Difficulty::Hard)))
|
||||
.executes(DifficultyQueryExecutor),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -113,10 +113,6 @@ pub async fn default_dispatcher(
|
||||
dispatcher.register(say::init_command_tree(), "minecraft:command.say");
|
||||
dispatcher.register(gamemode::init_command_tree(), "minecraft:command.gamemode");
|
||||
dispatcher.register(gamerule::init_command_tree(), "minecraft:command.gamerule");
|
||||
dispatcher.register(
|
||||
difficulty::init_command_tree(),
|
||||
"minecraft:command.difficulty",
|
||||
);
|
||||
dispatcher.register(
|
||||
stopsound::init_command_tree(),
|
||||
"minecraft:command.stopsound",
|
||||
@@ -161,6 +157,7 @@ pub async fn default_dispatcher(
|
||||
wrapper_dispatcher
|
||||
};
|
||||
|
||||
difficulty::register(&mut dispatcher, registry);
|
||||
help::register(&mut dispatcher, registry);
|
||||
seed::register(&mut dispatcher, registry);
|
||||
stop::register(&mut dispatcher, registry);
|
||||
@@ -382,13 +379,6 @@ fn register_level_2_permissions(registry: &mut PermissionRegistry) {
|
||||
PermissionDefault::Op(PermissionLvl::Two),
|
||||
))
|
||||
.unwrap();
|
||||
registry
|
||||
.register_permission(Permission::new(
|
||||
"minecraft:command.difficulty",
|
||||
"Sets the difficulty of the world",
|
||||
PermissionDefault::Op(PermissionLvl::Two),
|
||||
))
|
||||
.unwrap();
|
||||
registry
|
||||
.register_permission(Permission::new(
|
||||
"minecraft:command.data",
|
||||
|
||||
Reference in New Issue
Block a user