From 033cbf22733298952be82ad8df8360f6b549ecf0 Mon Sep 17 00:00:00 2001 From: Condorra Date: Wed, 17 Jan 2024 22:48:42 +1100 Subject: [PATCH] Allow plugging in to charge in powered locations --- .../src/message_handler/user_commands.rs | 4 + .../src/message_handler/user_commands/get.rs | 1 + .../src/message_handler/user_commands/plug.rs | 143 ++++++++++++++++++ .../src/static_content/possession_type.rs | 2 + .../static_content/possession_type/food.rs | 2 + .../static_content/possession_type/lights.rs | 2 + .../static_content/possession_type/meat.rs | 1 + .../src/static_content/room/cok_murl.yaml | 2 + 8 files changed, 157 insertions(+) create mode 100644 blastmud_game/src/message_handler/user_commands/plug.rs diff --git a/blastmud_game/src/message_handler/user_commands.rs b/blastmud_game/src/message_handler/user_commands.rs index b30c571..2cc823c 100644 --- a/blastmud_game/src/message_handler/user_commands.rs +++ b/blastmud_game/src/message_handler/user_commands.rs @@ -55,6 +55,7 @@ pub mod open; mod page; pub mod parsing; pub mod pay; +pub mod plug; mod pow; pub mod put; mod quit; @@ -198,6 +199,8 @@ static REGISTERED_COMMANDS: UserVerbRegistry = phf_map! { "l" => look::VERB, "look" => look::VERB, "read" => look::VERB, + "examine" => look::VERB, + "ex" => look::VERB, "feint" => feint::VERB, "list" => list::VERB, @@ -221,6 +224,7 @@ static REGISTERED_COMMANDS: UserVerbRegistry = phf_map! { "reply" => page::VERB, "pay" => pay::VERB, + "plug" => plug::VERB, "pow" => pow::VERB, "power" => pow::VERB, diff --git a/blastmud_game/src/message_handler/user_commands/get.rs b/blastmud_game/src/message_handler/user_commands/get.rs index 982e6f5..80ea8b7 100644 --- a/blastmud_game/src/message_handler/user_commands/get.rs +++ b/blastmud_game/src/message_handler/user_commands/get.rs @@ -114,6 +114,7 @@ impl QueueCommandHandler for QueueHandler { &item.display_for_sentence(1, false) ))? } + ctx.trans.delete_task("ChargeItem", &item.refstr()).await?; let msg = format!( "{} picks up {}\n", diff --git a/blastmud_game/src/message_handler/user_commands/plug.rs b/blastmud_game/src/message_handler/user_commands/plug.rs new file mode 100644 index 0000000..fd10665 --- /dev/null +++ b/blastmud_game/src/message_handler/user_commands/plug.rs @@ -0,0 +1,143 @@ +use crate::{ + db::ItemSearchParams, + models::{ + item::ItemSpecialData, + task::{Task, TaskDetails, TaskMeta}, + }, + services::comms::broadcast_to_room, + static_content::{ + dynzone::{dynzone_by_type, DynzoneType}, + possession_type::possession_data, + room::room_map_by_code, + }, + DResult, +}; + +use super::{ + get_player_item_or_fail, search_item_for_user, user_error, CommandHandlingError, UResult, + UserError, UserVerb, UserVerbRef, VerbContext, +}; +#[double] +use crate::db::DBTrans; +use ansi::ansi; +use async_trait::async_trait; +use chrono::{Duration, Utc}; +use mockall_double::double; + +async fn place_has_power(trans: &DBTrans, place_type: &str, place_code: &str) -> DResult { + match place_type { + "room" => room_map_by_code() + .get(place_code) + .map(|r| Ok(r.has_power)) + .unwrap_or(Ok(false)), + "dynroom" => trans + .find_item_by_type_code(place_type, place_code) + .await? + .and_then(|place| match place.special_data.as_ref() { + Some(ItemSpecialData::DynroomData { + dynzone_code, + dynroom_code, + }) => DynzoneType::from_str(&dynzone_code) + .and_then(|dzt| dynzone_by_type().get(&dzt)) + .and_then(|dz| dz.dyn_rooms.get(dynroom_code.as_str())) + .map(|dr| Ok(dr.has_power)), + _ => None, + }) + .unwrap_or(Ok(false)), + _ => Ok(false), + } +} + +pub struct Verb; +#[async_trait] +impl UserVerb for Verb { + async fn handle( + self: &Self, + ctx: &mut VerbContext, + _verb: &str, + remaining: &str, + ) -> UResult<()> { + let (word, remaining) = match remaining.split_once(" ") { + None => user_error(ansi!("Try plug in something").to_owned())?, + Some(v) => v, + }; + if word.trim() != "in" { + user_error(ansi!("Try plug in something").to_owned())?; + } + let player_item = get_player_item_or_fail(ctx).await?; + if player_item.death_data.is_some() { + user_error("Plugging metal things in can make you dead, but being dead doesn't let you plug things in.".to_owned())?; + } + let remaining = remaining.trim(); + let item = search_item_for_user( + ctx, + &ItemSearchParams { + limit: 1, + include_loc_contents: true, + item_type_only: Some("possession"), + ..ItemSearchParams::base(&player_item, &remaining) + }, + ) + .await + .map_err(|e| match e { + CommandHandlingError::UserError(m) => CommandHandlingError::UserError( + m + " I only looked in the room - try dropping an item first.", + ), + e => e, + })?; + let charge_data = match item + .possession_type + .as_ref() + .and_then(|pt| possession_data().get(pt)) + .and_then(|pd| pd.charge_data.as_ref()) + { + Some(v) if v.electric_recharge => v, + _ => user_error("You can't recharge that!".to_owned())?, + }; + + let (place_type, place_code) = player_item + .location + .split_once("/") + .ok_or_else(|| UserError("Bad location".to_owned()))?; + if !place_has_power(&ctx.trans, place_type, place_code).await? { + user_error("You can't find any power sockets to plug in to.".to_owned())?; + } + + if item.charges >= charge_data.max_charges { + user_error("You realise it's already fully charged.".to_owned())?; + } + + let refstr = item.refstr(); + if ctx + .trans + .check_task_by_type_code("ChargeItem", &refstr) + .await? + { + user_error("It's already charging!".to_owned())?; + } + ctx.trans + .upsert_task(&Task { + meta: TaskMeta { + task_code: refstr.clone(), + next_scheduled: Utc::now() + Duration::minutes(1), + ..Default::default() + }, + details: TaskDetails::ChargeItem { item: refstr }, + }) + .await?; + broadcast_to_room( + &ctx.trans, + &player_item.location, + None, + &format!( + "{} plugs in {}.\n", + &player_item.display_for_sentence(1, true), + &item.display_for_sentence(1, false) + ), + ) + .await?; + Ok(()) + } +} +static VERB_INT: Verb = Verb; +pub static VERB: UserVerbRef = &VERB_INT as UserVerbRef; diff --git a/blastmud_game/src/static_content/possession_type.rs b/blastmud_game/src/static_content/possession_type.rs index 7378142..186ec8f 100644 --- a/blastmud_game/src/static_content/possession_type.rs +++ b/blastmud_game/src/static_content/possession_type.rs @@ -155,6 +155,7 @@ pub struct ChargeData { pub max_charges: u8, pub charge_name_prefix: &'static str, pub charge_name_suffix: &'static str, + pub electric_recharge: bool, } impl Default for ChargeData { @@ -163,6 +164,7 @@ impl Default for ChargeData { max_charges: 1, charge_name_prefix: "charge", charge_name_suffix: "", + electric_recharge: false, } } } diff --git a/blastmud_game/src/static_content/possession_type/food.rs b/blastmud_game/src/static_content/possession_type/food.rs index ce40b65..d5a576b 100644 --- a/blastmud_game/src/static_content/possession_type/food.rs +++ b/blastmud_game/src/static_content/possession_type/food.rs @@ -20,6 +20,7 @@ pub fn data() -> &'static Vec<(PossessionType, PossessionData)> { max_charges: 20, charge_name_prefix: "bite", charge_name_suffix: "of food", + ..Default::default() }), ..Default::default() } @@ -39,6 +40,7 @@ pub fn data() -> &'static Vec<(PossessionType, PossessionData)> { max_charges: 20, charge_name_prefix: "bite", charge_name_suffix: "of food", + ..Default::default() }), ..Default::default() } diff --git a/blastmud_game/src/static_content/possession_type/lights.rs b/blastmud_game/src/static_content/possession_type/lights.rs index 6c4c055..38e2ee1 100644 --- a/blastmud_game/src/static_content/possession_type/lights.rs +++ b/blastmud_game/src/static_content/possession_type/lights.rs @@ -175,6 +175,8 @@ pub fn data() -> &'static Vec<(PossessionType, PossessionData)> { max_charges: 20, charge_name_prefix: "bar", charge_name_suffix: "of power", + electric_recharge: true, + ..ChargeData::default() }), ..Default::default() })]) diff --git a/blastmud_game/src/static_content/possession_type/meat.rs b/blastmud_game/src/static_content/possession_type/meat.rs index 88d2a9a..bc1e4ce 100644 --- a/blastmud_game/src/static_content/possession_type/meat.rs +++ b/blastmud_game/src/static_content/possession_type/meat.rs @@ -29,6 +29,7 @@ pub fn data() -> &'static Vec<(PossessionType, PossessionData)> { max_charges: 20, charge_name_prefix: "bite", charge_name_suffix: "of food", + ..Default::default() }), ..Default::default() } diff --git a/blastmud_game/src/static_content/room/cok_murl.yaml b/blastmud_game/src/static_content/room/cok_murl.yaml index 6f237a8..683b5b7 100644 --- a/blastmud_game/src/static_content/room/cok_murl.yaml +++ b/blastmud_game/src/static_content/room/cok_murl.yaml @@ -15,6 +15,7 @@ y: 0 z: 0 description: "A sizeable lobby that looks like it is serves the dual purpose as the entrance to the residential condos and as a grand entrance to the linked Murlison Suites commercial building. It is tiled with sparkling clean bluestone tiles. Light green tinted tempered glass panels line the walls. You notice a set of sleek lifts, supervised by a friendly robot, and a passage to the attached Murlison commercial building to the east.\n\n\"Welcome to Condos on King!\", intones the bot, \"say in name\" with the name of the person you are here to see, and I'll guide you to their apartment. Or try rent studio to rent a studio apartment for $20 a day ($40 setup fee), and vacate studio to give notice to vacate" + has_power: true exits: - direction: west target: !Custom room/melbs_kingst_80 @@ -34,6 +35,7 @@ y: 0 z: 0 description: "A sleek reception that could have been the bridge of a 2000s era sci-fi spaceship. Linished metal plates are lit up by ambient blue LEDs, while stone tiles cover the floor. You see a white android, complete with elegant rounded corners and glowing blue eyes.\n\n\"Welcome to Murlison Suites - the best a business can rent\", purs the bot pleasantly. \"Just say in corpname\" and I'll guide you to the suite for that corp before you can blink! Or if you hold a corp and would like to rent the best suite money can buy for it, just say rent deluxe for corpname, and I'll set you up\"" + has_power: true exits: - direction: west rentable_dynzone: