azalea_entity/
data.rs

1//! Define some types needed for entity metadata.
2
3// TODO: this is here because of a bug in enum_as_inner. remove when it's fixed
4#![allow(clippy::double_parens)]
5
6use std::io::{self, Cursor, Write};
7
8use azalea_buf::{AzBuf, AzBufVar, BufReadError};
9use azalea_chat::FormattedText;
10use azalea_core::{
11    direction::Direction,
12    position::{BlockPos, GlobalPos, Vec3f32},
13};
14use azalea_inventory::{ItemStack, components};
15use azalea_registry::builtin::{VillagerKind, VillagerProfession};
16use derive_more::Deref;
17use enum_as_inner::EnumAsInner;
18use uuid::Uuid;
19
20use crate::particle::Particle;
21
22#[derive(Clone, Debug, Deref, PartialEq)]
23pub struct EntityMetadataItems(pub Vec<EntityDataItem>);
24
25#[derive(Clone, Debug, PartialEq)]
26pub struct EntityDataItem {
27    // we can't identify what the index is for here because we don't know the
28    // entity type
29    pub index: u8,
30    pub value: EntityDataValue,
31}
32
33impl AzBuf for EntityMetadataItems {
34    fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
35        let mut metadata = Vec::new();
36        loop {
37            let id = u8::azalea_read(buf)?;
38            if id == 0xff {
39                break;
40            }
41            let value = EntityDataValue::azalea_read(buf)?;
42            metadata.push(EntityDataItem { index: id, value });
43        }
44        Ok(EntityMetadataItems(metadata))
45    }
46    fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> {
47        for item in &self.0 {
48            item.index.azalea_write(buf)?;
49            item.value.azalea_write(buf)?;
50        }
51        0xffu8.azalea_write(buf)?;
52        Ok(())
53    }
54}
55
56// Note: This enum is partially generated and parsed by
57// codegen/lib/code/entity.py
58#[derive(AzBuf, Clone, Debug, EnumAsInner, PartialEq)]
59pub enum EntityDataValue {
60    Byte(u8),
61    Int(#[var] i32),
62    Long(#[var] i64),
63    Float(f32),
64    String(Box<str>),
65    FormattedText(Box<FormattedText>),
66    OptionalFormattedText(Option<Box<FormattedText>>),
67    ItemStack(ItemStack),
68    Boolean(bool),
69    Rotations(Rotations),
70    BlockPos(BlockPos),
71    OptionalBlockPos(Option<BlockPos>),
72    Direction(Direction),
73    OptionalLivingEntityReference(Option<Uuid>),
74    BlockState(azalea_block::BlockState),
75    /// If this is air, that means it's absent,
76    OptionalBlockState(azalea_block::BlockState),
77    Particle(Particle),
78    Particles(Box<[Particle]>),
79    VillagerData(VillagerData),
80    // 0 for absent; 1 + actual value otherwise. Used for entity IDs.
81    OptionalUnsignedInt(OptionalUnsignedInt),
82    Pose(Pose),
83    CatVariant(azalea_registry::data::CatVariant),
84    CowVariant(azalea_registry::data::CowVariant),
85    WolfVariant(azalea_registry::data::WolfVariant),
86    WolfSoundVariant(azalea_registry::data::WolfSoundVariant),
87    FrogVariant(azalea_registry::data::FrogVariant),
88    PigVariant(azalea_registry::data::PigVariant),
89    ChickenVariant(azalea_registry::data::ChickenVariant),
90    ZombieNautilusVariant(azalea_registry::data::ZombieNautilusVariant),
91    OptionalGlobalPos(Option<Box<GlobalPos>>),
92    PaintingVariant(azalea_registry::data::PaintingVariant),
93    SnifferState(SnifferStateKind),
94    ArmadilloState(ArmadilloStateKind),
95    CopperGolemState(CopperGolemStateKind),
96    WeatheringCopperState(WeatheringCopperStateKind),
97    Vector3(Vec3f32),
98    Quaternion(Quaternion),
99    ResolvableProfile(components::Profile),
100    HumanoidArm(HumanoidArm),
101}
102
103const _: () = assert!(size_of::<EntityDataValue>() == 24);
104
105#[derive(Clone, Debug, PartialEq)]
106pub struct OptionalUnsignedInt(pub Option<u32>);
107
108#[derive(AzBuf, Clone, Debug, PartialEq)]
109pub struct Quaternion {
110    pub x: f32,
111    pub y: f32,
112    pub z: f32,
113    pub w: f32,
114}
115
116// mojang just calls this ArmadilloState but i added "Kind" since otherwise it
117// collides with a name in metadata.rs
118#[derive(AzBuf, Clone, Copy, Debug, Default, PartialEq)]
119pub enum ArmadilloStateKind {
120    #[default]
121    Idle,
122    Rolling,
123    Scared,
124}
125
126impl AzBuf for OptionalUnsignedInt {
127    fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
128        let val = u32::azalea_read_var(buf)?;
129        Ok(OptionalUnsignedInt(if val == 0 {
130            None
131        } else {
132            Some(val - 1)
133        }))
134    }
135    fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> {
136        match self.0 {
137            Some(val) => (val + 1).azalea_write_var(buf),
138            None => 0u32.azalea_write_var(buf),
139        }
140    }
141}
142
143/// A set of x, y, and z rotations. This is used for armor stands.
144#[derive(AzBuf, Clone, Debug, Default, PartialEq)]
145pub struct Rotations {
146    pub x: f32,
147    pub y: f32,
148    pub z: f32,
149}
150
151#[cfg_attr(feature = "bevy_ecs", derive(bevy_ecs::component::Component))]
152#[derive(AzBuf, Clone, Copy, Debug, Default, Eq, PartialEq)]
153pub enum Pose {
154    #[default]
155    Standing = 0,
156    FallFlying,
157    Sleeping,
158    Swimming,
159    SpinAttack,
160    Crouching,
161    LongJumping,
162    Dying,
163    Croaking,
164    UsingTongue,
165    Sitting,
166    Roaring,
167    Sniffing,
168    Emerging,
169    Digging,
170    Sliding,
171    Shooting,
172    Inhaling,
173}
174
175#[derive(AzBuf, Clone, Debug, PartialEq)]
176pub struct VillagerData {
177    pub kind: VillagerKind,
178    pub profession: VillagerProfession,
179    #[var]
180    pub level: u32,
181}
182
183#[derive(AzBuf, Clone, Copy, Debug, Default, PartialEq)]
184pub enum SnifferStateKind {
185    #[default]
186    Idling,
187    FeelingHappy,
188    Scenting,
189    Sniffing,
190    Searching,
191    Digging,
192    Rising,
193}
194
195#[derive(AzBuf, Clone, Copy, Debug, Default, PartialEq)]
196pub enum CopperGolemStateKind {
197    #[default]
198    Idle,
199    GettingItem,
200    GettingNoItem,
201    DroppingItem,
202    DroppingNoItem,
203}
204#[derive(AzBuf, Clone, Copy, Debug, Default, PartialEq)]
205pub enum WeatheringCopperStateKind {
206    #[default]
207    Unaffected,
208    Exposed,
209    Weathered,
210    Oxidized,
211}
212
213#[derive(AzBuf, Clone, Copy, Debug, Default, Eq, PartialEq)]
214pub enum HumanoidArm {
215    Left = 0,
216    #[default]
217    Right = 1,
218}