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