azalea_inventory/components/
mod.rs

1mod profile;
2
3use core::f64;
4use std::{
5    any::Any,
6    collections::HashMap,
7    io::{self, Cursor},
8    mem::ManuallyDrop,
9};
10
11use azalea_buf::{AzBuf, AzaleaRead, AzaleaWrite, BufReadError};
12use azalea_chat::FormattedText;
13use azalea_core::{
14    checksum::{Checksum, get_checksum},
15    codec_utils::*,
16    filterable::Filterable,
17    position::GlobalPos,
18    registry_holder::RegistryHolder,
19    resource_location::ResourceLocation,
20    sound::CustomSound,
21};
22use azalea_registry::{
23    self as registry, Attribute, Block, DamageKind, DataComponentKind, Enchantment, EntityKind,
24    Holder, HolderSet, Item, MobEffect, Potion, SoundEvent, TrimMaterial, TrimPattern,
25};
26pub use profile::*;
27use serde::{Serialize, ser::SerializeMap};
28use simdnbt::owned::{Nbt, NbtCompound};
29use tracing::trace;
30
31use crate::{ItemStack, item::consume_effect::ConsumeEffect};
32
33pub trait DataComponentTrait:
34    Send + Sync + Any + Clone + Serialize + Into<DataComponentUnion>
35{
36    const KIND: DataComponentKind;
37}
38
39pub trait EncodableDataComponent: Send + Sync + Any {
40    fn encode(&self, buf: &mut Vec<u8>) -> io::Result<()>;
41    fn crc_hash(&self, registries: &RegistryHolder) -> Checksum;
42    // using the Clone trait makes it not be object-safe, so we have our own clone
43    // function instead
44    fn clone(&self) -> Box<dyn EncodableDataComponent>;
45    // same thing here
46    fn eq(&self, other: &dyn EncodableDataComponent) -> bool;
47}
48
49impl<T> EncodableDataComponent for T
50where
51    T: DataComponentTrait + Clone + AzaleaWrite + AzaleaRead + PartialEq,
52{
53    fn encode(&self, buf: &mut Vec<u8>) -> io::Result<()> {
54        self.azalea_write(buf)
55    }
56    fn crc_hash(&self, registries: &RegistryHolder) -> Checksum {
57        get_checksum(self, registries).expect("serializing data components should always succeed")
58    }
59    fn clone(&self) -> Box<dyn EncodableDataComponent> {
60        let cloned = self.clone();
61        Box::new(cloned)
62    }
63    fn eq(&self, other: &dyn EncodableDataComponent) -> bool {
64        let other_any: &dyn Any = other;
65        match other_any.downcast_ref::<T>() {
66            Some(other) => self == other,
67            _ => false,
68        }
69    }
70}
71
72#[macro_export]
73macro_rules! define_data_components {
74    ( $( $x:ident ),* $(,)? ) => {
75        /// A union of all data components.
76        ///
77        /// You probably don't want to use this directly. Consider [`DataComponentPatch`] instead.
78        ///
79        /// This type does not know its own value, and as such every function for it requires the
80        /// `DataComponentKind` to be passed in. Passing the wrong `DataComponentKind` will result
81        /// in undefined behavior. Also, all of the values are `ManuallyDrop`.
82        ///
83        /// [`DataComponentPatch`]: crate::DataComponentPatch
84        #[allow(non_snake_case)]
85        pub union DataComponentUnion {
86            $( $x: ManuallyDrop<$x>, )*
87        }
88        impl DataComponentUnion {
89            /// # Safety
90            ///
91            /// `kind` must be the correct value for this union.
92            pub unsafe fn serialize_entry_as<S: SerializeMap>(
93                &self,
94                serializer: &mut S,
95                kind: DataComponentKind,
96            ) -> Result<(), S::Error> {
97                match kind {
98                    $( DataComponentKind::$x => { unsafe { serializer.serialize_entry(&kind, &*self.$x) } }, )*
99                }
100            }
101            /// # Safety
102            ///
103            /// `kind` must be the correct value for this union.
104            pub unsafe fn drop_as(&mut self, kind: DataComponentKind) {
105                match kind {
106                    $( DataComponentKind::$x => { unsafe { ManuallyDrop::drop(&mut self.$x) } }, )*
107                }
108            }
109            /// # Safety
110            ///
111            /// `kind` must be the correct value for this union.
112            pub unsafe fn as_kind(&self, kind: DataComponentKind) -> &dyn EncodableDataComponent {
113                match kind {
114                    $( DataComponentKind::$x => { unsafe { &**(&self.$x as &ManuallyDrop<dyn EncodableDataComponent>) } }, )*
115                }
116            }
117            pub fn azalea_read_as(
118                kind: registry::DataComponentKind,
119                buf: &mut Cursor<&[u8]>,
120            ) -> Result<Self, BufReadError> {
121                trace!("Reading data component {kind}");
122
123                Ok(match kind {
124                    $( DataComponentKind::$x => {
125                        Self { $x: ManuallyDrop::new($x::azalea_read(buf)?) }
126                    }, )*
127                })
128            }
129            /// # Safety
130            ///
131            /// `kind` must be the correct value for this union.
132            pub unsafe fn azalea_write_as(
133                &self,
134                kind: registry::DataComponentKind,
135                buf: &mut impl std::io::Write,
136            ) -> io::Result<()> {
137                let mut value = Vec::new();
138                match kind {
139                    $( DataComponentKind::$x => unsafe { self.$x.encode(&mut value)? }, )*
140                };
141                buf.write_all(&value)?;
142
143                Ok(())
144            }
145            /// # Safety
146            ///
147            /// `kind` must be the correct value for this union.
148            pub unsafe fn clone_as(
149                &self,
150                kind: registry::DataComponentKind,
151            ) -> Self {
152                match kind {
153                    $( DataComponentKind::$x => {
154                        Self { $x: unsafe { self.$x.clone() } }
155                    }, )*
156                }
157            }
158            /// # Safety
159            ///
160            /// `kind` must be the correct value for this union.
161            pub unsafe fn eq_as(
162                &self,
163                other: &Self,
164                kind: registry::DataComponentKind,
165            ) -> bool {
166                match kind {
167                    $( DataComponentKind::$x => unsafe { self.$x.eq(&other.$x) }, )*
168                }
169            }
170        }
171        $(
172            impl From<$x> for DataComponentUnion {
173                fn from(value: $x) -> Self {
174                    DataComponentUnion { $x: ManuallyDrop::new(value) }
175                }
176            }
177        )*
178
179        $(
180            impl DataComponentTrait for $x {
181                const KIND: DataComponentKind = DataComponentKind::$x;
182            }
183        )*
184    };
185}
186
187// if this is causing a compile-time error, look at DataComponents.java in the
188// decompiled vanilla code to see how to implement new components
189
190// note that this statement is updated by genitemcomponents.py
191define_data_components!(
192    CustomData,
193    MaxStackSize,
194    MaxDamage,
195    Damage,
196    Unbreakable,
197    CustomName,
198    ItemName,
199    ItemModel,
200    Lore,
201    Rarity,
202    Enchantments,
203    CanPlaceOn,
204    CanBreak,
205    AttributeModifiers,
206    CustomModelData,
207    TooltipDisplay,
208    RepairCost,
209    CreativeSlotLock,
210    EnchantmentGlintOverride,
211    IntangibleProjectile,
212    Food,
213    Consumable,
214    UseRemainder,
215    UseCooldown,
216    DamageResistant,
217    Tool,
218    Weapon,
219    Enchantable,
220    Equippable,
221    Repairable,
222    Glider,
223    TooltipStyle,
224    DeathProtection,
225    BlocksAttacks,
226    StoredEnchantments,
227    DyedColor,
228    MapColor,
229    MapId,
230    MapDecorations,
231    MapPostProcessing,
232    ChargedProjectiles,
233    BundleContents,
234    PotionContents,
235    PotionDurationScale,
236    SuspiciousStewEffects,
237    WritableBookContent,
238    WrittenBookContent,
239    Trim,
240    DebugStickState,
241    EntityData,
242    BucketEntityData,
243    BlockEntityData,
244    Instrument,
245    ProvidesTrimMaterial,
246    OminousBottleAmplifier,
247    JukeboxPlayable,
248    ProvidesBannerPatterns,
249    Recipes,
250    LodestoneTracker,
251    FireworkExplosion,
252    Fireworks,
253    Profile,
254    NoteBlockSound,
255    BannerPatterns,
256    BaseColor,
257    PotDecorations,
258    Container,
259    BlockState,
260    Bees,
261    Lock,
262    ContainerLoot,
263    BreakSound,
264    VillagerVariant,
265    WolfVariant,
266    WolfSoundVariant,
267    WolfCollar,
268    FoxVariant,
269    SalmonSize,
270    ParrotVariant,
271    TropicalFishPattern,
272    TropicalFishBaseColor,
273    TropicalFishPatternColor,
274    MooshroomVariant,
275    RabbitVariant,
276    PigVariant,
277    CowVariant,
278    ChickenVariant,
279    FrogVariant,
280    HorseVariant,
281    PaintingVariant,
282    LlamaVariant,
283    AxolotlVariant,
284    CatVariant,
285    CatCollar,
286    SheepColor,
287    ShulkerColor,
288);
289
290#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)]
291#[serde(transparent)]
292pub struct CustomData {
293    pub nbt: Nbt,
294}
295
296#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)]
297#[serde(transparent)]
298pub struct MaxStackSize {
299    #[var]
300    pub count: i32,
301}
302
303#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)]
304#[serde(transparent)]
305pub struct MaxDamage {
306    #[var]
307    pub amount: i32,
308}
309
310#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)]
311#[serde(transparent)]
312pub struct Damage {
313    #[var]
314    pub amount: i32,
315}
316
317#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)]
318pub struct Unbreakable;
319
320#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)]
321#[serde(transparent)]
322pub struct CustomName {
323    pub name: FormattedText,
324}
325
326#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)]
327#[serde(transparent)]
328pub struct ItemName {
329    pub name: FormattedText,
330}
331
332#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)]
333#[serde(transparent)]
334pub struct Lore {
335    pub lines: Vec<FormattedText>,
336    // vanilla also has styled_lines here but it doesn't appear to be used for the protocol
337}
338
339#[derive(Clone, Copy, PartialEq, AzBuf, Debug, Serialize)]
340#[serde(rename_all = "snake_case")]
341pub enum Rarity {
342    Common,
343    Uncommon,
344    Rare,
345    Epic,
346}
347
348#[derive(Clone, PartialEq, AzBuf, Serialize)]
349#[serde(transparent)]
350pub struct Enchantments {
351    #[var]
352    pub levels: HashMap<Enchantment, u32>,
353}
354
355#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)]
356pub enum BlockStateValueMatcher {
357    Exact {
358        value: String,
359    },
360    Range {
361        min: Option<String>,
362        max: Option<String>,
363    },
364}
365
366#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)]
367pub struct BlockStatePropertyMatcher {
368    pub name: String,
369    pub value_matcher: BlockStateValueMatcher,
370}
371
372#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)]
373pub struct BlockPredicate {
374    #[serde(skip_serializing_if = "is_default")]
375    pub blocks: Option<HolderSet<Block, ResourceLocation>>,
376    #[serde(skip_serializing_if = "is_default")]
377    pub properties: Option<Vec<BlockStatePropertyMatcher>>,
378    #[serde(skip_serializing_if = "is_default")]
379    pub nbt: Option<NbtCompound>,
380}
381
382#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)]
383#[serde(transparent)]
384pub struct AdventureModePredicate {
385    #[serde(serialize_with = "flatten_array")]
386    pub predicates: Vec<BlockPredicate>,
387}
388
389#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)]
390#[serde(transparent)]
391pub struct CanPlaceOn {
392    pub predicate: AdventureModePredicate,
393}
394
395#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)]
396#[serde(transparent)]
397pub struct CanBreak {
398    pub predicate: AdventureModePredicate,
399}
400
401#[derive(Clone, Copy, PartialEq, AzBuf, Debug, Serialize)]
402#[serde(rename_all = "snake_case")]
403pub enum EquipmentSlotGroup {
404    Any,
405    Mainhand,
406    Offhand,
407    Hand,
408    Feet,
409    Legs,
410    Chest,
411    Head,
412    Armor,
413    Body,
414}
415
416#[derive(Clone, Copy, PartialEq, AzBuf, Debug, Serialize)]
417#[serde(rename_all = "snake_case")]
418pub enum AttributeModifierOperation {
419    AddValue,
420    AddMultipliedBase,
421    AddMultipliedTotal,
422}
423
424// this is duplicated in azalea-entity, BUT the one there has a different
425// protocol format (and we can't use it anyways because it would cause a
426// circular dependency)
427#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)]
428pub struct AttributeModifier {
429    pub id: ResourceLocation,
430    pub amount: f64,
431    pub operation: AttributeModifierOperation,
432}
433
434#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)]
435pub struct AttributeModifiersEntry {
436    #[serde(rename = "type")]
437    pub kind: Attribute,
438    #[serde(flatten)]
439    pub modifier: AttributeModifier,
440    pub slot: EquipmentSlotGroup,
441    #[serde(skip_serializing_if = "is_default")]
442    pub display: AttributeModifierDisplay,
443}
444
445#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)]
446#[serde(transparent)]
447pub struct AttributeModifiers {
448    pub modifiers: Vec<AttributeModifiersEntry>,
449}
450
451#[derive(Clone, PartialEq, AzBuf, Debug, Default, Serialize)]
452#[serde(rename_all = "snake_case")]
453pub enum AttributeModifierDisplay {
454    #[default]
455    Default,
456    Hidden,
457    Override {
458        text: FormattedText,
459    },
460}
461
462#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)]
463pub struct CustomModelData {
464    #[serde(skip_serializing_if = "Vec::is_empty")]
465    pub floats: Vec<f32>,
466    #[serde(skip_serializing_if = "Vec::is_empty")]
467    pub flags: Vec<bool>,
468    #[serde(skip_serializing_if = "Vec::is_empty")]
469    pub strings: Vec<String>,
470    #[serde(skip_serializing_if = "Vec::is_empty")]
471    pub colors: Vec<i32>,
472}
473
474#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)]
475#[serde(transparent)]
476pub struct RepairCost {
477    #[var]
478    pub cost: u32,
479}
480
481#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)]
482pub struct CreativeSlotLock;
483
484#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)]
485#[serde(transparent)]
486pub struct EnchantmentGlintOverride {
487    pub show_glint: bool,
488}
489
490#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)]
491pub struct IntangibleProjectile;
492
493#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)]
494pub struct MobEffectDetails {
495    #[var]
496    #[serde(skip_serializing_if = "is_default")]
497    pub amplifier: i32,
498    #[var]
499    #[serde(skip_serializing_if = "is_default")]
500    pub duration: i32,
501    #[serde(skip_serializing_if = "is_default")]
502    pub ambient: bool,
503    #[serde(skip_serializing_if = "is_default")]
504    pub show_particles: bool,
505    pub show_icon: bool,
506    #[serde(skip_serializing_if = "is_default")]
507    pub hidden_effect: Option<Box<MobEffectDetails>>,
508}
509impl MobEffectDetails {
510    pub const fn new() -> Self {
511        MobEffectDetails {
512            amplifier: 0,
513            duration: 0,
514            ambient: false,
515            show_particles: true,
516            show_icon: true,
517            hidden_effect: None,
518        }
519    }
520}
521impl Default for MobEffectDetails {
522    fn default() -> Self {
523        Self::new()
524    }
525}
526
527#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)]
528pub struct MobEffectInstance {
529    pub id: MobEffect,
530    #[serde(flatten)]
531    pub details: MobEffectDetails,
532}
533
534#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)]
535pub struct PossibleEffect {
536    pub effect: MobEffectInstance,
537    pub probability: f32,
538}
539
540#[derive(Clone, PartialEq, AzBuf, Debug, Default, Serialize)]
541pub struct Food {
542    #[var]
543    pub nutrition: i32,
544    pub saturation: f32,
545    #[serde(skip_serializing_if = "is_default")]
546    pub can_always_eat: bool,
547}
548
549impl Food {
550    pub const fn new() -> Self {
551        Food {
552            nutrition: 0,
553            saturation: 0.,
554            can_always_eat: false,
555        }
556    }
557}
558
559#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)]
560pub struct ToolRule {
561    pub blocks: HolderSet<Block, ResourceLocation>,
562    #[serde(skip_serializing_if = "is_default")]
563    pub speed: Option<f32>,
564    #[serde(skip_serializing_if = "is_default")]
565    pub correct_for_drops: Option<bool>,
566}
567impl ToolRule {
568    pub const fn new() -> Self {
569        ToolRule {
570            blocks: HolderSet::Direct { contents: vec![] },
571            speed: None,
572            correct_for_drops: None,
573        }
574    }
575}
576impl Default for ToolRule {
577    fn default() -> Self {
578        Self::new()
579    }
580}
581
582#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)]
583pub struct Tool {
584    #[serde(serialize_with = "flatten_array")]
585    pub rules: Vec<ToolRule>,
586    #[serde(skip_serializing_if = "is_default")]
587    pub default_mining_speed: f32,
588    #[var]
589    #[serde(skip_serializing_if = "is_default")]
590    pub damage_per_block: i32,
591    #[serde(skip_serializing_if = "is_default")]
592    pub can_destroy_blocks_in_creative: bool,
593}
594
595impl Tool {
596    pub const fn new() -> Self {
597        Tool {
598            rules: vec![],
599            default_mining_speed: 1.,
600            damage_per_block: 1,
601            can_destroy_blocks_in_creative: true,
602        }
603    }
604}
605impl Default for Tool {
606    fn default() -> Self {
607        Self::new()
608    }
609}
610
611#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)]
612#[serde(transparent)]
613pub struct StoredEnchantments {
614    #[var]
615    pub enchantments: HashMap<Enchantment, i32>,
616}
617
618#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)]
619#[serde(transparent)]
620pub struct DyedColor {
621    pub rgb: i32,
622}
623
624#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)]
625#[serde(transparent)]
626pub struct MapColor {
627    pub color: i32,
628}
629
630#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)]
631#[serde(transparent)]
632pub struct MapId {
633    #[var]
634    pub id: i32,
635}
636
637#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)]
638#[serde(transparent)]
639pub struct MapDecorations {
640    pub decorations: NbtCompound,
641}
642
643#[derive(Clone, Copy, PartialEq, AzBuf, Debug, Serialize)]
644pub enum MapPostProcessing {
645    Lock,
646    Scale,
647}
648
649#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)]
650#[serde(transparent)]
651pub struct ChargedProjectiles {
652    pub items: Vec<ItemStack>,
653}
654
655#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)]
656#[serde(transparent)]
657pub struct BundleContents {
658    pub items: Vec<ItemStack>,
659}
660
661#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)]
662pub struct PotionContents {
663    #[serde(skip_serializing_if = "is_default")]
664    pub potion: Option<Potion>,
665    #[serde(skip_serializing_if = "is_default")]
666    pub custom_color: Option<i32>,
667    #[serde(skip_serializing_if = "is_default")]
668    pub custom_effects: Vec<MobEffectInstance>,
669    #[serde(skip_serializing_if = "is_default")]
670    pub custom_name: Option<String>,
671}
672
673impl PotionContents {
674    pub const fn new() -> Self {
675        PotionContents {
676            potion: None,
677            custom_color: None,
678            custom_effects: vec![],
679            custom_name: None,
680        }
681    }
682}
683impl Default for PotionContents {
684    fn default() -> Self {
685        Self::new()
686    }
687}
688
689#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)]
690pub struct SuspiciousStewEffect {
691    #[serde(rename = "id")]
692    pub effect: MobEffect,
693    #[var]
694    #[serde(skip_serializing_if = "is_default")]
695    pub duration: i32,
696}
697
698#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)]
699#[serde(transparent)]
700pub struct SuspiciousStewEffects {
701    pub effects: Vec<SuspiciousStewEffect>,
702}
703
704#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)]
705pub struct WritableBookContent {
706    pub pages: Vec<String>,
707}
708
709#[derive(Clone, PartialEq, AzBuf, Serialize)]
710pub struct WrittenBookContent {
711    #[limit(32)]
712    pub title: Filterable<String>,
713    pub author: String,
714    #[var]
715    #[serde(skip_serializing_if = "is_default")]
716    pub generation: i32,
717    #[serde(skip_serializing_if = "is_default")]
718    pub pages: Vec<Filterable<FormattedText>>,
719    #[serde(skip_serializing_if = "is_default")]
720    pub resolved: bool,
721}
722
723#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)]
724pub struct Trim {
725    pub material: TrimMaterial,
726    pub pattern: TrimPattern,
727}
728
729#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)]
730#[serde(transparent)]
731pub struct DebugStickState {
732    pub properties: NbtCompound,
733}
734
735#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)]
736pub struct EntityData {
737    #[serde(rename = "id")]
738    pub kind: EntityKind,
739    #[serde(flatten)]
740    pub data: NbtCompound,
741}
742
743#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)]
744#[serde(transparent)]
745pub struct BucketEntityData {
746    pub entity: NbtCompound,
747}
748
749#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)]
750pub struct BlockEntityData {
751    #[serde(rename = "id")]
752    pub kind: EntityKind,
753    #[serde(flatten)]
754    pub data: NbtCompound,
755}
756
757#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)]
758#[serde(untagged)]
759pub enum Instrument {
760    Registry(registry::Instrument),
761    Holder(Holder<registry::Instrument, InstrumentData>),
762}
763
764#[derive(Clone, PartialEq, Debug, AzBuf, Serialize)]
765pub struct InstrumentData {
766    pub sound_event: Holder<SoundEvent, azalea_core::sound::CustomSound>,
767    pub use_duration: f32,
768    pub range: f32,
769    pub description: FormattedText,
770}
771
772#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)]
773#[serde(transparent)]
774pub struct OminousBottleAmplifier {
775    #[var]
776    pub amplifier: i32,
777}
778
779#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)]
780#[serde(transparent)]
781pub struct Recipes {
782    pub recipes: Vec<ResourceLocation>,
783}
784
785#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)]
786pub struct LodestoneTracker {
787    #[serde(skip_serializing_if = "is_default")]
788    pub target: Option<GlobalPos>,
789    #[serde(skip_serializing_if = "is_true")]
790    pub tracked: bool,
791}
792
793#[derive(Clone, Copy, PartialEq, AzBuf, Debug, Serialize)]
794#[serde(rename_all = "snake_case")]
795pub enum FireworkExplosionShape {
796    SmallBall,
797    LargeBall,
798    Star,
799    Creeper,
800    Burst,
801}
802
803#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)]
804pub struct FireworkExplosion {
805    pub shape: FireworkExplosionShape,
806    #[serde(skip_serializing_if = "is_default")]
807    pub colors: Vec<i32>,
808    #[serde(skip_serializing_if = "is_default")]
809    pub fade_colors: Vec<i32>,
810    #[serde(skip_serializing_if = "is_default")]
811    pub has_trail: bool,
812    #[serde(skip_serializing_if = "is_default")]
813    pub has_twinkle: bool,
814}
815
816#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)]
817pub struct Fireworks {
818    #[var]
819    #[serde(skip_serializing_if = "is_default")]
820    pub flight_duration: i32,
821    #[limit(256)]
822    pub explosions: Vec<FireworkExplosion>,
823}
824
825impl Fireworks {
826    pub const fn new() -> Self {
827        Fireworks {
828            flight_duration: 0,
829            explosions: vec![],
830        }
831    }
832}
833impl Default for Fireworks {
834    fn default() -> Self {
835        Self::new()
836    }
837}
838
839#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)]
840#[serde(transparent)]
841pub struct NoteBlockSound {
842    pub sound: ResourceLocation,
843}
844
845#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)]
846pub struct BannerPattern {
847    #[var]
848    pub pattern: i32,
849    #[var]
850    pub color: i32,
851}
852
853#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)]
854#[serde(transparent)]
855pub struct BannerPatterns {
856    pub patterns: Vec<BannerPattern>,
857}
858
859#[derive(Clone, Copy, PartialEq, AzBuf, Debug, Serialize)]
860#[serde(rename_all = "snake_case")]
861pub enum DyeColor {
862    White,
863    Orange,
864    Magenta,
865    LightBlue,
866    Yellow,
867    Lime,
868    Pink,
869    Gray,
870    LightGray,
871    Cyan,
872    Purple,
873    Blue,
874    Brown,
875    Green,
876    Red,
877    Black,
878}
879
880#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)]
881#[serde(transparent)]
882pub struct BaseColor {
883    pub color: DyeColor,
884}
885
886#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)]
887#[serde(transparent)]
888pub struct PotDecorations {
889    pub items: Vec<Item>,
890}
891
892#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)]
893#[serde(transparent)]
894pub struct Container {
895    pub items: Vec<ItemStack>,
896}
897
898#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)]
899#[serde(transparent)]
900pub struct BlockState {
901    pub properties: HashMap<String, String>,
902}
903
904#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)]
905pub struct BeehiveOccupant {
906    #[serde(skip_serializing_if = "is_default")]
907    pub entity_data: NbtCompound,
908    #[var]
909    pub ticks_in_hive: i32,
910    #[var]
911    pub min_ticks_in_hive: i32,
912}
913
914#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)]
915#[serde(transparent)]
916pub struct Bees {
917    pub occupants: Vec<BeehiveOccupant>,
918}
919
920#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)]
921pub struct Lock {
922    pub key: String,
923}
924
925#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)]
926pub struct ContainerLoot {
927    pub loot_table: NbtCompound,
928}
929
930#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)]
931#[serde(untagged)]
932pub enum JukeboxPlayable {
933    Referenced(ResourceLocation),
934    Direct(Holder<registry::JukeboxSong, JukeboxSongData>),
935}
936
937#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)]
938pub struct JukeboxSongData {
939    pub sound_event: Holder<SoundEvent, CustomSound>,
940    pub description: FormattedText,
941    pub length_in_seconds: f32,
942    #[var]
943    pub comparator_output: i32,
944}
945
946#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)]
947pub struct Consumable {
948    #[serde(skip_serializing_if = "is_default")]
949    pub consume_seconds: f32,
950    #[serde(skip_serializing_if = "is_default")]
951    pub animation: ItemUseAnimation,
952    #[serde(skip_serializing_if = "is_default_eat_sound")]
953    pub sound: azalea_registry::Holder<SoundEvent, CustomSound>,
954    #[serde(skip_serializing_if = "is_default")]
955    pub has_consume_particles: bool,
956    #[serde(skip_serializing_if = "is_default")]
957    pub on_consume_effects: Vec<ConsumeEffect>,
958}
959fn is_default_eat_sound(sound: &azalea_registry::Holder<SoundEvent, CustomSound>) -> bool {
960    matches!(
961        sound,
962        azalea_registry::Holder::Reference(SoundEvent::EntityGenericEat)
963    )
964}
965
966impl Consumable {
967    pub const fn new() -> Self {
968        Self {
969            consume_seconds: 1.6,
970            animation: ItemUseAnimation::Eat,
971            sound: azalea_registry::Holder::Reference(SoundEvent::EntityGenericEat),
972            has_consume_particles: true,
973            on_consume_effects: Vec::new(),
974        }
975    }
976}
977impl Default for Consumable {
978    fn default() -> Self {
979        Self::new()
980    }
981}
982
983#[derive(Clone, Copy, PartialEq, AzBuf, Debug, Default, Serialize)]
984#[serde(rename_all = "snake_case")]
985pub enum ItemUseAnimation {
986    #[default]
987    None,
988    Eat,
989    Drink,
990    Block,
991    Bow,
992    Spear,
993    Crossbow,
994    Spyglass,
995    TootHorn,
996    Brush,
997}
998
999#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)]
1000#[serde(transparent)]
1001pub struct UseRemainder {
1002    pub convert_into: ItemStack,
1003}
1004
1005#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)]
1006pub struct UseCooldown {
1007    pub seconds: f32,
1008    #[serde(skip_serializing_if = "is_default")]
1009    pub cooldown_group: Option<ResourceLocation>,
1010}
1011
1012impl UseCooldown {
1013    pub const fn new() -> Self {
1014        Self {
1015            seconds: 0.,
1016            cooldown_group: None,
1017        }
1018    }
1019}
1020impl Default for UseCooldown {
1021    fn default() -> Self {
1022        Self::new()
1023    }
1024}
1025
1026#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)]
1027pub struct Enchantable {
1028    #[var]
1029    pub value: u32,
1030}
1031
1032#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)]
1033pub struct Repairable {
1034    pub items: HolderSet<Item, ResourceLocation>,
1035}
1036
1037#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)]
1038#[serde(transparent)]
1039pub struct ItemModel {
1040    pub resource_location: ResourceLocation,
1041}
1042
1043#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)]
1044pub struct DamageResistant {
1045    /// In vanilla this only allows tag keys, i.e. it must start with '#'
1046    pub types: ResourceLocation,
1047}
1048
1049#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)]
1050pub struct Equippable {
1051    pub slot: EquipmentSlot,
1052    #[serde(skip_serializing_if = "is_default_equip_sound")]
1053    pub equip_sound: SoundEvent,
1054    #[serde(skip_serializing_if = "is_default")]
1055    pub asset_id: Option<ResourceLocation>,
1056    #[serde(skip_serializing_if = "is_default")]
1057    pub camera_overlay: Option<ResourceLocation>,
1058    #[serde(skip_serializing_if = "is_default")]
1059    pub allowed_entities: Option<HolderSet<EntityKind, ResourceLocation>>,
1060    #[serde(skip_serializing_if = "is_true")]
1061    pub dispensable: bool,
1062    #[serde(skip_serializing_if = "is_true")]
1063    pub swappable: bool,
1064    #[serde(skip_serializing_if = "is_true")]
1065    pub damage_on_hurt: bool,
1066    #[serde(skip_serializing_if = "is_default")]
1067    pub equip_on_interact: bool,
1068    #[serde(skip_serializing_if = "is_default")]
1069    pub can_be_sheared: bool,
1070    #[serde(skip_serializing_if = "is_default_shearing_sound")]
1071    pub shearing_sound: SoundEvent,
1072}
1073fn is_default_equip_sound(sound: &SoundEvent) -> bool {
1074    matches!(sound, SoundEvent::ItemArmorEquipGeneric)
1075}
1076fn is_default_shearing_sound(sound: &SoundEvent) -> bool {
1077    matches!(sound, SoundEvent::ItemShearsSnip)
1078}
1079
1080impl Equippable {
1081    pub const fn new() -> Self {
1082        Self {
1083            slot: EquipmentSlot::Body,
1084            equip_sound: SoundEvent::ItemArmorEquipGeneric,
1085            asset_id: None,
1086            camera_overlay: None,
1087            allowed_entities: None,
1088            dispensable: true,
1089            swappable: true,
1090            damage_on_hurt: true,
1091            equip_on_interact: false,
1092            can_be_sheared: false,
1093            shearing_sound: SoundEvent::ItemShearsSnip,
1094        }
1095    }
1096}
1097impl Default for Equippable {
1098    fn default() -> Self {
1099        Self::new()
1100    }
1101}
1102
1103#[derive(Clone, Copy, Debug, PartialEq, AzBuf, Serialize)]
1104#[serde(rename_all = "snake_case")]
1105pub enum EquipmentSlot {
1106    Mainhand,
1107    Offhand,
1108    Feet,
1109    Legs,
1110    Chest,
1111    Head,
1112    Body,
1113    Saddle,
1114}
1115
1116#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)]
1117pub struct Glider;
1118
1119#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)]
1120#[serde(transparent)]
1121pub struct TooltipStyle {
1122    pub resource_location: ResourceLocation,
1123}
1124
1125#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)]
1126pub struct DeathProtection {
1127    pub death_effects: Vec<ConsumeEffect>,
1128}
1129
1130#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)]
1131pub struct Weapon {
1132    #[var]
1133    #[serde(skip_serializing_if = "is_default_item_damage_per_attack")]
1134    pub item_damage_per_attack: i32,
1135    #[serde(skip_serializing_if = "is_default")]
1136    pub disable_blocking_for_seconds: f32,
1137}
1138fn is_default_item_damage_per_attack(value: &i32) -> bool {
1139    *value == 1
1140}
1141
1142impl Weapon {
1143    pub const fn new() -> Self {
1144        Self {
1145            item_damage_per_attack: 1,
1146            disable_blocking_for_seconds: 0.,
1147        }
1148    }
1149}
1150impl Default for Weapon {
1151    fn default() -> Self {
1152        Self::new()
1153    }
1154}
1155
1156#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)]
1157#[serde(transparent)]
1158pub struct PotionDurationScale {
1159    pub value: f32,
1160}
1161
1162#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)]
1163#[serde(transparent)]
1164pub struct VillagerVariant {
1165    pub variant: registry::VillagerKind,
1166}
1167
1168#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)]
1169#[serde(transparent)]
1170pub struct WolfVariant {
1171    pub variant: registry::WolfVariant,
1172}
1173
1174#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)]
1175#[serde(transparent)]
1176pub struct WolfCollar {
1177    pub color: DyeColor,
1178}
1179
1180#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)]
1181#[serde(transparent)]
1182pub struct FoxVariant {
1183    pub variant: registry::FoxVariant,
1184}
1185
1186#[derive(Clone, Copy, PartialEq, AzBuf, Debug, Serialize)]
1187#[serde(rename_all = "snake_case")]
1188pub enum SalmonSize {
1189    Small,
1190    Medium,
1191    Large,
1192}
1193
1194#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)]
1195#[serde(transparent)]
1196pub struct ParrotVariant {
1197    pub variant: registry::ParrotVariant,
1198}
1199
1200#[derive(Clone, Copy, PartialEq, AzBuf, Debug, Serialize)]
1201#[serde(rename_all = "snake_case")]
1202pub enum TropicalFishPattern {
1203    Kob,
1204    Sunstreak,
1205    Snooper,
1206    Dasher,
1207    Brinely,
1208    Spotty,
1209    Flopper,
1210    Stripey,
1211    Glitter,
1212    Blockfish,
1213    Betty,
1214    Clayfish,
1215}
1216
1217#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)]
1218#[serde(transparent)]
1219pub struct TropicalFishBaseColor {
1220    pub color: DyeColor,
1221}
1222
1223#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)]
1224#[serde(transparent)]
1225pub struct TropicalFishPatternColor {
1226    pub color: DyeColor,
1227}
1228
1229#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)]
1230#[serde(transparent)]
1231pub struct MooshroomVariant {
1232    pub variant: registry::MooshroomVariant,
1233}
1234
1235#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)]
1236#[serde(transparent)]
1237pub struct RabbitVariant {
1238    pub variant: registry::RabbitVariant,
1239}
1240
1241#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)]
1242#[serde(transparent)]
1243pub struct PigVariant {
1244    pub variant: registry::PigVariant,
1245}
1246
1247#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)]
1248#[serde(transparent)]
1249pub struct FrogVariant {
1250    pub variant: registry::FrogVariant,
1251}
1252
1253#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)]
1254#[serde(transparent)]
1255pub struct HorseVariant {
1256    pub variant: registry::HorseVariant,
1257}
1258
1259#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)]
1260#[serde(transparent)]
1261pub struct PaintingVariant {
1262    pub variant: Holder<registry::PaintingVariant, PaintingVariantData>,
1263}
1264
1265#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)]
1266pub struct PaintingVariantData {
1267    #[var]
1268    pub width: i32,
1269    #[var]
1270    pub height: i32,
1271    pub asset_id: ResourceLocation,
1272    #[serde(skip_serializing_if = "is_default")]
1273    pub title: Option<FormattedText>,
1274    #[serde(skip_serializing_if = "is_default")]
1275    pub author: Option<FormattedText>,
1276}
1277
1278#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)]
1279#[serde(transparent)]
1280pub struct LlamaVariant {
1281    pub variant: registry::LlamaVariant,
1282}
1283
1284#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)]
1285#[serde(transparent)]
1286pub struct AxolotlVariant {
1287    pub variant: registry::AxolotlVariant,
1288}
1289
1290#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)]
1291#[serde(transparent)]
1292pub struct CatVariant {
1293    pub variant: registry::CatVariant,
1294}
1295
1296#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)]
1297#[serde(transparent)]
1298pub struct CatCollar {
1299    pub color: DyeColor,
1300}
1301
1302#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)]
1303#[serde(transparent)]
1304pub struct SheepColor {
1305    pub color: DyeColor,
1306}
1307
1308#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)]
1309#[serde(transparent)]
1310pub struct ShulkerColor {
1311    pub color: DyeColor,
1312}
1313
1314#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)]
1315pub struct TooltipDisplay {
1316    #[serde(skip_serializing_if = "is_default")]
1317    pub hide_tooltip: bool,
1318    #[serde(skip_serializing_if = "is_default")]
1319    pub hidden_components: Vec<DataComponentKind>,
1320}
1321
1322impl TooltipDisplay {
1323    pub const fn new() -> Self {
1324        Self {
1325            hide_tooltip: false,
1326            hidden_components: Vec::new(),
1327        }
1328    }
1329}
1330impl Default for TooltipDisplay {
1331    fn default() -> Self {
1332        Self::new()
1333    }
1334}
1335
1336#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)]
1337pub struct BlocksAttacks {
1338    #[serde(skip_serializing_if = "is_default")]
1339    pub block_delay_seconds: f32,
1340    #[serde(skip_serializing_if = "is_default_disable_cooldown_scale")]
1341    pub disable_cooldown_scale: f32,
1342    #[serde(skip_serializing_if = "is_default")]
1343    pub damage_reductions: Vec<DamageReduction>,
1344    #[serde(skip_serializing_if = "is_default")]
1345    pub item_damage: ItemDamageFunction,
1346    #[serde(skip_serializing_if = "is_default")]
1347    pub bypassed_by: Option<ResourceLocation>,
1348    #[serde(skip_serializing_if = "is_default")]
1349    pub block_sound: Option<azalea_registry::Holder<SoundEvent, CustomSound>>,
1350    #[serde(skip_serializing_if = "is_default")]
1351    pub disabled_sound: Option<azalea_registry::Holder<SoundEvent, CustomSound>>,
1352}
1353fn is_default_disable_cooldown_scale(value: &f32) -> bool {
1354    *value == 1.
1355}
1356
1357impl BlocksAttacks {
1358    pub fn new() -> Self {
1359        Self {
1360            block_delay_seconds: 0.,
1361            disable_cooldown_scale: 1.,
1362            damage_reductions: vec![DamageReduction {
1363                horizontal_blocking_angle: 90.,
1364                kind: None,
1365                base: 0.,
1366                factor: 1.,
1367            }],
1368            item_damage: ItemDamageFunction::default(),
1369            bypassed_by: None,
1370            block_sound: None,
1371            disabled_sound: None,
1372        }
1373    }
1374}
1375impl Default for BlocksAttacks {
1376    fn default() -> Self {
1377        Self::new()
1378    }
1379}
1380
1381#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)]
1382pub struct DamageReduction {
1383    #[serde(skip_serializing_if = "is_default_horizontal_blocking_angle")]
1384    pub horizontal_blocking_angle: f32,
1385    #[serde(skip_serializing_if = "is_default")]
1386    pub kind: Option<HolderSet<DamageKind, ResourceLocation>>,
1387    pub base: f32,
1388    pub factor: f32,
1389}
1390fn is_default_horizontal_blocking_angle(value: &f32) -> bool {
1391    *value == 90.
1392}
1393#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)]
1394pub struct ItemDamageFunction {
1395    pub threshold: f32,
1396    pub base: f32,
1397    pub factor: f32,
1398}
1399impl Default for ItemDamageFunction {
1400    fn default() -> Self {
1401        ItemDamageFunction {
1402            threshold: 1.,
1403            base: 0.,
1404            factor: 1.,
1405        }
1406    }
1407}
1408
1409#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)]
1410#[serde(untagged)]
1411pub enum ProvidesTrimMaterial {
1412    Referenced(ResourceLocation),
1413    Direct(Holder<TrimMaterial, DirectTrimMaterial>),
1414}
1415
1416#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)]
1417pub struct DirectTrimMaterial {
1418    pub assets: MaterialAssetGroup,
1419    pub description: FormattedText,
1420}
1421#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)]
1422pub struct MaterialAssetGroup {
1423    pub base: AssetInfo,
1424    #[serde(skip_serializing_if = "is_default")]
1425    pub overrides: Vec<(ResourceLocation, AssetInfo)>,
1426}
1427
1428#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)]
1429pub struct AssetInfo {
1430    pub suffix: String,
1431}
1432
1433#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)]
1434#[serde(transparent)]
1435pub struct ProvidesBannerPatterns {
1436    pub key: ResourceLocation,
1437}
1438
1439#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)]
1440#[serde(transparent)]
1441pub struct BreakSound {
1442    pub sound: azalea_registry::Holder<SoundEvent, CustomSound>,
1443}
1444
1445#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)]
1446#[serde(transparent)]
1447pub struct WolfSoundVariant {
1448    pub variant: azalea_registry::WolfSoundVariant,
1449}
1450
1451#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)]
1452#[serde(transparent)]
1453pub struct CowVariant {
1454    pub variant: azalea_registry::CowVariant,
1455}
1456
1457#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)]
1458#[serde(untagged)]
1459pub enum ChickenVariant {
1460    Referenced(ResourceLocation),
1461    Direct(ChickenVariantData),
1462}
1463
1464#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)]
1465pub struct ChickenVariantData {
1466    pub registry: azalea_registry::ChickenVariant,
1467}