azalea_entity/
data.rs

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