Add drop command, and show inventory on look.
This commit is contained in:
parent
25cfda033b
commit
d5314c981e
@ -14,6 +14,7 @@ use std::sync::Arc;
|
||||
mod agree;
|
||||
pub mod attack;
|
||||
mod buy;
|
||||
pub mod drop;
|
||||
pub mod get;
|
||||
mod describe;
|
||||
mod help;
|
||||
@ -107,6 +108,7 @@ static REGISTERED_COMMANDS: UserVerbRegistry = phf_map! {
|
||||
// Other commands (alphabetical except aliases grouped):
|
||||
"attack" => attack::VERB,
|
||||
"buy" => buy::VERB,
|
||||
"drop" => drop::VERB,
|
||||
"get" => get::VERB,
|
||||
"inventory" => inventory::VERB,
|
||||
"inv" => inventory::VERB,
|
||||
|
133
blastmud_game/src/message_handler/user_commands/drop.rs
Normal file
133
blastmud_game/src/message_handler/user_commands/drop.rs
Normal file
@ -0,0 +1,133 @@
|
||||
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;
|
@ -2,9 +2,12 @@ use super::{VerbContext, UserVerb, UserVerbRef, UResult, UserError, user_error,
|
||||
get_player_item_or_fail, search_item_for_user};
|
||||
use async_trait::async_trait;
|
||||
use ansi::{ansi, flow_around, word_wrap};
|
||||
use crate::db::ItemSearchParams;
|
||||
use crate::models::{item::{Item, LocationActionType, Subattack, ItemFlag}};
|
||||
use crate::static_content::room::{self, Direction};
|
||||
use crate::{
|
||||
db::ItemSearchParams,
|
||||
models::{item::{Item, LocationActionType, Subattack, ItemFlag}},
|
||||
static_content::room::{self, Direction},
|
||||
language,
|
||||
};
|
||||
use itertools::Itertools;
|
||||
use std::sync::Arc;
|
||||
|
||||
@ -39,11 +42,45 @@ pub fn render_map(room: &room::Room, width: usize, height: usize) -> String {
|
||||
}
|
||||
|
||||
pub async fn describe_normal_item(ctx: &VerbContext<'_>, item: &Item) -> UResult<()> {
|
||||
let mut contents_desc = String::new();
|
||||
|
||||
let mut items = ctx.trans.find_items_by_location(&format!("{}/{}",
|
||||
item.item_type, item.item_code)).await?;
|
||||
items.sort_unstable_by(|it1, it2| (&it1.display).cmp(&it2.display));
|
||||
|
||||
let all_groups: Vec<Vec<&Arc<Item>>> = items
|
||||
.iter()
|
||||
.group_by(|i| i.display_for_sentence(true, 1, false))
|
||||
.into_iter()
|
||||
.map(|(_, g)|g.collect::<Vec<&Arc<Item>>>())
|
||||
.collect::<Vec<Vec<&Arc<Item>>>>();
|
||||
|
||||
if all_groups.len() > 0 {
|
||||
contents_desc.push_str(&(language::caps_first(&item.pronouns.subject)));
|
||||
if item.item_type == "player" || item.item_type == "npc" {
|
||||
contents_desc.push_str("'s carrying ");
|
||||
} else {
|
||||
contents_desc.push_str(" contains ");
|
||||
}
|
||||
let mut phrases = Vec::<String>::new();
|
||||
for group_items in all_groups {
|
||||
let head = &group_items[0];
|
||||
let mut details = head.display_for_sentence(!ctx.session_dat.less_explicit_mode,
|
||||
group_items.len(), false);
|
||||
if head.action_type == LocationActionType::Wielded {
|
||||
details.push_str(" (wielded)");
|
||||
}
|
||||
phrases.push(details);
|
||||
}
|
||||
let phrases_str: Vec<&str> = phrases.iter().map(|p| p.as_str()).collect();
|
||||
contents_desc.push_str(&(language::join_words(&phrases_str) + ".\n"));
|
||||
}
|
||||
ctx.trans.queue_for_session(
|
||||
ctx.session,
|
||||
Some(&format!("{}\n{}\n",
|
||||
Some(&format!("{}\n{}\n{}",
|
||||
&item.display_for_session(&ctx.session_dat),
|
||||
item.details_for_session(&ctx.session_dat).unwrap_or("")
|
||||
item.details_for_session(&ctx.session_dat).unwrap_or(""),
|
||||
contents_desc,
|
||||
))
|
||||
).await?;
|
||||
Ok(())
|
||||
@ -73,7 +110,7 @@ pub async fn describe_room(ctx: &VerbContext<'_>, item: &Item,
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn list_item_contents<'l>(ctx: &'l VerbContext<'_>, item: &'l Item) -> UResult<String> {
|
||||
async fn list_room_contents<'l>(ctx: &'l VerbContext<'_>, item: &'l Item) -> UResult<String> {
|
||||
if item.flags.contains(&ItemFlag::NoSeeContents) {
|
||||
return Ok(" It is too foggy to see who or what else is here.".to_owned());
|
||||
}
|
||||
@ -192,7 +229,7 @@ impl UserVerb for Verb {
|
||||
let room =
|
||||
room::room_map_by_code().get(item.item_code.as_str())
|
||||
.ok_or_else(|| UserError("Sorry, that room no longer exists".to_owned()))?;
|
||||
describe_room(ctx, &item, &room, &list_item_contents(ctx, &item).await?).await?;
|
||||
describe_room(ctx, &item, &room, &list_room_contents(ctx, &item).await?).await?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
@ -14,9 +14,10 @@ use crate::message_handler::user_commands::{
|
||||
VerbContext,
|
||||
CommandHandlingError,
|
||||
UResult,
|
||||
get,
|
||||
drop,
|
||||
movement,
|
||||
wield,
|
||||
get,
|
||||
user_error,
|
||||
get_user_or_fail
|
||||
};
|
||||
@ -28,6 +29,7 @@ pub enum QueueCommand {
|
||||
Movement { direction: Direction },
|
||||
Wield { possession_id: String },
|
||||
Get { possession_id: String },
|
||||
Drop { possession_id: String },
|
||||
}
|
||||
impl QueueCommand {
|
||||
pub fn name(&self) -> &'static str {
|
||||
@ -36,6 +38,7 @@ impl QueueCommand {
|
||||
Movement {..} => "Movement",
|
||||
Wield {..} => "Wield",
|
||||
Get {..} => "Get",
|
||||
Drop {..} => "Drop",
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -50,9 +53,10 @@ fn queue_command_registry() -> &'static BTreeMap<&'static str, &'static (dyn Que
|
||||
static REGISTRY: OnceCell<BTreeMap<&'static str, &'static (dyn QueueCommandHandler + Sync + Send)>> =
|
||||
OnceCell::new();
|
||||
REGISTRY.get_or_init(|| vec!(
|
||||
("Drop", &drop::QueueHandler as &(dyn QueueCommandHandler + Sync + Send)),
|
||||
("Get", &get::QueueHandler as &(dyn QueueCommandHandler + Sync + Send)),
|
||||
("Movement", &movement::QueueHandler as &(dyn QueueCommandHandler + Sync + Send)),
|
||||
("Wield", &wield::QueueHandler as &(dyn QueueCommandHandler + Sync + Send)),
|
||||
("Get", &get::QueueHandler as &(dyn QueueCommandHandler + Sync + Send)),
|
||||
).into_iter().collect())
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user