azalea_entity/
data.rs

1//! Define some types needed for entity metadata.
2
3use std::io::{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, Vec3},
10};
11use azalea_inventory::ItemStack;
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)]
20pub struct EntityMetadataItems(pub Vec<EntityDataItem>);
21
22#[derive(Clone, Debug)]
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) -> Result<(), std::io::Error> {
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)]
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    OptionalUuid(Option<Uuid>),
74    BlockState(azalea_block::BlockState),
75    /// If this is air, that means it's absent,
76    OptionalBlockState(azalea_block::BlockState),
77    CompoundTag(simdnbt::owned::NbtCompound),
78    Particle(Particle),
79    Particles(Vec<Particle>),
80    VillagerData(VillagerData),
81    // 0 for absent; 1 + actual value otherwise. Used for entity IDs.
82    OptionalUnsignedInt(OptionalUnsignedInt),
83    Pose(Pose),
84    CatVariant(azalea_registry::CatVariant),
85    WolfVariant(azalea_registry::WolfVariant),
86    FrogVariant(azalea_registry::FrogVariant),
87    OptionalGlobalPos(Option<GlobalPos>),
88    PaintingVariant(azalea_registry::PaintingVariant),
89    SnifferState(SnifferStateKind),
90    ArmadilloState(ArmadilloStateKind),
91    Vector3(Vec3),
92    Quaternion(Quaternion),
93}
94
95#[derive(Clone, Debug)]
96pub struct OptionalUnsignedInt(pub Option<u32>);
97
98#[derive(Clone, Debug, AzBuf)]
99pub struct Quaternion {
100    pub x: f32,
101    pub y: f32,
102    pub z: f32,
103    pub w: f32,
104}
105
106// mojang just calls this ArmadilloState but i added "Kind" since otherwise it
107// collides with a name in metadata.rs
108#[derive(Clone, Debug, Copy, Default, AzBuf)]
109pub enum ArmadilloStateKind {
110    #[default]
111    Idle,
112    Rolling,
113    Scared,
114}
115
116impl AzaleaRead for OptionalUnsignedInt {
117    fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
118        let val = u32::azalea_read_var(buf)?;
119        Ok(OptionalUnsignedInt(if val == 0 {
120            None
121        } else {
122            Some(val - 1)
123        }))
124    }
125}
126impl AzaleaWrite for OptionalUnsignedInt {
127    fn azalea_write(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
128        match self.0 {
129            Some(val) => (val + 1).azalea_write_var(buf),
130            None => 0u32.azalea_write_var(buf),
131        }
132    }
133}
134
135/// A set of x, y, and z rotations. This is used for armor stands.
136#[derive(Clone, Debug, AzBuf, Default)]
137pub struct Rotations {
138    pub x: f32,
139    pub y: f32,
140    pub z: f32,
141}
142
143#[derive(Clone, Debug, Copy, AzBuf, Default, Component, Eq, PartialEq)]
144pub enum Pose {
145    #[default]
146    Standing = 0,
147    FallFlying,
148    Sleeping,
149    Swimming,
150    SpinAttack,
151    Sneaking,
152    LongJumping,
153    Dying,
154}
155
156#[derive(Debug, Clone, AzBuf)]
157pub struct VillagerData {
158    pub kind: azalea_registry::VillagerKind,
159    pub profession: azalea_registry::VillagerProfession,
160    #[var]
161    pub level: u32,
162}
163
164#[derive(Debug, Copy, Clone, AzBuf, Default)]
165pub enum SnifferStateKind {
166    #[default]
167    Idling,
168    FeelingHappy,
169    Scenting,
170    Sniffing,
171    Searching,
172    Digging,
173    Rising,
174}