Implement capacity limit system.
This commit is contained in:
parent
99ffe45479
commit
f21f574ebb
@ -61,6 +61,12 @@ pub struct OnlineInfo {
|
||||
pub time: Option<DateTime<Utc>>
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
pub struct LocationStats {
|
||||
pub total_count: u64,
|
||||
pub total_weight: u64,
|
||||
}
|
||||
|
||||
impl DBPool {
|
||||
pub async fn record_listener_ping(self: &DBPool, listener: Uuid) -> DResult<()> {
|
||||
self.get_conn().await?.execute(
|
||||
@ -621,6 +627,13 @@ impl DBTrans {
|
||||
.filter_map(|row| serde_json::from_value(row.get(0)).ok())
|
||||
.collect())
|
||||
}
|
||||
|
||||
pub async fn get_location_stats(&self, location: &str) -> DResult<LocationStats> {
|
||||
Ok(serde_json::from_value(self.pg_trans()?.query_one(
|
||||
"SELECT COUNT(*) AS total_count, SUM(details->>'weight') AS total_weight \
|
||||
FROM items WHERE location = $1", &[&location]
|
||||
).await?.get(0))?)
|
||||
}
|
||||
|
||||
pub async fn commit(mut self: Self) -> DResult<()> {
|
||||
let trans_opt = self.with_trans_mut(|t| std::mem::replace(t, None));
|
||||
|
@ -7,6 +7,7 @@ use crate::{
|
||||
static_content::room,
|
||||
static_content::possession_type::possession_data,
|
||||
models::item::Item,
|
||||
services::capacity::{check_item_capacity, CapacityLevel},
|
||||
};
|
||||
use async_trait::async_trait;
|
||||
use ansi::ansi;
|
||||
@ -51,19 +52,26 @@ impl UserVerb for Verb {
|
||||
user_error("You don't have enough credits to buy that!".to_owned())?;
|
||||
}
|
||||
user.credits -= stock.list_price;
|
||||
let player_item_str = format!("player/{}", &player_item.item_code);
|
||||
let item_code = ctx.trans.alloc_item_code().await?;
|
||||
let loc = match check_item_capacity(ctx.trans, &player_item_str,
|
||||
possession_type.weight).await? {
|
||||
CapacityLevel::OverBurdened | CapacityLevel::AboveItemLimit => {
|
||||
match check_item_capacity(ctx.trans, &player_item.location,
|
||||
possession_type.weight).await? {
|
||||
CapacityLevel::AboveItemLimit =>
|
||||
user_error(
|
||||
"You can't carry it, and there is too much stuff \
|
||||
here already".to_owned())?,
|
||||
_ => &player_item.location
|
||||
}
|
||||
}
|
||||
_ => &player_item_str
|
||||
};
|
||||
let new_item = Item {
|
||||
item_type: "possession".to_owned(),
|
||||
item_code: format!("{}", item_code),
|
||||
possession_type: Some(stock.possession_type.clone()),
|
||||
display: possession_type.display.to_owned(),
|
||||
display_less_explicit: possession_type.display_less_explicit.map(|d| d.to_owned()),
|
||||
details: Some(possession_type.details.to_owned()),
|
||||
details_less_explicit: possession_type.details_less_explicit.map(|d| d.to_owned()),
|
||||
aliases: possession_type.aliases.iter().map(|al| (*al).to_owned()).collect(),
|
||||
location: format!("player/{}", &player_item.item_code),
|
||||
health: possession_type.max_health,
|
||||
..Default::default()
|
||||
location: loc.to_owned(),
|
||||
..stock.possession_type.clone().into()
|
||||
};
|
||||
ctx.trans.create_item(&new_item).await?;
|
||||
ctx.trans.queue_for_session(
|
||||
|
@ -301,6 +301,7 @@ pub struct Item {
|
||||
pub flags: Vec<ItemFlag>,
|
||||
pub sex: Option<Sex>,
|
||||
pub active_combat: Option<ActiveCombat>,
|
||||
pub weight: u64,
|
||||
}
|
||||
|
||||
impl Item {
|
||||
@ -375,6 +376,7 @@ impl Default for Item {
|
||||
flags: vec!(),
|
||||
sex: None,
|
||||
active_combat: Some(Default::default()),
|
||||
weight: 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6,7 +6,7 @@ use crate::{
|
||||
|
||||
pub mod skills;
|
||||
pub mod combat;
|
||||
|
||||
pub mod capacity;
|
||||
pub async fn broadcast_to_room(trans: &DBTrans, location: &str, from_item: Option<&Item>,
|
||||
message_explicit_ok: &str, message_nonexplicit: Option<&str>) -> DResult<()> {
|
||||
for item in trans.find_items_by_location(location).await? {
|
||||
|
36
blastmud_game/src/services/capacity.rs
Normal file
36
blastmud_game/src/services/capacity.rs
Normal file
@ -0,0 +1,36 @@
|
||||
use crate::{
|
||||
db::DBTrans,
|
||||
DResult,
|
||||
};
|
||||
|
||||
pub enum CapacityLevel {
|
||||
Unburdened,
|
||||
SlightlyBurdened,
|
||||
HeavilyBurdened,
|
||||
OverBurdened,
|
||||
AboveItemLimit,
|
||||
}
|
||||
pub async fn check_item_capacity(trans: &DBTrans,
|
||||
container: &str,
|
||||
proposed_weight: u64) -> DResult<CapacityLevel> {
|
||||
let stats = trans.get_location_stats(
|
||||
container
|
||||
).await?;
|
||||
if stats.total_count >= 50 || proposed_weight > 0 && stats.total_count >= 49 {
|
||||
return Ok(CapacityLevel::AboveItemLimit);
|
||||
}
|
||||
if let Some((item_type, _item_code)) = container.split_once("/") {
|
||||
if item_type == "player" || item_type == "npc" {
|
||||
let max_weight = 20000; // TODO Calculate properly
|
||||
let new_weight = stats.total_weight + proposed_weight;
|
||||
if new_weight >= max_weight {
|
||||
return Ok(CapacityLevel::OverBurdened);
|
||||
} else if new_weight >= max_weight * 4 / 5 {
|
||||
return Ok(CapacityLevel::HeavilyBurdened);
|
||||
} else if new_weight >= max_weight / 2 {
|
||||
return Ok(CapacityLevel::SlightlyBurdened);
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(CapacityLevel::Unburdened)
|
||||
}
|
@ -110,6 +110,24 @@ pub enum PossessionType {
|
||||
AntennaWhip,
|
||||
}
|
||||
|
||||
impl Into<Item> for PossessionType {
|
||||
fn into(self) -> Item {
|
||||
let possession_dat = possession_data().get(&self).unwrap();
|
||||
Item {
|
||||
item_type: "possession".to_owned(),
|
||||
possession_type: Some(self.clone()),
|
||||
display: possession_dat.display.to_owned(),
|
||||
display_less_explicit: possession_dat.display_less_explicit.map(|d| d.to_owned()),
|
||||
details: Some(possession_dat.details.to_owned()),
|
||||
details_less_explicit: possession_dat.details_less_explicit.map(|d| d.to_owned()),
|
||||
aliases: possession_dat.aliases.iter().map(|al| (*al).to_owned()).collect(),
|
||||
health: possession_dat.max_health,
|
||||
weight: possession_dat.weight,
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn fist() -> &'static WeaponData {
|
||||
static FIST_WEAPON: OnceCell<WeaponData> = OnceCell::new();
|
||||
FIST_WEAPON.get_or_init(|| {
|
||||
|
Loading…
Reference in New Issue
Block a user