1
2
Fork 0
mirror of https://github.com/mat-1/azalea.git synced 2025-08-02 06:16:04 +00:00

fix CustomModelData and WrittenBookContent datacomponents

This commit is contained in:
mat 2025-02-21 17:22:00 +00:00
parent c285fadd34
commit 63b1036a96
7 changed files with 126 additions and 6 deletions

1
Cargo.lock generated
View file

@ -432,6 +432,7 @@ dependencies = [
"azalea-registry",
"indexmap",
"simdnbt",
"tracing",
"uuid",
]

View file

@ -21,6 +21,8 @@ pub enum BufReadError {
CouldNotReadBytes,
#[error("The received encoded string buffer length is longer than maximum allowed ({length} > {max_length})")]
StringLengthTooLong { length: u32, max_length: u32 },
#[error("The received Vec length is longer than maximum allowed ({length} > {max_length})")]
VecLengthTooLong { length: u32, max_length: u32 },
#[error("{source}")]
Io {
#[from]
@ -183,7 +185,7 @@ impl AzaleaRead for UnsizedByteArray {
}
}
impl<T: AzaleaRead + Send> AzaleaRead for Vec<T> {
impl<T: AzaleaRead> AzaleaRead for Vec<T> {
default fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
let length = u32::azalea_read_var(buf)? as usize;
// we limit the capacity to not get exploited into allocating a bunch
@ -194,6 +196,23 @@ impl<T: AzaleaRead + Send> AzaleaRead for Vec<T> {
Ok(contents)
}
}
impl<T: AzaleaRead> AzaleaReadLimited for Vec<T> {
fn azalea_read_limited(buf: &mut Cursor<&[u8]>, limit: usize) -> Result<Self, BufReadError> {
let length = u32::azalea_read_var(buf)? as usize;
if length > limit {
return Err(BufReadError::VecLengthTooLong {
length: length as u32,
max_length: limit as u32,
});
}
let mut contents = Vec::with_capacity(usize::min(length, 65536));
for _ in 0..length {
contents.push(T::azalea_read(buf)?);
}
Ok(contents)
}
}
impl<K: AzaleaRead + Send + Eq + Hash, V: AzaleaRead + Send> AzaleaRead for HashMap<K, V> {
fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
@ -343,6 +362,16 @@ impl<T: AzaleaReadVar> AzaleaReadVar for Option<T> {
})
}
}
impl<T: AzaleaReadLimited> AzaleaReadLimited for Option<T> {
fn azalea_read_limited(buf: &mut Cursor<&[u8]>, limit: usize) -> Result<Self, BufReadError> {
let present = bool::azalea_read(buf)?;
Ok(if present {
Some(T::azalea_read_limited(buf, limit)?)
} else {
None
})
}
}
// [String; 4]
impl<T: AzaleaRead, const N: usize> AzaleaRead for [T; N] {

View file

@ -0,0 +1,55 @@
use std::io::Cursor;
use azalea_buf::{AzaleaRead, AzaleaReadLimited, AzaleaReadVar, AzaleaWrite};
/// Used for written books.
pub struct Filterable<T> {
pub raw: T,
pub filtered: Option<T>,
}
impl<T: AzaleaWrite> azalea_buf::AzaleaWrite for Filterable<T> {
fn azalea_write(&self, buf: &mut impl std::io::Write) -> Result<(), std::io::Error> {
self.raw.azalea_write(buf)?;
self.filtered.azalea_write(buf)?;
Ok(())
}
}
impl<T: AzaleaRead> azalea_buf::AzaleaRead for Filterable<T> {
fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, azalea_buf::BufReadError> {
let raw = AzaleaRead::azalea_read(buf)?;
let filtered = AzaleaRead::azalea_read(buf)?;
Ok(Self { raw, filtered })
}
}
impl<T: AzaleaReadLimited> azalea_buf::AzaleaReadLimited for Filterable<T> {
fn azalea_read_limited(
buf: &mut Cursor<&[u8]>,
limit: usize,
) -> Result<Self, azalea_buf::BufReadError> {
let raw = AzaleaReadLimited::azalea_read_limited(buf, limit)?;
let filtered = AzaleaReadLimited::azalea_read_limited(buf, limit)?;
Ok(Self { raw, filtered })
}
}
impl<T: AzaleaReadVar> azalea_buf::AzaleaReadVar for Filterable<T> {
fn azalea_read_var(buf: &mut Cursor<&[u8]>) -> Result<Self, azalea_buf::BufReadError> {
let raw = AzaleaReadVar::azalea_read_var(buf)?;
let filtered = AzaleaReadVar::azalea_read_var(buf)?;
Ok(Self { raw, filtered })
}
}
impl<T: Clone> Clone for Filterable<T> {
fn clone(&self) -> Self {
Self {
raw: self.raw.clone(),
filtered: self.filtered.clone(),
}
}
}
impl<T: PartialEq> PartialEq for Filterable<T> {
fn eq(&self, other: &Self) -> bool {
self.raw == other.raw && self.filtered == other.filtered
}
}

View file

@ -9,6 +9,7 @@ pub mod data_registry;
pub mod delta;
pub mod difficulty;
pub mod direction;
pub mod filterable;
pub mod game_type;
pub mod math;
pub mod objectives;

View file

@ -17,4 +17,5 @@ azalea-registry = { path = "../azalea-registry", version = "0.11.0" }
indexmap.workspace = true
simdnbt.workspace = true
tracing.workspace = true
uuid.workspace = true

View file

@ -3,12 +3,15 @@ use std::{any::Any, collections::HashMap, io::Cursor};
use azalea_buf::{AzBuf, AzaleaRead, AzaleaWrite, BufReadError};
use azalea_chat::FormattedText;
use azalea_core::{position::GlobalPos, resource_location::ResourceLocation};
use azalea_core::{
filterable::Filterable, position::GlobalPos, resource_location::ResourceLocation,
};
use azalea_registry::{
Attribute, Block, ConsumeEffectKind, DataComponentKind, Enchantment, EntityKind, HolderSet,
Item, MobEffect, Potion, SoundEvent, TrimMaterial, TrimPattern,
};
use simdnbt::owned::{Nbt, NbtCompound};
use tracing::trace;
use uuid::Uuid;
use crate::ItemStack;
@ -54,6 +57,8 @@ pub fn from_kind(
// if this is causing a compile-time error, look at DataComponents.java in the
// decompiled vanilla code to see how to implement new components
trace!("Reading data component {kind}");
// note that this match statement is updated by genitemcomponents.py
Ok(match kind {
DataComponentKind::CustomData => Box::new(CustomData::azalea_read(buf)?),
@ -328,8 +333,10 @@ impl DataComponent for AttributeModifiers {
#[derive(Clone, PartialEq, AzBuf)]
pub struct CustomModelData {
#[var]
pub value: i32,
pub floats: Vec<f32>,
pub flags: Vec<bool>,
pub strings: Vec<String>,
pub colors: Vec<i32>,
}
impl DataComponent for CustomModelData {
const KIND: DataComponentKind = DataComponentKind::CustomModelData;
@ -535,13 +542,15 @@ impl DataComponent for WritableBookContent {
#[derive(Clone, PartialEq, AzBuf)]
pub struct WrittenBookContent {
pub title: String,
#[limit(32)]
pub title: Filterable<String>,
pub author: String,
#[var]
pub generation: i32,
pub pages: Vec<FormattedText>,
pub pages: Vec<Filterable<FormattedText>>,
pub resolved: bool,
}
impl DataComponent for WrittenBookContent {
const KIND: DataComponentKind = DataComponentKind::WrittenBookContent;
}

File diff suppressed because one or more lines are too long