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 fn clone(&self) -> Box<dyn EncodableDataComponent>;
43 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 #[allow(non_snake_case)]
83 pub union DataComponentUnion {
84 $( $x: ManuallyDrop<$x>, )*
85 }
86 impl DataComponentUnion {
87 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 pub unsafe fn drop_as(&mut self, kind: DataComponentKind) {
103 match kind {
104 $( DataComponentKind::$x => { unsafe { ManuallyDrop::drop(&mut self.$x) } }, )*
105 }
106 }
107 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 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 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 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
185define_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 }
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#[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 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}