Skip to main content

azalea_inventory/components/
mod.rs

1mod profile;
2
3use core::f64;
4use std::{
5    any::Any,
6    collections::HashMap,
7    fmt::{self, Debug, Display},
8    io::{self, Cursor},
9    mem::ManuallyDrop,
10};
11
12use azalea_buf::{AzBuf, BufReadError};
13use azalea_chat::FormattedText;
14use azalea_core::{
15    attribute_modifier_operation::AttributeModifierOperation,
16    checksum::{Checksum, get_checksum},
17    codec_utils::*,
18    filterable::Filterable,
19    position::GlobalPos,
20    registry_holder::RegistryHolder,
21    sound::CustomSound,
22};
23use azalea_registry::{
24    Holder, HolderSet,
25    builtin::{
26        Attribute, BlockKind, DataComponentKind, EntityKind, ItemKind, MobEffect, Potion,
27        SoundEvent, VillagerKind,
28    },
29    data::{self, BannerPatternKind, DamageKind, Enchantment, TrimMaterial, TrimPattern},
30    identifier::Identifier,
31};
32pub use profile::*;
33use serde::{Serialize, Serializer, ser::SerializeMap};
34use simdnbt::owned::{Nbt, NbtCompound};
35use tracing::trace;
36
37use crate::{ItemStack, item::consume_effect::ConsumeEffect};
38
39pub trait DataComponentTrait:
40    Send + Sync + Any + Clone + Serialize + Into<DataComponentUnion>
41{
42    const KIND: DataComponentKind;
43}
44
45pub trait EncodableDataComponent: Send + Sync + Any + Debug {
46    fn encode(&self, buf: &mut Vec<u8>) -> io::Result<()>;
47    fn crc_hash(&self, registries: &RegistryHolder) -> Checksum;
48    // using the Clone trait makes it not be object-safe, so we have our own clone
49    // function instead
50    fn clone(&self) -> Box<dyn EncodableDataComponent>;
51    // same thing here
52    fn eq(&self, other: &dyn EncodableDataComponent) -> bool;
53}
54
55impl<T> EncodableDataComponent for T
56where
57    T: DataComponentTrait + Clone + AzBuf + PartialEq + Debug,
58{
59    fn encode(&self, buf: &mut Vec<u8>) -> io::Result<()> {
60        self.azalea_write(buf)
61    }
62    fn crc_hash(&self, registries: &RegistryHolder) -> Checksum {
63        get_checksum(self, registries).expect("serializing data components should always succeed")
64    }
65    fn clone(&self) -> Box<dyn EncodableDataComponent> {
66        let cloned = self.clone();
67        Box::new(cloned)
68    }
69    fn eq(&self, other: &dyn EncodableDataComponent) -> bool {
70        let other_any: &dyn Any = other;
71        match other_any.downcast_ref::<T>() {
72            Some(other) => self == other,
73            _ => false,
74        }
75    }
76}
77
78#[macro_export]
79macro_rules! define_data_components {
80    ( $( $x:ident ),* $(,)? ) => {
81        /// A union of all data components.
82        ///
83        /// You probably don't want to use this directly. Consider [`DataComponentPatch`] instead.
84        ///
85        /// This type does not know its own value, and as such every function for it requires the
86        /// `DataComponentKind` to be passed in. Passing the wrong `DataComponentKind` will result
87        /// in undefined behavior. Also, all of the values are `ManuallyDrop`.
88        ///
89        /// [`DataComponentPatch`]: crate::DataComponentPatch
90        #[allow(non_snake_case)]
91        pub union DataComponentUnion {
92            $( $x: ManuallyDrop<$x>, )*
93        }
94        impl DataComponentUnion {
95            /// # Safety
96            ///
97            /// `kind` must be the correct value for this union.
98            pub unsafe fn serialize_entry_as<S: SerializeMap>(
99                &self,
100                serializer: &mut S,
101                kind: DataComponentKind,
102            ) -> Result<(), S::Error> {
103                match kind {
104                    $( DataComponentKind::$x => { unsafe { serializer.serialize_entry(&kind, &*self.$x) } }, )*
105                }
106            }
107            /// # Safety
108            ///
109            /// `kind` must be the correct value for this union.
110            pub unsafe fn drop_as(&mut self, kind: DataComponentKind) {
111                match kind {
112                    $( DataComponentKind::$x => { unsafe { ManuallyDrop::drop(&mut self.$x) } }, )*
113                }
114            }
115            /// # Safety
116            ///
117            /// `kind` must be the correct value for this union.
118            pub unsafe fn as_kind(&self, kind: DataComponentKind) -> &dyn EncodableDataComponent {
119                match kind {
120                    $( DataComponentKind::$x => { unsafe { &**(&self.$x as &ManuallyDrop<dyn EncodableDataComponent>) } }, )*
121                }
122            }
123            pub fn azalea_read_as(
124                kind: DataComponentKind,
125                buf: &mut Cursor<&[u8]>,
126            ) -> Result<Self, BufReadError> {
127                trace!("Reading data component {kind}");
128
129                Ok(match kind {
130                    $( DataComponentKind::$x => {
131                        let v = $x::azalea_read(buf)?;
132                        Self { $x: ManuallyDrop::new(v) }
133                    }, )*
134                })
135            }
136            /// # Safety
137            ///
138            /// `kind` must be the correct value for this union.
139            pub unsafe fn azalea_write_as(
140                &self,
141                kind: DataComponentKind,
142                buf: &mut impl std::io::Write,
143            ) -> io::Result<()> {
144                let mut value = Vec::new();
145                match kind {
146                    $( DataComponentKind::$x => unsafe { self.$x.encode(&mut value)? }, )*
147                };
148                buf.write_all(&value)?;
149
150                Ok(())
151            }
152            /// # Safety
153            ///
154            /// `kind` must be the correct value for this union.
155            pub unsafe fn clone_as(
156                &self,
157                kind: DataComponentKind,
158            ) -> Self {
159                match kind {
160                    $( DataComponentKind::$x => {
161                        Self { $x: unsafe { self.$x.clone() } }
162                    }, )*
163                }
164            }
165            /// # Safety
166            ///
167            /// `kind` must be the correct value for this union.
168            pub unsafe fn eq_as(
169                &self,
170                other: &Self,
171                kind: DataComponentKind,
172            ) -> bool {
173                match kind {
174                    $( DataComponentKind::$x => unsafe { self.$x.eq(&other.$x) }, )*
175                }
176            }
177        }
178        $(
179            impl From<$x> for DataComponentUnion {
180                fn from(value: $x) -> Self {
181                    DataComponentUnion { $x: ManuallyDrop::new(value) }
182                }
183            }
184        )*
185
186        $(
187            impl DataComponentTrait for $x {
188                const KIND: DataComponentKind = DataComponentKind::$x;
189            }
190        )*
191    };
192}
193
194// if this is causing a compile-time error, look at DataComponents.java in the
195// decompiled vanilla code to see how to implement new components
196
197// note that this statement is updated by genitemcomponents.py
198define_data_components!(
199    CustomData,
200    MaxStackSize,
201    MaxDamage,
202    Damage,
203    Unbreakable,
204    CustomName,
205    ItemName,
206    ItemModel,
207    Lore,
208    Rarity,
209    Enchantments,
210    CanPlaceOn,
211    CanBreak,
212    AttributeModifiers,
213    CustomModelData,
214    TooltipDisplay,
215    RepairCost,
216    CreativeSlotLock,
217    EnchantmentGlintOverride,
218    IntangibleProjectile,
219    Food,
220    Consumable,
221    UseRemainder,
222    UseCooldown,
223    DamageResistant,
224    Tool,
225    Weapon,
226    Enchantable,
227    Equippable,
228    Repairable,
229    Glider,
230    TooltipStyle,
231    DeathProtection,
232    BlocksAttacks,
233    StoredEnchantments,
234    DyedColor,
235    MapColor,
236    MapId,
237    MapDecorations,
238    MapPostProcessing,
239    ChargedProjectiles,
240    BundleContents,
241    PotionContents,
242    PotionDurationScale,
243    SuspiciousStewEffects,
244    WritableBookContent,
245    WrittenBookContent,
246    Trim,
247    DebugStickState,
248    EntityData,
249    BucketEntityData,
250    BlockEntityData,
251    Instrument,
252    ProvidesTrimMaterial,
253    OminousBottleAmplifier,
254    JukeboxPlayable,
255    ProvidesBannerPatterns,
256    Recipes,
257    LodestoneTracker,
258    FireworkExplosion,
259    Fireworks,
260    Profile,
261    NoteBlockSound,
262    BannerPatterns,
263    BaseColor,
264    PotDecorations,
265    Container,
266    BlockState,
267    Bees,
268    Lock,
269    ContainerLoot,
270    BreakSound,
271    VillagerVariant,
272    WolfVariant,
273    WolfSoundVariant,
274    WolfCollar,
275    FoxVariant,
276    SalmonSize,
277    ParrotVariant,
278    TropicalFishPattern,
279    TropicalFishBaseColor,
280    TropicalFishPatternColor,
281    MooshroomVariant,
282    RabbitVariant,
283    PigVariant,
284    CowVariant,
285    ChickenVariant,
286    FrogVariant,
287    HorseVariant,
288    PaintingVariant,
289    LlamaVariant,
290    AxolotlVariant,
291    CatVariant,
292    CatCollar,
293    SheepColor,
294    ShulkerColor,
295    UseEffects,
296    MinimumAttackCharge,
297    DamageType,
298    PiercingWeapon,
299    KineticWeapon,
300    SwingAnimation,
301    ZombieNautilusVariant,
302    AttackRange,
303    AdditionalTradeCost,
304    Dye,
305    PigSoundVariant,
306    CowSoundVariant,
307    ChickenSoundVariant,
308    CatSoundVariant,
309    SulfurCubeContent,
310);
311
312#[derive(AzBuf, Clone, Debug, PartialEq, Serialize)]
313#[serde(transparent)]
314pub struct CustomData {
315    pub nbt: Nbt,
316}
317
318#[derive(AzBuf, Clone, Debug, PartialEq, Serialize)]
319#[serde(transparent)]
320pub struct MaxStackSize {
321    #[var]
322    pub count: i32,
323}
324
325#[derive(AzBuf, Clone, Debug, PartialEq, Serialize)]
326#[serde(transparent)]
327pub struct MaxDamage {
328    #[var]
329    pub amount: i32,
330}
331
332#[derive(AzBuf, Clone, Debug, PartialEq, Serialize)]
333#[serde(transparent)]
334pub struct Damage {
335    #[var]
336    pub amount: i32,
337}
338
339#[derive(AzBuf, Clone, Debug, PartialEq, Serialize)]
340pub struct Unbreakable;
341
342#[derive(AzBuf, Clone, Debug, PartialEq, Serialize)]
343#[serde(transparent)]
344pub struct CustomName {
345    pub name: FormattedText,
346}
347
348#[derive(AzBuf, Clone, Debug, PartialEq, Serialize)]
349#[serde(transparent)]
350pub struct ItemName {
351    pub name: FormattedText,
352}
353
354#[derive(AzBuf, Clone, Debug, PartialEq, Serialize)]
355#[serde(transparent)]
356pub struct Lore {
357    pub lines: Vec<FormattedText>,
358    // vanilla also has styled_lines here but it doesn't appear to be used for the protocol
359}
360
361#[derive(AzBuf, Clone, Copy, Debug, PartialEq, Serialize)]
362#[serde(rename_all = "snake_case")]
363pub enum Rarity {
364    Common,
365    Uncommon,
366    Rare,
367    Epic,
368}
369
370#[derive(AzBuf, Clone, Default, PartialEq, Serialize, Debug)]
371#[serde(transparent)]
372pub struct Enchantments {
373    /// Enchantment levels here are 1-indexed, level 0 does not exist.
374    #[var]
375    pub levels: HashMap<Enchantment, i32>,
376}
377
378#[derive(AzBuf, Clone, Debug, PartialEq, Serialize)]
379pub enum BlockStateValueMatcher {
380    Exact {
381        value: String,
382    },
383    Range {
384        min: Option<String>,
385        max: Option<String>,
386    },
387}
388
389#[derive(AzBuf, Clone, Debug, PartialEq, Serialize)]
390pub struct BlockStatePropertyMatcher {
391    pub name: String,
392    pub value_matcher: BlockStateValueMatcher,
393}
394
395#[derive(AzBuf, Clone, Debug, PartialEq, Serialize)]
396pub struct BlockPredicate {
397    #[serde(skip_serializing_if = "is_default")]
398    pub blocks: Option<HolderSet<BlockKind, Identifier>>,
399    #[serde(skip_serializing_if = "is_default")]
400    pub properties: Option<Vec<BlockStatePropertyMatcher>>,
401    #[serde(skip_serializing_if = "is_default")]
402    pub nbt: Option<NbtCompound>,
403}
404
405#[derive(AzBuf, Clone, Debug, PartialEq, Serialize)]
406#[serde(transparent)]
407pub struct AdventureModePredicate {
408    #[serde(serialize_with = "flatten_array")]
409    pub predicates: Vec<BlockPredicate>,
410}
411
412#[derive(AzBuf, Clone, Debug, PartialEq, Serialize)]
413#[serde(transparent)]
414pub struct CanPlaceOn {
415    pub predicate: AdventureModePredicate,
416}
417
418#[derive(AzBuf, Clone, Debug, PartialEq, Serialize)]
419#[serde(transparent)]
420pub struct CanBreak {
421    pub predicate: AdventureModePredicate,
422}
423
424#[derive(AzBuf, Clone, Copy, Debug, PartialEq, Serialize)]
425#[serde(rename_all = "snake_case")]
426pub enum EquipmentSlotGroup {
427    Any,
428    Mainhand,
429    Offhand,
430    Hand,
431    Feet,
432    Legs,
433    Chest,
434    Head,
435    Armor,
436    Body,
437}
438
439// this is duplicated in azalea-entity, BUT the one there has a different
440// protocol format (and we can't use it anyways because it would cause a
441// circular dependency)
442#[derive(AzBuf, Clone, Debug, PartialEq, Serialize)]
443pub struct AttributeModifier {
444    pub id: Identifier,
445    pub amount: f64,
446    pub operation: AttributeModifierOperation,
447}
448
449#[derive(AzBuf, Clone, Debug, PartialEq, Serialize)]
450pub struct AttributeModifiersEntry {
451    #[serde(rename = "type")]
452    pub kind: Attribute,
453    #[serde(flatten)]
454    pub modifier: AttributeModifier,
455    pub slot: EquipmentSlotGroup,
456    #[serde(skip_serializing_if = "is_default")]
457    pub display: AttributeModifierDisplay,
458}
459
460#[derive(AzBuf, Clone, Debug, Default, PartialEq, Serialize)]
461#[serde(transparent)]
462pub struct AttributeModifiers {
463    pub modifiers: Vec<AttributeModifiersEntry>,
464}
465
466#[derive(AzBuf, Clone, Debug, Default, PartialEq, Serialize)]
467#[serde(rename_all = "snake_case")]
468pub enum AttributeModifierDisplay {
469    #[default]
470    Default,
471    Hidden,
472    Override {
473        text: FormattedText,
474    },
475}
476
477#[derive(AzBuf, Clone, Debug, PartialEq, Serialize)]
478pub struct CustomModelData {
479    #[serde(skip_serializing_if = "Vec::is_empty")]
480    pub floats: Vec<f32>,
481    #[serde(skip_serializing_if = "Vec::is_empty")]
482    pub flags: Vec<bool>,
483    #[serde(skip_serializing_if = "Vec::is_empty")]
484    pub strings: Vec<String>,
485    #[serde(skip_serializing_if = "Vec::is_empty")]
486    pub colors: Vec<i32>,
487}
488
489#[derive(AzBuf, Clone, Debug, PartialEq, Serialize)]
490#[serde(transparent)]
491pub struct RepairCost {
492    #[var]
493    pub cost: u32,
494}
495
496#[derive(AzBuf, Clone, Debug, PartialEq, Serialize)]
497pub struct CreativeSlotLock;
498
499#[derive(AzBuf, Clone, Debug, PartialEq, Serialize)]
500#[serde(transparent)]
501pub struct EnchantmentGlintOverride {
502    pub show_glint: bool,
503}
504
505#[derive(AzBuf, Clone, Debug, PartialEq, Serialize)]
506pub struct IntangibleProjectile;
507
508#[derive(AzBuf, Clone, Debug, PartialEq, Serialize)]
509pub struct MobEffectDetails {
510    #[var]
511    #[serde(skip_serializing_if = "is_default")]
512    pub amplifier: i32,
513    #[var]
514    #[serde(skip_serializing_if = "is_default")]
515    pub duration: i32,
516    #[serde(skip_serializing_if = "is_default")]
517    pub ambient: bool,
518    #[serde(skip_serializing_if = "is_default")]
519    pub show_particles: bool,
520    pub show_icon: bool,
521    #[serde(skip_serializing_if = "is_default")]
522    pub hidden_effect: Option<Box<MobEffectDetails>>,
523}
524impl MobEffectDetails {
525    pub const fn new() -> Self {
526        MobEffectDetails {
527            amplifier: 0,
528            duration: 0,
529            ambient: false,
530            show_particles: true,
531            show_icon: true,
532            hidden_effect: None,
533        }
534    }
535}
536impl Default for MobEffectDetails {
537    fn default() -> Self {
538        Self::new()
539    }
540}
541
542#[derive(AzBuf, Clone, Debug, PartialEq, Serialize)]
543pub struct MobEffectInstance {
544    pub id: MobEffect,
545    #[serde(flatten)]
546    pub details: MobEffectDetails,
547}
548
549#[derive(AzBuf, Clone, Debug, PartialEq, Serialize)]
550pub struct PossibleEffect {
551    pub effect: MobEffectInstance,
552    pub probability: f32,
553}
554
555#[derive(AzBuf, Clone, Debug, Default, PartialEq, Serialize)]
556pub struct Food {
557    #[var]
558    pub nutrition: i32,
559    pub saturation: f32,
560    #[serde(skip_serializing_if = "is_default")]
561    pub can_always_eat: bool,
562}
563
564impl Food {
565    pub const fn new() -> Self {
566        Food {
567            nutrition: 0,
568            saturation: 0.,
569            can_always_eat: false,
570        }
571    }
572}
573
574#[derive(AzBuf, Clone, Debug, PartialEq, Serialize)]
575pub struct ToolRule {
576    pub blocks: HolderSet<BlockKind, Identifier>,
577    #[serde(skip_serializing_if = "is_default")]
578    pub speed: Option<f32>,
579    #[serde(skip_serializing_if = "is_default")]
580    pub correct_for_drops: Option<bool>,
581}
582impl ToolRule {
583    pub const fn new() -> Self {
584        ToolRule {
585            blocks: HolderSet::Direct { contents: vec![] },
586            speed: None,
587            correct_for_drops: None,
588        }
589    }
590}
591impl Default for ToolRule {
592    fn default() -> Self {
593        Self::new()
594    }
595}
596
597#[derive(AzBuf, Clone, Debug, PartialEq, Serialize)]
598pub struct Tool {
599    #[serde(serialize_with = "flatten_array")]
600    pub rules: Vec<ToolRule>,
601    #[serde(skip_serializing_if = "is_default")]
602    pub default_mining_speed: f32,
603    #[var]
604    #[serde(skip_serializing_if = "is_default")]
605    pub damage_per_block: i32,
606    #[serde(skip_serializing_if = "is_default")]
607    pub can_destroy_blocks_in_creative: bool,
608}
609
610impl Tool {
611    pub const fn new() -> Self {
612        Tool {
613            rules: vec![],
614            default_mining_speed: 1.,
615            damage_per_block: 1,
616            can_destroy_blocks_in_creative: true,
617        }
618    }
619}
620impl Default for Tool {
621    fn default() -> Self {
622        Self::new()
623    }
624}
625
626#[derive(AzBuf, Clone, Debug, PartialEq, Serialize)]
627#[serde(transparent)]
628pub struct StoredEnchantments {
629    #[var]
630    pub enchantments: HashMap<Enchantment, i32>,
631}
632
633#[derive(AzBuf, Clone, Debug, PartialEq, Serialize)]
634#[serde(transparent)]
635pub struct DyedColor {
636    pub rgb: i32,
637}
638
639#[derive(AzBuf, Clone, Debug, PartialEq, Serialize)]
640#[serde(transparent)]
641pub struct MapColor {
642    pub color: i32,
643}
644
645#[derive(AzBuf, Clone, Debug, PartialEq, Serialize)]
646#[serde(transparent)]
647pub struct MapId {
648    #[var]
649    pub id: i32,
650}
651
652#[derive(AzBuf, Clone, Debug, PartialEq, Serialize)]
653#[serde(transparent)]
654pub struct MapDecorations {
655    pub decorations: NbtCompound,
656}
657
658#[derive(AzBuf, Clone, Copy, Debug, PartialEq, Serialize)]
659pub enum MapPostProcessing {
660    Lock,
661    Scale,
662}
663
664#[derive(AzBuf, Clone, Debug, PartialEq, Serialize)]
665#[serde(transparent)]
666pub struct ChargedProjectiles {
667    pub items: Vec<ItemStack>,
668}
669
670#[derive(AzBuf, Clone, Debug, PartialEq, Serialize)]
671#[serde(transparent)]
672pub struct BundleContents {
673    pub items: Vec<ItemStack>,
674}
675
676#[derive(AzBuf, Clone, Debug, PartialEq, Serialize)]
677pub struct PotionContents {
678    #[serde(skip_serializing_if = "is_default")]
679    pub potion: Option<Potion>,
680    #[serde(skip_serializing_if = "is_default")]
681    pub custom_color: Option<i32>,
682    #[serde(skip_serializing_if = "is_default")]
683    pub custom_effects: Vec<MobEffectInstance>,
684    #[serde(skip_serializing_if = "is_default")]
685    pub custom_name: Option<String>,
686}
687
688impl PotionContents {
689    pub const fn new() -> Self {
690        PotionContents {
691            potion: None,
692            custom_color: None,
693            custom_effects: vec![],
694            custom_name: None,
695        }
696    }
697}
698impl Default for PotionContents {
699    fn default() -> Self {
700        Self::new()
701    }
702}
703
704#[derive(AzBuf, Clone, Debug, PartialEq, Serialize)]
705pub struct SuspiciousStewEffect {
706    #[serde(rename = "id")]
707    pub effect: MobEffect,
708    #[var]
709    #[serde(skip_serializing_if = "is_default")]
710    pub duration: i32,
711}
712
713#[derive(AzBuf, Clone, Debug, PartialEq, Serialize)]
714#[serde(transparent)]
715pub struct SuspiciousStewEffects {
716    pub effects: Vec<SuspiciousStewEffect>,
717}
718
719#[derive(AzBuf, Clone, Debug, PartialEq, Serialize)]
720pub struct WritableBookContent {
721    pub pages: Vec<Filterable<String>>,
722}
723
724#[derive(AzBuf, Clone, PartialEq, Serialize, Debug)]
725pub struct WrittenBookContent {
726    #[limit(32)]
727    pub title: Filterable<String>,
728    pub author: String,
729    #[var]
730    #[serde(skip_serializing_if = "is_default")]
731    pub generation: i32,
732    #[serde(skip_serializing_if = "is_default")]
733    pub pages: Vec<Filterable<FormattedText>>,
734    #[serde(skip_serializing_if = "is_default")]
735    pub resolved: bool,
736}
737
738#[derive(AzBuf, Clone, Debug, PartialEq, Serialize)]
739pub struct Trim {
740    pub material: TrimMaterial,
741    pub pattern: TrimPattern,
742}
743
744#[derive(AzBuf, Clone, Debug, PartialEq, Serialize)]
745#[serde(transparent)]
746pub struct DebugStickState {
747    pub properties: NbtCompound,
748}
749
750#[derive(AzBuf, Clone, Debug, PartialEq, Serialize)]
751pub struct EntityData {
752    #[serde(rename = "id")]
753    pub kind: EntityKind,
754    #[serde(flatten)]
755    pub data: NbtCompound,
756}
757
758#[derive(AzBuf, Clone, Debug, PartialEq, Serialize)]
759#[serde(transparent)]
760pub struct BucketEntityData {
761    pub entity: NbtCompound,
762}
763
764#[derive(AzBuf, Clone, Debug, PartialEq, Serialize)]
765pub struct BlockEntityData {
766    #[serde(rename = "id")]
767    pub kind: EntityKind,
768    #[serde(flatten)]
769    pub data: NbtCompound,
770}
771
772#[derive(AzBuf, Clone, Debug, PartialEq, Serialize)]
773#[serde(transparent)]
774pub struct Instrument {
775    pub value: Holder<azalea_registry::data::Instrument, InstrumentData>,
776}
777
778#[derive(AzBuf, Clone, Debug, PartialEq, Serialize)]
779pub struct InstrumentData {
780    pub sound_event: Holder<SoundEvent, azalea_core::sound::CustomSound>,
781    pub use_duration: f32,
782    pub range: f32,
783    pub description: FormattedText,
784}
785
786#[derive(AzBuf, Clone, Debug, PartialEq, Serialize)]
787#[serde(transparent)]
788pub struct OminousBottleAmplifier {
789    #[var]
790    pub amplifier: i32,
791}
792
793#[derive(AzBuf, Clone, Debug, PartialEq, Serialize)]
794#[serde(transparent)]
795pub struct Recipes {
796    pub recipes: Vec<Identifier>,
797}
798
799#[derive(AzBuf, Clone, Debug, PartialEq, Serialize)]
800pub struct LodestoneTracker {
801    #[serde(skip_serializing_if = "is_default")]
802    pub target: Option<GlobalPos>,
803    #[serde(skip_serializing_if = "is_true")]
804    pub tracked: bool,
805}
806
807#[derive(AzBuf, Clone, Copy, Debug, PartialEq, Serialize)]
808#[serde(rename_all = "snake_case")]
809pub enum FireworkExplosionShape {
810    SmallBall,
811    LargeBall,
812    Star,
813    Creeper,
814    Burst,
815}
816
817#[derive(AzBuf, Clone, Debug, PartialEq, Serialize)]
818pub struct FireworkExplosion {
819    pub shape: FireworkExplosionShape,
820    #[serde(skip_serializing_if = "is_default")]
821    pub colors: Vec<i32>,
822    #[serde(skip_serializing_if = "is_default")]
823    pub fade_colors: Vec<i32>,
824    #[serde(skip_serializing_if = "is_default")]
825    pub has_trail: bool,
826    #[serde(skip_serializing_if = "is_default")]
827    pub has_twinkle: bool,
828}
829
830#[derive(AzBuf, Clone, Debug, PartialEq, Serialize)]
831pub struct Fireworks {
832    #[var]
833    #[serde(skip_serializing_if = "is_default")]
834    pub flight_duration: i32,
835    #[limit(256)]
836    pub explosions: Vec<FireworkExplosion>,
837}
838
839impl Fireworks {
840    pub const fn new() -> Self {
841        Fireworks {
842            flight_duration: 0,
843            explosions: vec![],
844        }
845    }
846}
847impl Default for Fireworks {
848    fn default() -> Self {
849        Self::new()
850    }
851}
852
853#[derive(AzBuf, Clone, Debug, PartialEq, Serialize)]
854#[serde(transparent)]
855pub struct NoteBlockSound {
856    pub sound: Identifier,
857}
858
859#[derive(AzBuf, Clone, Debug, PartialEq, Serialize)]
860pub struct BannerPatternLayer {
861    #[var]
862    pub pattern: i32,
863    #[var]
864    pub color: i32,
865}
866
867#[derive(AzBuf, Clone, Debug, PartialEq, Serialize)]
868#[serde(transparent)]
869pub struct BannerPatterns {
870    pub patterns: Vec<BannerPatternLayer>,
871}
872
873#[derive(AzBuf, Clone, Copy, Debug, PartialEq, Serialize)]
874#[serde(rename_all = "snake_case")]
875pub enum DyeColor {
876    White,
877    Orange,
878    Magenta,
879    LightBlue,
880    Yellow,
881    Lime,
882    Pink,
883    Gray,
884    LightGray,
885    Cyan,
886    Purple,
887    Blue,
888    Brown,
889    Green,
890    Red,
891    Black,
892}
893
894#[derive(AzBuf, Clone, Debug, PartialEq, Serialize)]
895#[serde(transparent)]
896pub struct BaseColor {
897    pub color: DyeColor,
898}
899
900#[derive(AzBuf, Clone, Debug, PartialEq, Serialize)]
901#[serde(transparent)]
902pub struct PotDecorations {
903    pub items: Vec<ItemKind>,
904}
905
906#[derive(AzBuf, Clone, Debug, PartialEq, Serialize)]
907#[serde(transparent)]
908pub struct Container {
909    pub items: Vec<ItemStack>,
910}
911
912#[derive(AzBuf, Clone, Debug, PartialEq, Serialize)]
913#[serde(transparent)]
914pub struct BlockState {
915    pub properties: HashMap<String, String>,
916}
917
918#[derive(AzBuf, Clone, Debug, PartialEq, Serialize)]
919pub struct BeehiveOccupant {
920    #[serde(skip_serializing_if = "is_default")]
921    pub entity_data: NbtCompound,
922    #[var]
923    pub ticks_in_hive: i32,
924    #[var]
925    pub min_ticks_in_hive: i32,
926}
927
928#[derive(AzBuf, Clone, Debug, PartialEq, Serialize)]
929#[serde(transparent)]
930pub struct Bees {
931    pub occupants: Vec<BeehiveOccupant>,
932}
933
934#[derive(AzBuf, Clone, Debug, PartialEq, Serialize)]
935pub struct Lock {
936    pub key: String,
937}
938
939#[derive(AzBuf, Clone, Debug, PartialEq, Serialize)]
940pub struct ContainerLoot {
941    pub loot_table: NbtCompound,
942}
943
944#[derive(AzBuf, Clone, Debug, PartialEq, Serialize)]
945#[serde(transparent)]
946pub struct JukeboxPlayable {
947    pub value: Holder<azalea_registry::data::JukeboxSong, JukeboxSongData>,
948}
949
950#[derive(AzBuf, Clone, Debug, PartialEq, Serialize)]
951pub struct JukeboxSongData {
952    pub sound_event: Holder<SoundEvent, CustomSound>,
953    pub description: FormattedText,
954    pub length_in_seconds: f32,
955    #[var]
956    pub comparator_output: i32,
957}
958
959#[derive(AzBuf, Clone, Debug, PartialEq, Serialize)]
960pub struct Consumable {
961    #[serde(skip_serializing_if = "is_default")]
962    pub consume_seconds: f32,
963    #[serde(skip_serializing_if = "is_default")]
964    pub animation: ItemUseAnimation,
965    #[serde(skip_serializing_if = "is_default_eat_sound")]
966    pub sound: azalea_registry::Holder<SoundEvent, CustomSound>,
967    #[serde(skip_serializing_if = "is_default")]
968    pub has_consume_particles: bool,
969    #[serde(skip_serializing_if = "is_default")]
970    pub on_consume_effects: Vec<ConsumeEffect>,
971}
972fn is_default_eat_sound(sound: &azalea_registry::Holder<SoundEvent, CustomSound>) -> bool {
973    matches!(
974        sound,
975        azalea_registry::Holder::Reference(SoundEvent::EntityGenericEat)
976    )
977}
978
979impl Consumable {
980    pub const fn new() -> Self {
981        Self {
982            consume_seconds: 1.6,
983            animation: ItemUseAnimation::Eat,
984            sound: azalea_registry::Holder::Reference(SoundEvent::EntityGenericEat),
985            has_consume_particles: true,
986            on_consume_effects: Vec::new(),
987        }
988    }
989}
990impl Default for Consumable {
991    fn default() -> Self {
992        Self::new()
993    }
994}
995
996#[derive(AzBuf, Clone, Copy, Debug, Default, PartialEq, Serialize)]
997#[serde(rename_all = "snake_case")]
998pub enum ItemUseAnimation {
999    #[default]
1000    None,
1001    Eat,
1002    Drink,
1003    BlockKind,
1004    Bow,
1005    Spear,
1006    Crossbow,
1007    Spyglass,
1008    TootHorn,
1009    Brush,
1010}
1011
1012#[derive(AzBuf, Clone, Debug, PartialEq, Serialize)]
1013#[serde(transparent)]
1014pub struct UseRemainder {
1015    pub convert_into: ItemStack,
1016}
1017
1018#[derive(AzBuf, Clone, Debug, PartialEq, Serialize)]
1019pub struct UseCooldown {
1020    pub seconds: f32,
1021    #[serde(skip_serializing_if = "is_default")]
1022    pub cooldown_group: Option<Identifier>,
1023}
1024
1025impl UseCooldown {
1026    pub const fn new() -> Self {
1027        Self {
1028            seconds: 0.,
1029            cooldown_group: None,
1030        }
1031    }
1032}
1033impl Default for UseCooldown {
1034    fn default() -> Self {
1035        Self::new()
1036    }
1037}
1038
1039#[derive(AzBuf, Clone, Debug, PartialEq, Serialize)]
1040pub struct Enchantable {
1041    #[var]
1042    pub value: u32,
1043}
1044
1045#[derive(AzBuf, Clone, Debug, PartialEq, Serialize)]
1046pub struct Repairable {
1047    pub items: HolderSet<ItemKind, Identifier>,
1048}
1049
1050#[derive(AzBuf, Clone, Debug, PartialEq, Serialize)]
1051#[serde(transparent)]
1052pub struct ItemModel {
1053    pub resource_location: Identifier,
1054}
1055
1056#[derive(AzBuf, Clone, Debug, PartialEq, Serialize)]
1057pub struct DamageResistant {
1058    pub types: HolderSet<DamageKind, Identifier>,
1059}
1060
1061#[derive(AzBuf, Clone, Debug, PartialEq, Serialize)]
1062pub struct Equippable {
1063    pub slot: EquipmentSlot,
1064    #[serde(skip_serializing_if = "is_default_equip_sound")]
1065    pub equip_sound: SoundEvent,
1066    #[serde(skip_serializing_if = "is_default")]
1067    pub asset_id: Option<Identifier>,
1068    #[serde(skip_serializing_if = "is_default")]
1069    pub camera_overlay: Option<Identifier>,
1070    #[serde(skip_serializing_if = "is_default")]
1071    pub allowed_entities: Option<HolderSet<EntityKind, Identifier>>,
1072    #[serde(skip_serializing_if = "is_true")]
1073    pub dispensable: bool,
1074    #[serde(skip_serializing_if = "is_true")]
1075    pub swappable: bool,
1076    #[serde(skip_serializing_if = "is_true")]
1077    pub damage_on_hurt: bool,
1078    #[serde(skip_serializing_if = "is_default")]
1079    pub equip_on_interact: bool,
1080    #[serde(skip_serializing_if = "is_default")]
1081    pub can_be_sheared: bool,
1082    #[serde(skip_serializing_if = "is_default_shearing_sound")]
1083    pub shearing_sound: SoundEvent,
1084}
1085fn is_default_equip_sound(sound: &SoundEvent) -> bool {
1086    matches!(sound, SoundEvent::ItemArmorEquipGeneric)
1087}
1088fn is_default_shearing_sound(sound: &SoundEvent) -> bool {
1089    matches!(sound, SoundEvent::ItemShearsSnip)
1090}
1091
1092impl Equippable {
1093    pub const fn new() -> Self {
1094        Self {
1095            slot: EquipmentSlot::Body,
1096            equip_sound: SoundEvent::ItemArmorEquipGeneric,
1097            asset_id: None,
1098            camera_overlay: None,
1099            allowed_entities: None,
1100            dispensable: true,
1101            swappable: true,
1102            damage_on_hurt: true,
1103            equip_on_interact: false,
1104            can_be_sheared: false,
1105            shearing_sound: SoundEvent::ItemShearsSnip,
1106        }
1107    }
1108}
1109impl Default for Equippable {
1110    fn default() -> Self {
1111        Self::new()
1112    }
1113}
1114
1115/// An enum that represents inventory slots that can hold items.
1116#[derive(AzBuf, Clone, Copy, Debug, Eq, Hash, PartialEq, Serialize)]
1117#[serde(rename_all = "snake_case")]
1118pub enum EquipmentSlot {
1119    Mainhand,
1120    Offhand,
1121    Feet,
1122    Legs,
1123    Chest,
1124    Head,
1125    /// This is for animal armor, use [`Self::Chest`] for the chestplate slot.
1126    Body,
1127    Saddle,
1128}
1129impl EquipmentSlot {
1130    #[must_use]
1131    pub fn from_byte(byte: u8) -> Option<Self> {
1132        let value = match byte {
1133            0 => Self::Mainhand,
1134            1 => Self::Offhand,
1135            2 => Self::Feet,
1136            3 => Self::Legs,
1137            4 => Self::Chest,
1138            5 => Self::Head,
1139            6 => Self::Body,
1140            7 => Self::Saddle,
1141            _ => return None,
1142        };
1143        Some(value)
1144    }
1145    pub fn values() -> [Self; 8] {
1146        [
1147            Self::Mainhand,
1148            Self::Offhand,
1149            Self::Feet,
1150            Self::Legs,
1151            Self::Chest,
1152            Self::Head,
1153            Self::Body,
1154            Self::Saddle,
1155        ]
1156    }
1157    /// Get the display name for the equipment slot, like "mainhand".
1158    pub fn name(self) -> &'static str {
1159        match self {
1160            Self::Mainhand => "mainhand",
1161            Self::Offhand => "offhand",
1162            Self::Feet => "feet",
1163            Self::Legs => "legs",
1164            Self::Chest => "chest",
1165            Self::Head => "head",
1166            Self::Body => "body",
1167            Self::Saddle => "saddle",
1168        }
1169    }
1170}
1171impl Display for EquipmentSlot {
1172    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1173        write!(f, "{}", self.name())
1174    }
1175}
1176
1177#[derive(AzBuf, Clone, Debug, PartialEq, Serialize)]
1178pub struct Glider;
1179
1180#[derive(AzBuf, Clone, Debug, PartialEq, Serialize)]
1181#[serde(transparent)]
1182pub struct TooltipStyle {
1183    pub resource_location: Identifier,
1184}
1185
1186#[derive(AzBuf, Clone, Debug, PartialEq, Serialize)]
1187pub struct DeathProtection {
1188    pub death_effects: Vec<ConsumeEffect>,
1189}
1190
1191#[derive(AzBuf, Clone, Debug, PartialEq, Serialize)]
1192pub struct Weapon {
1193    #[var]
1194    #[serde(skip_serializing_if = "is_default_item_damage_per_attack")]
1195    pub item_damage_per_attack: i32,
1196    #[serde(skip_serializing_if = "is_default")]
1197    pub disable_blocking_for_seconds: f32,
1198}
1199fn is_default_item_damage_per_attack(value: &i32) -> bool {
1200    *value == 1
1201}
1202
1203impl Weapon {
1204    pub const fn new() -> Self {
1205        Self {
1206            item_damage_per_attack: 1,
1207            disable_blocking_for_seconds: 0.,
1208        }
1209    }
1210}
1211impl Default for Weapon {
1212    fn default() -> Self {
1213        Self::new()
1214    }
1215}
1216
1217#[derive(AzBuf, Clone, Debug, PartialEq, Serialize)]
1218#[serde(transparent)]
1219pub struct PotionDurationScale {
1220    pub value: f32,
1221}
1222
1223#[derive(AzBuf, Clone, Debug, PartialEq, Serialize)]
1224#[serde(transparent)]
1225pub struct VillagerVariant {
1226    pub variant: VillagerKind,
1227}
1228
1229#[derive(AzBuf, Clone, Debug, PartialEq, Serialize)]
1230#[serde(transparent)]
1231pub struct WolfVariant {
1232    pub variant: data::WolfVariant,
1233}
1234
1235#[derive(AzBuf, Clone, Debug, PartialEq, Serialize)]
1236#[serde(transparent)]
1237pub struct WolfCollar {
1238    pub color: DyeColor,
1239}
1240
1241#[derive(AzBuf, Clone, Debug, PartialEq, Serialize)]
1242#[serde(transparent)]
1243pub struct FoxVariant {
1244    pub variant: FoxVariantKind,
1245}
1246
1247#[derive(AzBuf, Clone, Copy, Debug, Default, PartialEq)]
1248pub enum FoxVariantKind {
1249    #[default]
1250    Red,
1251    Snow,
1252}
1253impl Display for FoxVariantKind {
1254    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1255        match self {
1256            Self::Red => write!(f, "minecraft:red"),
1257            Self::Snow => write!(f, "minecraft:snow"),
1258        }
1259    }
1260}
1261impl Serialize for FoxVariantKind {
1262    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
1263    where
1264        S: Serializer,
1265    {
1266        serializer.serialize_str(&self.to_string())
1267    }
1268}
1269
1270#[derive(AzBuf, Clone, Copy, Debug, PartialEq, Serialize)]
1271#[serde(rename_all = "snake_case")]
1272pub enum SalmonSize {
1273    Small,
1274    Medium,
1275    Large,
1276}
1277
1278#[derive(AzBuf, Clone, Debug, PartialEq, Serialize)]
1279#[serde(transparent)]
1280pub struct ParrotVariant {
1281    pub variant: ParrotVariantKind,
1282}
1283#[derive(AzBuf, Clone, Copy, Debug, PartialEq)]
1284pub enum ParrotVariantKind {
1285    RedBlue,
1286    Blue,
1287    Green,
1288    YellowBlue,
1289    Gray,
1290}
1291impl Display for ParrotVariantKind {
1292    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1293        match self {
1294            Self::RedBlue => write!(f, "minecraft:red_blue"),
1295            Self::Blue => write!(f, "minecraft:blue"),
1296            Self::Green => write!(f, "minecraft:green"),
1297            Self::YellowBlue => write!(f, "minecraft:yellow_blue"),
1298            Self::Gray => write!(f, "minecraft:gray"),
1299        }
1300    }
1301}
1302impl Serialize for ParrotVariantKind {
1303    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
1304    where
1305        S: Serializer,
1306    {
1307        serializer.serialize_str(&self.to_string())
1308    }
1309}
1310
1311#[derive(AzBuf, Clone, Copy, Debug, PartialEq, Serialize)]
1312#[serde(rename_all = "snake_case")]
1313pub enum TropicalFishPattern {
1314    Kob,
1315    Sunstreak,
1316    Snooper,
1317    Dasher,
1318    Brinely,
1319    Spotty,
1320    Flopper,
1321    Stripey,
1322    Glitter,
1323    Blockfish,
1324    Betty,
1325    Clayfish,
1326}
1327
1328#[derive(AzBuf, Clone, Debug, PartialEq, Serialize)]
1329#[serde(transparent)]
1330pub struct TropicalFishBaseColor {
1331    pub color: DyeColor,
1332}
1333
1334#[derive(AzBuf, Clone, Debug, PartialEq, Serialize)]
1335#[serde(transparent)]
1336pub struct TropicalFishPatternColor {
1337    pub color: DyeColor,
1338}
1339
1340#[derive(AzBuf, Clone, Debug, PartialEq, Serialize)]
1341#[serde(transparent)]
1342pub struct MooshroomVariant {
1343    pub variant: MooshroomVariantKind,
1344}
1345#[derive(AzBuf, Clone, Copy, Debug, Default, PartialEq)]
1346pub enum MooshroomVariantKind {
1347    #[default]
1348    Red,
1349    Brown,
1350}
1351impl Display for MooshroomVariantKind {
1352    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1353        match self {
1354            Self::Red => write!(f, "minecraft:red"),
1355            Self::Brown => write!(f, "minecraft:brown"),
1356        }
1357    }
1358}
1359impl Serialize for MooshroomVariantKind {
1360    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
1361    where
1362        S: Serializer,
1363    {
1364        serializer.serialize_str(&self.to_string())
1365    }
1366}
1367
1368#[derive(AzBuf, Clone, Debug, PartialEq, Serialize)]
1369#[serde(transparent)]
1370pub struct RabbitVariant {
1371    pub variant: RabbitVariantKind,
1372}
1373#[derive(AzBuf, Clone, Copy, Debug, Default, PartialEq)]
1374pub enum RabbitVariantKind {
1375    #[default]
1376    Brown,
1377    White,
1378    Black,
1379    WhiteSplotched,
1380    Gold,
1381    Salt,
1382    Evil,
1383}
1384impl Display for RabbitVariantKind {
1385    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1386        match self {
1387            Self::Brown => write!(f, "minecraft:brown"),
1388            Self::White => write!(f, "minecraft:white"),
1389            Self::Black => write!(f, "minecraft:black"),
1390            Self::WhiteSplotched => write!(f, "minecraft:white_splotched"),
1391            Self::Gold => write!(f, "minecraft:gold"),
1392            Self::Salt => write!(f, "minecraft:salt"),
1393            Self::Evil => write!(f, "minecraft:evil"),
1394        }
1395    }
1396}
1397impl Serialize for RabbitVariantKind {
1398    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
1399    where
1400        S: Serializer,
1401    {
1402        serializer.serialize_str(&self.to_string())
1403    }
1404}
1405
1406#[derive(AzBuf, Clone, Debug, PartialEq, Serialize)]
1407#[serde(transparent)]
1408pub struct PigVariant {
1409    pub variant: data::PigVariant,
1410}
1411
1412#[derive(AzBuf, Clone, Debug, PartialEq, Serialize)]
1413#[serde(transparent)]
1414pub struct FrogVariant {
1415    pub variant: data::FrogVariant,
1416}
1417
1418#[derive(AzBuf, Clone, Debug, PartialEq, Serialize)]
1419#[serde(transparent)]
1420pub struct HorseVariant {
1421    pub variant: HorseVariantKind,
1422}
1423#[derive(AzBuf, Clone, Copy, Debug, Default, PartialEq)]
1424pub enum HorseVariantKind {
1425    #[default]
1426    White,
1427    Creamy,
1428    Chestnut,
1429    Brown,
1430    Black,
1431    Gray,
1432    DarkBrown,
1433}
1434impl Display for HorseVariantKind {
1435    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1436        match self {
1437            Self::White => write!(f, "minecraft:white"),
1438            Self::Creamy => write!(f, "minecraft:creamy"),
1439            Self::Chestnut => write!(f, "minecraft:chestnut"),
1440            Self::Brown => write!(f, "minecraft:brown"),
1441            Self::Black => write!(f, "minecraft:black"),
1442            Self::Gray => write!(f, "minecraft:gray"),
1443            Self::DarkBrown => write!(f, "minecraft:dark_brown"),
1444        }
1445    }
1446}
1447impl Serialize for HorseVariantKind {
1448    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
1449    where
1450        S: Serializer,
1451    {
1452        serializer.serialize_str(&self.to_string())
1453    }
1454}
1455
1456#[derive(AzBuf, Clone, Debug, PartialEq, Serialize)]
1457#[serde(transparent)]
1458pub struct PaintingVariant {
1459    pub variant: Holder<data::PaintingVariant, PaintingVariantData>,
1460}
1461
1462#[derive(AzBuf, Clone, Debug, PartialEq, Serialize)]
1463pub struct PaintingVariantData {
1464    #[var]
1465    pub width: i32,
1466    #[var]
1467    pub height: i32,
1468    pub asset_id: Identifier,
1469    #[serde(skip_serializing_if = "is_default")]
1470    pub title: Option<FormattedText>,
1471    #[serde(skip_serializing_if = "is_default")]
1472    pub author: Option<FormattedText>,
1473}
1474
1475#[derive(AzBuf, Clone, Debug, PartialEq, Serialize)]
1476#[serde(transparent)]
1477pub struct LlamaVariant {
1478    pub variant: LlamaVariantKind,
1479}
1480#[derive(AzBuf, Clone, Copy, Debug, Default, PartialEq)]
1481pub enum LlamaVariantKind {
1482    #[default]
1483    Creamy,
1484    White,
1485    Brown,
1486    Gray,
1487}
1488impl Display for LlamaVariantKind {
1489    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1490        match self {
1491            Self::Creamy => write!(f, "minecraft:creamy"),
1492            Self::White => write!(f, "minecraft:white"),
1493            Self::Brown => write!(f, "minecraft:brown"),
1494            Self::Gray => write!(f, "minecraft:gray"),
1495        }
1496    }
1497}
1498impl Serialize for LlamaVariantKind {
1499    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
1500    where
1501        S: Serializer,
1502    {
1503        serializer.serialize_str(&self.to_string())
1504    }
1505}
1506
1507#[derive(AzBuf, Clone, Debug, PartialEq, Serialize)]
1508#[serde(transparent)]
1509pub struct AxolotlVariant {
1510    pub variant: AxolotlVariantKind,
1511}
1512#[derive(AzBuf, Clone, Copy, Debug, Default, PartialEq)]
1513pub enum AxolotlVariantKind {
1514    #[default]
1515    Lucy,
1516    Wild,
1517    Gold,
1518    Cyan,
1519    Blue,
1520}
1521impl Display for AxolotlVariantKind {
1522    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1523        match self {
1524            Self::Lucy => write!(f, "minecraft:lucy"),
1525            Self::Wild => write!(f, "minecraft:wild"),
1526            Self::Gold => write!(f, "minecraft:gold"),
1527            Self::Cyan => write!(f, "minecraft:cyan"),
1528            Self::Blue => write!(f, "minecraft:blue"),
1529        }
1530    }
1531}
1532impl Serialize for AxolotlVariantKind {
1533    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
1534    where
1535        S: Serializer,
1536    {
1537        serializer.serialize_str(&self.to_string())
1538    }
1539}
1540
1541#[derive(AzBuf, Clone, Debug, PartialEq, Serialize)]
1542#[serde(transparent)]
1543pub struct CatVariant {
1544    pub variant: data::CatVariant,
1545}
1546
1547#[derive(AzBuf, Clone, Debug, PartialEq, Serialize)]
1548#[serde(transparent)]
1549pub struct CatCollar {
1550    pub color: DyeColor,
1551}
1552
1553#[derive(AzBuf, Clone, Debug, PartialEq, Serialize)]
1554#[serde(transparent)]
1555pub struct SheepColor {
1556    pub color: DyeColor,
1557}
1558
1559#[derive(AzBuf, Clone, Debug, PartialEq, Serialize)]
1560#[serde(transparent)]
1561pub struct ShulkerColor {
1562    pub color: DyeColor,
1563}
1564
1565#[derive(AzBuf, Clone, Debug, PartialEq, Serialize)]
1566pub struct TooltipDisplay {
1567    #[serde(skip_serializing_if = "is_default")]
1568    pub hide_tooltip: bool,
1569    #[serde(skip_serializing_if = "is_default")]
1570    pub hidden_components: Vec<DataComponentKind>,
1571}
1572
1573impl TooltipDisplay {
1574    pub const fn new() -> Self {
1575        Self {
1576            hide_tooltip: false,
1577            hidden_components: Vec::new(),
1578        }
1579    }
1580}
1581impl Default for TooltipDisplay {
1582    fn default() -> Self {
1583        Self::new()
1584    }
1585}
1586
1587#[derive(AzBuf, Clone, Debug, PartialEq, Serialize)]
1588pub struct BlocksAttacks {
1589    #[serde(skip_serializing_if = "is_default")]
1590    pub block_delay_seconds: f32,
1591    #[serde(skip_serializing_if = "is_default_disable_cooldown_scale")]
1592    pub disable_cooldown_scale: f32,
1593    #[serde(skip_serializing_if = "is_default")]
1594    pub damage_reductions: Vec<DamageReduction>,
1595    #[serde(skip_serializing_if = "is_default")]
1596    pub item_damage: ItemDamageFunction,
1597    #[serde(skip_serializing_if = "is_default")]
1598    pub bypassed_by: Option<HolderSet<DamageKind, Identifier>>,
1599    #[serde(skip_serializing_if = "is_default")]
1600    pub block_sound: Option<azalea_registry::Holder<SoundEvent, CustomSound>>,
1601    #[serde(skip_serializing_if = "is_default")]
1602    pub disabled_sound: Option<azalea_registry::Holder<SoundEvent, CustomSound>>,
1603}
1604fn is_default_disable_cooldown_scale(value: &f32) -> bool {
1605    *value == 1.
1606}
1607
1608impl BlocksAttacks {
1609    pub fn new() -> Self {
1610        Self {
1611            block_delay_seconds: 0.,
1612            disable_cooldown_scale: 1.,
1613            damage_reductions: vec![DamageReduction {
1614                horizontal_blocking_angle: 90.,
1615                kind: None,
1616                base: 0.,
1617                factor: 1.,
1618            }],
1619            item_damage: ItemDamageFunction::default(),
1620            bypassed_by: None,
1621            block_sound: None,
1622            disabled_sound: None,
1623        }
1624    }
1625}
1626impl Default for BlocksAttacks {
1627    fn default() -> Self {
1628        Self::new()
1629    }
1630}
1631
1632#[derive(AzBuf, Clone, Debug, PartialEq, Serialize)]
1633pub struct DamageReduction {
1634    #[serde(skip_serializing_if = "is_default_horizontal_blocking_angle")]
1635    pub horizontal_blocking_angle: f32,
1636    #[serde(skip_serializing_if = "is_default")]
1637    pub kind: Option<HolderSet<DamageKind, Identifier>>,
1638    pub base: f32,
1639    pub factor: f32,
1640}
1641fn is_default_horizontal_blocking_angle(value: &f32) -> bool {
1642    *value == 90.
1643}
1644#[derive(AzBuf, Clone, Debug, PartialEq, Serialize)]
1645pub struct ItemDamageFunction {
1646    pub threshold: f32,
1647    pub base: f32,
1648    pub factor: f32,
1649}
1650impl Default for ItemDamageFunction {
1651    fn default() -> Self {
1652        ItemDamageFunction {
1653            threshold: 1.,
1654            base: 0.,
1655            factor: 1.,
1656        }
1657    }
1658}
1659
1660#[derive(AzBuf, Clone, Debug, PartialEq, Serialize)]
1661#[serde(transparent)]
1662pub struct ProvidesTrimMaterial {
1663    pub value: Holder<azalea_registry::data::TrimMaterial, DirectTrimMaterial>,
1664}
1665
1666#[derive(AzBuf, Clone, Debug, PartialEq, Serialize)]
1667pub struct DirectTrimMaterial {
1668    #[serde(flatten)]
1669    pub assets: MaterialAssetGroup,
1670    pub description: FormattedText,
1671}
1672#[derive(AzBuf, Clone, Debug, PartialEq, Serialize)]
1673pub struct MaterialAssetGroup {
1674    pub assert_name: AssetInfo,
1675    #[serde(skip_serializing_if = "is_default")]
1676    pub override_armor_assets: Vec<(Identifier, AssetInfo)>,
1677}
1678
1679#[derive(AzBuf, Clone, Debug, PartialEq, Serialize)]
1680#[serde(transparent)]
1681pub struct AssetInfo {
1682    pub suffix: String,
1683}
1684
1685#[derive(AzBuf, Clone, Debug, PartialEq, Serialize)]
1686#[serde(transparent)]
1687pub struct ProvidesBannerPatterns {
1688    pub key: HolderSet<BannerPatternKind, Identifier>,
1689}
1690
1691#[derive(AzBuf, Clone, Debug, PartialEq, Serialize)]
1692#[serde(transparent)]
1693pub struct BreakSound {
1694    pub sound: azalea_registry::Holder<SoundEvent, CustomSound>,
1695}
1696
1697#[derive(AzBuf, Clone, Debug, PartialEq, Serialize)]
1698#[serde(transparent)]
1699pub struct WolfSoundVariant {
1700    pub variant: azalea_registry::data::WolfSoundVariant,
1701}
1702
1703#[derive(AzBuf, Clone, Debug, PartialEq, Serialize)]
1704#[serde(transparent)]
1705pub struct CowVariant {
1706    pub variant: azalea_registry::data::CowVariant,
1707}
1708
1709#[derive(AzBuf, Clone, Debug, PartialEq, Serialize)]
1710#[serde(transparent)]
1711pub struct ChickenVariant {
1712    pub data: azalea_registry::data::ChickenVariant,
1713}
1714
1715#[derive(AzBuf, Clone, Debug, PartialEq, Serialize)]
1716#[serde(transparent)]
1717pub struct ZombieNautilusVariant {
1718    pub value: azalea_registry::data::ZombieNautilusVariant,
1719}
1720
1721#[derive(AzBuf, Clone, Debug, PartialEq, Serialize)]
1722pub struct UseEffects {
1723    pub can_sprint: bool,
1724    pub interact_vibrations: bool,
1725    pub speed_multiplier: f32,
1726}
1727impl UseEffects {
1728    pub const fn new() -> Self {
1729        Self {
1730            can_sprint: false,
1731            interact_vibrations: true,
1732            speed_multiplier: 0.2,
1733        }
1734    }
1735}
1736impl Default for UseEffects {
1737    fn default() -> Self {
1738        Self::new()
1739    }
1740}
1741
1742#[derive(AzBuf, Clone, Debug, PartialEq, Serialize)]
1743#[serde(transparent)]
1744pub struct MinimumAttackCharge {
1745    pub value: f32,
1746}
1747
1748#[derive(AzBuf, Clone, Debug, PartialEq, Serialize)]
1749#[serde(transparent)]
1750pub struct DamageType {
1751    pub value: azalea_registry::data::DamageKind,
1752}
1753
1754#[derive(AzBuf, Clone, Debug, PartialEq, Serialize)]
1755pub struct PiercingWeapon {
1756    pub deals_knockback: bool,
1757    pub dismounts: bool,
1758    pub sound: Option<Holder<SoundEvent, azalea_core::sound::CustomSound>>,
1759    pub hit_sound: Option<Holder<SoundEvent, azalea_core::sound::CustomSound>>,
1760}
1761impl PiercingWeapon {
1762    pub const fn new() -> Self {
1763        Self {
1764            deals_knockback: true,
1765            dismounts: false,
1766            sound: None,
1767            hit_sound: None,
1768        }
1769    }
1770}
1771impl Default for PiercingWeapon {
1772    fn default() -> Self {
1773        Self::new()
1774    }
1775}
1776
1777#[derive(AzBuf, Clone, Debug, PartialEq, Serialize)]
1778pub struct KineticWeapon {
1779    #[var]
1780    pub contact_cooldown_ticks: i32,
1781    #[var]
1782    pub delay_ticks: i32,
1783    pub dismount_conditions: Option<KineticWeaponCondition>,
1784    pub knockback_conditions: Option<KineticWeaponCondition>,
1785    pub damage_conditions: Option<KineticWeaponCondition>,
1786    pub forward_movement: f32,
1787    pub damage_multiplier: f32,
1788    pub sound: Option<Holder<SoundEvent, azalea_core::sound::CustomSound>>,
1789    pub hit_sound: Option<Holder<SoundEvent, azalea_core::sound::CustomSound>>,
1790}
1791impl KineticWeapon {
1792    pub const fn new() -> Self {
1793        Self {
1794            contact_cooldown_ticks: 10,
1795            delay_ticks: 0,
1796            dismount_conditions: None,
1797            knockback_conditions: None,
1798            damage_conditions: None,
1799            forward_movement: 0.,
1800            damage_multiplier: 1.,
1801            sound: None,
1802            hit_sound: None,
1803        }
1804    }
1805}
1806impl Default for KineticWeapon {
1807    fn default() -> Self {
1808        Self::new()
1809    }
1810}
1811
1812#[derive(AzBuf, Clone, Debug, PartialEq, Serialize)]
1813pub struct KineticWeaponCondition {
1814    #[var]
1815    pub max_duration_ticks: i32,
1816    pub min_speed: f32,
1817    pub min_relative_speed: f32,
1818}
1819impl KineticWeaponCondition {
1820    pub const fn new() -> Self {
1821        Self {
1822            max_duration_ticks: 0,
1823            min_speed: 0.,
1824            min_relative_speed: 0.,
1825        }
1826    }
1827}
1828impl Default for KineticWeaponCondition {
1829    fn default() -> Self {
1830        Self::new()
1831    }
1832}
1833
1834#[derive(AzBuf, Clone, Debug, PartialEq, Serialize)]
1835pub struct SwingAnimation {
1836    #[serde(rename = "type")]
1837    pub kind: SwingAnimationKind,
1838    #[var]
1839    pub duration: i32,
1840}
1841impl SwingAnimation {
1842    pub const fn new() -> Self {
1843        Self {
1844            kind: SwingAnimationKind::Whack,
1845            duration: 6,
1846        }
1847    }
1848}
1849impl Default for SwingAnimation {
1850    fn default() -> Self {
1851        Self::new()
1852    }
1853}
1854
1855#[derive(AzBuf, Clone, Copy, Debug, PartialEq, Serialize)]
1856#[serde(rename_all = "snake_case")]
1857pub enum SwingAnimationKind {
1858    None,
1859    Whack,
1860    Stab,
1861}
1862
1863#[derive(AzBuf, Clone, Debug, PartialEq, Serialize)]
1864pub struct AttackRange {
1865    pub min_reach: f32,
1866    pub max_reach: f32,
1867    pub min_creative_reach: f32,
1868    pub max_creative_reach: f32,
1869    pub hitbox_margin: f32,
1870    pub mob_factor: f32,
1871}
1872impl AttackRange {
1873    pub const fn new() -> Self {
1874        Self {
1875            min_reach: 0.,
1876            max_reach: 3.,
1877            min_creative_reach: 0.,
1878            max_creative_reach: 5.,
1879            hitbox_margin: 0.3,
1880            mob_factor: 1.,
1881        }
1882    }
1883}
1884impl Default for AttackRange {
1885    fn default() -> Self {
1886        Self::new()
1887    }
1888}
1889
1890#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)]
1891#[serde(transparent)]
1892pub struct AdditionalTradeCost {
1893    #[var]
1894    pub cost: i32,
1895}
1896
1897#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)]
1898#[serde(transparent)]
1899pub struct Dye {
1900    pub color: DyeColor,
1901}
1902
1903#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)]
1904#[serde(transparent)]
1905pub struct PigSoundVariant {
1906    pub value: azalea_registry::data::PigSoundVariant,
1907}
1908
1909#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)]
1910#[serde(transparent)]
1911pub struct CowSoundVariant {
1912    pub value: azalea_registry::data::CowSoundVariant,
1913}
1914
1915#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)]
1916#[serde(transparent)]
1917pub struct ChickenSoundVariant {
1918    pub value: azalea_registry::data::ChickenSoundVariant,
1919}
1920
1921#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)]
1922#[serde(transparent)]
1923pub struct CatSoundVariant {
1924    pub value: azalea_registry::data::CatSoundVariant,
1925}
1926
1927#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)]
1928#[serde(transparent)]
1929pub struct SulfurCubeContent {
1930    pub absorbed_block_item_stack: ItemStack,
1931}