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 CatSoundVariant(azalea_registry::data::CatSoundVariant),
85 CowVariant(azalea_registry::data::CowVariant),
86 CowSoundVariant(azalea_registry::data::CowSoundVariant),
87 WolfVariant(azalea_registry::data::WolfVariant),
88 WolfSoundVariant(azalea_registry::data::WolfSoundVariant),
89 FrogVariant(azalea_registry::data::FrogVariant),
90 PigVariant(azalea_registry::data::PigVariant),
91 PigSoundVariant(azalea_registry::data::PigSoundVariant),
92 ChickenVariant(azalea_registry::data::ChickenVariant),
93 ChickenSoundVariant(azalea_registry::data::ChickenSoundVariant),
94 ZombieNautilusVariant(azalea_registry::data::ZombieNautilusVariant),
95 OptionalGlobalPos(Option<Box<GlobalPos>>),
96 PaintingVariant(azalea_registry::data::PaintingVariant),
97 SnifferState(SnifferStateKind),
98 ArmadilloState(ArmadilloStateKind),
99 CopperGolemState(CopperGolemStateKind),
100 WeatheringCopperState(WeatheringCopperStateKind),
101 Vector3(Vec3f32),
102 Quaternion(Quaternion),
103 ResolvableProfile(components::Profile),
104 HumanoidArm(HumanoidArm),
105}
106
107const _: () = assert!(size_of::<EntityDataValue>() == 24);
108
109#[derive(Clone, Debug, PartialEq, Default)]
110pub struct OptionalUnsignedInt(pub Option<u32>);
111
112#[derive(AzBuf, Clone, Debug, PartialEq, Default)]
113pub struct Quaternion {
114 pub x: f32,
115 pub y: f32,
116 pub z: f32,
117 pub w: f32,
118}
119
120#[derive(AzBuf, Clone, Copy, Debug, Default, PartialEq)]
123pub enum ArmadilloStateKind {
124 #[default]
125 Idle,
126 Rolling,
127 Scared,
128}
129
130impl AzBuf for OptionalUnsignedInt {
131 fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
132 let val = u32::azalea_read_var(buf)?;
133 Ok(OptionalUnsignedInt(if val == 0 {
134 None
135 } else {
136 Some(val - 1)
137 }))
138 }
139 fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> {
140 match self.0 {
141 Some(val) => (val + 1).azalea_write_var(buf),
142 None => 0u32.azalea_write_var(buf),
143 }
144 }
145}
146
147#[derive(AzBuf, Clone, Debug, Default, PartialEq)]
149pub struct Rotations {
150 pub x: f32,
151 pub y: f32,
152 pub z: f32,
153}
154
155#[cfg_attr(feature = "bevy_ecs", derive(bevy_ecs::component::Component))]
156#[derive(AzBuf, Clone, Copy, Debug, Default, Eq, PartialEq)]
157pub enum Pose {
158 #[default]
159 Standing = 0,
160 FallFlying,
161 Sleeping,
162 Swimming,
163 SpinAttack,
164 Crouching,
165 LongJumping,
166 Dying,
167 Croaking,
168 UsingTongue,
169 Sitting,
170 Roaring,
171 Sniffing,
172 Emerging,
173 Digging,
174 Sliding,
175 Shooting,
176 Inhaling,
177}
178
179#[derive(AzBuf, Clone, Debug, PartialEq)]
180pub struct VillagerData {
181 pub kind: VillagerKind,
182 pub profession: VillagerProfession,
183 #[var]
184 pub level: u32,
185}
186
187#[derive(AzBuf, Clone, Copy, Debug, Default, PartialEq)]
188pub enum SnifferStateKind {
189 #[default]
190 Idling,
191 FeelingHappy,
192 Scenting,
193 Sniffing,
194 Searching,
195 Digging,
196 Rising,
197}
198
199#[derive(AzBuf, Clone, Copy, Debug, Default, PartialEq)]
200pub enum CopperGolemStateKind {
201 #[default]
202 Idle,
203 GettingItem,
204 GettingNoItem,
205 DroppingItem,
206 DroppingNoItem,
207}
208#[derive(AzBuf, Clone, Copy, Debug, Default, PartialEq)]
209pub enum WeatheringCopperStateKind {
210 #[default]
211 Unaffected,
212 Exposed,
213 Weathered,
214 Oxidized,
215}
216
217#[derive(AzBuf, Clone, Copy, Debug, Default, Eq, PartialEq)]
218pub enum HumanoidArm {
219 Left = 0,
220 #[default]
221 Right = 1,
222}