feat(command): reimplement /setidletimeout (#1967)

* reimplemented `/setidletimeout` and fixed swappage of format args in error type helper method

* switched to use `register_permission_or_panic`
This commit is contained in:
Laptop59
2026-04-05 15:27:16 +05:30
committed by GitHub
parent 3825ee2b28
commit cd9068bd17
3 changed files with 47 additions and 53 deletions

View File

@@ -30,15 +30,15 @@ where
reader.set_cursor(reader_start);
Err(too_low_error_type.create(
reader,
TextComponent::text(value.to_string()),
TextComponent::text(min.to_string()),
TextComponent::text(value.to_string()),
))
} else if value > max {
reader.set_cursor(reader_start);
Err(too_high_error_type.create(
reader,
TextComponent::text(value.to_string()),
TextComponent::text(max.to_string()),
TextComponent::text(value.to_string()),
))
} else {
Ok(value)

View File

@@ -146,10 +146,6 @@ pub async fn default_dispatcher(
"minecraft:command.whitelist",
);
dispatcher.register(transfer::init_command_tree(), "minecraft:command.transfer");
dispatcher.register(
setidletimeout::init_command_tree(),
"minecraft:command.setidletimeout",
);
let mut dispatcher = {
let mut wrapper_dispatcher = CommandDispatcher::new();
@@ -160,6 +156,7 @@ pub async fn default_dispatcher(
difficulty::register(&mut dispatcher, registry);
help::register(&mut dispatcher, registry);
seed::register(&mut dispatcher, registry);
setidletimeout::register(&mut dispatcher, registry);
stop::register(&mut dispatcher, registry);
dispatcher
@@ -418,7 +415,6 @@ fn register_level_2_permissions(registry: &mut PermissionRegistry) {
.unwrap();
}
#[expect(clippy::too_many_lines)]
fn register_level_3_permissions(registry: &mut PermissionRegistry) {
// Register permissions for commands with PermissionLvl::Three
registry
@@ -519,11 +515,4 @@ fn register_level_3_permissions(registry: &mut PermissionRegistry) {
PermissionDefault::Op(PermissionLvl::Three),
))
.unwrap();
registry
.register_permission(Permission::new(
"minecraft:command.setidletimeout",
"Sets the time before idle players are kicked",
PermissionDefault::Op(PermissionLvl::Three),
))
.unwrap();
}

View File

@@ -1,55 +1,49 @@
use std::sync::atomic::Ordering;
use pumpkin_util::text::TextComponent;
use pumpkin_util::{
PermissionLvl,
permission::{Permission, PermissionDefault, PermissionRegistry},
text::TextComponent,
};
use crate::command::args::bounded_num::BoundedNumArgumentConsumer;
use crate::command::args::{Arg, GetCloned};
use crate::command::dispatcher::CommandError;
use crate::command::tree::CommandTree;
use crate::command::tree::builder::argument;
use crate::command::{CommandExecutor, CommandResult, CommandSender, args::ConsumedArgs};
const NAMES: [&str; 1] = ["setidletimeout"];
use crate::command::{
argument_builder::{ArgumentBuilder, argument, command},
argument_types::core::integer::IntegerArgumentType,
context::command_context::CommandContext,
node::{CommandExecutor, CommandExecutorResult, dispatcher::CommandDispatcher},
};
const DESCRIPTION: &str = "Sets the time before idle players are kicked from the server.";
const PERMISSION: &str = "minecraft:command.setidletimeout";
const ARG_MINUTES: &str = "minutes";
const fn minutes_consumer() -> BoundedNumArgumentConsumer<i32> {
BoundedNumArgumentConsumer::new().min(0).name(ARG_MINUTES)
}
struct SetIdleTimeoutExecutor;
impl CommandExecutor for SetIdleTimeoutExecutor {
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::Num(Ok(minutes))) = args.get_cloned(&ARG_MINUTES) else {
return Err(CommandError::InvalidConsumption(Some(ARG_MINUTES.into())));
};
let minutes: i32 = *context.get_argument(ARG_MINUTES)?;
let crate::command::args::bounded_num::Number::I32(minutes) = minutes else {
return Err(CommandError::InvalidConsumption(Some(ARG_MINUTES.into())));
};
server.player_idle_timeout.store(minutes, Ordering::Relaxed);
context
.server()
.player_idle_timeout
.store(minutes, Ordering::Relaxed);
{
if minutes == 0 {
sender.send_message(TextComponent::translate(
"commands.setidletimeout.success.disabled",
[],
))
context.source.send_feedback(
TextComponent::translate("commands.setidletimeout.success.disabled", []),
true,
)
} else {
sender.send_message(TextComponent::translate(
"commands.setidletimeout.success",
[TextComponent::text(minutes.to_string())],
))
context.source.send_feedback(
TextComponent::translate(
"commands.setidletimeout.success",
[TextComponent::text(minutes.to_string())],
),
true,
)
}
}
.await;
@@ -59,8 +53,19 @@ impl CommandExecutor for SetIdleTimeoutExecutor {
}
}
#[must_use]
pub fn init_command_tree() -> CommandTree {
CommandTree::new(NAMES, DESCRIPTION)
.then(argument(ARG_MINUTES, minutes_consumer()).execute(SetIdleTimeoutExecutor))
pub fn register(dispatcher: &mut CommandDispatcher, registry: &mut PermissionRegistry) {
registry.register_permission_or_panic(Permission::new(
PERMISSION,
DESCRIPTION,
PermissionDefault::Op(PermissionLvl::Three),
));
dispatcher.register(
command("setidletimeout", DESCRIPTION)
.requires(PERMISSION)
.then(
argument(ARG_MINUTES, IntegerArgumentType::with_min(0))
.executes(SetIdleTimeoutExecutor),
),
);
}