blastmud/blastmud_game/src/message_handler/user_commands/drop.rs

134 lines
5.6 KiB
Rust
Raw Normal View History

use super::{
VerbContext,
UserVerb,
UserVerbRef,
UResult,
ItemSearchParams,
user_error,
get_player_item_or_fail,
search_item_for_user,
};
use crate::{
static_content::possession_type::possession_data,
regular_tasks::queued_command::{
QueueCommandHandler,
QueueCommand,
queue_command
},
services::{
broadcast_to_room,
capacity::{
check_item_capacity,
CapacityLevel,
}
},
models::item::LocationActionType,
};
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<time::Duration> {
let player_item = get_player_item_or_fail(ctx).await?;
if player_item.is_dead {
user_error("You try to drop it, but your ghostly hands slip through it uselessly".to_owned())?;
}
let item_id = match command {
QueueCommand::Drop { possession_id } => possession_id,
_ => user_error("Unexpected command".to_owned())?
};
let item = match ctx.trans.find_item_by_type_code("possession", &item_id).await? {
None => user_error("Item not found".to_owned())?,
Some(it) => it
};
if item.location != format!("{}/{}", &player_item.item_type, &player_item.item_code) {
user_error(
format!("You try to drop {} but realise you no longer have it",
item.display_for_sentence(!ctx.session_dat.less_explicit_mode, 1, false)
)
)?
}
let msg_exp = format!("{} prepares to drop {}\n",
&player_item.display_for_sentence(true, 1, true),
&item.display_for_sentence(true, 1, false));
let msg_nonexp = format!("{} prepares to drop {}\n",
&player_item.display_for_sentence(false, 1, true),
&item.display_for_sentence(false, 1, false));
broadcast_to_room(ctx.trans, &player_item.location, None, &msg_exp, Some(&msg_nonexp)).await?;
Ok(time::Duration::from_secs(1))
}
#[allow(unreachable_patterns)]
async fn finish_command(&self, ctx: &mut VerbContext<'_>, command: &QueueCommand)
-> UResult<()> {
let player_item = get_player_item_or_fail(ctx).await?;
if player_item.is_dead {
user_error("You try to get it, but your ghostly hands slip through it uselessly".to_owned())?;
}
let item_id = match command {
QueueCommand::Drop { possession_id } => possession_id,
_ => user_error("Unexpected command".to_owned())?
};
let item = match ctx.trans.find_item_by_type_code("possession", &item_id).await? {
None => user_error("Item not found".to_owned())?,
Some(it) => it
};
if item.location != format!("{}/{}", &player_item.item_type, &player_item.item_code) {
user_error(format!("You try to drop {} but realise you no longer have it!",
&item.display_for_sentence(!ctx.session_dat.less_explicit_mode, 1, false)))?
}
let possession_data = match item.possession_type.as_ref().and_then(|pt| possession_data().get(&pt)) {
None => user_error("That item no longer exists in the game so can't be handled".to_owned())?,
Some(pd) => pd
};
match check_item_capacity(ctx.trans, &player_item.location, possession_data.weight).await? {
CapacityLevel::AboveItemLimit => user_error(
format!("You can't drop {}, because it is so cluttered here there is no where to put it!",
&item.display_for_sentence(!ctx.session_dat.less_explicit_mode, 1, false)
),
)?,
_ => ()
}
let msg_exp = format!("{} drops {}\n",
&player_item.display_for_sentence(true, 1, true),
&item.display_for_sentence(true, 1, false));
let msg_nonexp = format!("{} drops {}\n",
&player_item.display_for_sentence(false, 1, true),
&item.display_for_sentence(false, 1, false));
broadcast_to_room(ctx.trans, &player_item.location, None, &msg_exp, Some(&msg_nonexp)).await?;
let mut item_mut = (*item).clone();
item_mut.location = player_item.location.clone();
item_mut.action_type = LocationActionType::Normal;
ctx.trans.save_item_model(&item_mut).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 player_item = get_player_item_or_fail(ctx).await?;
let target = search_item_for_user(ctx, &ItemSearchParams {
include_contents: true,
..ItemSearchParams::base(&player_item, &remaining)
}).await?;
if player_item.is_dead {
user_error("You try to drop it, but your ghostly hands slip through it uselessly".to_owned())?;
}
if target.item_type != "possession" {
user_error("You can't drop that!".to_owned())?;
}
queue_command(ctx, &QueueCommand::Drop { possession_id: target.item_code.clone() }).await?;
Ok(())
}
}
static VERB_INT: Verb = Verb;
pub static VERB: UserVerbRef = &VERB_INT as UserVerbRef;