diff options
| author | mat <27899617+mat-1@users.noreply.github.com> | 2025-12-09 13:29:59 -0600 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-12-09 13:29:59 -0600 |
| commit | 26d619c9a329087a23d6577ee74bd764f50cd773 (patch) | |
| tree | 8020fe902257764a23a445c6ed9987ea4848189d /azalea-inventory/src | |
| parent | 84cd261118c9d1e3145d4d1751c0d22098cd8cd8 (diff) | |
| download | azalea-drasl-26d619c9a329087a23d6577ee74bd764f50cd773.tar.xz | |
Enchantments (#286)
* start implementing enchants
* store parsed registries
* more work on enchants
* implement deserializer for some entity effects
* mostly working definitions for enchants
* fix tests
* detect equipment changes
* fix errors
* update changelog
* fix some imports
* remove outdated todo
* add basic test for enchants applying attributes
* use git simdnbt
Diffstat (limited to 'azalea-inventory/src')
| -rw-r--r-- | azalea-inventory/src/components/mod.rs | 76 | ||||
| -rw-r--r-- | azalea-inventory/src/default_components/generated.rs | 1 | ||||
| -rw-r--r-- | azalea-inventory/src/lib.rs | 20 | ||||
| -rw-r--r-- | azalea-inventory/src/slot.rs | 17 |
4 files changed, 84 insertions, 30 deletions
diff --git a/azalea-inventory/src/components/mod.rs b/azalea-inventory/src/components/mod.rs index 9c27db8c..87d4256b 100644 --- a/azalea-inventory/src/components/mod.rs +++ b/azalea-inventory/src/components/mod.rs @@ -4,6 +4,7 @@ use core::f64; use std::{ any::Any, collections::HashMap, + fmt::{self, Display}, io::{self, Cursor}, mem::ManuallyDrop, }; @@ -11,12 +12,13 @@ use std::{ use azalea_buf::{AzBuf, AzaleaRead, AzaleaWrite, BufReadError}; use azalea_chat::FormattedText; use azalea_core::{ + attribute_modifier_operation::AttributeModifierOperation, checksum::{Checksum, get_checksum}, codec_utils::*, filterable::Filterable, identifier::Identifier, position::GlobalPos, - registry_holder::{DamageTypeElement, RegistryHolder}, + registry_holder::{RegistryHolder, dimension_type::DamageTypeElement}, sound::CustomSound, }; use azalea_registry::{ @@ -115,7 +117,7 @@ macro_rules! define_data_components { } } pub fn azalea_read_as( - kind: registry::DataComponentKind, + kind: DataComponentKind, buf: &mut Cursor<&[u8]>, ) -> Result<Self, BufReadError> { trace!("Reading data component {kind}"); @@ -131,7 +133,7 @@ macro_rules! define_data_components { /// `kind` must be the correct value for this union. pub unsafe fn azalea_write_as( &self, - kind: registry::DataComponentKind, + kind: DataComponentKind, buf: &mut impl std::io::Write, ) -> io::Result<()> { let mut value = Vec::new(); @@ -147,7 +149,7 @@ macro_rules! define_data_components { /// `kind` must be the correct value for this union. pub unsafe fn clone_as( &self, - kind: registry::DataComponentKind, + kind: DataComponentKind, ) -> Self { match kind { $( DataComponentKind::$x => { @@ -161,7 +163,7 @@ macro_rules! define_data_components { pub unsafe fn eq_as( &self, other: &Self, - kind: registry::DataComponentKind, + kind: DataComponentKind, ) -> bool { match kind { $( DataComponentKind::$x => unsafe { self.$x.eq(&other.$x) }, )* @@ -353,11 +355,12 @@ pub enum Rarity { Epic, } -#[derive(Clone, PartialEq, AzBuf, Serialize)] +#[derive(Clone, PartialEq, AzBuf, Serialize, Default)] #[serde(transparent)] pub struct Enchantments { + /// Enchantment levels here are 1-indexed, level 0 does not exist. #[var] - pub levels: HashMap<Enchantment, u32>, + pub levels: HashMap<Enchantment, i32>, } #[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] @@ -421,14 +424,6 @@ pub enum EquipmentSlotGroup { 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) @@ -450,7 +445,7 @@ pub struct AttributeModifiersEntry { pub display: AttributeModifierDisplay, } -#[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] +#[derive(Clone, PartialEq, AzBuf, Debug, Serialize, Default)] #[serde(transparent)] pub struct AttributeModifiers { pub modifiers: Vec<AttributeModifiersEntry>, @@ -1108,7 +1103,8 @@ impl Default for Equippable { } } -#[derive(Clone, Copy, Debug, PartialEq, AzBuf, Serialize)] +/// An enum that represents inventory slots that can hold items. +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, AzBuf, Serialize)] #[serde(rename_all = "snake_case")] pub enum EquipmentSlot { Mainhand, @@ -1117,9 +1113,55 @@ pub enum EquipmentSlot { Legs, Chest, Head, + /// This is for animal armor, use [`Self::Chest`] for the chestplate slot. Body, Saddle, } +impl EquipmentSlot { + #[must_use] + pub fn from_byte(byte: u8) -> Option<Self> { + let value = match byte { + 0 => Self::Mainhand, + 1 => Self::Offhand, + 2 => Self::Feet, + 3 => Self::Legs, + 4 => Self::Chest, + 5 => Self::Head, + _ => return None, + }; + Some(value) + } + pub fn values() -> [Self; 8] { + [ + Self::Mainhand, + Self::Offhand, + Self::Feet, + Self::Legs, + Self::Chest, + Self::Head, + Self::Body, + Self::Saddle, + ] + } + /// Get the display name for the equipment slot, like "mainhand". + pub fn name(self) -> &'static str { + match self { + Self::Mainhand => "mainhand", + Self::Offhand => "offhand", + Self::Feet => "feet", + Self::Legs => "legs", + Self::Chest => "chest", + Self::Head => "head", + Self::Body => "body", + Self::Saddle => "saddle", + } + } +} +impl Display for EquipmentSlot { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{}", self.name()) + } +} #[derive(Clone, PartialEq, AzBuf, Debug, Serialize)] pub struct Glider; diff --git a/azalea-inventory/src/default_components/generated.rs b/azalea-inventory/src/default_components/generated.rs index 7daa545e..11f8d160 100644 --- a/azalea-inventory/src/default_components/generated.rs +++ b/azalea-inventory/src/default_components/generated.rs @@ -6,6 +6,7 @@ use std::collections::HashMap; use azalea_chat::translatable_component::TranslatableComponent; +use azalea_core::attribute_modifier_operation::AttributeModifierOperation; use azalea_registry::{ Attribute, Block, DataRegistry, EntityKind, HolderSet, Item, MobEffect, SoundEvent, }; diff --git a/azalea-inventory/src/lib.rs b/azalea-inventory/src/lib.rs index 4a15ea31..87cd61e4 100644 --- a/azalea-inventory/src/lib.rs +++ b/azalea-inventory/src/lib.rs @@ -49,10 +49,16 @@ impl Menu { /// /// Will panic if the menu isn't `Menu::Player`. pub fn as_player(&self) -> &Player { + self.try_as_player() + .expect("Called `Menu::as_player` on a menu that wasn't `Player`.") + } + /// Get the [`Player`] from this [`Menu`], or returns `None` if the menu + /// isn't a player menu. + pub fn try_as_player(&self) -> Option<&Player> { if let Menu::Player(player) = &self { - player + Some(player) } else { - unreachable!("Called `Menu::as_player` on a menu that wasn't `Player`.") + None } } @@ -63,10 +69,16 @@ impl Menu { /// /// Will panic if the menu isn't `Menu::Player`. pub fn as_player_mut(&mut self) -> &mut Player { + self.try_as_player_mut() + .expect("Called `Menu::as_player_mut` on a menu that wasn't `Player`.") + } + /// Same as [`Menu::try_as_player`], but returns a mutable reference to the + /// [`Player`]. + pub fn try_as_player_mut(&mut self) -> Option<&mut Player> { if let Menu::Player(player) = self { - player + Some(player) } else { - unreachable!("Called `Menu::as_player_mut` on a menu that wasn't `Player`.") + None } } } diff --git a/azalea-inventory/src/slot.rs b/azalea-inventory/src/slot.rs index d19ab177..c3134214 100644 --- a/azalea-inventory/src/slot.rs +++ b/azalea-inventory/src/slot.rs @@ -1,7 +1,7 @@ use std::{ any::Any, borrow::Cow, - fmt, + fmt::{self, Debug}, io::{self, Cursor, Write}, }; @@ -79,11 +79,10 @@ impl ItemStack { } } - /// Get the `kind` of the item in this slot, or - /// [`azalea_registry::Item::Air`] - pub fn kind(&self) -> azalea_registry::Item { + /// Get the `kind` of the item in this slot, or [`Item::Air`] + pub fn kind(&self) -> Item { match self { - ItemStack::Empty => azalea_registry::Item::Air, + ItemStack::Empty => Item::Air, ItemStack::Present(i) => i.kind, } } @@ -152,7 +151,7 @@ impl Serialize for ItemStack { #[derive(Debug, Clone, PartialEq, Serialize)] pub struct ItemStackData { #[serde(rename = "id")] - pub kind: azalea_registry::Item, + pub kind: Item, /// The amount of the item in this slot. /// /// The count can be zero or negative, but this is rare. @@ -184,7 +183,7 @@ impl ItemStackData { /// Check if the count of the item is <= 0 or if the item is air. pub fn is_empty(&self) -> bool { - self.count <= 0 || self.kind == azalea_registry::Item::Air + self.count <= 0 || self.kind == Item::Air } /// Whether this item is the same as another item, ignoring the count. @@ -222,7 +221,7 @@ impl AzaleaRead for ItemStack { if count <= 0 { Ok(ItemStack::Empty) } else { - let kind = azalea_registry::Item::azalea_read(buf)?; + let kind = Item::azalea_read(buf)?; let component_patch = DataComponentPatch::azalea_read(buf)?; Ok(ItemStack::Present(ItemStackData { count, @@ -449,7 +448,7 @@ impl Clone for DataComponentPatch { DataComponentPatch { components } } } -impl fmt::Debug for DataComponentPatch { +impl Debug for DataComponentPatch { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_set().entries(self.components.keys()).finish() } |
