forked from blasthavers/blastmud
Possessions eventually expire if dropped in a public place.
This commit is contained in:
parent
8085689490
commit
863ba692f4
@ -11,10 +11,14 @@ use super::{
|
|||||||
};
|
};
|
||||||
use crate::{
|
use crate::{
|
||||||
static_content::possession_type::possession_data,
|
static_content::possession_type::possession_data,
|
||||||
regular_tasks::queued_command::{
|
regular_tasks::{
|
||||||
QueueCommandHandler,
|
queued_command::{
|
||||||
QueueCommand,
|
QueueCommandHandler,
|
||||||
queue_command
|
QueueCommand,
|
||||||
|
queue_command
|
||||||
|
},
|
||||||
|
TaskHandler,
|
||||||
|
TaskRunContext,
|
||||||
},
|
},
|
||||||
services::{
|
services::{
|
||||||
broadcast_to_room,
|
broadcast_to_room,
|
||||||
@ -23,10 +27,91 @@ use crate::{
|
|||||||
CapacityLevel,
|
CapacityLevel,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
models::item::LocationActionType,
|
DResult,
|
||||||
|
models::{
|
||||||
|
item::{LocationActionType, Item, ItemFlag},
|
||||||
|
task::{Task, TaskMeta, TaskDetails},
|
||||||
|
},
|
||||||
};
|
};
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use std::time;
|
use std::time;
|
||||||
|
use chrono::Utc;
|
||||||
|
use mockall_double::double;
|
||||||
|
#[double] use crate::db::DBTrans;
|
||||||
|
|
||||||
|
pub struct ExpireItemTaskHandler;
|
||||||
|
#[async_trait]
|
||||||
|
impl TaskHandler for ExpireItemTaskHandler {
|
||||||
|
async fn do_task(&self, ctx: &mut TaskRunContext) -> DResult<Option<time::Duration>> {
|
||||||
|
let item_code = match &mut ctx.task.details {
|
||||||
|
TaskDetails::ExpireItem { item_code } => item_code,
|
||||||
|
_ => Err("Expected ExpireItem type")?
|
||||||
|
};
|
||||||
|
let item = match ctx.trans.find_item_by_type_code("possession", item_code).await? {
|
||||||
|
None => {
|
||||||
|
return Ok(None);
|
||||||
|
}
|
||||||
|
Some(it) => it
|
||||||
|
};
|
||||||
|
let (loc_type, loc_code) = match item.location.split_once("/") {
|
||||||
|
None => return Ok(None),
|
||||||
|
Some(p) => p
|
||||||
|
};
|
||||||
|
|
||||||
|
if loc_type != "room" {
|
||||||
|
return Ok(None);
|
||||||
|
}
|
||||||
|
|
||||||
|
let loc_item = match ctx.trans.find_item_by_type_code(loc_type, loc_code).await? {
|
||||||
|
None => return Ok(None),
|
||||||
|
Some(i) => i
|
||||||
|
};
|
||||||
|
|
||||||
|
if loc_item.flags.contains(&ItemFlag::DroppedItemsDontExpire) {
|
||||||
|
return Ok(None);
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.trans.delete_item("possession", item_code).await?;
|
||||||
|
|
||||||
|
Ok(None)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub static EXPIRE_ITEM_HANDLER: &'static (dyn TaskHandler + Sync + Send) = &ExpireItemTaskHandler;
|
||||||
|
|
||||||
|
pub async fn consider_expire_job_for_item(trans: &DBTrans, item: &Item) -> DResult<()> {
|
||||||
|
let (loc_type, loc_code) = match item.location.split_once("/") {
|
||||||
|
None => return Ok(()),
|
||||||
|
Some(p) => p
|
||||||
|
};
|
||||||
|
|
||||||
|
if loc_type != "room" {
|
||||||
|
return Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
let loc_item = match trans.find_item_by_type_code(loc_type, loc_code).await? {
|
||||||
|
None => return Ok(()),
|
||||||
|
Some(i) => i
|
||||||
|
};
|
||||||
|
|
||||||
|
if loc_item.flags.contains(&ItemFlag::DroppedItemsDontExpire) {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
trans.upsert_task(
|
||||||
|
&Task {
|
||||||
|
meta: TaskMeta {
|
||||||
|
task_code: format!("{}/{}", item.item_type, item.item_code),
|
||||||
|
next_scheduled: Utc::now() + chrono::Duration::hours(1),
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
details: TaskDetails::ExpireItem {
|
||||||
|
item_code: item.item_code.clone()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
).await?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
pub struct QueueHandler;
|
pub struct QueueHandler;
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
@ -106,6 +191,7 @@ impl QueueCommandHandler for QueueHandler {
|
|||||||
broadcast_to_room(ctx.trans, &player_item.location, None, &msg_exp, Some(&msg_nonexp)).await?;
|
broadcast_to_room(ctx.trans, &player_item.location, None, &msg_exp, Some(&msg_nonexp)).await?;
|
||||||
let mut item_mut = (*item).clone();
|
let mut item_mut = (*item).clone();
|
||||||
item_mut.location = player_item.location.clone();
|
item_mut.location = player_item.location.clone();
|
||||||
|
consider_expire_job_for_item(ctx.trans, &item_mut).await?;
|
||||||
item_mut.action_type = LocationActionType::Normal;
|
item_mut.action_type = LocationActionType::Normal;
|
||||||
ctx.trans.save_item_model(&item_mut).await?;
|
ctx.trans.save_item_model(&item_mut).await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -255,7 +255,8 @@ pub enum Sex {
|
|||||||
#[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq, Ord, PartialOrd)]
|
#[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq, Ord, PartialOrd)]
|
||||||
pub enum ItemFlag {
|
pub enum ItemFlag {
|
||||||
NoSay,
|
NoSay,
|
||||||
NoSeeContents
|
NoSeeContents,
|
||||||
|
DroppedItemsDontExpire
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq, Ord, PartialOrd)]
|
#[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq, Ord, PartialOrd)]
|
||||||
|
@ -33,7 +33,10 @@ pub enum TaskDetails {
|
|||||||
DelayedHealth {
|
DelayedHealth {
|
||||||
item: String,
|
item: String,
|
||||||
effect_series: VecDeque<DelayedHealthEffect>
|
effect_series: VecDeque<DelayedHealthEffect>
|
||||||
}
|
},
|
||||||
|
ExpireItem {
|
||||||
|
item_code: String
|
||||||
|
},
|
||||||
}
|
}
|
||||||
impl TaskDetails {
|
impl TaskDetails {
|
||||||
pub fn name(self: &Self) -> &'static str {
|
pub fn name(self: &Self) -> &'static str {
|
||||||
@ -47,6 +50,7 @@ impl TaskDetails {
|
|||||||
RecloneNPC { .. } => "RecloneNPC",
|
RecloneNPC { .. } => "RecloneNPC",
|
||||||
RotCorpse { .. } => "RotCorpse",
|
RotCorpse { .. } => "RotCorpse",
|
||||||
DelayedHealth { .. } => "DelayedHealth",
|
DelayedHealth { .. } => "DelayedHealth",
|
||||||
|
ExpireItem { .. } => "ExpireItem",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,7 @@ use crate::{
|
|||||||
listener::{ListenerMap, ListenerSend},
|
listener::{ListenerMap, ListenerSend},
|
||||||
static_content::npc,
|
static_content::npc,
|
||||||
services::{combat, effect},
|
services::{combat, effect},
|
||||||
|
message_handler::user_commands::drop,
|
||||||
};
|
};
|
||||||
#[cfg(not(test))] use crate::models::task::{TaskParse, TaskRecurrence};
|
#[cfg(not(test))] use crate::models::task::{TaskParse, TaskRecurrence};
|
||||||
use mockall_double::double;
|
use mockall_double::double;
|
||||||
@ -43,6 +44,7 @@ fn task_handler_registry() -> &'static BTreeMap<&'static str, &'static (dyn Task
|
|||||||
("RecloneNPC", npc::RECLONE_HANDLER.clone()),
|
("RecloneNPC", npc::RECLONE_HANDLER.clone()),
|
||||||
("RotCorpse", combat::ROT_CORPSE_HANDLER.clone()),
|
("RotCorpse", combat::ROT_CORPSE_HANDLER.clone()),
|
||||||
("DelayedHealth", effect::DELAYED_HEALTH_HANDLER.clone()),
|
("DelayedHealth", effect::DELAYED_HEALTH_HANDLER.clone()),
|
||||||
|
("ExpireItem", drop::EXPIRE_ITEM_HANDLER.clone()),
|
||||||
).into_iter().collect()
|
).into_iter().collect()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,7 @@ use crate::{
|
|||||||
possession_type::{WeaponData, possession_data, fist},
|
possession_type::{WeaponData, possession_data, fist},
|
||||||
npc::npc_by_code,
|
npc::npc_by_code,
|
||||||
},
|
},
|
||||||
message_handler::user_commands::{user_error, UResult},
|
message_handler::user_commands::{user_error, UResult, drop::consider_expire_job_for_item},
|
||||||
regular_tasks::{TaskRunContext, TaskHandler},
|
regular_tasks::{TaskRunContext, TaskHandler},
|
||||||
DResult,
|
DResult,
|
||||||
};
|
};
|
||||||
@ -504,6 +504,15 @@ impl TaskHandler for RotCorpseTaskHandler {
|
|||||||
corpse.display_for_sentence(true, 1, true));
|
corpse.display_for_sentence(true, 1, true));
|
||||||
let msg_nonexp = format!("{} rots away to nothing.\n",
|
let msg_nonexp = format!("{} rots away to nothing.\n",
|
||||||
corpse.display_for_sentence(false, 1, true));
|
corpse.display_for_sentence(false, 1, true));
|
||||||
|
|
||||||
|
for item in ctx.trans.find_items_by_location(
|
||||||
|
&format!("{}/{}", &corpse.item_type, &corpse.item_code)).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 = corpse.location.clone();
|
||||||
|
consider_expire_job_for_item(ctx.trans, &item_mut).await?;
|
||||||
|
}
|
||||||
ctx.trans.transfer_all_possessions_code(
|
ctx.trans.transfer_all_possessions_code(
|
||||||
&format!("{}/{}", &corpse.item_type, &corpse.item_code),
|
&format!("{}/{}", &corpse.item_type, &corpse.item_code),
|
||||||
&corpse.location).await?;
|
&corpse.location).await?;
|
||||||
|
Loading…
Reference in New Issue
Block a user