diff --git a/client/src/cmd.rs b/client/src/cmd.rs index de523bd39b..09d59ee15f 100644 --- a/client/src/cmd.rs +++ b/client/src/cmd.rs @@ -47,9 +47,10 @@ fn complete_player(part: &str, client: &Client) -> Vec { } fn complete_command(part: &str) -> Vec { - CHAT_COMMANDS - .iter() - .map(|com| com.keyword()) + CHAT_SHORTCUTS + .keys() + .map(ToString::to_string) + .chain(CHAT_COMMANDS.iter().map(ToString::to_string)) .filter(|kwd| kwd.starts_with(part) || format!("/{}", kwd).starts_with(part)) .map(|c| format!("/{}", c)) .collect() diff --git a/common/src/cmd.rs b/common/src/cmd.rs index d9dedc50b3..181404e465 100644 --- a/common/src/cmd.rs +++ b/common/src/cmd.rs @@ -1,7 +1,13 @@ use crate::{assets, comp, npc}; use lazy_static::lazy_static; -use std::{ops::Deref, path::Path, str::FromStr}; use tracing::warn; +use std::{ + collections::HashMap, + fmt::{self, Display}, + ops::Deref, + path::Path, + str::FromStr, +}; /// Struct representing a command that a user can run from server chat. pub struct ChatCommandData { @@ -109,6 +115,15 @@ pub static CHAT_COMMANDS: &[ChatCommand] = &[ ]; lazy_static! { + pub static ref CHAT_SHORTCUTS: HashMap = [ + ('f', ChatCommand::Faction), + ('g', ChatCommand::Group), + ('r', ChatCommand::Region), + ('s', ChatCommand::Say), + ('t', ChatCommand::Tell), + ('w', ChatCommand::World), + ].iter().cloned().collect(); + static ref ALIGNMENTS: Vec = vec!["wild", "enemy", "npc", "pet"] .iter() .map(|s| s.to_string()) @@ -404,13 +419,19 @@ impl ChatCommand { ArgumentSpec::Command(_) => "{}", ArgumentSpec::Message(_) => "{/.*/}", ArgumentSpec::SubCommand => "{} {/.*/}", - ArgumentSpec::Enum(_, _, _) => "{}", // TODO + ArgumentSpec::Enum(_, _, _) => "{}", }) .collect::>() .join(" ") } } +impl Display for ChatCommand { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { + write!(f, "{}", self.keyword()) + } +} + impl FromStr for ChatCommand { type Err = (); @@ -420,10 +441,21 @@ impl FromStr for ChatCommand { } else { &keyword[..] }; - for c in CHAT_COMMANDS { - if kwd == c.keyword() { + if keyword.len() == 1 { + if let Some(c) = keyword + .chars() + .nth(0) + .as_ref() + .and_then(|k| CHAT_SHORTCUTS.get(k)) + { return Ok(*c); } + } else { + for c in CHAT_COMMANDS { + if kwd == c.keyword() { + return Ok(*c); + } + } } Err(()) } diff --git a/server/src/cmd.rs b/server/src/cmd.rs index f88d63ae29..680126bb67 100644 --- a/server/src/cmd.rs +++ b/server/src/cmd.rs @@ -6,7 +6,7 @@ use crate::{Server, StateExt}; use chrono::{NaiveTime, Timelike}; use common::{ assets, - cmd::{ChatCommand, CHAT_COMMANDS}, + cmd::{ChatCommand, CHAT_COMMANDS, CHAT_SHORTCUTS}, comp, comp::Item, event::{EventBus, ServerEvent}, @@ -657,6 +657,11 @@ fn handle_help( server.notify_client(client, ServerMsg::private(String::from(cmd.help_string()))); } } + let shortcuts = CHAT_SHORTCUTS.iter().fold( + "Aditionally, you can use the following shortcuts:".to_string(), + |s, (k, v)| format!("{}\n/{} => /{}", s, k, v.keyword()), + ); + server.notify_client(client, ServerMsg::private(shortcuts.to_string())); } } @@ -1591,19 +1596,14 @@ fn handle_sudo( scan_fmt_some!(&args, &action.arg_fmt(), String, String, String) { let cmd_args = cmd_args.unwrap_or(String::from("")); - let cmd = if cmd.chars().next() == Some('/') { - cmd.chars().skip(1).collect() - } else { - cmd - }; - if let Some(action) = CHAT_COMMANDS.iter().find(|c| c.keyword() == cmd) { + if let Ok(action) = cmd.parse() { let ecs = server.state.ecs(); let entity_opt = (&ecs.entities(), &ecs.read_storage::()) .join() .find(|(_, player)| player.alias == player_alias) .map(|(entity, _)| entity); if let Some(entity) = entity_opt { - get_handler(action)(server, client, entity, cmd_args, action); + get_handler(&action)(server, client, entity, cmd_args, &action); } else { server.notify_client( client, diff --git a/server/src/events/mod.rs b/server/src/events/mod.rs index 1689739871..fb26dad411 100644 --- a/server/src/events/mod.rs +++ b/server/src/events/mod.rs @@ -20,9 +20,16 @@ mod inventory_manip; mod player; pub enum Event { - ClientConnected { entity: EcsEntity }, - ClientDisconnected { entity: EcsEntity }, - Chat { entity: Option, msg: String }, + ClientConnected { + entity: EcsEntity, + }, + ClientDisconnected { + entity: EcsEntity, + }, + Chat { + entity: Option, + msg: String, + }, } impl Server {