Skip to main content

steel_registry/recipe/
smithing.rs

1//! Passive smithing recipe data and input snapshots.
2
3use 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/// Every vanilla serializer whose operational type is `minecraft:smithing`.
30#[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
46// SAFETY: This Steel-owned key uniquely identifies the unified vanilla smithing data enum.
47unsafe 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
75// SAFETY: This Steel-owned key uniquely identifies a smithing matching snapshot.
76unsafe 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}