1#[derive(Debug, Clone)]
20pub struct FoodDef {
21 pub nutrition: u32,
23 pub saturation: f32,
25 pub can_always_eat: bool,
27}
28
29impl FoodDef {
30 pub fn new(nutrition: u32, saturation: f32) -> Self {
31 Self { nutrition, saturation, can_always_eat: false }
32 }
33
34 pub fn can_always_eat(mut self) -> Self {
35 self.can_always_eat = true;
36 self
37 }
38}
39
40#[derive(Debug, Clone)]
42pub struct ItemDef {
43 pub id: String,
44 pub max_stack: u8,
45 pub name: Option<String>,
46 pub tooltip: Option<String>,
47 pub max_damage: u32,
49 pub fire_resistant: bool,
51 pub fuel_ticks: u32,
53 pub food: Option<FoodDef>,
55}
56
57impl ItemDef {
58 pub fn new(id: impl Into<String>) -> Self {
59 Self {
60 id: id.into(),
61 max_stack: 64,
62 name: None,
63 tooltip: None,
64 max_damage: 0,
65 fire_resistant: false,
66 fuel_ticks: 0,
67 food: None,
68 }
69 }
70
71 pub fn max_stack(mut self, n: u8) -> Self {
73 self.max_stack = n;
74 self
75 }
76
77 pub fn name(mut self, name: impl Into<String>) -> Self {
79 self.name = Some(name.into());
80 self
81 }
82
83 pub fn tooltip(mut self, tooltip: impl Into<String>) -> Self {
85 self.tooltip = Some(tooltip.into());
86 self
87 }
88
89 pub fn max_damage(mut self, durability: u32) -> Self {
91 self.max_damage = durability;
92 self
93 }
94
95 pub fn fire_resistant(mut self) -> Self {
97 self.fire_resistant = true;
98 self
99 }
100
101 pub fn fuel(mut self, ticks: u32) -> Self {
103 self.fuel_ticks = ticks;
104 self
105 }
106
107 pub fn food(mut self, food: FoodDef) -> Self {
109 self.food = Some(food);
110 self
111 }
112}
113
114#[derive(Debug, Clone)]
125pub struct ShapedRecipe {
126 pub id: String,
127 pub output: String,
128 pub count: u32,
129 rows: Vec<String>,
130 keys: Vec<(char, String)>,
131}
132
133impl ShapedRecipe {
134 pub fn new(id: impl Into<String>, output: impl Into<String>, count: u32) -> Self {
135 Self { id: id.into(), output: output.into(), count, rows: Vec::new(), keys: Vec::new() }
136 }
137
138 pub fn row(mut self, pattern: impl Into<String>) -> Self {
139 self.rows.push(pattern.into());
140 self
141 }
142
143 pub fn key(mut self, symbol: char, item_id: impl Into<String>) -> Self {
144 self.keys.push((symbol, item_id.into()));
145 self
146 }
147
148 pub fn to_json(&self) -> String {
150 let pattern: String = self.rows.iter()
151 .map(|r| format!("\"{}\"", r))
152 .collect::<Vec<_>>()
153 .join(",");
154 let keys: String = self.keys.iter()
155 .map(|(ch, item)| format!("\"{}\":{{\"item\":\"{}\"}}", ch, item))
156 .collect::<Vec<_>>()
157 .join(",");
158 format!(
159 "{{\"type\":\"minecraft:crafting_shaped\",\"pattern\":[{}],\"key\":{{{}}},\"result\":{{\"item\":\"{}\",\"count\":{}}}}}",
160 pattern, keys, self.output, self.count
161 )
162 }
163
164 pub fn ns_name(&self) -> (&str, &str) {
166 self.id.split_once(':').unwrap_or(("minecraft", &self.id))
167 }
168}
169
170#[derive(Debug, Clone)]
172pub struct ShapelessRecipe {
173 pub id: String,
174 pub output: String,
175 pub count: u32,
176 pub ingredients: Vec<String>,
177}
178
179impl ShapelessRecipe {
180 pub fn new(id: impl Into<String>, output: impl Into<String>, count: u32) -> Self {
181 Self { id: id.into(), output: output.into(), count, ingredients: Vec::new() }
182 }
183
184 pub fn ingredient(mut self, item_id: impl Into<String>) -> Self {
185 self.ingredients.push(item_id.into());
186 self
187 }
188
189 pub fn to_json(&self) -> String {
190 let ingr: String = self.ingredients.iter()
191 .map(|i| format!("{{\"item\":\"{}\"}}", i))
192 .collect::<Vec<_>>()
193 .join(",");
194 format!(
195 "{{\"type\":\"minecraft:crafting_shapeless\",\"ingredients\":[{}],\"result\":{{\"item\":\"{}\",\"count\":{}}}}}",
196 ingr, self.output, self.count
197 )
198 }
199
200 pub fn ns_name(&self) -> (&str, &str) {
201 self.id.split_once(':').unwrap_or(("minecraft", &self.id))
202 }
203}
204
205#[derive(Debug, Clone)]
207pub struct FurnaceRecipe {
208 pub id: String,
209 pub input: String,
210 pub output: String,
211 pub count: u32,
212 pub experience: f32,
213 pub cook_time: u32,
214}
215
216impl FurnaceRecipe {
217 pub fn new(
218 id: impl Into<String>,
219 input: impl Into<String>,
220 output: impl Into<String>,
221 count: u32,
222 ) -> Self {
223 Self { id: id.into(), input: input.into(), output: output.into(), count, experience: 0.1, cook_time: 200 }
224 }
225
226 pub fn experience(mut self, xp: f32) -> Self {
227 self.experience = xp;
228 self
229 }
230
231 pub fn cook_time(mut self, ticks: u32) -> Self {
233 self.cook_time = ticks;
234 self
235 }
236
237 pub fn to_json(&self) -> String {
238 format!(
239 "{{\"type\":\"minecraft:smelting\",\"ingredient\":{{\"item\":\"{}\"}},\"result\":\"{}\",\"experience\":{},\"cookingtime\":{}}}",
240 self.input, self.output, self.experience, self.cook_time
241 )
242 }
243
244 pub fn ns_name(&self) -> (&str, &str) {
245 self.id.split_once(':').unwrap_or(("minecraft", &self.id))
246 }
247}
248
249#[derive(Debug, Clone)]
254pub struct BookRecipe {
255 pub id: String,
256 pub book: String,
257 pub ingredients: Vec<String>,
258}
259
260impl BookRecipe {
261 pub fn new(id: impl Into<String>, book: impl Into<String>) -> Self {
262 Self { id: id.into(), book: book.into(), ingredients: Vec::new() }
263 }
264
265 pub fn ingredient(mut self, item_id: impl Into<String>) -> Self {
266 self.ingredients.push(item_id.into());
267 self
268 }
269
270 pub fn to_json(&self) -> String {
271 let ingr: String = self.ingredients.iter()
272 .map(|i| format!("{{\"item\":\"{}\"}}", i))
273 .collect::<Vec<_>>()
274 .join(",");
275 format!(
276 "{{\"type\":\"yog:crafting_book\",\"ingredients\":[{}],\"book\":\"{}\"}}",
277 ingr, self.book
278 )
279 }
280
281 pub fn ns_name(&self) -> (&str, &str) {
282 self.id.split_once(':').unwrap_or(("yog", &self.id))
283 }
284}
285
286#[derive(Debug, Clone)]
290pub struct ItemModifier {
291 pub id: String,
292 pub function: String,
294 pub parameters: std::collections::HashMap<String, String>,
296}
297
298impl ItemModifier {
299 pub fn new(id: impl Into<String>, function: impl Into<String>) -> Self {
300 Self { id: id.into(), function: function.into(), parameters: std::collections::HashMap::new() }
301 }
302
303 pub fn param(mut self, key: impl Into<String>, value: impl Into<String>) -> Self {
304 self.parameters.insert(key.into(), value.into());
305 self
306 }
307
308 pub fn to_json(&self) -> String {
309 let params: String = self.parameters.iter()
310 .map(|(k, v)| format!("\"{}\":{}", k, v))
311 .collect::<Vec<_>>()
312 .join(",");
313 format!(
314 "{{\"function\":\"{}\",{}}}",
315 self.function, if params.is_empty() { String::new() } else { params }
316 )
317 }
318}
319
320#[derive(Debug, Clone)]
325pub struct AdvancementReward {
326 pub id: String,
327 pub item: String,
329 pub nbt: Option<String>,
331 pub book: Option<String>,
333}
334
335impl AdvancementReward {
336 pub fn new(id: impl Into<String>) -> Self {
337 Self { id: id.into(), item: "minecraft:written_book".into(), nbt: None, book: None }
338 }
339
340 pub fn item(mut self, item: impl Into<String>) -> Self {
341 self.item = item.into();
342 self
343 }
344
345 pub fn nbt(mut self, nbt: impl Into<String>) -> Self {
346 self.nbt = Some(nbt.into());
347 self
348 }
349
350 pub fn book(mut self, book: impl Into<String>) -> Self {
351 let book_str: String = book.into();
352 self.book = Some(book_str.clone());
353 self.nbt = Some(format!("{{yog_book:\"{}\",title:\"Yog Book\",author:\"Yog\"}}", book_str));
354 self
355 }
356
357 pub fn to_json(&self) -> String {
358 let nbt_part = self.nbt.as_ref().map(|n| format!("{{\"function\":\"set_nbt\",\"tag\":{}}}", n));
359 let entries = if let Some(nbt_part) = nbt_part {
360 format!("[{{\"type\":\"item\",\"name\":\"{}\",\"functions\":[{}]}}]", self.item, nbt_part)
361 } else {
362 format!("[{{\"type\":\"item\",\"name\":\"{}\"}}]", self.item)
363 };
364 format!(
365 "{{\"type\":\"advancement_reward\",\"pools\":[{{\"rolls\":1,\"entries\":{}}}]}}",
366 entries
367 )
368 }
369}
370
371#[derive(Debug, Clone)]
375pub struct BlockDef {
376 pub id: String,
377 pub hardness: f32,
378 pub resistance: f32,
379 pub name: Option<String>,
380 pub shape: Option<[f32; 6]>,
383 pub light_level: u8,
385 pub sound: Option<String>,
389 pub requires_tool: bool,
391 pub no_collision: bool,
393 pub slipperiness: f32,
395}
396
397impl BlockDef {
398 pub fn new(id: impl Into<String>) -> Self {
399 Self {
400 id: id.into(),
401 hardness: 1.5,
402 resistance: 6.0,
403 name: None,
404 shape: None,
405 light_level: 0,
406 sound: None,
407 requires_tool: false,
408 no_collision: false,
409 slipperiness: 0.0,
410 }
411 }
412
413 pub fn strength(mut self, hardness: f32, resistance: f32) -> Self {
415 self.hardness = hardness;
416 self.resistance = resistance;
417 self
418 }
419
420 pub fn name(mut self, name: impl Into<String>) -> Self {
422 self.name = Some(name.into());
423 self
424 }
425
426 pub fn shape(mut self, x1: f32, y1: f32, z1: f32, x2: f32, y2: f32, z2: f32) -> Self {
428 self.shape = Some([x1, y1, z1, x2, y2, z2]);
429 self
430 }
431
432 pub fn light_level(mut self, level: u8) -> Self {
434 self.light_level = level.min(15);
435 self
436 }
437
438 pub fn sound(mut self, group: impl Into<String>) -> Self {
441 self.sound = Some(group.into());
442 self
443 }
444
445 pub fn requires_tool(mut self) -> Self {
447 self.requires_tool = true;
448 self
449 }
450
451 pub fn no_collision(mut self) -> Self {
453 self.no_collision = true;
454 self
455 }
456
457 pub fn slipperiness(mut self, value: f32) -> Self {
459 self.slipperiness = value;
460 self
461 }
462}