diff options
| author | mat <27899617+mat-1@users.noreply.github.com> | 2025-08-10 18:55:23 -0500 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-08-10 18:55:23 -0500 |
| commit | 7120842f9d2c659a2f12d8922299c2a761bc5582 (patch) | |
| tree | 0d7976ceec82d914e4c75f23adcdd5839f9960a4 /azalea-inventory/src | |
| parent | 3b659833c1ad4cca89b4cd553193edcb6d223163 (diff) | |
| download | azalea-drasl-7120842f9d2c659a2f12d8922299c2a761bc5582.tar.xz | |
Send correct data component checksums (#234)
* start implementing data component crc32 hashes
* start doing serde impls for checksums
* make more components hashable
* make all data components serializable
* support recursive components
* fix simdnbt dep
* update changelog
* clippy
Diffstat (limited to 'azalea-inventory/src')
| -rw-r--r-- | azalea-inventory/src/components.rs | 1122 | ||||
| -rw-r--r-- | azalea-inventory/src/default_components/generated.rs | 274 | ||||
| -rw-r--r-- | azalea-inventory/src/default_components/mod.rs | 6 | ||||
| -rw-r--r-- | azalea-inventory/src/item/consume_effect.rs | 10 | ||||
| -rw-r--r-- | azalea-inventory/src/slot.rs | 117 |
5 files changed, 813 insertions, 716 deletions
diff --git a/azalea-inventory/src/components.rs b/azalea-inventory/src/components.rs index e11a4491..09923af0 100644 --- a/azalea-inventory/src/components.rs +++ b/azalea-inventory/src/components.rs @@ -3,30 +3,40 @@ use std::{ any::Any, collections::HashMap, io::{self, Cursor}, + mem::ManuallyDrop, }; use azalea_buf::{AzBuf, AzaleaRead, AzaleaWrite, BufReadError}; use azalea_chat::FormattedText; use azalea_core::{ - filterable::Filterable, position::GlobalPos, resource_location::ResourceLocation, + checksum::{Checksum, get_checksum}, + codec_utils::*, + filterable::Filterable, + position::GlobalPos, + registry_holder::RegistryHolder, + resource_location::ResourceLocation, sound::CustomSound, }; use azalea_registry::{ self as registry, Attribute, Block, DamageKind, DataComponentKind, Enchantment, EntityKind, Holder, HolderSet, Item, MobEffect, Potion, SoundEvent, TrimMaterial, TrimPattern, }; +use serde::{Serialize, ser::SerializeMap}; use simdnbt::owned::{Nbt, NbtCompound}; use tracing::trace; use uuid::Uuid; use crate::{ItemStack, item::consume_effect::ConsumeEffect}; -pub trait DataComponent: Send + Sync + Any + Clone { +pub trait DataComponentTrait: + Send + Sync + Any + Clone + Serialize + Into<DataComponentUnion> +{ const KIND: DataComponentKind; } pub trait EncodableDataComponent: Send + Sync + Any { fn encode(&self, buf: &mut Vec<u8>) -> io::Result<()>; + fn crc_hash(&self, registries: &RegistryHolder) -> Checksum; // using the Clone trait makes it not be object-safe, so we have our own clone // function instead fn clone(&self) -> Box<dyn EncodableDataComponent>; @@ -36,11 +46,14 @@ pub trait EncodableDataComponent: Send + Sync + Any { impl<T> EncodableDataComponent for T where - T: DataComponent + Clone + AzaleaWrite + AzaleaRead + PartialEq, + T: DataComponentTrait + Clone + AzaleaWrite + AzaleaRead + PartialEq, { fn encode(&self, buf: &mut Vec<u8>) -> io::Result<()> { self.azalea_write(buf) } + fn crc_hash(&self, registries: &RegistryHolder) -> Checksum { + get_checksum(self, registries).expect("serializing data components should always succeed") + } fn clone(&self) -> Box<dyn EncodableDataComponent> { let cloned = self.clone(); Box::new(cloned) @@ -54,220 +67,286 @@ where } } -pub fn from_kind( - kind: registry::DataComponentKind, - buf: &mut Cursor<&[u8]>, -) -> Result<Box<dyn EncodableDataComponent>, BufReadError> { - // if this is causing a compile-time error, look at DataComponents.java in the - // decompiled vanilla code to see how to implement new components - - trace!("Reading data component {kind}"); - - // note that this match statement is updated by genitemcomponents.py - Ok(match kind { - DataComponentKind::CustomData => Box::new(CustomData::azalea_read(buf)?), - DataComponentKind::MaxStackSize => Box::new(MaxStackSize::azalea_read(buf)?), - DataComponentKind::MaxDamage => Box::new(MaxDamage::azalea_read(buf)?), - DataComponentKind::Damage => Box::new(Damage::azalea_read(buf)?), - DataComponentKind::Unbreakable => Box::new(Unbreakable::azalea_read(buf)?), - DataComponentKind::CustomName => Box::new(CustomName::azalea_read(buf)?), - DataComponentKind::ItemName => Box::new(ItemName::azalea_read(buf)?), - DataComponentKind::Lore => Box::new(Lore::azalea_read(buf)?), - DataComponentKind::Rarity => Box::new(Rarity::azalea_read(buf)?), - DataComponentKind::Enchantments => Box::new(Enchantments::azalea_read(buf)?), - DataComponentKind::CanPlaceOn => Box::new(CanPlaceOn::azalea_read(buf)?), - DataComponentKind::CanBreak => Box::new(CanBreak::azalea_read(buf)?), - DataComponentKind::AttributeModifiers => Box::new(AttributeModifiers::azalea_read(buf)?), - DataComponentKind::CustomModelData => Box::new(CustomModelData::azalea_read(buf)?), - DataComponentKind::RepairCost => Box::new(RepairCost::azalea_read(buf)?), - DataComponentKind::CreativeSlotLock => Box::new(CreativeSlotLock::azalea_read(buf)?), - DataComponentKind::EnchantmentGlintOverride => { - Box::new(EnchantmentGlintOverride::azalea_read(buf)?) - } - DataComponentKind::IntangibleProjectile => { - Box::new(IntangibleProjectile::azalea_read(buf)?) - } - DataComponentKind::Food => Box::new(Food::azalea_read(buf)?), - DataComponentKind::Tool => Box::new(Tool::azalea_read(buf)?), - DataComponentKind::StoredEnchantments => Box::new(StoredEnchantments::azalea_read(buf)?), - DataComponentKind::DyedColor => Box::new(DyedColor::azalea_read(buf)?), - DataComponentKind::MapColor => Box::new(MapColor::azalea_read(buf)?), - DataComponentKind::MapId => Box::new(MapId::azalea_read(buf)?), - DataComponentKind::MapDecorations => Box::new(MapDecorations::azalea_read(buf)?), - DataComponentKind::MapPostProcessing => Box::new(MapPostProcessing::azalea_read(buf)?), - DataComponentKind::ChargedProjectiles => Box::new(ChargedProjectiles::azalea_read(buf)?), - DataComponentKind::BundleContents => Box::new(BundleContents::azalea_read(buf)?), - DataComponentKind::PotionContents => Box::new(PotionContents::azalea_read(buf)?), - DataComponentKind::SuspiciousStewEffects => { - Box::new(SuspiciousStewEffects::azalea_read(buf)?) - } - DataComponentKind::WritableBookContent => Box::new(WritableBookContent::azalea_read(buf)?), - DataComponentKind::WrittenBookContent => Box::new(WrittenBookContent::azalea_read(buf)?), - DataComponentKind::Trim => Box::new(Trim::azalea_read(buf)?), - DataComponentKind::DebugStickState => Box::new(DebugStickState::azalea_read(buf)?), - DataComponentKind::EntityData => Box::new(EntityData::azalea_read(buf)?), - DataComponentKind::BucketEntityData => Box::new(BucketEntityData::azalea_read(buf)?), - DataComponentKind::BlockEntityData => Box::new(BlockEntityData::azalea_read(buf)?), - DataComponentKind::Instrument => Box::new(Instrument::azalea_read(buf)?), - DataComponentKind::OminousBottleAmplifier => { - Box::new(OminousBottleAmplifier::azalea_read(buf)?) +#[macro_export] +macro_rules! define_data_components { + ( $( $x:ident ),* $(,)? ) => { + /// A union of all data components. + /// + /// You probably don't want to use this directly. Consider [`DataComponentPatch`] instead. + /// + /// This type does not know its own value, and as such every function for it requires the + /// `DataComponentKind` to be passed in. Passing the wrong `DataComponentKind` will result + /// in undefined behavior. Also, all of the values are `ManuallyDrop`. + /// + /// [`DataComponentPatch`]: crate::DataComponentPatch + #[allow(non_snake_case)] + pub union DataComponentUnion { + $( $x: ManuallyDrop<$x>, )* } - DataComponentKind::Recipes => Box::new(Recipes::azalea_read(buf)?), - DataComponentKind::LodestoneTracker => Box::new(LodestoneTracker::azalea_read(buf)?), - DataComponentKind::FireworkExplosion => Box::new(FireworkExplosion::azalea_read(buf)?), - DataComponentKind::Fireworks => Box::new(Fireworks::azalea_read(buf)?), - DataComponentKind::Profile => Box::new(Profile::azalea_read(buf)?), - DataComponentKind::NoteBlockSound => Box::new(NoteBlockSound::azalea_read(buf)?), - DataComponentKind::BannerPatterns => Box::new(BannerPatterns::azalea_read(buf)?), - DataComponentKind::BaseColor => Box::new(BaseColor::azalea_read(buf)?), - DataComponentKind::PotDecorations => Box::new(PotDecorations::azalea_read(buf)?), - DataComponentKind::Container => Box::new(Container::azalea_read(buf)?), - DataComponentKind::BlockState => Box::new(BlockState::azalea_read(buf)?), - DataComponentKind::Bees => Box::new(Bees::azalea_read(buf)?), - DataComponentKind::Lock => Box::new(Lock::azalea_read(buf)?), - DataComponentKind::ContainerLoot => Box::new(ContainerLoot::azalea_read(buf)?), - DataComponentKind::JukeboxPlayable => Box::new(JukeboxPlayable::azalea_read(buf)?), - DataComponentKind::Consumable => Box::new(Consumable::azalea_read(buf)?), - DataComponentKind::UseRemainder => Box::new(UseRemainder::azalea_read(buf)?), - DataComponentKind::UseCooldown => Box::new(UseCooldown::azalea_read(buf)?), - DataComponentKind::Enchantable => Box::new(Enchantable::azalea_read(buf)?), - DataComponentKind::Repairable => Box::new(Repairable::azalea_read(buf)?), - DataComponentKind::ItemModel => Box::new(ItemModel::azalea_read(buf)?), - DataComponentKind::DamageResistant => Box::new(DamageResistant::azalea_read(buf)?), - DataComponentKind::Equippable => Box::new(Equippable::azalea_read(buf)?), - DataComponentKind::Glider => Box::new(Glider::azalea_read(buf)?), - DataComponentKind::TooltipStyle => Box::new(TooltipStyle::azalea_read(buf)?), - DataComponentKind::DeathProtection => Box::new(DeathProtection::azalea_read(buf)?), - DataComponentKind::Weapon => Box::new(Weapon::azalea_read(buf)?), - DataComponentKind::PotionDurationScale => Box::new(PotionDurationScale::azalea_read(buf)?), - DataComponentKind::VillagerVariant => Box::new(VillagerVariant::azalea_read(buf)?), - DataComponentKind::WolfVariant => Box::new(WolfVariant::azalea_read(buf)?), - DataComponentKind::WolfCollar => Box::new(WolfCollar::azalea_read(buf)?), - DataComponentKind::FoxVariant => Box::new(FoxVariant::azalea_read(buf)?), - DataComponentKind::SalmonSize => Box::new(SalmonSize::azalea_read(buf)?), - DataComponentKind::ParrotVariant => Box::new(ParrotVariant::azalea_read(buf)?), - DataComponentKind::TropicalFishPattern => Box::new(TropicalFishPattern::azalea_read(buf)?), - DataComponentKind::TropicalFishBaseColor => { - Box::new(TropicalFishBaseColor::azalea_read(buf)?) + impl DataComponentUnion { + /// # Safety + /// + /// `kind` must be the correct value for this union. + pub unsafe fn serialize_entry_as<S: SerializeMap>( + &self, + serializer: &mut S, + kind: DataComponentKind, + ) -> Result<(), S::Error> { + match kind { + $( DataComponentKind::$x => { unsafe { serializer.serialize_entry(&kind, &*self.$x) } }, )* + } + } + /// # Safety + /// + /// `kind` must be the correct value for this union. + pub unsafe fn drop_as(&mut self, kind: DataComponentKind) { + match kind { + $( DataComponentKind::$x => { unsafe { ManuallyDrop::drop(&mut self.$x) } }, )* + } + } + /// # Safety + /// + /// `kind` must be the correct value for this union. + pub unsafe fn as_kind(&self, kind: DataComponentKind) -> &dyn EncodableDataComponent { + match kind { + $( DataComponentKind::$x => { unsafe { &**(&self.$x as &ManuallyDrop<dyn EncodableDataComponent>) } }, )* + } + } + pub fn azalea_read_as( + kind: registry::DataComponentKind, + buf: &mut Cursor<&[u8]>, + ) -> Result<Self, BufReadError> { + trace!("Reading data component {kind}"); + + Ok(match kind { + $( DataComponentKind::$x => { + Self { $x: ManuallyDrop::new($x::azalea_read(buf)?) } + }, )* + }) + } + /// # Safety + /// + /// `kind` must be the correct value for this union. + pub unsafe fn azalea_write_as( + &self, + kind: registry::DataComponentKind, + buf: &mut Vec<u8>, + ) -> io::Result<()> { + match kind { + $( DataComponentKind::$x => unsafe { self.$x.encode(buf) }, )* + } + } + /// # Safety + /// + /// `kind` must be the correct value for this union. + pub unsafe fn clone_as( + &self, + kind: registry::DataComponentKind, + ) -> Self { + match kind { + $( DataComponentKind::$x => { + Self { $x: unsafe { self.$x.clone() } } + }, )* + } + } + /// # Safety + /// + /// `kind` must be the correct value for this union. + pub unsafe fn eq_as( + &self, + other: &Self, + kind: registry::DataComponentKind, + ) -> bool { + match kind { + $( DataComponentKind::$x => unsafe { self.$x.eq(&other.$x) }, )* + } + } } - DataComponentKind::TropicalFishPatternColor => { - Box::new(TropicalFishPatternColor::azalea_read(buf)?) - } - DataComponentKind::MooshroomVariant => Box::new(MooshroomVariant::azalea_read(buf)?), - DataComponentKind::RabbitVariant => Box::new(RabbitVariant::azalea_read(buf)?), - DataComponentKind::PigVariant => Box::new(PigVariant::azalea_read(buf)?), - DataComponentKind::FrogVariant => Box::new(FrogVariant::azalea_read(buf)?), - DataComponentKind::HorseVariant => Box::new(HorseVariant::azalea_read(buf)?), - DataComponentKind::PaintingVariant => Box::new(PaintingVariant::azalea_read(buf)?), - DataComponentKind::LlamaVariant => Box::new(LlamaVariant::azalea_read(buf)?), - DataComponentKind::AxolotlVariant => Box::new(AxolotlVariant::azalea_read(buf)?), - DataComponentKind::CatVariant => Box::new(CatVariant::azalea_read(buf)?), - DataComponentKind::CatCollar => Box::new(CatCollar::azalea_read(buf)?), - DataComponentKind::SheepColor => Box::new(SheepColor::azalea_read(buf)?), - DataComponentKind::ShulkerColor => Box::new(ShulkerColor::azalea_read(buf)?), - DataComponentKind::TooltipDisplay => Box::new(TooltipDisplay::azalea_read(buf)?), - DataComponentKind::BlocksAttacks => Box::new(BlocksAttacks::azalea_read(buf)?), - DataComponentKind::ProvidesTrimMaterial => { - Box::new(ProvidesTrimMaterial::azalea_read(buf)?) - } - DataComponentKind::ProvidesBannerPatterns => { - Box::new(ProvidesBannerPatterns::azalea_read(buf)?) - } - DataComponentKind::BreakSound => Box::new(BreakSound::azalea_read(buf)?), - DataComponentKind::WolfSoundVariant => Box::new(WolfSoundVariant::azalea_read(buf)?), - DataComponentKind::CowVariant => Box::new(CowVariant::azalea_read(buf)?), - DataComponentKind::ChickenVariant => Box::new(ChickenVariant::azalea_read(buf)?), - }) -} - -#[derive(Clone, PartialEq, AzBuf)] + $( + impl From<$x> for DataComponentUnion { + fn from(value: $x) -> Self { + DataComponentUnion { $x: ManuallyDrop::new(value) } + } + } + )* + + $( + impl DataComponentTrait for $x { + const KIND: DataComponentKind = DataComponentKind::$x; + } + )* + }; +} + +// if this is causing a compile-time error, look at DataComponents.java in the +// decompiled vanilla code to see how to implement new components + +// note that this statement is updated by genitemcomponents.py +define_data_components!( + CustomData, + MaxStackSize, + MaxDamage, + Damage, + Unbreakable, + CustomName, + ItemName, + ItemModel, + Lore, + Rarity, + Enchantments, + CanPlaceOn, + CanBreak, + AttributeModifiers, + CustomModelData, + TooltipDisplay, + RepairCost, + CreativeSlotLock, + EnchantmentGlintOverride, + IntangibleProjectile, + Food, + Consumable, + UseRemainder, + UseCooldown, + DamageResistant, + Tool, + Weapon, + Enchantable, + Equippable, + Repairable, + Glider, + TooltipStyle, + DeathProtection, + BlocksAttacks, + StoredEnchantments, + DyedColor, + MapColor, + MapId, + MapDecorations, + MapPostProcessing, + ChargedProjectiles, + BundleContents, + PotionContents, + PotionDurationScale, + SuspiciousStewEffects, + WritableBookContent, + WrittenBookContent, + Trim, + DebugStickState, + EntityData, + BucketEntityData, + BlockEntityData, + Instrument, + ProvidesTrimMaterial, + OminousBottleAmplifier, + JukeboxPlayable, + ProvidesBannerPatterns, + Recipes, + LodestoneTracker, + FireworkExplosion, + Fireworks, + Profile, + NoteBlockSound, + BannerPatterns, + BaseColor, + PotDecorations, + Container, + BlockState, + Bees, + Lock, + ContainerLoot, + BreakSound, + VillagerVariant, + WolfVariant, + WolfSoundVariant, + WolfCollar, + FoxVariant, + SalmonSize, + ParrotVariant, + TropicalFishPattern, + TropicalFishBaseColor, + TropicalFishPatternColor, + MooshroomVariant, + RabbitVariant, + PigVariant, + CowVariant, + ChickenVariant, + FrogVariant, + HorseVariant, + PaintingVariant, + LlamaVariant, + AxolotlVariant, + CatVariant, + CatCollar, + SheepColor, + ShulkerColor, +); + +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] +#[serde(transparent)] pub struct CustomData { pub nbt: Nbt, } -impl DataComponent for CustomData { - const KIND: DataComponentKind = DataComponentKind::CustomData; -} -#[derive(Clone, PartialEq, AzBuf)] +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] +#[serde(transparent)] pub struct MaxStackSize { #[var] pub count: i32, } -impl DataComponent for MaxStackSize { - const KIND: DataComponentKind = DataComponentKind::MaxStackSize; -} -#[derive(Clone, PartialEq, AzBuf)] +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] +#[serde(transparent)] pub struct MaxDamage { #[var] pub amount: i32, } -impl DataComponent for MaxDamage { - const KIND: DataComponentKind = DataComponentKind::MaxDamage; -} -#[derive(Clone, PartialEq, AzBuf)] +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] +#[serde(transparent)] pub struct Damage { #[var] pub amount: i32, } -impl DataComponent for Damage { - const KIND: DataComponentKind = DataComponentKind::Damage; -} - -#[derive(Clone, PartialEq, Default, AzBuf)] +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] pub struct Unbreakable; -impl DataComponent for Unbreakable { - const KIND: DataComponentKind = DataComponentKind::Unbreakable; -} -#[derive(Clone, PartialEq, AzBuf)] +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] +#[serde(transparent)] pub struct CustomName { pub name: FormattedText, } -impl DataComponent for CustomName { - const KIND: DataComponentKind = DataComponentKind::CustomName; -} -#[derive(Clone, PartialEq, AzBuf)] +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] +#[serde(transparent)] pub struct ItemName { pub name: FormattedText, } -impl DataComponent for ItemName { - const KIND: DataComponentKind = DataComponentKind::ItemName; -} -#[derive(Clone, PartialEq, AzBuf)] +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] +#[serde(transparent)] pub struct Lore { pub lines: Vec<FormattedText>, // vanilla also has styled_lines here but it doesn't appear to be used for the protocol } -impl DataComponent for Lore { - const KIND: DataComponentKind = DataComponentKind::Lore; -} -#[derive(Clone, PartialEq, Copy, AzBuf)] +#[derive(Clone, Copy, PartialEq, AzBuf, Debug, Serialize)] +#[serde(rename_all = "snake_case")] pub enum Rarity { Common, Uncommon, Rare, Epic, } -impl DataComponent for Rarity { - const KIND: DataComponentKind = DataComponentKind::Rarity; -} -#[derive(Clone, PartialEq, AzBuf)] +#[derive(Clone, PartialEq, AzBuf, Serialize)] +#[serde(transparent)] pub struct Enchantments { #[var] pub levels: HashMap<Enchantment, u32>, } -impl DataComponent for Enchantments { - const KIND: DataComponentKind = DataComponentKind::Enchantments; -} -#[derive(Clone, PartialEq, AzBuf)] +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] pub enum BlockStateValueMatcher { Exact { value: String, @@ -278,41 +357,43 @@ pub enum BlockStateValueMatcher { }, } -#[derive(Clone, PartialEq, AzBuf)] +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] pub struct BlockStatePropertyMatcher { pub name: String, pub value_matcher: BlockStateValueMatcher, } -#[derive(Clone, PartialEq, AzBuf)] +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] pub struct BlockPredicate { + #[serde(skip_serializing_if = "is_default")] pub blocks: Option<HolderSet<Block, ResourceLocation>>, + #[serde(skip_serializing_if = "is_default")] pub properties: Option<Vec<BlockStatePropertyMatcher>>, + #[serde(skip_serializing_if = "is_default")] pub nbt: Option<NbtCompound>, } -#[derive(Clone, PartialEq, AzBuf)] +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] +#[serde(transparent)] pub struct AdventureModePredicate { + #[serde(serialize_with = "flatten_array")] pub predicates: Vec<BlockPredicate>, } -#[derive(Clone, PartialEq, AzBuf)] +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] +#[serde(transparent)] pub struct CanPlaceOn { pub predicate: AdventureModePredicate, } -impl DataComponent for CanPlaceOn { - const KIND: DataComponentKind = DataComponentKind::CanPlaceOn; -} -#[derive(Clone, PartialEq, AzBuf)] +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] +#[serde(transparent)] pub struct CanBreak { pub predicate: AdventureModePredicate, } -impl DataComponent for CanBreak { - const KIND: DataComponentKind = DataComponentKind::CanBreak; -} -#[derive(Clone, Copy, PartialEq, AzBuf)] +#[derive(Clone, Copy, PartialEq, AzBuf, Debug, Serialize)] +#[serde(rename_all = "snake_case")] pub enum EquipmentSlotGroup { Any, Mainhand, @@ -326,7 +407,8 @@ pub enum EquipmentSlotGroup { Body, } -#[derive(Clone, Copy, PartialEq, AzBuf)] +#[derive(Clone, Copy, PartialEq, AzBuf, Debug, Serialize)] +#[serde(rename_all = "snake_case")] pub enum AttributeModifierOperation { AddValue, AddMultipliedBase, @@ -336,85 +418,86 @@ pub enum AttributeModifierOperation { // this is duplicated in azalea-entity, BUT the one there has a different // protocol format (and we can't use it anyways because it would cause a // circular dependency) -#[derive(Clone, PartialEq, AzBuf)] +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] pub struct AttributeModifier { pub id: ResourceLocation, pub amount: f64, pub operation: AttributeModifierOperation, } -#[derive(Clone, PartialEq, AzBuf)] +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] pub struct AttributeModifiersEntry { - pub attribute: Attribute, + #[serde(rename = "type")] + pub kind: Attribute, + #[serde(flatten)] pub modifier: AttributeModifier, pub slot: EquipmentSlotGroup, + #[serde(skip_serializing_if = "is_default")] pub display: AttributeModifierDisplay, } -#[derive(Clone, PartialEq, AzBuf)] +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] +#[serde(transparent)] pub struct AttributeModifiers { pub modifiers: Vec<AttributeModifiersEntry>, } -impl DataComponent for AttributeModifiers { - const KIND: DataComponentKind = DataComponentKind::AttributeModifiers; -} -#[derive(Clone, PartialEq, AzBuf)] +#[derive(Clone, PartialEq, AzBuf, Debug, Default, Serialize)] +#[serde(rename_all = "snake_case")] pub enum AttributeModifierDisplay { + #[default] Default, Hidden, - Override { text: FormattedText }, + Override { + text: FormattedText, + }, } -#[derive(Clone, PartialEq, AzBuf)] +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] pub struct CustomModelData { + #[serde(skip_serializing_if = "Vec::is_empty")] pub floats: Vec<f32>, + #[serde(skip_serializing_if = "Vec::is_empty")] pub flags: Vec<bool>, + #[serde(skip_serializing_if = "Vec::is_empty")] pub strings: Vec<String>, + #[serde(skip_serializing_if = "Vec::is_empty")] pub colors: Vec<i32>, } -impl DataComponent for CustomModelData { - const KIND: DataComponentKind = DataComponentKind::CustomModelData; -} -#[derive(Clone, PartialEq, AzBuf)] +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] +#[serde(transparent)] pub struct RepairCost { #[var] pub cost: u32, } -impl DataComponent for RepairCost { - const KIND: DataComponentKind = DataComponentKind::RepairCost; -} -#[derive(Clone, PartialEq, AzBuf)] +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] pub struct CreativeSlotLock; -impl DataComponent for CreativeSlotLock { - const KIND: DataComponentKind = DataComponentKind::CreativeSlotLock; -} -#[derive(Clone, PartialEq, AzBuf)] +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] +#[serde(transparent)] pub struct EnchantmentGlintOverride { pub show_glint: bool, } -impl DataComponent for EnchantmentGlintOverride { - const KIND: DataComponentKind = DataComponentKind::EnchantmentGlintOverride; -} -#[derive(Clone, PartialEq, AzBuf)] +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] pub struct IntangibleProjectile; -impl DataComponent for IntangibleProjectile { - const KIND: DataComponentKind = DataComponentKind::IntangibleProjectile; -} -#[derive(Clone, PartialEq, AzBuf)] +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] pub struct MobEffectDetails { #[var] + #[serde(skip_serializing_if = "is_default")] pub amplifier: i32, #[var] + #[serde(skip_serializing_if = "is_default")] pub duration: i32, + #[serde(skip_serializing_if = "is_default")] pub ambient: bool, + #[serde(skip_serializing_if = "is_default")] pub show_particles: bool, pub show_icon: bool, + #[serde(skip_serializing_if = "is_default")] pub hidden_effect: Option<Box<MobEffectDetails>>, } impl MobEffectDetails { @@ -424,7 +507,7 @@ impl MobEffectDetails { duration: 0, ambient: false, show_particles: true, - show_icon: false, + show_icon: true, hidden_effect: None, } } @@ -435,28 +518,28 @@ impl Default for MobEffectDetails { } } -#[derive(Clone, PartialEq, AzBuf)] +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] pub struct MobEffectInstance { pub id: MobEffect, + #[serde(flatten)] pub details: MobEffectDetails, } -#[derive(Clone, PartialEq, AzBuf)] +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] pub struct PossibleEffect { pub effect: MobEffectInstance, pub probability: f32, } -#[derive(Clone, PartialEq, Default, AzBuf)] +#[derive(Clone, PartialEq, AzBuf, Debug, Default, Serialize)] pub struct Food { #[var] pub nutrition: i32, pub saturation: f32, + #[serde(skip_serializing_if = "is_default")] pub can_always_eat: bool, } -impl DataComponent for Food { - const KIND: DataComponentKind = DataComponentKind::Food; -} + impl Food { pub const fn new() -> Self { Food { @@ -467,10 +550,12 @@ impl Food { } } -#[derive(Clone, PartialEq, AzBuf)] +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] pub struct ToolRule { pub blocks: HolderSet<Block, ResourceLocation>, + #[serde(skip_serializing_if = "is_default")] pub speed: Option<f32>, + #[serde(skip_serializing_if = "is_default")] pub correct_for_drops: Option<bool>, } impl ToolRule { @@ -488,17 +573,19 @@ impl Default for ToolRule { } } -#[derive(Clone, PartialEq, AzBuf)] +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] pub struct Tool { + #[serde(serialize_with = "flatten_array")] pub rules: Vec<ToolRule>, + #[serde(skip_serializing_if = "is_default")] pub default_mining_speed: f32, #[var] + #[serde(skip_serializing_if = "is_default")] pub damage_per_block: i32, + #[serde(skip_serializing_if = "is_default")] pub can_destroy_blocks_in_creative: bool, } -impl DataComponent for Tool { - const KIND: DataComponentKind = DataComponentKind::Tool; -} + impl Tool { pub const fn new() -> Self { Tool { @@ -515,83 +602,68 @@ impl Default for Tool { } } -#[derive(Clone, PartialEq, AzBuf)] +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] +#[serde(transparent)] pub struct StoredEnchantments { #[var] pub enchantments: HashMap<Enchantment, i32>, } -impl DataComponent for StoredEnchantments { - const KIND: DataComponentKind = DataComponentKind::StoredEnchantments; -} -#[derive(Clone, PartialEq, AzBuf)] +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] +#[serde(transparent)] pub struct DyedColor { pub rgb: i32, } -impl DataComponent for DyedColor { - const KIND: DataComponentKind = DataComponentKind::DyedColor; -} -#[derive(Clone, PartialEq, AzBuf)] +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] +#[serde(transparent)] pub struct MapColor { pub color: i32, } -impl DataComponent for MapColor { - const KIND: DataComponentKind = DataComponentKind::MapColor; -} -#[derive(Clone, PartialEq, AzBuf)] +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] +#[serde(transparent)] pub struct MapId { #[var] pub id: i32, } -impl DataComponent for MapId { - const KIND: DataComponentKind = DataComponentKind::MapId; -} -#[derive(Clone, PartialEq, AzBuf)] +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] +#[serde(transparent)] pub struct MapDecorations { pub decorations: NbtCompound, } -impl DataComponent for MapDecorations { - const KIND: DataComponentKind = DataComponentKind::MapDecorations; -} -#[derive(Clone, Copy, PartialEq, AzBuf)] +#[derive(Clone, Copy, PartialEq, AzBuf, Debug, Serialize)] pub enum MapPostProcessing { Lock, Scale, } -impl DataComponent for MapPostProcessing { - const KIND: DataComponentKind = DataComponentKind::MapPostProcessing; -} -#[derive(Clone, PartialEq, AzBuf)] +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] +#[serde(transparent)] pub struct ChargedProjectiles { pub items: Vec<ItemStack>, } -impl DataComponent for ChargedProjectiles { - const KIND: DataComponentKind = DataComponentKind::ChargedProjectiles; -} -#[derive(Clone, PartialEq, AzBuf)] +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] +#[serde(transparent)] pub struct BundleContents { pub items: Vec<ItemStack>, } -impl DataComponent for BundleContents { - const KIND: DataComponentKind = DataComponentKind::BundleContents; -} -#[derive(Clone, PartialEq, AzBuf)] +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] pub struct PotionContents { + #[serde(skip_serializing_if = "is_default")] pub potion: Option<Potion>, + #[serde(skip_serializing_if = "is_default")] pub custom_color: Option<i32>, + #[serde(skip_serializing_if = "is_default")] pub custom_effects: Vec<MobEffectInstance>, + #[serde(skip_serializing_if = "is_default")] pub custom_name: Option<String>, } -impl DataComponent for PotionContents { - const KIND: DataComponentKind = DataComponentKind::PotionContents; -} + impl PotionContents { pub const fn new() -> Self { PotionContents { @@ -608,95 +680,78 @@ impl Default for PotionContents { } } -#[derive(Clone, PartialEq, AzBuf)] +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] pub struct SuspiciousStewEffect { + #[serde(rename = "id")] pub effect: MobEffect, #[var] + #[serde(skip_serializing_if = "is_default")] pub duration: i32, } -#[derive(Clone, PartialEq, AzBuf)] +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] +#[serde(transparent)] pub struct SuspiciousStewEffects { pub effects: Vec<SuspiciousStewEffect>, } -impl DataComponent for SuspiciousStewEffects { - const KIND: DataComponentKind = DataComponentKind::SuspiciousStewEffects; -} -#[derive(Clone, PartialEq, AzBuf)] +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] pub struct WritableBookContent { pub pages: Vec<String>, } -impl DataComponent for WritableBookContent { - const KIND: DataComponentKind = DataComponentKind::WritableBookContent; -} -#[derive(Clone, PartialEq, AzBuf)] +#[derive(Clone, PartialEq, AzBuf, Serialize)] pub struct WrittenBookContent { #[limit(32)] pub title: Filterable<String>, pub author: String, #[var] + #[serde(skip_serializing_if = "is_default")] pub generation: i32, + #[serde(skip_serializing_if = "is_default")] pub pages: Vec<Filterable<FormattedText>>, + #[serde(skip_serializing_if = "is_default")] pub resolved: bool, } -impl DataComponent for WrittenBookContent { - const KIND: DataComponentKind = DataComponentKind::WrittenBookContent; -} - -#[derive(Clone, PartialEq, AzBuf)] +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] pub struct Trim { pub material: TrimMaterial, pub pattern: TrimPattern, } -impl DataComponent for Trim { - const KIND: DataComponentKind = DataComponentKind::Trim; -} -#[derive(Clone, PartialEq, AzBuf)] +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] +#[serde(transparent)] pub struct DebugStickState { pub properties: NbtCompound, } -impl DataComponent for DebugStickState { - const KIND: DataComponentKind = DataComponentKind::DebugStickState; -} -#[derive(Clone, PartialEq, AzBuf)] +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] +#[serde(transparent)] pub struct EntityData { pub entity: NbtCompound, } -impl DataComponent for EntityData { - const KIND: DataComponentKind = DataComponentKind::EntityData; -} -#[derive(Clone, PartialEq, AzBuf)] +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] +#[serde(transparent)] pub struct BucketEntityData { pub entity: NbtCompound, } -impl DataComponent for BucketEntityData { - const KIND: DataComponentKind = DataComponentKind::BucketEntityData; -} -#[derive(Clone, PartialEq, AzBuf)] +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] +#[serde(transparent)] pub struct BlockEntityData { pub entity: NbtCompound, } -impl DataComponent for BlockEntityData { - const KIND: DataComponentKind = DataComponentKind::BlockEntityData; -} -#[derive(Clone, PartialEq, Debug, AzBuf)] +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] +#[serde(untagged)] pub enum Instrument { Registry(registry::Instrument), Holder(Holder<registry::Instrument, InstrumentData>), } -impl DataComponent for Instrument { - const KIND: DataComponentKind = DataComponentKind::Instrument; -} -#[derive(Clone, PartialEq, Debug, AzBuf)] +#[derive(Clone, PartialEq, Debug, AzBuf, Serialize)] pub struct InstrumentData { pub sound_event: Holder<SoundEvent, azalea_core::sound::CustomSound>, pub use_duration: f32, @@ -704,33 +759,29 @@ pub struct InstrumentData { pub description: FormattedText, } -#[derive(Clone, PartialEq, AzBuf)] +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] +#[serde(transparent)] pub struct OminousBottleAmplifier { #[var] pub amplifier: i32, } -impl DataComponent for OminousBottleAmplifier { - const KIND: DataComponentKind = DataComponentKind::OminousBottleAmplifier; -} -#[derive(Clone, PartialEq, AzBuf)] +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] +#[serde(transparent)] pub struct Recipes { pub recipes: Vec<ResourceLocation>, } -impl DataComponent for Recipes { - const KIND: DataComponentKind = DataComponentKind::Recipes; -} -#[derive(Clone, PartialEq, AzBuf)] +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] pub struct LodestoneTracker { + #[serde(skip_serializing_if = "is_default")] pub target: Option<GlobalPos>, + #[serde(skip_serializing_if = "is_true")] pub tracked: bool, } -impl DataComponent for LodestoneTracker { - const KIND: DataComponentKind = DataComponentKind::LodestoneTracker; -} -#[derive(Clone, Copy, PartialEq, AzBuf)] +#[derive(Clone, Copy, PartialEq, AzBuf, Debug, Serialize)] +#[serde(rename_all = "snake_case")] pub enum FireworkExplosionShape { SmallBall, LargeBall, @@ -739,28 +790,28 @@ pub enum FireworkExplosionShape { Burst, } -#[derive(Clone, PartialEq, AzBuf)] +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] pub struct FireworkExplosion { pub shape: FireworkExplosionShape, + #[serde(skip_serializing_if = "is_default")] pub colors: Vec<i32>, + #[serde(skip_serializing_if = "is_default")] pub fade_colors: Vec<i32>, + #[serde(skip_serializing_if = "is_default")] pub has_trail: bool, + #[serde(skip_serializing_if = "is_default")] pub has_twinkle: bool, } -impl DataComponent for FireworkExplosion { - const KIND: DataComponentKind = DataComponentKind::FireworkExplosion; -} -#[derive(Clone, PartialEq, AzBuf)] +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] pub struct Fireworks { #[var] + #[serde(skip_serializing_if = "is_default")] pub flight_duration: i32, #[limit(256)] pub explosions: Vec<FireworkExplosion>, } -impl DataComponent for Fireworks { - const KIND: DataComponentKind = DataComponentKind::Fireworks; -} + impl Fireworks { pub const fn new() -> Self { Fireworks { @@ -775,32 +826,32 @@ impl Default for Fireworks { } } -#[derive(Clone, PartialEq, AzBuf)] +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] pub struct GameProfileProperty { pub name: String, pub value: String, + #[serde(skip_serializing_if = "is_default")] pub signature: Option<String>, } -#[derive(Clone, PartialEq, AzBuf)] +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] pub struct Profile { + #[serde(skip_serializing_if = "is_default")] pub name: Option<String>, + #[serde(skip_serializing_if = "is_default")] + #[serde(serialize_with = "azalea_core::codec_utils::uuid")] pub id: Option<Uuid>, + #[serde(skip_serializing_if = "is_default")] pub properties: Vec<GameProfileProperty>, } -impl DataComponent for Profile { - const KIND: DataComponentKind = DataComponentKind::Profile; -} -#[derive(Clone, PartialEq, AzBuf)] +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] +#[serde(transparent)] pub struct NoteBlockSound { pub sound: ResourceLocation, } -impl DataComponent for NoteBlockSound { - const KIND: DataComponentKind = DataComponentKind::NoteBlockSound; -} -#[derive(Clone, PartialEq, AzBuf)] +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] pub struct BannerPattern { #[var] pub pattern: i32, @@ -808,15 +859,14 @@ pub struct BannerPattern { pub color: i32, } -#[derive(Clone, PartialEq, AzBuf)] +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] +#[serde(transparent)] pub struct BannerPatterns { pub patterns: Vec<BannerPattern>, } -impl DataComponent for BannerPatterns { - const KIND: DataComponentKind = DataComponentKind::BannerPatterns; -} -#[derive(Clone, Copy, PartialEq, AzBuf)] +#[derive(Clone, Copy, PartialEq, AzBuf, Debug, Serialize)] +#[serde(rename_all = "snake_case")] pub enum DyeColor { White, Orange, @@ -836,40 +886,33 @@ pub enum DyeColor { Black, } -#[derive(Clone, PartialEq, AzBuf)] +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] +#[serde(transparent)] pub struct BaseColor { pub color: DyeColor, } -impl DataComponent for BaseColor { - const KIND: DataComponentKind = DataComponentKind::BaseColor; -} -#[derive(Clone, PartialEq, AzBuf)] +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] +#[serde(transparent)] pub struct PotDecorations { - pub items: Vec<Item>, -} -impl DataComponent for PotDecorations { - const KIND: DataComponentKind = DataComponentKind::PotDecorations; + pub items: [Item; 4], } -#[derive(Clone, PartialEq, AzBuf)] +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] +#[serde(transparent)] pub struct Container { pub items: Vec<ItemStack>, } -impl DataComponent for Container { - const KIND: DataComponentKind = DataComponentKind::Container; -} -#[derive(Clone, PartialEq, AzBuf)] +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] +#[serde(transparent)] pub struct BlockState { pub properties: HashMap<String, String>, } -impl DataComponent for BlockState { - const KIND: DataComponentKind = DataComponentKind::BlockState; -} -#[derive(Clone, PartialEq, AzBuf)] +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] pub struct BeehiveOccupant { + #[serde(skip_serializing_if = "is_default")] pub entity_data: NbtCompound, #[var] pub ticks_in_hive: i32, @@ -877,39 +920,30 @@ pub struct BeehiveOccupant { pub min_ticks_in_hive: i32, } -#[derive(Clone, PartialEq, AzBuf)] +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] +#[serde(transparent)] pub struct Bees { pub occupants: Vec<BeehiveOccupant>, } -impl DataComponent for Bees { - const KIND: DataComponentKind = DataComponentKind::Bees; -} -#[derive(Clone, PartialEq, AzBuf)] +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] pub struct Lock { pub key: String, } -impl DataComponent for Lock { - const KIND: DataComponentKind = DataComponentKind::Lock; -} -#[derive(Clone, PartialEq, AzBuf)] +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] pub struct ContainerLoot { - pub loot: NbtCompound, -} -impl DataComponent for ContainerLoot { - const KIND: DataComponentKind = DataComponentKind::ContainerLoot; + pub loot_table: NbtCompound, } -#[derive(Clone, PartialEq, AzBuf)] +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] +#[serde(untagged)] pub enum JukeboxPlayable { Referenced(ResourceLocation), Direct(Holder<registry::JukeboxSong, JukeboxSongData>), } -impl DataComponent for JukeboxPlayable { - const KIND: DataComponentKind = DataComponentKind::JukeboxPlayable; -} -#[derive(Clone, PartialEq, AzBuf)] + +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] pub struct JukeboxSongData { pub sound_event: Holder<SoundEvent, CustomSound>, pub description: FormattedText, @@ -918,17 +952,26 @@ pub struct JukeboxSongData { pub comparator_output: i32, } -#[derive(Clone, PartialEq, AzBuf)] +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] pub struct Consumable { + #[serde(skip_serializing_if = "is_default")] pub consume_seconds: f32, + #[serde(skip_serializing_if = "is_default")] pub animation: ItemUseAnimation, + #[serde(skip_serializing_if = "is_default_eat_sound")] pub sound: azalea_registry::Holder<SoundEvent, CustomSound>, + #[serde(skip_serializing_if = "is_default")] pub has_consume_particles: bool, + #[serde(skip_serializing_if = "is_default")] pub on_consume_effects: Vec<ConsumeEffect>, } -impl DataComponent for Consumable { - const KIND: DataComponentKind = DataComponentKind::Consumable; +fn is_default_eat_sound(sound: &azalea_registry::Holder<SoundEvent, CustomSound>) -> bool { + matches!( + sound, + azalea_registry::Holder::Reference(SoundEvent::EntityGenericEat) + ) } + impl Consumable { pub const fn new() -> Self { Self { @@ -946,8 +989,10 @@ impl Default for Consumable { } } -#[derive(Clone, Copy, PartialEq, AzBuf)] +#[derive(Clone, Copy, PartialEq, AzBuf, Debug, Default, Serialize)] +#[serde(rename_all = "snake_case")] pub enum ItemUseAnimation { + #[default] None, Eat, Drink, @@ -960,22 +1005,19 @@ pub enum ItemUseAnimation { Brush, } -#[derive(Clone, PartialEq, AzBuf)] +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] +#[serde(transparent)] pub struct UseRemainder { pub convert_into: ItemStack, } -impl DataComponent for UseRemainder { - const KIND: DataComponentKind = DataComponentKind::UseRemainder; -} -#[derive(Clone, PartialEq, AzBuf)] +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] pub struct UseCooldown { pub seconds: f32, + #[serde(skip_serializing_if = "is_default")] pub cooldown_group: Option<ResourceLocation>, } -impl DataComponent for UseCooldown { - const KIND: DataComponentKind = DataComponentKind::UseCooldown; -} + impl UseCooldown { pub const fn new() -> Self { Self { @@ -990,66 +1032,60 @@ impl Default for UseCooldown { } } -#[derive(Clone, PartialEq, AzBuf)] +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] pub struct Enchantable { #[var] pub value: u32, } -impl DataComponent for Enchantable { - const KIND: DataComponentKind = DataComponentKind::Enchantable; -} -#[derive(Clone, PartialEq, AzBuf)] +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] pub struct Repairable { pub items: HolderSet<Item, ResourceLocation>, } -impl DataComponent for Repairable { - const KIND: DataComponentKind = DataComponentKind::Repairable; -} -#[derive(Clone, PartialEq, AzBuf)] +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] +#[serde(transparent)] pub struct ItemModel { pub resource_location: ResourceLocation, } -impl DataComponent for ItemModel { - const KIND: DataComponentKind = DataComponentKind::ItemModel; -} -#[derive(Clone, PartialEq, AzBuf)] +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] pub struct DamageResistant { - // in the vanilla code this is - // ``` - // StreamCodec.composite( - // TagKey.streamCodec(Registries.DAMAGE_TYPE), - // DamageResistant::types, - // DamageResistant::new, - // ); - // ``` - // i'm not entirely sure if this is meant to be a vec or something, i just made it a - // resourcelocation for now + /// In vanilla this only allows tag keys, i.e. it must start with '#' pub types: ResourceLocation, } -impl DataComponent for DamageResistant { - const KIND: DataComponentKind = DataComponentKind::DamageResistant; -} -#[derive(Clone, PartialEq, AzBuf)] +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] pub struct Equippable { pub slot: EquipmentSlot, + #[serde(skip_serializing_if = "is_default_equip_sound")] pub equip_sound: SoundEvent, + #[serde(skip_serializing_if = "is_default")] pub asset_id: Option<ResourceLocation>, + #[serde(skip_serializing_if = "is_default")] pub camera_overlay: Option<ResourceLocation>, + #[serde(skip_serializing_if = "is_default")] pub allowed_entities: Option<HolderSet<EntityKind, ResourceLocation>>, + #[serde(skip_serializing_if = "is_true")] pub dispensable: bool, + #[serde(skip_serializing_if = "is_true")] pub swappable: bool, + #[serde(skip_serializing_if = "is_true")] pub damage_on_hurt: bool, + #[serde(skip_serializing_if = "is_default")] pub equip_on_interact: bool, + #[serde(skip_serializing_if = "is_default")] pub can_be_sheared: bool, + #[serde(skip_serializing_if = "is_default_shearing_sound")] pub shearing_sound: SoundEvent, } -impl DataComponent for Equippable { - const KIND: DataComponentKind = DataComponentKind::Equippable; +fn is_default_equip_sound(sound: &SoundEvent) -> bool { + matches!(sound, SoundEvent::ItemArmorEquipGeneric) } +fn is_default_shearing_sound(sound: &SoundEvent) -> bool { + matches!(sound, SoundEvent::ItemShearsSnip) +} + impl Equippable { pub const fn new() -> Self { Self { @@ -1073,7 +1109,8 @@ impl Default for Equippable { } } -#[derive(Clone, Copy, Debug, PartialEq, AzBuf)] +#[derive(Clone, Copy, Debug, PartialEq, AzBuf, Serialize)] +#[serde(rename_all = "snake_case")] pub enum EquipmentSlot { Mainhand, Offhand, @@ -1085,37 +1122,32 @@ pub enum EquipmentSlot { Saddle, } -#[derive(Clone, PartialEq, AzBuf)] +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] pub struct Glider; -impl DataComponent for Glider { - const KIND: DataComponentKind = DataComponentKind::Glider; -} -#[derive(Clone, PartialEq, AzBuf)] +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] +#[serde(transparent)] pub struct TooltipStyle { pub resource_location: ResourceLocation, } -impl DataComponent for TooltipStyle { - const KIND: DataComponentKind = DataComponentKind::TooltipStyle; -} -#[derive(Clone, PartialEq, AzBuf)] +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] pub struct DeathProtection { pub death_effects: Vec<ConsumeEffect>, } -impl DataComponent for DeathProtection { - const KIND: DataComponentKind = DataComponentKind::DeathProtection; -} -#[derive(Clone, PartialEq, AzBuf)] +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] pub struct Weapon { #[var] + #[serde(skip_serializing_if = "is_default_item_damage_per_attack")] pub item_damage_per_attack: i32, + #[serde(skip_serializing_if = "is_default")] pub disable_blocking_for_seconds: f32, } -impl DataComponent for Weapon { - const KIND: DataComponentKind = DataComponentKind::Weapon; +fn is_default_item_damage_per_attack(value: &i32) -> bool { + *value == 1 } + impl Weapon { pub const fn new() -> Self { Self { @@ -1130,65 +1162,52 @@ impl Default for Weapon { } } -#[derive(Clone, PartialEq, AzBuf)] +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] +#[serde(transparent)] pub struct PotionDurationScale { pub value: f32, } -impl DataComponent for PotionDurationScale { - const KIND: DataComponentKind = DataComponentKind::PotionDurationScale; -} -#[derive(Clone, PartialEq, AzBuf)] +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] +#[serde(transparent)] pub struct VillagerVariant { pub variant: registry::VillagerKind, } -impl DataComponent for VillagerVariant { - const KIND: DataComponentKind = DataComponentKind::VillagerVariant; -} -#[derive(Clone, PartialEq, AzBuf)] +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] +#[serde(transparent)] pub struct WolfVariant { pub variant: registry::WolfVariant, } -impl DataComponent for WolfVariant { - const KIND: DataComponentKind = DataComponentKind::WolfVariant; -} -#[derive(Clone, PartialEq, AzBuf)] +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] +#[serde(transparent)] pub struct WolfCollar { pub color: DyeColor, } -impl DataComponent for WolfCollar { - const KIND: DataComponentKind = DataComponentKind::WolfCollar; -} -#[derive(Clone, PartialEq, AzBuf)] +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] +#[serde(transparent)] pub struct FoxVariant { pub variant: registry::FoxVariant, } -impl DataComponent for FoxVariant { - const KIND: DataComponentKind = DataComponentKind::FoxVariant; -} -#[derive(Clone, Copy, PartialEq, AzBuf)] +#[derive(Clone, Copy, PartialEq, AzBuf, Debug, Serialize)] +#[serde(rename_all = "snake_case")] pub enum SalmonSize { Small, Medium, Large, } -impl DataComponent for SalmonSize { - const KIND: DataComponentKind = DataComponentKind::SalmonSize; -} -#[derive(Clone, PartialEq, AzBuf)] +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] +#[serde(transparent)] pub struct ParrotVariant { pub variant: registry::ParrotVariant, } -impl DataComponent for ParrotVariant { - const KIND: DataComponentKind = DataComponentKind::ParrotVariant; -} -#[derive(Clone, Copy, PartialEq, AzBuf)] +#[derive(Clone, Copy, PartialEq, AzBuf, Debug, Serialize)] +#[serde(rename_all = "snake_case")] pub enum TropicalFishPattern { Kob, Sunstreak, @@ -1203,140 +1222,112 @@ pub enum TropicalFishPattern { Betty, Clayfish, } -impl DataComponent for TropicalFishPattern { - const KIND: DataComponentKind = DataComponentKind::TropicalFishPattern; -} -#[derive(Clone, PartialEq, AzBuf)] +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] +#[serde(transparent)] pub struct TropicalFishBaseColor { pub color: DyeColor, } -impl DataComponent for TropicalFishBaseColor { - const KIND: DataComponentKind = DataComponentKind::TropicalFishBaseColor; -} -#[derive(Clone, PartialEq, AzBuf)] +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] +#[serde(transparent)] pub struct TropicalFishPatternColor { pub color: DyeColor, } -impl DataComponent for TropicalFishPatternColor { - const KIND: DataComponentKind = DataComponentKind::TropicalFishPatternColor; -} -#[derive(Clone, PartialEq, AzBuf)] +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] +#[serde(transparent)] pub struct MooshroomVariant { pub variant: registry::MooshroomVariant, } -impl DataComponent for MooshroomVariant { - const KIND: DataComponentKind = DataComponentKind::MooshroomVariant; -} -#[derive(Clone, PartialEq, AzBuf)] +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] +#[serde(transparent)] pub struct RabbitVariant { pub variant: registry::RabbitVariant, } -impl DataComponent for RabbitVariant { - const KIND: DataComponentKind = DataComponentKind::RabbitVariant; -} -#[derive(Clone, PartialEq, AzBuf)] +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] +#[serde(transparent)] pub struct PigVariant { pub variant: registry::PigVariant, } -impl DataComponent for PigVariant { - const KIND: DataComponentKind = DataComponentKind::PigVariant; -} -#[derive(Clone, PartialEq, AzBuf)] +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] +#[serde(transparent)] pub struct FrogVariant { pub variant: registry::FrogVariant, } -impl DataComponent for FrogVariant { - const KIND: DataComponentKind = DataComponentKind::FrogVariant; -} -#[derive(Clone, PartialEq, AzBuf)] +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] +#[serde(transparent)] pub struct HorseVariant { pub variant: registry::HorseVariant, } -impl DataComponent for HorseVariant { - const KIND: DataComponentKind = DataComponentKind::HorseVariant; -} -#[derive(Clone, PartialEq, AzBuf)] +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] +#[serde(transparent)] pub struct PaintingVariant { pub variant: Holder<registry::PaintingVariant, PaintingVariantData>, } -impl DataComponent for PaintingVariant { - const KIND: DataComponentKind = DataComponentKind::PaintingVariant; -} -#[derive(Clone, PartialEq, AzBuf)] + +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] pub struct PaintingVariantData { #[var] pub width: i32, #[var] pub height: i32, pub asset_id: ResourceLocation, + #[serde(skip_serializing_if = "is_default")] pub title: Option<FormattedText>, + #[serde(skip_serializing_if = "is_default")] pub author: Option<FormattedText>, } -#[derive(Clone, PartialEq, AzBuf)] +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] +#[serde(transparent)] pub struct LlamaVariant { pub variant: registry::LlamaVariant, } -impl DataComponent for LlamaVariant { - const KIND: DataComponentKind = DataComponentKind::LlamaVariant; -} -#[derive(Clone, PartialEq, AzBuf)] +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] +#[serde(transparent)] pub struct AxolotlVariant { pub variant: registry::AxolotlVariant, } -impl DataComponent for AxolotlVariant { - const KIND: DataComponentKind = DataComponentKind::AxolotlVariant; -} -#[derive(Clone, PartialEq, AzBuf)] +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] +#[serde(transparent)] pub struct CatVariant { pub variant: registry::CatVariant, } -impl DataComponent for CatVariant { - const KIND: DataComponentKind = DataComponentKind::CatVariant; -} -#[derive(Clone, PartialEq, AzBuf)] +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] +#[serde(transparent)] pub struct CatCollar { pub color: DyeColor, } -impl DataComponent for CatCollar { - const KIND: DataComponentKind = DataComponentKind::CatCollar; -} -#[derive(Clone, PartialEq, AzBuf)] +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] +#[serde(transparent)] pub struct SheepColor { pub color: DyeColor, } -impl DataComponent for SheepColor { - const KIND: DataComponentKind = DataComponentKind::SheepColor; -} -#[derive(Clone, PartialEq, AzBuf)] +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] +#[serde(transparent)] pub struct ShulkerColor { pub color: DyeColor, } -impl DataComponent for ShulkerColor { - const KIND: DataComponentKind = DataComponentKind::ShulkerColor; -} -#[derive(Clone, PartialEq, AzBuf, Default)] +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] pub struct TooltipDisplay { + #[serde(skip_serializing_if = "is_default")] pub hide_tooltip: bool, + #[serde(skip_serializing_if = "is_default")] pub hidden_components: Vec<DataComponentKind>, } -impl DataComponent for TooltipDisplay { - const KIND: DataComponentKind = DataComponentKind::TooltipDisplay; -} + impl TooltipDisplay { pub const fn new() -> Self { Self { @@ -1345,20 +1336,33 @@ impl TooltipDisplay { } } } +impl Default for TooltipDisplay { + fn default() -> Self { + Self::new() + } +} -#[derive(Clone, PartialEq, AzBuf)] +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] pub struct BlocksAttacks { + #[serde(skip_serializing_if = "is_default")] pub block_delay_seconds: f32, + #[serde(skip_serializing_if = "is_default_disable_cooldown_scale")] pub disable_cooldown_scale: f32, + #[serde(skip_serializing_if = "is_default")] pub damage_reductions: Vec<DamageReduction>, + #[serde(skip_serializing_if = "is_default")] pub item_damage: ItemDamageFunction, + #[serde(skip_serializing_if = "is_default")] pub bypassed_by: Option<ResourceLocation>, + #[serde(skip_serializing_if = "is_default")] pub block_sound: Option<azalea_registry::Holder<SoundEvent, CustomSound>>, + #[serde(skip_serializing_if = "is_default")] pub disabled_sound: Option<azalea_registry::Holder<SoundEvent, CustomSound>>, } -impl DataComponent for BlocksAttacks { - const KIND: DataComponentKind = DataComponentKind::BlocksAttacks; +fn is_default_disable_cooldown_scale(value: &f32) -> bool { + *value == 1. } + impl BlocksAttacks { pub fn new() -> Self { Self { @@ -1370,11 +1374,7 @@ impl BlocksAttacks { base: 0., factor: 1., }], - item_damage: ItemDamageFunction { - threshold: 1., - base: 0., - factor: 1., - }, + item_damage: ItemDamageFunction::default(), bypassed_by: None, block_sound: None, disabled_sound: None, @@ -1387,86 +1387,90 @@ impl Default for BlocksAttacks { } } -#[derive(Clone, PartialEq, AzBuf)] +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] pub struct DamageReduction { + #[serde(skip_serializing_if = "is_default_horizontal_blocking_angle")] pub horizontal_blocking_angle: f32, + #[serde(skip_serializing_if = "is_default")] pub kind: Option<HolderSet<DamageKind, ResourceLocation>>, pub base: f32, pub factor: f32, } -#[derive(Clone, PartialEq, AzBuf)] +fn is_default_horizontal_blocking_angle(value: &f32) -> bool { + *value == 90. +} +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] pub struct ItemDamageFunction { pub threshold: f32, pub base: f32, pub factor: f32, } +impl Default for ItemDamageFunction { + fn default() -> Self { + ItemDamageFunction { + threshold: 1., + base: 0., + factor: 1., + } + } +} -#[derive(Clone, PartialEq, AzBuf)] +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] +#[serde(untagged)] pub enum ProvidesTrimMaterial { Referenced(ResourceLocation), Direct(Holder<TrimMaterial, DirectTrimMaterial>), } -impl DataComponent for ProvidesTrimMaterial { - const KIND: DataComponentKind = DataComponentKind::ProvidesTrimMaterial; -} -#[derive(Clone, PartialEq, AzBuf)] +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] pub struct DirectTrimMaterial { pub assets: MaterialAssetGroup, pub description: FormattedText, } -#[derive(Clone, PartialEq, AzBuf)] +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] pub struct MaterialAssetGroup { pub base: AssetInfo, + #[serde(skip_serializing_if = "is_default")] pub overrides: Vec<(ResourceLocation, AssetInfo)>, } -#[derive(Clone, PartialEq, AzBuf)] +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] pub struct AssetInfo { pub suffix: String, } -#[derive(Clone, PartialEq, AzBuf)] +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] +#[serde(transparent)] pub struct ProvidesBannerPatterns { pub key: ResourceLocation, } -impl DataComponent for ProvidesBannerPatterns { - const KIND: DataComponentKind = DataComponentKind::ProvidesBannerPatterns; -} -#[derive(Clone, PartialEq, AzBuf)] +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] +#[serde(transparent)] pub struct BreakSound { pub sound: azalea_registry::Holder<SoundEvent, CustomSound>, } -impl DataComponent for BreakSound { - const KIND: DataComponentKind = DataComponentKind::BreakSound; -} -#[derive(Clone, PartialEq, AzBuf)] +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] +#[serde(transparent)] pub struct WolfSoundVariant { pub variant: azalea_registry::WolfSoundVariant, } -impl DataComponent for WolfSoundVariant { - const KIND: DataComponentKind = DataComponentKind::WolfSoundVariant; -} -#[derive(Clone, PartialEq, AzBuf)] +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] +#[serde(transparent)] pub struct CowVariant { pub variant: azalea_registry::CowVariant, } -impl DataComponent for CowVariant { - const KIND: DataComponentKind = DataComponentKind::CowVariant; -} -#[derive(Clone, PartialEq, AzBuf)] +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] +#[serde(untagged)] pub enum ChickenVariant { Referenced(ResourceLocation), Direct(ChickenVariantData), } -impl DataComponent for ChickenVariant { - const KIND: DataComponentKind = DataComponentKind::ChickenVariant; -} -#[derive(Clone, PartialEq, AzBuf)] + +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] pub struct ChickenVariantData { pub registry: azalea_registry::ChickenVariant, } diff --git a/azalea-inventory/src/default_components/generated.rs b/azalea-inventory/src/default_components/generated.rs index c62a43dd..6b948ec3 100644 --- a/azalea-inventory/src/default_components/generated.rs +++ b/azalea-inventory/src/default_components/generated.rs @@ -20,7 +20,7 @@ impl DefaultableComponent for AttributeModifiers { Item::CarvedPumpkin => vec![AttributeModifiersEntry { display: AttributeModifierDisplay::Hidden, slot: EquipmentSlotGroup::Head, - attribute: Attribute::WaypointTransmitRange, + kind: Attribute::WaypointTransmitRange, modifier: AttributeModifier { id: "minecraft:waypoint_transmit_range_hide".into(), amount: -1.0, @@ -30,7 +30,7 @@ impl DefaultableComponent for AttributeModifiers { Item::ChainmailBoots => vec![ AttributeModifiersEntry { slot: EquipmentSlotGroup::Feet, - attribute: Attribute::Armor, + kind: Attribute::Armor, display: AttributeModifierDisplay::Default, modifier: AttributeModifier { id: "minecraft:armor.boots".into(), @@ -40,7 +40,7 @@ impl DefaultableComponent for AttributeModifiers { }, AttributeModifiersEntry { slot: EquipmentSlotGroup::Feet, - attribute: Attribute::ArmorToughness, + kind: Attribute::ArmorToughness, display: AttributeModifierDisplay::Default, modifier: AttributeModifier { id: "minecraft:armor.boots".into(), @@ -52,7 +52,7 @@ impl DefaultableComponent for AttributeModifiers { Item::ChainmailChestplate => vec![ AttributeModifiersEntry { slot: EquipmentSlotGroup::Chest, - attribute: Attribute::Armor, + kind: Attribute::Armor, display: AttributeModifierDisplay::Default, modifier: AttributeModifier { id: "minecraft:armor.chestplate".into(), @@ -62,7 +62,7 @@ impl DefaultableComponent for AttributeModifiers { }, AttributeModifiersEntry { slot: EquipmentSlotGroup::Chest, - attribute: Attribute::ArmorToughness, + kind: Attribute::ArmorToughness, display: AttributeModifierDisplay::Default, modifier: AttributeModifier { id: "minecraft:armor.chestplate".into(), @@ -74,7 +74,7 @@ impl DefaultableComponent for AttributeModifiers { Item::ChainmailHelmet => vec![ AttributeModifiersEntry { slot: EquipmentSlotGroup::Head, - attribute: Attribute::Armor, + kind: Attribute::Armor, display: AttributeModifierDisplay::Default, modifier: AttributeModifier { id: "minecraft:armor.helmet".into(), @@ -84,7 +84,7 @@ impl DefaultableComponent for AttributeModifiers { }, AttributeModifiersEntry { slot: EquipmentSlotGroup::Head, - attribute: Attribute::ArmorToughness, + kind: Attribute::ArmorToughness, display: AttributeModifierDisplay::Default, modifier: AttributeModifier { id: "minecraft:armor.helmet".into(), @@ -96,7 +96,7 @@ impl DefaultableComponent for AttributeModifiers { Item::ChainmailLeggings => vec![ AttributeModifiersEntry { slot: EquipmentSlotGroup::Legs, - attribute: Attribute::Armor, + kind: Attribute::Armor, display: AttributeModifierDisplay::Default, modifier: AttributeModifier { id: "minecraft:armor.leggings".into(), @@ -106,7 +106,7 @@ impl DefaultableComponent for AttributeModifiers { }, AttributeModifiersEntry { slot: EquipmentSlotGroup::Legs, - attribute: Attribute::ArmorToughness, + kind: Attribute::ArmorToughness, display: AttributeModifierDisplay::Default, modifier: AttributeModifier { id: "minecraft:armor.leggings".into(), @@ -118,7 +118,7 @@ impl DefaultableComponent for AttributeModifiers { Item::CreeperHead => vec![AttributeModifiersEntry { display: AttributeModifierDisplay::Hidden, slot: EquipmentSlotGroup::Head, - attribute: Attribute::WaypointTransmitRange, + kind: Attribute::WaypointTransmitRange, modifier: AttributeModifier { id: "minecraft:waypoint_transmit_range_hide".into(), amount: -1.0, @@ -128,7 +128,7 @@ impl DefaultableComponent for AttributeModifiers { Item::DiamondAxe => vec![ AttributeModifiersEntry { slot: EquipmentSlotGroup::Mainhand, - attribute: Attribute::AttackDamage, + kind: Attribute::AttackDamage, display: AttributeModifierDisplay::Default, modifier: AttributeModifier { id: "minecraft:base_attack_damage".into(), @@ -138,7 +138,7 @@ impl DefaultableComponent for AttributeModifiers { }, AttributeModifiersEntry { slot: EquipmentSlotGroup::Mainhand, - attribute: Attribute::AttackSpeed, + kind: Attribute::AttackSpeed, display: AttributeModifierDisplay::Default, modifier: AttributeModifier { id: "minecraft:base_attack_speed".into(), @@ -150,7 +150,7 @@ impl DefaultableComponent for AttributeModifiers { Item::DiamondBoots => vec![ AttributeModifiersEntry { slot: EquipmentSlotGroup::Feet, - attribute: Attribute::Armor, + kind: Attribute::Armor, display: AttributeModifierDisplay::Default, modifier: AttributeModifier { id: "minecraft:armor.boots".into(), @@ -160,7 +160,7 @@ impl DefaultableComponent for AttributeModifiers { }, AttributeModifiersEntry { slot: EquipmentSlotGroup::Feet, - attribute: Attribute::ArmorToughness, + kind: Attribute::ArmorToughness, display: AttributeModifierDisplay::Default, modifier: AttributeModifier { id: "minecraft:armor.boots".into(), @@ -172,7 +172,7 @@ impl DefaultableComponent for AttributeModifiers { Item::DiamondChestplate => vec![ AttributeModifiersEntry { slot: EquipmentSlotGroup::Chest, - attribute: Attribute::Armor, + kind: Attribute::Armor, display: AttributeModifierDisplay::Default, modifier: AttributeModifier { id: "minecraft:armor.chestplate".into(), @@ -182,7 +182,7 @@ impl DefaultableComponent for AttributeModifiers { }, AttributeModifiersEntry { slot: EquipmentSlotGroup::Chest, - attribute: Attribute::ArmorToughness, + kind: Attribute::ArmorToughness, display: AttributeModifierDisplay::Default, modifier: AttributeModifier { id: "minecraft:armor.chestplate".into(), @@ -194,7 +194,7 @@ impl DefaultableComponent for AttributeModifiers { Item::DiamondHelmet => vec![ AttributeModifiersEntry { slot: EquipmentSlotGroup::Head, - attribute: Attribute::Armor, + kind: Attribute::Armor, display: AttributeModifierDisplay::Default, modifier: AttributeModifier { id: "minecraft:armor.helmet".into(), @@ -204,7 +204,7 @@ impl DefaultableComponent for AttributeModifiers { }, AttributeModifiersEntry { slot: EquipmentSlotGroup::Head, - attribute: Attribute::ArmorToughness, + kind: Attribute::ArmorToughness, display: AttributeModifierDisplay::Default, modifier: AttributeModifier { id: "minecraft:armor.helmet".into(), @@ -216,7 +216,7 @@ impl DefaultableComponent for AttributeModifiers { Item::DiamondHoe => vec![ AttributeModifiersEntry { slot: EquipmentSlotGroup::Mainhand, - attribute: Attribute::AttackDamage, + kind: Attribute::AttackDamage, display: AttributeModifierDisplay::Default, modifier: AttributeModifier { id: "minecraft:base_attack_damage".into(), @@ -226,7 +226,7 @@ impl DefaultableComponent for AttributeModifiers { }, AttributeModifiersEntry { slot: EquipmentSlotGroup::Mainhand, - attribute: Attribute::AttackSpeed, + kind: Attribute::AttackSpeed, display: AttributeModifierDisplay::Default, modifier: AttributeModifier { id: "minecraft:base_attack_speed".into(), @@ -238,7 +238,7 @@ impl DefaultableComponent for AttributeModifiers { Item::DiamondHorseArmor => vec![ AttributeModifiersEntry { slot: EquipmentSlotGroup::Body, - attribute: Attribute::Armor, + kind: Attribute::Armor, display: AttributeModifierDisplay::Default, modifier: AttributeModifier { id: "minecraft:armor.body".into(), @@ -248,7 +248,7 @@ impl DefaultableComponent for AttributeModifiers { }, AttributeModifiersEntry { slot: EquipmentSlotGroup::Body, - attribute: Attribute::ArmorToughness, + kind: Attribute::ArmorToughness, display: AttributeModifierDisplay::Default, modifier: AttributeModifier { id: "minecraft:armor.body".into(), @@ -260,7 +260,7 @@ impl DefaultableComponent for AttributeModifiers { Item::DiamondLeggings => vec![ AttributeModifiersEntry { slot: EquipmentSlotGroup::Legs, - attribute: Attribute::Armor, + kind: Attribute::Armor, display: AttributeModifierDisplay::Default, modifier: AttributeModifier { id: "minecraft:armor.leggings".into(), @@ -270,7 +270,7 @@ impl DefaultableComponent for AttributeModifiers { }, AttributeModifiersEntry { slot: EquipmentSlotGroup::Legs, - attribute: Attribute::ArmorToughness, + kind: Attribute::ArmorToughness, display: AttributeModifierDisplay::Default, modifier: AttributeModifier { id: "minecraft:armor.leggings".into(), @@ -282,7 +282,7 @@ impl DefaultableComponent for AttributeModifiers { Item::DiamondPickaxe => vec![ AttributeModifiersEntry { slot: EquipmentSlotGroup::Mainhand, - attribute: Attribute::AttackDamage, + kind: Attribute::AttackDamage, display: AttributeModifierDisplay::Default, modifier: AttributeModifier { id: "minecraft:base_attack_damage".into(), @@ -292,7 +292,7 @@ impl DefaultableComponent for AttributeModifiers { }, AttributeModifiersEntry { slot: EquipmentSlotGroup::Mainhand, - attribute: Attribute::AttackSpeed, + kind: Attribute::AttackSpeed, display: AttributeModifierDisplay::Default, modifier: AttributeModifier { id: "minecraft:base_attack_speed".into(), @@ -304,7 +304,7 @@ impl DefaultableComponent for AttributeModifiers { Item::DiamondShovel => vec![ AttributeModifiersEntry { slot: EquipmentSlotGroup::Mainhand, - attribute: Attribute::AttackDamage, + kind: Attribute::AttackDamage, display: AttributeModifierDisplay::Default, modifier: AttributeModifier { id: "minecraft:base_attack_damage".into(), @@ -314,7 +314,7 @@ impl DefaultableComponent for AttributeModifiers { }, AttributeModifiersEntry { slot: EquipmentSlotGroup::Mainhand, - attribute: Attribute::AttackSpeed, + kind: Attribute::AttackSpeed, display: AttributeModifierDisplay::Default, modifier: AttributeModifier { id: "minecraft:base_attack_speed".into(), @@ -326,7 +326,7 @@ impl DefaultableComponent for AttributeModifiers { Item::DiamondSword => vec![ AttributeModifiersEntry { slot: EquipmentSlotGroup::Mainhand, - attribute: Attribute::AttackDamage, + kind: Attribute::AttackDamage, display: AttributeModifierDisplay::Default, modifier: AttributeModifier { id: "minecraft:base_attack_damage".into(), @@ -336,7 +336,7 @@ impl DefaultableComponent for AttributeModifiers { }, AttributeModifiersEntry { slot: EquipmentSlotGroup::Mainhand, - attribute: Attribute::AttackSpeed, + kind: Attribute::AttackSpeed, display: AttributeModifierDisplay::Default, modifier: AttributeModifier { id: "minecraft:base_attack_speed".into(), @@ -348,7 +348,7 @@ impl DefaultableComponent for AttributeModifiers { Item::DragonHead => vec![AttributeModifiersEntry { display: AttributeModifierDisplay::Hidden, slot: EquipmentSlotGroup::Head, - attribute: Attribute::WaypointTransmitRange, + kind: Attribute::WaypointTransmitRange, modifier: AttributeModifier { id: "minecraft:waypoint_transmit_range_hide".into(), amount: -1.0, @@ -358,7 +358,7 @@ impl DefaultableComponent for AttributeModifiers { Item::GoldenAxe => vec![ AttributeModifiersEntry { slot: EquipmentSlotGroup::Mainhand, - attribute: Attribute::AttackDamage, + kind: Attribute::AttackDamage, display: AttributeModifierDisplay::Default, modifier: AttributeModifier { id: "minecraft:base_attack_damage".into(), @@ -368,7 +368,7 @@ impl DefaultableComponent for AttributeModifiers { }, AttributeModifiersEntry { slot: EquipmentSlotGroup::Mainhand, - attribute: Attribute::AttackSpeed, + kind: Attribute::AttackSpeed, display: AttributeModifierDisplay::Default, modifier: AttributeModifier { id: "minecraft:base_attack_speed".into(), @@ -380,7 +380,7 @@ impl DefaultableComponent for AttributeModifiers { Item::GoldenBoots => vec![ AttributeModifiersEntry { slot: EquipmentSlotGroup::Feet, - attribute: Attribute::Armor, + kind: Attribute::Armor, display: AttributeModifierDisplay::Default, modifier: AttributeModifier { id: "minecraft:armor.boots".into(), @@ -390,7 +390,7 @@ impl DefaultableComponent for AttributeModifiers { }, AttributeModifiersEntry { slot: EquipmentSlotGroup::Feet, - attribute: Attribute::ArmorToughness, + kind: Attribute::ArmorToughness, display: AttributeModifierDisplay::Default, modifier: AttributeModifier { id: "minecraft:armor.boots".into(), @@ -402,7 +402,7 @@ impl DefaultableComponent for AttributeModifiers { Item::GoldenChestplate => vec![ AttributeModifiersEntry { slot: EquipmentSlotGroup::Chest, - attribute: Attribute::Armor, + kind: Attribute::Armor, display: AttributeModifierDisplay::Default, modifier: AttributeModifier { id: "minecraft:armor.chestplate".into(), @@ -412,7 +412,7 @@ impl DefaultableComponent for AttributeModifiers { }, AttributeModifiersEntry { slot: EquipmentSlotGroup::Chest, - attribute: Attribute::ArmorToughness, + kind: Attribute::ArmorToughness, display: AttributeModifierDisplay::Default, modifier: AttributeModifier { id: "minecraft:armor.chestplate".into(), @@ -424,7 +424,7 @@ impl DefaultableComponent for AttributeModifiers { Item::GoldenHelmet => vec![ AttributeModifiersEntry { slot: EquipmentSlotGroup::Head, - attribute: Attribute::Armor, + kind: Attribute::Armor, display: AttributeModifierDisplay::Default, modifier: AttributeModifier { id: "minecraft:armor.helmet".into(), @@ -434,7 +434,7 @@ impl DefaultableComponent for AttributeModifiers { }, AttributeModifiersEntry { slot: EquipmentSlotGroup::Head, - attribute: Attribute::ArmorToughness, + kind: Attribute::ArmorToughness, display: AttributeModifierDisplay::Default, modifier: AttributeModifier { id: "minecraft:armor.helmet".into(), @@ -446,7 +446,7 @@ impl DefaultableComponent for AttributeModifiers { Item::GoldenHoe => vec![ AttributeModifiersEntry { slot: EquipmentSlotGroup::Mainhand, - attribute: Attribute::AttackDamage, + kind: Attribute::AttackDamage, display: AttributeModifierDisplay::Default, modifier: AttributeModifier { id: "minecraft:base_attack_damage".into(), @@ -456,7 +456,7 @@ impl DefaultableComponent for AttributeModifiers { }, AttributeModifiersEntry { slot: EquipmentSlotGroup::Mainhand, - attribute: Attribute::AttackSpeed, + kind: Attribute::AttackSpeed, display: AttributeModifierDisplay::Default, modifier: AttributeModifier { id: "minecraft:base_attack_speed".into(), @@ -468,7 +468,7 @@ impl DefaultableComponent for AttributeModifiers { Item::GoldenHorseArmor => vec![ AttributeModifiersEntry { slot: EquipmentSlotGroup::Body, - attribute: Attribute::Armor, + kind: Attribute::Armor, display: AttributeModifierDisplay::Default, modifier: AttributeModifier { id: "minecraft:armor.body".into(), @@ -478,7 +478,7 @@ impl DefaultableComponent for AttributeModifiers { }, AttributeModifiersEntry { slot: EquipmentSlotGroup::Body, - attribute: Attribute::ArmorToughness, + kind: Attribute::ArmorToughness, display: AttributeModifierDisplay::Default, modifier: AttributeModifier { id: "minecraft:armor.body".into(), @@ -490,7 +490,7 @@ impl DefaultableComponent for AttributeModifiers { Item::GoldenLeggings => vec![ AttributeModifiersEntry { slot: EquipmentSlotGroup::Legs, - attribute: Attribute::Armor, + kind: Attribute::Armor, display: AttributeModifierDisplay::Default, modifier: AttributeModifier { id: "minecraft:armor.leggings".into(), @@ -500,7 +500,7 @@ impl DefaultableComponent for AttributeModifiers { }, AttributeModifiersEntry { slot: EquipmentSlotGroup::Legs, - attribute: Attribute::ArmorToughness, + kind: Attribute::ArmorToughness, display: AttributeModifierDisplay::Default, modifier: AttributeModifier { id: "minecraft:armor.leggings".into(), @@ -512,7 +512,7 @@ impl DefaultableComponent for AttributeModifiers { Item::GoldenPickaxe => vec![ AttributeModifiersEntry { slot: EquipmentSlotGroup::Mainhand, - attribute: Attribute::AttackDamage, + kind: Attribute::AttackDamage, display: AttributeModifierDisplay::Default, modifier: AttributeModifier { id: "minecraft:base_attack_damage".into(), @@ -522,7 +522,7 @@ impl DefaultableComponent for AttributeModifiers { }, AttributeModifiersEntry { slot: EquipmentSlotGroup::Mainhand, - attribute: Attribute::AttackSpeed, + kind: Attribute::AttackSpeed, display: AttributeModifierDisplay::Default, modifier: AttributeModifier { id: "minecraft:base_attack_speed".into(), @@ -534,7 +534,7 @@ impl DefaultableComponent for AttributeModifiers { Item::GoldenShovel => vec![ AttributeModifiersEntry { slot: EquipmentSlotGroup::Mainhand, - attribute: Attribute::AttackDamage, + kind: Attribute::AttackDamage, display: AttributeModifierDisplay::Default, modifier: AttributeModifier { id: "minecraft:base_attack_damage".into(), @@ -544,7 +544,7 @@ impl DefaultableComponent for AttributeModifiers { }, AttributeModifiersEntry { slot: EquipmentSlotGroup::Mainhand, - attribute: Attribute::AttackSpeed, + kind: Attribute::AttackSpeed, display: AttributeModifierDisplay::Default, modifier: AttributeModifier { id: "minecraft:base_attack_speed".into(), @@ -556,7 +556,7 @@ impl DefaultableComponent for AttributeModifiers { Item::GoldenSword => vec![ AttributeModifiersEntry { slot: EquipmentSlotGroup::Mainhand, - attribute: Attribute::AttackDamage, + kind: Attribute::AttackDamage, display: AttributeModifierDisplay::Default, modifier: AttributeModifier { id: "minecraft:base_attack_damage".into(), @@ -566,7 +566,7 @@ impl DefaultableComponent for AttributeModifiers { }, AttributeModifiersEntry { slot: EquipmentSlotGroup::Mainhand, - attribute: Attribute::AttackSpeed, + kind: Attribute::AttackSpeed, display: AttributeModifierDisplay::Default, modifier: AttributeModifier { id: "minecraft:base_attack_speed".into(), @@ -578,7 +578,7 @@ impl DefaultableComponent for AttributeModifiers { Item::IronAxe => vec![ AttributeModifiersEntry { slot: EquipmentSlotGroup::Mainhand, - attribute: Attribute::AttackDamage, + kind: Attribute::AttackDamage, display: AttributeModifierDisplay::Default, modifier: AttributeModifier { id: "minecraft:base_attack_damage".into(), @@ -588,7 +588,7 @@ impl DefaultableComponent for AttributeModifiers { }, AttributeModifiersEntry { slot: EquipmentSlotGroup::Mainhand, - attribute: Attribute::AttackSpeed, + kind: Attribute::AttackSpeed, display: AttributeModifierDisplay::Default, modifier: AttributeModifier { id: "minecraft:base_attack_speed".into(), @@ -600,7 +600,7 @@ impl DefaultableComponent for AttributeModifiers { Item::IronBoots => vec![ AttributeModifiersEntry { slot: EquipmentSlotGroup::Feet, - attribute: Attribute::Armor, + kind: Attribute::Armor, display: AttributeModifierDisplay::Default, modifier: AttributeModifier { id: "minecraft:armor.boots".into(), @@ -610,7 +610,7 @@ impl DefaultableComponent for AttributeModifiers { }, AttributeModifiersEntry { slot: EquipmentSlotGroup::Feet, - attribute: Attribute::ArmorToughness, + kind: Attribute::ArmorToughness, display: AttributeModifierDisplay::Default, modifier: AttributeModifier { id: "minecraft:armor.boots".into(), @@ -622,7 +622,7 @@ impl DefaultableComponent for AttributeModifiers { Item::IronChestplate => vec![ AttributeModifiersEntry { slot: EquipmentSlotGroup::Chest, - attribute: Attribute::Armor, + kind: Attribute::Armor, display: AttributeModifierDisplay::Default, modifier: AttributeModifier { id: "minecraft:armor.chestplate".into(), @@ -632,7 +632,7 @@ impl DefaultableComponent for AttributeModifiers { }, AttributeModifiersEntry { slot: EquipmentSlotGroup::Chest, - attribute: Attribute::ArmorToughness, + kind: Attribute::ArmorToughness, display: AttributeModifierDisplay::Default, modifier: AttributeModifier { id: "minecraft:armor.chestplate".into(), @@ -644,7 +644,7 @@ impl DefaultableComponent for AttributeModifiers { Item::IronHelmet => vec![ AttributeModifiersEntry { slot: EquipmentSlotGroup::Head, - attribute: Attribute::Armor, + kind: Attribute::Armor, display: AttributeModifierDisplay::Default, modifier: AttributeModifier { id: "minecraft:armor.helmet".into(), @@ -654,7 +654,7 @@ impl DefaultableComponent for AttributeModifiers { }, AttributeModifiersEntry { slot: EquipmentSlotGroup::Head, - attribute: Attribute::ArmorToughness, + kind: Attribute::ArmorToughness, display: AttributeModifierDisplay::Default, modifier: AttributeModifier { id: "minecraft:armor.helmet".into(), @@ -666,7 +666,7 @@ impl DefaultableComponent for AttributeModifiers { Item::IronHoe => vec![ AttributeModifiersEntry { slot: EquipmentSlotGroup::Mainhand, - attribute: Attribute::AttackDamage, + kind: Attribute::AttackDamage, display: AttributeModifierDisplay::Default, modifier: AttributeModifier { id: "minecraft:base_attack_damage".into(), @@ -676,7 +676,7 @@ impl DefaultableComponent for AttributeModifiers { }, AttributeModifiersEntry { slot: EquipmentSlotGroup::Mainhand, - attribute: Attribute::AttackSpeed, + kind: Attribute::AttackSpeed, display: AttributeModifierDisplay::Default, modifier: AttributeModifier { id: "minecraft:base_attack_speed".into(), @@ -688,7 +688,7 @@ impl DefaultableComponent for AttributeModifiers { Item::IronHorseArmor => vec![ AttributeModifiersEntry { slot: EquipmentSlotGroup::Body, - attribute: Attribute::Armor, + kind: Attribute::Armor, display: AttributeModifierDisplay::Default, modifier: AttributeModifier { id: "minecraft:armor.body".into(), @@ -698,7 +698,7 @@ impl DefaultableComponent for AttributeModifiers { }, AttributeModifiersEntry { slot: EquipmentSlotGroup::Body, - attribute: Attribute::ArmorToughness, + kind: Attribute::ArmorToughness, display: AttributeModifierDisplay::Default, modifier: AttributeModifier { id: "minecraft:armor.body".into(), @@ -710,7 +710,7 @@ impl DefaultableComponent for AttributeModifiers { Item::IronLeggings => vec![ AttributeModifiersEntry { slot: EquipmentSlotGroup::Legs, - attribute: Attribute::Armor, + kind: Attribute::Armor, display: AttributeModifierDisplay::Default, modifier: AttributeModifier { id: "minecraft:armor.leggings".into(), @@ -720,7 +720,7 @@ impl DefaultableComponent for AttributeModifiers { }, AttributeModifiersEntry { slot: EquipmentSlotGroup::Legs, - attribute: Attribute::ArmorToughness, + kind: Attribute::ArmorToughness, display: AttributeModifierDisplay::Default, modifier: AttributeModifier { id: "minecraft:armor.leggings".into(), @@ -732,7 +732,7 @@ impl DefaultableComponent for AttributeModifiers { Item::IronPickaxe => vec![ AttributeModifiersEntry { slot: EquipmentSlotGroup::Mainhand, - attribute: Attribute::AttackDamage, + kind: Attribute::AttackDamage, display: AttributeModifierDisplay::Default, modifier: AttributeModifier { id: "minecraft:base_attack_damage".into(), @@ -742,7 +742,7 @@ impl DefaultableComponent for AttributeModifiers { }, AttributeModifiersEntry { slot: EquipmentSlotGroup::Mainhand, - attribute: Attribute::AttackSpeed, + kind: Attribute::AttackSpeed, display: AttributeModifierDisplay::Default, modifier: AttributeModifier { id: "minecraft:base_attack_speed".into(), @@ -754,7 +754,7 @@ impl DefaultableComponent for AttributeModifiers { Item::IronShovel => vec![ AttributeModifiersEntry { slot: EquipmentSlotGroup::Mainhand, - attribute: Attribute::AttackDamage, + kind: Attribute::AttackDamage, display: AttributeModifierDisplay::Default, modifier: AttributeModifier { id: "minecraft:base_attack_damage".into(), @@ -764,7 +764,7 @@ impl DefaultableComponent for AttributeModifiers { }, AttributeModifiersEntry { slot: EquipmentSlotGroup::Mainhand, - attribute: Attribute::AttackSpeed, + kind: Attribute::AttackSpeed, display: AttributeModifierDisplay::Default, modifier: AttributeModifier { id: "minecraft:base_attack_speed".into(), @@ -776,7 +776,7 @@ impl DefaultableComponent for AttributeModifiers { Item::IronSword => vec![ AttributeModifiersEntry { slot: EquipmentSlotGroup::Mainhand, - attribute: Attribute::AttackDamage, + kind: Attribute::AttackDamage, display: AttributeModifierDisplay::Default, modifier: AttributeModifier { id: "minecraft:base_attack_damage".into(), @@ -786,7 +786,7 @@ impl DefaultableComponent for AttributeModifiers { }, AttributeModifiersEntry { slot: EquipmentSlotGroup::Mainhand, - attribute: Attribute::AttackSpeed, + kind: Attribute::AttackSpeed, display: AttributeModifierDisplay::Default, modifier: AttributeModifier { id: "minecraft:base_attack_speed".into(), @@ -798,7 +798,7 @@ impl DefaultableComponent for AttributeModifiers { Item::LeatherBoots => vec![ AttributeModifiersEntry { slot: EquipmentSlotGroup::Feet, - attribute: Attribute::Armor, + kind: Attribute::Armor, display: AttributeModifierDisplay::Default, modifier: AttributeModifier { id: "minecraft:armor.boots".into(), @@ -808,7 +808,7 @@ impl DefaultableComponent for AttributeModifiers { }, AttributeModifiersEntry { slot: EquipmentSlotGroup::Feet, - attribute: Attribute::ArmorToughness, + kind: Attribute::ArmorToughness, display: AttributeModifierDisplay::Default, modifier: AttributeModifier { id: "minecraft:armor.boots".into(), @@ -820,7 +820,7 @@ impl DefaultableComponent for AttributeModifiers { Item::LeatherChestplate => vec![ AttributeModifiersEntry { slot: EquipmentSlotGroup::Chest, - attribute: Attribute::Armor, + kind: Attribute::Armor, display: AttributeModifierDisplay::Default, modifier: AttributeModifier { id: "minecraft:armor.chestplate".into(), @@ -830,7 +830,7 @@ impl DefaultableComponent for AttributeModifiers { }, AttributeModifiersEntry { slot: EquipmentSlotGroup::Chest, - attribute: Attribute::ArmorToughness, + kind: Attribute::ArmorToughness, display: AttributeModifierDisplay::Default, modifier: AttributeModifier { id: "minecraft:armor.chestplate".into(), @@ -842,7 +842,7 @@ impl DefaultableComponent for AttributeModifiers { Item::LeatherHelmet => vec![ AttributeModifiersEntry { slot: EquipmentSlotGroup::Head, - attribute: Attribute::Armor, + kind: Attribute::Armor, display: AttributeModifierDisplay::Default, modifier: AttributeModifier { id: "minecraft:armor.helmet".into(), @@ -852,7 +852,7 @@ impl DefaultableComponent for AttributeModifiers { }, AttributeModifiersEntry { slot: EquipmentSlotGroup::Head, - attribute: Attribute::ArmorToughness, + kind: Attribute::ArmorToughness, display: AttributeModifierDisplay::Default, modifier: AttributeModifier { id: "minecraft:armor.helmet".into(), @@ -864,7 +864,7 @@ impl DefaultableComponent for AttributeModifiers { Item::LeatherHorseArmor => vec![ AttributeModifiersEntry { slot: EquipmentSlotGroup::Body, - attribute: Attribute::Armor, + kind: Attribute::Armor, display: AttributeModifierDisplay::Default, modifier: AttributeModifier { id: "minecraft:armor.body".into(), @@ -874,7 +874,7 @@ impl DefaultableComponent for AttributeModifiers { }, AttributeModifiersEntry { slot: EquipmentSlotGroup::Body, - attribute: Attribute::ArmorToughness, + kind: Attribute::ArmorToughness, display: AttributeModifierDisplay::Default, modifier: AttributeModifier { id: "minecraft:armor.body".into(), @@ -886,7 +886,7 @@ impl DefaultableComponent for AttributeModifiers { Item::LeatherLeggings => vec![ AttributeModifiersEntry { slot: EquipmentSlotGroup::Legs, - attribute: Attribute::Armor, + kind: Attribute::Armor, display: AttributeModifierDisplay::Default, modifier: AttributeModifier { id: "minecraft:armor.leggings".into(), @@ -896,7 +896,7 @@ impl DefaultableComponent for AttributeModifiers { }, AttributeModifiersEntry { slot: EquipmentSlotGroup::Legs, - attribute: Attribute::ArmorToughness, + kind: Attribute::ArmorToughness, display: AttributeModifierDisplay::Default, modifier: AttributeModifier { id: "minecraft:armor.leggings".into(), @@ -908,7 +908,7 @@ impl DefaultableComponent for AttributeModifiers { Item::Mace => vec![ AttributeModifiersEntry { slot: EquipmentSlotGroup::Mainhand, - attribute: Attribute::AttackDamage, + kind: Attribute::AttackDamage, display: AttributeModifierDisplay::Default, modifier: AttributeModifier { id: "minecraft:base_attack_damage".into(), @@ -918,7 +918,7 @@ impl DefaultableComponent for AttributeModifiers { }, AttributeModifiersEntry { slot: EquipmentSlotGroup::Mainhand, - attribute: Attribute::AttackSpeed, + kind: Attribute::AttackSpeed, display: AttributeModifierDisplay::Default, modifier: AttributeModifier { id: "minecraft:base_attack_speed".into(), @@ -930,7 +930,7 @@ impl DefaultableComponent for AttributeModifiers { Item::NetheriteAxe => vec![ AttributeModifiersEntry { slot: EquipmentSlotGroup::Mainhand, - attribute: Attribute::AttackDamage, + kind: Attribute::AttackDamage, display: AttributeModifierDisplay::Default, modifier: AttributeModifier { id: "minecraft:base_attack_damage".into(), @@ -940,7 +940,7 @@ impl DefaultableComponent for AttributeModifiers { }, AttributeModifiersEntry { slot: EquipmentSlotGroup::Mainhand, - attribute: Attribute::AttackSpeed, + kind: Attribute::AttackSpeed, display: AttributeModifierDisplay::Default, modifier: AttributeModifier { id: "minecraft:base_attack_speed".into(), @@ -952,7 +952,7 @@ impl DefaultableComponent for AttributeModifiers { Item::NetheriteBoots => vec![ AttributeModifiersEntry { slot: EquipmentSlotGroup::Feet, - attribute: Attribute::Armor, + kind: Attribute::Armor, display: AttributeModifierDisplay::Default, modifier: AttributeModifier { id: "minecraft:armor.boots".into(), @@ -962,7 +962,7 @@ impl DefaultableComponent for AttributeModifiers { }, AttributeModifiersEntry { slot: EquipmentSlotGroup::Feet, - attribute: Attribute::ArmorToughness, + kind: Attribute::ArmorToughness, display: AttributeModifierDisplay::Default, modifier: AttributeModifier { id: "minecraft:armor.boots".into(), @@ -972,7 +972,7 @@ impl DefaultableComponent for AttributeModifiers { }, AttributeModifiersEntry { slot: EquipmentSlotGroup::Feet, - attribute: Attribute::KnockbackResistance, + kind: Attribute::KnockbackResistance, display: AttributeModifierDisplay::Default, modifier: AttributeModifier { id: "minecraft:armor.boots".into(), @@ -984,7 +984,7 @@ impl DefaultableComponent for AttributeModifiers { Item::NetheriteChestplate => vec![ AttributeModifiersEntry { slot: EquipmentSlotGroup::Chest, - attribute: Attribute::Armor, + kind: Attribute::Armor, display: AttributeModifierDisplay::Default, modifier: AttributeModifier { id: "minecraft:armor.chestplate".into(), @@ -994,7 +994,7 @@ impl DefaultableComponent for AttributeModifiers { }, AttributeModifiersEntry { slot: EquipmentSlotGroup::Chest, - attribute: Attribute::ArmorToughness, + kind: Attribute::ArmorToughness, display: AttributeModifierDisplay::Default, modifier: AttributeModifier { id: "minecraft:armor.chestplate".into(), @@ -1004,7 +1004,7 @@ impl DefaultableComponent for AttributeModifiers { }, AttributeModifiersEntry { slot: EquipmentSlotGroup::Chest, - attribute: Attribute::KnockbackResistance, + kind: Attribute::KnockbackResistance, display: AttributeModifierDisplay::Default, modifier: AttributeModifier { id: "minecraft:armor.chestplate".into(), @@ -1016,7 +1016,7 @@ impl DefaultableComponent for AttributeModifiers { Item::NetheriteHelmet => vec![ AttributeModifiersEntry { slot: EquipmentSlotGroup::Head, - attribute: Attribute::Armor, + kind: Attribute::Armor, display: AttributeModifierDisplay::Default, modifier: AttributeModifier { id: "minecraft:armor.helmet".into(), @@ -1026,7 +1026,7 @@ impl DefaultableComponent for AttributeModifiers { }, AttributeModifiersEntry { slot: EquipmentSlotGroup::Head, - attribute: Attribute::ArmorToughness, + kind: Attribute::ArmorToughness, display: AttributeModifierDisplay::Default, modifier: AttributeModifier { id: "minecraft:armor.helmet".into(), @@ -1036,7 +1036,7 @@ impl DefaultableComponent for AttributeModifiers { }, AttributeModifiersEntry { slot: EquipmentSlotGroup::Head, - attribute: Attribute::KnockbackResistance, + kind: Attribute::KnockbackResistance, display: AttributeModifierDisplay::Default, modifier: AttributeModifier { id: "minecraft:armor.helmet".into(), @@ -1048,7 +1048,7 @@ impl DefaultableComponent for AttributeModifiers { Item::NetheriteHoe => vec![ AttributeModifiersEntry { slot: EquipmentSlotGroup::Mainhand, - attribute: Attribute::AttackDamage, + kind: Attribute::AttackDamage, display: AttributeModifierDisplay::Default, modifier: AttributeModifier { id: "minecraft:base_attack_damage".into(), @@ -1058,7 +1058,7 @@ impl DefaultableComponent for AttributeModifiers { }, AttributeModifiersEntry { slot: EquipmentSlotGroup::Mainhand, - attribute: Attribute::AttackSpeed, + kind: Attribute::AttackSpeed, display: AttributeModifierDisplay::Default, modifier: AttributeModifier { id: "minecraft:base_attack_speed".into(), @@ -1070,7 +1070,7 @@ impl DefaultableComponent for AttributeModifiers { Item::NetheriteLeggings => vec![ AttributeModifiersEntry { slot: EquipmentSlotGroup::Legs, - attribute: Attribute::Armor, + kind: Attribute::Armor, display: AttributeModifierDisplay::Default, modifier: AttributeModifier { id: "minecraft:armor.leggings".into(), @@ -1080,7 +1080,7 @@ impl DefaultableComponent for AttributeModifiers { }, AttributeModifiersEntry { slot: EquipmentSlotGroup::Legs, - attribute: Attribute::ArmorToughness, + kind: Attribute::ArmorToughness, display: AttributeModifierDisplay::Default, modifier: AttributeModifier { id: "minecraft:armor.leggings".into(), @@ -1090,7 +1090,7 @@ impl DefaultableComponent for AttributeModifiers { }, AttributeModifiersEntry { slot: EquipmentSlotGroup::Legs, - attribute: Attribute::KnockbackResistance, + kind: Attribute::KnockbackResistance, display: AttributeModifierDisplay::Default, modifier: AttributeModifier { id: "minecraft:armor.leggings".into(), @@ -1102,7 +1102,7 @@ impl DefaultableComponent for AttributeModifiers { Item::NetheritePickaxe => vec![ AttributeModifiersEntry { slot: EquipmentSlotGroup::Mainhand, - attribute: Attribute::AttackDamage, + kind: Attribute::AttackDamage, display: AttributeModifierDisplay::Default, modifier: AttributeModifier { id: "minecraft:base_attack_damage".into(), @@ -1112,7 +1112,7 @@ impl DefaultableComponent for AttributeModifiers { }, AttributeModifiersEntry { slot: EquipmentSlotGroup::Mainhand, - attribute: Attribute::AttackSpeed, + kind: Attribute::AttackSpeed, display: AttributeModifierDisplay::Default, modifier: AttributeModifier { id: "minecraft:base_attack_speed".into(), @@ -1124,7 +1124,7 @@ impl DefaultableComponent for AttributeModifiers { Item::NetheriteShovel => vec![ AttributeModifiersEntry { slot: EquipmentSlotGroup::Mainhand, - attribute: Attribute::AttackDamage, + kind: Attribute::AttackDamage, display: AttributeModifierDisplay::Default, modifier: AttributeModifier { id: "minecraft:base_attack_damage".into(), @@ -1134,7 +1134,7 @@ impl DefaultableComponent for AttributeModifiers { }, AttributeModifiersEntry { slot: EquipmentSlotGroup::Mainhand, - attribute: Attribute::AttackSpeed, + kind: Attribute::AttackSpeed, display: AttributeModifierDisplay::Default, modifier: AttributeModifier { id: "minecraft:base_attack_speed".into(), @@ -1146,7 +1146,7 @@ impl DefaultableComponent for AttributeModifiers { Item::NetheriteSword => vec![ AttributeModifiersEntry { slot: EquipmentSlotGroup::Mainhand, - attribute: Attribute::AttackDamage, + kind: Attribute::AttackDamage, display: AttributeModifierDisplay::Default, modifier: AttributeModifier { id: "minecraft:base_attack_damage".into(), @@ -1156,7 +1156,7 @@ impl DefaultableComponent for AttributeModifiers { }, AttributeModifiersEntry { slot: EquipmentSlotGroup::Mainhand, - attribute: Attribute::AttackSpeed, + kind: Attribute::AttackSpeed, display: AttributeModifierDisplay::Default, modifier: AttributeModifier { id: "minecraft:base_attack_speed".into(), @@ -1168,7 +1168,7 @@ impl DefaultableComponent for AttributeModifiers { Item::PiglinHead => vec![AttributeModifiersEntry { display: AttributeModifierDisplay::Hidden, slot: EquipmentSlotGroup::Head, - attribute: Attribute::WaypointTransmitRange, + kind: Attribute::WaypointTransmitRange, modifier: AttributeModifier { id: "minecraft:waypoint_transmit_range_hide".into(), amount: -1.0, @@ -1178,7 +1178,7 @@ impl DefaultableComponent for AttributeModifiers { Item::PlayerHead => vec![AttributeModifiersEntry { display: AttributeModifierDisplay::Hidden, slot: EquipmentSlotGroup::Head, - attribute: Attribute::WaypointTransmitRange, + kind: Attribute::WaypointTransmitRange, modifier: AttributeModifier { id: "minecraft:waypoint_transmit_range_hide".into(), amount: -1.0, @@ -1188,7 +1188,7 @@ impl DefaultableComponent for AttributeModifiers { Item::SkeletonSkull => vec![AttributeModifiersEntry { display: AttributeModifierDisplay::Hidden, slot: EquipmentSlotGroup::Head, - attribute: Attribute::WaypointTransmitRange, + kind: Attribute::WaypointTransmitRange, modifier: AttributeModifier { id: "minecraft:waypoint_transmit_range_hide".into(), amount: -1.0, @@ -1198,7 +1198,7 @@ impl DefaultableComponent for AttributeModifiers { Item::StoneAxe => vec![ AttributeModifiersEntry { slot: EquipmentSlotGroup::Mainhand, - attribute: Attribute::AttackDamage, + kind: Attribute::AttackDamage, display: AttributeModifierDisplay::Default, modifier: AttributeModifier { id: "minecraft:base_attack_damage".into(), @@ -1208,7 +1208,7 @@ impl DefaultableComponent for AttributeModifiers { }, AttributeModifiersEntry { slot: EquipmentSlotGroup::Mainhand, - attribute: Attribute::AttackSpeed, + kind: Attribute::AttackSpeed, display: AttributeModifierDisplay::Default, modifier: AttributeModifier { id: "minecraft:base_attack_speed".into(), @@ -1220,7 +1220,7 @@ impl DefaultableComponent for AttributeModifiers { Item::StoneHoe => vec![ AttributeModifiersEntry { slot: EquipmentSlotGroup::Mainhand, - attribute: Attribute::AttackDamage, + kind: Attribute::AttackDamage, display: AttributeModifierDisplay::Default, modifier: AttributeModifier { id: "minecraft:base_attack_damage".into(), @@ -1230,7 +1230,7 @@ impl DefaultableComponent for AttributeModifiers { }, AttributeModifiersEntry { slot: EquipmentSlotGroup::Mainhand, - attribute: Attribute::AttackSpeed, + kind: Attribute::AttackSpeed, display: AttributeModifierDisplay::Default, modifier: AttributeModifier { id: "minecraft:base_attack_speed".into(), @@ -1242,7 +1242,7 @@ impl DefaultableComponent for AttributeModifiers { Item::StonePickaxe => vec![ AttributeModifiersEntry { slot: EquipmentSlotGroup::Mainhand, - attribute: Attribute::AttackDamage, + kind: Attribute::AttackDamage, display: AttributeModifierDisplay::Default, modifier: AttributeModifier { id: "minecraft:base_attack_damage".into(), @@ -1252,7 +1252,7 @@ impl DefaultableComponent for AttributeModifiers { }, AttributeModifiersEntry { slot: EquipmentSlotGroup::Mainhand, - attribute: Attribute::AttackSpeed, + kind: Attribute::AttackSpeed, display: AttributeModifierDisplay::Default, modifier: AttributeModifier { id: "minecraft:base_attack_speed".into(), @@ -1264,7 +1264,7 @@ impl DefaultableComponent for AttributeModifiers { Item::StoneShovel => vec![ AttributeModifiersEntry { slot: EquipmentSlotGroup::Mainhand, - attribute: Attribute::AttackDamage, + kind: Attribute::AttackDamage, display: AttributeModifierDisplay::Default, modifier: AttributeModifier { id: "minecraft:base_attack_damage".into(), @@ -1274,7 +1274,7 @@ impl DefaultableComponent for AttributeModifiers { }, AttributeModifiersEntry { slot: EquipmentSlotGroup::Mainhand, - attribute: Attribute::AttackSpeed, + kind: Attribute::AttackSpeed, display: AttributeModifierDisplay::Default, modifier: AttributeModifier { id: "minecraft:base_attack_speed".into(), @@ -1286,7 +1286,7 @@ impl DefaultableComponent for AttributeModifiers { Item::StoneSword => vec![ AttributeModifiersEntry { slot: EquipmentSlotGroup::Mainhand, - attribute: Attribute::AttackDamage, + kind: Attribute::AttackDamage, display: AttributeModifierDisplay::Default, modifier: AttributeModifier { id: "minecraft:base_attack_damage".into(), @@ -1296,7 +1296,7 @@ impl DefaultableComponent for AttributeModifiers { }, AttributeModifiersEntry { slot: EquipmentSlotGroup::Mainhand, - attribute: Attribute::AttackSpeed, + kind: Attribute::AttackSpeed, display: AttributeModifierDisplay::Default, modifier: AttributeModifier { id: "minecraft:base_attack_speed".into(), @@ -1308,7 +1308,7 @@ impl DefaultableComponent for AttributeModifiers { Item::Trident => vec![ AttributeModifiersEntry { slot: EquipmentSlotGroup::Mainhand, - attribute: Attribute::AttackDamage, + kind: Attribute::AttackDamage, display: AttributeModifierDisplay::Default, modifier: AttributeModifier { id: "minecraft:base_attack_damage".into(), @@ -1318,7 +1318,7 @@ impl DefaultableComponent for AttributeModifiers { }, AttributeModifiersEntry { slot: EquipmentSlotGroup::Mainhand, - attribute: Attribute::AttackSpeed, + kind: Attribute::AttackSpeed, display: AttributeModifierDisplay::Default, modifier: AttributeModifier { id: "minecraft:base_attack_speed".into(), @@ -1330,7 +1330,7 @@ impl DefaultableComponent for AttributeModifiers { Item::TurtleHelmet => vec![ AttributeModifiersEntry { slot: EquipmentSlotGroup::Head, - attribute: Attribute::Armor, + kind: Attribute::Armor, display: AttributeModifierDisplay::Default, modifier: AttributeModifier { id: "minecraft:armor.helmet".into(), @@ -1340,7 +1340,7 @@ impl DefaultableComponent for AttributeModifiers { }, AttributeModifiersEntry { slot: EquipmentSlotGroup::Head, - attribute: Attribute::ArmorToughness, + kind: Attribute::ArmorToughness, display: AttributeModifierDisplay::Default, modifier: AttributeModifier { id: "minecraft:armor.helmet".into(), @@ -1352,7 +1352,7 @@ impl DefaultableComponent for AttributeModifiers { Item::WitherSkeletonSkull => vec![AttributeModifiersEntry { display: AttributeModifierDisplay::Hidden, slot: EquipmentSlotGroup::Head, - attribute: Attribute::WaypointTransmitRange, + kind: Attribute::WaypointTransmitRange, modifier: AttributeModifier { id: "minecraft:waypoint_transmit_range_hide".into(), amount: -1.0, @@ -1362,7 +1362,7 @@ impl DefaultableComponent for AttributeModifiers { Item::WolfArmor => vec![ AttributeModifiersEntry { slot: EquipmentSlotGroup::Body, - attribute: Attribute::Armor, + kind: Attribute::Armor, display: AttributeModifierDisplay::Default, modifier: AttributeModifier { id: "minecraft:armor.body".into(), @@ -1372,7 +1372,7 @@ impl DefaultableComponent for AttributeModifiers { }, AttributeModifiersEntry { slot: EquipmentSlotGroup::Body, - attribute: Attribute::ArmorToughness, + kind: Attribute::ArmorToughness, display: AttributeModifierDisplay::Default, modifier: AttributeModifier { id: "minecraft:armor.body".into(), @@ -1384,7 +1384,7 @@ impl DefaultableComponent for AttributeModifiers { Item::WoodenAxe => vec![ AttributeModifiersEntry { slot: EquipmentSlotGroup::Mainhand, - attribute: Attribute::AttackDamage, + kind: Attribute::AttackDamage, display: AttributeModifierDisplay::Default, modifier: AttributeModifier { id: "minecraft:base_attack_damage".into(), @@ -1394,7 +1394,7 @@ impl DefaultableComponent for AttributeModifiers { }, AttributeModifiersEntry { slot: EquipmentSlotGroup::Mainhand, - attribute: Attribute::AttackSpeed, + kind: Attribute::AttackSpeed, display: AttributeModifierDisplay::Default, modifier: AttributeModifier { id: "minecraft:base_attack_speed".into(), @@ -1406,7 +1406,7 @@ impl DefaultableComponent for AttributeModifiers { Item::WoodenHoe => vec![ AttributeModifiersEntry { slot: EquipmentSlotGroup::Mainhand, - attribute: Attribute::AttackDamage, + kind: Attribute::AttackDamage, display: AttributeModifierDisplay::Default, modifier: AttributeModifier { id: "minecraft:base_attack_damage".into(), @@ -1416,7 +1416,7 @@ impl DefaultableComponent for AttributeModifiers { }, AttributeModifiersEntry { slot: EquipmentSlotGroup::Mainhand, - attribute: Attribute::AttackSpeed, + kind: Attribute::AttackSpeed, display: AttributeModifierDisplay::Default, modifier: AttributeModifier { id: "minecraft:base_attack_speed".into(), @@ -1428,7 +1428,7 @@ impl DefaultableComponent for AttributeModifiers { Item::WoodenPickaxe => vec![ AttributeModifiersEntry { slot: EquipmentSlotGroup::Mainhand, - attribute: Attribute::AttackDamage, + kind: Attribute::AttackDamage, display: AttributeModifierDisplay::Default, modifier: AttributeModifier { id: "minecraft:base_attack_damage".into(), @@ -1438,7 +1438,7 @@ impl DefaultableComponent for AttributeModifiers { }, AttributeModifiersEntry { slot: EquipmentSlotGroup::Mainhand, - attribute: Attribute::AttackSpeed, + kind: Attribute::AttackSpeed, display: AttributeModifierDisplay::Default, modifier: AttributeModifier { id: "minecraft:base_attack_speed".into(), @@ -1450,7 +1450,7 @@ impl DefaultableComponent for AttributeModifiers { Item::WoodenShovel => vec![ AttributeModifiersEntry { slot: EquipmentSlotGroup::Mainhand, - attribute: Attribute::AttackDamage, + kind: Attribute::AttackDamage, display: AttributeModifierDisplay::Default, modifier: AttributeModifier { id: "minecraft:base_attack_damage".into(), @@ -1460,7 +1460,7 @@ impl DefaultableComponent for AttributeModifiers { }, AttributeModifiersEntry { slot: EquipmentSlotGroup::Mainhand, - attribute: Attribute::AttackSpeed, + kind: Attribute::AttackSpeed, display: AttributeModifierDisplay::Default, modifier: AttributeModifier { id: "minecraft:base_attack_speed".into(), @@ -1472,7 +1472,7 @@ impl DefaultableComponent for AttributeModifiers { Item::WoodenSword => vec![ AttributeModifiersEntry { slot: EquipmentSlotGroup::Mainhand, - attribute: Attribute::AttackDamage, + kind: Attribute::AttackDamage, display: AttributeModifierDisplay::Default, modifier: AttributeModifier { id: "minecraft:base_attack_damage".into(), @@ -1482,7 +1482,7 @@ impl DefaultableComponent for AttributeModifiers { }, AttributeModifiersEntry { slot: EquipmentSlotGroup::Mainhand, - attribute: Attribute::AttackSpeed, + kind: Attribute::AttackSpeed, display: AttributeModifierDisplay::Default, modifier: AttributeModifier { id: "minecraft:base_attack_speed".into(), @@ -1494,7 +1494,7 @@ impl DefaultableComponent for AttributeModifiers { Item::ZombieHead => vec![AttributeModifiersEntry { display: AttributeModifierDisplay::Hidden, slot: EquipmentSlotGroup::Head, - attribute: Attribute::WaypointTransmitRange, + kind: Attribute::WaypointTransmitRange, modifier: AttributeModifier { id: "minecraft:waypoint_transmit_range_hide".into(), amount: -1.0, @@ -3691,7 +3691,7 @@ impl DefaultableComponent for EnchantmentGlintOverride { impl DefaultableComponent for PotDecorations { fn default_for_item(item: Item) -> Option<Self> { let value = match item { - Item::DecoratedPot => vec![Item::Brick, Item::Brick, Item::Brick, Item::Brick], + Item::DecoratedPot => [Item::Brick, Item::Brick, Item::Brick, Item::Brick], _ => return None, }; Some(PotDecorations { items: value }) diff --git a/azalea-inventory/src/default_components/mod.rs b/azalea-inventory/src/default_components/mod.rs index e6150066..7f9ef6fb 100644 --- a/azalea-inventory/src/default_components/mod.rs +++ b/azalea-inventory/src/default_components/mod.rs @@ -2,15 +2,15 @@ pub mod generated; use azalea_registry::Item; -use crate::components::DataComponent; +use crate::components::DataComponentTrait; /// A [`DataComponent`] that some [`Item`]s may have a default value for. -pub trait DefaultableComponent: DataComponent { +pub trait DefaultableComponent: DataComponentTrait { fn default_for_item(item: Item) -> Option<Self> where Self: Sized; } -impl<T: DataComponent> DefaultableComponent for T { +impl<T: DataComponentTrait> DefaultableComponent for T { default fn default_for_item(_item: Item) -> Option<Self> { None } diff --git a/azalea-inventory/src/item/consume_effect.rs b/azalea-inventory/src/item/consume_effect.rs index b9540955..8aab42b8 100644 --- a/azalea-inventory/src/item/consume_effect.rs +++ b/azalea-inventory/src/item/consume_effect.rs @@ -1,20 +1,26 @@ use azalea_buf::AzBuf; -use azalea_core::resource_location::ResourceLocation; +use azalea_core::{codec_utils::is_default, resource_location::ResourceLocation}; use azalea_registry::{HolderSet, MobEffect, SoundEvent}; +use serde::Serialize; use crate::components::MobEffectInstance; -#[derive(Clone, PartialEq, AzBuf)] +#[derive(Clone, PartialEq, Debug, AzBuf, Serialize)] +#[serde(rename_all = "snake_case", tag = "type")] pub enum ConsumeEffect { ApplyEffects { + #[serde(skip_serializing_if = "is_default")] effects: Vec<MobEffectInstance>, + #[serde(skip_serializing_if = "is_default")] probability: f32, }, RemoveEffects { + #[serde(skip_serializing_if = "is_default")] effects: HolderSet<MobEffect, ResourceLocation>, }, ClearAllEffects, TeleportRandomly { + #[serde(skip_serializing_if = "is_default")] diameter: f32, }, PlaySound { diff --git a/azalea-inventory/src/slot.rs b/azalea-inventory/src/slot.rs index 57f57696..444e0b2b 100644 --- a/azalea-inventory/src/slot.rs +++ b/azalea-inventory/src/slot.rs @@ -6,11 +6,13 @@ use std::{ }; use azalea_buf::{AzaleaRead, AzaleaReadVar, AzaleaWrite, AzaleaWriteVar, BufReadError}; +use azalea_core::codec_utils::is_default; use azalea_registry::{DataComponentKind, Item}; use indexmap::IndexMap; +use serde::{Serialize, ser::SerializeMap}; use crate::{ - components::{self}, + components::{self, DataComponentUnion}, default_components::get_default_component, }; @@ -114,22 +116,49 @@ impl ItemStack { /// /// This is used for things like getting the damage of an item, or seeing /// how much food it replenishes. - pub fn get_component<'a, T: components::DataComponent>(&'a self) -> Option<Cow<'a, T>> { + pub fn get_component<'a, T: components::DataComponentTrait>(&'a self) -> Option<Cow<'a, T>> { self.as_present().and_then(|i| i.get_component::<T>()) } + + pub fn with_component< + T: components::EncodableDataComponent + components::DataComponentTrait, + >( + mut self, + component: impl Into<Option<T>>, + ) -> Self { + if let ItemStack::Present(i) = &mut self { + let component: Option<T> = component.into(); + let component: Option<DataComponentUnion> = component.map(|c| c.into()); + i.component_patch.components.insert(T::KIND, component); + } + self + } +} +impl Serialize for ItemStack { + fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> + where + S: serde::Serializer, + { + match self { + ItemStack::Empty => serializer.serialize_unit(), + ItemStack::Present(i) => i.serialize(serializer), + } + } } /// An item in an inventory, with a count and NBT. Usually you want /// [`ItemStack`] or [`azalea_registry::Item`] instead. -#[derive(Debug, Clone, PartialEq)] +#[derive(Debug, Clone, PartialEq, Serialize)] pub struct ItemStackData { + #[serde(rename = "id")] + pub kind: azalea_registry::Item, /// The amount of the item in this slot. /// /// The count can be zero or negative, but this is rare. pub count: i32, - pub kind: azalea_registry::Item, /// The item's components that the server set to be different from the /// defaults. + #[serde(rename = "components", skip_serializing_if = "is_default")] pub component_patch: DataComponentPatch, } @@ -177,7 +206,7 @@ impl ItemStackData { /// /// This is used for things like getting the damage of an item, or seeing /// how much food it replenishes. - pub fn get_component<'a, T: components::DataComponent>(&'a self) -> Option<Cow<'a, T>> { + pub fn get_component<'a, T: components::DataComponentTrait>(&'a self) -> Option<Cow<'a, T>> { if let Some(c) = self.component_patch.get::<T>() { Some(Cow::Borrowed(c)) } else { @@ -253,8 +282,7 @@ impl From<(Item, i32)> for ItemStackData { /// and Azalea does not implement that yet. #[derive(Default)] pub struct DataComponentPatch { - pub components: - IndexMap<DataComponentKind, Option<Box<dyn components::EncodableDataComponent>>>, + components: IndexMap<DataComponentKind, Option<DataComponentUnion>>, } impl DataComponentPatch { @@ -269,8 +297,8 @@ impl DataComponentPatch { /// # Some(()) /// # } /// ``` - pub fn get<T: components::DataComponent>(&self) -> Option<&T> { - let component = self.components.get(&T::KIND).and_then(|c| c.as_deref())?; + pub fn get<T: components::DataComponentTrait>(&self) -> Option<&T> { + let component = self.components.get(&T::KIND)?; let component_any = component as &dyn Any; component_any.downcast_ref::<T>() } @@ -279,7 +307,13 @@ impl DataComponentPatch { &self, kind: DataComponentKind, ) -> Option<&dyn components::EncodableDataComponent> { - self.components.get(&kind).and_then(|c| c.as_deref()) + self.components.get(&kind).and_then(|c| { + c.as_ref().map(|c| { + // SAFETY: we just got the component from the map, so it must be the correct + // kind + unsafe { c.as_kind(kind) } + }) + }) } /// Returns whether the component in the generic argument is present for @@ -292,13 +326,41 @@ impl DataComponentPatch { /// let is_edible = item.component_patch.has::<components::Food>(); /// # assert!(!is_edible); /// ``` - pub fn has<T: components::DataComponent>(&self) -> bool { + pub fn has<T: components::DataComponentTrait>(&self) -> bool { self.has_kind(T::KIND) } pub fn has_kind(&self, kind: DataComponentKind) -> bool { self.get_kind(kind).is_some() } + + pub fn iter<'a>( + &'a self, + ) -> impl Iterator< + Item = ( + DataComponentKind, + Option<&'a dyn components::EncodableDataComponent>, + ), + > + 'a { + self.components.iter().map(|(&kind, component)| { + component.as_ref().map_or_else( + || (kind, None), + |c| (kind, unsafe { Some(c.as_kind(kind)) }), + ) + }) + } +} + +impl Drop for DataComponentPatch { + fn drop(&mut self) { + // the component values are ManuallyDrop since they're in a union + for (kind, component) in &mut self.components { + if let Some(component) = component { + // SAFETY: we got the kind and component from the map + unsafe { component.drop_as(*kind) }; + } + } + } } impl AzaleaRead for DataComponentPatch { @@ -313,7 +375,7 @@ impl AzaleaRead for DataComponentPatch { let mut components = IndexMap::new(); for _ in 0..components_with_data_count { let component_kind = DataComponentKind::azalea_read(buf)?; - let component_data = components::from_kind(component_kind, buf)?; + let component_data = DataComponentUnion::azalea_read_as(component_kind, buf)?; components.insert(component_kind, Some(component_data)); } @@ -347,7 +409,8 @@ impl AzaleaWrite for DataComponentPatch { kind.azalea_write(buf)?; component_buf.clear(); - component.encode(&mut component_buf)?; + // SAFETY: we got the component from the map and are passing in the same kind + unsafe { component.azalea_write_as(*kind, &mut component_buf) }?; buf.write_all(&component_buf)?; } } @@ -366,7 +429,10 @@ impl Clone for DataComponentPatch { fn clone(&self) -> Self { let mut components = IndexMap::with_capacity(self.components.len()); for (kind, component) in &self.components { - components.insert(*kind, component.as_ref().map(|c| (*c).clone())); + components.insert( + *kind, + component.as_ref().map(|c| unsafe { c.clone_as(*kind) }), + ); } DataComponentPatch { components } } @@ -390,7 +456,9 @@ impl PartialEq for DataComponentPatch { let Some(other_component) = other_component else { return false; }; - if !component.eq((*other_component).clone()) { + // SAFETY: we already checked that the kinds are the same, and we got the + // components from the map, so they must be the correct kinds + if !unsafe { component.eq_as(other_component, *kind) } { return false; } } else if other_component.is_some() { @@ -400,3 +468,22 @@ impl PartialEq for DataComponentPatch { true } } + +impl Serialize for DataComponentPatch { + fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> + where + S: serde::Serializer, + { + let mut s = serializer.serialize_map(Some(self.components.len()))?; + for (kind, component) in &self.components { + if let Some(component) = component { + unsafe { component.serialize_entry_as(&mut s, *kind) }?; + } else { + #[derive(Serialize)] + struct EmptyComponent; + s.serialize_entry(&format!("!{kind}"), &EmptyComponent)?; + } + } + s.end() + } +} |
