From 3d3f792fdc79680c9b07628f30c2ef0761a4a870 Mon Sep 17 00:00:00 2001 From: Condorra Date: Sun, 16 Apr 2023 22:39:34 +1000 Subject: [PATCH] Support closing doors. --- .../src/message_handler/user_commands.rs | 2 + .../message_handler/user_commands/close.rs | 120 ++++++++++++++++++ .../src/message_handler/user_commands/open.rs | 7 - .../src/regular_tasks/queued_command.rs | 6 +- 4 files changed, 127 insertions(+), 8 deletions(-) create mode 100644 blastmud_game/src/message_handler/user_commands/close.rs diff --git a/blastmud_game/src/message_handler/user_commands.rs b/blastmud_game/src/message_handler/user_commands.rs index bfd2445..f5fe5db 100644 --- a/blastmud_game/src/message_handler/user_commands.rs +++ b/blastmud_game/src/message_handler/user_commands.rs @@ -16,6 +16,7 @@ mod allow; pub mod attack; mod buy; mod c; +pub mod close; pub mod corp; pub mod drop; pub mod get; @@ -125,6 +126,7 @@ static REGISTERED_COMMANDS: UserVerbRegistry = phf_map! { "attack" => attack::VERB, "buy" => buy::VERB, "c" => c::VERB, + "close" => close::VERB, "corp" => corp::VERB, "drop" => drop::VERB, "get" => get::VERB, diff --git a/blastmud_game/src/message_handler/user_commands/close.rs b/blastmud_game/src/message_handler/user_commands/close.rs new file mode 100644 index 0000000..7bd7a7d --- /dev/null +++ b/blastmud_game/src/message_handler/user_commands/close.rs @@ -0,0 +1,120 @@ +use super::{ + VerbContext, UserVerb, UserVerbRef, UResult, UserError, user_error, + get_player_item_or_fail, + open::{is_door_in_direction, DoorSituation}, +}; +use crate::{ + regular_tasks::{ + queued_command::{ + QueueCommandHandler, + QueueCommand, + queue_command + }, + }, + static_content::{ + room::Direction, + }, + models::{ + item::DoorState, + }, + services::comms::broadcast_to_room, +}; +use async_trait::async_trait; +use std::time; + +pub struct QueueHandler; +#[async_trait] +impl QueueCommandHandler for QueueHandler { + async fn start_command(&self, ctx: &mut VerbContext<'_>, command: &QueueCommand) + -> UResult { + let direction = match command { + QueueCommand::CloseDoor { direction } => direction, + _ => user_error("Unexpected queued command".to_owned())? + }; + let player_item = get_player_item_or_fail(ctx).await?; + match is_door_in_direction(&ctx.trans, &direction, &player_item).await? { + DoorSituation::NoDoor => user_error("There is no door to close.".to_owned())?, + DoorSituation::DoorIntoRoom { state: DoorState { open: false, .. }, .. } | + DoorSituation::DoorOutOfRoom { state: DoorState { open: false, .. }, .. } => + user_error("The door is already closed.".to_owned())?, + _ => {} + } + + Ok(time::Duration::from_secs(1)) + } + + #[allow(unreachable_patterns)] + async fn finish_command(&self, ctx: &mut VerbContext<'_>, command: &QueueCommand) + -> UResult<()> { + let direction = match command { + QueueCommand::CloseDoor { direction } => direction, + _ => user_error("Unexpected queued command".to_owned())? + }; + let player_item = get_player_item_or_fail(ctx).await?; + let (room_1, dir_in_room, room_2) = match is_door_in_direction(&ctx.trans, &direction, &player_item).await? { + DoorSituation::NoDoor => user_error("There is no door to close.".to_owned())?, + DoorSituation::DoorIntoRoom { state: DoorState { open: false, .. }, .. } | + DoorSituation::DoorOutOfRoom { state: DoorState { open: false, .. }, .. } => + user_error("The door is already closed.".to_owned())?, + DoorSituation::DoorIntoRoom { room_with_door, current_room, .. } => { + if let Some(revdir) = direction.reverse() { + let mut entering_room_mut = (*room_with_door).clone(); + if let Some(door_map) = entering_room_mut.door_states.as_mut() { + if let Some(door) = door_map.get_mut(&revdir) { + (*door).open = false; + } + }; + ctx.trans.save_item_model(&entering_room_mut).await?; + (room_with_door, revdir, current_room) + } else { + user_error("There's no door possible there.".to_owned())? + } + }, + DoorSituation::DoorOutOfRoom { room_with_door, new_room, .. } => { + let mut entering_room_mut = (*room_with_door).clone(); + if let Some(door_map) = entering_room_mut.door_states.as_mut() { + if let Some(door) = door_map.get_mut(&direction) { + (*door).open = false; + } + } + ctx.trans.save_item_model(&entering_room_mut).await?; + (room_with_door, direction.clone(), new_room) + } + }; + + for (loc, dir) in [(&room_1.refstr(), &dir_in_room.describe()), + (&room_2.refstr(), &dir_in_room.reverse().map(|d| d.describe()) + .unwrap_or_else(|| "outside".to_owned()))] { + broadcast_to_room( + &ctx.trans, + loc, + None, + &format!("{} closes the door to the {}.\n", + &player_item.display_for_sentence(true, 1, true), + dir + ), + Some( + &format!("{} closes the door to the {}.\n", + &player_item.display_for_sentence(false, 1, true), + dir + ) + ) + ).await?; + } + + Ok(()) + } +} + +pub struct Verb; +#[async_trait] +impl UserVerb for Verb { + async fn handle(self: &Self, ctx: &mut VerbContext, _verb: &str, remaining: &str) -> UResult<()> { + let dir = Direction::parse(remaining) + .ok_or_else(|| UserError("Unknown direction".to_owned()))?; + queue_command(ctx, &QueueCommand::CloseDoor { direction: dir.clone() }).await?; + Ok(()) + } +} +static VERB_INT: Verb = Verb; +pub static VERB: UserVerbRef = &VERB_INT as UserVerbRef; diff --git a/blastmud_game/src/message_handler/user_commands/open.rs b/blastmud_game/src/message_handler/user_commands/open.rs index 4b836da..f943617 100644 --- a/blastmud_game/src/message_handler/user_commands/open.rs +++ b/blastmud_game/src/message_handler/user_commands/open.rs @@ -30,7 +30,6 @@ use std::time; use chrono::{self, Utc}; use mockall_double::double; #[double] use crate::db::DBTrans; -use log::info; #[derive(Clone)] pub struct SwingShutHandler; @@ -106,14 +105,8 @@ pub async fn attempt_open_immediate(trans: &DBTrans, ctx_opt: &mut Option<&mut V if let Some(door_map) = entering_room_mut.door_states.as_mut() { if let Some(door) = door_map.get_mut(&revdir) { (*door).open = true; - info!("Set door_map"); - } else { - info!("door_map missing direction"); } - } else { - info!("door_map None"); } - info!("Saving door map"); trans.save_item_model(&entering_room_mut).await?; (room_with_door, revdir, current_room) diff --git a/blastmud_game/src/regular_tasks/queued_command.rs b/blastmud_game/src/regular_tasks/queued_command.rs index 3ed243b..e3d0b55 100644 --- a/blastmud_game/src/regular_tasks/queued_command.rs +++ b/blastmud_game/src/regular_tasks/queued_command.rs @@ -21,7 +21,8 @@ use crate::message_handler::user_commands::{ wield, user_error, get_user_or_fail, - open + open, + close }; use crate::static_content::room::Direction; use once_cell::sync::OnceCell; @@ -34,6 +35,7 @@ pub enum QueueCommand { Get { possession_id: String }, Drop { possession_id: String }, OpenDoor { direction: Direction }, + CloseDoor { direction: Direction }, } impl QueueCommand { pub fn name(&self) -> &'static str { @@ -45,6 +47,7 @@ impl QueueCommand { Get {..} => "Get", Drop {..} => "Drop", OpenDoor {..} => "OpenDoor", + CloseDoor {..} => "CloseDoor", } } } @@ -65,6 +68,7 @@ fn queue_command_registry() -> &'static BTreeMap<&'static str, &'static (dyn Que ("Use", &use_cmd::QueueHandler as &(dyn QueueCommandHandler + Sync + Send)), ("Wield", &wield::QueueHandler as &(dyn QueueCommandHandler + Sync + Send)), ("OpenDoor", &open::QueueHandler as &(dyn QueueCommandHandler + Sync + Send)), + ("CloseDoor", &close::QueueHandler as &(dyn QueueCommandHandler + Sync + Send)), ).into_iter().collect()) }