mirror of
https://github.com/Pumpkin-MC/Pumpkin.git
synced 2026-08-31 08:22:33 +00:00
make commands async (#179)
This commit is contained in:
@@ -63,3 +63,6 @@ png = "0.17.14"
|
||||
|
||||
# logging
|
||||
simple_logger = { version = "5.0.0", features = ["threads"] }
|
||||
|
||||
# commands
|
||||
async-trait = "0.1.83"
|
||||
|
||||
@@ -1,32 +1,44 @@
|
||||
use async_trait::async_trait;
|
||||
use pumpkin_inventory::OpenContainer;
|
||||
|
||||
use crate::commands::tree::CommandTree;
|
||||
|
||||
use super::RunFunctionType;
|
||||
|
||||
const NAMES: [&str; 2] = ["echest", "enderchest"];
|
||||
|
||||
const DESCRIPTION: &str =
|
||||
"Show your personal enderchest (this command is used for testing container behaviour)";
|
||||
|
||||
#[allow(unused_variables)]
|
||||
struct EchestExecutor {}
|
||||
|
||||
pub fn init_command_tree<'a>() -> CommandTree<'a> {
|
||||
CommandTree::new(NAMES, DESCRIPTION).execute(&|sender, server, _| {
|
||||
#[async_trait]
|
||||
impl RunFunctionType for EchestExecutor {
|
||||
async fn execute(
|
||||
&self,
|
||||
sender: &mut super::CommandSender,
|
||||
server: &crate::server::Server,
|
||||
_args: &super::tree::ConsumedArgs,
|
||||
) -> Result<(), super::dispatcher::InvalidTreeError> {
|
||||
if let Some(player) = sender.as_player() {
|
||||
let entity_id = player.entity_id();
|
||||
// player.open_container.store(Some(0));
|
||||
// {
|
||||
// let mut open_containers = server.open_containers.write().await;
|
||||
// match open_containers.get_mut(&0) {
|
||||
// Some(ender_chest) => {
|
||||
// ender_chest.add_player(entity_id);
|
||||
// }
|
||||
// None => {
|
||||
// let open_container = OpenContainer::empty(entity_id);
|
||||
// open_containers.insert(0, open_container);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// player.open_container(server, "minecraft:generic_9x3");
|
||||
player.open_container.store(Some(0));
|
||||
{
|
||||
let mut open_containers = server.open_containers.write().await;
|
||||
if let Some(ender_chest) = open_containers.get_mut(&0) {
|
||||
ender_chest.add_player(entity_id);
|
||||
} else {
|
||||
let open_container = OpenContainer::empty(entity_id);
|
||||
open_containers.insert(0, open_container);
|
||||
}
|
||||
}
|
||||
player.open_container(server, "minecraft:generic_9x3").await;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub fn init_command_tree<'a>() -> CommandTree<'a> {
|
||||
CommandTree::new(NAMES, DESCRIPTION).execute(&EchestExecutor {})
|
||||
}
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
use std::str::FromStr;
|
||||
|
||||
use async_trait::async_trait;
|
||||
use num_traits::FromPrimitive;
|
||||
use pumpkin_core::GameMode;
|
||||
|
||||
use crate::TextComponent;
|
||||
|
||||
use crate::commands::arg_player::{consume_arg_player, parse_arg_player};
|
||||
|
||||
use crate::commands::dispatcher::InvalidTreeError;
|
||||
@@ -15,6 +18,8 @@ use crate::commands::CommandSender;
|
||||
use crate::commands::CommandSender::Player;
|
||||
use crate::server::Server;
|
||||
|
||||
use super::RunFunctionType;
|
||||
|
||||
const NAMES: [&str; 1] = ["gamemode"];
|
||||
|
||||
const DESCRIPTION: &str = "Change a player's gamemode.";
|
||||
@@ -63,56 +68,83 @@ pub fn parse_arg_gamemode(consumed_args: &ConsumedArgs) -> Result<GameMode, Inva
|
||||
}
|
||||
}
|
||||
|
||||
struct GamemodeTargetSelf {}
|
||||
|
||||
#[async_trait]
|
||||
impl RunFunctionType for GamemodeTargetSelf {
|
||||
async fn execute(
|
||||
&self,
|
||||
sender: &mut CommandSender,
|
||||
_server: &Server,
|
||||
args: &ConsumedArgs,
|
||||
) -> Result<(), InvalidTreeError> {
|
||||
let gamemode = parse_arg_gamemode(args)?;
|
||||
|
||||
if let Player(target) = sender {
|
||||
if target.gamemode.load() == gamemode {
|
||||
target
|
||||
.send_system_message(&TextComponent::text(&format!(
|
||||
"You already in {gamemode:?} gamemode"
|
||||
)))
|
||||
.await;
|
||||
} else {
|
||||
target.set_gamemode(gamemode).await;
|
||||
target
|
||||
.send_system_message(&TextComponent::text(&format!(
|
||||
"Game mode was set to {gamemode:?}"
|
||||
)))
|
||||
.await;
|
||||
}
|
||||
Ok(())
|
||||
} else {
|
||||
Err(InvalidRequirementError)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct GamemodeTargetPlayer {}
|
||||
|
||||
#[async_trait]
|
||||
impl RunFunctionType for GamemodeTargetPlayer {
|
||||
async fn execute(
|
||||
&self,
|
||||
sender: &mut CommandSender,
|
||||
server: &Server,
|
||||
args: &ConsumedArgs,
|
||||
) -> Result<(), InvalidTreeError> {
|
||||
let gamemode = parse_arg_gamemode(args)?;
|
||||
let target = parse_arg_player(sender, server, ARG_TARGET, args)?;
|
||||
|
||||
if target.gamemode.load() == gamemode {
|
||||
sender
|
||||
.send_message(TextComponent::text(&format!(
|
||||
"{} is already in {:?} gamemode",
|
||||
target.gameprofile.name, gamemode
|
||||
)))
|
||||
.await;
|
||||
} else {
|
||||
target.set_gamemode(gamemode).await;
|
||||
sender
|
||||
.send_message(TextComponent::text(&format!(
|
||||
"{}'s Game mode was set to {:?}",
|
||||
target.gameprofile.name, gamemode
|
||||
)))
|
||||
.await;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::redundant_closure_for_method_calls)]
|
||||
pub fn init_command_tree<'a>() -> CommandTree<'a> {
|
||||
CommandTree::new(NAMES, DESCRIPTION).with_child(
|
||||
require(&|sender| sender.permission_lvl() >= 2).with_child(
|
||||
argument(ARG_GAMEMODE, consume_arg_gamemode)
|
||||
.with_child(require(&|sender| sender.is_player()).execute(&GamemodeTargetSelf {}))
|
||||
.with_child(
|
||||
require(&|sender| sender.is_player()).execute(&|sender, _, args| {
|
||||
let gamemode = parse_arg_gamemode(args)?;
|
||||
|
||||
if let Player(target) = sender {
|
||||
if target.gamemode.load() == gamemode {
|
||||
// target.send_system_message(&TextComponent::text(&format!(
|
||||
// "You already in {:?} gamemode",
|
||||
// gamemode
|
||||
// )));
|
||||
} else {
|
||||
// TODO
|
||||
// target.set_gamemode(gamemode);
|
||||
// target.send_system_message(&TextComponent::text(&format!(
|
||||
// "Game mode was set to {:?}",
|
||||
// gamemode
|
||||
// )));
|
||||
}
|
||||
Ok(())
|
||||
} else {
|
||||
Err(InvalidRequirementError)
|
||||
}
|
||||
}),
|
||||
)
|
||||
.with_child(argument(ARG_TARGET, consume_arg_player).execute(
|
||||
&|sender, server, args| {
|
||||
let gamemode = parse_arg_gamemode(args)?;
|
||||
let target = parse_arg_player(sender, server, ARG_TARGET, args)?;
|
||||
|
||||
if target.gamemode.load() == gamemode {
|
||||
// sender.send_message(TextComponent::text(&format!(
|
||||
// "{} is already in {:?} gamemode",
|
||||
// target.gameprofile.name, gamemode
|
||||
// )));
|
||||
} else {
|
||||
// TODO
|
||||
// target.set_gamemode(gamemode);
|
||||
// sender.send_message(TextComponent::text(&format!(
|
||||
// "{}'s Game mode was set to {:?}",
|
||||
// target.gameprofile.name, gamemode
|
||||
// )));
|
||||
}
|
||||
|
||||
Ok(())
|
||||
},
|
||||
)),
|
||||
argument(ARG_TARGET, consume_arg_player).execute(&GamemodeTargetPlayer {}),
|
||||
),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
use async_trait::async_trait;
|
||||
use pumpkin_core::text::TextComponent;
|
||||
|
||||
use crate::commands::dispatcher::InvalidTreeError::InvalidConsumptionError;
|
||||
use crate::commands::dispatcher::{CommandDispatcher, InvalidTreeError};
|
||||
use crate::commands::tree::{Command, CommandTree, ConsumedArgs, RawArgs};
|
||||
@@ -5,6 +8,8 @@ use crate::commands::tree_builder::argument;
|
||||
use crate::commands::CommandSender;
|
||||
use crate::server::Server;
|
||||
|
||||
use super::RunFunctionType;
|
||||
|
||||
const NAMES: [&str; 3] = ["help", "h", "?"];
|
||||
|
||||
const DESCRIPTION: &str = "Print a help message.";
|
||||
@@ -36,41 +41,65 @@ fn parse_arg_command<'a>(
|
||||
.map_err(|_| InvalidConsumptionError(Some(command_name.into())))
|
||||
}
|
||||
|
||||
#[allow(unused_variables)]
|
||||
struct BaseHelpExecutor {}
|
||||
|
||||
#[async_trait]
|
||||
impl RunFunctionType for BaseHelpExecutor {
|
||||
async fn execute(
|
||||
&self,
|
||||
sender: &mut CommandSender,
|
||||
server: &Server,
|
||||
args: &ConsumedArgs,
|
||||
) -> Result<(), InvalidTreeError> {
|
||||
let tree = parse_arg_command(args, &server.command_dispatcher)?;
|
||||
|
||||
sender
|
||||
.send_message(TextComponent::text(&format!(
|
||||
"{} - {} Usage: {}",
|
||||
tree.names.join("/"),
|
||||
tree.description,
|
||||
tree
|
||||
)))
|
||||
.await;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
struct CommandHelpExecutor {}
|
||||
|
||||
#[async_trait]
|
||||
impl RunFunctionType for CommandHelpExecutor {
|
||||
async fn execute(
|
||||
&self,
|
||||
sender: &mut CommandSender,
|
||||
server: &Server,
|
||||
_args: &ConsumedArgs,
|
||||
) -> Result<(), InvalidTreeError> {
|
||||
let mut keys: Vec<&str> = server.command_dispatcher.commands.keys().copied().collect();
|
||||
keys.sort_unstable();
|
||||
|
||||
for key in keys {
|
||||
let Command::Tree(tree) = &server.command_dispatcher.commands[key] else {
|
||||
continue;
|
||||
};
|
||||
|
||||
sender
|
||||
.send_message(TextComponent::text(&format!(
|
||||
"{} - {} Usage: {}",
|
||||
tree.names.join("/"),
|
||||
tree.description,
|
||||
tree
|
||||
)))
|
||||
.await;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn init_command_tree<'a>() -> CommandTree<'a> {
|
||||
CommandTree::new(NAMES, DESCRIPTION)
|
||||
.with_child(
|
||||
argument(ARG_COMMAND, consume_arg_command).execute(&|sender, server, args| {
|
||||
let tree = parse_arg_command(args, &server.command_dispatcher)?;
|
||||
|
||||
// sender.send_message(TextComponent::text(&format!(
|
||||
// "{} - {} Usage: {}",
|
||||
// tree.names.join("/"),
|
||||
// tree.description,
|
||||
// tree
|
||||
// )));
|
||||
|
||||
Ok(())
|
||||
}),
|
||||
)
|
||||
.execute(&|sender, server, _args| {
|
||||
let mut keys: Vec<&str> = server.command_dispatcher.commands.keys().copied().collect();
|
||||
keys.sort_unstable();
|
||||
|
||||
for key in keys {
|
||||
let Command::Tree(tree) = &server.command_dispatcher.commands[key] else {
|
||||
continue;
|
||||
};
|
||||
|
||||
// sender.send_message(TextComponent::text(&format!(
|
||||
// "{} - {} Usage: {}",
|
||||
// tree.names.join("/"),
|
||||
// tree.description,
|
||||
// tree
|
||||
// )));
|
||||
}
|
||||
|
||||
Ok(())
|
||||
})
|
||||
.with_child(argument(ARG_COMMAND, consume_arg_command).execute(&BaseHelpExecutor {}))
|
||||
.execute(&CommandHelpExecutor {})
|
||||
}
|
||||
|
||||
@@ -1,27 +1,45 @@
|
||||
use async_trait::async_trait;
|
||||
use pumpkin_core::text::color::NamedColor;
|
||||
use pumpkin_core::text::TextComponent;
|
||||
|
||||
use crate::commands::arg_player::parse_arg_player;
|
||||
use crate::commands::tree::CommandTree;
|
||||
use crate::commands::tree_builder::argument;
|
||||
|
||||
use super::arg_player::consume_arg_player;
|
||||
use super::RunFunctionType;
|
||||
|
||||
const NAMES: [&str; 1] = ["kick"];
|
||||
const DESCRIPTION: &str = "Kicks the target player from the server.";
|
||||
|
||||
const ARG_TARGET: &str = "target";
|
||||
|
||||
#[expect(unused)]
|
||||
struct KickExecutor {}
|
||||
|
||||
#[async_trait]
|
||||
impl RunFunctionType for KickExecutor {
|
||||
async fn execute(
|
||||
&self,
|
||||
sender: &mut super::CommandSender,
|
||||
server: &crate::server::Server,
|
||||
args: &super::tree::ConsumedArgs,
|
||||
) -> Result<(), super::dispatcher::InvalidTreeError> {
|
||||
let target = parse_arg_player(sender, server, ARG_TARGET, args)?;
|
||||
target
|
||||
.kick(TextComponent::text("Kicked by an operator"))
|
||||
.await;
|
||||
|
||||
sender
|
||||
.send_message(
|
||||
TextComponent::text("Player has been kicked.").color_named(NamedColor::Blue),
|
||||
)
|
||||
.await;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn init_command_tree<'a>() -> CommandTree<'a> {
|
||||
CommandTree::new(NAMES, DESCRIPTION).with_child(
|
||||
argument(ARG_TARGET, consume_arg_player).execute(&|sender, server, args| {
|
||||
let target = parse_arg_player(sender, server, ARG_TARGET, args)?;
|
||||
// target.kick(TextComponent::text("Kicked by an operator"));
|
||||
|
||||
// sender.send_message(
|
||||
// TextComponent::text("Player has been kicked.").color_named(NamedColor::Blue),
|
||||
// );
|
||||
|
||||
Ok(())
|
||||
}),
|
||||
)
|
||||
CommandTree::new(NAMES, DESCRIPTION)
|
||||
.with_child(argument(ARG_TARGET, consume_arg_player).execute(&KickExecutor {}))
|
||||
}
|
||||
|
||||
@@ -1,26 +1,43 @@
|
||||
use async_trait::async_trait;
|
||||
use pumpkin_core::text::color::NamedColor;
|
||||
use pumpkin_core::text::TextComponent;
|
||||
|
||||
use crate::commands::arg_player::{consume_arg_player, parse_arg_player};
|
||||
use crate::commands::tree::CommandTree;
|
||||
use crate::commands::tree_builder::argument;
|
||||
|
||||
use super::RunFunctionType;
|
||||
|
||||
const NAMES: [&str; 1] = ["kill"];
|
||||
const DESCRIPTION: &str = "Kills a target player.";
|
||||
|
||||
const ARG_TARGET: &str = "target";
|
||||
|
||||
#[expect(unused)]
|
||||
struct KillExecutor {}
|
||||
|
||||
#[async_trait]
|
||||
impl RunFunctionType for KillExecutor {
|
||||
async fn execute(
|
||||
&self,
|
||||
sender: &mut super::CommandSender,
|
||||
server: &crate::server::Server,
|
||||
args: &super::tree::ConsumedArgs,
|
||||
) -> Result<(), super::dispatcher::InvalidTreeError> {
|
||||
// TODO parse entities not only players
|
||||
let target = parse_arg_player(sender, server, ARG_TARGET, args)?;
|
||||
target.living_entity.kill().await;
|
||||
|
||||
sender
|
||||
.send_message(
|
||||
TextComponent::text("Player has been killed.").color_named(NamedColor::Blue),
|
||||
)
|
||||
.await;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn init_command_tree<'a>() -> CommandTree<'a> {
|
||||
CommandTree::new(NAMES, DESCRIPTION).with_child(
|
||||
argument(ARG_TARGET, consume_arg_player).execute(&|sender, server, args| {
|
||||
// TODO parse entities not only players
|
||||
let target = parse_arg_player(sender, server, ARG_TARGET, args)?;
|
||||
// target.living_entity.kill();
|
||||
|
||||
// sender.send_message(
|
||||
// TextComponent::text("Player has been killed.").color_named(NamedColor::Blue),
|
||||
// );
|
||||
|
||||
Ok(())
|
||||
}),
|
||||
)
|
||||
CommandTree::new(NAMES, DESCRIPTION)
|
||||
.with_child(argument(ARG_TARGET, consume_arg_player).execute(&KillExecutor {}))
|
||||
}
|
||||
|
||||
@@ -1,20 +1,36 @@
|
||||
use crate::commands::tree::CommandTree;
|
||||
use async_trait::async_trait;
|
||||
use pumpkin_core::text::{color::NamedColor, TextComponent};
|
||||
use pumpkin_protocol::CURRENT_MC_PROTOCOL;
|
||||
|
||||
use crate::{commands::tree::CommandTree, server::CURRENT_MC_VERSION};
|
||||
|
||||
use super::RunFunctionType;
|
||||
|
||||
const NAMES: [&str; 1] = ["pumpkin"];
|
||||
|
||||
const DESCRIPTION: &str = "Display information about Pumpkin.";
|
||||
|
||||
#[expect(unused)]
|
||||
struct PumpkinExecutor {}
|
||||
|
||||
pub fn init_command_tree<'a>() -> CommandTree<'a> {
|
||||
CommandTree::new(NAMES, DESCRIPTION).execute(&|sender, _, _| {
|
||||
#[async_trait]
|
||||
impl RunFunctionType for PumpkinExecutor {
|
||||
async fn execute(
|
||||
&self,
|
||||
sender: &mut super::CommandSender,
|
||||
_server: &crate::server::Server,
|
||||
_args: &super::tree::ConsumedArgs,
|
||||
) -> Result<(), super::dispatcher::InvalidTreeError> {
|
||||
let version = env!("CARGO_PKG_VERSION");
|
||||
let description = env!("CARGO_PKG_DESCRIPTION");
|
||||
|
||||
// sender.send_message(TextComponent::text(
|
||||
// &format!("Pumpkin {version}, {description} (Minecraft {CURRENT_MC_VERSION}, Protocol {CURRENT_MC_PROTOCOL})")
|
||||
// ).color_named(NamedColor::Green)).await;
|
||||
sender.send_message(TextComponent::text(
|
||||
&format!("Pumpkin {version}, {description} (Minecraft {CURRENT_MC_VERSION}, Protocol {CURRENT_MC_PROTOCOL})")
|
||||
).color_named(NamedColor::Green)).await;
|
||||
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub fn init_command_tree<'a>() -> CommandTree<'a> {
|
||||
CommandTree::new(NAMES, DESCRIPTION).execute(&PumpkinExecutor {})
|
||||
}
|
||||
|
||||
@@ -1,16 +1,36 @@
|
||||
use async_trait::async_trait;
|
||||
use pumpkin_core::text::color::NamedColor;
|
||||
use pumpkin_core::text::TextComponent;
|
||||
|
||||
use crate::commands::tree::CommandTree;
|
||||
use crate::commands::tree_builder::require;
|
||||
|
||||
use super::RunFunctionType;
|
||||
|
||||
const NAMES: [&str; 1] = ["stop"];
|
||||
|
||||
const DESCRIPTION: &str = "Stop the server.";
|
||||
|
||||
struct StopExecutor {}
|
||||
|
||||
#[async_trait]
|
||||
impl RunFunctionType for StopExecutor {
|
||||
async fn execute(
|
||||
&self,
|
||||
sender: &mut super::CommandSender,
|
||||
_server: &crate::server::Server,
|
||||
_args: &super::tree::ConsumedArgs,
|
||||
) -> Result<(), super::dispatcher::InvalidTreeError> {
|
||||
sender
|
||||
.send_message(TextComponent::text("Stopping Server").color_named(NamedColor::Red))
|
||||
.await;
|
||||
|
||||
// TODO: Gracefully stop
|
||||
std::process::exit(0)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn init_command_tree<'a>() -> CommandTree<'a> {
|
||||
CommandTree::new(NAMES, DESCRIPTION).with_child(
|
||||
require(&|sender| sender.permission_lvl() >= 4).execute(&|_sender, _, _args| {
|
||||
// sender
|
||||
// .send_message(TextComponent::text("Stopping Server").color_named(NamedColor::Red));
|
||||
std::process::exit(0)
|
||||
}),
|
||||
)
|
||||
CommandTree::new(NAMES, DESCRIPTION)
|
||||
.with_child(require(&|sender| sender.permission_lvl() >= 4).execute(&StopExecutor {}))
|
||||
}
|
||||
|
||||
@@ -26,8 +26,13 @@ pub struct CommandDispatcher<'a> {
|
||||
|
||||
/// Stores registered [`CommandTree`]s and dispatches commands to them.
|
||||
impl<'a> CommandDispatcher<'a> {
|
||||
pub async fn handle_command(&self, sender: &mut CommandSender<'a>, server: &Server, cmd: &str) {
|
||||
if let Err(err) = self.dispatch(sender, server, cmd) {
|
||||
pub async fn handle_command(
|
||||
&'a self,
|
||||
sender: &mut CommandSender<'a>,
|
||||
server: &Server,
|
||||
cmd: &'a str,
|
||||
) {
|
||||
if let Err(err) = self.dispatch(sender, server, cmd).await {
|
||||
sender
|
||||
.send_message(
|
||||
TextComponent::text_string(err)
|
||||
@@ -38,13 +43,14 @@ impl<'a> CommandDispatcher<'a> {
|
||||
}
|
||||
|
||||
/// Execute a command using its corresponding [`CommandTree`].
|
||||
pub(crate) fn dispatch(
|
||||
pub(crate) async fn dispatch(
|
||||
&'a self,
|
||||
src: &mut CommandSender,
|
||||
src: &mut CommandSender<'a>,
|
||||
server: &Server,
|
||||
cmd: &str,
|
||||
cmd: &'a str,
|
||||
) -> Result<(), String> {
|
||||
let mut parts = cmd.split_ascii_whitespace();
|
||||
// Other languages dont use the ascii whitespace
|
||||
let mut parts = cmd.split_whitespace();
|
||||
let key = parts.next().ok_or("Empty Command")?;
|
||||
let raw_args: Vec<&str> = parts.rev().collect();
|
||||
|
||||
@@ -52,7 +58,7 @@ impl<'a> CommandDispatcher<'a> {
|
||||
|
||||
// try paths until fitting path is found
|
||||
for path in tree.iter_paths() {
|
||||
match Self::try_is_fitting_path(src, server, &path, tree, raw_args.clone()) {
|
||||
match Self::try_is_fitting_path(src, server, &path, tree, raw_args.clone()).await {
|
||||
Err(InvalidConsumptionError(s)) => {
|
||||
println!("Error while parsing command \"{cmd}\": {s:?} was consumed, but couldn't be parsed");
|
||||
return Err("Internal Error (See logs for details)".into());
|
||||
@@ -90,20 +96,20 @@ impl<'a> CommandDispatcher<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
fn try_is_fitting_path(
|
||||
src: &mut CommandSender,
|
||||
async fn try_is_fitting_path(
|
||||
src: &mut CommandSender<'a>,
|
||||
server: &Server,
|
||||
path: &[usize],
|
||||
tree: &CommandTree,
|
||||
mut raw_args: RawArgs,
|
||||
tree: &CommandTree<'a>,
|
||||
mut raw_args: RawArgs<'a>,
|
||||
) -> Result<Result<(), Option<String>>, InvalidTreeError> {
|
||||
let mut parsed_args: ConsumedArgs = HashMap::new();
|
||||
|
||||
for node in path.iter().map(|&i| &tree.nodes[i]) {
|
||||
match node.node_type {
|
||||
NodeType::ExecuteLeaf { run } => {
|
||||
NodeType::ExecuteLeaf { executor } => {
|
||||
return if raw_args.is_empty() {
|
||||
run(src, server, &parsed_args)?;
|
||||
executor.execute(src, server, &parsed_args).await?;
|
||||
Ok(Ok(()))
|
||||
} else {
|
||||
Ok(Err(None))
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use async_trait::async_trait;
|
||||
use dispatcher::InvalidTreeError;
|
||||
use pumpkin_core::text::TextComponent;
|
||||
use tree::ConsumedArgs;
|
||||
@@ -60,7 +61,7 @@ impl<'a> CommandSender<'a> {
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn default_dispatcher<'a>() -> CommandDispatcher<'a> {
|
||||
pub fn default_dispatcher<'a>() -> Arc<CommandDispatcher<'a>> {
|
||||
let mut dispatcher = CommandDispatcher::default();
|
||||
|
||||
dispatcher.register(cmd_pumpkin::init_command_tree());
|
||||
@@ -71,8 +72,15 @@ pub fn default_dispatcher<'a>() -> CommandDispatcher<'a> {
|
||||
dispatcher.register(cmd_kill::init_command_tree());
|
||||
dispatcher.register(cmd_kick::init_command_tree());
|
||||
|
||||
dispatcher
|
||||
Arc::new(dispatcher)
|
||||
}
|
||||
|
||||
type RunFunctionType =
|
||||
(dyn Fn(&mut CommandSender, &Server, &ConsumedArgs) -> Result<(), InvalidTreeError> + Sync);
|
||||
#[async_trait]
|
||||
pub(crate) trait RunFunctionType: Sync {
|
||||
async fn execute(
|
||||
&self,
|
||||
sender: &mut CommandSender,
|
||||
server: &Server,
|
||||
args: &ConsumedArgs,
|
||||
) -> Result<(), InvalidTreeError>;
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ pub struct Node<'a> {
|
||||
|
||||
pub enum NodeType<'a> {
|
||||
ExecuteLeaf {
|
||||
run: &'a RunFunctionType,
|
||||
executor: &'a dyn RunFunctionType,
|
||||
},
|
||||
Literal {
|
||||
string: &'a str,
|
||||
@@ -39,7 +39,6 @@ pub enum Command<'a> {
|
||||
Alias(&'a str),
|
||||
}
|
||||
|
||||
#[expect(unused)]
|
||||
pub struct CommandTree<'a> {
|
||||
pub(crate) nodes: Vec<Node<'a>>,
|
||||
pub(crate) children: Vec<usize>,
|
||||
|
||||
@@ -40,9 +40,9 @@ impl<'a> CommandTree<'a> {
|
||||
/// desired type.
|
||||
///
|
||||
/// Also see [`NonLeafNodeBuilder::execute`].
|
||||
pub fn execute(mut self, run: &'a RunFunctionType) -> Self {
|
||||
pub fn execute(mut self, executor: &'a dyn RunFunctionType) -> Self {
|
||||
let node = Node {
|
||||
node_type: NodeType::ExecuteLeaf { run },
|
||||
node_type: NodeType::ExecuteLeaf { executor },
|
||||
children: Vec::new(),
|
||||
};
|
||||
|
||||
@@ -113,9 +113,9 @@ impl<'a> NonLeafNodeBuilder<'a> {
|
||||
/// desired type.
|
||||
///
|
||||
/// Also see [`CommandTree::execute`].
|
||||
pub fn execute(mut self, run: &'a RunFunctionType) -> Self {
|
||||
pub fn execute(mut self, executor: &'a dyn RunFunctionType) -> Self {
|
||||
self.leaf_nodes.push(LeafNodeBuilder {
|
||||
node_type: NodeType::ExecuteLeaf { run },
|
||||
node_type: NodeType::ExecuteLeaf { executor },
|
||||
});
|
||||
|
||||
self
|
||||
|
||||
@@ -84,7 +84,7 @@ impl Server {
|
||||
// 0 is invalid
|
||||
entity_id: 2.into(),
|
||||
worlds: vec![Arc::new(world)],
|
||||
command_dispatcher: Arc::new(command_dispatcher),
|
||||
command_dispatcher,
|
||||
auth_client,
|
||||
key_store: KeyStore::new(),
|
||||
server_listing: Mutex::new(CachedStatus::new()),
|
||||
|
||||
Reference in New Issue
Block a user