mcdata_rs/
structs.rs

1use serde::Deserialize;
2use std::collections::HashMap;
3
4// Structs related to version information from protocolVersions.json.
5
6#[derive(Deserialize, Debug, Clone, PartialEq, Eq, Hash)]
7#[serde(rename_all = "camelCase")]
8pub struct ProtocolVersionInfo {
9    pub minecraft_version: String,
10    pub version: i32,              // Protocol version number
11    pub data_version: Option<i32>, // Data version number (used for comparisons)
12    pub uses_netty: bool,
13    pub major_version: String,
14    #[serde(default = "default_release_type")]
15    pub release_type: String, // e.g., "release", "snapshot"
16}
17
18fn default_release_type() -> String {
19    "release".to_string()
20}
21
22#[derive(Deserialize, Debug, Clone)]
23#[serde(rename_all = "camelCase")]
24pub struct VersionInfo {
25    pub version: i32,
26    pub minecraft_version: String,
27    pub major_version: String,
28    #[serde(default = "default_release_type")]
29    pub release_type: String,
30}
31
32// Structs representing various game data elements loaded from JSON files.
33
34#[derive(Deserialize, Debug, Clone)]
35#[serde(rename_all = "camelCase")]
36pub struct Block {
37    pub id: u32,
38    pub name: String,
39    pub display_name: String,
40    pub hardness: Option<f32>,
41    pub resistance: f32,
42    pub stack_size: u32,
43    pub diggable: bool,
44    pub bounding_box: String, // Typically "block" or "empty"
45    pub material: Option<String>,
46    #[serde(default)]
47    pub harvest_tools: HashMap<String, bool>,
48    #[serde(default)]
49    pub variations: Option<Vec<BlockVariation>>,
50    #[serde(default)]
51    pub drops: Vec<BlockDrop>, // Handles simple ID drops or complex drop definitions
52    #[serde(default)]
53    pub emit_light: u8,
54    #[serde(default)]
55    pub filter_light: u8,
56    #[serde(default)]
57    pub transparent: bool,
58    #[serde(default)]
59    pub states: Vec<BlockStateDefinition>, // Block states (relevant for 1.13+)
60
61    // State IDs might be calculated during indexing if not present in the source JSON.
62    #[serde(default = "default_state_id")]
63    pub min_state_id: u32,
64    #[serde(default = "default_state_id")]
65    pub max_state_id: u32,
66    #[serde(default = "default_state_id")]
67    pub default_state: u32,
68
69    // Internal map added during indexing for quick state ID lookup.
70    #[serde(skip)]
71    pub state_id_map: Option<HashMap<u32, Block>>,
72}
73
74// Default value for state IDs before calculation.
75fn default_state_id() -> u32 {
76    0
77}
78
79#[derive(Deserialize, Debug, Clone)]
80#[serde(rename_all = "camelCase")]
81pub struct BlockVariation {
82    pub metadata: u32,
83    pub display_name: String,
84    pub description: Option<String>,
85}
86
87#[derive(Deserialize, Debug, Clone)]
88#[serde(rename_all = "camelCase")]
89pub struct BlockStateDefinition {
90    pub name: String,
91    #[serde(rename = "type")]
92    pub state_type: String, // e.g., "bool", "enum", "int"
93    pub num_values: Option<u32>,
94    #[serde(default)]
95    pub values: Vec<String>,
96}
97
98// Structs for handling block drops, especially in older formats (pre-1.13)
99// where drops could be simple item IDs or more complex objects.
100
101#[derive(Deserialize, Debug, Clone)]
102pub struct DropItem {
103    pub id: u32,
104    pub metadata: u32,
105}
106
107#[derive(Deserialize, Debug, Clone)]
108#[serde(untagged)] // Allows deserializing as either a simple u32 or a DropItem object.
109pub enum DropType {
110    Id(u32),
111    Item(DropItem),
112}
113
114#[derive(Deserialize, Debug, Clone)]
115#[serde(rename_all = "camelCase")]
116pub struct DropElement {
117    pub drop: DropType, // The actual item dropped.
118    pub min_count: Option<f32>,
119    pub max_count: Option<f32>,
120}
121
122#[derive(Deserialize, Debug, Clone)]
123#[serde(untagged)] // Allows deserializing as either a simple u32 ID or a DropElement object.
124pub enum BlockDrop {
125    Id(u32),
126    Element(DropElement),
127}
128
129#[derive(Deserialize, Debug, Clone)]
130#[serde(rename_all = "camelCase")]
131pub struct Item {
132    pub id: u32,
133    pub name: String,
134    pub display_name: String,
135    pub stack_size: u32,
136    #[serde(default)]
137    pub enchant_categories: Option<Vec<String>>,
138    #[serde(default)]
139    pub repair_with: Option<Vec<String>>,
140    #[serde(default)]
141    pub max_durability: Option<u32>,
142    #[serde(default)]
143    pub variations: Option<Vec<ItemVariation>>, // Relevant for older versions with metadata variations.
144}
145
146#[derive(Deserialize, Debug, Clone)]
147#[serde(rename_all = "camelCase")]
148pub struct ItemVariation {
149    pub metadata: u32,
150    pub display_name: String,
151}
152
153#[derive(Deserialize, Debug, Clone)]
154#[serde(rename_all = "camelCase")]
155pub struct Biome {
156    pub id: u32,
157    pub name: String,
158    pub category: String,
159    pub temperature: f32,
160    pub precipitation: Option<String>, // e.g., "none", "rain", "snow"
161    pub dimension: String,             // e.g., "overworld", "nether", "end"
162    pub display_name: String,
163    pub color: i32,
164    pub rainfall: Option<f32>,
165    #[serde(default)]
166    pub depth: Option<f32>,
167    #[serde(default)]
168    pub has_precipitation: Option<bool>,
169}
170
171#[derive(Deserialize, Debug, Clone)]
172#[serde(rename_all = "camelCase")]
173pub struct Effect {
174    pub id: u32,
175    pub name: String,
176    pub display_name: String,
177    #[serde(rename = "type")]
178    pub effect_type: String, // Typically "good" or "bad"
179}
180
181#[derive(Deserialize, Debug, Clone)]
182#[serde(rename_all = "camelCase")]
183pub struct Entity {
184    pub id: u32,
185    pub internal_id: Option<u32>, // Used in some older versions.
186    pub name: String,
187    pub display_name: String,
188    #[serde(rename = "type")]
189    pub entity_type: String, // e.g., "mob", "object", "projectile"
190    pub width: Option<f32>,
191    pub height: Option<f32>,
192    pub category: Option<String>,
193    #[serde(default)]
194    pub metadata_keys: Vec<String>, // Relevant for 1.20.2+
195}
196
197// Structs for feature checking from features.json.
198
199#[derive(Deserialize, Debug, Clone)]
200#[serde(rename_all = "camelCase")]
201pub struct Feature {
202    pub name: String,
203    pub description: Option<String>,
204    #[serde(default)]
205    pub values: Vec<FeatureValue>, // Prioritized if present.
206    pub version: Option<String>, // Used if `values` is empty.
207    #[serde(default)]
208    pub versions: Vec<String>, // Used if `values` and `version` are empty; expected [min, max].
209}
210
211#[derive(Deserialize, Debug, Clone)]
212#[serde(rename_all = "camelCase")]
213pub struct FeatureValue {
214    pub value: serde_json::Value, // The actual feature value (bool, string, number).
215    pub version: Option<String>,  // Single version applicability.
216    #[serde(default)]
217    pub versions: Vec<String>, // Version range applicability [min, max].
218}
219
220// Struct for dataPaths.json, mapping versions and keys to file paths.
221#[derive(Deserialize, Debug, Clone)]
222pub struct DataPaths {
223    // Major Version -> Data Key -> Path Suffix
224    pub pc: HashMap<String, HashMap<String, String>>,
225    pub bedrock: HashMap<String, HashMap<String, String>>,
226}
227
228// Other miscellaneous data structs.
229
230#[derive(Deserialize, Debug, Clone)]
231#[serde(rename_all = "camelCase")]
232pub struct Sound {
233    pub id: u32,
234    pub name: String,
235}
236
237#[derive(Deserialize, Debug, Clone)]
238#[serde(untagged)] // Allows deserializing as a single index or multiple indices.
239pub enum BlockShapeRef {
240    Single(u32),        // Single shape index for all states.
241    Multiple(Vec<u32>), // Shape indices per state/metadata.
242}
243
244#[derive(Deserialize, Debug, Clone)]
245#[serde(rename_all = "camelCase")]
246pub struct BlockCollisionShapes {
247    // Maps block name to its shape reference (single index or list of indices).
248    pub blocks: HashMap<String, BlockShapeRef>,
249    // Maps shape index (as string key) to an array of bounding boxes ([x1, y1, z1, x2, y2, z2]).
250    pub shapes: HashMap<String, Vec<[f64; 6]>>,
251}
252
253#[derive(Deserialize, Debug, Clone)]
254#[serde(rename_all = "camelCase")]
255pub struct Particle {
256    pub id: u32,
257    pub name: String,
258}
259
260#[derive(Deserialize, Debug, Clone)]
261#[serde(rename_all = "camelCase")]
262pub struct Attribute {
263    pub name: String,
264    pub resource: String, // Namespaced key
265    #[serde(default)]
266    pub default: f64,
267    pub min: f64,
268    pub max: f64,
269}
270
271#[derive(Deserialize, Debug, Clone)]
272#[serde(rename_all = "camelCase")]
273pub struct Instrument {
274    pub id: u32,
275    pub name: String,
276}
277
278#[derive(Deserialize, Debug, Clone)]
279#[serde(rename_all = "camelCase")]
280pub struct BlockLoot {
281    pub block: String, // Block name
282    pub drops: Vec<BlockLootDrop>,
283}
284
285#[derive(Deserialize, Debug, Clone)]
286#[serde(rename_all = "camelCase")]
287pub struct BlockLootDrop {
288    pub item: String, // Item name
289    #[serde(default = "default_drop_chance")]
290    pub drop_chance: f32,
291    #[serde(default = "default_stack_size_range")]
292    pub stack_size_range: Vec<Option<i32>>, // Range [min] or [min, max]
293    #[serde(default)]
294    pub silk_touch: Option<bool>,
295    #[serde(default)]
296    pub no_silk_touch: Option<bool>,
297    #[serde(default)]
298    pub block_age: Option<i32>,
299}
300
301fn default_drop_chance() -> f32 {
302    1.0
303}
304
305// Default stack size range is [1].
306fn default_stack_size_range() -> Vec<Option<i32>> {
307    vec![Some(1)]
308}
309
310#[derive(Deserialize, Debug, Clone)]
311#[serde(rename_all = "camelCase")]
312pub struct Window {
313    pub id: String, // Can be numeric string or namespaced string (e.g., "minecraft:chest")
314    pub name: String,
315    #[serde(default)]
316    pub slots: Vec<WindowSlot>,
317    #[serde(default)]
318    pub opened_with: Vec<WindowOpenedWith>,
319    #[serde(default)]
320    pub properties: Vec<String>,
321}
322
323#[derive(Deserialize, Debug, Clone)]
324#[serde(rename_all = "camelCase")]
325pub struct WindowSlot {
326    pub name: String,
327    pub index: u32,
328    pub size: Option<u32>,
329}
330
331#[derive(Deserialize, Debug, Clone)]
332#[serde(rename_all = "camelCase")]
333pub struct WindowOpenedWith {
334    #[serde(rename = "type")]
335    pub opener_type: String, // e.g., "block", "entity"
336    pub id: u32,
337}
338
339#[derive(Deserialize, Debug, Clone)]
340#[serde(rename_all = "camelCase")]
341pub struct EntityLoot {
342    pub entity: String, // Entity name
343    pub drops: Vec<EntityLootDrop>,
344}
345
346#[derive(Deserialize, Debug, Clone)]
347#[serde(rename_all = "camelCase")]
348pub struct EntityLootDrop {
349    pub item: String, // Item name
350    #[serde(default = "default_drop_chance")]
351    pub drop_chance: f32,
352    #[serde(default = "default_entity_stack_size_range")]
353    pub stack_size_range: Vec<u32>, // Range [min] or [min, max]
354    #[serde(default)]
355    pub player_kill: Option<bool>,
356}
357
358// Default stack size range is [1].
359fn default_entity_stack_size_range() -> Vec<u32> {
360    vec![1]
361}
362
363#[derive(Deserialize, Debug, Clone)]
364#[serde(rename_all = "camelCase")]
365pub struct Food {
366    pub id: u32,
367    pub name: String,
368    pub display_name: String,
369    pub stack_size: u32,
370    pub food_points: f32,
371    pub saturation: f32,
372    pub effective_quality: f32,
373    pub saturation_ratio: f32,
374    #[serde(default)]
375    pub variations: Option<Vec<ItemVariation>>, // Relevant for older versions.
376}
377
378#[derive(Deserialize, Debug, Clone)]
379#[serde(rename_all = "camelCase")]
380pub struct Enchantment {
381    pub id: u32,
382    pub name: String,
383    pub display_name: String,
384    #[serde(rename = "maxLevel")]
385    pub max_level: u32,
386    #[serde(default)]
387    pub min_cost: EnchantmentCost,
388    #[serde(default)]
389    pub max_cost: EnchantmentCost,
390    #[serde(default)]
391    pub treasure_only: bool,
392    #[serde(default)]
393    pub curse: bool,
394    #[serde(default)]
395    pub exclude: Vec<String>, // Names of mutually exclusive enchantments
396    pub category: String, // e.g., "weapon", "armor"
397    pub weight: u32,      // Rarity weight
398    #[serde(default)]
399    pub tradeable: bool,
400    #[serde(default)]
401    pub discoverable: bool,
402}
403
404#[derive(Deserialize, Debug, Clone, Default)]
405#[serde(rename_all = "camelCase")]
406pub struct EnchantmentCost {
407    // Cost calculation parameters: cost = a * level + b
408    pub a: i32,
409    pub b: i32,
410}
411
412#[derive(Deserialize, Debug, Clone)]
413#[serde(rename_all = "camelCase")]
414pub struct MapIcon {
415    pub id: u32,
416    pub name: String,
417    pub appearance: Option<String>,
418    #[serde(default)]
419    pub visible_in_item_frame: bool,
420}
421
422#[derive(Deserialize, Debug, Clone)]
423#[serde(rename_all = "camelCase")]
424pub struct Tints {
425    pub grass: TintData,
426    pub foliage: TintData,
427    pub water: TintData,
428    pub redstone: TintData,
429    pub constant: TintData,
430}
431
432#[derive(Deserialize, Debug, Clone)]
433#[serde(rename_all = "camelCase")]
434pub struct TintData {
435    #[serde(default)]
436    pub default: Option<i32>, // Default color value
437    pub data: Vec<TintDatum>, // List of specific tint rules
438}
439
440#[derive(Deserialize, Debug, Clone)]
441#[serde(rename_all = "camelCase")]
442pub struct TintDatum {
443    // Keys can be biome names (string) or redstone levels (number).
444    pub keys: Vec<serde_json::Value>,
445    pub color: i32, // The tint color associated with these keys.
446}
447
448#[derive(Deserialize, Debug, Clone)]
449#[serde(rename_all = "camelCase")]
450pub struct Legacy {
451    // Maps legacy numeric IDs (as strings) to modern namespaced IDs.
452    pub blocks: HashMap<String, String>,
453    pub items: HashMap<String, String>,
454}
455
456// Note: Commands and Materials are often loaded as raw `serde_json::Value`
457// due to their high variability across versions.