diff --git a/pumpkin/src/commands/arg_player.rs b/pumpkin/src/commands/arg_player.rs index d7587ebf2..a804a6f13 100644 --- a/pumpkin/src/commands/arg_player.rs +++ b/pumpkin/src/commands/arg_player.rs @@ -5,39 +5,50 @@ use crate::commands::dispatcher::InvalidTreeError; use crate::commands::dispatcher::InvalidTreeError::InvalidConsumptionError; use crate::commands::tree::{ConsumedArgs, RawArgs}; -/// todo: implement (so far only own name + @s is implemented) +/// todo: implement (so far only own name + @s/@p is implemented) pub fn consume_arg_player(src: &CommandSender, args: &mut RawArgs) -> Option { let s = args.pop()?; - - if let Player(client) = src { - if s == "@s" { - return Some(s.into()) - } - if let Some(profile) = &client.gameprofile { - if profile.name == s { - return Some(s.into()) + + match s { + "@s" if src.is_player() => Some(s.into()), + "@p" if src.is_player() => Some(s.into()), + "@r" => None, // todo: implement random player target selector + "@a" | "@e" => None, // todo: implement all players target selector + _ => { + // todo: implement any other player than sender + if let Player(client) = src { + if let Some(profile) = &client.gameprofile { + if profile.name == s { + return Some(s.into()) + }; + }; }; - }; - }; - - None + None + } + } } -/// todo: implement (so far only own name + @s is implemented) +/// todo: implement (so far only own name + @s/@p is implemented) pub fn parse_arg_player<'a>(src: &'a mut CommandSender, arg_name: &str, consumed_args: &ConsumedArgs) -> Result<&'a mut Client, InvalidTreeError> { let s = consumed_args.get(arg_name) - .ok_or(InvalidConsumptionError(None))?; + .ok_or(InvalidConsumptionError(None))? + .as_str(); - if let Player(client) = src { - if s == "@s" { - return Ok(client) - } - if let Some(profile) = &client.gameprofile { - if profile.name == s.as_ref() { - return Ok(client) + 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 + _ => { + // todo: implement any other player than sender + if let Player(client) = src { + if let Some(profile) = &client.gameprofile { + if profile.name == s { + return Ok(client) + }; + }; }; - }; - }; - - Err(InvalidConsumptionError(Some(s.into()))) + Err(InvalidConsumptionError(Some(s.into()))) + } + } } \ No newline at end of file diff --git a/pumpkin/src/commands/cmd_gamemode.rs b/pumpkin/src/commands/cmd_gamemode.rs index fec3bc70c..f4a558cb2 100644 --- a/pumpkin/src/commands/cmd_gamemode.rs +++ b/pumpkin/src/commands/cmd_gamemode.rs @@ -30,7 +30,7 @@ pub fn consume_arg_gamemode(_src: &CommandSender, args: &mut RawArgs) -> Option< }; }; - return match GameMode::from_str(s) { + match GameMode::from_str(s) { Err(_) | Ok(GameMode::Undefined) => None, Ok(_) => Some(s.into()) } @@ -47,10 +47,10 @@ pub fn parse_arg_gamemode(consumed_args: &ConsumedArgs) -> Result Err(InvalidConsumptionError(Some(s.into()))), Ok(gamemode) => Ok(gamemode) - }; + } } pub(crate) fn init_command_tree<'a>() -> CommandTree<'a> { diff --git a/pumpkin/src/commands/cmd_help.rs b/pumpkin/src/commands/cmd_help.rs index d6353a715..7255fc9f1 100644 --- a/pumpkin/src/commands/cmd_help.rs +++ b/pumpkin/src/commands/cmd_help.rs @@ -15,8 +15,7 @@ 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); + let dispatcher = DISPATCHER.get_or_init(dispatcher_init); if dispatcher.commands.contains_key(s) { Some(s.into()) } else { None } @@ -36,8 +35,7 @@ fn parse_arg_command<'a>(consumed_args: &'a ConsumedArgs, dispatcher: &'a Comman 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 dispatcher = DISPATCHER.get_or_init(dispatcher_init); let (name, tree) = parse_arg_command(args, dispatcher)?; @@ -50,8 +48,7 @@ pub(crate) fn init_command_tree<'a>() -> CommandTree<'a> { Ok(()) }) ).execute(&|sender, _args| { - let dispatcher = DISPATCHER; - let dispatcher = dispatcher.get_or_init(dispatcher_init); + let dispatcher = DISPATCHER.get_or_init(dispatcher_init); for (name, tree) in &dispatcher.commands { sender.send_message( diff --git a/pumpkin/src/commands/mod.rs b/pumpkin/src/commands/mod.rs index f84ce719a..7bec0e83a 100644 --- a/pumpkin/src/commands/mod.rs +++ b/pumpkin/src/commands/mod.rs @@ -66,7 +66,7 @@ impl<'a> CommandSender<'a> { /// /// Central point from which commands are dispatched. Should always be initialized using /// [dispatcher_init]. -const DISPATCHER: OnceLock = OnceLock::new(); +static DISPATCHER: OnceLock = OnceLock::new(); /// create [CommandDispatcher] instance for [DISPATCHER] fn dispatcher_init<'a>() -> CommandDispatcher<'a> { @@ -84,8 +84,7 @@ fn dispatcher_init<'a>() -> CommandDispatcher<'a> { } pub fn handle_command(sender: &mut CommandSender, cmd: &str) { - let dispatcher = DISPATCHER; - let dispatcher = dispatcher.get_or_init(dispatcher_init); + let dispatcher = DISPATCHER.get_or_init(dispatcher_init); if let Err(err) = dispatcher.dispatch(sender, cmd) { sender.send_message( diff --git a/pumpkin/src/commands/tree.rs b/pumpkin/src/commands/tree.rs index 52c406231..492214e69 100644 --- a/pumpkin/src/commands/tree.rs +++ b/pumpkin/src/commands/tree.rs @@ -2,15 +2,13 @@ use std::collections::{HashMap, VecDeque}; use crate::commands::CommandSender; use crate::commands::dispatcher::InvalidTreeError; -use crate::commands::tree_builder::{argument, NonLeafNodeBuilder}; - -/// see [argument] +/// see [crate::commands::tree_builder::argument] pub(crate) type RawArgs<'a> = Vec<&'a str>; -/// see [argument] and [CommandTree::execute]/[NonLeafNodeBuilder::execute] +/// see [crate::commands::tree_builder::argument] and [CommandTree::execute]/[crate::commands::tree_builder::NonLeafNodeBuilder::execute] pub(crate) type ConsumedArgs<'a> = HashMap<&'a str, String>; -/// see [argument] +/// see [crate::commands::tree_builder::argument] pub(crate) type ArgumentConsumer<'a> = fn(&CommandSender, &mut RawArgs) -> Option; pub(crate) struct Node<'a> { @@ -20,7 +18,7 @@ pub(crate) struct Node<'a> { pub(crate) enum NodeType<'a> { ExecuteLeaf { - run: &'a dyn Fn(&mut CommandSender, &ConsumedArgs) -> Result<(), InvalidTreeError>, + run: &'a (dyn Fn(&mut CommandSender, &ConsumedArgs) -> Result<(), InvalidTreeError> + Sync), }, Literal { string: &'a str, @@ -30,7 +28,7 @@ pub(crate) enum NodeType<'a> { consumer: ArgumentConsumer<'a>, }, Require { - predicate: &'a dyn Fn(&CommandSender) -> bool, + predicate: &'a (dyn Fn(&CommandSender) -> bool + Sync), } } diff --git a/pumpkin/src/commands/tree_builder.rs b/pumpkin/src/commands/tree_builder.rs index c3dac899c..28f721217 100644 --- a/pumpkin/src/commands/tree_builder.rs +++ b/pumpkin/src/commands/tree_builder.rs @@ -27,7 +27,7 @@ impl <'a> CommandTree<'a> { /// desired type. /// /// Also see [NonLeafNodeBuilder::execute]. - pub fn execute(mut self, run: &'a dyn Fn(&mut CommandSender, &ConsumedArgs) -> Result<(), InvalidTreeError>) -> Self { + pub fn execute(mut self, run: &'a (dyn Fn(&mut CommandSender, &ConsumedArgs) -> Result<(), InvalidTreeError> + Sync)) -> Self { let node = Node { node_type: NodeType::ExecuteLeaf { run, @@ -103,7 +103,7 @@ impl <'a>NonLeafNodeBuilder<'a> { /// desired type. /// /// Also see [CommandTree::execute]. - pub fn execute(mut self, run: &'a dyn Fn(&mut CommandSender, &ConsumedArgs) -> Result<(), InvalidTreeError>) -> Self { + pub fn execute(mut self, run: &'a (dyn Fn(&mut CommandSender, &ConsumedArgs) -> Result<(), InvalidTreeError> + Sync)) -> Self { self.leaf_nodes.push(LeafNodeBuilder { node_type: NodeType::ExecuteLeaf { run @@ -146,7 +146,7 @@ pub fn argument<'a>(name: &'a str, consumer: ArgumentConsumer) -> NonLeafNodeBui /// ```predicate``` should return ```false``` if requirement for reaching following [Node]s is not /// met. -pub fn require(predicate: &dyn Fn(&CommandSender) -> bool) -> NonLeafNodeBuilder { +pub fn require(predicate: &(dyn Fn(&CommandSender) -> bool + Sync)) -> NonLeafNodeBuilder { NonLeafNodeBuilder { node_type: NodeType::Require { predicate