You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

130 lines
3.7 KiB

use std::default::Default;
use mio::Token;
use strum_macros::{Display, EnumIter};
use crate::command::{CommandNew, CommandSet, Parse, ParserError};
use crate::database::Db;
use crate::queue::SendQueue;
use crate::result::RudeResult;
use crate::try_log;
/// Root level of command.
///
/// Every command must be implemented here, either directly or nested inside
/// a subcommand somewhere.
///
/// The parser matches against lowercase string representations of the enum
/// variants
#[derive(Clone, Debug, Display, EnumIter, Eq, Ord, PartialEq, PartialOrd)]
pub enum Command {
N,
S,
E,
W,
U,
D,
North,
South,
East,
West,
Up,
Down,
Dig,
Help,
Look,
New(CommandNew),
Quit,
Save,
Say,
Set(CommandSet),
Default,
}
impl Default for Command {
fn default() -> Self {
Self::Default
}
}
impl Parse for Command {
fn help(&self) -> &str {
match self {
Self::N => "n :: Move one room to the north.",
Self::S => "s :: Move one room to the south.",
Self::E => "e :: Move one room to the east.",
Self::W => "w :: Move one room to the west.",
Self::U => "u :: Move one room up.",
Self::D => "d :: Move one room down.",
Self::North => "north :: Move one room to the north.",
Self::South => "south :: Move one room to the south.",
Self::East => "east :: Move one room to the east.",
Self::West => "west :: Move one room to the west.",
Self::Up => "up :: Move one room up.",
Self::Down => "down :: Move one room down.",
Self::Dig => "dig DIRECTION:: Dig a new path to a new room in the provided direction.",
Self::Help => "help [COMMAND]:: Provide help on a specific command, or an overview.",
Self::Look => "look :: Take a look around the current room.",
Self::New(_) => "new :: Create new things.",
Self::Quit => "quit :: Quit playing and disconnect from the game.",
Self::Save => "save :: Write player information to disk.",
Self::Say => "say MESSAGE:: Say something to the room.",
Self::Set(_) => "set OPTIONS :: Set various parameters.",
Self::Default => "",
}
}
fn parse_subcommand(&self, s: String) -> RudeResult<(Self, String)> {
match self {
Self::New(_) => {
let (command, args) =
try_log!(CommandNew::parse(s), "Unable to parse new subcommand");
Ok((Self::New(command), args))
}
Self::Set(_) => {
let (command, args) =
try_log!(CommandSet::parse(s), "Unable to parse set subcommand");
Ok((Self::Set(command), args))
}
Self::Default => Err(ParserError::Default.into()),
_ => Ok((self.clone(), s)),
}
}
fn subcommand_help(&self) -> Option<String> {
match self {
Self::New(command_new) => Some(command_new.help_all()),
Self::Set(command_set) => Some(command_set.help_all()),
_ => None,
}
}
fn dispatch_map_subcommand(&self, args: String, token: Token, db: &mut Db) -> SendQueue {
match self {
Self::New(command_new) => command_new.dispatch(command_new, args, token, db),
Self::Set(command_set) => command_set.dispatch(command_set, args, token, db),
_ => SendQueue::new(),
}
}
fn dispatch_map(&self) -> fn(&Self, String, Token, &mut Db) -> SendQueue {
match self {
Self::N | Self::North => Self::dispatch_move_room,
Self::S | Self::South => Self::dispatch_move_room,
Self::E | Self::East => Self::dispatch_move_room,
Self::W | Self::West => Self::dispatch_move_room,
Self::U | Self::Up => Self::dispatch_move_room,
Self::D | Self::Down => Self::dispatch_move_room,
Self::Dig => Self::dispatch_dig,
Self::Help => Self::dispatch_help,
Self::New(_) => Self::dispatch_map_subcommand,
Self::Look => Self::dispatch_look,
Self::Quit => Self::dispatch_quit,
Self::Save => Self::dispatch_save,
Self::Say => Self::dispatch_say,
Self::Set(_) => Self::dispatch_map_subcommand,
Self::Default => Self::dispatch_default,
}
}
}