diff --git a/src/command/dispatch/dig.rs b/src/command/dispatch/dig.rs index 838f455..2fe3586 100644 --- a/src/command/dispatch/dig.rs +++ b/src/command/dispatch/dig.rs @@ -21,7 +21,7 @@ impl Command { let direction = match Direction::from_str(&args) { Ok(d) => d, Err(e) => { - send_queue.push(token, format!("{}", e), true); + send_queue.push(token, format!("{}", e), true, None); return send_queue; } }; @@ -31,7 +31,7 @@ impl Command { // make sure exit doesn't already exist if start_room.exits.contains_key(&direction) { - send_queue.push(token, "Exit already exists", true); + send_queue.push(token, "Exit already exists", true, None); return send_queue; } @@ -73,25 +73,25 @@ impl Command { // save the new room if db.save_room(&new_room).is_ok() { - send_queue.push(token, "New room saved\n", false); + send_queue.push(token, "New room saved\n", false, None); } else { - send_queue.push(token, "Unable to save new room", true); + send_queue.push(token, "Unable to save new room", true, None); return send_queue; } // save the start room if db.save_room(&start_room).is_ok() { - send_queue.push(token, "Start room saved\n", false); + send_queue.push(token, "Start room saved\n", false, None); } else { - send_queue.push(token, "Unable to save start room", true); + send_queue.push(token, "Unable to save start room", true, None); return send_queue; } // save the zone if db.save_zone(&zone).is_ok() { - send_queue.push(token, "Zone saved\n", false); + send_queue.push(token, "Zone saved\n", false, None); } else { - send_queue.push(token, "Unable to save zone", true); + send_queue.push(token, "Unable to save zone", true, None); return send_queue; } @@ -99,12 +99,17 @@ impl Command { player.location = new_room.id; if db.save_player(&player).is_ok() { if db.save_connected_player(token, &player).is_ok() { - send_queue.push(token, format!("You dig {}.\n\n", direction.long()), false); + send_queue.push( + token, + format!("You dig {}.\n\n", direction.long()), + false, + None, + ); } else { - send_queue.push(token, "Unable to save connected player", true); + send_queue.push(token, "Unable to save connected player", true, None); } } else { - send_queue.push(token, "Unable to save player", true); + send_queue.push(token, "Unable to save player", true, None); return send_queue; } @@ -117,6 +122,7 @@ impl Command { neighbor_token, format!("{} digs {}.", player.name, direction.long()), true, + None, ); } } diff --git a/src/command/dispatch/look.rs b/src/command/dispatch/look.rs index 21b3491..bf2d2a3 100644 --- a/src/command/dispatch/look.rs +++ b/src/command/dispatch/look.rs @@ -18,7 +18,12 @@ impl Command { let room = try_option_send_error!(token, db.load_room(player.location)); // room name - send_queue.push(token, format!("{}\n", room.name.cyan().to_string()), false); + send_queue.push( + token, + format!("{}\n", room.name.cyan().to_string()), + false, + None, + ); // room description send_queue.push( @@ -29,6 +34,7 @@ impl Command { s }), false, + None, ); // exits @@ -38,6 +44,7 @@ impl Command { .cyan() .to_string(), false, + None, ); // other people in room @@ -46,11 +53,16 @@ impl Command { db.find_connected_players_by_location(player.location) ) { if neighbor_token != token { - send_queue.push(token, format!("{} is here", neighbor_player.name), false); + send_queue.push( + token, + format!("{} is here", neighbor_player.name), + false, + None, + ); } } - send_queue.push(token, "", true); + send_queue.push(token, "", true, None); send_queue } diff --git a/src/command/dispatch/move_room.rs b/src/command/dispatch/move_room.rs index 167fe6a..85cc9af 100644 --- a/src/command/dispatch/move_room.rs +++ b/src/command/dispatch/move_room.rs @@ -39,7 +39,7 @@ impl Command { let exit = if let Some(exit) = start_room.exits.get(&direction) { exit } else { - send_queue.push(token, "You can't go that way.", true); + send_queue.push(token, "You can't go that way.", true, None); return send_queue; }; @@ -50,7 +50,12 @@ impl Command { player.location = target_room.id; let _ = try_send_error!(token, db.save_player(&player)); let _ = try_send_error!(token, db.save_connected_player(token, &player)); - send_queue.push(token, format!("You leave {}.\n\n", direction.long()), false); + send_queue.push( + token, + format!("You leave {}.\n\n", direction.long()), + false, + None, + ); // tell people about leaving for (neighbor_token, _) in @@ -61,6 +66,7 @@ impl Command { neighbor_token, format!("{} leaves {}.", player.name, direction.long()), true, + None, ); } } @@ -78,6 +84,7 @@ impl Command { direction.opposite().long() ), true, + None, ); } } diff --git a/src/command/dispatch/quit.rs b/src/command/dispatch/quit.rs index 7f1e1b2..484b2d8 100644 --- a/src/command/dispatch/quit.rs +++ b/src/command/dispatch/quit.rs @@ -6,6 +6,6 @@ use crate::queue::SendQueue; impl Command { pub fn dispatch_quit(&self, _: String, token: Token, _: &mut Db) -> SendQueue { - SendQueue(vec![(token, "Goodbye\n\n".into(), false)].into()) + SendQueue(vec![(token, "Goodbye\n\n".into(), false, None)].into()) } } diff --git a/src/command/dispatch/save.rs b/src/command/dispatch/save.rs index 677af44..78f2cb4 100644 --- a/src/command/dispatch/save.rs +++ b/src/command/dispatch/save.rs @@ -14,7 +14,7 @@ impl Command { let _ = try_send_error!(token, db.save_player(&player)); let _ = try_send_error!(token, db.save_connected_player(token, &player)); - send_queue.push(token, "Ok", true); + send_queue.push(token, "Ok", true, None); send_queue } } diff --git a/src/command/dispatch/say.rs b/src/command/dispatch/say.rs index 0678654..1bef846 100644 --- a/src/command/dispatch/say.rs +++ b/src/command/dispatch/say.rs @@ -24,6 +24,7 @@ impl Command { format!("{} says, \"{}\"\n", player.name, args) }, true, + None, ); } diff --git a/src/command/new/room.rs b/src/command/new/room.rs index cc17c4b..67ebada 100644 --- a/src/command/new/room.rs +++ b/src/command/new/room.rs @@ -35,6 +35,14 @@ impl CommandNew { 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()) + SendQueue( + vec![( + token, + format!("Room created with id {}", new_room_id), + true, + None, + )] + .into(), + ) } } diff --git a/src/command/new/zone.rs b/src/command/new/zone.rs index 7074686..a6adbb1 100644 --- a/src/command/new/zone.rs +++ b/src/command/new/zone.rs @@ -34,6 +34,14 @@ impl CommandNew { 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()) + SendQueue( + vec![( + token, + format!("Zone created with id {}", new_zone_id), + true, + None, + )] + .into(), + ) } } diff --git a/src/command/set/player/name.rs b/src/command/set/player/name.rs index 79dd240..e52cb37 100644 --- a/src/command/set/player/name.rs +++ b/src/command/set/player/name.rs @@ -12,7 +12,7 @@ impl CommandSetPlayer { let new_name = args.trim(); if new_name.is_empty() { - return SendQueue(vec![(token, "Name can't be empty".into(), true)].into()); + return SendQueue(vec![(token, "Name can't be empty".into(), true, None)].into()); } player.name = new_name.to_string(); diff --git a/src/command/set/room/description/delete.rs b/src/command/set/room/description/delete.rs index e385c5d..04bf403 100644 --- a/src/command/set/room/description/delete.rs +++ b/src/command/set/room/description/delete.rs @@ -12,7 +12,7 @@ impl CommandSetRoomDescription { pub fn dispatch_delete(&self, args: String, token: Token, db: &mut Db) -> SendQueue { // make sure something was provided if args.is_empty() { - return SendQueue(vec![(token, "Delete which line?".into(), true)].into()); + return SendQueue(vec![(token, "Delete which line?".into(), true, None)].into()); } // try and get the line number @@ -30,7 +30,7 @@ impl CommandSetRoomDescription { // make sure description has enough lines if line_num > room.description.len().into() || line_num <= 0 { - return SendQueue(vec![(token, "Line doeesn't exist".into(), true)].into()); + return SendQueue(vec![(token, "Line doeesn't exist".into(), true, None)].into()); } // remove the line and save diff --git a/src/command/set/room/description/set.rs b/src/command/set/room/description/set.rs index 48cd6aa..220de07 100644 --- a/src/command/set/room/description/set.rs +++ b/src/command/set/room/description/set.rs @@ -13,7 +13,13 @@ impl CommandSetRoomDescription { // make sure something was provided if args.is_empty() { return SendQueue( - vec![(token, "Set what line to what description?".into(), true)].into(), + vec![( + token, + "Set what line to what description?".into(), + true, + None, + )] + .into(), ); } diff --git a/src/game/iter_once.rs b/src/game/iter_once.rs index 3ed6060..3f662e5 100644 --- a/src/game/iter_once.rs +++ b/src/game/iter_once.rs @@ -22,7 +22,7 @@ impl Game { } // send everything in the send queue - while let Some((token, message, prompt)) = send_queue.pop() { + while let Some((token, message, prompt, state)) = send_queue.pop() { // get the client let client = if let Some(client) = self.clients.get_mut(&token) { client diff --git a/src/game/state/action.rs b/src/game/state/action.rs index 8fdf5f0..ae8e4d0 100644 --- a/src/game/state/action.rs +++ b/src/game/state/action.rs @@ -23,7 +23,7 @@ impl Game { // no need to do anything else if there's nothing to process if lines.is_empty() { - send_queue.push(token, "", true); + send_queue.push(token, "", true, None); return send_queue; } @@ -33,7 +33,7 @@ impl Game { let (command, args) = match Command::parse(&line) { Ok(c) => c, Err(e) => { - send_queue.push(token, format!("{}", e), true); + send_queue.push(token, format!("{}", e), true, None); continue; } }; diff --git a/src/game/state/login.rs b/src/game/state/login.rs index 98b0b8e..3233c1a 100644 --- a/src/game/state/login.rs +++ b/src/game/state/login.rs @@ -24,11 +24,11 @@ impl Game { // get the username Login::Username => { if message.is_empty() { - send_queue.push(token, "\n\nUsername: ", false); + send_queue.push(token, "\n\nUsername: ", false, None); } else { match self.db.find_player_by_name(&message) { Ok(Some(_)) => { - send_queue.push(token, "\nPassword: ", false); + send_queue.push(token, "\nPassword: ", false, None); client.state = State::Login(Login::Password(message)); } Ok(None) => { @@ -36,11 +36,12 @@ impl Game { token, format!("\nCreate {}? [y/N]: ", message.clone()), false, + None, ); client.state = State::Login(Login::CreateUser(message)); } Err(_) => { - send_queue.push(token, "\nError\n\nUsername: ", false); + send_queue.push(token, "\nError\n\nUsername: ", false, None); } } } @@ -49,10 +50,10 @@ impl Game { // username not found Login::CreateUser(username) => { if !message.clone().is_empty() && message != "n" { - send_queue.push(token, "\nNew password: ", false); + send_queue.push(token, "\nNew password: ", false, None); client.state = State::Login(Login::CreatePassword(username.to_owned())); } else { - send_queue.push(token, "\n\nUsername: ", false); + send_queue.push(token, "\n\nUsername: ", false, None); client.state = State::Login(Login::Username); } } @@ -60,10 +61,10 @@ impl Game { // first new user password Login::CreatePassword(username) => { if message.is_empty() { - send_queue.push(token, "\n\nUsername: ", false); + send_queue.push(token, "\n\nUsername: ", false, None); client.state = State::Login(Login::Username); } else { - send_queue.push(token, "\nNew password again: ", false); + send_queue.push(token, "\nNew password again: ", false, None); client.state = State::Login(Login::CreatePassword2((username.to_owned(), message))); } @@ -72,7 +73,7 @@ impl Game { Login::CreatePassword2((username, pass)) => { let pass = pass.to_owned(); if message.is_empty() || message != pass { - send_queue.push(token, "\n\nUsername: ", false); + send_queue.push(token, "\n\nUsername: ", false, None); client.state = State::Login(Login::Username); } else { if let Ok(id) = self.db.new_player_id() { @@ -85,8 +86,8 @@ impl Game { }; if self.db.single_save_player(token, &player).is_ok() { - send_queue.push(token, format!("Welcome, {}\n", username), false); - send_queue.push(token, "", true); + send_queue.push(token, format!("Welcome, {}\n", username), false, None); + send_queue.push(token, "", true, None); send_queue.append(&mut Command::dispatch_look( &Command::default(), @@ -97,17 +98,17 @@ impl Game { client.state = State::Action; } else { - send_queue.push(token, "Error", true); + send_queue.push(token, "Error", true, None); } } else { - send_queue.push(token, "Error", true); + send_queue.push(token, "Error", true, None); } } } Login::Password(username) => { if message.is_empty() { - send_queue.push(token, "\n\nUsername: ", false); + send_queue.push(token, "\n\nUsername: ", false, None); client.state = State::Login(Login::Username); } else { match self.db.find_player_by_name(username) { @@ -118,6 +119,7 @@ impl Game { token, format!("Welcome back, {}\n\n", username), false, + None, ); client.state = State::Action; @@ -128,19 +130,19 @@ impl Game { &mut self.db, )); } else { - send_queue.push(token, "Unable to login\n", false); - send_queue.push(token, "\n\nUsername: ", false); + send_queue.push(token, "Unable to login\n", false, None); + send_queue.push(token, "\n\nUsername: ", false, None); client.state = State::Login(Login::Username); } } else { - send_queue.push(token, "Incorrect password\n", false); - send_queue.push(token, "\n\nUsername: ", false); + send_queue.push(token, "Incorrect password\n", false, None); + send_queue.push(token, "\n\nUsername: ", false, None); client.state = State::Login(Login::Username); } } Ok(None) | Err(_) => { - send_queue.push(token, "Error\n", false); - send_queue.push(token, "\n\nUsername: ", false); + send_queue.push(token, "Error\n", false, None); + send_queue.push(token, "\n\nUsername: ", false, None); client.state = State::Login(Login::Username); } } diff --git a/src/macros.rs b/src/macros.rs index 9677179..6f3af33 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -139,7 +139,7 @@ macro_rules! try_send { Ok(r) => r, Err(_e) => { return $crate::queue::SendQueue( - vec![($i, std::fmt::format(format_args!($($arg)*)), true)].into() + vec![($i, std::fmt::format(format_args!($($arg)*)), true, None)].into() ); } } @@ -177,7 +177,7 @@ macro_rules! option_send { Some(r) => r, None => { return $crate::queue::SendQueue( - vec![($i, std::fmt::format(format_args!($($arg)*)), true)].into() + vec![($i, std::fmt::format(format_args!($($arg)*)), true, None)].into() ); } } diff --git a/src/queue.rs b/src/queue.rs index dfdbcc6..5c2a5fc 100644 --- a/src/queue.rs +++ b/src/queue.rs @@ -1,8 +1,11 @@ //! Queues for recv and send + use std::collections::VecDeque; use mio::Token; +use crate::state::State; + /// Queue of clients with a message to receive. /// /// * The client is designated with the [`Token`](../../mio/struct.Token.html). @@ -35,8 +38,9 @@ impl RecvQueue { /// is used to store the message. /// * [`bool`](https://doc.rust-lang.org/nightly/std/primitive.bool.html) is set to `true` if a /// prompt is to be displayed following the message. +/// * `Option` to have the player be put into a different play state #[derive(Debug)] -pub struct SendQueue(pub VecDeque<(Token, String, bool)>); +pub struct SendQueue(pub VecDeque<(Token, String, bool, Option)>); impl SendQueue { pub fn new() -> Self { @@ -47,19 +51,25 @@ impl SendQueue { self.0.append(&mut queue.0); } - pub fn pop(&mut self) -> Option<(Token, String, bool)> { + pub fn pop(&mut self) -> Option<(Token, String, bool, Option)> { self.0.pop_front() } - pub fn push>(&mut self, token: Token, s: S, prompt: bool) { - self.0.push_back((token, s.into(), prompt)); + pub fn push>( + &mut self, + token: Token, + s: S, + prompt: bool, + state: Option, + ) { + self.0.push_back((token, s.into(), prompt, state)); } pub fn error(token: Token) -> Self { - Self(vec![(token, "Error".to_string(), true)].into()) + Self(vec![(token, "Error".to_string(), true, None)].into()) } pub fn ok(token: Token) -> Self { - Self(vec![(token, "Ok".to_string(), true)].into()) + Self(vec![(token, "Ok".to_string(), true, None)].into()) } }