From 1cf6d92f1a8be954f6885704c31f317b99b05972 Mon Sep 17 00:00:00 2001 From: mat Date: Tue, 7 Oct 2025 06:01:19 +0400 Subject: update ResolvableProfile data component to 1.21.9 --- Cargo.lock | 1 + azalea-auth/src/game_profile.rs | 115 +- azalea-client/src/client.rs | 16 +- azalea-client/src/plugins/packet/config/events.rs | 4 +- azalea-client/tests/mine_block_rollback.rs | 1 + azalea-client/tests/mine_block_timing.rs | 1 + azalea-client/tests/mine_block_without_rollback.rs | 1 + .../tests/packet_order_set_carried_item.rs | 3 +- azalea-entity/src/data.rs | 51 +- azalea-entity/src/metadata.rs | 7 +- azalea-inventory/Cargo.toml | 1 + azalea-inventory/src/components.rs | 1484 -------------------- azalea-inventory/src/components/mod.rs | 1467 +++++++++++++++++++ azalea-inventory/src/components/profile.rs | 73 + codegen/lib/code/data_components.py | 8 +- codegen/lib/code/entity.py | 5 +- 16 files changed, 1634 insertions(+), 1604 deletions(-) delete mode 100644 azalea-inventory/src/components.rs create mode 100644 azalea-inventory/src/components/mod.rs create mode 100644 azalea-inventory/src/components/profile.rs diff --git a/Cargo.lock b/Cargo.lock index e19a8279..6a46064c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -436,6 +436,7 @@ dependencies = [ name = "azalea-inventory" version = "0.14.0+mc1.21.9" dependencies = [ + "azalea-auth", "azalea-buf", "azalea-chat", "azalea-core", diff --git a/azalea-auth/src/game_profile.rs b/azalea-auth/src/game_profile.rs index c944bcc4..4f5bccfd 100644 --- a/azalea-auth/src/game_profile.rs +++ b/azalea-auth/src/game_profile.rs @@ -4,14 +4,14 @@ use std::{ }; use azalea_buf::{ - AzaleaRead, AzaleaReadLimited, AzaleaReadVar, AzaleaWrite, AzaleaWriteVar, BufReadError, + AzBuf, AzaleaRead, AzaleaReadLimited, AzaleaReadVar, AzaleaWrite, AzaleaWriteVar, BufReadError, }; use indexmap::IndexMap; -use serde::{Deserialize, Serialize}; +use serde::{Deserialize, Serialize, Serializer}; use uuid::Uuid; /// Information about the player that's usually stored on Mojang's servers. -#[derive(Debug, Clone, Default, Eq, PartialEq)] +#[derive(Debug, Clone, Default, Eq, PartialEq, AzBuf)] pub struct GameProfile { /// The UUID of the player. /// @@ -27,26 +27,6 @@ pub struct GameProfile { /// This is an `Arc` to make it cheaper to clone. pub properties: Arc, } -impl AzaleaRead for GameProfile { - fn azalea_read(buf: &mut io::Cursor<&[u8]>) -> Result { - let uuid = Uuid::azalea_read(buf)?; - let name = String::azalea_read(buf)?; - let properties = GameProfileProperties::azalea_read(buf)?; - Ok(GameProfile { - uuid, - name, - properties: Arc::new(properties), - }) - } -} -impl AzaleaWrite for GameProfile { - fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> { - self.uuid.azalea_write(buf)?; - self.name.azalea_write(buf)?; - self.properties.azalea_write(buf)?; - Ok(()) - } -} impl GameProfile { pub fn new(uuid: Uuid, name: String) -> Self { @@ -60,20 +40,10 @@ impl GameProfile { impl From for GameProfile { fn from(value: SerializableGameProfile) -> Self { - let mut properties = IndexMap::new(); - for value in value.properties { - properties.insert( - value.name, - ProfilePropertyValue { - value: value.value, - signature: value.signature, - }, - ); - } Self { - uuid: value.id, - name: value.name, - properties: Arc::new(GameProfileProperties { map: properties }), + uuid: value.id.unwrap_or_default(), + name: value.name.unwrap_or_default(), + properties: Arc::new(value.properties.into()), } } } @@ -134,36 +104,81 @@ impl AzaleaWrite for ProfilePropertyValue { #[derive(Debug, Clone, Serialize, Deserialize)] pub struct SerializableGameProfile { - pub id: Uuid, - pub name: String, - pub properties: Vec, + #[serde(default)] + #[serde(skip_serializing_if = "Option::is_none")] + pub id: Option, + #[serde(default)] + #[serde(skip_serializing_if = "Option::is_none")] + pub name: Option, + #[serde(default)] + #[serde(skip_serializing_if = "SerializableProfileProperties::is_empty")] + pub properties: SerializableProfileProperties, } impl From for SerializableGameProfile { fn from(value: GameProfile) -> Self { - let mut properties = Vec::new(); - for (key, value) in &value.properties.map { - properties.push(SerializableProfilePropertyValue { - name: key.clone(), - value: value.value.clone(), - signature: value.signature.clone(), - }); - } Self { - id: value.uuid, - name: value.name, - properties, + id: Some(value.uuid), + name: Some(value.name), + properties: (*value.properties).clone().into(), } } } +#[derive(Debug, Clone, Serialize, Deserialize, Default)] +#[serde(transparent)] +pub struct SerializableProfileProperties { + pub list: Vec, +} +impl SerializableProfileProperties { + pub fn is_empty(&self) -> bool { + self.list.is_empty() + } +} #[derive(Debug, Clone, Serialize, Deserialize)] pub struct SerializableProfilePropertyValue { pub name: String, pub value: String, + #[serde(default)] + #[serde(skip_serializing_if = "Option::is_none")] pub signature: Option, } +impl From for SerializableProfileProperties { + fn from(value: GameProfileProperties) -> Self { + let mut list = Vec::new(); + for (name, entry) in value.map { + list.push(SerializableProfilePropertyValue { + name, + value: entry.value, + signature: entry.signature, + }); + } + Self { list } + } +} +impl From for GameProfileProperties { + fn from(value: SerializableProfileProperties) -> Self { + let mut map = IndexMap::new(); + for entry in value.list { + map.insert( + entry.name, + ProfilePropertyValue { + value: entry.value, + signature: entry.signature, + }, + ); + } + Self { map } + } +} +impl Serialize for GameProfile { + fn serialize(&self, serializer: S) -> Result { + let serializable = SerializableGameProfile::from(self.clone()); + serializable.serialize(serializer) + } +} + #[cfg(test)] mod tests { use super::*; diff --git a/azalea-client/src/client.rs b/azalea-client/src/client.rs index bb827838..cf07f8b2 100644 --- a/azalea-client/src/client.rs +++ b/azalea-client/src/client.rs @@ -261,12 +261,13 @@ impl Client { /// return it. /// /// - /// If the component can't be cloned, try [`Self::map_component`] instead. - /// If it isn't guaranteed to be present, use [`Self::get_component`] or - /// [`Self::map_get_component`]. + /// If the component can't be cloned, try [`Self::query_self`] instead. + /// If it isn't guaranteed to be present, you can use + /// [`Self::get_component`] or [`Self::query_self`]. /// - /// You may also use [`Self::ecs`] and [`Self::query`] directly if you need - /// more control over when the ECS is locked. + /// + /// You may also use [`Self::ecs`] directly if you need more control over + /// when the ECS is locked. /// /// # Panics /// @@ -285,9 +286,10 @@ impl Client { /// Get a component from this client, or `None` if it doesn't exist. /// - /// If the component can't be cloned, try [`Self::map_component`] instead. + /// If the component can't be cloned, consider using [`Self::query_self`] + /// with `Option<&T>` instead. /// - /// You may also have to use [`Self::with_query`] directly. + /// You may also have to use [`Self::query_self`] directly. pub fn get_component(&self) -> Option { self.query_self::, _>(|t| t.cloned()) } diff --git a/azalea-client/src/plugins/packet/config/events.rs b/azalea-client/src/plugins/packet/config/events.rs index be5cfdb1..92df8d74 100644 --- a/azalea-client/src/plugins/packet/config/events.rs +++ b/azalea-client/src/plugins/packet/config/events.rs @@ -54,10 +54,10 @@ pub fn handle_outgoing_packets_observer( /// A Bevy trigger that's sent when our client receives a [`ClientboundPing`] /// packet in the config state. /// -/// Also see [`PingEvent`]. +/// Also see [`GamePingEvent`]. /// /// [`ClientboundPing`]: azalea_protocol::packets::config::ClientboundPing -/// [`PingEvent`]: crate::packet::game::PingEvent +/// [`GamePingEvent`]: crate::packet::game::GamePingEvent #[derive(Event, Debug, Clone)] pub struct ConfigPingEvent { pub entity: Entity, diff --git a/azalea-client/tests/mine_block_rollback.rs b/azalea-client/tests/mine_block_rollback.rs index 67a66169..44ad629f 100644 --- a/azalea-client/tests/mine_block_rollback.rs +++ b/azalea-client/tests/mine_block_rollback.rs @@ -30,6 +30,7 @@ fn test_mine_block_rollback() { simulation.write_message(StartMiningBlockEvent { entity: simulation.entity, position: pos, + force: true, }); simulation.tick(); assert_eq!(simulation.get_block_state(pos), Some(Block::Air.into())); diff --git a/azalea-client/tests/mine_block_timing.rs b/azalea-client/tests/mine_block_timing.rs index 1cbd2f61..6548b28a 100644 --- a/azalea-client/tests/mine_block_timing.rs +++ b/azalea-client/tests/mine_block_timing.rs @@ -57,6 +57,7 @@ fn test_mine_block_timing() { simulation.write_message(StartMiningBlockEvent { entity: simulation.entity, position: pos, + force: false, }); sent_packets.clear(); simulation.tick(); diff --git a/azalea-client/tests/mine_block_without_rollback.rs b/azalea-client/tests/mine_block_without_rollback.rs index 16a371e5..a5a437a0 100644 --- a/azalea-client/tests/mine_block_without_rollback.rs +++ b/azalea-client/tests/mine_block_without_rollback.rs @@ -29,6 +29,7 @@ fn test_mine_block_without_rollback() { simulation.write_message(StartMiningBlockEvent { entity: simulation.entity, position: pos, + force: true, }); simulation.tick(); assert_eq!(simulation.get_block_state(pos), Some(Block::Air.into())); diff --git a/azalea-client/tests/packet_order_set_carried_item.rs b/azalea-client/tests/packet_order_set_carried_item.rs index 0506ad8e..a357dec0 100644 --- a/azalea-client/tests/packet_order_set_carried_item.rs +++ b/azalea-client/tests/packet_order_set_carried_item.rs @@ -55,13 +55,14 @@ fn test_packet_order_set_carried_item() { simulation.tick(); simulation.tick(); - simulation.write_message(SetSelectedHotbarSlotEvent { + simulation.trigger(SetSelectedHotbarSlotEvent { entity: simulation.entity, slot: 1, }); simulation.write_message(StartMiningBlockEvent { entity: simulation.entity, position: pos, + force: false, }); sent_packets.clear(); diff --git a/azalea-entity/src/data.rs b/azalea-entity/src/data.rs index 84a5b153..65267c4a 100644 --- a/azalea-entity/src/data.rs +++ b/azalea-entity/src/data.rs @@ -2,15 +2,13 @@ use std::io::{self, Cursor, Write}; -use azalea_auth::game_profile::{GameProfile, GameProfileProperties}; use azalea_buf::{AzBuf, AzaleaRead, AzaleaReadVar, AzaleaWrite, AzaleaWriteVar, BufReadError}; use azalea_chat::FormattedText; use azalea_core::{ direction::Direction, position::{BlockPos, GlobalPos, Vec3f32}, - resource_location::ResourceLocation, }; -use azalea_inventory::ItemStack; +use azalea_inventory::{ItemStack, components}; use bevy_ecs::component::Component; use derive_more::Deref; use enum_as_inner::EnumAsInner; @@ -97,7 +95,7 @@ pub enum EntityDataValue { WeatheringCopperState(WeatheringCopperStateKind), Vector3(Vec3f32), Quaternion(Quaternion), - ResolvableProfile(ResolvableProfile), + ResolvableProfile(components::Profile), } #[derive(Clone, Debug, PartialEq)] @@ -111,51 +109,6 @@ pub struct Quaternion { pub w: f32, } -#[derive(Clone, Debug, AzBuf, Default, PartialEq)] -pub struct ResolvableProfile { - pub unpack: Box, - pub skin_patch: Box, -} - -#[derive(Clone, Debug, AzBuf, PartialEq)] -pub enum PartialOrFullProfile { - Partial(PartialProfile), - Full(GameProfile), -} -impl Default for PartialOrFullProfile { - fn default() -> Self { - Self::Partial(PartialProfile::default()) - } -} - -#[derive(Clone, Debug, AzBuf, Default, PartialEq)] -pub struct PartialProfile { - #[limit(16)] - pub name: Option, - pub id: Option, - pub properties: GameProfileProperties, -} - -#[derive(Clone, Debug, AzBuf, Default, PartialEq)] -pub struct PlayerSkinPatch { - pub body: Option, - pub cape: Option, - pub elytra: Option, - pub model: Option, -} - -#[derive(Clone, Debug, Copy, AzBuf, Default, PartialEq)] -pub enum PlayerModelType { - #[default] - Wide, - Slim, -} - -#[derive(Clone, Debug, AzBuf, PartialEq)] -pub struct ResourceTexture { - pub id: ResourceLocation, -} - // mojang just calls this ArmadilloState but i added "Kind" since otherwise it // collides with a name in metadata.rs #[derive(Clone, Debug, Copy, Default, AzBuf, PartialEq)] diff --git a/azalea-entity/src/metadata.rs b/azalea-entity/src/metadata.rs index 56455bb7..68b8b78c 100644 --- a/azalea-entity/src/metadata.rs +++ b/azalea-entity/src/metadata.rs @@ -8,7 +8,7 @@ use azalea_core::{ direction::Direction, position::{BlockPos, Vec3f32}, }; -use azalea_inventory::ItemStack; +use azalea_inventory::{ItemStack, components}; use azalea_registry::DataRegistry; use bevy_ecs::{bundle::Bundle, component::Component}; use derive_more::{Deref, DerefMut}; @@ -17,8 +17,7 @@ use uuid::Uuid; use super::{ ArmadilloStateKind, CopperGolemStateKind, EntityDataItem, EntityDataValue, OptionalUnsignedInt, - Pose, Quaternion, ResolvableProfile, Rotations, SnifferStateKind, VillagerData, - WeatheringCopperStateKind, + Pose, Quaternion, Rotations, SnifferStateKind, VillagerData, WeatheringCopperStateKind, }; use crate::particle::Particle; @@ -6054,7 +6053,7 @@ pub struct MannequinPlayerMainHand(pub u8); #[derive(Component, Deref, DerefMut, Clone, PartialEq)] pub struct MannequinPlayerModeCustomisation(pub u8); #[derive(Component, Deref, DerefMut, Clone, PartialEq)] -pub struct Profile(pub ResolvableProfile); +pub struct Profile(pub components::Profile); #[derive(Component, Deref, DerefMut, Clone, PartialEq)] pub struct Immovable(pub bool); #[derive(Component, Deref, DerefMut, Clone, PartialEq)] diff --git a/azalea-inventory/Cargo.toml b/azalea-inventory/Cargo.toml index d10aa787..8fb1d625 100644 --- a/azalea-inventory/Cargo.toml +++ b/azalea-inventory/Cargo.toml @@ -7,6 +7,7 @@ license.workspace = true repository.workspace = true [dependencies] +azalea-auth.workspace = true azalea-buf.workspace = true azalea-chat = { workspace = true, features = ["azalea-buf"] } azalea-core.workspace = true diff --git a/azalea-inventory/src/components.rs b/azalea-inventory/src/components.rs deleted file mode 100644 index b820afc9..00000000 --- a/azalea-inventory/src/components.rs +++ /dev/null @@ -1,1484 +0,0 @@ -use core::f64; -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::{ - 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 DataComponentTrait: - Send + Sync + Any + Clone + Serialize + Into -{ - const KIND: DataComponentKind; -} - -pub trait EncodableDataComponent: Send + Sync + Any { - fn encode(&self, buf: &mut Vec) -> 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; - // same thing here - fn eq(&self, other: &dyn EncodableDataComponent) -> bool; -} - -impl EncodableDataComponent for T -where - T: DataComponentTrait + Clone + AzaleaWrite + AzaleaRead + PartialEq, -{ - fn encode(&self, buf: &mut Vec) -> 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 { - let cloned = self.clone(); - Box::new(cloned) - } - fn eq(&self, other: &dyn EncodableDataComponent) -> bool { - let other_any: &dyn Any = other; - match other_any.downcast_ref::() { - Some(other) => self == other, - _ => false, - } - } -} - -#[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>, )* - } - impl DataComponentUnion { - /// # Safety - /// - /// `kind` must be the correct value for this union. - pub unsafe fn serialize_entry_as( - &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) } }, )* - } - } - pub fn azalea_read_as( - kind: registry::DataComponentKind, - buf: &mut Cursor<&[u8]>, - ) -> Result { - 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 impl std::io::Write, - ) -> io::Result<()> { - let mut value = Vec::new(); - match kind { - $( DataComponentKind::$x => unsafe { self.$x.encode(&mut value)? }, )* - }; - buf.write_all(&value)?; - - Ok(()) - } - /// # 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) }, )* - } - } - } - $( - 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, -} - -#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] -#[serde(transparent)] -pub struct MaxStackSize { - #[var] - pub count: i32, -} - -#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] -#[serde(transparent)] -pub struct MaxDamage { - #[var] - pub amount: i32, -} - -#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] -#[serde(transparent)] -pub struct Damage { - #[var] - pub amount: i32, -} - -#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] -pub struct Unbreakable; - -#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] -#[serde(transparent)] -pub struct CustomName { - pub name: FormattedText, -} - -#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] -#[serde(transparent)] -pub struct ItemName { - pub name: FormattedText, -} - -#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] -#[serde(transparent)] -pub struct Lore { - pub lines: Vec, - // vanilla also has styled_lines here but it doesn't appear to be used for the protocol -} - -#[derive(Clone, Copy, PartialEq, AzBuf, Debug, Serialize)] -#[serde(rename_all = "snake_case")] -pub enum Rarity { - Common, - Uncommon, - Rare, - Epic, -} - -#[derive(Clone, PartialEq, AzBuf, Serialize)] -#[serde(transparent)] -pub struct Enchantments { - #[var] - pub levels: HashMap, -} - -#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] -pub enum BlockStateValueMatcher { - Exact { - value: String, - }, - Range { - min: Option, - max: Option, - }, -} - -#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] -pub struct BlockStatePropertyMatcher { - pub name: String, - pub value_matcher: BlockStateValueMatcher, -} - -#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] -pub struct BlockPredicate { - #[serde(skip_serializing_if = "is_default")] - pub blocks: Option>, - #[serde(skip_serializing_if = "is_default")] - pub properties: Option>, - #[serde(skip_serializing_if = "is_default")] - pub nbt: Option, -} - -#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] -#[serde(transparent)] -pub struct AdventureModePredicate { - #[serde(serialize_with = "flatten_array")] - pub predicates: Vec, -} - -#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] -#[serde(transparent)] -pub struct CanPlaceOn { - pub predicate: AdventureModePredicate, -} - -#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] -#[serde(transparent)] -pub struct CanBreak { - pub predicate: AdventureModePredicate, -} - -#[derive(Clone, Copy, PartialEq, AzBuf, Debug, Serialize)] -#[serde(rename_all = "snake_case")] -pub enum EquipmentSlotGroup { - Any, - Mainhand, - Offhand, - Hand, - Feet, - Legs, - Chest, - Head, - Armor, - Body, -} - -#[derive(Clone, Copy, PartialEq, AzBuf, Debug, Serialize)] -#[serde(rename_all = "snake_case")] -pub enum AttributeModifierOperation { - AddValue, - AddMultipliedBase, - AddMultipliedTotal, -} - -// 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, Debug, Serialize)] -pub struct AttributeModifier { - pub id: ResourceLocation, - pub amount: f64, - pub operation: AttributeModifierOperation, -} - -#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] -pub struct AttributeModifiersEntry { - #[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, Debug, Serialize)] -#[serde(transparent)] -pub struct AttributeModifiers { - pub modifiers: Vec, -} - -#[derive(Clone, PartialEq, AzBuf, Debug, Default, Serialize)] -#[serde(rename_all = "snake_case")] -pub enum AttributeModifierDisplay { - #[default] - Default, - Hidden, - Override { - text: FormattedText, - }, -} - -#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] -pub struct CustomModelData { - #[serde(skip_serializing_if = "Vec::is_empty")] - pub floats: Vec, - #[serde(skip_serializing_if = "Vec::is_empty")] - pub flags: Vec, - #[serde(skip_serializing_if = "Vec::is_empty")] - pub strings: Vec, - #[serde(skip_serializing_if = "Vec::is_empty")] - pub colors: Vec, -} - -#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] -#[serde(transparent)] -pub struct RepairCost { - #[var] - pub cost: u32, -} - -#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] -pub struct CreativeSlotLock; - -#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] -#[serde(transparent)] -pub struct EnchantmentGlintOverride { - pub show_glint: bool, -} - -#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] -pub struct IntangibleProjectile; - -#[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>, -} -impl MobEffectDetails { - pub const fn new() -> Self { - MobEffectDetails { - amplifier: 0, - duration: 0, - ambient: false, - show_particles: true, - show_icon: true, - hidden_effect: None, - } - } -} -impl Default for MobEffectDetails { - fn default() -> Self { - Self::new() - } -} - -#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] -pub struct MobEffectInstance { - pub id: MobEffect, - #[serde(flatten)] - pub details: MobEffectDetails, -} - -#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] -pub struct PossibleEffect { - pub effect: MobEffectInstance, - pub probability: f32, -} - -#[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 Food { - pub const fn new() -> Self { - Food { - nutrition: 0, - saturation: 0., - can_always_eat: false, - } - } -} - -#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] -pub struct ToolRule { - pub blocks: HolderSet, - #[serde(skip_serializing_if = "is_default")] - pub speed: Option, - #[serde(skip_serializing_if = "is_default")] - pub correct_for_drops: Option, -} -impl ToolRule { - pub const fn new() -> Self { - ToolRule { - blocks: HolderSet::Direct { contents: vec![] }, - speed: None, - correct_for_drops: None, - } - } -} -impl Default for ToolRule { - fn default() -> Self { - Self::new() - } -} - -#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] -pub struct Tool { - #[serde(serialize_with = "flatten_array")] - pub rules: Vec, - #[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 Tool { - pub const fn new() -> Self { - Tool { - rules: vec![], - default_mining_speed: 1., - damage_per_block: 1, - can_destroy_blocks_in_creative: true, - } - } -} -impl Default for Tool { - fn default() -> Self { - Self::new() - } -} - -#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] -#[serde(transparent)] -pub struct StoredEnchantments { - #[var] - pub enchantments: HashMap, -} - -#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] -#[serde(transparent)] -pub struct DyedColor { - pub rgb: i32, -} - -#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] -#[serde(transparent)] -pub struct MapColor { - pub color: i32, -} - -#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] -#[serde(transparent)] -pub struct MapId { - #[var] - pub id: i32, -} - -#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] -#[serde(transparent)] -pub struct MapDecorations { - pub decorations: NbtCompound, -} - -#[derive(Clone, Copy, PartialEq, AzBuf, Debug, Serialize)] -pub enum MapPostProcessing { - Lock, - Scale, -} - -#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] -#[serde(transparent)] -pub struct ChargedProjectiles { - pub items: Vec, -} - -#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] -#[serde(transparent)] -pub struct BundleContents { - pub items: Vec, -} - -#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] -pub struct PotionContents { - #[serde(skip_serializing_if = "is_default")] - pub potion: Option, - #[serde(skip_serializing_if = "is_default")] - pub custom_color: Option, - #[serde(skip_serializing_if = "is_default")] - pub custom_effects: Vec, - #[serde(skip_serializing_if = "is_default")] - pub custom_name: Option, -} - -impl PotionContents { - pub const fn new() -> Self { - PotionContents { - potion: None, - custom_color: None, - custom_effects: vec![], - custom_name: None, - } - } -} -impl Default for PotionContents { - fn default() -> Self { - Self::new() - } -} - -#[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, Debug, Serialize)] -#[serde(transparent)] -pub struct SuspiciousStewEffects { - pub effects: Vec, -} - -#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] -pub struct WritableBookContent { - pub pages: Vec, -} - -#[derive(Clone, PartialEq, AzBuf, Serialize)] -pub struct WrittenBookContent { - #[limit(32)] - pub title: Filterable, - pub author: String, - #[var] - #[serde(skip_serializing_if = "is_default")] - pub generation: i32, - #[serde(skip_serializing_if = "is_default")] - pub pages: Vec>, - #[serde(skip_serializing_if = "is_default")] - pub resolved: bool, -} - -#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] -pub struct Trim { - pub material: TrimMaterial, - pub pattern: TrimPattern, -} - -#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] -#[serde(transparent)] -pub struct DebugStickState { - pub properties: NbtCompound, -} - -#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] -pub struct EntityData { - #[serde(rename = "id")] - pub kind: EntityKind, - #[serde(flatten)] - pub data: NbtCompound, -} - -#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] -#[serde(transparent)] -pub struct BucketEntityData { - pub entity: NbtCompound, -} - -#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] -pub struct BlockEntityData { - #[serde(rename = "id")] - pub kind: EntityKind, - #[serde(flatten)] - pub data: NbtCompound, -} - -#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] -#[serde(untagged)] -pub enum Instrument { - Registry(registry::Instrument), - Holder(Holder), -} - -#[derive(Clone, PartialEq, Debug, AzBuf, Serialize)] -pub struct InstrumentData { - pub sound_event: Holder, - pub use_duration: f32, - pub range: f32, - pub description: FormattedText, -} - -#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] -#[serde(transparent)] -pub struct OminousBottleAmplifier { - #[var] - pub amplifier: i32, -} - -#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] -#[serde(transparent)] -pub struct Recipes { - pub recipes: Vec, -} - -#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] -pub struct LodestoneTracker { - #[serde(skip_serializing_if = "is_default")] - pub target: Option, - #[serde(skip_serializing_if = "is_true")] - pub tracked: bool, -} - -#[derive(Clone, Copy, PartialEq, AzBuf, Debug, Serialize)] -#[serde(rename_all = "snake_case")] -pub enum FireworkExplosionShape { - SmallBall, - LargeBall, - Star, - Creeper, - Burst, -} - -#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] -pub struct FireworkExplosion { - pub shape: FireworkExplosionShape, - #[serde(skip_serializing_if = "is_default")] - pub colors: Vec, - #[serde(skip_serializing_if = "is_default")] - pub fade_colors: Vec, - #[serde(skip_serializing_if = "is_default")] - pub has_trail: bool, - #[serde(skip_serializing_if = "is_default")] - pub has_twinkle: bool, -} - -#[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, -} - -impl Fireworks { - pub const fn new() -> Self { - Fireworks { - flight_duration: 0, - explosions: vec![], - } - } -} -impl Default for Fireworks { - fn default() -> Self { - Self::new() - } -} - -#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] -pub struct GameProfileProperty { - pub name: String, - pub value: String, - #[serde(skip_serializing_if = "is_default")] - pub signature: Option, -} - -#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] -pub struct Profile { - #[serde(skip_serializing_if = "is_default")] - pub name: Option, - #[serde(skip_serializing_if = "is_default")] - #[serde(serialize_with = "azalea_core::codec_utils::uuid")] - pub id: Option, - #[serde(skip_serializing_if = "is_default")] - pub properties: Vec, -} - -#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] -#[serde(transparent)] -pub struct NoteBlockSound { - pub sound: ResourceLocation, -} - -#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] -pub struct BannerPattern { - #[var] - pub pattern: i32, - #[var] - pub color: i32, -} - -#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] -#[serde(transparent)] -pub struct BannerPatterns { - pub patterns: Vec, -} - -#[derive(Clone, Copy, PartialEq, AzBuf, Debug, Serialize)] -#[serde(rename_all = "snake_case")] -pub enum DyeColor { - White, - Orange, - Magenta, - LightBlue, - Yellow, - Lime, - Pink, - Gray, - LightGray, - Cyan, - Purple, - Blue, - Brown, - Green, - Red, - Black, -} - -#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] -#[serde(transparent)] -pub struct BaseColor { - pub color: DyeColor, -} - -#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] -#[serde(transparent)] -pub struct PotDecorations { - pub items: Vec, -} - -#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] -#[serde(transparent)] -pub struct Container { - pub items: Vec, -} - -#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] -#[serde(transparent)] -pub struct BlockState { - pub properties: HashMap, -} - -#[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, - #[var] - pub min_ticks_in_hive: i32, -} - -#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] -#[serde(transparent)] -pub struct Bees { - pub occupants: Vec, -} - -#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] -pub struct Lock { - pub key: String, -} - -#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] -pub struct ContainerLoot { - pub loot_table: NbtCompound, -} - -#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] -#[serde(untagged)] -pub enum JukeboxPlayable { - Referenced(ResourceLocation), - Direct(Holder), -} - -#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] -pub struct JukeboxSongData { - pub sound_event: Holder, - pub description: FormattedText, - pub length_in_seconds: f32, - #[var] - pub comparator_output: i32, -} - -#[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, - #[serde(skip_serializing_if = "is_default")] - pub has_consume_particles: bool, - #[serde(skip_serializing_if = "is_default")] - pub on_consume_effects: Vec, -} -fn is_default_eat_sound(sound: &azalea_registry::Holder) -> bool { - matches!( - sound, - azalea_registry::Holder::Reference(SoundEvent::EntityGenericEat) - ) -} - -impl Consumable { - pub const fn new() -> Self { - Self { - consume_seconds: 1.6, - animation: ItemUseAnimation::Eat, - sound: azalea_registry::Holder::Reference(SoundEvent::EntityGenericEat), - has_consume_particles: true, - on_consume_effects: Vec::new(), - } - } -} -impl Default for Consumable { - fn default() -> Self { - Self::new() - } -} - -#[derive(Clone, Copy, PartialEq, AzBuf, Debug, Default, Serialize)] -#[serde(rename_all = "snake_case")] -pub enum ItemUseAnimation { - #[default] - None, - Eat, - Drink, - Block, - Bow, - Spear, - Crossbow, - Spyglass, - TootHorn, - Brush, -} - -#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] -#[serde(transparent)] -pub struct UseRemainder { - pub convert_into: ItemStack, -} - -#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] -pub struct UseCooldown { - pub seconds: f32, - #[serde(skip_serializing_if = "is_default")] - pub cooldown_group: Option, -} - -impl UseCooldown { - pub const fn new() -> Self { - Self { - seconds: 0., - cooldown_group: None, - } - } -} -impl Default for UseCooldown { - fn default() -> Self { - Self::new() - } -} - -#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] -pub struct Enchantable { - #[var] - pub value: u32, -} - -#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] -pub struct Repairable { - pub items: HolderSet, -} - -#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] -#[serde(transparent)] -pub struct ItemModel { - pub resource_location: ResourceLocation, -} - -#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] -pub struct DamageResistant { - /// In vanilla this only allows tag keys, i.e. it must start with '#' - pub types: ResourceLocation, -} - -#[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, - #[serde(skip_serializing_if = "is_default")] - pub camera_overlay: Option, - #[serde(skip_serializing_if = "is_default")] - pub allowed_entities: Option>, - #[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, -} -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 { - slot: EquipmentSlot::Body, - equip_sound: SoundEvent::ItemArmorEquipGeneric, - asset_id: None, - camera_overlay: None, - allowed_entities: None, - dispensable: true, - swappable: true, - damage_on_hurt: true, - equip_on_interact: false, - can_be_sheared: false, - shearing_sound: SoundEvent::ItemShearsSnip, - } - } -} -impl Default for Equippable { - fn default() -> Self { - Self::new() - } -} - -#[derive(Clone, Copy, Debug, PartialEq, AzBuf, Serialize)] -#[serde(rename_all = "snake_case")] -pub enum EquipmentSlot { - Mainhand, - Offhand, - Feet, - Legs, - Chest, - Head, - Body, - Saddle, -} - -#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] -pub struct Glider; - -#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] -#[serde(transparent)] -pub struct TooltipStyle { - pub resource_location: ResourceLocation, -} - -#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] -pub struct DeathProtection { - pub death_effects: Vec, -} - -#[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, -} -fn is_default_item_damage_per_attack(value: &i32) -> bool { - *value == 1 -} - -impl Weapon { - pub const fn new() -> Self { - Self { - item_damage_per_attack: 1, - disable_blocking_for_seconds: 0., - } - } -} -impl Default for Weapon { - fn default() -> Self { - Self::new() - } -} - -#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] -#[serde(transparent)] -pub struct PotionDurationScale { - pub value: f32, -} - -#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] -#[serde(transparent)] -pub struct VillagerVariant { - pub variant: registry::VillagerKind, -} - -#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] -#[serde(transparent)] -pub struct WolfVariant { - pub variant: registry::WolfVariant, -} - -#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] -#[serde(transparent)] -pub struct WolfCollar { - pub color: DyeColor, -} - -#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] -#[serde(transparent)] -pub struct FoxVariant { - pub variant: registry::FoxVariant, -} - -#[derive(Clone, Copy, PartialEq, AzBuf, Debug, Serialize)] -#[serde(rename_all = "snake_case")] -pub enum SalmonSize { - Small, - Medium, - Large, -} - -#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] -#[serde(transparent)] -pub struct ParrotVariant { - pub variant: registry::ParrotVariant, -} - -#[derive(Clone, Copy, PartialEq, AzBuf, Debug, Serialize)] -#[serde(rename_all = "snake_case")] -pub enum TropicalFishPattern { - Kob, - Sunstreak, - Snooper, - Dasher, - Brinely, - Spotty, - Flopper, - Stripey, - Glitter, - Blockfish, - Betty, - Clayfish, -} - -#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] -#[serde(transparent)] -pub struct TropicalFishBaseColor { - pub color: DyeColor, -} - -#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] -#[serde(transparent)] -pub struct TropicalFishPatternColor { - pub color: DyeColor, -} - -#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] -#[serde(transparent)] -pub struct MooshroomVariant { - pub variant: registry::MooshroomVariant, -} - -#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] -#[serde(transparent)] -pub struct RabbitVariant { - pub variant: registry::RabbitVariant, -} - -#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] -#[serde(transparent)] -pub struct PigVariant { - pub variant: registry::PigVariant, -} - -#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] -#[serde(transparent)] -pub struct FrogVariant { - pub variant: registry::FrogVariant, -} - -#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] -#[serde(transparent)] -pub struct HorseVariant { - pub variant: registry::HorseVariant, -} - -#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] -#[serde(transparent)] -pub struct PaintingVariant { - pub variant: Holder, -} - -#[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, - #[serde(skip_serializing_if = "is_default")] - pub author: Option, -} - -#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] -#[serde(transparent)] -pub struct LlamaVariant { - pub variant: registry::LlamaVariant, -} - -#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] -#[serde(transparent)] -pub struct AxolotlVariant { - pub variant: registry::AxolotlVariant, -} - -#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] -#[serde(transparent)] -pub struct CatVariant { - pub variant: registry::CatVariant, -} - -#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] -#[serde(transparent)] -pub struct CatCollar { - pub color: DyeColor, -} - -#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] -#[serde(transparent)] -pub struct SheepColor { - pub color: DyeColor, -} - -#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] -#[serde(transparent)] -pub struct ShulkerColor { - pub color: DyeColor, -} - -#[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, -} - -impl TooltipDisplay { - pub const fn new() -> Self { - Self { - hide_tooltip: false, - hidden_components: Vec::new(), - } - } -} -impl Default for TooltipDisplay { - fn default() -> Self { - Self::new() - } -} - -#[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, - #[serde(skip_serializing_if = "is_default")] - pub item_damage: ItemDamageFunction, - #[serde(skip_serializing_if = "is_default")] - pub bypassed_by: Option, - #[serde(skip_serializing_if = "is_default")] - pub block_sound: Option>, - #[serde(skip_serializing_if = "is_default")] - pub disabled_sound: Option>, -} -fn is_default_disable_cooldown_scale(value: &f32) -> bool { - *value == 1. -} - -impl BlocksAttacks { - pub fn new() -> Self { - Self { - block_delay_seconds: 0., - disable_cooldown_scale: 1., - damage_reductions: vec![DamageReduction { - horizontal_blocking_angle: 90., - kind: None, - base: 0., - factor: 1., - }], - item_damage: ItemDamageFunction::default(), - bypassed_by: None, - block_sound: None, - disabled_sound: None, - } - } -} -impl Default for BlocksAttacks { - fn default() -> Self { - Self::new() - } -} - -#[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>, - pub base: f32, - pub factor: f32, -} -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, Debug, Serialize)] -#[serde(untagged)] -pub enum ProvidesTrimMaterial { - Referenced(ResourceLocation), - Direct(Holder), -} - -#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] -pub struct DirectTrimMaterial { - pub assets: MaterialAssetGroup, - pub description: FormattedText, -} -#[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, Debug, Serialize)] -pub struct AssetInfo { - pub suffix: String, -} - -#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] -#[serde(transparent)] -pub struct ProvidesBannerPatterns { - pub key: ResourceLocation, -} - -#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] -#[serde(transparent)] -pub struct BreakSound { - pub sound: azalea_registry::Holder, -} - -#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] -#[serde(transparent)] -pub struct WolfSoundVariant { - pub variant: azalea_registry::WolfSoundVariant, -} - -#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] -#[serde(transparent)] -pub struct CowVariant { - pub variant: azalea_registry::CowVariant, -} - -#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] -#[serde(untagged)] -pub enum ChickenVariant { - Referenced(ResourceLocation), - Direct(ChickenVariantData), -} - -#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] -pub struct ChickenVariantData { - pub registry: azalea_registry::ChickenVariant, -} diff --git a/azalea-inventory/src/components/mod.rs b/azalea-inventory/src/components/mod.rs new file mode 100644 index 00000000..5661547a --- /dev/null +++ b/azalea-inventory/src/components/mod.rs @@ -0,0 +1,1467 @@ +mod profile; + +use core::f64; +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::{ + 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, +}; +pub use profile::*; +use serde::{Serialize, ser::SerializeMap}; +use simdnbt::owned::{Nbt, NbtCompound}; +use tracing::trace; + +use crate::{ItemStack, item::consume_effect::ConsumeEffect}; + +pub trait DataComponentTrait: + Send + Sync + Any + Clone + Serialize + Into +{ + const KIND: DataComponentKind; +} + +pub trait EncodableDataComponent: Send + Sync + Any { + fn encode(&self, buf: &mut Vec) -> 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; + // same thing here + fn eq(&self, other: &dyn EncodableDataComponent) -> bool; +} + +impl EncodableDataComponent for T +where + T: DataComponentTrait + Clone + AzaleaWrite + AzaleaRead + PartialEq, +{ + fn encode(&self, buf: &mut Vec) -> 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 { + let cloned = self.clone(); + Box::new(cloned) + } + fn eq(&self, other: &dyn EncodableDataComponent) -> bool { + let other_any: &dyn Any = other; + match other_any.downcast_ref::() { + Some(other) => self == other, + _ => false, + } + } +} + +#[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>, )* + } + impl DataComponentUnion { + /// # Safety + /// + /// `kind` must be the correct value for this union. + pub unsafe fn serialize_entry_as( + &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) } }, )* + } + } + pub fn azalea_read_as( + kind: registry::DataComponentKind, + buf: &mut Cursor<&[u8]>, + ) -> Result { + 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 impl std::io::Write, + ) -> io::Result<()> { + let mut value = Vec::new(); + match kind { + $( DataComponentKind::$x => unsafe { self.$x.encode(&mut value)? }, )* + }; + buf.write_all(&value)?; + + Ok(()) + } + /// # 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) }, )* + } + } + } + $( + 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, +} + +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] +#[serde(transparent)] +pub struct MaxStackSize { + #[var] + pub count: i32, +} + +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] +#[serde(transparent)] +pub struct MaxDamage { + #[var] + pub amount: i32, +} + +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] +#[serde(transparent)] +pub struct Damage { + #[var] + pub amount: i32, +} + +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] +pub struct Unbreakable; + +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] +#[serde(transparent)] +pub struct CustomName { + pub name: FormattedText, +} + +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] +#[serde(transparent)] +pub struct ItemName { + pub name: FormattedText, +} + +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] +#[serde(transparent)] +pub struct Lore { + pub lines: Vec, + // vanilla also has styled_lines here but it doesn't appear to be used for the protocol +} + +#[derive(Clone, Copy, PartialEq, AzBuf, Debug, Serialize)] +#[serde(rename_all = "snake_case")] +pub enum Rarity { + Common, + Uncommon, + Rare, + Epic, +} + +#[derive(Clone, PartialEq, AzBuf, Serialize)] +#[serde(transparent)] +pub struct Enchantments { + #[var] + pub levels: HashMap, +} + +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] +pub enum BlockStateValueMatcher { + Exact { + value: String, + }, + Range { + min: Option, + max: Option, + }, +} + +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] +pub struct BlockStatePropertyMatcher { + pub name: String, + pub value_matcher: BlockStateValueMatcher, +} + +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] +pub struct BlockPredicate { + #[serde(skip_serializing_if = "is_default")] + pub blocks: Option>, + #[serde(skip_serializing_if = "is_default")] + pub properties: Option>, + #[serde(skip_serializing_if = "is_default")] + pub nbt: Option, +} + +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] +#[serde(transparent)] +pub struct AdventureModePredicate { + #[serde(serialize_with = "flatten_array")] + pub predicates: Vec, +} + +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] +#[serde(transparent)] +pub struct CanPlaceOn { + pub predicate: AdventureModePredicate, +} + +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] +#[serde(transparent)] +pub struct CanBreak { + pub predicate: AdventureModePredicate, +} + +#[derive(Clone, Copy, PartialEq, AzBuf, Debug, Serialize)] +#[serde(rename_all = "snake_case")] +pub enum EquipmentSlotGroup { + Any, + Mainhand, + Offhand, + Hand, + Feet, + Legs, + Chest, + Head, + Armor, + Body, +} + +#[derive(Clone, Copy, PartialEq, AzBuf, Debug, Serialize)] +#[serde(rename_all = "snake_case")] +pub enum AttributeModifierOperation { + AddValue, + AddMultipliedBase, + AddMultipliedTotal, +} + +// 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, Debug, Serialize)] +pub struct AttributeModifier { + pub id: ResourceLocation, + pub amount: f64, + pub operation: AttributeModifierOperation, +} + +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] +pub struct AttributeModifiersEntry { + #[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, Debug, Serialize)] +#[serde(transparent)] +pub struct AttributeModifiers { + pub modifiers: Vec, +} + +#[derive(Clone, PartialEq, AzBuf, Debug, Default, Serialize)] +#[serde(rename_all = "snake_case")] +pub enum AttributeModifierDisplay { + #[default] + Default, + Hidden, + Override { + text: FormattedText, + }, +} + +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] +pub struct CustomModelData { + #[serde(skip_serializing_if = "Vec::is_empty")] + pub floats: Vec, + #[serde(skip_serializing_if = "Vec::is_empty")] + pub flags: Vec, + #[serde(skip_serializing_if = "Vec::is_empty")] + pub strings: Vec, + #[serde(skip_serializing_if = "Vec::is_empty")] + pub colors: Vec, +} + +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] +#[serde(transparent)] +pub struct RepairCost { + #[var] + pub cost: u32, +} + +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] +pub struct CreativeSlotLock; + +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] +#[serde(transparent)] +pub struct EnchantmentGlintOverride { + pub show_glint: bool, +} + +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] +pub struct IntangibleProjectile; + +#[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>, +} +impl MobEffectDetails { + pub const fn new() -> Self { + MobEffectDetails { + amplifier: 0, + duration: 0, + ambient: false, + show_particles: true, + show_icon: true, + hidden_effect: None, + } + } +} +impl Default for MobEffectDetails { + fn default() -> Self { + Self::new() + } +} + +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] +pub struct MobEffectInstance { + pub id: MobEffect, + #[serde(flatten)] + pub details: MobEffectDetails, +} + +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] +pub struct PossibleEffect { + pub effect: MobEffectInstance, + pub probability: f32, +} + +#[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 Food { + pub const fn new() -> Self { + Food { + nutrition: 0, + saturation: 0., + can_always_eat: false, + } + } +} + +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] +pub struct ToolRule { + pub blocks: HolderSet, + #[serde(skip_serializing_if = "is_default")] + pub speed: Option, + #[serde(skip_serializing_if = "is_default")] + pub correct_for_drops: Option, +} +impl ToolRule { + pub const fn new() -> Self { + ToolRule { + blocks: HolderSet::Direct { contents: vec![] }, + speed: None, + correct_for_drops: None, + } + } +} +impl Default for ToolRule { + fn default() -> Self { + Self::new() + } +} + +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] +pub struct Tool { + #[serde(serialize_with = "flatten_array")] + pub rules: Vec, + #[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 Tool { + pub const fn new() -> Self { + Tool { + rules: vec![], + default_mining_speed: 1., + damage_per_block: 1, + can_destroy_blocks_in_creative: true, + } + } +} +impl Default for Tool { + fn default() -> Self { + Self::new() + } +} + +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] +#[serde(transparent)] +pub struct StoredEnchantments { + #[var] + pub enchantments: HashMap, +} + +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] +#[serde(transparent)] +pub struct DyedColor { + pub rgb: i32, +} + +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] +#[serde(transparent)] +pub struct MapColor { + pub color: i32, +} + +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] +#[serde(transparent)] +pub struct MapId { + #[var] + pub id: i32, +} + +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] +#[serde(transparent)] +pub struct MapDecorations { + pub decorations: NbtCompound, +} + +#[derive(Clone, Copy, PartialEq, AzBuf, Debug, Serialize)] +pub enum MapPostProcessing { + Lock, + Scale, +} + +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] +#[serde(transparent)] +pub struct ChargedProjectiles { + pub items: Vec, +} + +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] +#[serde(transparent)] +pub struct BundleContents { + pub items: Vec, +} + +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] +pub struct PotionContents { + #[serde(skip_serializing_if = "is_default")] + pub potion: Option, + #[serde(skip_serializing_if = "is_default")] + pub custom_color: Option, + #[serde(skip_serializing_if = "is_default")] + pub custom_effects: Vec, + #[serde(skip_serializing_if = "is_default")] + pub custom_name: Option, +} + +impl PotionContents { + pub const fn new() -> Self { + PotionContents { + potion: None, + custom_color: None, + custom_effects: vec![], + custom_name: None, + } + } +} +impl Default for PotionContents { + fn default() -> Self { + Self::new() + } +} + +#[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, Debug, Serialize)] +#[serde(transparent)] +pub struct SuspiciousStewEffects { + pub effects: Vec, +} + +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] +pub struct WritableBookContent { + pub pages: Vec, +} + +#[derive(Clone, PartialEq, AzBuf, Serialize)] +pub struct WrittenBookContent { + #[limit(32)] + pub title: Filterable, + pub author: String, + #[var] + #[serde(skip_serializing_if = "is_default")] + pub generation: i32, + #[serde(skip_serializing_if = "is_default")] + pub pages: Vec>, + #[serde(skip_serializing_if = "is_default")] + pub resolved: bool, +} + +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] +pub struct Trim { + pub material: TrimMaterial, + pub pattern: TrimPattern, +} + +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] +#[serde(transparent)] +pub struct DebugStickState { + pub properties: NbtCompound, +} + +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] +pub struct EntityData { + #[serde(rename = "id")] + pub kind: EntityKind, + #[serde(flatten)] + pub data: NbtCompound, +} + +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] +#[serde(transparent)] +pub struct BucketEntityData { + pub entity: NbtCompound, +} + +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] +pub struct BlockEntityData { + #[serde(rename = "id")] + pub kind: EntityKind, + #[serde(flatten)] + pub data: NbtCompound, +} + +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] +#[serde(untagged)] +pub enum Instrument { + Registry(registry::Instrument), + Holder(Holder), +} + +#[derive(Clone, PartialEq, Debug, AzBuf, Serialize)] +pub struct InstrumentData { + pub sound_event: Holder, + pub use_duration: f32, + pub range: f32, + pub description: FormattedText, +} + +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] +#[serde(transparent)] +pub struct OminousBottleAmplifier { + #[var] + pub amplifier: i32, +} + +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] +#[serde(transparent)] +pub struct Recipes { + pub recipes: Vec, +} + +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] +pub struct LodestoneTracker { + #[serde(skip_serializing_if = "is_default")] + pub target: Option, + #[serde(skip_serializing_if = "is_true")] + pub tracked: bool, +} + +#[derive(Clone, Copy, PartialEq, AzBuf, Debug, Serialize)] +#[serde(rename_all = "snake_case")] +pub enum FireworkExplosionShape { + SmallBall, + LargeBall, + Star, + Creeper, + Burst, +} + +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] +pub struct FireworkExplosion { + pub shape: FireworkExplosionShape, + #[serde(skip_serializing_if = "is_default")] + pub colors: Vec, + #[serde(skip_serializing_if = "is_default")] + pub fade_colors: Vec, + #[serde(skip_serializing_if = "is_default")] + pub has_trail: bool, + #[serde(skip_serializing_if = "is_default")] + pub has_twinkle: bool, +} + +#[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, +} + +impl Fireworks { + pub const fn new() -> Self { + Fireworks { + flight_duration: 0, + explosions: vec![], + } + } +} +impl Default for Fireworks { + fn default() -> Self { + Self::new() + } +} + +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] +#[serde(transparent)] +pub struct NoteBlockSound { + pub sound: ResourceLocation, +} + +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] +pub struct BannerPattern { + #[var] + pub pattern: i32, + #[var] + pub color: i32, +} + +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] +#[serde(transparent)] +pub struct BannerPatterns { + pub patterns: Vec, +} + +#[derive(Clone, Copy, PartialEq, AzBuf, Debug, Serialize)] +#[serde(rename_all = "snake_case")] +pub enum DyeColor { + White, + Orange, + Magenta, + LightBlue, + Yellow, + Lime, + Pink, + Gray, + LightGray, + Cyan, + Purple, + Blue, + Brown, + Green, + Red, + Black, +} + +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] +#[serde(transparent)] +pub struct BaseColor { + pub color: DyeColor, +} + +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] +#[serde(transparent)] +pub struct PotDecorations { + pub items: Vec, +} + +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] +#[serde(transparent)] +pub struct Container { + pub items: Vec, +} + +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] +#[serde(transparent)] +pub struct BlockState { + pub properties: HashMap, +} + +#[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, + #[var] + pub min_ticks_in_hive: i32, +} + +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] +#[serde(transparent)] +pub struct Bees { + pub occupants: Vec, +} + +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] +pub struct Lock { + pub key: String, +} + +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] +pub struct ContainerLoot { + pub loot_table: NbtCompound, +} + +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] +#[serde(untagged)] +pub enum JukeboxPlayable { + Referenced(ResourceLocation), + Direct(Holder), +} + +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] +pub struct JukeboxSongData { + pub sound_event: Holder, + pub description: FormattedText, + pub length_in_seconds: f32, + #[var] + pub comparator_output: i32, +} + +#[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, + #[serde(skip_serializing_if = "is_default")] + pub has_consume_particles: bool, + #[serde(skip_serializing_if = "is_default")] + pub on_consume_effects: Vec, +} +fn is_default_eat_sound(sound: &azalea_registry::Holder) -> bool { + matches!( + sound, + azalea_registry::Holder::Reference(SoundEvent::EntityGenericEat) + ) +} + +impl Consumable { + pub const fn new() -> Self { + Self { + consume_seconds: 1.6, + animation: ItemUseAnimation::Eat, + sound: azalea_registry::Holder::Reference(SoundEvent::EntityGenericEat), + has_consume_particles: true, + on_consume_effects: Vec::new(), + } + } +} +impl Default for Consumable { + fn default() -> Self { + Self::new() + } +} + +#[derive(Clone, Copy, PartialEq, AzBuf, Debug, Default, Serialize)] +#[serde(rename_all = "snake_case")] +pub enum ItemUseAnimation { + #[default] + None, + Eat, + Drink, + Block, + Bow, + Spear, + Crossbow, + Spyglass, + TootHorn, + Brush, +} + +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] +#[serde(transparent)] +pub struct UseRemainder { + pub convert_into: ItemStack, +} + +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] +pub struct UseCooldown { + pub seconds: f32, + #[serde(skip_serializing_if = "is_default")] + pub cooldown_group: Option, +} + +impl UseCooldown { + pub const fn new() -> Self { + Self { + seconds: 0., + cooldown_group: None, + } + } +} +impl Default for UseCooldown { + fn default() -> Self { + Self::new() + } +} + +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] +pub struct Enchantable { + #[var] + pub value: u32, +} + +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] +pub struct Repairable { + pub items: HolderSet, +} + +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] +#[serde(transparent)] +pub struct ItemModel { + pub resource_location: ResourceLocation, +} + +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] +pub struct DamageResistant { + /// In vanilla this only allows tag keys, i.e. it must start with '#' + pub types: ResourceLocation, +} + +#[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, + #[serde(skip_serializing_if = "is_default")] + pub camera_overlay: Option, + #[serde(skip_serializing_if = "is_default")] + pub allowed_entities: Option>, + #[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, +} +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 { + slot: EquipmentSlot::Body, + equip_sound: SoundEvent::ItemArmorEquipGeneric, + asset_id: None, + camera_overlay: None, + allowed_entities: None, + dispensable: true, + swappable: true, + damage_on_hurt: true, + equip_on_interact: false, + can_be_sheared: false, + shearing_sound: SoundEvent::ItemShearsSnip, + } + } +} +impl Default for Equippable { + fn default() -> Self { + Self::new() + } +} + +#[derive(Clone, Copy, Debug, PartialEq, AzBuf, Serialize)] +#[serde(rename_all = "snake_case")] +pub enum EquipmentSlot { + Mainhand, + Offhand, + Feet, + Legs, + Chest, + Head, + Body, + Saddle, +} + +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] +pub struct Glider; + +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] +#[serde(transparent)] +pub struct TooltipStyle { + pub resource_location: ResourceLocation, +} + +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] +pub struct DeathProtection { + pub death_effects: Vec, +} + +#[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, +} +fn is_default_item_damage_per_attack(value: &i32) -> bool { + *value == 1 +} + +impl Weapon { + pub const fn new() -> Self { + Self { + item_damage_per_attack: 1, + disable_blocking_for_seconds: 0., + } + } +} +impl Default for Weapon { + fn default() -> Self { + Self::new() + } +} + +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] +#[serde(transparent)] +pub struct PotionDurationScale { + pub value: f32, +} + +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] +#[serde(transparent)] +pub struct VillagerVariant { + pub variant: registry::VillagerKind, +} + +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] +#[serde(transparent)] +pub struct WolfVariant { + pub variant: registry::WolfVariant, +} + +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] +#[serde(transparent)] +pub struct WolfCollar { + pub color: DyeColor, +} + +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] +#[serde(transparent)] +pub struct FoxVariant { + pub variant: registry::FoxVariant, +} + +#[derive(Clone, Copy, PartialEq, AzBuf, Debug, Serialize)] +#[serde(rename_all = "snake_case")] +pub enum SalmonSize { + Small, + Medium, + Large, +} + +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] +#[serde(transparent)] +pub struct ParrotVariant { + pub variant: registry::ParrotVariant, +} + +#[derive(Clone, Copy, PartialEq, AzBuf, Debug, Serialize)] +#[serde(rename_all = "snake_case")] +pub enum TropicalFishPattern { + Kob, + Sunstreak, + Snooper, + Dasher, + Brinely, + Spotty, + Flopper, + Stripey, + Glitter, + Blockfish, + Betty, + Clayfish, +} + +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] +#[serde(transparent)] +pub struct TropicalFishBaseColor { + pub color: DyeColor, +} + +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] +#[serde(transparent)] +pub struct TropicalFishPatternColor { + pub color: DyeColor, +} + +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] +#[serde(transparent)] +pub struct MooshroomVariant { + pub variant: registry::MooshroomVariant, +} + +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] +#[serde(transparent)] +pub struct RabbitVariant { + pub variant: registry::RabbitVariant, +} + +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] +#[serde(transparent)] +pub struct PigVariant { + pub variant: registry::PigVariant, +} + +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] +#[serde(transparent)] +pub struct FrogVariant { + pub variant: registry::FrogVariant, +} + +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] +#[serde(transparent)] +pub struct HorseVariant { + pub variant: registry::HorseVariant, +} + +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] +#[serde(transparent)] +pub struct PaintingVariant { + pub variant: Holder, +} + +#[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, + #[serde(skip_serializing_if = "is_default")] + pub author: Option, +} + +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] +#[serde(transparent)] +pub struct LlamaVariant { + pub variant: registry::LlamaVariant, +} + +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] +#[serde(transparent)] +pub struct AxolotlVariant { + pub variant: registry::AxolotlVariant, +} + +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] +#[serde(transparent)] +pub struct CatVariant { + pub variant: registry::CatVariant, +} + +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] +#[serde(transparent)] +pub struct CatCollar { + pub color: DyeColor, +} + +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] +#[serde(transparent)] +pub struct SheepColor { + pub color: DyeColor, +} + +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] +#[serde(transparent)] +pub struct ShulkerColor { + pub color: DyeColor, +} + +#[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, +} + +impl TooltipDisplay { + pub const fn new() -> Self { + Self { + hide_tooltip: false, + hidden_components: Vec::new(), + } + } +} +impl Default for TooltipDisplay { + fn default() -> Self { + Self::new() + } +} + +#[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, + #[serde(skip_serializing_if = "is_default")] + pub item_damage: ItemDamageFunction, + #[serde(skip_serializing_if = "is_default")] + pub bypassed_by: Option, + #[serde(skip_serializing_if = "is_default")] + pub block_sound: Option>, + #[serde(skip_serializing_if = "is_default")] + pub disabled_sound: Option>, +} +fn is_default_disable_cooldown_scale(value: &f32) -> bool { + *value == 1. +} + +impl BlocksAttacks { + pub fn new() -> Self { + Self { + block_delay_seconds: 0., + disable_cooldown_scale: 1., + damage_reductions: vec![DamageReduction { + horizontal_blocking_angle: 90., + kind: None, + base: 0., + factor: 1., + }], + item_damage: ItemDamageFunction::default(), + bypassed_by: None, + block_sound: None, + disabled_sound: None, + } + } +} +impl Default for BlocksAttacks { + fn default() -> Self { + Self::new() + } +} + +#[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>, + pub base: f32, + pub factor: f32, +} +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, Debug, Serialize)] +#[serde(untagged)] +pub enum ProvidesTrimMaterial { + Referenced(ResourceLocation), + Direct(Holder), +} + +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] +pub struct DirectTrimMaterial { + pub assets: MaterialAssetGroup, + pub description: FormattedText, +} +#[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, Debug, Serialize)] +pub struct AssetInfo { + pub suffix: String, +} + +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] +#[serde(transparent)] +pub struct ProvidesBannerPatterns { + pub key: ResourceLocation, +} + +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] +#[serde(transparent)] +pub struct BreakSound { + pub sound: azalea_registry::Holder, +} + +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] +#[serde(transparent)] +pub struct WolfSoundVariant { + pub variant: azalea_registry::WolfSoundVariant, +} + +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] +#[serde(transparent)] +pub struct CowVariant { + pub variant: azalea_registry::CowVariant, +} + +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] +#[serde(untagged)] +pub enum ChickenVariant { + Referenced(ResourceLocation), + Direct(ChickenVariantData), +} + +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] +pub struct ChickenVariantData { + pub registry: azalea_registry::ChickenVariant, +} diff --git a/azalea-inventory/src/components/profile.rs b/azalea-inventory/src/components/profile.rs new file mode 100644 index 00000000..9966bc8f --- /dev/null +++ b/azalea-inventory/src/components/profile.rs @@ -0,0 +1,73 @@ +use azalea_auth::game_profile::{ + GameProfile, GameProfileProperties, SerializableProfileProperties, +}; +use azalea_buf::AzBuf; +use azalea_core::{codec_utils::*, resource_location::ResourceLocation}; +use serde::{Serialize, Serializer}; +use uuid::Uuid; + +#[derive(Clone, Debug, AzBuf, Default, PartialEq, Serialize)] +#[doc(alias = "ResolvableProfile")] +pub struct Profile { + #[serde(flatten)] + pub unpack: Box, + #[serde(flatten)] + pub skin_patch: Box, +} + +#[derive(Clone, Debug, AzBuf, PartialEq, Serialize)] +#[serde(untagged)] +pub enum PartialOrFullProfile { + Partial(PartialProfile), + Full(GameProfile), +} +impl Default for PartialOrFullProfile { + fn default() -> Self { + Self::Partial(PartialProfile::default()) + } +} + +#[derive(Clone, Debug, AzBuf, Default, PartialEq, Serialize)] +pub struct PartialProfile { + #[limit(16)] + #[serde(skip_serializing_if = "is_default")] + pub name: Option, + #[serde(skip_serializing_if = "is_default")] + pub id: Option, + #[serde(serialize_with = "serialize_properties")] + pub properties: GameProfileProperties, +} +fn serialize_properties( + properties: &GameProfileProperties, + serializer: S, +) -> Result { + let serializable = SerializableProfileProperties::from(properties.clone()); + serializable.serialize(serializer) +} + +#[derive(Clone, Debug, AzBuf, Default, PartialEq, Serialize)] +pub struct PlayerSkinPatch { + #[serde(rename = "texture")] + #[serde(skip_serializing_if = "is_default")] + pub body: Option, + #[serde(skip_serializing_if = "is_default")] + pub cape: Option, + #[serde(skip_serializing_if = "is_default")] + pub elytra: Option, + #[serde(skip_serializing_if = "is_default")] + pub model: Option, +} + +#[derive(Clone, Debug, Copy, AzBuf, Default, PartialEq, Serialize)] +#[serde(rename_all = "snake_case")] +pub enum PlayerModelType { + #[default] + Wide, + Slim, +} + +#[derive(Clone, Debug, AzBuf, PartialEq, Serialize)] +#[serde(transparent)] +pub struct ResourceTexture { + pub id: ResourceLocation, +} diff --git a/codegen/lib/code/data_components.py b/codegen/lib/code/data_components.py index b1444860..89796a91 100644 --- a/codegen/lib/code/data_components.py +++ b/codegen/lib/code/data_components.py @@ -4,7 +4,7 @@ import lib.extract import lib.utils -DATA_COMPONENTS_DIR = "azalea-inventory/src/components.rs" +DATA_COMPONENTS_DIR = "azalea-inventory/src/components/mod.rs" DEFAULT_DATA_COMPONENTS_DIR = "azalea-inventory/src/default_components/generated.rs" @@ -322,7 +322,7 @@ use crate::{ entity_id = python_value["id"] elif isinstance(python_value, str): entity_id = python_value - + if entity_id and entity_id.startswith("minecraft:"): entity_name = entity_id[10:] # Remove "minecraft:" prefix entity_name_camel = lib.utils.to_camel_case(entity_name) @@ -512,7 +512,7 @@ use crate::{ # Special handling for EntityData to use EntityData structure # Keep rust_value as "value" so it gets processed correctly field_type = "EntityKind" - + def transform_value_fn(rust_value: str): return f"{component_struct_name} {{ kind: {rust_value}, data: NbtCompound::new() }}" @@ -623,7 +623,7 @@ use crate::{ def get_enum_and_struct_fields(): """ Returns a map like map like `{ "MaxStackSize": { "count": i32 }, "Rarity": [ "common", ... ], ... }` - with an entry for each struct in components.rs. + with an entry for each struct in components/mod.rs. """ with open(DATA_COMPONENTS_DIR, "r") as f: diff --git a/codegen/lib/code/entity.py b/codegen/lib/code/entity.py index 1c2a0d48..18a7a04b 100644 --- a/codegen/lib/code/entity.py +++ b/codegen/lib/code/entity.py @@ -113,7 +113,7 @@ use azalea_core::{ direction::Direction, position::{BlockPos, Vec3f32}, }; -use azalea_inventory::ItemStack; +use azalea_inventory::{ItemStack, components}; use azalea_registry::DataRegistry; use bevy_ecs::{bundle::Bundle, component::Component}; use derive_more::{Deref, DerefMut}; @@ -122,8 +122,7 @@ use uuid::Uuid; use super::{ ArmadilloStateKind, CopperGolemStateKind, EntityDataItem, EntityDataValue, OptionalUnsignedInt, - Pose, Quaternion, ResolvableProfile, Rotations, SnifferStateKind, VillagerData, - WeatheringCopperStateKind, + Pose, Quaternion, Rotations, SnifferStateKind, VillagerData, WeatheringCopperStateKind, }; use crate::particle::Particle; -- cgit v1.2.3