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 OptionalLivingEntityReference(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 ChickenVariant(azalea_registry::ChickenVariant),
86 CowVariant(azalea_registry::CowVariant),
87 WolfVariant(azalea_registry::WolfVariant),
88 WolfSoundVariant(azalea_registry::WolfSoundVariant),
89 FrogVariant(azalea_registry::FrogVariant),
90 PigVariant(azalea_registry::PigVariant),
91 OptionalGlobalPos(Option<GlobalPos>),
92 PaintingVariant(azalea_registry::PaintingVariant),
93 SnifferState(SnifferStateKind),
94 ArmadilloState(ArmadilloStateKind),
95 Vector3(Vec3),
96 Quaternion(Quaternion),
97}
98
99#[derive(Clone, Debug)]
100pub struct OptionalUnsignedInt(pub Option<u32>);
101
102#[derive(Clone, Debug, AzBuf)]
103pub struct Quaternion {
104 pub x: f32,
105 pub y: f32,
106 pub z: f32,
107 pub w: f32,
108}
109
110#[derive(Clone, Debug, Copy, Default, AzBuf)]
113pub enum ArmadilloStateKind {
114 #[default]
115 Idle,
116 Rolling,
117 Scared,
118}
119
120impl AzaleaRead for OptionalUnsignedInt {
121 fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
122 let val = u32::azalea_read_var(buf)?;
123 Ok(OptionalUnsignedInt(if val == 0 {
124 None
125 } else {
126 Some(val - 1)
127 }))
128 }
129}
130impl AzaleaWrite for OptionalUnsignedInt {
131 fn azalea_write(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
132 match self.0 {
133 Some(val) => (val + 1).azalea_write_var(buf),
134 None => 0u32.azalea_write_var(buf),
135 }
136 }
137}
138
139#[derive(Clone, Debug, AzBuf, Default)]
141pub struct Rotations {
142 pub x: f32,
143 pub y: f32,
144 pub z: f32,
145}
146
147#[derive(Clone, Debug, Copy, AzBuf, Default, Component, Eq, PartialEq)]
148pub enum Pose {
149 #[default]
150 Standing = 0,
151 FallFlying,
152 Sleeping,
153 Swimming,
154 SpinAttack,
155 Sneaking,
156 LongJumping,
157 Dying,
158}
159
160#[derive(Debug, Clone, AzBuf)]
161pub struct VillagerData {
162 pub kind: azalea_registry::VillagerKind,
163 pub profession: azalea_registry::VillagerProfession,
164 #[var]
165 pub level: u32,
166}
167
168#[derive(Debug, Copy, Clone, AzBuf, Default)]
169pub enum SnifferStateKind {
170 #[default]
171 Idling,
172 FeelingHappy,
173 Scenting,
174 Sniffing,
175 Searching,
176 Digging,
177 Rising,
178}