steel_registry/recipe/
smithing.rs1use steel_utils::{DowncastType, DowncastTypeKey};
4
5use crate::item_stack::ItemStack;
6use crate::item_stack_template::ItemStackTemplate;
7use crate::trim_pattern::TrimPatternRef;
8
9use super::{Ingredient, RecipeData, RecipeInput, RecipeMatches, RecipeProperties};
10
11#[derive(Debug)]
12pub struct SmithingTransformRecipe {
13 pub properties: RecipeProperties,
14 pub template: Option<Ingredient>,
15 pub base: Ingredient,
16 pub addition: Option<Ingredient>,
17 pub result: ItemStackTemplate,
18}
19
20#[derive(Debug)]
21pub struct SmithingTrimRecipe {
22 pub properties: RecipeProperties,
23 pub template: Ingredient,
24 pub base: Ingredient,
25 pub addition: Ingredient,
26 pub pattern: TrimPatternRef,
27}
28
29#[derive(Debug)]
31pub enum SmithingRecipe {
32 Transform(SmithingTransformRecipe),
33 Trim(SmithingTrimRecipe),
34}
35
36impl SmithingRecipe {
37 #[must_use]
38 pub const fn properties(&self) -> &RecipeProperties {
39 match self {
40 Self::Transform(recipe) => &recipe.properties,
41 Self::Trim(recipe) => &recipe.properties,
42 }
43 }
44}
45
46unsafe impl DowncastType for SmithingRecipe {
48 const TYPE_KEY: DowncastTypeKey = DowncastTypeKey::new("steel:recipe_data/smithing");
49}
50
51impl RecipeData for SmithingRecipe {
52 fn properties(&self) -> Option<&RecipeProperties> {
53 Some(self.properties())
54 }
55}
56
57#[derive(Debug, Clone)]
58pub struct SmithingRecipeInput {
59 pub template: ItemStack,
60 pub base: ItemStack,
61 pub addition: ItemStack,
62}
63
64impl SmithingRecipeInput {
65 #[must_use]
66 pub const fn new(template: ItemStack, base: ItemStack, addition: ItemStack) -> Self {
67 Self {
68 template,
69 base,
70 addition,
71 }
72 }
73}
74
75unsafe impl DowncastType for SmithingRecipeInput {
77 const TYPE_KEY: DowncastTypeKey = DowncastTypeKey::new("steel:recipe_input/smithing");
78}
79
80impl RecipeInput for SmithingRecipeInput {
81 fn is_empty(&self) -> bool {
82 self.template.is_empty() && self.base.is_empty() && self.addition.is_empty()
83 }
84}
85
86impl RecipeMatches<SmithingRecipeInput> for SmithingRecipe {
87 fn matches(&self, input: &SmithingRecipeInput) -> bool {
88 let (template, base, addition) = match self {
89 Self::Transform(recipe) => (
90 recipe.template.as_ref(),
91 &recipe.base,
92 recipe.addition.as_ref(),
93 ),
94 Self::Trim(recipe) => (Some(&recipe.template), &recipe.base, Some(&recipe.addition)),
95 };
96 optional_ingredient_matches(template, &input.template)
97 && base.test(&input.base)
98 && optional_ingredient_matches(addition, &input.addition)
99 }
100}
101
102fn optional_ingredient_matches(ingredient: Option<&Ingredient>, stack: &ItemStack) -> bool {
103 match ingredient {
104 Some(ingredient) => ingredient.test(stack),
105 None => stack.is_empty(),
106 }
107}