Add a fill command to fill bottles etc...
This commit is contained in:
parent
fab18d604e
commit
3023b5317a
@ -29,6 +29,7 @@ mod describe;
|
|||||||
pub mod drink;
|
pub mod drink;
|
||||||
pub mod drop;
|
pub mod drop;
|
||||||
pub mod eat;
|
pub mod eat;
|
||||||
|
pub mod fill;
|
||||||
mod fire;
|
mod fire;
|
||||||
pub mod follow;
|
pub mod follow;
|
||||||
mod gear;
|
mod gear;
|
||||||
@ -159,7 +160,7 @@ static REGISTERED_COMMANDS: UserVerbRegistry = phf_map! {
|
|||||||
"drink" => drink::VERB,
|
"drink" => drink::VERB,
|
||||||
"drop" => drop::VERB,
|
"drop" => drop::VERB,
|
||||||
"eat" => eat::VERB,
|
"eat" => eat::VERB,
|
||||||
|
"fill" => fill::VERB,
|
||||||
"fire" => fire::VERB,
|
"fire" => fire::VERB,
|
||||||
|
|
||||||
"follow" => follow::VERB,
|
"follow" => follow::VERB,
|
||||||
|
@ -4,9 +4,10 @@ use super::{
|
|||||||
};
|
};
|
||||||
use crate::{
|
use crate::{
|
||||||
regular_tasks::queued_command::{
|
regular_tasks::queued_command::{
|
||||||
queue_command, QueueCommand, QueueCommandHandler, QueuedCommandContext,
|
queue_command_and_save, QueueCommand, QueueCommandHandler, QueuedCommandContext,
|
||||||
},
|
},
|
||||||
services::{
|
services::{
|
||||||
|
capacity::recalculate_container_weight_mut,
|
||||||
comms::broadcast_to_room,
|
comms::broadcast_to_room,
|
||||||
urges::{hunger_changed, thirst_changed},
|
urges::{hunger_changed, thirst_changed},
|
||||||
},
|
},
|
||||||
@ -177,6 +178,18 @@ impl QueueCommandHandler for QueueHandler {
|
|||||||
.and_modify(|v| *v -= how_many_drunk as u64);
|
.and_modify(|v| *v -= how_many_drunk as u64);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
match item_mut.liquid_details.as_mut() {
|
||||||
|
None => {}
|
||||||
|
Some(ld) => {
|
||||||
|
ld.contents = ld
|
||||||
|
.contents
|
||||||
|
.clone()
|
||||||
|
.into_iter()
|
||||||
|
.filter(|c| c.1 != 0)
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
recalculate_container_weight_mut(&ctx.trans, &mut item_mut).await?;
|
||||||
ctx.trans.save_item_model(&item_mut).await?;
|
ctx.trans.save_item_model(&item_mut).await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -223,7 +236,6 @@ impl UserVerb for Verb {
|
|||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut player_item_mut = (*player_item).clone();
|
|
||||||
for target in targets {
|
for target in targets {
|
||||||
if target.item_type != "possession" && target.item_type != "fixed_item" {
|
if target.item_type != "possession" && target.item_type != "fixed_item" {
|
||||||
user_error("You can't drink that!".to_owned())?;
|
user_error("You can't drink that!".to_owned())?;
|
||||||
@ -231,9 +243,9 @@ impl UserVerb for Verb {
|
|||||||
if target.liquid_details.is_none() {
|
if target.liquid_details.is_none() {
|
||||||
user_error("There's nothing to drink!".to_owned())?;
|
user_error("There's nothing to drink!".to_owned())?;
|
||||||
}
|
}
|
||||||
queue_command(
|
queue_command_and_save(
|
||||||
ctx,
|
ctx,
|
||||||
&mut player_item_mut,
|
&player_item,
|
||||||
&QueueCommand::Drink {
|
&QueueCommand::Drink {
|
||||||
item_type: target.item_type.clone(),
|
item_type: target.item_type.clone(),
|
||||||
item_code: target.item_code.clone(),
|
item_code: target.item_code.clone(),
|
||||||
@ -241,7 +253,6 @@ impl UserVerb for Verb {
|
|||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
}
|
}
|
||||||
ctx.trans.save_item_model(&player_item_mut).await?;
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
341
blastmud_game/src/message_handler/user_commands/fill.rs
Normal file
341
blastmud_game/src/message_handler/user_commands/fill.rs
Normal file
@ -0,0 +1,341 @@
|
|||||||
|
use super::{
|
||||||
|
get_player_item_or_fail, search_item_for_user, user_error, ItemSearchParams, UResult, UserVerb,
|
||||||
|
UserVerbRef, VerbContext,
|
||||||
|
};
|
||||||
|
use crate::{
|
||||||
|
models::item::{Item, LiquidDetails, LiquidType},
|
||||||
|
regular_tasks::queued_command::{
|
||||||
|
queue_command_and_save, QueueCommand, QueueCommandHandler, QueuedCommandContext,
|
||||||
|
},
|
||||||
|
services::{capacity::recalculate_container_weight_mut, comms::broadcast_to_room},
|
||||||
|
};
|
||||||
|
use ansi::ansi;
|
||||||
|
use async_trait::async_trait;
|
||||||
|
use std::collections::{btree_map::Entry, BTreeMap};
|
||||||
|
use std::time;
|
||||||
|
|
||||||
|
pub struct QueueHandler;
|
||||||
|
#[async_trait]
|
||||||
|
impl QueueCommandHandler for QueueHandler {
|
||||||
|
async fn start_command(&self, ctx: &mut QueuedCommandContext<'_>) -> UResult<time::Duration> {
|
||||||
|
if ctx.item.death_data.is_some() {
|
||||||
|
user_error(
|
||||||
|
"You try to fill it, but your ghostly hands slip through it uselessly".to_owned(),
|
||||||
|
)?;
|
||||||
|
}
|
||||||
|
let (from_item_type, from_item_code, to_item_type, to_item_code) = match ctx.command {
|
||||||
|
QueueCommand::Fill {
|
||||||
|
from_item_type,
|
||||||
|
from_item_code,
|
||||||
|
to_item_type,
|
||||||
|
to_item_code,
|
||||||
|
} => (from_item_type, from_item_code, to_item_type, to_item_code),
|
||||||
|
_ => user_error("Unexpected command".to_owned())?,
|
||||||
|
};
|
||||||
|
let from_item = match ctx
|
||||||
|
.trans
|
||||||
|
.find_item_by_type_code(&from_item_type, &from_item_code)
|
||||||
|
.await?
|
||||||
|
{
|
||||||
|
None => user_error("Item not found".to_owned())?,
|
||||||
|
Some(it) => it,
|
||||||
|
};
|
||||||
|
let to_item = match ctx
|
||||||
|
.trans
|
||||||
|
.find_item_by_type_code(&to_item_type, &to_item_code)
|
||||||
|
.await?
|
||||||
|
{
|
||||||
|
None => user_error("Item not found".to_owned())?,
|
||||||
|
Some(it) => it,
|
||||||
|
};
|
||||||
|
if to_item.location != ctx.item.location && to_item.location != ctx.item.refstr() {
|
||||||
|
user_error(format!(
|
||||||
|
"You try to fill {} but realise you no longer have it",
|
||||||
|
to_item.display_for_sentence(ctx.explicit().await?, 1, false)
|
||||||
|
))?
|
||||||
|
}
|
||||||
|
if from_item.location != ctx.item.location && from_item.location != ctx.item.refstr() {
|
||||||
|
user_error(format!(
|
||||||
|
"You try to fill from {} but realise you no longer have it",
|
||||||
|
to_item.display_for_sentence(ctx.explicit().await?, 1, false)
|
||||||
|
))?
|
||||||
|
}
|
||||||
|
|
||||||
|
let msg_exp = format!(
|
||||||
|
"{} prepares to fill {} from {}\n",
|
||||||
|
&ctx.item.display_for_sentence(true, 1, true),
|
||||||
|
&to_item.display_for_sentence(true, 1, false),
|
||||||
|
&from_item.display_for_sentence(true, 1, false),
|
||||||
|
);
|
||||||
|
let msg_nonexp = format!(
|
||||||
|
"{} prepares to fill {} from {}\n",
|
||||||
|
&ctx.item.display_for_sentence(false, 1, true),
|
||||||
|
&to_item.display_for_sentence(false, 1, false),
|
||||||
|
&from_item.display_for_sentence(false, 1, false)
|
||||||
|
);
|
||||||
|
broadcast_to_room(
|
||||||
|
ctx.trans,
|
||||||
|
&ctx.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 QueuedCommandContext<'_>) -> UResult<()> {
|
||||||
|
if ctx.item.death_data.is_some() {
|
||||||
|
user_error(
|
||||||
|
"You try to fill it, but your ghostly hands slip through it uselessly".to_owned(),
|
||||||
|
)?;
|
||||||
|
}
|
||||||
|
let (from_item_type, from_item_code, to_item_type, to_item_code) = match ctx.command {
|
||||||
|
QueueCommand::Fill {
|
||||||
|
from_item_type,
|
||||||
|
from_item_code,
|
||||||
|
to_item_type,
|
||||||
|
to_item_code,
|
||||||
|
} => (from_item_type, from_item_code, to_item_type, to_item_code),
|
||||||
|
_ => user_error("Unexpected command".to_owned())?,
|
||||||
|
};
|
||||||
|
let from_item = match ctx
|
||||||
|
.trans
|
||||||
|
.find_item_by_type_code(&from_item_type, &from_item_code)
|
||||||
|
.await?
|
||||||
|
{
|
||||||
|
None => user_error("Item not found".to_owned())?,
|
||||||
|
Some(it) => it,
|
||||||
|
};
|
||||||
|
let to_item = match ctx
|
||||||
|
.trans
|
||||||
|
.find_item_by_type_code(&to_item_type, &to_item_code)
|
||||||
|
.await?
|
||||||
|
{
|
||||||
|
None => user_error("Item not found".to_owned())?,
|
||||||
|
Some(it) => it,
|
||||||
|
};
|
||||||
|
if to_item.location != ctx.item.location && to_item.location != ctx.item.refstr() {
|
||||||
|
user_error(format!(
|
||||||
|
"You try to fill {} but realise you no longer have it",
|
||||||
|
to_item.display_for_sentence(ctx.explicit().await?, 1, false)
|
||||||
|
))?
|
||||||
|
}
|
||||||
|
if from_item.location != ctx.item.location && from_item.location != ctx.item.refstr() {
|
||||||
|
user_error(format!(
|
||||||
|
"You try to fill from {} but realise you no longer have it",
|
||||||
|
to_item.display_for_sentence(ctx.explicit().await?, 1, false)
|
||||||
|
))?
|
||||||
|
}
|
||||||
|
|
||||||
|
let from_liquid_details = match from_item.liquid_details.as_ref() {
|
||||||
|
None => user_error(format!(
|
||||||
|
"{} appears to be empty.",
|
||||||
|
from_item.display_for_sentence(ctx.explicit().await?, 1, true)
|
||||||
|
))?,
|
||||||
|
Some(v) => v,
|
||||||
|
};
|
||||||
|
|
||||||
|
let available_vol = from_liquid_details
|
||||||
|
.contents
|
||||||
|
.iter()
|
||||||
|
.map(|r| r.1.clone())
|
||||||
|
.sum::<u64>();
|
||||||
|
if available_vol == 0 {
|
||||||
|
user_error(format!(
|
||||||
|
"{} appears to be empty.",
|
||||||
|
from_item.display_for_sentence(ctx.explicit().await?, 1, true)
|
||||||
|
))?
|
||||||
|
}
|
||||||
|
|
||||||
|
let into_liqdata = match to_item
|
||||||
|
.static_data()
|
||||||
|
.and_then(|pd| pd.liquid_container_data.as_ref())
|
||||||
|
{
|
||||||
|
None => user_error(format!(
|
||||||
|
"You can't find a way to fill {}.",
|
||||||
|
to_item.display_for_sentence(ctx.explicit().await?, 1, false)
|
||||||
|
))?,
|
||||||
|
Some(v) => v,
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Some(allowed) = &into_liqdata.allowed_contents {
|
||||||
|
for (liq_type, _) in &from_liquid_details.contents {
|
||||||
|
if !allowed.contains(&liq_type) {
|
||||||
|
user_error(format!(
|
||||||
|
"You don't think putting {} into {} is a good idea.",
|
||||||
|
liq_type.display(),
|
||||||
|
to_item.display_for_sentence(ctx.explicit().await?, 1, false)
|
||||||
|
))?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let capacity_remaining = into_liqdata.capacity
|
||||||
|
- to_item
|
||||||
|
.liquid_details
|
||||||
|
.as_ref()
|
||||||
|
.map(|ld| ld.contents.iter().map(|c| c.1.clone()).sum::<u64>())
|
||||||
|
.unwrap_or(0);
|
||||||
|
let actually_transferred = available_vol.min(capacity_remaining);
|
||||||
|
|
||||||
|
if actually_transferred == 0 {
|
||||||
|
user_error(format!(
|
||||||
|
"You don't think you can get any more into {}.",
|
||||||
|
to_item.display_for_sentence(ctx.explicit().await?, 1, false)
|
||||||
|
))?;
|
||||||
|
}
|
||||||
|
|
||||||
|
let transfer_frac = (actually_transferred as f64) / (available_vol as f64);
|
||||||
|
let mut remaining_total = actually_transferred;
|
||||||
|
let transfer_volumes: BTreeMap<LiquidType, u64> = from_liquid_details
|
||||||
|
.contents
|
||||||
|
.iter()
|
||||||
|
.flat_map(|(liqtype, vol)| {
|
||||||
|
let move_vol = (((*vol as f64) * transfer_frac).ceil() as u64).min(remaining_total);
|
||||||
|
remaining_total -= move_vol;
|
||||||
|
if move_vol > 0 {
|
||||||
|
Some((liqtype.clone(), move_vol))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
let mut to_item_mut: Item = (*to_item).clone();
|
||||||
|
match to_item_mut.liquid_details.as_mut() {
|
||||||
|
None => {
|
||||||
|
to_item_mut.liquid_details = Some(LiquidDetails {
|
||||||
|
contents: transfer_volumes.clone(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
Some(ld) => {
|
||||||
|
for (liq, vol) in &transfer_volumes {
|
||||||
|
ld.contents
|
||||||
|
.entry(liq.clone())
|
||||||
|
.and_modify(|v| {
|
||||||
|
*v += *vol;
|
||||||
|
})
|
||||||
|
.or_insert(vol.clone());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let mut from_item_mut: Item = (*from_item).clone();
|
||||||
|
if let Some(ld) = from_item_mut.liquid_details.as_mut() {
|
||||||
|
for (liq, vol) in &transfer_volumes {
|
||||||
|
match ld.contents.entry(liq.clone()) {
|
||||||
|
Entry::Vacant(_) => {}
|
||||||
|
Entry::Occupied(mut ent) => {
|
||||||
|
if ent.get() <= vol {
|
||||||
|
ent.remove();
|
||||||
|
} else {
|
||||||
|
*(ent.get_mut()) -= *vol;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
recalculate_container_weight_mut(&ctx.trans, &mut from_item_mut).await?;
|
||||||
|
recalculate_container_weight_mut(&ctx.trans, &mut to_item_mut).await?;
|
||||||
|
ctx.trans.save_item_model(&from_item_mut).await?;
|
||||||
|
ctx.trans.save_item_model(&to_item_mut).await?;
|
||||||
|
|
||||||
|
let msg_exp = format!(
|
||||||
|
"{} fills {} from {}\n",
|
||||||
|
&ctx.item.display_for_sentence(true, 1, true),
|
||||||
|
&to_item.display_for_sentence(true, 1, false),
|
||||||
|
&from_item.display_for_sentence(true, 1, false),
|
||||||
|
);
|
||||||
|
let msg_nonexp = format!(
|
||||||
|
"{} fills {} from {}\n",
|
||||||
|
&ctx.item.display_for_sentence(false, 1, true),
|
||||||
|
&to_item.display_for_sentence(false, 1, false),
|
||||||
|
&from_item.display_for_sentence(false, 1, false)
|
||||||
|
);
|
||||||
|
broadcast_to_room(
|
||||||
|
ctx.trans,
|
||||||
|
&ctx.item.location,
|
||||||
|
None,
|
||||||
|
&msg_exp,
|
||||||
|
Some(&msg_nonexp),
|
||||||
|
)
|
||||||
|
.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 (to_str, from_str) = match remaining.split_once(" from ") {
|
||||||
|
None => user_error(
|
||||||
|
ansi!("Try <bold>fill<reset> container <bold>from<reset> container.").to_owned(),
|
||||||
|
)?,
|
||||||
|
Some((to_str, from_str)) => (to_str.trim(), from_str.trim()),
|
||||||
|
};
|
||||||
|
|
||||||
|
let to_target = search_item_for_user(
|
||||||
|
ctx,
|
||||||
|
&ItemSearchParams {
|
||||||
|
include_contents: true,
|
||||||
|
include_loc_contents: true,
|
||||||
|
..ItemSearchParams::base(&player_item, to_str)
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
let from_target = search_item_for_user(
|
||||||
|
ctx,
|
||||||
|
&ItemSearchParams {
|
||||||
|
include_contents: true,
|
||||||
|
include_loc_contents: true,
|
||||||
|
..ItemSearchParams::base(&player_item, from_str)
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
if player_item.death_data.is_some() {
|
||||||
|
user_error(
|
||||||
|
"You try to fill it, but your ghostly hands slip through it uselessly".to_owned(),
|
||||||
|
)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
if from_target.item_type != "possession" && from_target.item_type != "fixed_item" {
|
||||||
|
user_error("You can't fill from that!".to_owned())?;
|
||||||
|
}
|
||||||
|
if to_target.item_type != "possession" && to_target.item_type != "fixed_item" {
|
||||||
|
user_error("You can't fill that!".to_owned())?;
|
||||||
|
}
|
||||||
|
if to_target.item_type == from_target.item_type
|
||||||
|
&& to_target.item_code == from_target.item_code
|
||||||
|
{
|
||||||
|
user_error(
|
||||||
|
"You can't figure out how to fill something from itself - a shame!".to_owned(),
|
||||||
|
)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
queue_command_and_save(
|
||||||
|
ctx,
|
||||||
|
&player_item,
|
||||||
|
&QueueCommand::Fill {
|
||||||
|
from_item_type: from_target.item_type.clone(),
|
||||||
|
from_item_code: from_target.item_code.clone(),
|
||||||
|
to_item_type: to_target.item_type.clone(),
|
||||||
|
to_item_code: to_target.item_code.clone(),
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
static VERB_INT: Verb = Verb;
|
||||||
|
pub static VERB: UserVerbRef = &VERB_INT as UserVerbRef;
|
@ -172,6 +172,11 @@ impl LiquidType {
|
|||||||
LiquidType::Water => "water",
|
LiquidType::Water => "water",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
pub fn density(&self) -> f64 {
|
||||||
|
match self {
|
||||||
|
LiquidType::Water => 1.0, // g / mL.
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq, Ord, PartialOrd)]
|
#[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq, Ord, PartialOrd)]
|
||||||
|
@ -2,7 +2,7 @@ use super::{TaskHandler, TaskRunContext};
|
|||||||
#[double]
|
#[double]
|
||||||
use crate::db::DBTrans;
|
use crate::db::DBTrans;
|
||||||
use crate::message_handler::user_commands::{
|
use crate::message_handler::user_commands::{
|
||||||
close, cut, drink, drop, eat, get, improvise, make, movement, open, put, remove, use_cmd,
|
close, cut, drink, drop, eat, fill, get, improvise, make, movement, open, put, remove, use_cmd,
|
||||||
user_error, wear, wield, CommandHandlingError, UResult, VerbContext,
|
user_error, wear, wield, CommandHandlingError, UResult, VerbContext,
|
||||||
};
|
};
|
||||||
use crate::message_handler::ListenerSession;
|
use crate::message_handler::ListenerSession;
|
||||||
@ -57,6 +57,12 @@ pub enum QueueCommand {
|
|||||||
from_corpse: String,
|
from_corpse: String,
|
||||||
what_part: String,
|
what_part: String,
|
||||||
},
|
},
|
||||||
|
Fill {
|
||||||
|
from_item_type: String,
|
||||||
|
from_item_code: String,
|
||||||
|
to_item_type: String,
|
||||||
|
to_item_code: String,
|
||||||
|
},
|
||||||
Drink {
|
Drink {
|
||||||
item_type: String,
|
item_type: String,
|
||||||
item_code: String,
|
item_code: String,
|
||||||
@ -121,6 +127,7 @@ impl QueueCommand {
|
|||||||
Drink { .. } => "Drink",
|
Drink { .. } => "Drink",
|
||||||
Drop { .. } => "Drop",
|
Drop { .. } => "Drop",
|
||||||
Eat { .. } => "Eat",
|
Eat { .. } => "Eat",
|
||||||
|
Fill { .. } => "Fill",
|
||||||
Get { .. } => "Get",
|
Get { .. } => "Get",
|
||||||
GetFromContainer { .. } => "GetFromContainer",
|
GetFromContainer { .. } => "GetFromContainer",
|
||||||
Make { .. } => "Make",
|
Make { .. } => "Make",
|
||||||
@ -204,6 +211,10 @@ fn queue_command_registry(
|
|||||||
"Eat",
|
"Eat",
|
||||||
&eat::QueueHandler as &(dyn QueueCommandHandler + Sync + Send),
|
&eat::QueueHandler as &(dyn QueueCommandHandler + Sync + Send),
|
||||||
),
|
),
|
||||||
|
(
|
||||||
|
"Fill",
|
||||||
|
&fill::QueueHandler as &(dyn QueueCommandHandler + Sync + Send),
|
||||||
|
),
|
||||||
(
|
(
|
||||||
"Make",
|
"Make",
|
||||||
&make::QueueHandler as &(dyn QueueCommandHandler + Sync + Send),
|
&make::QueueHandler as &(dyn QueueCommandHandler + Sync + Send),
|
||||||
|
@ -65,7 +65,19 @@ pub async fn check_item_capacity(
|
|||||||
Ok(CapacityLevel::Unburdened)
|
Ok(CapacityLevel::Unburdened)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn recalculate_container_weight(trans: &DBTrans, container: &Item) -> DResult<()> {
|
pub async fn recalculate_container_weight_mut(
|
||||||
|
trans: &DBTrans,
|
||||||
|
container: &mut Item,
|
||||||
|
) -> DResult<bool> {
|
||||||
|
let liq_weight = match container.liquid_details.as_ref() {
|
||||||
|
None => 0,
|
||||||
|
Some(ld) => ld
|
||||||
|
.contents
|
||||||
|
.iter()
|
||||||
|
.map(|(liq, vol)| (liq.density() * (*vol as f64)).ceil() as u64)
|
||||||
|
.sum(),
|
||||||
|
};
|
||||||
|
|
||||||
if let Some(container_data) = container.possession_type.as_ref().and_then(|pt| {
|
if let Some(container_data) = container.possession_type.as_ref().and_then(|pt| {
|
||||||
possession_data()
|
possession_data()
|
||||||
.get(pt)
|
.get(pt)
|
||||||
@ -73,12 +85,39 @@ pub async fn recalculate_container_weight(trans: &DBTrans, container: &Item) ->
|
|||||||
}) {
|
}) {
|
||||||
let stats = trans.get_location_stats(&container.refstr()).await?;
|
let stats = trans.get_location_stats(&container.refstr()).await?;
|
||||||
let new_weight = container_data.base_weight
|
let new_weight = container_data.base_weight
|
||||||
+ (((stats.total_weight as f64) * container_data.compression_ratio).ceil() as u64);
|
+ (((stats.total_weight as f64) * container_data.compression_ratio).ceil() as u64)
|
||||||
|
+ liq_weight;
|
||||||
if new_weight != container.weight {
|
if new_weight != container.weight {
|
||||||
let mut container_mut = container.clone();
|
container.weight = new_weight;
|
||||||
container_mut.weight = new_weight;
|
Ok(true)
|
||||||
trans.save_item_model(&container_mut).await?;
|
} else {
|
||||||
|
Ok(false)
|
||||||
}
|
}
|
||||||
|
} else if liq_weight > 0 {
|
||||||
|
if let Some(pd) = container
|
||||||
|
.possession_type
|
||||||
|
.as_ref()
|
||||||
|
.and_then(|pt| possession_data().get(pt))
|
||||||
|
{
|
||||||
|
let new_weight = liq_weight + pd.weight;
|
||||||
|
if new_weight != container.weight {
|
||||||
|
container.weight = new_weight;
|
||||||
|
Ok(true)
|
||||||
|
} else {
|
||||||
|
Ok(false)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Ok(false)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Ok(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn recalculate_container_weight(trans: &DBTrans, container: &Item) -> DResult<()> {
|
||||||
|
let mut container_mut = (*container).clone();
|
||||||
|
if recalculate_container_weight_mut(trans, &mut container_mut).await? {
|
||||||
|
trans.save_item_model(&container_mut).await?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -18,6 +18,7 @@ mod bags;
|
|||||||
mod benches;
|
mod benches;
|
||||||
mod blade;
|
mod blade;
|
||||||
mod books;
|
mod books;
|
||||||
|
mod bottles;
|
||||||
mod corp_licence;
|
mod corp_licence;
|
||||||
mod fangs;
|
mod fangs;
|
||||||
pub mod head_armour;
|
pub mod head_armour;
|
||||||
@ -405,6 +406,8 @@ pub enum PossessionType {
|
|||||||
CertificateOfIncorporation,
|
CertificateOfIncorporation,
|
||||||
// Storage
|
// Storage
|
||||||
DuffelBag,
|
DuffelBag,
|
||||||
|
// Fluid containers
|
||||||
|
DrinkBottle,
|
||||||
// Security
|
// Security
|
||||||
Scanlock,
|
Scanlock,
|
||||||
// Food
|
// Food
|
||||||
@ -492,6 +495,7 @@ pub fn possession_data() -> &'static BTreeMap<PossessionType, &'static Possessio
|
|||||||
.chain(bags::data().iter().map(|v| ((*v).0.clone(), &(*v).1)))
|
.chain(bags::data().iter().map(|v| ((*v).0.clone(), &(*v).1)))
|
||||||
.chain(benches::data().iter().map(|v| ((*v).0.clone(), &(*v).1)))
|
.chain(benches::data().iter().map(|v| ((*v).0.clone(), &(*v).1)))
|
||||||
.chain(blade::data().iter().map(|v| ((*v).0.clone(), &(*v).1)))
|
.chain(blade::data().iter().map(|v| ((*v).0.clone(), &(*v).1)))
|
||||||
|
.chain(bottles::data().iter().map(|v| ((*v).0.clone(), &(*v).1)))
|
||||||
.chain(trauma_kit::data().iter().map(|v| ((*v).0.clone(), &(*v).1)))
|
.chain(trauma_kit::data().iter().map(|v| ((*v).0.clone(), &(*v).1)))
|
||||||
.chain(
|
.chain(
|
||||||
corp_licence::data()
|
corp_licence::data()
|
||||||
|
26
blastmud_game/src/static_content/possession_type/bottles.rs
Normal file
26
blastmud_game/src/static_content/possession_type/bottles.rs
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
use super::{PossessionData, PossessionType};
|
||||||
|
use crate::static_content::possession_type::LiquidContainerData;
|
||||||
|
use once_cell::sync::OnceCell;
|
||||||
|
|
||||||
|
pub fn data() -> &'static Vec<(PossessionType, PossessionData)> {
|
||||||
|
static D: OnceCell<Vec<(PossessionType, PossessionData)>> = OnceCell::new();
|
||||||
|
&D.get_or_init(|| {
|
||||||
|
vec![(
|
||||||
|
PossessionType::DrinkBottle,
|
||||||
|
PossessionData {
|
||||||
|
display: "drink bottle",
|
||||||
|
aliases: vec!["bottle", "flask", "canteen"],
|
||||||
|
details: "A stainless steel bottle, dinged up a bit with dents \
|
||||||
|
and scruff marks from use, but still looking perfectly \
|
||||||
|
usable for whatever fluid you might want it to hold. It \
|
||||||
|
seems to be the right size to hold about 1L.",
|
||||||
|
weight: 100,
|
||||||
|
liquid_container_data: Some(LiquidContainerData {
|
||||||
|
capacity: 1000,
|
||||||
|
..Default::default()
|
||||||
|
}),
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
)]
|
||||||
|
})
|
||||||
|
}
|
@ -2555,6 +2555,11 @@ pub fn room_list() -> Vec<Room> {
|
|||||||
list_price: 250,
|
list_price: 250,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
|
RoomStock {
|
||||||
|
possession_type: PossessionType::DrinkBottle,
|
||||||
|
list_price: 80,
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
),
|
),
|
||||||
should_caption: true,
|
should_caption: true,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
|
Loading…
Reference in New Issue
Block a user