diff --git a/common/src/comp/inventory/item/mod.rs b/common/src/comp/inventory/item/mod.rs index f1f87c35b6..0f9eb51cd5 100644 --- a/common/src/comp/inventory/item/mod.rs +++ b/common/src/comp/inventory/item/mod.rs @@ -24,10 +24,10 @@ use core::{ ops::Deref, }; use crossbeam_utils::atomic::AtomicCell; -use serde::{Deserialize, Serialize}; +use serde::{de, Deserialize, Serialize, Serializer}; use specs::{Component, DerefFlaggedStorage}; use specs_idvs::IdvStorage; -use std::sync::Arc; +use std::{fmt, sync::Arc}; use vek::Rgb; #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] @@ -205,6 +205,10 @@ pub struct Item { /// item_def is hidden because changing the item definition for an item /// could change invariants like whether it was stackable (invalidating /// the amount). + #[serde( + serialize_with = "serialize_item_def", + deserialize_with = "deserialize_item_def" + )] item_def: Arc, /// components is hidden to maintain the following invariants: /// - It should only contain modular components (and enhancements, once they @@ -224,6 +228,42 @@ pub struct Item { item_config: Option>, } +// Custom serialization for ItemDef, we only want to send the item_definition_id +// over the network, the client will use deserialize_item_def to fetch the +// ItemDef from assets. +fn serialize_item_def(field: &Arc, serializer: S) -> Result +where + S: Serializer, +{ + serializer.serialize_str(&field.item_definition_id) +} + +// Custom de-serialization for ItemDef to retrieve the ItemDef from assets using +// its asset specifier (item_definition_id) +fn deserialize_item_def<'de, D>(deserializer: D) -> Result, D::Error> +where + D: de::Deserializer<'de>, +{ + struct ItemDefStringVisitor; + + impl<'de> de::Visitor<'de> for ItemDefStringVisitor { + type Value = Arc; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("item def string") + } + + fn visit_str(self, item_definition_id: &str) -> Result + where + E: de::Error, + { + Ok(Arc::::load_expect_cloned(item_definition_id)) + } + } + + deserializer.deserialize_str(ItemDefStringVisitor) +} + #[derive(Debug, Serialize, Deserialize)] pub struct ItemDef { #[serde(default)]