Skip to content

Commit

Permalink
Merge pull request #81 from Snowiiii/command-rewrite
Browse files Browse the repository at this point in the history
Command system rewrite
  • Loading branch information
Snowiiii authored Sep 7, 2024
2 parents 2ee9710 + 870059a commit 01a71d6
Show file tree
Hide file tree
Showing 7 changed files with 49 additions and 49 deletions.
5 changes: 3 additions & 2 deletions pumpkin/src/client/player_packet.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use std::f32::consts::PI;

use crate::{
commands::{handle_command, CommandSender},
commands::CommandSender,
entity::player::{ChatMode, Hand, Player},
server::Server,
world::player_chunker,
Expand Down Expand Up @@ -214,7 +214,8 @@ impl Player {
}

pub fn handle_chat_command(&mut self, server: &mut Server, command: SChatCommand) {
handle_command(&mut CommandSender::Player(self), server, &command.command);
let dispatcher = server.command_dispatcher.clone();
dispatcher.handle_command(&mut CommandSender::Player(self), server, &command.command);
}

pub fn handle_player_ground(&mut self, _server: &mut Server, ground: SSetPlayerGround) {
Expand Down
26 changes: 11 additions & 15 deletions pumpkin/src/commands/cmd_help.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use crate::commands::dispatcher::InvalidTreeError::InvalidConsumptionError;
use crate::commands::dispatcher::{CommandDispatcher, InvalidTreeError};
use crate::commands::tree::{Command, CommandTree, ConsumedArgs, RawArgs};
use crate::commands::tree_builder::argument;
use crate::commands::{dispatcher_init, CommandSender, DISPATCHER};
use crate::commands::CommandSender;
use pumpkin_core::text::TextComponent;

const NAMES: [&str; 3] = ["help", "h", "?"];
Expand All @@ -11,12 +11,12 @@ const DESCRIPTION: &str = "Print a help message.";

const ARG_COMMAND: &str = "command";

fn consume_arg_command(_src: &CommandSender, args: &mut RawArgs) -> Option<String> {
let s = args.pop()?;
fn consume_arg_command(_src: &CommandSender, _args: &mut RawArgs) -> Option<String> {
// let s = args.pop()?;

let dispatcher = DISPATCHER.get_or_init(dispatcher_init);

dispatcher.get_tree(s).ok().map(|tree| tree.names[0].into())
// dispatcher.get_tree(s).ok().map(|tree| tree.names[0].into())
// TODO
None
}

fn parse_arg_command<'a>(
Expand All @@ -35,10 +35,8 @@ fn parse_arg_command<'a>(
pub(crate) fn init_command_tree<'a>() -> CommandTree<'a> {
CommandTree::new(NAMES, DESCRIPTION)
.with_child(
argument(ARG_COMMAND, consume_arg_command).execute(&|sender, _, args| {
let dispatcher = DISPATCHER.get_or_init(dispatcher_init);

let tree = parse_arg_command(args, dispatcher)?;
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: {}",
Expand All @@ -50,14 +48,12 @@ pub(crate) fn init_command_tree<'a>() -> CommandTree<'a> {
Ok(())
}),
)
.execute(&|sender, _, _args| {
let dispatcher = DISPATCHER.get_or_init(dispatcher_init);

let mut keys: Vec<&str> = dispatcher.commands.keys().copied().collect();
.execute(&|sender, server, _args| {
let mut keys: Vec<&str> = server.command_dispatcher.commands.keys().copied().collect();
keys.sort();

for key in keys {
let Command::Tree(tree) = &dispatcher.commands[key] else {
let Command::Tree(tree) = &server.command_dispatcher.commands[key] else {
continue;
};

Expand Down
13 changes: 12 additions & 1 deletion pumpkin/src/commands/dispatcher.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use pumpkin_core::text::TextComponent;

use crate::commands::dispatcher::InvalidTreeError::{
InvalidConsumptionError, InvalidRequirementError,
};
Expand All @@ -17,12 +19,21 @@ pub(crate) enum InvalidTreeError {
InvalidRequirementError,
}

pub(crate) struct CommandDispatcher<'a> {
#[derive(Default)]
pub struct CommandDispatcher<'a> {
pub(crate) commands: HashMap<&'a str, Command<'a>>,
}

/// Stores registered [CommandTree]s and dispatches commands to them.
impl<'a> CommandDispatcher<'a> {
pub fn handle_command(&self, sender: &mut CommandSender, server: &mut Server, cmd: &str) {
if let Err(err) = self.dispatch(sender, server, cmd) {
sender.send_message(
TextComponent::text(&err).color_named(pumpkin_core::text::color::NamedColor::Red),
)
}
}

/// Execute a command using its corresponding [CommandTree].
pub(crate) fn dispatch(
&'a self,
Expand Down
28 changes: 3 additions & 25 deletions pumpkin/src/commands/mod.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,13 @@
use pumpkin_core::text::TextComponent;
use std::collections::HashMap;
use std::sync::OnceLock;

use crate::commands::dispatcher::CommandDispatcher;
use crate::entity::player::Player;
use crate::server::Server;
mod arg_player;
mod cmd_gamemode;
mod cmd_help;
mod cmd_pumpkin;
mod cmd_stop;
mod dispatcher;
pub mod dispatcher;
mod tree;
mod tree_builder;
mod tree_format;
Expand Down Expand Up @@ -64,17 +61,8 @@ impl<'a> CommandSender<'a> {
}
}

/// todo: reconsider using constant
///
/// Central point from which commands are dispatched. Should always be initialized using
/// [dispatcher_init].
static DISPATCHER: OnceLock<CommandDispatcher> = OnceLock::new();

/// create [CommandDispatcher] instance for [DISPATCHER]
fn dispatcher_init<'a>() -> CommandDispatcher<'a> {
let mut dispatcher = CommandDispatcher {
commands: HashMap::new(),
};
pub fn default_dispatcher<'a>() -> CommandDispatcher<'a> {
let mut dispatcher = CommandDispatcher::default();

dispatcher.register(cmd_pumpkin::init_command_tree());
dispatcher.register(cmd_gamemode::init_command_tree());
Expand All @@ -83,13 +71,3 @@ fn dispatcher_init<'a>() -> CommandDispatcher<'a> {

dispatcher
}

pub fn handle_command(sender: &mut CommandSender, server: &mut Server, cmd: &str) {
let dispatcher = DISPATCHER.get_or_init(dispatcher_init);

if let Err(err) = dispatcher.dispatch(sender, server, cmd) {
sender.send_message(
TextComponent::text(&err).color_named(pumpkin_core::text::color::NamedColor::Red),
)
}
}
8 changes: 6 additions & 2 deletions pumpkin/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ use std::collections::HashMap;
use std::io::{self};

use client::{interrupted, Client};
use commands::handle_command;
use server::Server;

// Setup some tokens to allow us to identify which event is for which socket.
Expand Down Expand Up @@ -98,7 +97,12 @@ fn main() -> io::Result<()> {

if !out.is_empty() {
let mut server = server1.lock().await;
handle_command(&mut commands::CommandSender::Console, &mut server, &out);
let dispatcher = server.command_dispatcher.clone();
dispatcher.handle_command(
&mut commands::CommandSender::Console,
&mut server,
&out,
);
}
}
});
Expand Down
5 changes: 3 additions & 2 deletions pumpkin/src/rcon/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use packet::{Packet, PacketError, PacketType};
use pumpkin_config::RCONConfig;
use thiserror::Error;

use crate::{commands::handle_command, server::Server};
use crate::server::Server;

mod packet;

Expand Down Expand Up @@ -194,7 +194,8 @@ impl RCONClient {
if self.logged_in {
let mut output = Vec::new();
let mut server = server.lock().await;
handle_command(
let dispatcher = server.command_dispatcher.clone();
dispatcher.handle_command(
&mut crate::commands::CommandSender::Rcon(&mut output),
&mut server,
packet.get_body(),
Expand Down
13 changes: 11 additions & 2 deletions pumpkin/src/server/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,12 @@ use pumpkin_world::dimension::Dimension;
use pumpkin_registry::Registry;
use rsa::{traits::PublicKeyParts, RsaPrivateKey, RsaPublicKey};

use crate::{client::Client, entity::player::Player, world::World};
use crate::{
client::Client,
commands::{default_dispatcher, dispatcher::CommandDispatcher},
entity::player::Player,
world::World,
};

pub const CURRENT_MC_VERSION: &str = "1.21.1";

Expand All @@ -35,6 +40,8 @@ pub struct Server {

pub plugin_loader: PluginLoader,

pub command_dispatcher: Arc<CommandDispatcher<'static>>,

pub worlds: Vec<Arc<tokio::sync::Mutex<World>>>,
pub status_response: StatusResponse,
// We cache the json response here so we don't parse it every time someone makes a Status request.
Expand Down Expand Up @@ -81,14 +88,15 @@ impl Server {
None
};

// First register default command, after that plugins can put in their own
let command_dispatcher = default_dispatcher();
log::info!("Loading Plugins");
let plugin_loader = PluginLoader::load();

let world = World::load(Dimension::OverWorld.into_level(
// TODO: load form config
"./world".parse().unwrap(),
));

Self {
plugin_loader,
cached_registry: Registry::get_static(),
Expand All @@ -98,6 +106,7 @@ impl Server {
public_key,
cached_server_brand,
private_key,
command_dispatcher: Arc::new(command_dispatcher),
status_response,
status_response_json,
public_key_der,
Expand Down

0 comments on commit 01a71d6

Please sign in to comment.