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

133 lines
4.5 KiB
Rust

use super::{
get_player_item_or_fail, parsing::parse_count, search_item_for_user, search_items_for_user,
user_error, UResult, UserVerb, UserVerbRef, VerbContext,
};
use crate::{
db::ItemSearchParams,
models::item::{ItemFlag, ItemSpecialData},
services::{
capacity::{check_item_capacity, check_item_ref_capacity, CapacityLevel},
comms::broadcast_to_room,
},
};
use ansi::ansi;
use async_trait::async_trait;
pub struct Verb;
#[async_trait]
impl UserVerb for Verb {
async fn handle(
self: &Self,
ctx: &mut VerbContext,
verb: &str,
remaining: &str,
) -> UResult<()> {
let reverse: bool = verb == "unload";
let sep = if reverse { "from" } else { "onto" };
let (mut item_name, npc_name) = match remaining.split_once(sep) {
None => user_error(format!(
ansi!("I couldn't understand that. Try <bold>{}<reset> item {} npc"),
verb, sep
))?,
Some(v) => v,
};
let player_item = get_player_item_or_fail(ctx).await?;
let npc = search_item_for_user(
ctx,
&ItemSearchParams {
include_loc_contents: true,
..ItemSearchParams::base(&player_item, npc_name.trim())
},
)
.await?;
if !npc.flags.contains(&ItemFlag::CanLoad) {
user_error(format!("You can't {} things {} that!", verb, sep))?
}
match npc.special_data.as_ref() {
Some(ItemSpecialData::HireData {
hired_by: Some(hired_by),
}) if hired_by == &player_item.item_code => {}
_ => user_error(format!(
"{} doesn't seem to be letting you do that. Try hiring {} first!",
npc.display_for_session(&ctx.session_dat),
npc.pronouns.object
))?,
}
let mut item_limit = Some(1);
if item_name == "all" || item_name.starts_with("all ") {
item_name = item_name[3..].trim();
item_limit = None;
} else if let (Some(n), remaining2) = parse_count(item_name) {
item_limit = Some(n);
item_name = remaining2;
}
let items = search_items_for_user(
ctx,
&ItemSearchParams {
include_contents: reverse,
include_loc_contents: !reverse,
item_type_only: Some("possession"),
limit: item_limit.unwrap_or(100),
..ItemSearchParams::base(&npc, item_name.trim())
},
)
.await?;
for item in items {
if reverse {
match check_item_ref_capacity(&ctx.trans, &player_item.location, item.weight)
.await?
{
CapacityLevel::AboveItemLimit => user_error(
"There is not enough space here to unload another item.".to_owned(),
)?,
_ => {}
}
} else {
match check_item_capacity(&ctx.trans, &npc, item.weight).await? {
CapacityLevel::AboveItemLimit | CapacityLevel::OverBurdened => {
user_error("There is not enough capacity to load that item.".to_owned())?
}
_ => {}
}
}
let mut item_mut = (*item).clone();
item_mut.location = if reverse {
npc.location.clone()
} else {
npc.refstr()
};
ctx.trans.save_item_model(&item_mut).await?;
broadcast_to_room(
&ctx.trans,
&npc.location,
None,
&format!(
"{} {}s {} {} {}\n",
&npc.display_for_sentence(true, 1, true),
verb,
&item.display_for_sentence(true, 1, false),
sep,
&npc.pronouns.intensive
),
Some(&format!(
"{} {}s {} {} {}\n",
&npc.display_for_sentence(false, 1, true),
verb,
&item.display_for_sentence(false, 1, false),
sep,
&npc.pronouns.intensive
)),
)
.await?;
}
Ok(())
}
}
static VERB_INT: Verb = Verb;
pub static VERB: UserVerbRef = &VERB_INT as UserVerbRef;