implement help command

This commit is contained in:
Zoey 2024-04-23 11:53:43 -07:00
parent 8f73d8e788
commit b3050b5f29
No known key found for this signature in database
GPG key ID: 8611B896D1AAFAF2
2 changed files with 111 additions and 5 deletions

View file

@ -5,6 +5,10 @@ const CMD_SAY: &str = "say";
const CMD_SET_PERM: &str = "setperm";
const CMD_KICK: &str = "kick";
const CMD_STOP: &str = "stop";
const CMD_HELP: &str = "help";
/// list of commands available on the server
pub const COMMANDS_LIST: &[&str] = &[CMD_ME, CMD_SAY, CMD_SET_PERM, CMD_KICK, CMD_STOP, CMD_HELP];
/// enum for possible commands
#[derive(Debug, Clone)]
@ -27,6 +31,8 @@ pub enum Command<'m> {
},
/// command to stop the server
Stop,
/// gets help about the given command, or about all commands if no command is given
Help { command: Option<&'m str> },
}
impl<'m> Command<'m> {
@ -50,19 +56,73 @@ impl<'m> Command<'m> {
Self::Kick { username, message }
}
CMD_STOP => Self::Stop,
CMD_HELP => Self::Help {
command: (!arguments.is_empty()).then_some(arguments),
},
_ => return Err(format!("Unknown command: {command_name}")),
})
}
/// gets the command's name
pub fn command_name(&self) -> &'static str {
match self {
Self::Me { .. } => CMD_ME,
Self::Say { .. } => CMD_SAY,
Self::SetPermissions { .. } => CMD_SET_PERM,
Self::Kick { .. } => CMD_KICK,
Self::Stop => CMD_STOP,
Self::Help { .. } => CMD_HELP,
}
}
/// checks which permissions are required to run this command
pub fn perms_required(&self) -> PlayerType {
match self {
Self::Me { .. } => PlayerType::Normal,
Self::Stop => PlayerType::Operator,
Self::perms_required_by_name(self.command_name())
}
/// checks which permissions are required to run a command by name
pub fn perms_required_by_name(cmd: &str) -> PlayerType {
match cmd {
CMD_ME => PlayerType::Normal,
CMD_STOP => PlayerType::Operator,
CMD_HELP => PlayerType::Normal,
_ => PlayerType::Moderator,
}
}
/// gets help about the given command
pub fn help(cmd: &str) -> Vec<String> {
let c = |t: &str| format!("&f{}{cmd} {t}", Self::PREFIX);
match cmd {
CMD_ME => vec![
c("<action>"),
"&fDisplays an action as if you're doing it.".to_string(),
],
CMD_SAY => vec![
c("<message>"),
"&fSends a message as being from the server.".to_string(),
],
CMD_SET_PERM => vec![
c("<username> <permission level>"),
"&fSets a player's permission level.".to_string(),
],
CMD_KICK => vec![
c("<username> [reason]"),
"&fKicks a player from the server.".to_string(),
],
CMD_STOP => vec![
c(""),
"&fStops the server while saving the level.".to_string(),
],
CMD_HELP => vec![
c("[command]"),
"&fGets a list of commands or help about a command.".to_string(),
],
_ => vec!["&eUnknown command!".to_string()],
}
}
/// gets the next string argument from the command
fn next_string(args: &mut &'m str) -> Result<&'m str, String> {
if args.is_empty() {

View file

@ -10,9 +10,11 @@ use tokio::{
};
use crate::{
command::Command,
command::{Command, COMMANDS_LIST},
level::{block::BLOCK_INFO, BlockUpdate, Level},
packet::{client::ClientPacket, server::ServerPacket, PacketWriter, ARRAY_LENGTH},
packet::{
client::ClientPacket, server::ServerPacket, PacketWriter, ARRAY_LENGTH, STRING_LENGTH,
},
player::{Player, PlayerType},
server::config::ServerProtectionMode,
};
@ -365,6 +367,7 @@ async fn handle_stream_inner(
}
);
}
Command::Say { message } => {
let message =
format!("&d[SERVER] &f{message}");
@ -376,6 +379,7 @@ async fn handle_stream_inner(
}
);
}
Command::SetPermissions {
player_username,
permissions,
@ -471,6 +475,48 @@ async fn handle_stream_inner(
Command::Stop => {
data.stop = true;
}
Command::Help { command } => {
let messages =
if let Some(command) = command {
Command::help(command)
} else {
let mut messages = vec![
"Commands available to you:"
.to_string(),
];
let mut current_message =
"&f".to_string();
for command in COMMANDS_LIST.iter()
{
if Command::perms_required_by_name(command) > player.player_type {
continue;
}
if current_message.len()
+ 3 + command.len()
> STRING_LENGTH
{
messages.push(format!(
"{current_message},"
));
current_message =
"&f".to_string();
}
if current_message.len() == 2 {
current_message = format!("{current_message}{command}");
} else {
current_message = format!("{current_message}, {command}");
}
}
if !current_message.is_empty() {
messages.push(current_message);
}
messages
};
for msg in messages {
msg!(msg);
}
}
}
}
Err(msg) => {