156 lines
4.6 KiB
Rust
156 lines
4.6 KiB
Rust
#[double]
|
|
use crate::db::DBTrans;
|
|
use crate::{
|
|
message_handler::user_commands::{drop::consider_expire_job_for_item, user_error, UResult},
|
|
models::item::Item,
|
|
models::{
|
|
consent::{Consent, ConsentStatus, ConsentType},
|
|
item::ItemSpecialData,
|
|
},
|
|
static_content::{
|
|
dynzone::{dynzone_by_type, DynzoneType},
|
|
npc::npc_by_code,
|
|
room::room_map_by_code,
|
|
},
|
|
DResult,
|
|
};
|
|
use mockall_double::double;
|
|
|
|
pub mod capacity;
|
|
pub mod combat;
|
|
pub mod comms;
|
|
pub mod display;
|
|
pub mod effect;
|
|
pub mod sharing;
|
|
pub mod skills;
|
|
pub mod spawn;
|
|
pub mod urges;
|
|
|
|
pub fn check_one_consent(consent: &Consent, action: &str, target: &Item) -> bool {
|
|
if let Some((loctype, loccode)) = target.location.split_once("/") {
|
|
if !consent.only_in.is_empty() {
|
|
if loctype != "room" || !consent.only_in.iter().any(|v| v == loccode) {
|
|
return false;
|
|
}
|
|
}
|
|
if !consent.allow_private && loctype != "room" {
|
|
return false;
|
|
}
|
|
} else {
|
|
if !consent.only_in.is_empty() || !consent.allow_private {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
if let Some(fight_consent) = consent.fight_consent.as_ref() {
|
|
if fight_consent.status == ConsentStatus::PendingAdd {
|
|
return false;
|
|
}
|
|
if !fight_consent.allow_pick && action == "pick" {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
true
|
|
}
|
|
|
|
pub async fn check_consent(
|
|
trans: &DBTrans,
|
|
action: &str,
|
|
consent_type: &ConsentType,
|
|
by: &Item,
|
|
target: &Item,
|
|
) -> DResult<bool> {
|
|
// Consent is only a factor on actions by players towards other players or npcs.
|
|
if by.item_type != "player" || (target.item_type != "player" && target.item_type != "npc") {
|
|
return Ok(true);
|
|
}
|
|
if target.item_type == "npc" {
|
|
return Ok(match npc_by_code().get(target.item_code.as_str()) {
|
|
None => false,
|
|
Some(npc) => npc.player_consents.contains(consent_type),
|
|
});
|
|
}
|
|
|
|
if target.item_code == by.item_code {
|
|
return Ok(true);
|
|
}
|
|
|
|
trans.delete_expired_user_consent().await?;
|
|
if let Some(consent) = trans
|
|
.find_user_consent_by_parties_type(&target.item_code, &by.item_code, consent_type)
|
|
.await?
|
|
{
|
|
if check_one_consent(&consent, action, &target) {
|
|
return Ok(true);
|
|
}
|
|
}
|
|
|
|
trans.delete_expired_corp_consent().await?;
|
|
if let Some(consent) = trans
|
|
.find_corp_consent_by_user_parties_type(&target.item_code, &by.item_code, consent_type)
|
|
.await?
|
|
{
|
|
if check_one_consent(&consent, action, &target) {
|
|
return Ok(true);
|
|
}
|
|
}
|
|
|
|
Ok(false)
|
|
}
|
|
|
|
pub async fn destroy_container(trans: &DBTrans, container: &Item) -> DResult<()> {
|
|
trans
|
|
.delete_item(&container.item_type, &container.item_code)
|
|
.await?;
|
|
|
|
for item in trans
|
|
.find_items_by_location(&container.refstr())
|
|
.await?
|
|
.into_iter()
|
|
{
|
|
let mut item_mut = (*item).clone();
|
|
// We only update this to support consider_expire_job - it gets updated in bulk
|
|
// by transfer_all_possession below.
|
|
item_mut.location = container.location.clone();
|
|
match capacity::check_item_ref_capacity(trans, &container.location, item_mut.weight).await?
|
|
{
|
|
capacity::CapacityLevel::OverBurdened | capacity::CapacityLevel::AboveItemLimit => {
|
|
trans
|
|
.delete_item(&item_mut.item_type, &item_mut.item_code)
|
|
.await?
|
|
}
|
|
_ => consider_expire_job_for_item(trans, &item_mut).await?,
|
|
}
|
|
}
|
|
trans
|
|
.transfer_all_possessions_code(&container.refstr(), &container.location)
|
|
.await?;
|
|
Ok(())
|
|
}
|
|
|
|
pub fn require_power(item: &Item) -> UResult<()> {
|
|
let result = match item.item_type.as_str() {
|
|
"room" => room_map_by_code()
|
|
.get(item.item_code.as_str())
|
|
.map(|r| r.has_power)
|
|
.unwrap_or(false),
|
|
"dynroom" => match &item.special_data {
|
|
Some(ItemSpecialData::DynroomData {
|
|
dynzone_code,
|
|
dynroom_code,
|
|
}) => DynzoneType::from_str(dynzone_code.as_str())
|
|
.and_then(|dzt| dynzone_by_type().get(&dzt))
|
|
.and_then(|dz| dz.dyn_rooms.get(dynroom_code.as_str()))
|
|
.map(|dr| dr.has_power)
|
|
.unwrap_or(false),
|
|
_ => false,
|
|
},
|
|
_ => false,
|
|
};
|
|
if !result {
|
|
user_error("That would require power, and it looks like wireless power distribution is not available here.".to_owned())?;
|
|
}
|
|
Ok(())
|
|
}
|