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