From 7fdfc0e71b6ecaa3844786b42d26c309b0407c37 Mon Sep 17 00:00:00 2001 From: Sam Date: Sun, 16 Apr 2023 17:31:39 -0400 Subject: [PATCH] Addressed review --- common/src/comp/inventory/item/mod.rs | 10 ++-- common/src/comp/inventory/loadout.rs | 43 ++++++++++++---- common/src/comp/inventory/mod.rs | 64 +++++++++++++----------- common/src/recipe.rs | 2 +- server/src/events/entity_manipulation.rs | 34 ++++++------- voxygen/src/hud/crafting.rs | 4 +- voxygen/src/hud/util.rs | 2 +- voxygen/src/ui/widgets/item_tooltip.rs | 2 +- 8 files changed, 95 insertions(+), 66 deletions(-) diff --git a/common/src/comp/inventory/item/mod.rs b/common/src/comp/inventory/item/mod.rs index 4432d17d9f..a003c50ee7 100644 --- a/common/src/comp/inventory/item/mod.rs +++ b/common/src/comp/inventory/item/mod.rs @@ -1213,7 +1213,7 @@ impl Item { } } - pub fn durability(&self) -> Option { + pub fn durability_lost(&self) -> Option { self.durability_lost.map(|x| x.min(Self::MAX_DURABILITY)) } @@ -1294,7 +1294,7 @@ pub trait ItemDesc { fn is_modular(&self) -> bool; fn components(&self) -> &[Item]; fn has_durability(&self) -> bool; - fn durability(&self) -> Option; + fn durability_lost(&self) -> Option; fn stats_durability_multiplier(&self) -> DurabilityMultiplier; fn tool_info(&self) -> Option { @@ -1327,7 +1327,7 @@ impl ItemDesc for Item { fn has_durability(&self) -> bool { self.has_durability() } - fn durability(&self) -> Option { self.durability() } + fn durability_lost(&self) -> Option { self.durability_lost() } fn stats_durability_multiplier(&self) -> DurabilityMultiplier { self.stats_durability_multiplier() @@ -1359,7 +1359,7 @@ impl ItemDesc for ItemDef { self.kind().has_durability() && self.quality != Quality::Debug } - fn durability(&self) -> Option { None } + fn durability_lost(&self) -> Option { None } fn stats_durability_multiplier(&self) -> DurabilityMultiplier { DurabilityMultiplier(1.0) } } @@ -1399,7 +1399,7 @@ impl<'a, T: ItemDesc + ?Sized> ItemDesc for &'a T { fn has_durability(&self) -> bool { (*self).has_durability() } - fn durability(&self) -> Option { (*self).durability() } + fn durability_lost(&self) -> Option { (*self).durability_lost() } fn stats_durability_multiplier(&self) -> DurabilityMultiplier { (*self).stats_durability_multiplier() diff --git a/common/src/comp/inventory/loadout.rs b/common/src/comp/inventory/loadout.rs index 5cef680415..8075bef650 100644 --- a/common/src/comp/inventory/loadout.rs +++ b/common/src/comp/inventory/loadout.rs @@ -20,7 +20,10 @@ pub(super) const UNEQUIP_TRACKING_DURATION: f64 = 60.0; pub struct Loadout { slots: Vec, // Includes time that item was unequipped at - pub(super) recently_unequipped_items: HashMap, + #[serde(skip)] + // Tracks time unequipped at and number that have been unequipped (for things like dual + // wielding, rings, or other future cases) + pub(super) recently_unequipped_items: HashMap, } /// NOTE: Please don't derive a PartialEq Instance for this; that's broken! @@ -103,22 +106,26 @@ impl Loadout { item: Option, time: Time, ) -> Option { - self.recently_unequipped_items.retain(|def, unequip_time| { - let item_reequipped = item - .as_ref() - .map_or(false, |i| def.as_ref() == i.item_definition_id()); - let old_unequip = time.0 - unequip_time.0 > UNEQUIP_TRACKING_DURATION; - // Stop tracking item if it is re-equipped or if was unequipped a while ago - !(item_reequipped || old_unequip) - }); + if let Some(item_def_id) = item.as_ref().map(|item| item.item_definition_id()) { + if let Some((_unequip_time, count)) = self + .recently_unequipped_items + .get_mut(&item_def_id.to_owned()) + { + *count = count.saturating_sub(1); + } + } + self.cull_recently_unequipped_items(time); let unequipped_item = self .slots .iter_mut() .find(|x| x.equip_slot == equip_slot) .and_then(|x| core::mem::replace(&mut x.slot, item)); if let Some(unequipped_item) = unequipped_item.as_ref() { - self.recently_unequipped_items - .insert(unequipped_item.item_definition_id().to_owned(), time); + let entry = self + .recently_unequipped_items + .entry(unequipped_item.item_definition_id().to_owned()) + .or_insert((time, 0)); + *entry = (time, entry.1 + 1); } unequipped_item } @@ -485,6 +492,20 @@ impl Loadout { item.reset_durability(ability_map, msm); } } + + pub(super) fn cull_recently_unequipped_items(&mut self, time: Time) { + for (unequip_time, _count) in self.recently_unequipped_items.values_mut() { + // If somehow time went backwards or faulty unequip time supplied, set unequip + // time to minimum of current time and unequip time + if time.0 < unequip_time.0 { + *unequip_time = time; + } + } + self.recently_unequipped_items + .retain(|_def, (unequip_time, count)| { + (time.0 - unequip_time.0 < UNEQUIP_TRACKING_DURATION) || *count > 0 + }); + } } #[cfg(test)] diff --git a/common/src/comp/inventory/mod.rs b/common/src/comp/inventory/mod.rs index 4240bff167..6bfcf29635 100644 --- a/common/src/comp/inventory/mod.rs +++ b/common/src/comp/inventory/mod.rs @@ -899,39 +899,47 @@ impl Inventory { time: Time, ) { self.loadout.damage_items(ability_map, msm); - self.loadout - .recently_unequipped_items - .retain(|_item, unequip_time| { - time.0 - unequip_time.0 <= loadout::UNEQUIP_TRACKING_DURATION - }); - let inv_slots = self - .loadout - .recently_unequipped_items - .keys() - .filter_map(|item_def_id| { - self.slots_with_id() - .find(|&(_, item)| { - if let Some(item) = item { - // Find an item with the matching item definition id and that is not yet - // at maximum durability lost - item.item_definition_id() == *item_def_id - && item - .durability() - .map_or(true, |dur| dur < Item::MAX_DURABILITY) - } else { - false - } - }) - .map(|(slot, _)| slot) + self.loadout.cull_recently_unequipped_items(time); + + let slots = self + .slots_with_id() + .filter(|(_slot, item)| { + item.as_ref().map_or(false, |item| { + item.durability_lost() + .map_or(false, |dur| dur < Item::MAX_DURABILITY) + && self + .loadout + .recently_unequipped_items + .contains_key(&item.item_definition_id().to_owned()) + }) }) + .map(|(slot, _item)| slot) .collect::>(); - for inv_slot in inv_slots.iter() { - if let Some(Some(item)) = self.slot_mut(*inv_slot) { - if item.has_durability() { + slots.into_iter().for_each(|slot| { + let slot = if let Some(Some(item)) = self.slot(slot) { + if let Some((_unequip_time, count)) = self + .loadout + .recently_unequipped_items + .get_mut(&item.item_definition_id().to_owned()) + { + if *count > 0 { + *count -= 1; + Some(slot) + } else { + None + } + } else { + None + } + } else { + None + }; + if let Some(slot) = slot { + if let Some(Some(item)) = self.slot_mut(slot) { item.increment_damage(ability_map, msm); } } - } + }); } /// Resets durability of item in specified slot diff --git a/common/src/recipe.rs b/common/src/recipe.rs index b14abb1a7c..0db1ca695e 100644 --- a/common/src/recipe.rs +++ b/common/src/recipe.rs @@ -976,7 +976,7 @@ impl RepairRecipe { } pub fn inputs(&self, item: &Item) -> impl Iterator { - let item_durability = item.durability().unwrap_or(0); + let item_durability = item.durability_lost().unwrap_or(0); self.inputs .iter() .filter_map(move |(input, original_amount)| { diff --git a/server/src/events/entity_manipulation.rs b/server/src/events/entity_manipulation.rs index e91b92d584..ca06333997 100644 --- a/server/src/events/entity_manipulation.rs +++ b/server/src/events/entity_manipulation.rs @@ -1414,28 +1414,28 @@ pub fn handle_entity_attacked_hook(server: &Server, entity: EcsEntity) { // If entity was in an active trade, cancel it let mut trades = ecs.write_resource::(); let uids = ecs.read_storage::(); - let clients = ecs.read_storage::(); - let mut agents = ecs.write_storage::(); - let mut notify_trade_party = |entity| { - if let Some(client) = clients.get(entity) { - client.send_fallible(ServerGeneral::FinishedTrade(TradeResult::Declined)); - } - if let Some(agent) = agents.get_mut(entity) { - agent - .inbox - .push_back(AgentEvent::FinishedTrade(TradeResult::Declined)); - } - }; if let Some(uid) = uids.get(entity) { - // Notify attacked entity - notify_trade_party(entity); if let Some(trade) = trades.entity_trades.get(uid).copied() { trades .decline_trade(trade, *uid) .and_then(|uid| ecs.entity_from_uid(uid.0)) - .map(|entity| { - // Notify person trading with attacked person - notify_trade_party(entity) + .map(|entity_b| { + // Notify both parties that the trade ended + let clients = ecs.read_storage::(); + let mut agents = ecs.write_storage::(); + let mut notify_trade_party = |entity| { + if let Some(client) = clients.get(entity) { + client + .send_fallible(ServerGeneral::FinishedTrade(TradeResult::Declined)); + } + if let Some(agent) = agents.get_mut(entity) { + agent + .inbox + .push_back(AgentEvent::FinishedTrade(TradeResult::Declined)); + } + }; + notify_trade_party(entity); + notify_trade_party(entity_b); }); } } diff --git a/voxygen/src/hud/crafting.rs b/voxygen/src/hud/crafting.rs index 227e62a868..7ae95e7a39 100644 --- a/voxygen/src/hud/crafting.rs +++ b/voxygen/src/hud/crafting.rs @@ -1376,7 +1376,7 @@ impl<'a> Widget for Crafting<'a> { let repair_slot = CraftSlot { index: 0, slot: self.show.crafting_fields.recipe_inputs.get(&0).copied(), - requirement: |item, _, _| item.durability().map_or(false, |d| d > 0), + requirement: |item, _, _| item.durability_lost().map_or(false, |d| d > 0), info: None, }; @@ -1413,7 +1413,7 @@ impl<'a> Widget for Crafting<'a> { let can_repair = |item: &Item| { // Check that item needs to be repaired, and that inventory has sufficient // materials to repair - item.durability().map_or(false, |d| d > 0) + item.durability_lost().map_or(false, |d| d > 0) && self.client.repair_recipe_book().repair_recipe(item).map_or( false, |recipe| { diff --git a/voxygen/src/hud/util.rs b/voxygen/src/hud/util.rs index ffef7e3540..4d4cf139a2 100644 --- a/voxygen/src/hud/util.rs +++ b/voxygen/src/hud/util.rs @@ -359,7 +359,7 @@ pub fn protec2string(stat: Protection) -> String { /// Gets the durability of an item in a format more intuitive for UI pub fn item_durability(item: &dyn ItemDesc) -> Option { let durability = item - .durability() + .durability_lost() .or_else(|| item.has_durability().then_some(0)); durability.map(|d| Item::MAX_DURABILITY - d) } diff --git a/voxygen/src/ui/widgets/item_tooltip.rs b/voxygen/src/ui/widgets/item_tooltip.rs index 4e4161c738..8c6f60cbe4 100644 --- a/voxygen/src/ui/widgets/item_tooltip.rs +++ b/voxygen/src/ui/widgets/item_tooltip.rs @@ -670,7 +670,7 @@ impl<'a> Widget for ItemTooltip<'a> { ); if item.has_durability() { - let durability = Item::MAX_DURABILITY - item.durability().unwrap_or(0); + let durability = Item::MAX_DURABILITY - item.durability_lost().unwrap_or(0); stat_text( format!( "{} : {}/{}",