From bfb3840b945f2a8d53864cd7468a24027658dd24 Mon Sep 17 00:00:00 2001 From: user622628252416 Date: Mon, 19 Aug 2024 19:26:02 +0200 Subject: [PATCH] add help command --- pumpkin/src/commands/cmd_gamemode.rs | 2 +- pumpkin/src/commands/cmd_help.rs | 61 ++++++++++++++++++++++++++++ pumpkin/src/commands/cmd_pumpkin.rs | 2 +- pumpkin/src/commands/cmd_stop.rs | 2 +- pumpkin/src/commands/mod.rs | 5 ++- pumpkin/src/commands/tree.rs | 4 +- 6 files changed, 69 insertions(+), 7 deletions(-) create mode 100644 pumpkin/src/commands/cmd_help.rs diff --git a/pumpkin/src/commands/cmd_gamemode.rs b/pumpkin/src/commands/cmd_gamemode.rs index 1b80de38a..4373a7ff8 100644 --- a/pumpkin/src/commands/cmd_gamemode.rs +++ b/pumpkin/src/commands/cmd_gamemode.rs @@ -14,7 +14,7 @@ use crate::entity::player::GameMode; pub(crate) const NAME: &str = "gamemode"; -const DESCRIPTION: &str = "Changes the gamemode for a Player"; +const DESCRIPTION: &str = "Change a player's gamemode."; const ARG_GAMEMODE: &str = "gamemode"; const ARG_TARGET: &str = "target"; diff --git a/pumpkin/src/commands/cmd_help.rs b/pumpkin/src/commands/cmd_help.rs new file mode 100644 index 000000000..6c12182b5 --- /dev/null +++ b/pumpkin/src/commands/cmd_help.rs @@ -0,0 +1,61 @@ +use crate::commands::{CommandSender, DISPATCHER, dispatcher_init}; +use crate::commands::dispatcher::{CommandDispatcher, InvalidTreeError}; +use crate::commands::dispatcher::InvalidTreeError::InvalidConsumptionError; +use crate::commands::tree::{CommandTree, ConsumedArgs, RawArgs}; +use crate::commands::tree_builder::argument; + +pub(crate) const NAME: &str = "help"; +pub(crate) const ALIAS: &str = "?"; + +const DESCRIPTION: &str = "Print a help message."; + +const ARG_COMMAND: &str = "command"; + +fn consume_arg_command(_src: &CommandSender, args: &mut RawArgs) -> Option { + let s = args.pop()?; + + let dispatcher = DISPATCHER; + let dispatcher = dispatcher.get_or_init(dispatcher_init); + + if dispatcher.commands.contains_key(s) { Some(s.into()) } + else { None } +} + +fn parse_arg_command<'a>(consumed_args: &'a ConsumedArgs, dispatcher: &'a CommandDispatcher) -> Result<(&'a str, &'a CommandTree<'a>), InvalidTreeError> { + let command_name = consumed_args.get(ARG_COMMAND) + .ok_or(InvalidConsumptionError(None))?; + + if let Some(tree) = dispatcher.commands.get::<&str>(&command_name.as_str()) { + Ok((command_name, tree)) + } else { + Err(InvalidConsumptionError(Some(command_name.into()))) + } +} + +pub(crate) fn init_command_tree<'a>() -> CommandTree<'a> { + CommandTree::new(DESCRIPTION).with_child( + argument(ARG_COMMAND, consume_arg_command).execute(&|sender, args| { + let dispatcher = DISPATCHER; + let dispatcher = dispatcher.get_or_init(dispatcher_init); + + let (name, tree) = parse_arg_command(args, dispatcher)?; + + sender.send_message( + format!("{} - {} Usage:{}", name, tree.description, tree.paths_formatted(name)).into() + ); + + Ok(()) + }) + ).execute(&|sender, _args| { + let dispatcher = DISPATCHER; + let dispatcher = dispatcher.get_or_init(dispatcher_init); + + for (name, tree) in &dispatcher.commands { + sender.send_message( + format!("{} - {} Usage:{}", name, tree.description, tree.paths_formatted(name)).into() + ); + }; + + Ok(()) + }) +} \ No newline at end of file diff --git a/pumpkin/src/commands/cmd_pumpkin.rs b/pumpkin/src/commands/cmd_pumpkin.rs index 1bb0b9cab..40b9e7ff4 100644 --- a/pumpkin/src/commands/cmd_pumpkin.rs +++ b/pumpkin/src/commands/cmd_pumpkin.rs @@ -6,7 +6,7 @@ use crate::commands::tree::CommandTree; pub(crate) const NAME: &str = "pumpkin"; -const DESCRIPTION: &str = "Displays information about Pumpkin"; +const DESCRIPTION: &str = "Display information about Pumpkin."; pub(crate) fn init_command_tree<'a>() -> CommandTree<'a> { CommandTree::new(DESCRIPTION).execute(&|sender, _| { diff --git a/pumpkin/src/commands/cmd_stop.rs b/pumpkin/src/commands/cmd_stop.rs index 57f55fc78..55f694e6f 100644 --- a/pumpkin/src/commands/cmd_stop.rs +++ b/pumpkin/src/commands/cmd_stop.rs @@ -3,7 +3,7 @@ use crate::commands::tree_builder::require; pub(crate) const NAME: &str = "stop"; -const DESCRIPTION: &str = "Stops the server"; +const DESCRIPTION: &str = "Stop the server."; pub(crate) fn init_command_tree<'a>() -> CommandTree<'a> { CommandTree::new(DESCRIPTION).with_child( diff --git a/pumpkin/src/commands/mod.rs b/pumpkin/src/commands/mod.rs index 28e042f2d..2774182ac 100644 --- a/pumpkin/src/commands/mod.rs +++ b/pumpkin/src/commands/mod.rs @@ -4,8 +4,6 @@ use pumpkin_text::TextComponent; use crate::client::Client; use crate::commands::dispatcher::CommandDispatcher; -use crate::server::Server; - mod cmd_gamemode; mod cmd_pumpkin; mod cmd_stop; @@ -14,6 +12,7 @@ mod tree_builder; mod dispatcher; mod arg_player; mod cmd_teleport; +mod cmd_help; pub enum CommandSender<'a> { Rcon(&'a mut Vec), @@ -73,6 +72,8 @@ fn dispatcher_init<'a>() -> CommandDispatcher<'a> { map.insert(cmd_pumpkin::NAME, cmd_pumpkin::init_command_tree()); map.insert(cmd_gamemode::NAME, cmd_gamemode::init_command_tree()); map.insert(cmd_stop::NAME, cmd_stop::init_command_tree()); + map.insert(cmd_help::NAME, cmd_help::init_command_tree()); + map.insert(cmd_help::ALIAS, cmd_help::init_command_tree()); CommandDispatcher { commands: map, diff --git a/pumpkin/src/commands/tree.rs b/pumpkin/src/commands/tree.rs index 46b45dbba..852ac21d9 100644 --- a/pumpkin/src/commands/tree.rs +++ b/pumpkin/src/commands/tree.rs @@ -70,8 +70,8 @@ impl <'a> CommandTree<'a> { let mut s = String::with_capacity(len); - for path in paths { - s.push('\n'); + for path in paths.iter() { + s.push(if paths.len() > 1 { '\n' } else { ' ' }); s.push('/'); s.push_str(name); for node in path {