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