mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Changed item definition id to better handle modular items.
This commit is contained in:
@ -2,7 +2,8 @@ use crate::{
|
|||||||
assets::AssetExt,
|
assets::AssetExt,
|
||||||
comp::inventory::item::{
|
comp::inventory::item::{
|
||||||
armor::{Armor, ArmorKind},
|
armor::{Armor, ArmorKind},
|
||||||
modular, Glider, ItemDef, ItemDesc, ItemKind, Lantern, Throwable, Utility,
|
modular, Glider, ItemDef, ItemDefinitionId, ItemDesc, ItemKind, Lantern, Throwable,
|
||||||
|
Utility,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
@ -29,29 +30,33 @@ impl<T: ItemDesc> From<&T> for ItemKey {
|
|||||||
let item_definition_id = item_desc.item_definition_id();
|
let item_definition_id = item_desc.item_definition_id();
|
||||||
|
|
||||||
match &*item_desc.kind() {
|
match &*item_desc.kind() {
|
||||||
ItemKind::Tool(_) => {
|
ItemKind::Tool(_) => match item_definition_id {
|
||||||
if item_desc.is_modular() {
|
ItemDefinitionId::Simple(id) => ItemKey::Tool(id.to_string()),
|
||||||
|
ItemDefinitionId::Modular { .. } => {
|
||||||
ItemKey::ModularWeapon(modular::weapon_to_key(item_desc))
|
ItemKey::ModularWeapon(modular::weapon_to_key(item_desc))
|
||||||
} else {
|
},
|
||||||
ItemKey::Tool(item_definition_id.to_owned())
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
ItemKind::ModularComponent(mod_comp) => {
|
ItemKind::ModularComponent(mod_comp) => {
|
||||||
use modular::ModularComponent;
|
use modular::ModularComponent;
|
||||||
match mod_comp {
|
match mod_comp {
|
||||||
ModularComponent::ToolPrimaryComponent { .. } => {
|
ModularComponent::ToolPrimaryComponent { .. } => {
|
||||||
match modular::weapon_component_to_key(
|
if let Some(id) = item_definition_id.raw() {
|
||||||
item_definition_id,
|
match modular::weapon_component_to_key(id, item_desc.components()) {
|
||||||
item_desc.components(),
|
Ok(key) => ItemKey::ModularWeaponComponent(key),
|
||||||
) {
|
// TODO: Maybe use a different ItemKey?
|
||||||
Ok(key) => ItemKey::ModularWeaponComponent(key),
|
Err(_) => ItemKey::Tool(id.to_owned()),
|
||||||
// TODO: Maybe use a different ItemKey?
|
}
|
||||||
Err(_) => ItemKey::Tool(item_definition_id.to_owned()),
|
} else {
|
||||||
|
ItemKey::Empty
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
ModularComponent::ToolSecondaryComponent { .. } => {
|
ModularComponent::ToolSecondaryComponent { .. } => {
|
||||||
// TODO: Maybe use a different ItemKey?
|
if let Some(id) = item_definition_id.raw() {
|
||||||
ItemKey::Tool(item_definition_id.to_owned())
|
// TODO: Maybe use a different ItemKey?
|
||||||
|
ItemKey::Tool(id.to_owned())
|
||||||
|
} else {
|
||||||
|
ItemKey::Empty
|
||||||
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -59,7 +64,13 @@ impl<T: ItemDesc> From<&T> for ItemKey {
|
|||||||
ItemKind::Glider(Glider { kind, .. }) => ItemKey::Glider(kind.clone()),
|
ItemKind::Glider(Glider { kind, .. }) => ItemKey::Glider(kind.clone()),
|
||||||
ItemKind::Armor(Armor { kind, .. }) => ItemKey::Armor(kind.clone()),
|
ItemKind::Armor(Armor { kind, .. }) => ItemKey::Armor(kind.clone()),
|
||||||
ItemKind::Utility { kind, .. } => ItemKey::Utility(*kind),
|
ItemKind::Utility { kind, .. } => ItemKey::Utility(*kind),
|
||||||
ItemKind::Consumable { .. } => ItemKey::Consumable(item_definition_id.to_owned()),
|
ItemKind::Consumable { .. } => {
|
||||||
|
if let Some(id) = item_definition_id.raw() {
|
||||||
|
ItemKey::Consumable(id.to_owned())
|
||||||
|
} else {
|
||||||
|
ItemKey::Empty
|
||||||
|
}
|
||||||
|
},
|
||||||
ItemKind::Throwable { kind, .. } => ItemKey::Throwable(*kind),
|
ItemKind::Throwable { kind, .. } => ItemKey::Throwable(*kind),
|
||||||
ItemKind::Ingredient { kind, .. } => ItemKey::Ingredient(kind.clone()),
|
ItemKind::Ingredient { kind, .. } => ItemKey::Ingredient(kind.clone()),
|
||||||
ItemKind::TagExamples { item_ids } => ItemKey::TagExamples(
|
ItemKind::TagExamples { item_ids } => ItemKey::TagExamples(
|
||||||
|
@ -379,7 +379,7 @@ pub enum ItemName {
|
|||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub enum ItemBase {
|
pub enum ItemBase {
|
||||||
Raw(Arc<ItemDef>),
|
Simple(Arc<ItemDef>),
|
||||||
Modular(modular::ModularBase),
|
Modular(modular::ModularBase),
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -392,7 +392,7 @@ impl Serialize for ItemBase {
|
|||||||
S: Serializer,
|
S: Serializer,
|
||||||
{
|
{
|
||||||
serializer.serialize_str(match self {
|
serializer.serialize_str(match self {
|
||||||
ItemBase::Raw(item_def) => &item_def.item_definition_id,
|
ItemBase::Simple(item_def) => &item_def.item_definition_id,
|
||||||
ItemBase::Modular(mod_base) => mod_base.pseudo_item_id(),
|
ItemBase::Modular(mod_base) => mod_base.pseudo_item_id(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -422,7 +422,7 @@ impl<'de> Deserialize<'de> for ItemBase {
|
|||||||
if serialized_item_base.starts_with(crate::modular_item_id_prefix!()) {
|
if serialized_item_base.starts_with(crate::modular_item_id_prefix!()) {
|
||||||
ItemBase::Modular(ModularBase::load_from_pseudo_id(serialized_item_base))
|
ItemBase::Modular(ModularBase::load_from_pseudo_id(serialized_item_base))
|
||||||
} else {
|
} else {
|
||||||
ItemBase::Raw(Arc::<ItemDef>::load_expect_cloned(serialized_item_base))
|
ItemBase::Simple(Arc::<ItemDef>::load_expect_cloned(serialized_item_base))
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -435,19 +435,71 @@ impl<'de> Deserialize<'de> for ItemBase {
|
|||||||
impl ItemBase {
|
impl ItemBase {
|
||||||
fn num_slots(&self) -> u16 {
|
fn num_slots(&self) -> u16 {
|
||||||
match self {
|
match self {
|
||||||
ItemBase::Raw(item_def) => item_def.num_slots(),
|
ItemBase::Simple(item_def) => item_def.num_slots(),
|
||||||
ItemBase::Modular(_) => 0,
|
ItemBase::Modular(_) => 0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn item_definition_id(&self) -> &str {
|
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq, Hash)]
|
||||||
match &self {
|
pub enum ItemDefinitionId<'a> {
|
||||||
ItemBase::Raw(item_def) => &item_def.item_definition_id,
|
Simple(&'a str),
|
||||||
ItemBase::Modular(mod_base) => mod_base.pseudo_item_id(),
|
Modular {
|
||||||
|
pseudo_base: &'a str,
|
||||||
|
components: Vec<ItemDefinitionId<'a>>,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
|
||||||
|
pub enum ItemDefinitionIdOwned {
|
||||||
|
Simple(String),
|
||||||
|
Modular {
|
||||||
|
pseudo_base: String,
|
||||||
|
components: Vec<ItemDefinitionIdOwned>,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ItemDefinitionIdOwned {
|
||||||
|
pub fn as_ref(&self) -> ItemDefinitionId<'_> {
|
||||||
|
match *self {
|
||||||
|
Self::Simple(ref id) => ItemDefinitionId::Simple(id),
|
||||||
|
Self::Modular {
|
||||||
|
ref pseudo_base,
|
||||||
|
ref components,
|
||||||
|
} => ItemDefinitionId::Modular {
|
||||||
|
pseudo_base,
|
||||||
|
components: components.iter().map(|comp| comp.as_ref()).collect(),
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'a> ItemDefinitionId<'a> {
|
||||||
|
pub fn raw(&self) -> Option<&str> {
|
||||||
|
match self {
|
||||||
|
Self::Simple(id) => Some(id),
|
||||||
|
Self::Modular { .. } => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn to_owned(&self) -> ItemDefinitionIdOwned {
|
||||||
|
match self {
|
||||||
|
Self::Simple(id) => ItemDefinitionIdOwned::Simple(String::from(*id)),
|
||||||
|
Self::Modular {
|
||||||
|
pseudo_base,
|
||||||
|
components,
|
||||||
|
} => ItemDefinitionIdOwned::Modular {
|
||||||
|
pseudo_base: String::from(*pseudo_base),
|
||||||
|
components: components.iter().map(|comp| comp.to_owned()).collect(),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for ItemDefinitionIdOwned {
|
||||||
|
fn default() -> Self { Self::Simple(String::new()) }
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
pub struct ItemDef {
|
pub struct ItemDef {
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
@ -580,7 +632,7 @@ impl ItemDef {
|
|||||||
/// please don't rely on this for anything!
|
/// please don't rely on this for anything!
|
||||||
impl PartialEq for Item {
|
impl PartialEq for Item {
|
||||||
fn eq(&self, other: &Self) -> bool {
|
fn eq(&self, other: &Self) -> bool {
|
||||||
if let (ItemBase::Raw(self_def), ItemBase::Raw(other_def)) =
|
if let (ItemBase::Simple(self_def), ItemBase::Simple(other_def)) =
|
||||||
(&self.item_base, &other.item_base)
|
(&self.item_base, &other.item_base)
|
||||||
{
|
{
|
||||||
self_def.item_definition_id == other_def.item_definition_id
|
self_def.item_definition_id == other_def.item_definition_id
|
||||||
@ -706,7 +758,7 @@ impl Item {
|
|||||||
let inner_item = if asset.starts_with("veloren.core.pseudo_items.modular") {
|
let inner_item = if asset.starts_with("veloren.core.pseudo_items.modular") {
|
||||||
ItemBase::Modular(ModularBase::load_from_pseudo_id(asset))
|
ItemBase::Modular(ModularBase::load_from_pseudo_id(asset))
|
||||||
} else {
|
} else {
|
||||||
ItemBase::Raw(Arc::<ItemDef>::load_cloned(asset)?)
|
ItemBase::Simple(Arc::<ItemDef>::load_cloned(asset)?)
|
||||||
};
|
};
|
||||||
// TODO: Get msm and ability_map less hackily
|
// TODO: Get msm and ability_map less hackily
|
||||||
let msm = &MaterialStatManifest::load().read();
|
let msm = &MaterialStatManifest::load().read();
|
||||||
@ -729,7 +781,7 @@ impl Item {
|
|||||||
.collect();
|
.collect();
|
||||||
let mut new_item = Item::new_from_item_base(
|
let mut new_item = Item::new_from_item_base(
|
||||||
match &self.item_base {
|
match &self.item_base {
|
||||||
ItemBase::Raw(item_def) => ItemBase::Raw(Arc::clone(item_def)),
|
ItemBase::Simple(item_def) => ItemBase::Simple(Arc::clone(item_def)),
|
||||||
ItemBase::Modular(mod_base) => ItemBase::Modular(mod_base.clone()),
|
ItemBase::Modular(mod_base) => ItemBase::Modular(mod_base.clone()),
|
||||||
},
|
},
|
||||||
duplicated_components,
|
duplicated_components,
|
||||||
@ -844,10 +896,22 @@ impl Item {
|
|||||||
self.slots.iter_mut().filter_map(mem::take)
|
self.slots.iter_mut().filter_map(mem::take)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn item_definition_id(&self) -> &str { self.item_base.item_definition_id() }
|
pub fn item_definition_id(&self) -> ItemDefinitionId<'_> {
|
||||||
|
match &self.item_base {
|
||||||
|
ItemBase::Simple(item_def) => ItemDefinitionId::Simple(&item_def.item_definition_id),
|
||||||
|
ItemBase::Modular(mod_base) => ItemDefinitionId::Modular {
|
||||||
|
pseudo_base: mod_base.pseudo_item_id(),
|
||||||
|
components: self
|
||||||
|
.components
|
||||||
|
.iter()
|
||||||
|
.map(|item| item.item_definition_id())
|
||||||
|
.collect(),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn is_same_item_def(&self, item_def: &ItemDef) -> bool {
|
pub fn is_same_item_def(&self, item_def: &ItemDef) -> bool {
|
||||||
if let ItemBase::Raw(self_def) = &self.item_base {
|
if let ItemBase::Simple(self_def) = &self.item_base {
|
||||||
self_def.item_definition_id == item_def.item_definition_id
|
self_def.item_definition_id == item_def.item_definition_id
|
||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
@ -885,7 +949,7 @@ impl Item {
|
|||||||
|
|
||||||
pub fn name(&self) -> Cow<str> {
|
pub fn name(&self) -> Cow<str> {
|
||||||
match &self.item_base {
|
match &self.item_base {
|
||||||
ItemBase::Raw(item_def) => {
|
ItemBase::Simple(item_def) => {
|
||||||
if self.components.is_empty() {
|
if self.components.is_empty() {
|
||||||
Cow::Borrowed(&item_def.name)
|
Cow::Borrowed(&item_def.name)
|
||||||
} else {
|
} else {
|
||||||
@ -898,7 +962,7 @@ impl Item {
|
|||||||
|
|
||||||
pub fn description(&self) -> &str {
|
pub fn description(&self) -> &str {
|
||||||
match &self.item_base {
|
match &self.item_base {
|
||||||
ItemBase::Raw(item_def) => &item_def.description,
|
ItemBase::Simple(item_def) => &item_def.description,
|
||||||
// TODO: See if James wanted to make description, else leave with none
|
// TODO: See if James wanted to make description, else leave with none
|
||||||
ItemBase::Modular(_) => "",
|
ItemBase::Modular(_) => "",
|
||||||
}
|
}
|
||||||
@ -906,7 +970,7 @@ impl Item {
|
|||||||
|
|
||||||
pub fn kind(&self) -> Cow<ItemKind> {
|
pub fn kind(&self) -> Cow<ItemKind> {
|
||||||
match &self.item_base {
|
match &self.item_base {
|
||||||
ItemBase::Raw(item_def) => Cow::Borrowed(&item_def.kind),
|
ItemBase::Simple(item_def) => Cow::Borrowed(&item_def.kind),
|
||||||
ItemBase::Modular(mod_base) => {
|
ItemBase::Modular(mod_base) => {
|
||||||
// TODO: Try to move further upward
|
// TODO: Try to move further upward
|
||||||
let msm = MaterialStatManifest::load().read();
|
let msm = MaterialStatManifest::load().read();
|
||||||
@ -919,7 +983,7 @@ impl Item {
|
|||||||
|
|
||||||
pub fn is_stackable(&self) -> bool {
|
pub fn is_stackable(&self) -> bool {
|
||||||
match &self.item_base {
|
match &self.item_base {
|
||||||
ItemBase::Raw(item_def) => item_def.is_stackable(),
|
ItemBase::Simple(item_def) => item_def.is_stackable(),
|
||||||
// TODO: Let whoever implements stackable modular items deal with this
|
// TODO: Let whoever implements stackable modular items deal with this
|
||||||
ItemBase::Modular(_) => false,
|
ItemBase::Modular(_) => false,
|
||||||
}
|
}
|
||||||
@ -933,7 +997,7 @@ impl Item {
|
|||||||
|
|
||||||
pub fn quality(&self) -> Quality {
|
pub fn quality(&self) -> Quality {
|
||||||
match &self.item_base {
|
match &self.item_base {
|
||||||
ItemBase::Raw(item_def) => item_def.quality,
|
ItemBase::Simple(item_def) => item_def.quality,
|
||||||
ItemBase::Modular(mod_base) => mod_base.compute_quality(self.components()),
|
ItemBase::Modular(mod_base) => mod_base.compute_quality(self.components()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -964,7 +1028,7 @@ impl Item {
|
|||||||
|
|
||||||
pub fn ability_spec(&self) -> Option<Cow<AbilitySpec>> {
|
pub fn ability_spec(&self) -> Option<Cow<AbilitySpec>> {
|
||||||
match &self.item_base {
|
match &self.item_base {
|
||||||
ItemBase::Raw(item_def) => {
|
ItemBase::Simple(item_def) => {
|
||||||
item_def.ability_spec.as_ref().map(Cow::Borrowed).or({
|
item_def.ability_spec.as_ref().map(Cow::Borrowed).or({
|
||||||
// If no custom ability set is specified, fall back to abilityset of tool
|
// If no custom ability set is specified, fall back to abilityset of tool
|
||||||
// kind.
|
// kind.
|
||||||
@ -983,7 +1047,7 @@ impl Item {
|
|||||||
// iterator?
|
// iterator?
|
||||||
pub fn tags(&self) -> Vec<ItemTag> {
|
pub fn tags(&self) -> Vec<ItemTag> {
|
||||||
match &self.item_base {
|
match &self.item_base {
|
||||||
ItemBase::Raw(item_def) => item_def.tags.to_vec(),
|
ItemBase::Simple(item_def) => item_def.tags.to_vec(),
|
||||||
// TODO: Do this properly. It'll probably be important at some point.
|
// TODO: Do this properly. It'll probably be important at some point.
|
||||||
ItemBase::Modular(mod_base) => mod_base.generate_tags(self.components()),
|
ItemBase::Modular(mod_base) => mod_base.generate_tags(self.components()),
|
||||||
}
|
}
|
||||||
@ -991,7 +1055,7 @@ impl Item {
|
|||||||
|
|
||||||
pub fn is_modular(&self) -> bool {
|
pub fn is_modular(&self) -> bool {
|
||||||
match &self.item_base {
|
match &self.item_base {
|
||||||
ItemBase::Raw(_) => false,
|
ItemBase::Simple(_) => false,
|
||||||
ItemBase::Modular(_) => true,
|
ItemBase::Modular(_) => true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1003,7 +1067,7 @@ impl Item {
|
|||||||
let ability_map = &AbilityMap::load().read();
|
let ability_map = &AbilityMap::load().read();
|
||||||
let msm = &MaterialStatManifest::load().read();
|
let msm = &MaterialStatManifest::load().read();
|
||||||
Self::new_from_item_base(
|
Self::new_from_item_base(
|
||||||
ItemBase::Raw(Arc::new(ItemDef::create_test_itemdef_from_kind(kind))),
|
ItemBase::Simple(Arc::new(ItemDef::create_test_itemdef_from_kind(kind))),
|
||||||
Vec::new(),
|
Vec::new(),
|
||||||
ability_map,
|
ability_map,
|
||||||
msm,
|
msm,
|
||||||
@ -1019,7 +1083,7 @@ pub trait ItemDesc {
|
|||||||
fn kind(&self) -> Cow<ItemKind>;
|
fn kind(&self) -> Cow<ItemKind>;
|
||||||
fn quality(&self) -> Quality;
|
fn quality(&self) -> Quality;
|
||||||
fn num_slots(&self) -> u16;
|
fn num_slots(&self) -> u16;
|
||||||
fn item_definition_id(&self) -> &str;
|
fn item_definition_id(&self) -> ItemDefinitionId<'_>;
|
||||||
fn tags(&self) -> Vec<ItemTag>;
|
fn tags(&self) -> Vec<ItemTag>;
|
||||||
|
|
||||||
fn is_modular(&self) -> bool;
|
fn is_modular(&self) -> bool;
|
||||||
@ -1046,7 +1110,7 @@ impl ItemDesc for Item {
|
|||||||
|
|
||||||
fn num_slots(&self) -> u16 { self.num_slots() }
|
fn num_slots(&self) -> u16 { self.num_slots() }
|
||||||
|
|
||||||
fn item_definition_id(&self) -> &str { self.item_definition_id() }
|
fn item_definition_id(&self) -> ItemDefinitionId<'_> { self.item_definition_id() }
|
||||||
|
|
||||||
fn tags(&self) -> Vec<ItemTag> { self.tags() }
|
fn tags(&self) -> Vec<ItemTag> { self.tags() }
|
||||||
|
|
||||||
@ -1066,7 +1130,9 @@ impl ItemDesc for ItemDef {
|
|||||||
|
|
||||||
fn num_slots(&self) -> u16 { self.slots }
|
fn num_slots(&self) -> u16 { self.slots }
|
||||||
|
|
||||||
fn item_definition_id(&self) -> &str { &self.item_definition_id }
|
fn item_definition_id(&self) -> ItemDefinitionId<'_> {
|
||||||
|
ItemDefinitionId::Simple(&self.item_definition_id)
|
||||||
|
}
|
||||||
|
|
||||||
fn tags(&self) -> Vec<ItemTag> { self.tags.to_vec() }
|
fn tags(&self) -> Vec<ItemTag> { self.tags.to_vec() }
|
||||||
|
|
||||||
@ -1097,7 +1163,7 @@ impl<'a, T: ItemDesc + ?Sized> ItemDesc for &'a T {
|
|||||||
|
|
||||||
fn num_slots(&self) -> u16 { (*self).num_slots() }
|
fn num_slots(&self) -> u16 { (*self).num_slots() }
|
||||||
|
|
||||||
fn item_definition_id(&self) -> &str { (*self).item_definition_id() }
|
fn item_definition_id(&self) -> ItemDefinitionId<'_> { (*self).item_definition_id() }
|
||||||
|
|
||||||
fn components(&self) -> &[Item] { (*self).components() }
|
fn components(&self) -> &[Item] { (*self).components() }
|
||||||
|
|
||||||
|
@ -238,7 +238,13 @@ impl ModularComponent {
|
|||||||
Self::ToolPrimaryComponent { stats, .. } => {
|
Self::ToolPrimaryComponent { stats, .. } => {
|
||||||
let average_material_mult = components
|
let average_material_mult = components
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(|comp| msm.0.get(comp.item_definition_id()).copied().zip(Some(1)))
|
.filter_map(|comp| {
|
||||||
|
comp.item_definition_id()
|
||||||
|
.raw()
|
||||||
|
.and_then(|id| msm.0.get(id))
|
||||||
|
.copied()
|
||||||
|
.zip(Some(1))
|
||||||
|
})
|
||||||
.reduce(|(stats_a, count_a), (stats_b, count_b)| {
|
.reduce(|(stats_a, count_a), (stats_b, count_b)| {
|
||||||
(stats_a + stats_b, count_a + count_b)
|
(stats_a + stats_b, count_a + count_b)
|
||||||
})
|
})
|
||||||
@ -308,7 +314,7 @@ lazy_static! {
|
|||||||
if let Ok(items) = Item::new_from_asset_glob(&directory) {
|
if let Ok(items) = Item::new_from_asset_glob(&directory) {
|
||||||
items
|
items
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|comp| comp.item_definition_id().to_owned())
|
.filter_map(|comp| Some(comp.item_definition_id().raw()?.to_owned()))
|
||||||
.filter_map(|id| Arc::<ItemDef>::load_cloned(&id).ok())
|
.filter_map(|id| Arc::<ItemDef>::load_cloned(&id).ok())
|
||||||
.for_each(|comp_def| {
|
.for_each(|comp_def| {
|
||||||
if let ItemKind::ModularComponent(ModularComponent::ToolSecondaryComponent { hand_restriction, .. }) = comp_def.kind {
|
if let ItemKind::ModularComponent(ModularComponent::ToolSecondaryComponent { hand_restriction, .. }) = comp_def.kind {
|
||||||
@ -378,7 +384,7 @@ pub fn random_weapon(
|
|||||||
.ok_or(ModularWeaponCreationError::SecondaryComponentNotFound)?
|
.ok_or(ModularWeaponCreationError::SecondaryComponentNotFound)?
|
||||||
.0;
|
.0;
|
||||||
Item::new_from_item_base(
|
Item::new_from_item_base(
|
||||||
ItemBase::Raw(Arc::clone(def)),
|
ItemBase::Simple(Arc::clone(def)),
|
||||||
Vec::new(),
|
Vec::new(),
|
||||||
ability_map,
|
ability_map,
|
||||||
msm,
|
msm,
|
||||||
@ -441,9 +447,9 @@ pub fn weapon_to_key(mod_weap: impl ItemDesc) -> ModularWeaponKey {
|
|||||||
.iter()
|
.iter()
|
||||||
.find_map(|comp| match &*comp.kind() {
|
.find_map(|comp| match &*comp.kind() {
|
||||||
ItemKind::ModularComponent(ModularComponent::ToolPrimaryComponent { .. }) => {
|
ItemKind::ModularComponent(ModularComponent::ToolPrimaryComponent { .. }) => {
|
||||||
let component_id = comp.item_definition_id().to_owned();
|
let component_id = comp.item_definition_id().raw()?.to_owned();
|
||||||
let material_id = comp.components().iter().find_map(|mat| match &*mat.kind() {
|
let material_id = comp.components().iter().find_map(|mat| match &*mat.kind() {
|
||||||
ItemKind::Ingredient { .. } => Some(mat.item_definition_id().to_owned()),
|
ItemKind::Ingredient { .. } => Some(mat.item_definition_id().raw()?.to_owned()),
|
||||||
_ => None,
|
_ => None,
|
||||||
});
|
});
|
||||||
Some((component_id, material_id))
|
Some((component_id, material_id))
|
||||||
@ -469,7 +475,7 @@ pub fn weapon_component_to_key(
|
|||||||
components: &[Item],
|
components: &[Item],
|
||||||
) -> Result<ModularWeaponComponentKey, ModularWeaponComponentKeyError> {
|
) -> Result<ModularWeaponComponentKey, ModularWeaponComponentKeyError> {
|
||||||
match components.iter().find_map(|mat| match &*mat.kind() {
|
match components.iter().find_map(|mat| match &*mat.kind() {
|
||||||
ItemKind::Ingredient { .. } => Some(mat.item_definition_id().to_owned()),
|
ItemKind::Ingredient { .. } => Some(mat.item_definition_id().raw()?.to_owned()),
|
||||||
_ => None,
|
_ => None,
|
||||||
}) {
|
}) {
|
||||||
Some(material_id) => Ok((item_def_id.to_owned(), material_id)),
|
Some(material_id) => Ok((item_def_id.to_owned(), material_id)),
|
||||||
|
@ -23,7 +23,7 @@ pub(super) fn get_test_bag(slots: u16) -> Item {
|
|||||||
);
|
);
|
||||||
|
|
||||||
Item::new_from_item_base(
|
Item::new_from_item_base(
|
||||||
ItemBase::Raw(Arc::new(item_def)),
|
ItemBase::Simple(Arc::new(item_def)),
|
||||||
Vec::new(),
|
Vec::new(),
|
||||||
&AbilityMap::load().read(),
|
&AbilityMap::load().read(),
|
||||||
&MaterialStatManifest::load().read(),
|
&MaterialStatManifest::load().read(),
|
||||||
|
@ -135,7 +135,7 @@ impl Recipe {
|
|||||||
let (item_def, quantity) = &self.output;
|
let (item_def, quantity) = &self.output;
|
||||||
|
|
||||||
let crafted_item = Item::new_from_item_base(
|
let crafted_item = Item::new_from_item_base(
|
||||||
ItemBase::Raw(Arc::clone(item_def)),
|
ItemBase::Simple(Arc::clone(item_def)),
|
||||||
components,
|
components,
|
||||||
ability_map,
|
ability_map,
|
||||||
msm,
|
msm,
|
||||||
@ -659,7 +659,7 @@ impl ComponentRecipe {
|
|||||||
.iter()
|
.iter()
|
||||||
.map(|item_def| {
|
.map(|item_def| {
|
||||||
Item::new_from_item_base(
|
Item::new_from_item_base(
|
||||||
ItemBase::Raw(Arc::clone(item_def)),
|
ItemBase::Simple(Arc::clone(item_def)),
|
||||||
Vec::new(),
|
Vec::new(),
|
||||||
ability_map,
|
ability_map,
|
||||||
msm,
|
msm,
|
||||||
@ -667,7 +667,7 @@ impl ComponentRecipe {
|
|||||||
})
|
})
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
Item::new_from_item_base(
|
Item::new_from_item_base(
|
||||||
ItemBase::Raw(Arc::clone(item_def)),
|
ItemBase::Simple(Arc::clone(item_def)),
|
||||||
components,
|
components,
|
||||||
ability_map,
|
ability_map,
|
||||||
msm,
|
msm,
|
||||||
|
@ -29,8 +29,8 @@ pub struct StaticData {
|
|||||||
pub recover_duration: Duration,
|
pub recover_duration: Duration,
|
||||||
/// Inventory slot to use item from
|
/// Inventory slot to use item from
|
||||||
pub inv_slot: InvSlotId,
|
pub inv_slot: InvSlotId,
|
||||||
/// Item definition id, used to verify that slot still has the correct item
|
/// Item hash, used to verify that slot still has the correct item
|
||||||
pub item_definition_id: String,
|
pub item_hash: u64,
|
||||||
/// Kind of item used
|
/// Kind of item used
|
||||||
pub item_kind: ItemUseKind,
|
pub item_kind: ItemUseKind,
|
||||||
/// Had weapon wielded
|
/// Had weapon wielded
|
||||||
@ -213,7 +213,7 @@ fn use_item(data: &JoinData, output_events: &mut OutputEvents, state: &Data) {
|
|||||||
.inventory
|
.inventory
|
||||||
.and_then(|inv| inv.get(state.static_data.inv_slot))
|
.and_then(|inv| inv.get(state.static_data.inv_slot))
|
||||||
.map_or(false, |item| {
|
.map_or(false, |item| {
|
||||||
item.item_definition_id() == state.static_data.item_definition_id
|
item.item_hash() == state.static_data.item_hash
|
||||||
});
|
});
|
||||||
if item_is_same {
|
if item_is_same {
|
||||||
// Create inventory manipulation event
|
// Create inventory manipulation event
|
||||||
|
@ -714,7 +714,7 @@ pub fn handle_manipulate_loadout(
|
|||||||
recover_duration,
|
recover_duration,
|
||||||
inv_slot,
|
inv_slot,
|
||||||
item_kind,
|
item_kind,
|
||||||
item_definition_id: item.item_definition_id().to_string(),
|
item_hash: item.item_hash(),
|
||||||
was_wielded: matches!(data.character, CharacterState::Wielding(_)),
|
was_wielded: matches!(data.character, CharacterState::Wielding(_)),
|
||||||
was_sneak: data.character.is_stealthy(),
|
was_sneak: data.character.is_stealthy(),
|
||||||
},
|
},
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
use std::cmp::Ordering;
|
use std::cmp::Ordering;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
comp::inventory::{slot::InvSlotId, trade_pricing::TradePricing, Inventory},
|
comp::inventory::{
|
||||||
|
item::ItemDefinitionIdOwned, slot::InvSlotId, trade_pricing::TradePricing, Inventory,
|
||||||
|
},
|
||||||
terrain::BiomeKind,
|
terrain::BiomeKind,
|
||||||
uid::Uid,
|
uid::Uid,
|
||||||
};
|
};
|
||||||
@ -387,7 +389,12 @@ impl SitePrices {
|
|||||||
.as_ref()
|
.as_ref()
|
||||||
.and_then(|ri| {
|
.and_then(|ri| {
|
||||||
ri.inventory.get(slot).map(|item| {
|
ri.inventory.get(slot).map(|item| {
|
||||||
if let Some(vec) = TradePricing::get_materials(&item.name) {
|
if let Some(vec) = item
|
||||||
|
.name
|
||||||
|
.as_ref()
|
||||||
|
.raw()
|
||||||
|
.and_then(TradePricing::get_materials)
|
||||||
|
{
|
||||||
vec.iter()
|
vec.iter()
|
||||||
.map(|(amount2, material)| {
|
.map(|(amount2, material)| {
|
||||||
self.values.get(material).copied().unwrap_or_default()
|
self.values.get(material).copied().unwrap_or_default()
|
||||||
@ -409,7 +416,7 @@ impl SitePrices {
|
|||||||
|
|
||||||
#[derive(Clone, Debug, Default)]
|
#[derive(Clone, Debug, Default)]
|
||||||
pub struct ReducedInventoryItem {
|
pub struct ReducedInventoryItem {
|
||||||
pub name: String,
|
pub name: ItemDefinitionIdOwned,
|
||||||
pub amount: u32,
|
pub amount: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -425,7 +432,7 @@ impl ReducedInventory {
|
|||||||
.filter(|(_, it)| it.is_some())
|
.filter(|(_, it)| it.is_some())
|
||||||
.map(|(sl, it)| {
|
.map(|(sl, it)| {
|
||||||
(sl, ReducedInventoryItem {
|
(sl, ReducedInventoryItem {
|
||||||
name: it.as_ref().unwrap().item_definition_id().to_string(),
|
name: it.as_ref().unwrap().item_definition_id().to_owned(),
|
||||||
amount: it.as_ref().unwrap().amount(),
|
amount: it.as_ref().unwrap().amount(),
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -177,16 +177,15 @@ pub fn handle_mine_block(
|
|||||||
if let (Some(tool), Some(uid), Some(exp_reward)) = (
|
if let (Some(tool), Some(uid), Some(exp_reward)) = (
|
||||||
tool,
|
tool,
|
||||||
state.ecs().uid_from_entity(entity),
|
state.ecs().uid_from_entity(entity),
|
||||||
RESOURCE_EXPERIENCE_MANIFEST
|
item.item_definition_id()
|
||||||
.read()
|
.raw()
|
||||||
.0
|
.and_then(|id| RESOURCE_EXPERIENCE_MANIFEST.read().0.get(id).copied()),
|
||||||
.get(item.item_definition_id()),
|
|
||||||
) {
|
) {
|
||||||
let skill_group = SkillGroupKind::Weapon(tool);
|
let skill_group = SkillGroupKind::Weapon(tool);
|
||||||
let outcome_bus = state.ecs().read_resource::<EventBus<Outcome>>();
|
let outcome_bus = state.ecs().read_resource::<EventBus<Outcome>>();
|
||||||
let positions = state.ecs().read_component::<comp::Pos>();
|
let positions = state.ecs().read_component::<comp::Pos>();
|
||||||
if let (Some(level_outcome), Some(pos)) = (
|
if let (Some(level_outcome), Some(pos)) = (
|
||||||
skillset.add_experience(skill_group, *exp_reward),
|
skillset.add_experience(skill_group, exp_reward),
|
||||||
positions.get(entity),
|
positions.get(entity),
|
||||||
) {
|
) {
|
||||||
outcome_bus.emit_now(Outcome::SkillPointGain {
|
outcome_bus.emit_now(Outcome::SkillPointGain {
|
||||||
@ -198,7 +197,7 @@ pub fn handle_mine_block(
|
|||||||
}
|
}
|
||||||
outcome_bus.emit_now(Outcome::ExpChange {
|
outcome_bus.emit_now(Outcome::ExpChange {
|
||||||
uid,
|
uid,
|
||||||
exp: *exp_reward,
|
exp: exp_reward,
|
||||||
xp_pools: HashSet::from_iter(vec![skill_group]),
|
xp_pools: HashSet::from_iter(vec![skill_group]),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -223,10 +222,10 @@ pub fn handle_mine_block(
|
|||||||
rng.gen_bool(chance_mod * f64::from(skill_level))
|
rng.gen_bool(chance_mod * f64::from(skill_level))
|
||||||
};
|
};
|
||||||
|
|
||||||
let double_gain = (item.item_definition_id().contains("mineral.ore.")
|
let double_gain = item.item_definition_id().raw().map_or(false, |id| {
|
||||||
&& need_double_ore(&mut rng))
|
(id.contains("mineral.ore.") && need_double_ore(&mut rng))
|
||||||
|| (item.item_definition_id().contains("mineral.gem.")
|
|| (id.contains("mineral.gem.") && need_double_gem(&mut rng))
|
||||||
&& need_double_gem(&mut rng));
|
});
|
||||||
|
|
||||||
if double_gain {
|
if double_gain {
|
||||||
// Ignore non-stackable errors
|
// Ignore non-stackable errors
|
||||||
|
@ -678,13 +678,17 @@ pub fn handle_inventory(server: &mut Server, entity: EcsEntity, manip: comp::Inv
|
|||||||
slots,
|
slots,
|
||||||
} => {
|
} => {
|
||||||
let component_recipes = default_component_recipe_book().read();
|
let component_recipes = default_component_recipe_book().read();
|
||||||
let item_id = |slot| inventory.get(slot).map(|item| item.item_definition_id());
|
let item_id = |slot| {
|
||||||
|
inventory
|
||||||
|
.get(slot)
|
||||||
|
.and_then(|item| item.item_definition_id().raw().map(String::from))
|
||||||
|
};
|
||||||
if let Some(material_item_id) = item_id(material) {
|
if let Some(material_item_id) = item_id(material) {
|
||||||
component_recipes
|
component_recipes
|
||||||
.get(&ComponentKey {
|
.get(&ComponentKey {
|
||||||
toolkind,
|
toolkind,
|
||||||
material: String::from(material_item_id),
|
material: material_item_id,
|
||||||
modifier: modifier.and_then(item_id).map(String::from),
|
modifier: modifier.and_then(item_id),
|
||||||
})
|
})
|
||||||
.filter(|r| {
|
.filter(|r| {
|
||||||
if let Some(needed_sprite) = r.craft_sprite {
|
if let Some(needed_sprite) = r.craft_sprite {
|
||||||
|
@ -3,7 +3,7 @@ use common::{
|
|||||||
comp::{
|
comp::{
|
||||||
agent::{Agent, AgentEvent},
|
agent::{Agent, AgentEvent},
|
||||||
inventory::{
|
inventory::{
|
||||||
item::{tool::AbilityMap, MaterialStatManifest},
|
item::{tool::AbilityMap, ItemDefinitionIdOwned, MaterialStatManifest},
|
||||||
Inventory,
|
Inventory,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -239,7 +239,7 @@ fn commit_trade(ecs: &specs::World, trade: &PendingTrade) -> TradeResult {
|
|||||||
|
|
||||||
// Hashmap to compute merged stackable stacks, including overflow checks
|
// Hashmap to compute merged stackable stacks, including overflow checks
|
||||||
// TODO: add a ComponentKey struct to compare items properly, see issue #1226
|
// TODO: add a ComponentKey struct to compare items properly, see issue #1226
|
||||||
let mut stackable_items: HashMap<String, TradeQuantities> = HashMap::new();
|
let mut stackable_items: HashMap<ItemDefinitionIdOwned, TradeQuantities> = HashMap::new();
|
||||||
for who in [0, 1].iter().cloned() {
|
for who in [0, 1].iter().cloned() {
|
||||||
for (slot, quantity) in trade.offers[who].iter() {
|
for (slot, quantity) in trade.offers[who].iter() {
|
||||||
let inventory = inventories.get_mut(entities[who]).expect(invmsg);
|
let inventory = inventories.get_mut(entities[who]).expect(invmsg);
|
||||||
@ -274,7 +274,7 @@ fn commit_trade(ecs: &specs::World, trade: &PendingTrade) -> TradeResult {
|
|||||||
max_stack_size,
|
max_stack_size,
|
||||||
trade_quantities,
|
trade_quantities,
|
||||||
} = stackable_items
|
} = stackable_items
|
||||||
.entry(item.item_definition_id().to_string())
|
.entry(item.item_definition_id().to_owned())
|
||||||
.or_insert_with(|| TradeQuantities::new(item.max_amount()));
|
.or_insert_with(|| TradeQuantities::new(item.max_amount()));
|
||||||
|
|
||||||
trade_quantities[who].full_stacks += 1;
|
trade_quantities[who].full_stacks += 1;
|
||||||
@ -295,7 +295,7 @@ fn commit_trade(ecs: &specs::World, trade: &PendingTrade) -> TradeResult {
|
|||||||
max_stack_size: _,
|
max_stack_size: _,
|
||||||
trade_quantities,
|
trade_quantities,
|
||||||
} = stackable_items
|
} = stackable_items
|
||||||
.entry(item.item_definition_id().to_string())
|
.entry(item.item_definition_id().to_owned())
|
||||||
.or_insert_with(|| TradeQuantities::new(item.max_amount()));
|
.or_insert_with(|| TradeQuantities::new(item.max_amount()));
|
||||||
|
|
||||||
trade_quantities[who].quantity_sold += *quantity as u128;
|
trade_quantities[who].quantity_sold += *quantity as u128;
|
||||||
@ -338,7 +338,7 @@ fn commit_trade(ecs: &specs::World, trade: &PendingTrade) -> TradeResult {
|
|||||||
.slots()
|
.slots()
|
||||||
.flatten()
|
.flatten()
|
||||||
.filter_map(|it| {
|
.filter_map(|it| {
|
||||||
if it.item_definition_id() == item_id {
|
if it.item_definition_id() == item_id.as_ref() {
|
||||||
Some(*max_stack_size as u128 - it.amount() as u128)
|
Some(*max_stack_size as u128 - it.amount() as u128)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
|
@ -11,7 +11,7 @@ use common::{
|
|||||||
character::CharacterId,
|
character::CharacterId,
|
||||||
comp::{
|
comp::{
|
||||||
inventory::{
|
inventory::{
|
||||||
item::{tool::AbilityMap, Item as VelorenItem, MaterialStatManifest},
|
item::{tool::AbilityMap, Item as VelorenItem, ItemDefinitionId, MaterialStatManifest},
|
||||||
loadout::{Loadout, LoadoutError},
|
loadout::{Loadout, LoadoutError},
|
||||||
loadout_builder::LoadoutBuilder,
|
loadout_builder::LoadoutBuilder,
|
||||||
slot::InvSlotId,
|
slot::InvSlotId,
|
||||||
@ -165,9 +165,14 @@ pub fn convert_items_to_database_items(
|
|||||||
bfs_queue.push_back((format!("component_{}", i), Some(component), item_id));
|
bfs_queue.push_back((format!("component_{}", i), Some(component), item_id));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let persistence_item_id = match item.item_definition_id() {
|
||||||
|
ItemDefinitionId::Simple(id) => id.to_owned(),
|
||||||
|
ItemDefinitionId::Modular { pseudo_base, .. } => pseudo_base.to_owned(),
|
||||||
|
};
|
||||||
|
|
||||||
let upsert = ItemModelPair {
|
let upsert = ItemModelPair {
|
||||||
model: Item {
|
model: Item {
|
||||||
item_definition_id: item.item_definition_id().to_owned(),
|
item_definition_id: persistence_item_id,
|
||||||
position,
|
position,
|
||||||
parent_container_item_id,
|
parent_container_item_id,
|
||||||
item_id,
|
item_id,
|
||||||
|
@ -977,8 +977,9 @@ impl<'a> Widget for Crafting<'a> {
|
|||||||
// }) },
|
// }) },
|
||||||
RecipeKind::Component(_) => |item| {
|
RecipeKind::Component(_) => |item| {
|
||||||
item.map_or(false, |item| {
|
item.map_or(false, |item| {
|
||||||
item.item_definition_id()
|
item.item_definition_id().raw().map_or(false, |id| {
|
||||||
.starts_with("common.items.crafting_ing.animal_misc")
|
id.starts_with("common.items.crafting_ing.animal_misc")
|
||||||
|
})
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
RecipeKind::Simple => |_| unreachable!(),
|
RecipeKind::Simple => |_| unreachable!(),
|
||||||
@ -1099,7 +1100,7 @@ impl<'a> Widget for Crafting<'a> {
|
|||||||
if let Some(material) = primary_slot
|
if let Some(material) = primary_slot
|
||||||
.invslot
|
.invslot
|
||||||
.and_then(|slot| self.inventory.get(slot))
|
.and_then(|slot| self.inventory.get(slot))
|
||||||
.map(|item| String::from(item.item_definition_id()))
|
.and_then(|item| item.item_definition_id().raw().map(String::from))
|
||||||
{
|
{
|
||||||
let component_key = ComponentKey {
|
let component_key = ComponentKey {
|
||||||
toolkind,
|
toolkind,
|
||||||
@ -1107,7 +1108,9 @@ impl<'a> Widget for Crafting<'a> {
|
|||||||
modifier: secondary_slot
|
modifier: secondary_slot
|
||||||
.invslot
|
.invslot
|
||||||
.and_then(|slot| self.inventory.get(slot))
|
.and_then(|slot| self.inventory.get(slot))
|
||||||
.map(|item| String::from(item.item_definition_id())),
|
.and_then(|item| {
|
||||||
|
item.item_definition_id().raw().map(String::from)
|
||||||
|
}),
|
||||||
};
|
};
|
||||||
self.client.component_recipe_book().get(&component_key).map(
|
self.client.component_recipe_book().get(&component_key).map(
|
||||||
|component_recipe| {
|
|component_recipe| {
|
||||||
@ -1405,14 +1408,14 @@ impl<'a> Widget for Crafting<'a> {
|
|||||||
RecipeKind::Component(toolkind) => {
|
RecipeKind::Component(toolkind) => {
|
||||||
if let Some(material) = modular_primary_slot
|
if let Some(material) = modular_primary_slot
|
||||||
.and_then(|slot| self.inventory.get(slot))
|
.and_then(|slot| self.inventory.get(slot))
|
||||||
.map(|item| String::from(item.item_definition_id()))
|
.and_then(|item| item.item_definition_id().raw().map(String::from))
|
||||||
{
|
{
|
||||||
let component_key = ComponentKey {
|
let component_key = ComponentKey {
|
||||||
toolkind,
|
toolkind,
|
||||||
material,
|
material,
|
||||||
modifier: modular_secondary_slot
|
modifier: modular_secondary_slot
|
||||||
.and_then(|slot| self.inventory.get(slot))
|
.and_then(|slot| self.inventory.get(slot))
|
||||||
.map(|item| String::from(item.item_definition_id())),
|
.and_then(|item| item.item_definition_id().raw().map(String::from)),
|
||||||
};
|
};
|
||||||
if let Some(comp_recipe) =
|
if let Some(comp_recipe) =
|
||||||
self.client.component_recipe_book().get(&component_key)
|
self.client.component_recipe_book().get(&component_key)
|
||||||
@ -1491,42 +1494,54 @@ impl<'a> Widget for Crafting<'a> {
|
|||||||
for (i, (recipe_input, amount)) in ingredients.enumerate() {
|
for (i, (recipe_input, amount)) in ingredients.enumerate() {
|
||||||
let item_def = match recipe_input {
|
let item_def = match recipe_input {
|
||||||
RecipeInput::Item(item_def) => Arc::clone(item_def),
|
RecipeInput::Item(item_def) => Arc::clone(item_def),
|
||||||
RecipeInput::Tag(tag) | RecipeInput::TagSameItem(tag) => {
|
RecipeInput::Tag(tag) | RecipeInput::TagSameItem(tag) => self
|
||||||
Arc::<ItemDef>::load_expect_cloned(
|
.inventory
|
||||||
self.inventory
|
.slots()
|
||||||
.slots()
|
.find_map(|slot| {
|
||||||
.find_map(|slot| {
|
slot.as_ref().and_then(|item| {
|
||||||
slot.as_ref().and_then(|item| {
|
if item.matches_recipe_input(recipe_input, amount) {
|
||||||
if item.matches_recipe_input(recipe_input, amount) {
|
item.item_definition_id()
|
||||||
Some(item.item_definition_id())
|
.raw()
|
||||||
} else {
|
.map(Arc::<ItemDef>::load_expect_cloned)
|
||||||
None
|
} else {
|
||||||
}
|
None
|
||||||
})
|
}
|
||||||
})
|
|
||||||
.or_else(|| tag.exemplar_identifier())
|
|
||||||
.unwrap_or("common.items.weapons.empty.empty"),
|
|
||||||
)
|
|
||||||
},
|
|
||||||
RecipeInput::ListSameItem(item_defs) => Arc::<ItemDef>::load_expect_cloned(
|
|
||||||
self.inventory
|
|
||||||
.slots()
|
|
||||||
.find_map(|slot| {
|
|
||||||
slot.as_ref().and_then(|item| {
|
|
||||||
if item.matches_recipe_input(recipe_input, amount) {
|
|
||||||
Some(item.item_definition_id())
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
.unwrap_or_else(|| {
|
})
|
||||||
item_defs
|
.unwrap_or_else(|| {
|
||||||
.first()
|
Arc::<ItemDef>::load_expect_cloned(
|
||||||
.map(|i| i.item_definition_id())
|
tag.exemplar_identifier()
|
||||||
.unwrap_or_else(|| "common.items.weapons.empty.empty")
|
.unwrap_or("common.items.weapons.empty.empty"),
|
||||||
}),
|
)
|
||||||
),
|
}),
|
||||||
|
RecipeInput::ListSameItem(item_defs) => self
|
||||||
|
.inventory
|
||||||
|
.slots()
|
||||||
|
.find_map(|slot| {
|
||||||
|
slot.as_ref().and_then(|item| {
|
||||||
|
if item.matches_recipe_input(recipe_input, amount) {
|
||||||
|
item.item_definition_id()
|
||||||
|
.raw()
|
||||||
|
.map(Arc::<ItemDef>::load_expect_cloned)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.unwrap_or_else(|| {
|
||||||
|
item_defs
|
||||||
|
.first()
|
||||||
|
.and_then(|i| {
|
||||||
|
i.item_definition_id()
|
||||||
|
.raw()
|
||||||
|
.map(Arc::<ItemDef>::load_expect_cloned)
|
||||||
|
})
|
||||||
|
.unwrap_or_else(|| {
|
||||||
|
Arc::<ItemDef>::load_expect_cloned(
|
||||||
|
"common.items.weapons.empty.empty",
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}),
|
||||||
};
|
};
|
||||||
|
|
||||||
// Grey color for images and text if their amount is too low to craft the
|
// Grey color for images and text if their amount is too low to craft the
|
||||||
|
@ -3689,8 +3689,10 @@ impl Hud {
|
|||||||
false,
|
false,
|
||||||
);
|
);
|
||||||
if let Some(item) = inventory.get(slot) {
|
if let Some(item) = inventory.get(slot) {
|
||||||
if let Some(materials) =
|
if let Some(materials) = item
|
||||||
TradePricing::get_materials(item.item_definition_id())
|
.item_definition_id()
|
||||||
|
.raw()
|
||||||
|
.and_then(TradePricing::get_materials)
|
||||||
{
|
{
|
||||||
let unit_price: f32 = materials
|
let unit_price: f32 = materials
|
||||||
.iter()
|
.iter()
|
||||||
|
@ -15,7 +15,7 @@ use common::{
|
|||||||
item::{
|
item::{
|
||||||
armor::{Armor, ArmorKind},
|
armor::{Armor, ArmorKind},
|
||||||
item_key::ItemKey,
|
item_key::ItemKey,
|
||||||
modular, Item, ItemKind,
|
modular, Item, ItemDefinitionId, ItemKind,
|
||||||
},
|
},
|
||||||
CharacterState,
|
CharacterState,
|
||||||
},
|
},
|
||||||
@ -221,12 +221,11 @@ impl CharacterCacheKey {
|
|||||||
})
|
})
|
||||||
},
|
},
|
||||||
tool: if are_tools_visible {
|
tool: if are_tools_visible {
|
||||||
let tool_key_from_item = |item: &Item| {
|
let tool_key_from_item = |item: &Item| match item.item_definition_id() {
|
||||||
if item.is_modular() {
|
ItemDefinitionId::Simple(id) => ToolKey::Tool(String::from(id)),
|
||||||
|
ItemDefinitionId::Modular { .. } => {
|
||||||
ToolKey::Modular(modular::weapon_to_key(item))
|
ToolKey::Modular(modular::weapon_to_key(item))
|
||||||
} else {
|
},
|
||||||
ToolKey::Tool(item.item_definition_id().to_owned())
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
Some(CharacterToolKey {
|
Some(CharacterToolKey {
|
||||||
active: inventory
|
active: inventory
|
||||||
|
@ -8,7 +8,7 @@ use std::{cell::RefCell, collections::HashSet, rc::Rc, result::Result, sync::Arc
|
|||||||
use mumble_link::SharedLink;
|
use mumble_link::SharedLink;
|
||||||
use ordered_float::OrderedFloat;
|
use ordered_float::OrderedFloat;
|
||||||
use specs::{Join, WorldExt};
|
use specs::{Join, WorldExt};
|
||||||
use tracing::{error, info, warn};
|
use tracing::{error, info, trace, warn};
|
||||||
use vek::*;
|
use vek::*;
|
||||||
|
|
||||||
use client::{self, Client};
|
use client::{self, Client};
|
||||||
@ -18,7 +18,7 @@ use common::{
|
|||||||
comp::{
|
comp::{
|
||||||
inventory::slot::{EquipSlot, Slot},
|
inventory::slot::{EquipSlot, Slot},
|
||||||
invite::InviteKind,
|
invite::InviteKind,
|
||||||
item::{tool::ToolKind, ItemDef, ItemDesc},
|
item::{tool::ToolKind, ItemDef, ItemDefinitionId, ItemDesc},
|
||||||
ChatMsg, ChatType, InputKind, InventoryUpdateEvent, Pos, Stats, UtteranceKind, Vel,
|
ChatMsg, ChatType, InputKind, InventoryUpdateEvent, Pos, Stats, UtteranceKind, Vel,
|
||||||
},
|
},
|
||||||
consts::MAX_MOUNT_RANGE,
|
consts::MAX_MOUNT_RANGE,
|
||||||
@ -250,8 +250,8 @@ impl SessionState {
|
|||||||
self.hud.add_failed_entity_pickup(entity);
|
self.hud.add_failed_entity_pickup(entity);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
InventoryUpdateEvent::Collected(item) => {
|
InventoryUpdateEvent::Collected(item) => match item.item_definition_id() {
|
||||||
match Arc::<ItemDef>::load_cloned(item.item_definition_id()) {
|
ItemDefinitionId::Simple(id) => match Arc::<ItemDef>::load_cloned(id) {
|
||||||
Result::Ok(item_def) => {
|
Result::Ok(item_def) => {
|
||||||
self.hud.new_loot_message(LootMessage {
|
self.hud.new_loot_message(LootMessage {
|
||||||
item: item_def,
|
item: item_def,
|
||||||
@ -261,11 +261,14 @@ impl SessionState {
|
|||||||
Result::Err(e) => {
|
Result::Err(e) => {
|
||||||
warn!(
|
warn!(
|
||||||
?e,
|
?e,
|
||||||
"Item not present on client: {}",
|
"Item not present on client: {:?}",
|
||||||
item.item_definition_id()
|
item.item_definition_id()
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
}
|
},
|
||||||
|
ItemDefinitionId::Modular { .. } => {
|
||||||
|
trace!("Modular items not currently supported for loot messages.")
|
||||||
|
},
|
||||||
},
|
},
|
||||||
_ => {},
|
_ => {},
|
||||||
};
|
};
|
||||||
@ -1445,7 +1448,9 @@ impl PlayState for SessionState {
|
|||||||
.inventories()
|
.inventories()
|
||||||
.get(client.entity())
|
.get(client.entity())
|
||||||
.and_then(|inv| inv.get(slot))
|
.and_then(|inv| inv.get(slot))
|
||||||
.map(|item| String::from(item.item_definition_id()))
|
.and_then(|item| {
|
||||||
|
item.item_definition_id().raw().map(String::from)
|
||||||
|
})
|
||||||
};
|
};
|
||||||
if let Some(material_id) = item_id(material) {
|
if let Some(material_id) = item_id(material) {
|
||||||
let key = recipe::ComponentKey {
|
let key = recipe::ComponentKey {
|
||||||
|
@ -1316,8 +1316,10 @@ impl<'a> Widget for ItemTooltip<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Price display
|
// Price display
|
||||||
if let Some((buy, sell, factor)) =
|
if let Some((buy, sell, factor)) = item
|
||||||
util::price_desc(self.prices, item.item_definition_id(), i18n)
|
.item_definition_id()
|
||||||
|
.raw()
|
||||||
|
.and_then(|id| util::price_desc(self.prices, id, i18n))
|
||||||
{
|
{
|
||||||
widget::Text::new(&buy)
|
widget::Text::new(&buy)
|
||||||
.x_align_to(state.ids.item_frame, conrod_core::position::Align::Start)
|
.x_align_to(state.ids.item_frame, conrod_core::position::Align::Start)
|
||||||
@ -1413,11 +1415,11 @@ impl<'a> Widget for ItemTooltip<'a> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Price
|
// Price
|
||||||
let price_h: f64 = if let Some((buy, sell, _)) = util::price_desc(
|
let price_h: f64 = if let Some((buy, sell, _)) = item
|
||||||
self.prices,
|
.item_definition_id()
|
||||||
item.item_definition_id(),
|
.raw()
|
||||||
self.localized_strings,
|
.and_then(|id| util::price_desc(self.prices, id, self.localized_strings))
|
||||||
) {
|
{
|
||||||
//Get localized tooltip strings (gotten here because these should only show if
|
//Get localized tooltip strings (gotten here because these should only show if
|
||||||
// in a trade- aka if buy/sell prices are present)
|
// in a trade- aka if buy/sell prices are present)
|
||||||
let tt_hint_1 = self.localized_strings.get("hud.trade.tooltip_hint_1");
|
let tt_hint_1 = self.localized_strings.get("hud.trade.tooltip_hint_1");
|
||||||
|
Reference in New Issue
Block a user