1#![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 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#[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 OptionalBlockState(azalea_block::BlockState),
77 Particle(Particle),
78 Particles(Box<[Particle]>),
79 VillagerData(VillagerData),
80 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#[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#[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}