Crafting slots now properly check component recipe book to see if an input is valid.

This commit is contained in:
Sam 2022-05-06 00:22:23 -04:00
parent e9f36b9486
commit 1b85258838
3 changed files with 79 additions and 79 deletions

View File

@ -2,7 +2,7 @@ use super::{
get_quality_col, get_quality_col,
img_ids::{Imgs, ImgsRot}, img_ids::{Imgs, ImgsRot},
item_imgs::{animate_by_pulse, ItemImgs}, item_imgs::{animate_by_pulse, ItemImgs},
slots::{CraftSlot, SlotManager}, slots::{CraftSlot, CraftSlotInfo, SlotManager},
Show, TEXT_COLOR, TEXT_DULL_RED_COLOR, TEXT_GRAY_COLOR, UI_HIGHLIGHT_0, UI_MAIN, Show, TEXT_COLOR, TEXT_DULL_RED_COLOR, TEXT_GRAY_COLOR, UI_HIGHLIGHT_0, UI_MAIN,
}; };
use crate::ui::{ use crate::ui::{
@ -20,8 +20,8 @@ use common::{
modular, modular,
modular::ModularComponent, modular::ModularComponent,
tool::{AbilityMap, ToolKind}, tool::{AbilityMap, ToolKind},
Item, ItemBase, ItemDef, ItemDesc, ItemKind, ItemTag, MaterialKind, Item, ItemBase, ItemDef, ItemDesc, ItemKind, ItemTag, MaterialStatManifest, Quality,
MaterialStatManifest, Quality, TagExampleInfo, TagExampleInfo,
}, },
slot::InvSlotId, slot::InvSlotId,
Inventory, Inventory,
@ -38,8 +38,8 @@ use conrod_core::{
use hashbrown::HashMap; use hashbrown::HashMap;
use i18n::Localization; use i18n::Localization;
use std::{collections::BTreeMap, sync::Arc}; use std::{collections::BTreeMap, sync::Arc};
use strum::{EnumIter, IntoEnumIterator}; use strum::{EnumIter, IntoEnumIterator};
use tracing::warn;
use vek::*; use vek::*;
widget_ids! { widget_ids! {
@ -882,7 +882,7 @@ impl<'a> Widget for Crafting<'a> {
index: 0, index: 0,
invslot: self.show.crafting_fields.recipe_inputs.get(&0).copied(), invslot: self.show.crafting_fields.recipe_inputs.get(&0).copied(),
requirement: match recipe_kind { requirement: match recipe_kind {
RecipeKind::ModularWeapon => |item| { RecipeKind::ModularWeapon => |item, _, _| {
item.map_or(false, |item| { item.map_or(false, |item| {
matches!( matches!(
&*item.kind(), &*item.kind(),
@ -892,43 +892,26 @@ impl<'a> Widget for Crafting<'a> {
) )
}) })
}, },
// TODO: Maybe try to figure out way to get this to work? RecipeKind::Component(_) => |item, comp_recipes, info| {
// Captures self and toolkind which prevents it from becoming a function if let Some(CraftSlotInfo::Tool(toolkind)) = info {
// Some(RecipeKind::Component(toolkind)) => |inv, slot| { item.map_or(false, |item| {
// inv.and_then(|inv| inv.get(slot)).map_or(false, |item| { comp_recipes
// self.client.component_recipe_book().iter().filter(|(key,
// _recipe)| key.toolkind == toolkind).any(|(key, _recipe)| key.material
// == item.item_definition_id()) })
// },
RecipeKind::Component(
ToolKind::Sword | ToolKind::Axe | ToolKind::Hammer,
) => |item| {
item.map_or(false, |item| {
matches!(&*item.kind(), ItemKind::Ingredient { .. })
&& item
.tags()
.contains(&ItemTag::MaterialKind(MaterialKind::Metal))
&& item
.tags()
.iter() .iter()
.any(|tag| matches!(tag, ItemTag::Material(_))) .filter(|(key, _)| key.toolkind == toolkind)
}) .any(|(key, _)| {
Some(key.material.as_str())
== item.item_definition_id().raw()
})
})
} else {
false
}
}, },
RecipeKind::Component( RecipeKind::Simple => |_, _, _| unreachable!(),
ToolKind::Bow | ToolKind::Staff | ToolKind::Sceptre, },
) => |item| { info: match recipe_kind {
item.map_or(false, |item| { RecipeKind::Component(toolkind) => Some(CraftSlotInfo::Tool(toolkind)),
matches!(&*item.kind(), ItemKind::Ingredient { .. }) RecipeKind::ModularWeapon | RecipeKind::Simple => None,
&& item
.tags()
.contains(&ItemTag::MaterialKind(MaterialKind::Wood))
&& item
.tags()
.iter()
.any(|tag| matches!(tag, ItemTag::Material(_)))
})
},
RecipeKind::Component(_) | RecipeKind::Simple => |_| unreachable!(),
}, },
}; };
@ -957,7 +940,7 @@ impl<'a> Widget for Crafting<'a> {
index: 1, index: 1,
invslot: self.show.crafting_fields.recipe_inputs.get(&1).copied(), invslot: self.show.crafting_fields.recipe_inputs.get(&1).copied(),
requirement: match recipe_kind { requirement: match recipe_kind {
RecipeKind::ModularWeapon => |item| { RecipeKind::ModularWeapon => |item, _, _| {
item.map_or(false, |item| { item.map_or(false, |item| {
matches!( matches!(
&*item.kind(), &*item.kind(),
@ -967,22 +950,26 @@ impl<'a> Widget for Crafting<'a> {
) )
}) })
}, },
// TODO: Maybe try to figure out way to get this to work? RecipeKind::Component(_) => |item, comp_recipes, info| {
// Captures self and toolkind which prevents it from becoming a function if let Some(CraftSlotInfo::Tool(toolkind)) = info {
// Some(RecipeKind::Component(toolkind)) => |inv, slot| { item.map_or(false, |item| {
// inv.and_then(|inv| inv.get(slot)).map_or(false, |item| { comp_recipes
// self.client.component_recipe_book().iter().filter(|(key, .iter()
// _recipe)| key.toolkind == toolkind).any(|(key, _recipe)| key.modifier .filter(|(key, _)| key.toolkind == toolkind)
// == Some(item.item_definition_id())) .any(|(key, _)| {
// }) }, key.modifier.as_deref()
RecipeKind::Component(_) => |item| { == item.item_definition_id().raw()
item.map_or(false, |item| { })
item.item_definition_id().raw().map_or(false, |id| {
id.starts_with("common.items.crafting_ing.animal_misc")
}) })
}) } else {
false
}
}, },
RecipeKind::Simple => |_| unreachable!(), RecipeKind::Simple => |_, _, _| unreachable!(),
},
info: match recipe_kind {
RecipeKind::Component(toolkind) => Some(CraftSlotInfo::Tool(toolkind)),
RecipeKind::ModularWeapon | RecipeKind::Simple => None,
}, },
}; };
@ -1493,7 +1480,7 @@ impl<'a> Widget for Crafting<'a> {
// Widget generation for every ingredient // Widget generation for every ingredient
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) => Some(Arc::clone(item_def)),
RecipeInput::Tag(tag) | RecipeInput::TagSameItem(tag) => self RecipeInput::Tag(tag) | RecipeInput::TagSameItem(tag) => self
.inventory .inventory
.slots() .slots()
@ -1508,11 +1495,9 @@ impl<'a> Widget for Crafting<'a> {
} }
}) })
}) })
.unwrap_or_else(|| { .or_else(|| {
Arc::<ItemDef>::load_expect_cloned( tag.exemplar_identifier()
tag.exemplar_identifier() .map(Arc::<ItemDef>::load_expect_cloned)
.unwrap_or("common.items.weapons.empty.empty"),
)
}), }),
RecipeInput::ListSameItem(item_defs) => self RecipeInput::ListSameItem(item_defs) => self
.inventory .inventory
@ -1528,22 +1513,25 @@ impl<'a> Widget for Crafting<'a> {
} }
}) })
}) })
.unwrap_or_else(|| { .or_else(|| {
item_defs item_defs.first().and_then(|i| {
.first() i.item_definition_id()
.and_then(|i| { .raw()
i.item_definition_id() .map(Arc::<ItemDef>::load_expect_cloned)
.raw() })
.map(Arc::<ItemDef>::load_expect_cloned)
})
.unwrap_or_else(|| {
Arc::<ItemDef>::load_expect_cloned(
"common.items.weapons.empty.empty",
)
})
}), }),
}; };
let item_def = if let Some(item_def) = item_def {
item_def
} else {
warn!(
"Failed to create example item def for recipe input {:?}",
recipe_input
);
continue;
};
// 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
// item // item
let item_count_in_inventory = self.inventory.item_count(&*item_def); let item_count_in_inventory = self.inventory.item_count(&*item_def);

View File

@ -3479,6 +3479,8 @@ impl Hud {
inventories inventories
.get(client.entity()) .get(client.entity())
.and_then(|inv| inv.get(i.slot)), .and_then(|inv| inv.get(i.slot)),
client.component_recipe_book(),
c.info,
) { ) {
self.show self.show
.crafting_fields .crafting_fields

View File

@ -5,10 +5,14 @@ use super::{
util, util,
}; };
use crate::ui::slot::{self, SlotKey, SumSlot}; use crate::ui::slot::{self, SlotKey, SumSlot};
use common::comp::{ use common::{
ability::{Ability, AbilityInput, AuxiliaryAbility}, comp::{
slot::InvSlotId, ability::{Ability, AbilityInput, AuxiliaryAbility},
ActiveAbilities, Body, Energy, Inventory, Item, ItemKey, SkillSet, item::tool::ToolKind,
slot::InvSlotId,
ActiveAbilities, Body, Energy, Inventory, Item, ItemKey, SkillSet,
},
recipe::ComponentRecipeBook,
}; };
use conrod_core::{image, Color}; use conrod_core::{image, Color};
use specs::Entity as EcsEntity; use specs::Entity as EcsEntity;
@ -239,7 +243,13 @@ impl<'a> SlotKey<AbilitiesSource<'a>, img_ids::Imgs> for AbilitySlot {
pub struct CraftSlot { pub struct CraftSlot {
pub index: u32, pub index: u32,
pub invslot: Option<InvSlotId>, pub invslot: Option<InvSlotId>,
pub requirement: fn(Option<&Item>) -> bool, pub requirement: fn(Option<&Item>, &ComponentRecipeBook, Option<CraftSlotInfo>) -> bool,
pub info: Option<CraftSlotInfo>,
}
#[derive(Clone, Copy, Debug)]
pub enum CraftSlotInfo {
Tool(ToolKind),
} }
impl PartialEq for CraftSlot { impl PartialEq for CraftSlot {