1#![allow(clippy::double_parens)]
5
6use std::io::{self, Cursor, Write};
7
8use azalea_buf::{AzBuf, AzaleaRead, AzaleaReadVar, AzaleaWrite, AzaleaWriteVar, 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 bevy_ecs::component::Component;
17use derive_more::Deref;
18use enum_as_inner::EnumAsInner;
19use uuid::Uuid;
20
21use crate::particle::Particle;
22
23#[derive(Clone, Debug, Deref, PartialEq)]
24pub struct EntityMetadataItems(pub Vec<EntityDataItem>);
25
26#[derive(Clone, Debug, PartialEq)]
27pub struct EntityDataItem {
28 pub index: u8,
31 pub value: EntityDataValue,
32}
33
34impl AzaleaRead for EntityMetadataItems {
35 fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
36 let mut metadata = Vec::new();
37 loop {
38 let id = u8::azalea_read(buf)?;
39 if id == 0xff {
40 break;
41 }
42 let value = EntityDataValue::azalea_read(buf)?;
43 metadata.push(EntityDataItem { index: id, value });
44 }
45 Ok(EntityMetadataItems(metadata))
46 }
47}
48
49impl AzaleaWrite for EntityMetadataItems {
50 fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> {
51 for item in &self.0 {
52 item.index.azalea_write(buf)?;
53 item.value.azalea_write(buf)?;
54 }
55 0xffu8.azalea_write(buf)?;
56 Ok(())
57 }
58}
59
60#[derive(AzBuf, Clone, Debug, EnumAsInner, PartialEq)]
63pub enum EntityDataValue {
64 Byte(u8),
65 Int(#[var] i32),
66 Long(#[var] i64),
67 Float(f32),
68 String(Box<str>),
69 FormattedText(Box<FormattedText>),
70 OptionalFormattedText(Option<Box<FormattedText>>),
71 ItemStack(ItemStack),
72 Boolean(bool),
73 Rotations(Rotations),
74 BlockPos(BlockPos),
75 OptionalBlockPos(Option<BlockPos>),
76 Direction(Direction),
77 OptionalLivingEntityReference(Option<Uuid>),
78 BlockState(azalea_block::BlockState),
79 OptionalBlockState(azalea_block::BlockState),
81 Particle(Particle),
82 Particles(Box<[Particle]>),
83 VillagerData(VillagerData),
84 OptionalUnsignedInt(OptionalUnsignedInt),
86 Pose(Pose),
87 CatVariant(azalea_registry::data::CatVariant),
88 CowVariant(azalea_registry::data::CowVariant),
89 WolfVariant(azalea_registry::data::WolfVariant),
90 WolfSoundVariant(azalea_registry::data::WolfSoundVariant),
91 FrogVariant(azalea_registry::data::FrogVariant),
92 PigVariant(azalea_registry::data::PigVariant),
93 ChickenVariant(azalea_registry::data::ChickenVariant),
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)]
110pub struct OptionalUnsignedInt(pub Option<u32>);
111
112#[derive(AzBuf, Clone, Debug, PartialEq)]
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 AzaleaRead 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}
140impl AzaleaWrite for OptionalUnsignedInt {
141 fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> {
142 match self.0 {
143 Some(val) => (val + 1).azalea_write_var(buf),
144 None => 0u32.azalea_write_var(buf),
145 }
146 }
147}
148
149#[derive(AzBuf, Clone, Debug, Default, PartialEq)]
151pub struct Rotations {
152 pub x: f32,
153 pub y: f32,
154 pub z: f32,
155}
156
157#[derive(AzBuf, Clone, Component, Copy, Debug, Default, Eq, PartialEq)]
158pub enum Pose {
159 #[default]
160 Standing = 0,
161 FallFlying,
162 Sleeping,
163 Swimming,
164 SpinAttack,
165 Crouching,
166 LongJumping,
167 Dying,
168 Croaking,
169 UsingTongue,
170 Sitting,
171 Roaring,
172 Sniffing,
173 Emerging,
174 Digging,
175 Sliding,
176 Shooting,
177 Inhaling,
178}
179
180#[derive(AzBuf, Clone, Debug, PartialEq)]
181pub struct VillagerData {
182 pub kind: VillagerKind,
183 pub profession: VillagerProfession,
184 #[var]
185 pub level: u32,
186}
187
188#[derive(AzBuf, Clone, Copy, Debug, Default, PartialEq)]
189pub enum SnifferStateKind {
190 #[default]
191 Idling,
192 FeelingHappy,
193 Scenting,
194 Sniffing,
195 Searching,
196 Digging,
197 Rising,
198}
199
200#[derive(AzBuf, Clone, Copy, Debug, Default, PartialEq)]
201pub enum CopperGolemStateKind {
202 #[default]
203 Idle,
204 GettingItem,
205 GettingNoItem,
206 DroppingItem,
207 DroppingNoItem,
208}
209#[derive(AzBuf, Clone, Copy, Debug, Default, PartialEq)]
210pub enum WeatheringCopperStateKind {
211 #[default]
212 Unaffected,
213 Exposed,
214 Weathered,
215 Oxidized,
216}
217
218#[derive(AzBuf, Clone, Copy, Debug, Default, Eq, PartialEq)]
219pub enum HumanoidArm {
220 Left = 0,
221 #[default]
222 Right = 1,
223}