diff --git a/src/command/command.rs b/src/command/command.rs index 80666cf..aef70fd 100644 --- a/src/command/command.rs +++ b/src/command/command.rs @@ -3,7 +3,7 @@ use std::default::Default; use mio::Token; use strum_macros::{Display, EnumIter}; -use crate::command::{CommandSet, Parse, ParserError}; +use crate::command::{CommandNew, CommandSet, Parse, ParserError}; use crate::database::Db; use crate::queue::SendQueue; @@ -24,6 +24,7 @@ pub enum Command { Dig, Help, Look, + New(CommandNew), Quit, Save, Say, @@ -55,6 +56,7 @@ impl Parse for Command { 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.", @@ -65,6 +67,10 @@ impl Parse for Command { fn parse_subcommand(&self, s: String) -> Result<(Self, String), ParserError> { match self { + Self::New(_) => { + let (command, args) = CommandNew::parse(s)?; + Ok((Self::New(command), args)) + } Self::Set(_) => { let (command, args) = CommandSet::parse(s)?; Ok((Self::Set(command), args)) @@ -76,6 +82,7 @@ impl Parse for Command { fn subcommand_help(&self, _: String) -> Option { match self { + Self::New(command_new) => Some(command_new.help_all()), Self::Set(command_set) => Some(command_set.help_all()), _ => None, } @@ -83,6 +90,7 @@ impl Parse for Command { 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(), } @@ -98,6 +106,7 @@ impl Parse for Command { 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, diff --git a/src/command/mod.rs b/src/command/mod.rs index 423ba49..e280632 100644 --- a/src/command/mod.rs +++ b/src/command/mod.rs @@ -1,10 +1,12 @@ mod command; mod dispatch; +mod new; mod parse; mod parser_error; mod set; pub use command::Command; +pub use new::*; pub use parse::Parse; pub use parser_error::ParserError; pub use set::*; diff --git a/src/command/new/mod.rs b/src/command/new/mod.rs new file mode 100644 index 0000000..f5eb8b3 --- /dev/null +++ b/src/command/new/mod.rs @@ -0,0 +1,5 @@ +mod new; +mod room; +mod zone; + +pub use new::*; diff --git a/src/command/new/new.rs b/src/command/new/new.rs new file mode 100644 index 0000000..46fbc88 --- /dev/null +++ b/src/command/new/new.rs @@ -0,0 +1,39 @@ +use std::default::Default; + +use mio::Token; +use strum_macros::{Display, EnumIter}; + +use crate::command::Parse; +use crate::database::Db; +use crate::queue::SendQueue; + +#[derive(Clone, Debug, Display, EnumIter, Eq, Ord, PartialEq, PartialOrd)] +pub enum CommandNew { + Room, + Zone, + Default, +} + +impl Default for CommandNew { + fn default() -> Self { + Self::Default + } +} + +impl Parse for CommandNew { + fn help(&self) -> &str { + match self { + Self::Room => "new room :: Create a new room.", + Self::Zone => "new zone :: Create a new zone.", + Self::Default => "", + } + } + + fn dispatch_map(&self) -> fn(&Self, String, Token, &mut Db) -> SendQueue { + match self { + Self::Room => Self::dispatch_room, + Self::Zone => Self::dispatch_zone, + Self::Default => Self::dispatch_default, + } + } +} diff --git a/src/command/new/room.rs b/src/command/new/room.rs new file mode 100644 index 0000000..cc17c4b --- /dev/null +++ b/src/command/new/room.rs @@ -0,0 +1,40 @@ +use std::collections::HashMap; + +use mio::Token; + +use crate::command::CommandNew; +use crate::database::Db; +use crate::queue::SendQueue; +use crate::world::Room; +use crate::{try_option_send_error, try_send_error}; + +impl CommandNew { + /// Create a new room + pub fn dispatch_room( + _command: &CommandNew, + _args: String, + token: Token, + db: &mut Db, + ) -> SendQueue { + let player = try_option_send_error!(token, db.get_connected_player(token)); + let room = try_option_send_error!(token, db.load_room(player.location)); + let zone = try_option_send_error!(token, db.load_zone(room.zone)); + let mut root = try_send_error!(token, db.root_zone(&zone)); + let new_room_id = try_send_error!(token, db.new_area_id()); + + let new_room = Room { + id: new_room_id, + zone: root.id, + name: format!("New Room {}", new_room_id), + description: Vec::new(), + users_visible: true, + exits: HashMap::new(), + }; + + let _ = try_send_error!(token, db.save_room(&new_room)); + let _ = root.areas.insert(new_room.id); + let _ = try_send_error!(token, db.save_zone(&root)); + + SendQueue(vec![(token, format!("Room created with id {}", new_room_id), true)].into()) + } +} diff --git a/src/command/new/zone.rs b/src/command/new/zone.rs new file mode 100644 index 0000000..7074686 --- /dev/null +++ b/src/command/new/zone.rs @@ -0,0 +1,39 @@ +use std::collections::HashSet; + +use mio::Token; + +use crate::command::CommandNew; +use crate::database::Db; +use crate::queue::SendQueue; +use crate::world::Zone; +use crate::{try_option_send_error, try_send_error}; + +impl CommandNew { + /// Create a new zone + pub fn dispatch_zone( + _command: &CommandNew, + _args: String, + token: Token, + db: &mut Db, + ) -> SendQueue { + let player = try_option_send_error!(token, db.get_connected_player(token)); + let room = try_option_send_error!(token, db.load_room(player.location)); + let zone = try_option_send_error!(token, db.load_zone(room.zone)); + let mut root = try_send_error!(token, db.root_zone(&zone)); + let new_zone_id = try_send_error!(token, db.new_area_id()); + + let new_zone = Zone { + id: new_zone_id, + parent: root.id, + name: format!("New Zone {}", new_zone_id), + users_visible: true, + areas: HashSet::new(), + }; + + let _ = try_send_error!(token, db.save_zone(&new_zone)); + let _ = root.areas.insert(new_zone.id); + let _ = try_send_error!(token, db.save_zone(&root)); + + SendQueue(vec![(token, format!("Zone created with id {}", new_zone_id), true)].into()) + } +}