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}