world/text_value: add support for new NBT text serialization

Starting with DataVersion 4290, text is stored as NBT instead of JSON.
The structure remains the same.
This commit is contained in:
Matthias Schiffer 2025-04-02 22:43:02 +02:00
parent ba6e4bae7f
commit 5f84ec8ed2
Signed by: neocturne
GPG key ID: 16EF3F64CB201D9C
4 changed files with 35 additions and 11 deletions

View file

@ -41,10 +41,15 @@ pub struct Sign {
impl Sign {
/// Processes a [de::BlockEntitySign] into a [Sign]
fn new(sign: &de::BlockEntitySign, kind: SignKind, material: Option<String>) -> Sign {
fn new(
sign: &de::BlockEntitySign,
kind: SignKind,
material: Option<String>,
data_version: u32,
) -> Sign {
let (front_text, back_text) = sign.text();
let front_text = front_text.decode();
let back_text = back_text.decode();
let front_text = front_text.decode(data_version);
let back_text = back_text.decode(data_version);
Sign {
kind,
material,
@ -78,7 +83,11 @@ pub struct BlockEntity {
impl BlockEntity {
/// Processes a [de::BlockEntity] into a [BlockEntity]
pub fn new(entity: &de::BlockEntity, block_type: Option<&BlockType>) -> Option<Self> {
pub fn new(
entity: &de::BlockEntity,
block_type: Option<&BlockType>,
data_version: u32,
) -> Option<Self> {
let wall_sign = block_type
.map(|block_type| block_type.block_color.is(BlockFlag::WallSign))
.unwrap_or_default();
@ -92,7 +101,7 @@ impl BlockEntity {
let material = block_type
.as_ref()
.and_then(|block_type| block_type.sign_material.as_ref());
let data = BlockEntityData::Sign(Sign::new(sign, kind, material.cloned()));
let data = BlockEntityData::Sign(Sign::new(sign, kind, material.cloned(), data_version));
Some(BlockEntity {
x: entity.x,

View file

@ -58,6 +58,8 @@ pub struct Chunk<'a> {
inner: ChunkInner<'a>,
/// Unprocessed block entities
block_entities: &'a Vec<de::BlockEntity>,
/// Chunk data version
data_version: u32,
}
impl<'a> Chunk<'a> {
@ -87,6 +89,7 @@ impl<'a> Chunk<'a> {
Chunk {
inner,
block_entities,
data_version,
},
has_unknown,
))
@ -292,7 +295,11 @@ impl<'a> Chunk<'a> {
.iter()
.map(|block_entity| {
let block_type = self.block_type_at_block_entity(block_entity)?;
Ok(BlockEntity::new(block_entity, block_type))
Ok(BlockEntity::new(
block_entity,
block_type,
self.data_version,
))
})
.collect::<Result<_>>()?;
Ok(entities.into_iter().flatten().collect())

View file

@ -49,7 +49,7 @@ static DYE_COLORS: phf::Map<&'static str, Color> = phf::phf_map! {
impl RawSignText<'_> {
/// Decodes the [RawSignText] into a [SignText]
pub fn decode(&self) -> SignText {
pub fn decode(&self, data_version: u32) -> SignText {
let color = self
.color
.map(|c| DYE_COLORS.get(c).copied().unwrap_or(DEFAULT_COLOR));
@ -60,7 +60,7 @@ impl RawSignText<'_> {
SignText(
self.messages
.iter()
.map(|message| message.deserialize().linearize(&parent))
.map(|message| message.deserialize(data_version).linearize(&parent))
.collect(),
)
}

View file

@ -171,12 +171,20 @@ impl Default for DeserializedText {
/// Minecraft raw text value
#[derive(Debug, Deserialize)]
pub struct TextValue(pub String);
pub struct TextValue(pub fastnbt::Value);
impl TextValue {
/// Deserializes a [TextValue] into a [DeserializedText]
pub fn deserialize(&self) -> DeserializedText {
serde_json::from_str(&self.0).unwrap_or_default()
pub fn deserialize(&self, data_version: u32) -> DeserializedText {
if data_version < 4290 {
if let fastnbt::Value::String(json) = &self.0 {
if let Ok(content) = serde_json::from_str(json) {
return content;
}
}
}
fastnbt::from_value(&self.0).unwrap_or_default()
}
}