1use 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 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#[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 OptionalBlockState(azalea_block::BlockState),
77 CompoundTag(simdnbt::owned::NbtCompound),
78 Particle(Particle),
79 Particles(Vec<Particle>),
80 VillagerData(VillagerData),
81 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#[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#[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}