aboutsummaryrefslogtreecommitdiff
path: root/azalea-world/src/entity/data.rs
diff options
context:
space:
mode:
authormat <27899617+mat-1@users.noreply.github.com>2022-11-06 14:05:01 -0600
committerGitHub <noreply@github.com>2022-11-06 14:05:01 -0600
commitd112856ff6353592a50658b0ddd316f54dd97b87 (patch)
tree6c408ecab96012e3bffaf15843fad5b9b6817796 /azalea-world/src/entity/data.rs
parent9bc517511663193f3166320db4cb5ca02701b039 (diff)
downloadazalea-drasl-d112856ff6353592a50658b0ddd316f54dd97b87.tar.xz
Entity metadata (#37)
* add example generated metadata.rs * metadata.rs codegen * add the files * add comment to top of metadata.rs * avoid clone * metadata * defaults * defaults * fix metadata readers and writers * fix bad bitmasks and ignore some clippy warnings in generated code * add set_index function to entity metadatas * applying metadata
Diffstat (limited to 'azalea-world/src/entity/data.rs')
-rw-r--r--azalea-world/src/entity/data.rs87
1 files changed, 63 insertions, 24 deletions
diff --git a/azalea-world/src/entity/data.rs b/azalea-world/src/entity/data.rs
index c73a84d6..dcff6cfe 100644
--- a/azalea-world/src/entity/data.rs
+++ b/azalea-world/src/entity/data.rs
@@ -1,12 +1,16 @@
+use azalea_block::BlockState;
use azalea_buf::{BufReadError, McBufVarReadable};
use azalea_buf::{McBuf, McBufReadable, McBufWritable};
use azalea_chat::Component;
use azalea_core::{BlockPos, Direction, GlobalPos, Particle, Slot};
+use enum_as_inner::EnumAsInner;
+use log::warn;
+use nohash_hasher::IntSet;
use std::io::{Cursor, Write};
use uuid::Uuid;
#[derive(Clone, Debug)]
-pub struct EntityMetadata(Vec<EntityDataItem>);
+pub struct EntityMetadataItems(pub Vec<EntityDataItem>);
#[derive(Clone, Debug)]
pub struct EntityDataItem {
@@ -16,7 +20,7 @@ pub struct EntityDataItem {
pub value: EntityDataValue,
}
-impl McBufReadable for EntityMetadata {
+impl McBufReadable for EntityMetadataItems {
fn read_from(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
let mut metadata = Vec::new();
loop {
@@ -27,11 +31,11 @@ impl McBufReadable for EntityMetadata {
let value = EntityDataValue::read_from(buf)?;
metadata.push(EntityDataItem { index, value });
}
- Ok(EntityMetadata(metadata))
+ Ok(EntityMetadataItems(metadata))
}
}
-impl McBufWritable for EntityMetadata {
+impl McBufWritable for EntityMetadataItems {
fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
for item in &self.0 {
item.index.write_into(buf)?;
@@ -42,10 +46,9 @@ impl McBufWritable for EntityMetadata {
}
}
-#[derive(Clone, Debug)]
+#[derive(Clone, Debug, EnumAsInner)]
pub enum EntityDataValue {
Byte(u8),
- // varint
Int(i32),
Float(f32),
String(String),
@@ -53,14 +56,14 @@ pub enum EntityDataValue {
OptionalComponent(Option<Component>),
ItemStack(Slot),
Boolean(bool),
- Rotations { x: f32, y: f32, z: f32 },
+ Rotations(Rotations),
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>),
+ OptionalBlockState(Option<BlockState>),
CompoundTag(azalea_nbt::Tag),
Particle(Particle),
VillagerData(VillagerData),
@@ -73,6 +76,13 @@ pub enum EntityDataValue {
PaintingVariant(azalea_registry::PaintingVariant),
}
+#[derive(Clone, Debug, McBuf, Default)]
+pub struct Rotations {
+ pub x: f32,
+ pub y: f32,
+ pub z: f32,
+}
+
impl McBufReadable for EntityDataValue {
fn read_from(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
let data_type = u32::var_read_from(buf)?;
@@ -85,21 +95,20 @@ impl McBufReadable for EntityDataValue {
5 => EntityDataValue::OptionalComponent(Option::<Component>::read_from(buf)?),
6 => EntityDataValue::ItemStack(Slot::read_from(buf)?),
7 => EntityDataValue::Boolean(bool::read_from(buf)?),
- 8 => EntityDataValue::Rotations {
- x: f32::read_from(buf)?,
- y: f32::read_from(buf)?,
- z: f32::read_from(buf)?,
- },
+ 8 => EntityDataValue::Rotations(Rotations::read_from(buf)?),
9 => EntityDataValue::BlockPos(BlockPos::read_from(buf)?),
10 => EntityDataValue::OptionalBlockPos(Option::<BlockPos>::read_from(buf)?),
11 => EntityDataValue::Direction(Direction::read_from(buf)?),
12 => EntityDataValue::OptionalUuid(Option::<Uuid>::read_from(buf)?),
13 => EntityDataValue::OptionalBlockState({
- let val = i32::var_read_from(buf)?;
+ let val = u32::var_read_from(buf)?;
if val == 0 {
None
} else {
- Some(val)
+ Some(BlockState::try_from(val - 1).unwrap_or_else(|_| {
+ warn!("Invalid block state ID {} in entity metadata", val - 1);
+ BlockState::Air
+ }))
}
}),
14 => EntityDataValue::CompoundTag(azalea_nbt::Tag::read_from(buf)?),
@@ -135,19 +144,20 @@ impl McBufWritable for EntityDataValue {
}
}
-#[derive(Clone, Debug, Copy, McBuf)]
+#[derive(Clone, Debug, Copy, McBuf, Default)]
pub enum Pose {
+ #[default]
Standing = 0,
- FallFlying = 1,
- Sleeping = 2,
- Swimming = 3,
- SpinAttack = 4,
- Sneaking = 5,
- LongJumping = 6,
- Dying = 7,
+ FallFlying,
+ Sleeping,
+ Swimming,
+ SpinAttack,
+ Sneaking,
+ LongJumping,
+ Dying,
}
-#[derive(Debug, Clone, McBuf)]
+#[derive(Debug, Clone, McBuf, Default)]
pub struct VillagerData {
#[var]
type_: u32,
@@ -156,3 +166,32 @@ pub struct VillagerData {
#[var]
level: u32,
}
+
+impl TryFrom<EntityMetadataItems> for Vec<EntityDataValue> {
+ type Error = String;
+
+ fn try_from(data: EntityMetadataItems) -> Result<Self, Self::Error> {
+ let mut data = data.0;
+
+ data.sort_by(|a, b| a.index.cmp(&b.index));
+
+ let mut prev_indexes = IntSet::default();
+ let len = data.len();
+ // check to make sure it's valid, in vanilla this is guaranteed to pass
+ // but it's possible there's mods that mess with it so we want to make
+ // sure it's good
+ for item in &data {
+ if prev_indexes.contains(&item.index) {
+ return Err(format!("Index {} is duplicated", item.index));
+ }
+ if item.index as usize > len {
+ return Err(format!("Index {} is too big", item.index));
+ }
+ prev_indexes.insert(item.index);
+ }
+
+ let data = data.into_iter().map(|d| d.value).collect();
+
+ Ok(data)
+ }
+}