azalea_inventory/
components.rs

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