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 StartupGrant {
326 pub id: String,
327 pub items: Vec<String>,
328 pub book: Option<String>,
329 pub command: Option<String>,
330}
331
332impl StartupGrant {
333 pub fn new(id: impl Into<String>) -> Self {
334 Self { id: id.into(), items: Vec::new(), book: None, command: None }
335 }
336
337 pub fn item(mut self, item_id: impl Into<String>) -> Self {
338 self.items.push(item_id.into());
339 self
340 }
341
342 pub fn book(mut self, book: impl Into<String>) -> Self {
343 self.book = Some(book.into());
344 self
345 }
346
347 pub fn command(mut self, cmd: impl Into<String>) -> Self {
348 self.command = Some(cmd.into());
349 self
350 }
351
352 pub fn to_json(&self) -> String {
353 let items: Vec<String> = self.items.iter().map(|i| format!("{{\"item\":\"{}\"}}", i)).collect();
354 let mut entries = String::new();
355 if !items.is_empty() {
356 entries.push_str(&format!("[{}]", items.join(",")));
357 }
358 if let Some(book) = &self.book {
359 if !entries.is_empty() {
360 entries.push(',');
361 }
362 let book_entry = format!(
363 "{{\"type\":\"item\",\"name\":\"minecraft:written_book\",\"functions\":[{{\"function\":\"set_nbt\",\"tag\":\"{{yog_book:\\\"{}\\\"}}\"}}]}}",
364 book
365 );
366 entries.push_str(&book_entry);
367 }
368 if let Some(cmd) = &self.command {
369 if !entries.is_empty() {
370 entries.push(',');
371 }
372 entries.push_str(&format!(
373 "{{\"type\":\"minecraft:command\",\"command\":\"{}\"}}",
374 cmd.replace('"', "\\\"")
375 ));
376 }
377 format!(
378 "{{\"type\":\"yog:startup_grant\",\"entries\":{},\"id\":\"{}\"}}",
379 if entries.is_empty() { "[]".to_string() } else { entries },
380 self.id
381 )
382 }
383}
384
385#[derive(Debug, Clone)]
387pub struct AdvancementReward {
388 pub id: String,
389 pub item: String,
391 pub nbt: Option<String>,
393 pub book: Option<String>,
395}
396
397impl AdvancementReward {
398 pub fn new(id: impl Into<String>) -> Self {
399 Self { id: id.into(), item: "minecraft:written_book".into(), nbt: None, book: None }
400 }
401
402 pub fn item(mut self, item: impl Into<String>) -> Self {
403 self.item = item.into();
404 self
405 }
406
407 pub fn nbt(mut self, nbt: impl Into<String>) -> Self {
408 self.nbt = Some(nbt.into());
409 self
410 }
411
412 pub fn book(mut self, book: impl Into<String>) -> Self {
413 let book_str: String = book.into();
414 self.book = Some(book_str.clone());
415 self.nbt = Some(format!("{{yog_book:\"{}\",title:\"Yog Book\",author:\"Yog\"}}", book_str));
416 self
417 }
418
419 pub fn to_json(&self) -> String {
420 let nbt_part = self.nbt.as_ref().map(|n| format!("{{\"function\":\"set_nbt\",\"tag\":{}}}", n));
421 let entries = if let Some(nbt_part) = nbt_part {
422 format!("[{{\"type\":\"item\",\"name\":\"{}\",\"functions\":[{}]}}]", self.item, nbt_part)
423 } else {
424 format!("[{{\"type\":\"item\",\"name\":\"{}\"}}]", self.item)
425 };
426 format!(
427 "{{\"type\":\"advancement_reward\",\"pools\":[{{\"rolls\":1,\"entries\":{}}}]}}",
428 entries
429 )
430 }
431}
432
433#[derive(Debug, Clone)]
437pub struct BlockDef {
438 pub id: String,
439 pub hardness: f32,
440 pub resistance: f32,
441 pub name: Option<String>,
442 pub shape: Option<[f32; 6]>,
445 pub light_level: u8,
447 pub sound: Option<String>,
451 pub requires_tool: bool,
453 pub no_collision: bool,
455 pub slipperiness: f32,
457}
458
459impl BlockDef {
460 pub fn new(id: impl Into<String>) -> Self {
461 Self {
462 id: id.into(),
463 hardness: 1.5,
464 resistance: 6.0,
465 name: None,
466 shape: None,
467 light_level: 0,
468 sound: None,
469 requires_tool: false,
470 no_collision: false,
471 slipperiness: 0.0,
472 }
473 }
474
475 pub fn strength(mut self, hardness: f32, resistance: f32) -> Self {
477 self.hardness = hardness;
478 self.resistance = resistance;
479 self
480 }
481
482 pub fn name(mut self, name: impl Into<String>) -> Self {
484 self.name = Some(name.into());
485 self
486 }
487
488 pub fn shape(mut self, x1: f32, y1: f32, z1: f32, x2: f32, y2: f32, z2: f32) -> Self {
490 self.shape = Some([x1, y1, z1, x2, y2, z2]);
491 self
492 }
493
494 pub fn light_level(mut self, level: u8) -> Self {
496 self.light_level = level.min(15);
497 self
498 }
499
500 pub fn sound(mut self, group: impl Into<String>) -> Self {
503 self.sound = Some(group.into());
504 self
505 }
506
507 pub fn requires_tool(mut self) -> Self {
509 self.requires_tool = true;
510 self
511 }
512
513 pub fn no_collision(mut self) -> Self {
515 self.no_collision = true;
516 self
517 }
518
519 pub fn slipperiness(mut self, value: f32) -> Self {
521 self.slipperiness = value;
522 self
523 }
524}