forked from blasthavers/blastmud
Allow (un)installation of scanlocks.
This commit is contained in:
parent
3d3f792fdc
commit
ed3d77dcbe
@ -739,7 +739,7 @@ impl DBTrans {
|
|||||||
self.pg_trans()?.execute("UPDATE items SET details=\
|
self.pg_trans()?.execute("UPDATE items SET details=\
|
||||||
JSONB_SET(details, '{action_type}', $1) \
|
JSONB_SET(details, '{action_type}', $1) \
|
||||||
WHERE details->>'location' = $2 AND \
|
WHERE details->>'location' = $2 AND \
|
||||||
details->>'action_type' = $3::JSONB::TEXT",
|
(details->'action_type')::TEXT = $3::JSONB::TEXT",
|
||||||
&[&serde_json::to_value(other_item_action_type)?,
|
&[&serde_json::to_value(other_item_action_type)?,
|
||||||
&item.location,
|
&item.location,
|
||||||
&serde_json::to_value(new_action_type)?
|
&serde_json::to_value(new_action_type)?
|
||||||
@ -759,7 +759,7 @@ impl DBTrans {
|
|||||||
if let Some(item) = self.pg_trans()?.query_opt(
|
if let Some(item) = self.pg_trans()?.query_opt(
|
||||||
"SELECT details FROM items WHERE \
|
"SELECT details FROM items WHERE \
|
||||||
details->>'location' = $1 AND \
|
details->>'location' = $1 AND \
|
||||||
details->>'action_type' = $2::JSONB::TEXT",
|
((details->'action_type')::TEXT = $2::JSONB::TEXT)",
|
||||||
&[&location,
|
&[&location,
|
||||||
&serde_json::to_value(action_type)?]).await? {
|
&serde_json::to_value(action_type)?]).await? {
|
||||||
return Ok(Some(Arc::new(serde_json::from_value::<Item>(item.get("details"))?)));
|
return Ok(Some(Arc::new(serde_json::from_value::<Item>(item.get("details"))?)));
|
||||||
|
@ -23,6 +23,7 @@ pub mod get;
|
|||||||
mod describe;
|
mod describe;
|
||||||
mod help;
|
mod help;
|
||||||
mod ignore;
|
mod ignore;
|
||||||
|
mod install;
|
||||||
mod inventory;
|
mod inventory;
|
||||||
mod less_explicit_mode;
|
mod less_explicit_mode;
|
||||||
mod list;
|
mod list;
|
||||||
@ -40,6 +41,7 @@ pub mod say;
|
|||||||
mod score;
|
mod score;
|
||||||
mod sign;
|
mod sign;
|
||||||
mod status;
|
mod status;
|
||||||
|
mod uninstall;
|
||||||
pub mod use_cmd;
|
pub mod use_cmd;
|
||||||
mod vacate;
|
mod vacate;
|
||||||
mod whisper;
|
mod whisper;
|
||||||
@ -130,6 +132,7 @@ static REGISTERED_COMMANDS: UserVerbRegistry = phf_map! {
|
|||||||
"corp" => corp::VERB,
|
"corp" => corp::VERB,
|
||||||
"drop" => drop::VERB,
|
"drop" => drop::VERB,
|
||||||
"get" => get::VERB,
|
"get" => get::VERB,
|
||||||
|
"install" => install::VERB,
|
||||||
"inventory" => inventory::VERB,
|
"inventory" => inventory::VERB,
|
||||||
"inv" => inventory::VERB,
|
"inv" => inventory::VERB,
|
||||||
"i" => inventory::VERB,
|
"i" => inventory::VERB,
|
||||||
@ -170,7 +173,8 @@ static REGISTERED_COMMANDS: UserVerbRegistry = phf_map! {
|
|||||||
"st" => status::VERB,
|
"st" => status::VERB,
|
||||||
"stat" => status::VERB,
|
"stat" => status::VERB,
|
||||||
"status" => status::VERB,
|
"status" => status::VERB,
|
||||||
|
|
||||||
|
"uninstall" => uninstall::VERB,
|
||||||
"use" => use_cmd::VERB,
|
"use" => use_cmd::VERB,
|
||||||
"vacate" => vacate::VERB,
|
"vacate" => vacate::VERB,
|
||||||
|
|
||||||
|
@ -101,6 +101,9 @@ impl QueueCommandHandler for QueueHandler {
|
|||||||
)
|
)
|
||||||
).await?;
|
).await?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ctx.trans.delete_task("SwingShut",
|
||||||
|
&format!("{}/{}", &room_1.refstr(), &dir_in_room.describe())).await?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -136,12 +136,18 @@ impl UserVerb for Verb {
|
|||||||
if player_item.is_dead {
|
if player_item.is_dead {
|
||||||
user_error("You try to get it, but your ghostly hands slip through it uselessly".to_owned())?;
|
user_error("You try to get it, but your ghostly hands slip through it uselessly".to_owned())?;
|
||||||
}
|
}
|
||||||
for target in targets {
|
|
||||||
|
let mut did_anything: bool = false;
|
||||||
|
for target in targets.iter().filter(|t| t.action_type.is_visible_in_look()) {
|
||||||
if target.item_type != "possession" {
|
if target.item_type != "possession" {
|
||||||
user_error("You can't get that!".to_owned())?;
|
user_error("You can't get that!".to_owned())?;
|
||||||
}
|
}
|
||||||
|
did_anything = true;
|
||||||
queue_command(ctx, &QueueCommand::Get { possession_id: target.item_code.clone() }).await?;
|
queue_command(ctx, &QueueCommand::Get { possession_id: target.item_code.clone() }).await?;
|
||||||
}
|
}
|
||||||
|
if !did_anything {
|
||||||
|
user_error("I didn't find anything matching.".to_owned())?;
|
||||||
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
66
blastmud_game/src/message_handler/user_commands/install.rs
Normal file
66
blastmud_game/src/message_handler/user_commands/install.rs
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
use super::{VerbContext, UserVerb, UserVerbRef, UResult,
|
||||||
|
UserError,
|
||||||
|
user_error, get_player_item_or_fail, search_item_for_user};
|
||||||
|
use crate::{
|
||||||
|
db::ItemSearchParams,
|
||||||
|
static_content::{
|
||||||
|
possession_type::possession_data,
|
||||||
|
room::Direction,
|
||||||
|
},
|
||||||
|
models::item::ItemFlag,
|
||||||
|
};
|
||||||
|
use async_trait::async_trait;
|
||||||
|
use ansi::ansi;
|
||||||
|
|
||||||
|
pub struct Verb;
|
||||||
|
#[async_trait]
|
||||||
|
impl UserVerb for Verb {
|
||||||
|
async fn handle(self: &Self, ctx: &mut VerbContext, _verb: &str, remaining: &str) -> UResult<()> {
|
||||||
|
let (install_what_raw, what_dir_raw) = match remaining.rsplit_once(" on door to ") {
|
||||||
|
None => user_error(ansi!("Install where? Try <bold>install<reset> <lt>lock> <bold>on door to<reset> <lt>direction>").to_owned())?,
|
||||||
|
Some(v) => v
|
||||||
|
};
|
||||||
|
let player_item = get_player_item_or_fail(ctx).await?;
|
||||||
|
if player_item.is_dead {
|
||||||
|
user_error("Apparently, you have to be alive to work as an installer.\
|
||||||
|
So discriminatory!".to_owned())?;
|
||||||
|
}
|
||||||
|
let item = search_item_for_user(ctx, &ItemSearchParams {
|
||||||
|
include_contents: true,
|
||||||
|
..ItemSearchParams::base(&player_item, install_what_raw.trim())
|
||||||
|
}).await?;
|
||||||
|
if item.item_type != "possession" {
|
||||||
|
user_error("You can't install that!".to_owned())?;
|
||||||
|
}
|
||||||
|
|
||||||
|
let handler = match item.possession_type.as_ref()
|
||||||
|
.and_then(|pt| possession_data().get(pt))
|
||||||
|
.and_then(|pd| pd.install_handler) {
|
||||||
|
None => user_error("You can't install that!".to_owned())?,
|
||||||
|
Some(h) => h
|
||||||
|
};
|
||||||
|
|
||||||
|
let (loc_t, loc_c) = player_item.location.split_once("/")
|
||||||
|
.ok_or_else(|| UserError("Invalid current location".to_owned()))?;
|
||||||
|
let loc_item = ctx.trans.find_item_by_type_code(loc_t, loc_c).await?
|
||||||
|
.ok_or_else(|| UserError("Can't find your location".to_owned()))?;
|
||||||
|
if loc_item.owner.as_ref() != Some(&player_item.refstr()) || !loc_item.flags.contains(&ItemFlag::PrivatePlace) {
|
||||||
|
user_error("You can only install things while standing in a private room you own. \
|
||||||
|
If you are outside, try installing from the inside."
|
||||||
|
.to_owned())?;
|
||||||
|
}
|
||||||
|
|
||||||
|
let dir = Direction::parse(what_dir_raw.trim()).ok_or_else(
|
||||||
|
|| UserError("Invalid direction.".to_owned()))?;
|
||||||
|
|
||||||
|
loc_item.door_states.as_ref().and_then(|ds| ds.get(&dir)).ok_or_else(
|
||||||
|
|| UserError("No door to that direction in this room - are you on the wrong side?".to_owned())
|
||||||
|
)?;
|
||||||
|
|
||||||
|
handler.install_cmd(ctx, &player_item, &item, &loc_item, &dir).await?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
static VERB_INT: Verb = Verb;
|
||||||
|
pub static VERB: UserVerbRef = &VERB_INT as UserVerbRef;
|
@ -193,8 +193,7 @@ async fn describe_door(
|
|||||||
&LocationActionType::InstalledOnDoorAsLock((*direction).clone())).await?
|
&LocationActionType::InstalledOnDoorAsLock((*direction).clone())).await?
|
||||||
{
|
{
|
||||||
let lock_desc = lock.display_for_session(&ctx.session_dat);
|
let lock_desc = lock.display_for_session(&ctx.session_dat);
|
||||||
msg.push_str(&format!(" The door is locked with {} {}",
|
msg.push_str(&format!(" The door is locked with {}",
|
||||||
&language::indefinite_article(&lock_desc),
|
|
||||||
&lock_desc
|
&lock_desc
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
@ -217,6 +216,7 @@ async fn list_room_contents<'l>(ctx: &'l VerbContext<'_>, item: &'l Item) -> URe
|
|||||||
|
|
||||||
let all_groups: Vec<Vec<&Arc<Item>>> = items
|
let all_groups: Vec<Vec<&Arc<Item>>> = items
|
||||||
.iter()
|
.iter()
|
||||||
|
.filter(|i| i.action_type.is_visible_in_look())
|
||||||
.group_by(|i| i.display_for_sentence(true, 1, false))
|
.group_by(|i| i.display_for_sentence(true, 1, false))
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|(_, g)|g.collect::<Vec<&Arc<Item>>>())
|
.map(|(_, g)|g.collect::<Vec<&Arc<Item>>>())
|
||||||
|
67
blastmud_game/src/message_handler/user_commands/uninstall.rs
Normal file
67
blastmud_game/src/message_handler/user_commands/uninstall.rs
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
use super::{VerbContext, UserVerb, UserVerbRef, UResult,
|
||||||
|
UserError,
|
||||||
|
user_error, get_player_item_or_fail, search_items_for_user};
|
||||||
|
use crate::{
|
||||||
|
db::ItemSearchParams,
|
||||||
|
static_content::{
|
||||||
|
possession_type::possession_data,
|
||||||
|
room::Direction,
|
||||||
|
},
|
||||||
|
models::item::ItemFlag,
|
||||||
|
};
|
||||||
|
use async_trait::async_trait;
|
||||||
|
use ansi::ansi;
|
||||||
|
|
||||||
|
pub struct Verb;
|
||||||
|
#[async_trait]
|
||||||
|
impl UserVerb for Verb {
|
||||||
|
async fn handle(self: &Self, ctx: &mut VerbContext, _verb: &str, remaining: &str) -> UResult<()> {
|
||||||
|
let (uninstall_what_raw, what_dir_raw) = match remaining.rsplit_once(" from door to ") {
|
||||||
|
None => user_error(ansi!("Uninstall from where? Try <bold>uninstall<reset> <lt>lock> <bold>from door to<reset> <lt>direction>").to_owned())?,
|
||||||
|
Some(v) => v
|
||||||
|
};
|
||||||
|
let player_item = get_player_item_or_fail(ctx).await?;
|
||||||
|
if player_item.is_dead {
|
||||||
|
user_error("Apparently, you have to be alive to work as an uninstaller. \
|
||||||
|
So discriminatory!".to_owned())?;
|
||||||
|
}
|
||||||
|
|
||||||
|
let (loc_t, loc_c) = player_item.location.split_once("/")
|
||||||
|
.ok_or_else(|| UserError("Invalid current location".to_owned()))?;
|
||||||
|
let loc_item = ctx.trans.find_item_by_type_code(loc_t, loc_c).await?
|
||||||
|
.ok_or_else(|| UserError("Can't find your location".to_owned()))?;
|
||||||
|
if loc_item.owner.as_ref() != Some(&player_item.refstr()) || !loc_item.flags.contains(&ItemFlag::PrivatePlace) {
|
||||||
|
user_error("You can only uninstall things while standing in a private room you own. \
|
||||||
|
If you are outside, try uninstalling from the inside."
|
||||||
|
.to_owned())?;
|
||||||
|
}
|
||||||
|
|
||||||
|
let dir = Direction::parse(what_dir_raw.trim()).ok_or_else(
|
||||||
|
|| UserError("Invalid direction.".to_owned()))?;
|
||||||
|
|
||||||
|
let cand_items = search_items_for_user(ctx, &ItemSearchParams {
|
||||||
|
include_loc_contents: true,
|
||||||
|
..ItemSearchParams::base(&player_item, uninstall_what_raw.trim())
|
||||||
|
}).await?;
|
||||||
|
let item = cand_items.iter().find(|it| it.action_type.is_in_direction(&dir))
|
||||||
|
.ok_or_else(
|
||||||
|
|| UserError(
|
||||||
|
"Sorry, I couldn't find anything matching installed on that door.".to_owned()))?;
|
||||||
|
if item.item_type != "possession" {
|
||||||
|
user_error("You can't uninstall that!".to_owned())?;
|
||||||
|
}
|
||||||
|
|
||||||
|
let handler = match item.possession_type.as_ref()
|
||||||
|
.and_then(|pt| possession_data().get(pt))
|
||||||
|
.and_then(|pd| pd.install_handler) {
|
||||||
|
None => user_error("You can't uninstall that!".to_owned())?,
|
||||||
|
Some(h) => h
|
||||||
|
};
|
||||||
|
|
||||||
|
handler.uninstall_cmd(ctx, &player_item, &item, &loc_item, &dir).await?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
static VERB_INT: Verb = Verb;
|
||||||
|
pub static VERB: UserVerbRef = &VERB_INT as UserVerbRef;
|
@ -260,6 +260,23 @@ pub enum LocationActionType {
|
|||||||
InstalledOnDoorAsLock(Direction),
|
InstalledOnDoorAsLock(Direction),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl LocationActionType {
|
||||||
|
pub fn is_visible_in_look(&self) -> bool {
|
||||||
|
use LocationActionType::*;
|
||||||
|
match self {
|
||||||
|
InstalledOnDoorAsLock(_) => false,
|
||||||
|
_ => true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn is_in_direction(&self, dir: &Direction) -> bool {
|
||||||
|
use LocationActionType::*;
|
||||||
|
match self {
|
||||||
|
InstalledOnDoorAsLock(d) if d == dir => true,
|
||||||
|
_ => false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq, Ord, PartialOrd)]
|
#[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq, Ord, PartialOrd)]
|
||||||
pub enum Sex {
|
pub enum Sex {
|
||||||
Male,
|
Male,
|
||||||
|
@ -332,7 +332,7 @@ pub async fn stop_attacking(trans: &DBTrans, by_whom: &Item, to_whom: &Item) ->
|
|||||||
|
|
||||||
async fn what_wielded(trans: &DBTrans, who: &Item) -> DResult<&'static WeaponData> {
|
async fn what_wielded(trans: &DBTrans, who: &Item) -> DResult<&'static WeaponData> {
|
||||||
if let Some(item) = trans.find_by_action_and_location(
|
if let Some(item) = trans.find_by_action_and_location(
|
||||||
&format!("{}/{}", &who.item_type, &who.item_code), &LocationActionType::Wielded).await? {
|
&who.refstr(), &LocationActionType::Wielded).await? {
|
||||||
if let Some(dat) = item.possession_type.as_ref()
|
if let Some(dat) = item.possession_type.as_ref()
|
||||||
.and_then(|pt| possession_data().get(&pt))
|
.and_then(|pt| possession_data().get(&pt))
|
||||||
.and_then(|pd| pd.weapon_data.as_ref()) {
|
.and_then(|pd| pd.weapon_data.as_ref()) {
|
||||||
|
@ -3,6 +3,7 @@ use crate::{
|
|||||||
models::item::{SkillType, Item, Pronouns},
|
models::item::{SkillType, Item, Pronouns},
|
||||||
models::consent::ConsentType,
|
models::consent::ConsentType,
|
||||||
message_handler::user_commands::{UResult, VerbContext},
|
message_handler::user_commands::{UResult, VerbContext},
|
||||||
|
static_content::room::Direction,
|
||||||
};
|
};
|
||||||
use once_cell::sync::OnceCell;
|
use once_cell::sync::OnceCell;
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
@ -122,6 +123,12 @@ pub trait ArglessHandler {
|
|||||||
async fn cmd(&self, ctx: &mut VerbContext, player: &Item, what: &Item) -> UResult<()>;
|
async fn cmd(&self, ctx: &mut VerbContext, player: &Item, what: &Item) -> UResult<()>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
|
pub trait InstallHandler {
|
||||||
|
async fn install_cmd(&self, ctx: &mut VerbContext, player: &Item, what: &Item, room: &Item, direction: &Direction) -> UResult<()>;
|
||||||
|
async fn uninstall_cmd(&self, ctx: &mut VerbContext, player: &Item, what: &Item, room: &Item, direction: &Direction) -> UResult<()>;
|
||||||
|
}
|
||||||
|
|
||||||
pub struct PossessionData {
|
pub struct PossessionData {
|
||||||
pub weapon_data: Option<WeaponData>,
|
pub weapon_data: Option<WeaponData>,
|
||||||
pub display: &'static str,
|
pub display: &'static str,
|
||||||
@ -134,9 +141,10 @@ pub struct PossessionData {
|
|||||||
pub use_data: Option<UseData>,
|
pub use_data: Option<UseData>,
|
||||||
pub becomes_on_spent: Option<PossessionType>,
|
pub becomes_on_spent: Option<PossessionType>,
|
||||||
pub weight: u64,
|
pub weight: u64,
|
||||||
pub write_handler: Option<&'static (dyn WriteHandler + Sync + Send)>,
|
pub install_handler: Option<&'static (dyn InstallHandler + Sync + Send)>,
|
||||||
pub sign_handler: Option<&'static (dyn ArglessHandler + Sync + Send)>,
|
|
||||||
pub lockcheck_handler: Option<&'static (dyn ArglessHandler + Sync + Send)>,
|
pub lockcheck_handler: Option<&'static (dyn ArglessHandler + Sync + Send)>,
|
||||||
|
pub sign_handler: Option<&'static (dyn ArglessHandler + Sync + Send)>,
|
||||||
|
pub write_handler: Option<&'static (dyn WriteHandler + Sync + Send)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for PossessionData {
|
impl Default for PossessionData {
|
||||||
@ -153,9 +161,10 @@ impl Default for PossessionData {
|
|||||||
charge_data: None,
|
charge_data: None,
|
||||||
becomes_on_spent: None,
|
becomes_on_spent: None,
|
||||||
use_data: None,
|
use_data: None,
|
||||||
write_handler: None,
|
install_handler: None,
|
||||||
sign_handler: None,
|
|
||||||
lockcheck_handler: None,
|
lockcheck_handler: None,
|
||||||
|
sign_handler: None,
|
||||||
|
write_handler: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1,126 @@
|
|||||||
use super::PossessionData;
|
use super::{PossessionData, ArglessHandler};
|
||||||
|
use crate::{
|
||||||
|
models::item::{Item, LocationActionType},
|
||||||
|
message_handler::user_commands::{user_error, VerbContext, UResult},
|
||||||
|
static_content::{
|
||||||
|
possession_type::InstallHandler,
|
||||||
|
room::Direction,
|
||||||
|
},
|
||||||
|
services::{comms::broadcast_to_room,
|
||||||
|
capacity::{check_item_capacity, CapacityLevel}}
|
||||||
|
};
|
||||||
|
use async_trait::async_trait;
|
||||||
|
|
||||||
|
struct ScanLockLockcheck;
|
||||||
|
#[async_trait]
|
||||||
|
impl ArglessHandler for ScanLockLockcheck {
|
||||||
|
async fn cmd(&self, ctx: &mut VerbContext, player: &Item, what: &Item) -> UResult<()> {
|
||||||
|
if what.owner == Some(player.refstr()) {
|
||||||
|
ctx.trans.queue_for_session(&ctx.session, Some(
|
||||||
|
"The scanlock in the door emits a single high-pitched beep as it unlocks.\n")).await?;
|
||||||
|
} else {
|
||||||
|
user_error(
|
||||||
|
"The scanlock in the door emits a medium-pitched tone followed by a low tone, and remains locked.".to_owned())?;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static LOCK_WEIGHT: u64 = 500;
|
||||||
|
|
||||||
|
struct ScanLockInstall;
|
||||||
|
#[async_trait]
|
||||||
|
impl InstallHandler for ScanLockInstall {
|
||||||
|
async fn install_cmd(&self, ctx: &mut VerbContext, player: &Item, what: &Item, room: &Item,
|
||||||
|
direction: &Direction) -> UResult<()> {
|
||||||
|
if what.action_type != LocationActionType::Normal {
|
||||||
|
user_error("That scanlock is already in use.".to_owned())?;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ctx.trans.find_by_action_and_location(
|
||||||
|
&room.refstr(),
|
||||||
|
&LocationActionType::InstalledOnDoorAsLock(direction.clone())
|
||||||
|
).await?.is_some() {
|
||||||
|
user_error("There's already a lock on that door - uninstall it first.".to_owned())?;
|
||||||
|
}
|
||||||
|
|
||||||
|
match check_item_capacity(&ctx.trans, &room.refstr(), LOCK_WEIGHT).await? {
|
||||||
|
CapacityLevel::OverBurdened | CapacityLevel::AboveItemLimit =>
|
||||||
|
user_error("That room has so much stuff, you can't install anything new."
|
||||||
|
.to_owned())?,
|
||||||
|
_ => {}
|
||||||
|
};
|
||||||
|
let mut what_mut = (*what).clone();
|
||||||
|
what_mut.location = room.refstr();
|
||||||
|
what_mut.action_type = LocationActionType::InstalledOnDoorAsLock(direction.clone());
|
||||||
|
what_mut.owner = room.owner.clone();
|
||||||
|
ctx.trans.save_item_model(&what_mut).await?;
|
||||||
|
|
||||||
|
broadcast_to_room(
|
||||||
|
&ctx.trans, &room.refstr(), None,
|
||||||
|
&format!("{} bangs the door to the {} as he installs {} on it.\n",
|
||||||
|
&player.display_for_sentence(true, 1, true),
|
||||||
|
&direction.describe(),
|
||||||
|
&what.display_for_sentence(true, 1, false)),
|
||||||
|
Some(
|
||||||
|
&format!("{} bangs the door to the {} as he installs {} on it.\n",
|
||||||
|
&player.display_for_sentence(false, 1, true),
|
||||||
|
&direction.describe(),
|
||||||
|
&what.display_for_sentence(false, 1, false)),
|
||||||
|
)).await?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn uninstall_cmd(&self, ctx: &mut VerbContext, player: &Item, what: &Item, room: &Item,
|
||||||
|
direction: &Direction) -> UResult<()> {
|
||||||
|
if what.action_type != LocationActionType::InstalledOnDoorAsLock(direction.clone()) {
|
||||||
|
user_error("That scanlock is not installed as a lock.".to_owned())?;
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut what_mut = (*what).clone();
|
||||||
|
|
||||||
|
let extra_text = match check_item_capacity(&ctx.trans, &player.refstr(), LOCK_WEIGHT).await? {
|
||||||
|
CapacityLevel::OverBurdened | CapacityLevel::AboveItemLimit => {
|
||||||
|
", dropping it on the floor since he can't hold it."
|
||||||
|
},
|
||||||
|
_ => {
|
||||||
|
what_mut.location = player.refstr();
|
||||||
|
""
|
||||||
|
}
|
||||||
|
};
|
||||||
|
what_mut.action_type = LocationActionType::Normal;
|
||||||
|
what_mut.owner = None;
|
||||||
|
ctx.trans.save_item_model(&what_mut).await?;
|
||||||
|
|
||||||
|
broadcast_to_room(
|
||||||
|
&ctx.trans, &room.refstr(), None,
|
||||||
|
&format!("{} bangs the door to the {} as he uninstalls {} from it{}.\n",
|
||||||
|
&player.display_for_sentence(true, 1, true),
|
||||||
|
&direction.describe(),
|
||||||
|
&what.display_for_sentence(true, 1, false),
|
||||||
|
extra_text
|
||||||
|
),
|
||||||
|
Some(
|
||||||
|
&format!("{} bangs the door to the {} as he uninstalls {} from it{}.\n",
|
||||||
|
&player.display_for_sentence(false, 1, true),
|
||||||
|
&direction.describe(),
|
||||||
|
&what.display_for_sentence(false, 1, false),
|
||||||
|
extra_text
|
||||||
|
),
|
||||||
|
)).await?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
pub fn scan() -> PossessionData {
|
pub fn scan() -> PossessionData {
|
||||||
PossessionData {
|
PossessionData {
|
||||||
display: "scanlock",
|
display: "scanlock",
|
||||||
details: "A relatively basic lock with a fingerprint scanner built into it, made to ensure only the owner of something can enter or use it.",
|
details: "A relatively basic lock with a fingerprint scanner built into it, made to ensure only the owner of something can enter or use it.",
|
||||||
aliases: vec!("lock"),
|
aliases: vec!("lock"),
|
||||||
weight: 500,
|
weight: LOCK_WEIGHT,
|
||||||
|
lockcheck_handler: Some(&ScanLockLockcheck),
|
||||||
|
install_handler: Some(&ScanLockInstall),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user