1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
|
pub type EntityMetadata = Vec<EntityDataItem>;
#[derive(Clone, Debug)]
pub struct EntityDataItem {
// we can't identify what the index is for here because we don't know the
// entity type
pub index: u8,
pub value: EntityDataValue,
}
impl McBufReadable for Vec<EntityDataItem> {
fn read_into(buf: &mut impl Read) -> Result<Self, String> {
let mut metadata = Vec::new();
loop {
let index = u8::read_into(buf)?;
if index == 0xff {
break;
}
let value = EntityDataValue::read_into(buf)?;
metadata.push(EntityDataItem { index, value });
}
Ok(metadata)
}
}
impl McBufWritable for Vec<EntityDataItem> {
fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
for item in self {
buf.write_byte(item.index)?;
item.value.write_into(buf)?;
}
buf.write_byte(0xff)?;
Ok(())
}
}
#[derive(Clone, Debug)]
pub enum EntityDataValue {
Byte(u8),
// varint
Int(i32),
Float(f32),
String(String),
Component(Component),
OptionalComponent(Option<Component>),
ItemStack(Slot),
Boolean(bool),
Rotations { x: f32, y: f32, z: f32 },
BlockPos(BlockPos),
OptionalBlockPos(Option<BlockPos>),
Direction(Direction),
OptionalUuid(Option<Uuid>),
// 0 for absent (implies air); otherwise, a block state ID as per the global palette
// this is a varint
OptionalBlockState(Option<i32>),
CompoundTag(azalea_nbt::Tag),
Particle(Particle),
VillagerData(VillagerData),
// 0 for absent; 1 + actual value otherwise. Used for entity IDs.
OptionalUnsignedInt(Option<u32>),
Pose(Pose),
}
impl McBufReadable for EntityDataValue {
fn read_into(buf: &mut impl Read) -> Result<Self, String> {
let type_ = buf.read_varint()?;
Ok(match type_ {
0 => EntityDataValue::Byte(buf.read_byte()?),
1 => EntityDataValue::Int(buf.read_varint()?),
2 => EntityDataValue::Float(buf.read_float()?),
3 => EntityDataValue::String(buf.read_utf()?),
4 => EntityDataValue::Component(Component::read_into(buf)?),
5 => EntityDataValue::OptionalComponent(Option::<Component>::read_into(buf)?),
6 => EntityDataValue::ItemStack(Slot::read_into(buf)?),
7 => EntityDataValue::Boolean(buf.read_boolean()?),
8 => EntityDataValue::Rotations {
x: buf.read_float()?,
y: buf.read_float()?,
z: buf.read_float()?,
},
9 => EntityDataValue::BlockPos(BlockPos::read_into(buf)?),
10 => EntityDataValue::OptionalBlockPos(Option::<BlockPos>::read_into(buf)?),
11 => EntityDataValue::Direction(Direction::read_into(buf)?),
12 => EntityDataValue::OptionalUuid(Option::<Uuid>::read_into(buf)?),
13 => EntityDataValue::OptionalBlockState({
let val = i32::read_into(buf)?;
if val == 0 {
None
} else {
Some(val)
}
}),
14 => EntityDataValue::CompoundTag(azalea_nbt::Tag::read_into(buf)?),
15 => EntityDataValue::Particle(Particle::read_into(buf)?),
16 => EntityDataValue::VillagerData(VillagerData::read_into(buf)?),
17 => EntityDataValue::OptionalUnsignedInt({
let val = buf.read_varint()?;
if val == 0 {
None
} else {
Some((val - 1) as u32)
}
}),
18 => EntityDataValue::Pose(Pose::read_into(buf)?),
_ => return Err(format!("Unknown entity data type: {}", type_)),
})
}
}
impl McBufWritable for EntityDataValue {
fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
todo!();
}
}
#[derive(Clone, Debug, Copy, McBuf)]
pub enum Pose {
Standing = 0,
FallFlying = 1,
Sleeping = 2,
Swimming = 3,
SpinAttack = 4,
Sneaking = 5,
LongJumping = 6,
Dying = 7,
}
#[derive(Debug, Clone, McBuf)]
pub struct VillagerData {
#[var]
type_: u32,
#[var]
profession: u32,
#[var]
level: u32,
}
|