Skip to main content

basalt_api/recipes/
types.rs

1//! Owned recipe data types for plugin interaction.
2//!
3//! These types are the plugin-facing representations of crafting recipes.
4//! They own their data on the heap (unlike the static codegen'd types in
5//! `basalt-recipes::generated`) and are used in event payloads, registry
6//! trait methods, and plugin registration.
7
8use crate::recipes::id::RecipeId;
9
10/// An owned shaped crafting recipe for plugin-registered custom recipes.
11///
12/// Unlike the static [`basalt_recipes::generated::ShapedRecipe`] which uses
13/// `&'static` slices, this type owns its pattern data on the heap.
14/// The `result_count` is `i32` (not `u8`) for flexibility in plugin recipes.
15#[derive(Debug, Clone, PartialEq, Eq)]
16pub struct OwnedShapedRecipe {
17    /// Stable identifier — must be unique across the registry.
18    pub id: RecipeId,
19    /// Grid width (1-3 for standard crafting table recipes).
20    pub width: u8,
21    /// Grid height (1-3 for standard crafting table recipes).
22    pub height: u8,
23    /// Flat grid of ingredient item IDs in row-major order.
24    ///
25    /// Length must equal `width * height`. `None` means the slot must be
26    /// empty; `Some(id)` means the slot requires that item state ID.
27    pub pattern: Vec<Option<i32>>,
28    /// The item state ID of the crafted result.
29    pub result_id: i32,
30    /// How many items are produced per craft.
31    pub result_count: i32,
32}
33
34/// An owned shapeless crafting recipe for plugin-registered custom recipes.
35///
36/// Unlike the static [`basalt_recipes::generated::ShapelessRecipe`] which uses
37/// `&'static` slices, this type owns its ingredient list on the heap.
38/// The `result_count` is `i32` (not `u8`) for flexibility in plugin recipes.
39#[derive(Debug, Clone, PartialEq, Eq)]
40pub struct OwnedShapelessRecipe {
41    /// Stable identifier — must be unique across the registry.
42    pub id: RecipeId,
43    /// Unordered set of required ingredient item state IDs, sorted ascending.
44    ///
45    /// Must be kept sorted for correct matching. Duplicates are allowed.
46    pub ingredients: Vec<i32>,
47    /// The item state ID of the crafted result.
48    pub result_id: i32,
49    /// How many items are produced per craft.
50    pub result_count: i32,
51}
52
53/// A crafting recipe of either shape.
54///
55/// Used by event types and the registry's removal API to surface a recipe
56/// regardless of its underlying shape kind. Plugin handlers match on the
57/// variant when they need shape-specific access.
58#[derive(Debug, Clone, PartialEq, Eq)]
59pub enum Recipe {
60    /// A grid-pattern shaped recipe.
61    Shaped(OwnedShapedRecipe),
62    /// An unordered shapeless recipe.
63    Shapeless(OwnedShapelessRecipe),
64}
65
66impl Recipe {
67    /// Returns the recipe's stable identifier.
68    pub fn id(&self) -> &RecipeId {
69        match self {
70            Self::Shaped(r) => &r.id,
71            Self::Shapeless(r) => &r.id,
72        }
73    }
74
75    /// Returns the item state ID of the crafted result.
76    pub fn result_id(&self) -> i32 {
77        match self {
78            Self::Shaped(r) => r.result_id,
79            Self::Shapeless(r) => r.result_id,
80        }
81    }
82
83    /// Returns how many items are produced per craft.
84    pub fn result_count(&self) -> i32 {
85        match self {
86            Self::Shaped(r) => r.result_count,
87            Self::Shapeless(r) => r.result_count,
88        }
89    }
90}