diff options
| author | mat <27899617+mat-1@users.noreply.github.com> | 2022-11-06 14:05:01 -0600 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2022-11-06 14:05:01 -0600 |
| commit | d112856ff6353592a50658b0ddd316f54dd97b87 (patch) | |
| tree | 6c408ecab96012e3bffaf15843fad5b9b6817796 /azalea-world/src/entity/data.rs | |
| parent | 9bc517511663193f3166320db4cb5ca02701b039 (diff) | |
| download | azalea-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.rs | 87 |
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) + } +} |
