steel_registry/recipe/
properties.rs1use rustc_hash::FxHashMap;
4use steel_utils::Identifier;
5
6use super::Ingredient;
7
8#[derive(Debug, Clone, Copy, PartialEq, Eq)]
10pub enum CraftingBookCategory {
11 Building,
12 Redstone,
13 Equipment,
14 Misc,
15}
16
17#[derive(Debug, Clone, Copy, PartialEq, Eq)]
19pub enum CookingBookCategory {
20 Food,
21 Blocks,
22 Misc,
23}
24
25#[derive(Debug, Clone, Copy, PartialEq, Eq)]
31pub enum RecipeBookCategoryKind {
32 Crafting(CraftingBookCategory),
33 Cooking(CookingBookCategory),
34 Stonecutter,
35 Smithing,
36}
37
38#[derive(Debug, Clone, PartialEq, Eq)]
40pub struct RecipeBookProperties {
41 pub category: RecipeBookCategoryKind,
42 pub group: Option<String>,
43 pub show_notification: bool,
44}
45
46#[derive(Debug, Clone)]
48pub struct PlacementInfo {
49 pub ingredients: Vec<Ingredient>,
50 pub slots_to_ingredient: Vec<Option<usize>>,
52}
53
54impl PlacementInfo {
55 #[must_use]
56 pub const fn not_placeable() -> Self {
57 Self {
58 ingredients: Vec::new(),
59 slots_to_ingredient: Vec::new(),
60 }
61 }
62
63 #[must_use]
64 pub fn from_ingredient(ingredient: Ingredient) -> Self {
65 if ingredient.is_empty() {
66 return Self::not_placeable();
67 }
68 Self {
69 ingredients: vec![ingredient],
70 slots_to_ingredient: vec![Some(0)],
71 }
72 }
73
74 #[must_use]
75 pub fn from_optional_ingredients(ingredients: &[Ingredient]) -> Self {
76 let mut present = Vec::with_capacity(ingredients.len());
77 let mut slots = Vec::with_capacity(ingredients.len());
78 for ingredient in ingredients {
79 if ingredient.is_empty() {
80 slots.push(None);
81 } else {
82 slots.push(Some(present.len()));
83 present.push(ingredient.clone());
84 }
85 }
86 Self {
87 ingredients: present,
88 slots_to_ingredient: slots,
89 }
90 }
91
92 #[must_use]
93 pub fn from_ingredients(ingredients: &[Ingredient]) -> Self {
94 if ingredients.iter().any(Ingredient::is_empty) {
95 return Self::not_placeable();
96 }
97 Self {
98 ingredients: ingredients.to_vec(),
99 slots_to_ingredient: (0..ingredients.len()).map(Some).collect(),
100 }
101 }
102
103 #[must_use]
104 pub const fn is_impossible_to_place(&self) -> bool {
105 self.slots_to_ingredient.is_empty()
106 }
107}
108
109#[derive(Debug, Clone)]
111pub struct RecipeProperties {
112 pub special: bool,
113 pub placement: Option<PlacementInfo>,
114 pub recipe_book: Option<RecipeBookProperties>,
115}
116
117impl RecipeProperties {
118 #[must_use]
119 pub const fn special() -> Self {
120 Self {
121 special: true,
122 placement: None,
123 recipe_book: None,
124 }
125 }
126}
127
128#[derive(Debug)]
130pub struct RecipeBookCategory {
131 pub key: Identifier,
132}
133
134pub type RecipeBookCategoryRef = &'static RecipeBookCategory;
135
136pub struct RecipeBookCategoryRegistry {
138 categories: Vec<RecipeBookCategoryRef>,
139 by_key: FxHashMap<Identifier, usize>,
140 allows_registering: bool,
141}
142
143impl RecipeBookCategoryRegistry {
144 #[must_use]
145 pub fn new() -> Self {
146 Self {
147 categories: Vec::new(),
148 by_key: FxHashMap::default(),
149 allows_registering: true,
150 }
151 }
152}
153
154crate::impl_standard_methods!(
155 RecipeBookCategoryRegistry,
156 RecipeBookCategoryRef,
157 categories,
158 by_key,
159 allows_registering,
160 "Cannot register duplicate recipe book category key: {}"
161);
162crate::impl_registry!(
163 RecipeBookCategoryRegistry,
164 RecipeBookCategory,
165 categories,
166 by_key,
167 recipe_book_categories
168);
169
170pub mod vanilla_recipe_book_categories {
172 use super::{RecipeBookCategory, RecipeBookCategoryRegistry};
173 use steel_utils::Identifier;
174
175 macro_rules! category {
176 ($name:ident, $key:literal) => {
177 pub static $name: RecipeBookCategory = RecipeBookCategory {
178 key: Identifier::vanilla_static($key),
179 };
180 };
181 }
182
183 category!(CRAFTING_BUILDING_BLOCKS, "crafting_building_blocks");
184 category!(CRAFTING_REDSTONE, "crafting_redstone");
185 category!(CRAFTING_EQUIPMENT, "crafting_equipment");
186 category!(CRAFTING_MISC, "crafting_misc");
187 category!(FURNACE_FOOD, "furnace_food");
188 category!(FURNACE_BLOCKS, "furnace_blocks");
189 category!(FURNACE_MISC, "furnace_misc");
190 category!(BLAST_FURNACE_BLOCKS, "blast_furnace_blocks");
191 category!(BLAST_FURNACE_MISC, "blast_furnace_misc");
192 category!(SMOKER_FOOD, "smoker_food");
193 category!(STONECUTTER, "stonecutter");
194 category!(SMITHING, "smithing");
195 category!(CAMPFIRE, "campfire");
196
197 pub(crate) fn register(registry: &mut RecipeBookCategoryRegistry) {
198 registry.register(&CRAFTING_BUILDING_BLOCKS);
199 registry.register(&CRAFTING_REDSTONE);
200 registry.register(&CRAFTING_EQUIPMENT);
201 registry.register(&CRAFTING_MISC);
202 registry.register(&FURNACE_FOOD);
203 registry.register(&FURNACE_BLOCKS);
204 registry.register(&FURNACE_MISC);
205 registry.register(&BLAST_FURNACE_BLOCKS);
206 registry.register(&BLAST_FURNACE_MISC);
207 registry.register(&SMOKER_FOOD);
208 registry.register(&STONECUTTER);
209 registry.register(&SMITHING);
210 registry.register(&CAMPFIRE);
211 }
212}