From 8473383cce3e38b3e935ada20283cf078752d158 Mon Sep 17 00:00:00 2001 From: kralverde Date: Fri, 14 Feb 2025 16:22:43 -1000 Subject: [PATCH] work on removing bytebuf serialization --- pumpkin-macros/src/lib.rs | 4 +- pumpkin-nbt/Cargo.toml | 4 + pumpkin-nbt/src/compound.rs | 28 +- pumpkin-nbt/src/deserializer.rs | 111 +------- pumpkin-nbt/src/lib.rs | 196 +++++++++++++- pumpkin-nbt/src/serializer.rs | 255 ++++++++---------- pumpkin-nbt/src/tag.rs | 79 +++--- .../src/client/config/registry_data.rs | 2 +- .../src/client/play/chunk_data.rs | 6 +- .../src/client/play/update_objectives.rs | 6 +- pumpkin-protocol/src/lib.rs | 2 - pumpkin-registry/Cargo.toml | 1 - pumpkin-registry/src/lib.rs | 3 + pumpkin-util/Cargo.toml | 1 - pumpkin-util/src/lib.rs | 148 ++++++++++ pumpkin-util/src/text/mod.rs | 24 +- pumpkin-world/src/chunk/mod.rs | 12 +- pumpkin-world/src/world_info/anvil.rs | 2 +- 18 files changed, 522 insertions(+), 362 deletions(-) diff --git a/pumpkin-macros/src/lib.rs b/pumpkin-macros/src/lib.rs index 57adb0b66..42da977b5 100644 --- a/pumpkin-macros/src/lib.rs +++ b/pumpkin-macros/src/lib.rs @@ -163,7 +163,7 @@ pub fn client_packet(input: TokenStream, item: TokenStream) -> TokenStream { let gen = quote! { #item - impl #impl_generics crate::bytebuf::packet::Packet for #name #ty_generics { + impl #impl_generics crate::Packet for #name #ty_generics { const PACKET_ID: i32 = #input; } }; @@ -182,7 +182,7 @@ pub fn server_packet(input: TokenStream, item: TokenStream) -> TokenStream { let gen = quote! { #item - impl #impl_generics crate::bytebuf::packet::Packet for #name #ty_generics { + impl #impl_generics crate::Packet for #name #ty_generics { const PACKET_ID: i32 = #input; } }; diff --git a/pumpkin-nbt/Cargo.toml b/pumpkin-nbt/Cargo.toml index abb5172f1..cb718b8b2 100644 --- a/pumpkin-nbt/Cargo.toml +++ b/pumpkin-nbt/Cargo.toml @@ -4,12 +4,16 @@ version.workspace = true edition.workspace = true [dependencies] +pumpkin-util = { path = "../pumpkin-util" } + serde.workspace = true thiserror.workspace = true bytes.workspace = true + cesu8 = "1.1" [dev-dependencies] flate2 = "1.0" pumpkin-world = { path = "../pumpkin-world" } +fastnbt = { git = "https://github.com/owengage/fastnbt.git" } diff --git a/pumpkin-nbt/src/compound.rs b/pumpkin-nbt/src/compound.rs index fb44d5309..132141786 100644 --- a/pumpkin-nbt/src/compound.rs +++ b/pumpkin-nbt/src/compound.rs @@ -1,5 +1,5 @@ -use crate::deserializer::ReadAdaptor; -use crate::serializer::WriteAdaptor; +use pumpkin_util::{ReadHelper, WriteHelper}; + use crate::tag::NbtTag; use crate::{get_nbt_string, Error, Nbt, END_ID}; use std::io::{ErrorKind, Read, Write}; @@ -17,7 +17,7 @@ impl NbtCompound { } } - pub fn deserialize_content(reader: &mut ReadAdaptor) -> Result + pub fn deserialize_content(reader: &mut ReadHelper) -> Result where R: Read, { @@ -26,17 +26,12 @@ impl NbtCompound { loop { let tag_id = match reader.get_u8_be() { Ok(id) => id, - Err(err) => match err { - Error::Incomplete(err) => match err.kind() { - ErrorKind::UnexpectedEof => { - break; - } - _ => { - return Err(Error::Incomplete(err)); - } - }, + Err(err) => match err.kind() { + ErrorKind::UnexpectedEof => { + break; + } _ => { - return Err(err); + return Err(Error::Incomplete(err)); } }, }; @@ -56,16 +51,17 @@ impl NbtCompound { Ok(compound) } - pub fn serialize_content(&self, w: &mut WriteAdaptor) -> Result<(), Error> + pub fn serialize_content(&self, w: &mut WriteHelper) -> Result<(), Error> where W: Write, { for (name, tag) in &self.child_tags { - w.write_u8_be(tag.get_type_id())?; + w.write_u8_be(tag.get_type_id()) + .map_err(Error::Incomplete)?; NbtTag::String(name.clone()).serialize_data(w)?; tag.serialize_data(w)?; } - w.write_u8_be(END_ID)?; + w.write_u8_be(END_ID).map_err(Error::Incomplete)?; Ok(()) } diff --git a/pumpkin-nbt/src/deserializer.rs b/pumpkin-nbt/src/deserializer.rs index f2879cdf2..e5a156e64 100644 --- a/pumpkin-nbt/src/deserializer.rs +++ b/pumpkin-nbt/src/deserializer.rs @@ -5,104 +5,9 @@ use serde::{forward_to_deserialize_any, Deserialize}; pub type Result = std::result::Result; -#[derive(Debug)] -pub struct ReadAdaptor { - reader: R, -} - -impl ReadAdaptor { - pub fn new(r: R) -> Self { - Self { reader: r } - } -} - -impl ReadAdaptor { - //TODO: Macroize this - pub fn get_u8_be(&mut self) -> Result { - let mut buf = [0u8]; - self.reader - .read_exact(&mut buf) - .map_err(Error::Incomplete)?; - - Ok(u8::from_be_bytes(buf)) - } - - pub fn get_i8_be(&mut self) -> Result { - let mut buf = [0u8]; - self.reader - .read_exact(&mut buf) - .map_err(Error::Incomplete)?; - - Ok(i8::from_be_bytes(buf)) - } - - pub fn get_i16_be(&mut self) -> Result { - let mut buf = [0u8; 2]; - self.reader - .read_exact(&mut buf) - .map_err(Error::Incomplete)?; - - Ok(i16::from_be_bytes(buf)) - } - - pub fn get_u16_be(&mut self) -> Result { - let mut buf = [0u8; 2]; - self.reader - .read_exact(&mut buf) - .map_err(Error::Incomplete)?; - - Ok(u16::from_be_bytes(buf)) - } - - pub fn get_i32_be(&mut self) -> Result { - let mut buf = [0u8; 4]; - self.reader - .read_exact(&mut buf) - .map_err(Error::Incomplete)?; - - Ok(i32::from_be_bytes(buf)) - } - - pub fn get_i64_be(&mut self) -> Result { - let mut buf = [0u8; 8]; - self.reader - .read_exact(&mut buf) - .map_err(Error::Incomplete)?; - - Ok(i64::from_be_bytes(buf)) - } - - pub fn get_f32_be(&mut self) -> Result { - let mut buf = [0u8; 4]; - self.reader - .read_exact(&mut buf) - .map_err(Error::Incomplete)?; - - Ok(f32::from_be_bytes(buf)) - } - - pub fn get_f64_be(&mut self) -> Result { - let mut buf = [0u8; 8]; - self.reader - .read_exact(&mut buf) - .map_err(Error::Incomplete)?; - - Ok(f64::from_be_bytes(buf)) - } - - pub fn read_boxed_slice(&mut self, count: usize) -> Result> { - let mut buf = vec![0u8; count]; - self.reader - .read_exact(&mut buf) - .map_err(Error::Incomplete)?; - - Ok(buf.into()) - } -} - #[derive(Debug)] pub struct Deserializer { - input: ReadAdaptor, + input: ReadHelper, tag_to_deserialize: Option, in_list: bool, is_named: bool, @@ -111,7 +16,7 @@ pub struct Deserializer { impl Deserializer { pub fn new(input: R, is_named: bool) -> Self { Deserializer { - input: ReadAdaptor { reader: input }, + input: ReadHelper::new(input), tag_to_deserialize: None, in_list: false, is_named, @@ -152,7 +57,7 @@ impl<'de, R: Read> de::Deserializer<'de> for &mut Deserializer { let tag_to_deserialize = self.tag_to_deserialize.unwrap(); let list_type = match tag_to_deserialize { - LIST_ID => Some(self.input.get_u8_be()?), + LIST_ID => Some(self.input.get_u8_be().map_err(Error::Incomplete)?), INT_ARRAY_ID => Some(INT_ID), LONG_ARRAY_ID => Some(LONG_ID), BYTE_ARRAY_ID => Some(BYTE_ID), @@ -160,7 +65,7 @@ impl<'de, R: Read> de::Deserializer<'de> for &mut Deserializer { }; if let Some(list_type) = list_type { - let remaining_values = self.input.get_i32_be()?; + let remaining_values = self.input.get_i32_be().map_err(Error::Incomplete)?; if remaining_values < 0 { return Err(Error::NegativeLength(remaining_values)); } @@ -197,7 +102,7 @@ impl<'de, R: Read> de::Deserializer<'de> for &mut Deserializer { V: Visitor<'de>, { if self.in_list { - let value = self.input.get_u8_be()?; + let value = self.input.get_u8_be().map_err(Error::Incomplete)?; visitor.visit_u8::(value) } else { Err(Error::UnsupportedType( @@ -238,7 +143,7 @@ impl<'de, R: Read> de::Deserializer<'de> for &mut Deserializer { V: Visitor<'de>, { if self.tag_to_deserialize.unwrap() == BYTE_ID { - let value = self.input.get_u8_be()?; + let value = self.input.get_u8_be().map_err(Error::Incomplete)?; if value != 0 { visitor.visit_bool(true) } else { @@ -275,7 +180,7 @@ impl<'de, R: Read> de::Deserializer<'de> for &mut Deserializer { V: Visitor<'de>, { if self.tag_to_deserialize.is_none() { - let next_byte = self.input.get_u8_be()?; + let next_byte = self.input.get_u8_be().map_err(Error::Incomplete)?; if next_byte != COMPOUND_ID { return Err(Error::NoRootCompound(next_byte)); } @@ -326,7 +231,7 @@ impl<'de, R: Read> MapAccess<'de> for CompoundAccess<'_, R> { where K: DeserializeSeed<'de>, { - let tag = self.de.input.get_u8_be()?; + let tag = self.de.input.get_u8_be().map_err(Error::Incomplete)?; self.de.tag_to_deserialize = Some(tag); if tag == END_ID { diff --git a/pumpkin-nbt/src/lib.rs b/pumpkin-nbt/src/lib.rs index 9ad89268b..bec1e5c8b 100644 --- a/pumpkin-nbt/src/lib.rs +++ b/pumpkin-nbt/src/lib.rs @@ -6,10 +6,9 @@ use std::{ use bytes::Bytes; use compound::NbtCompound; -use deserializer::ReadAdaptor; -use serde::{de, ser}; +use pumpkin_util::{ReadHelper, WriteHelper}; +use serde::{de, ser, Serialize}; use serde::{Deserialize, Deserializer}; -use serializer::WriteAdaptor; use tag::NbtTag; use thiserror::Error; @@ -66,6 +65,24 @@ impl de::Error for Error { } } +#[derive(Deserialize, Serialize, Debug, Clone)] +#[serde(rename = "nbt_long_array", transparent)] +/// Use this value to tell the serializer to use a specific array type instead of the generic array +/// type +pub struct NbtLongArray(pub Box<[i64]>); + +#[derive(Deserialize, Serialize, Debug, Clone)] +#[serde(rename = "nbt_int_array", transparent)] +/// Use this value to tell the serializer to use a specific array type instead of the generic array +/// type +pub struct NbtIntArray(pub Box<[i32]>); + +#[derive(Deserialize, Serialize, Debug, Clone)] +#[serde(rename = "nbt_byte_array", transparent)] +/// Use this value to tell the serializer to use a specific array type instead of the generic array +/// type +pub struct NbtByteArray(pub Box<[u8]>); + #[derive(Clone, Debug, Default, PartialEq, PartialOrd)] pub struct Nbt { pub name: String, @@ -80,11 +97,11 @@ impl Nbt { } } - pub fn read(reader: &mut ReadAdaptor) -> Result + pub fn read(reader: &mut ReadHelper) -> Result where R: Read, { - let tag_type_id = reader.get_u8_be()?; + let tag_type_id = reader.get_u8_be().map_err(Error::Incomplete)?; if tag_type_id != COMPOUND_ID { return Err(Error::NoRootCompound(tag_type_id)); @@ -97,11 +114,11 @@ impl Nbt { } /// Reads NBT tag, that doesn't contain the name of root compound. - pub fn read_unnamed(reader: &mut ReadAdaptor) -> Result + pub fn read_unnamed(reader: &mut ReadHelper) -> Result where R: Read, { - let tag_type_id = reader.get_u8_be()?; + let tag_type_id = reader.get_u8_be().map_err(Error::Incomplete)?; if tag_type_id != COMPOUND_ID { return Err(Error::NoRootCompound(tag_type_id)); @@ -115,7 +132,7 @@ impl Nbt { pub fn write(&self) -> Bytes { let mut bytes = Vec::new(); - let mut writer = WriteAdaptor::new(&mut bytes); + let mut writer = WriteHelper::new(&mut bytes); writer.write_u8_be(COMPOUND_ID).unwrap(); NbtTag::String(self.name.to_string()) .serialize_data(&mut writer) @@ -133,7 +150,7 @@ impl Nbt { /// Writes NBT tag, without name of root compound. pub fn write_unnamed(&self) -> Bytes { let mut bytes = Vec::new(); - let mut writer = WriteAdaptor::new(&mut bytes); + let mut writer = WriteHelper::new(&mut bytes); writer.write_u8_be(COMPOUND_ID).unwrap(); self.root_tag.serialize_content(&mut writer).unwrap(); @@ -177,9 +194,9 @@ impl AsMut for Nbt { } } -pub fn get_nbt_string(bytes: &mut ReadAdaptor) -> Result { - let len = bytes.get_u16_be()? as usize; - let string_bytes = bytes.read_boxed_slice(len)?; +pub fn get_nbt_string(bytes: &mut ReadHelper) -> Result { + let len = bytes.get_u16_be().map_err(Error::Incomplete)? as usize; + let string_bytes = bytes.read_boxed_slice(len).map_err(Error::Incomplete)?; let string = cesu8::from_java_cesu8(&string_bytes).map_err(|_| Error::Cesu8DecodingError)?; Ok(string.to_string()) } @@ -216,13 +233,16 @@ impl_array!(BytesArray, "byte"); mod test { use std::sync::LazyLock; + use fastnbt::SerOpts; use flate2::read::GzDecoder; use serde::{Deserialize, Serialize}; + use pumpkin_util::text::{color::NamedColor, TextComponent}; use pumpkin_world::world_info::{DataPacks, LevelData, WorldGenSettings, WorldVersion}; use crate::deserializer::from_bytes; use crate::serializer::to_bytes; + use crate::serializer::to_bytes_named; use crate::BytesArray; use crate::IntArray; use crate::LongArray; @@ -330,8 +350,160 @@ mod test { }, }); + #[test] + fn test_simple_ser_de_named() { + let name = String::from("Test"); + let test = Test { + byte: 123, + short: 1342, + int: 4313, + long: 34, + float: 1.00, + string: "Hello test".to_string(), + }; + + let mut bytes = Vec::new(); + to_bytes_named(&test, name, &mut bytes).unwrap(); + let recreated_struct: Test = from_bytes(&bytes[..]).unwrap(); + + assert_eq!(test, recreated_struct); + } + + #[test] + fn test_simple_ser_de_array_named() { + let name = String::from("Test"); + let test = TestArray { + byte_array: vec![0, 3, 2], + int_array: vec![13, 1321, 2], + long_array: vec![1, 0, 200301, 1], + }; + + let mut bytes = Vec::new(); + to_bytes_named(&test, name, &mut bytes).unwrap(); + let recreated_struct: TestArray = from_bytes(&bytes[..]).unwrap(); + + assert_eq!(test, recreated_struct); + } + + #[derive(Serialize, Deserialize, PartialEq, Debug)] + struct Egg { + food: String, + } + + #[derive(Serialize, Deserialize, PartialEq, Debug)] + struct Breakfast { + food: Egg, + } + + #[derive(Serialize, Deserialize, PartialEq, Debug)] + struct TestList { + option: Option, + nested_compound: Breakfast, + compounds: Vec, + list_string: Vec, + empty: Vec, + } + + #[test] + fn test_list() { + let test1 = Test { + byte: 123, + short: 1342, + int: 4313, + long: 34, + float: 1.00, + string: "Hello test".to_string(), + }; + + let test2 = Test { + byte: 13, + short: 342, + int: -4313, + long: -132334, + float: -69.420, + string: "Hello compounds".to_string(), + }; + + let list_compound = TestList { + option: Some(Egg { + food: "Skibid".to_string(), + }), + nested_compound: Breakfast { + food: Egg { + food: "Over easy".to_string(), + }, + }, + compounds: vec![test1, test2], + list_string: vec!["".to_string(), "abcbcbcbbc".to_string()], + empty: vec![], + }; + + let mut bytes = Vec::new(); + to_bytes_unnamed(&list_compound, &mut bytes).unwrap(); + let recreated_struct: TestList = from_bytes_unnamed(&bytes[..]).unwrap(); + assert_eq!(list_compound, recreated_struct); + } + + #[test] + fn test_list_named() { + let test1 = Test { + byte: 123, + short: 1342, + int: 4313, + long: 34, + float: 1.00, + string: "Hello test".to_string(), + }; + + let test2 = Test { + byte: 13, + short: 342, + int: -4313, + long: -132334, + float: -69.420, + string: "Hello compounds".to_string(), + }; + + let list_compound = TestList { + option: None, + nested_compound: Breakfast { + food: Egg { + food: "Over easy".to_string(), + }, + }, + compounds: vec![test1, test2], + list_string: vec!["".to_string(), "abcbcbcbbc".to_string()], + empty: vec![], + }; + + let mut bytes = Vec::new(); + to_bytes_named(&list_compound, "a".to_string(), &mut bytes).unwrap(); + let recreated_struct: TestList = from_bytes(&bytes[..]).unwrap(); + assert_eq!(list_compound, recreated_struct); + } + // TODO: More robust tests + #[test] + fn test_serialize_text_component() { + let msg_comp = TextComponent::translate( + "multiplayer.player.joined", + [TextComponent::text("NAME".to_string())].into(), + ) + .color_named(NamedColor::Yellow); + + let mut bytes = Vec::new(); + to_bytes_unnamed(&msg_comp, &mut bytes).unwrap(); + + let bytes_known_good = fastnbt::to_bytes_with_opts( + &msg_comp.0, + SerOpts::new().serialize_root_compound_name(false), + ) + .unwrap(); + + assert_eq!(bytes, bytes_known_good); + } + #[test] fn test_deserialize_level_dat() { let raw_compressed_nbt = include_bytes!("../assets/level.dat"); diff --git a/pumpkin-nbt/src/serializer.rs b/pumpkin-nbt/src/serializer.rs index 99fc4e477..6f5fec5d5 100644 --- a/pumpkin-nbt/src/serializer.rs +++ b/pumpkin-nbt/src/serializer.rs @@ -1,3 +1,4 @@ +use pumpkin_util::WriteHelper; use serde::ser::Impossible; use serde::{ser, Serialize}; use std::io::Write; @@ -10,82 +11,10 @@ use crate::{ pub type Result = std::result::Result; -#[derive(Debug)] -pub struct WriteAdaptor { - writer: W, -} - -impl WriteAdaptor { - pub fn new(w: W) -> Self { - Self { writer: w } - } -} - -impl WriteAdaptor { - //TODO: Macroize this - pub fn write_u8_be(&mut self, value: u8) -> Result<()> { - let buf = value.to_be_bytes(); - self.writer.write_all(&buf).map_err(Error::Incomplete)?; - Ok(()) - } - - pub fn write_i8_be(&mut self, value: i8) -> Result<()> { - let buf = value.to_be_bytes(); - self.writer.write_all(&buf).map_err(Error::Incomplete)?; - Ok(()) - } - - pub fn write_u16_be(&mut self, value: u16) -> Result<()> { - let buf = value.to_be_bytes(); - self.writer.write_all(&buf).map_err(Error::Incomplete)?; - Ok(()) - } - - pub fn write_i16_be(&mut self, value: i16) -> Result<()> { - let buf = value.to_be_bytes(); - self.writer.write_all(&buf).map_err(Error::Incomplete)?; - Ok(()) - } - - pub fn write_i32_be(&mut self, value: i32) -> Result<()> { - let buf = value.to_be_bytes(); - self.writer.write_all(&buf).map_err(Error::Incomplete)?; - Ok(()) - } - - pub fn write_i64_be(&mut self, value: i64) -> Result<()> { - let buf = value.to_be_bytes(); - self.writer.write_all(&buf).map_err(Error::Incomplete)?; - Ok(()) - } - - pub fn write_f32_be(&mut self, value: f32) -> Result<()> { - let buf = value.to_be_bytes(); - self.writer.write_all(&buf).map_err(Error::Incomplete)?; - Ok(()) - } - - pub fn write_f64_be(&mut self, value: f64) -> Result<()> { - let buf = value.to_be_bytes(); - self.writer.write_all(&buf).map_err(Error::Incomplete)?; - Ok(()) - } - - pub fn write_slice(&mut self, value: &[u8]) -> Result<()> { - self.writer.write_all(value).map_err(Error::Incomplete)?; - Ok(()) - } -} - -pub trait SerializeChild { - fn serialize_child(&self, serializer: S) -> std::result::Result - where - S: ser::Serializer; -} - pub struct Serializer { - output: WriteAdaptor, + output: WriteHelper, state: State, + handled_root: bool, } // NBT has a different order of things, then most other formats @@ -99,19 +28,19 @@ enum State { MapKey, FirstListElement { len: i32 }, ListElement, - Array { name: String, array_type: String }, + Array { name: String, array_type: u8 }, } impl Serializer { fn parse_state(&mut self, tag: u8) -> Result<()> { match &mut self.state { State::Named(name) | State::Array { name, .. } => { - self.output.write_u8_be(tag)?; + self.output.write_u8_be(tag).map_err(Error::Incomplete)?; NbtTag::String(name.clone()).serialize_data(&mut self.output)?; } State::FirstListElement { len } => { - self.output.write_u8_be(tag)?; - self.output.write_i32_be(*len)?; + self.output.write_u8_be(tag).map_err(Error::Incomplete)?; + self.output.write_i32_be(*len).map_err(Error::Incomplete)?; } State::MapKey => { if tag != STRING_ID { @@ -121,33 +50,38 @@ impl Serializer { } } State::ListElement => {} - _ => return Err(Error::SerdeError("Invalid Serializer state!".to_string())), + State::Root(root_name) => { + if self.handled_root { + return Err(Error::SerdeError( + "Invalid state: already handled root component!".to_string(), + )); + } else { + if tag != COMPOUND_ID { + return Err(Error::SerdeError( + "Invalid state: root is not a compound!".to_string(), + )); + } + self.handled_root = true; + self.output.write_u8_be(tag).map_err(Error::Incomplete)?; + if let Some(root_name) = root_name { + NbtTag::String(root_name.clone()).serialize_data(&mut self.output)?; + } + } + } }; Ok(()) } } -/// Serializes struct using Serde Serializer to unnamed (network) NBT (Exclusive to TextComponent) -pub fn to_bytes_text_component(value: &T, w: impl Write) -> Result<()> -where - T: SerializeChild, -{ - let mut serializer = Serializer { - output: WriteAdaptor { writer: w }, - state: State::Root(None), - }; - value.serialize_child(&mut serializer)?; - Ok(()) -} - /// Serializes struct using Serde Serializer to unnamed (network) NBT pub fn to_bytes_unnamed(value: &T, w: impl Write) -> Result<()> where T: Serialize, { let mut serializer = Serializer { - output: WriteAdaptor { writer: w }, + output: WriteHelper::new(w), state: State::Root(None), + handled_root: false, }; value.serialize(&mut serializer)?; Ok(()) @@ -159,8 +93,9 @@ where T: Serialize, { let mut serializer = Serializer { - output: WriteAdaptor { writer: w }, + output: WriteHelper::new(w), state: State::Root(Some(name)), + handled_root: false, }; value.serialize(&mut serializer)?; Ok(()) @@ -192,25 +127,25 @@ impl ser::Serializer for &mut Serializer { fn serialize_i8(self, v: i8) -> Result<()> { self.parse_state(BYTE_ID)?; - self.output.write_i8_be(v)?; + self.output.write_i8_be(v).map_err(Error::Incomplete)?; Ok(()) } fn serialize_i16(self, v: i16) -> Result<()> { self.parse_state(SHORT_ID)?; - self.output.write_i16_be(v)?; + self.output.write_i16_be(v).map_err(Error::Incomplete)?; Ok(()) } fn serialize_i32(self, v: i32) -> Result<()> { self.parse_state(INT_ID)?; - self.output.write_i32_be(v)?; + self.output.write_i32_be(v).map_err(Error::Incomplete)?; Ok(()) } fn serialize_i64(self, v: i64) -> Result<()> { self.parse_state(LONG_ID)?; - self.output.write_i64_be(v)?; + self.output.write_i64_be(v).map_err(Error::Incomplete)?; Ok(()) } @@ -221,7 +156,7 @@ impl ser::Serializer for &mut Serializer { )), _ => { self.parse_state(BYTE_ID)?; - self.output.write_u8_be(v)?; + self.output.write_u8_be(v).map_err(Error::Incomplete)?; Ok(()) } } @@ -247,13 +182,13 @@ impl ser::Serializer for &mut Serializer { fn serialize_f32(self, v: f32) -> Result<()> { self.parse_state(FLOAT_ID)?; - self.output.write_f32_be(v)?; + self.output.write_f32_be(v).map_err(Error::Incomplete)?; Ok(()) } fn serialize_f64(self, v: f64) -> Result<()> { self.parse_state(DOUBLE_ID)?; - self.output.write_f64_be(v)?; + self.output.write_f64_be(v).map_err(Error::Incomplete)?; Ok(()) } @@ -264,25 +199,30 @@ impl ser::Serializer for &mut Serializer { fn serialize_str(self, v: &str) -> Result<()> { self.parse_state(STRING_ID)?; - NbtTag::String(v.to_string()).serialize_data(&mut self.output)?; - if self.state == State::MapKey { self.state = State::Named(v.to_string()); + } else { + NbtTag::String(v.to_string()).serialize_data(&mut self.output)?; } + Ok(()) } fn serialize_bytes(self, v: &[u8]) -> Result<()> { self.parse_state(LIST_ID)?; - self.output.write_u8_be(BYTE_ID)?; + self.output + .write_u8_be(BYTE_ID) + .map_err(Error::Incomplete)?; let len = v.len(); if len > i32::MAX as usize { return Err(Error::LargeLength(len)); } - self.output.write_i32_be(len as i32)?; - self.output.write_slice(v)?; + self.output + .write_i32_be(len as i32) + .map_err(Error::Incomplete)?; + self.output.write_slice(v).map_err(Error::Incomplete)?; Ok(()) } @@ -316,41 +256,67 @@ impl ser::Serializer for &mut Serializer { Ok(()) } - fn serialize_newtype_struct(self, _name: &'static str, _value: &T) -> Result<()> + fn serialize_newtype_struct(self, name: &'static str, value: &T) -> Result<()> where T: ?Sized + Serialize, { - Err(Error::UnsupportedType("newtype struct".to_string())) + if name == "nbt_long_array" { + let name = match self.state { + State::Named(ref name) => name.clone(), + _ => { + return Err(Error::SerdeError( + "Invalid Serializer state! (newtype variant)".to_string(), + )) + } + }; + + self.state = State::Array { + name, + array_type: LONG_ARRAY_ID, + }; + } else if name == "nbt_int_array" { + let name = match self.state { + State::Named(ref name) => name.clone(), + _ => { + return Err(Error::SerdeError( + "Invalid Serializer state! (newtype variant)".to_string(), + )) + } + }; + + self.state = State::Array { + name, + array_type: INT_ARRAY_ID, + }; + } else if name == "nbt_byte_array" { + let name = match self.state { + State::Named(ref name) => name.clone(), + _ => { + return Err(Error::SerdeError( + "Invalid Serializer state! (newtype variant)".to_string(), + )) + } + }; + + self.state = State::Array { + name, + array_type: BYTE_ARRAY_ID, + }; + } + value.serialize(self) } fn serialize_newtype_variant( self, - name: &'static str, + _name: &'static str, _variant_index: u32, - variant: &'static str, + _variant: &'static str, value: &T, ) -> Result<()> where T: ?Sized + Serialize, { - if name != "nbt_array" { - return Err(Error::SerdeError( - "new_type variant supports only nbt_array".to_string(), - )); - } - - let name = match self.state { - State::Named(ref name) => name.clone(), - _ => return Err(Error::SerdeError("Invalid Serializer state!".to_string())), - }; - - self.state = State::Array { - name, - array_type: variant.to_string(), - }; - value.serialize(self)?; - Ok(()) } @@ -366,19 +332,19 @@ impl ser::Serializer for &mut Serializer { match &mut self.state { State::Array { array_type, .. } => { - let id = match array_type.as_str() { - "byte" => BYTE_ARRAY_ID, - "int" => INT_ARRAY_ID, - "long" => LONG_ARRAY_ID, + let id = match *array_type { + BYTE_ARRAY_ID | INT_ARRAY_ID | LONG_ARRAY_ID => *array_type, _ => { return Err(Error::SerdeError( "Array supports only byte, int, long".to_string(), )) } }; - self.parse_state(id)?; - self.output.write_i32_be(len as i32)?; + self.parse_state(id)?; + self.output + .write_i32_be(len as i32) + .map_err(Error::Incomplete)?; self.state = State::ListElement; } _ => { @@ -387,8 +353,8 @@ impl ser::Serializer for &mut Serializer { if len == 0 { // If we have no elements, FirstListElement state will never be invoked; so // write the list type and length here. - self.output.write_u8_be(END_ID)?; - self.output.write_i32_be(0)?; + self.output.write_u8_be(END_ID).map_err(Error::Incomplete)?; + self.output.write_i32_be(0).map_err(Error::Incomplete)?; } } } @@ -424,22 +390,15 @@ impl ser::Serializer for &mut Serializer { } else if let State::ListElement = self.state { return Ok(self); } else { - self.output.write_u8_be(COMPOUND_ID)?; + self.output + .write_u8_be(COMPOUND_ID) + .map_err(Error::Incomplete)?; } Ok(self) } fn serialize_struct(self, _name: &'static str, _len: usize) -> Result { - match &mut self.state { - State::Root(root_name) => { - self.output.write_u8_be(COMPOUND_ID)?; - if let Some(root_name) = root_name { - NbtTag::String(root_name.clone()).serialize_data(&mut self.output)?; - } - } - _ => self.parse_state(COMPOUND_ID)?, - } - + self.parse_state(COMPOUND_ID)?; Ok(self) } @@ -489,7 +448,7 @@ impl ser::SerializeStruct for &mut Serializer { } fn end(self) -> Result<()> { - self.output.write_u8_be(END_ID)?; + self.output.write_u8_be(END_ID).map_err(Error::Incomplete)?; Ok(()) } } @@ -514,7 +473,7 @@ impl ser::SerializeMap for &mut Serializer { } fn end(self) -> Result<()> { - self.output.write_u8_be(END_ID)?; + self.output.write_u8_be(END_ID).map_err(Error::Incomplete)?; Ok(()) } } diff --git a/pumpkin-nbt/src/tag.rs b/pumpkin-nbt/src/tag.rs index 3503a8770..eeb84a01d 100644 --- a/pumpkin-nbt/src/tag.rs +++ b/pumpkin-nbt/src/tag.rs @@ -1,9 +1,6 @@ +use crate::*; use compound::NbtCompound; -use deserializer::ReadAdaptor; use io::Read; -use serializer::WriteAdaptor; - -use crate::*; #[derive(Clone, Debug, PartialEq, PartialOrd)] #[repr(u8)] @@ -30,35 +27,36 @@ impl NbtTag { unsafe { *(self as *const Self as *const u8) } } - pub fn serialize(&self, w: &mut WriteAdaptor) -> serializer::Result<()> + pub fn serialize(&self, w: &mut WriteHelper) -> serializer::Result<()> where W: Write, { - w.write_u8_be(self.get_type_id())?; + w.write_u8_be(self.get_type_id()) + .map_err(Error::Incomplete)?; self.serialize_data(w)?; Ok(()) } - pub fn serialize_data(&self, w: &mut WriteAdaptor) -> serializer::Result<()> + pub fn serialize_data(&self, w: &mut WriteHelper) -> serializer::Result<()> where W: Write, { match self { NbtTag::End => {} - NbtTag::Byte(byte) => w.write_i8_be(*byte)?, - NbtTag::Short(short) => w.write_i16_be(*short)?, - NbtTag::Int(int) => w.write_i32_be(*int)?, - NbtTag::Long(long) => w.write_i64_be(*long)?, - NbtTag::Float(float) => w.write_f32_be(*float)?, - NbtTag::Double(double) => w.write_f64_be(*double)?, + NbtTag::Byte(byte) => w.write_i8_be(*byte).map_err(Error::Incomplete)?, + NbtTag::Short(short) => w.write_i16_be(*short).map_err(Error::Incomplete)?, + NbtTag::Int(int) => w.write_i32_be(*int).map_err(Error::Incomplete)?, + NbtTag::Long(long) => w.write_i64_be(*long).map_err(Error::Incomplete)?, + NbtTag::Float(float) => w.write_f32_be(*float).map_err(Error::Incomplete)?, + NbtTag::Double(double) => w.write_f64_be(*double).map_err(Error::Incomplete)?, NbtTag::ByteArray(byte_array) => { let len = byte_array.len(); if len > i32::MAX as usize { return Err(Error::LargeLength(len)); } - w.write_i32_be(len as i32)?; - w.write_slice(byte_array)?; + w.write_i32_be(len as i32).map_err(Error::Incomplete)?; + w.write_slice(byte_array).map_err(Error::Incomplete)?; } NbtTag::String(string) => { let java_string = cesu8::to_java_cesu8(string); @@ -67,8 +65,8 @@ impl NbtTag { return Err(Error::LargeLength(len)); } - w.write_u16_be(len as u16)?; - w.write_slice(&java_string)?; + w.write_u16_be(len as u16).map_err(Error::Incomplete)?; + w.write_slice(&java_string).map_err(Error::Incomplete)?; } NbtTag::List(list) => { let len = list.len(); @@ -76,8 +74,9 @@ impl NbtTag { return Err(Error::LargeLength(len)); } - w.write_u8_be(list.first().unwrap_or(&NbtTag::End).get_type_id())?; - w.write_i32_be(len as i32)?; + w.write_u8_be(list.first().unwrap_or(&NbtTag::End).get_type_id()) + .map_err(Error::Incomplete)?; + w.write_i32_be(len as i32).map_err(Error::Incomplete)?; for nbt_tag in list { nbt_tag.serialize_data(w)?; } @@ -91,9 +90,9 @@ impl NbtTag { return Err(Error::LargeLength(len)); } - w.write_i32_be(len as i32)?; + w.write_i32_be(len as i32).map_err(Error::Incomplete)?; for int in int_array { - w.write_i32_be(*int)?; + w.write_i32_be(*int).map_err(Error::Incomplete)?; } } NbtTag::LongArray(long_array) => { @@ -102,63 +101,63 @@ impl NbtTag { return Err(Error::LargeLength(len)); } - w.write_i32_be(len as i32)?; + w.write_i32_be(len as i32).map_err(Error::Incomplete)?; for long in long_array { - w.write_i64_be(*long)?; + w.write_i64_be(*long).map_err(Error::Incomplete)?; } } }; Ok(()) } - pub fn deserialize(reader: &mut ReadAdaptor) -> Result + pub fn deserialize(reader: &mut ReadHelper) -> Result where R: Read, { - let tag_id = reader.get_u8_be()?; + let tag_id = reader.get_u8_be().map_err(Error::Incomplete)?; Self::deserialize_data(reader, tag_id) } - pub fn deserialize_data(reader: &mut ReadAdaptor, tag_id: u8) -> Result + pub fn deserialize_data(reader: &mut ReadHelper, tag_id: u8) -> Result where R: Read, { match tag_id { END_ID => Ok(NbtTag::End), BYTE_ID => { - let byte = reader.get_i8_be()?; + let byte = reader.get_i8_be().map_err(Error::Incomplete)?; Ok(NbtTag::Byte(byte)) } SHORT_ID => { - let short = reader.get_i16_be()?; + let short = reader.get_i16_be().map_err(Error::Incomplete)?; Ok(NbtTag::Short(short)) } INT_ID => { - let int = reader.get_i32_be()?; + let int = reader.get_i32_be().map_err(Error::Incomplete)?; Ok(NbtTag::Int(int)) } LONG_ID => { - let long = reader.get_i64_be()?; + let long = reader.get_i64_be().map_err(Error::Incomplete)?; Ok(NbtTag::Long(long)) } FLOAT_ID => { - let float = reader.get_f32_be()?; + let float = reader.get_f32_be().map_err(Error::Incomplete)?; Ok(NbtTag::Float(float)) } DOUBLE_ID => { - let double = reader.get_f64_be()?; + let double = reader.get_f64_be().map_err(Error::Incomplete)?; Ok(NbtTag::Double(double)) } BYTE_ARRAY_ID => { - let len = reader.get_i32_be()? as usize; - let byte_array = reader.read_boxed_slice(len)?; + let len = reader.get_i32_be().map_err(Error::Incomplete)? as usize; + let byte_array = reader.read_boxed_slice(len).map_err(Error::Incomplete)?; Ok(NbtTag::ByteArray(byte_array)) } STRING_ID => Ok(NbtTag::String(get_nbt_string(reader)?)), LIST_ID => { - let tag_type_id = reader.get_u8_be()?; - let len = reader.get_i32_be()?; + let tag_type_id = reader.get_u8_be().map_err(Error::Incomplete)?; + let len = reader.get_i32_be().map_err(Error::Incomplete)?; if len < 0 { return Err(Error::NegativeLength(len)); } @@ -173,7 +172,7 @@ impl NbtTag { } COMPOUND_ID => Ok(NbtTag::Compound(NbtCompound::deserialize_content(reader)?)), INT_ARRAY_ID => { - let len = reader.get_i32_be()?; + let len = reader.get_i32_be().map_err(Error::Incomplete)?; if len < 0 { return Err(Error::NegativeLength(len)); } @@ -181,13 +180,13 @@ impl NbtTag { let len = len as usize; let mut int_array = Vec::with_capacity(len); for _ in 0..len { - let int = reader.get_i32_be()?; + let int = reader.get_i32_be().map_err(Error::Incomplete)?; int_array.push(int); } Ok(NbtTag::IntArray(int_array.into_boxed_slice())) } LONG_ARRAY_ID => { - let len = reader.get_i32_be()?; + let len = reader.get_i32_be().map_err(Error::Incomplete)?; if len < 0 { return Err(Error::NegativeLength(len)); } @@ -195,7 +194,7 @@ impl NbtTag { let len = len as usize; let mut long_array = Vec::with_capacity(len); for _ in 0..len { - let long = reader.get_i64_be()?; + let long = reader.get_i64_be().map_err(Error::Incomplete)?; long_array.push(long); } Ok(NbtTag::LongArray(long_array.into_boxed_slice())) diff --git a/pumpkin-protocol/src/client/config/registry_data.rs b/pumpkin-protocol/src/client/config/registry_data.rs index 0733097bd..0ff760775 100644 --- a/pumpkin-protocol/src/client/config/registry_data.rs +++ b/pumpkin-protocol/src/client/config/registry_data.rs @@ -1,4 +1,4 @@ -use bytes::BufMut; +use bytes::{BufMut, BytesMut}; use pumpkin_data::packet::clientbound::CONFIG_REGISTRY_DATA; use pumpkin_macros::client_packet; use serde::Serialize; diff --git a/pumpkin-protocol/src/client/play/chunk_data.rs b/pumpkin-protocol/src/client/play/chunk_data.rs index dfe4af28e..d270f2a27 100644 --- a/pumpkin-protocol/src/client/play/chunk_data.rs +++ b/pumpkin-protocol/src/client/play/chunk_data.rs @@ -18,10 +18,12 @@ impl ClientPacket for CChunkData<'_> { // Chunk Z buf.put_i32(self.0.position.z); - let mut heightmap_nbt = Vec::new(); - pumpkin_nbt::serializer::to_bytes_unnamed(&self.0.heightmap, &mut heightmap_nbt).unwrap(); + // TODO: IMPLEMENT + /* + let heightmap_nbt = pumpkin_nbt::serializer::to_bytes_unnamed(&self.0.heightmap).unwrap(); // Heightmaps buf.put_slice(&heightmap_nbt); + */ let mut data_buf = BytesMut::new(); self.0.subchunks.array_iter().for_each(|subchunk| { diff --git a/pumpkin-protocol/src/client/play/update_objectives.rs b/pumpkin-protocol/src/client/play/update_objectives.rs index b98fdff7b..1f2a96c8b 100644 --- a/pumpkin-protocol/src/client/play/update_objectives.rs +++ b/pumpkin-protocol/src/client/play/update_objectives.rs @@ -46,10 +46,8 @@ impl ClientPacket for CUpdateObjectives<'_> { } NumberFormat::Styled(style) => { p.put_var_int(&VarInt(1)); - // TODO - let mut style_buf = Vec::new(); - pumpkin_nbt::serializer::to_bytes_unnamed(style, &mut style_buf).unwrap(); - p.put_slice(&style_buf); + // TODO: FIX + // p.put_slice(&pumpkin_nbt::serializer::to_bytes_unnamed(style).unwrap()); } NumberFormat::Fixed(text_component) => { p.put_var_int(&VarInt(2)); diff --git a/pumpkin-protocol/src/lib.rs b/pumpkin-protocol/src/lib.rs index d64ababab..8d6711052 100644 --- a/pumpkin-protocol/src/lib.rs +++ b/pumpkin-protocol/src/lib.rs @@ -82,12 +82,10 @@ pub struct RawPacket { pub bytebuf: Bytes, } -// TODO: Have the input be `impl Write` pub trait ClientPacket: Packet { fn write(&self, bytebuf: &mut impl BufMut); } -// TODO: Have the input be `impl Read` pub trait ServerPacket: Packet + Sized { fn read(bytebuf: &mut impl Buf) -> Result; } diff --git a/pumpkin-registry/Cargo.toml b/pumpkin-registry/Cargo.toml index e227698b8..a0c919cb0 100644 --- a/pumpkin-registry/Cargo.toml +++ b/pumpkin-registry/Cargo.toml @@ -12,4 +12,3 @@ indexmap = { version = "2.7", features = ["serde"] } serde.workspace = true serde_json.workspace = true - diff --git a/pumpkin-registry/src/lib.rs b/pumpkin-registry/src/lib.rs index 9b6e9e035..67e32758c 100644 --- a/pumpkin-registry/src/lib.rs +++ b/pumpkin-registry/src/lib.rs @@ -239,3 +239,6 @@ impl Registry { ] } } + +#[cfg(test)] +mod test {} diff --git a/pumpkin-util/Cargo.toml b/pumpkin-util/Cargo.toml index 0cb0be940..23362a574 100644 --- a/pumpkin-util/Cargo.toml +++ b/pumpkin-util/Cargo.toml @@ -4,7 +4,6 @@ version.workspace = true edition.workspace = true [dependencies] -pumpkin-nbt = { path = "../pumpkin-nbt" } serde.workspace = true serde_json.workspace = true bytes.workspace = true diff --git a/pumpkin-util/src/lib.rs b/pumpkin-util/src/lib.rs index 2e635f1f4..83cfe6fc3 100644 --- a/pumpkin-util/src/lib.rs +++ b/pumpkin-util/src/lib.rs @@ -5,6 +5,8 @@ pub mod random; pub mod text; pub mod translation; +use std::io::{Read, Write}; + pub use gamemode::GameMode; pub use permission::PermissionLvl; @@ -33,3 +35,149 @@ macro_rules! assert_eq_delta { } }; } + +#[derive(Debug)] +pub struct ReadHelper { + reader: R, +} + +impl ReadHelper { + pub fn new(r: R) -> Self { + Self { reader: r } + } +} + +impl ReadHelper { + //TODO: Macroize this + pub fn get_u8_be(&mut self) -> Result { + let mut buf = [0u8]; + self.reader.read_exact(&mut buf)?; + Ok(u8::from_be_bytes(buf)) + } + + pub fn get_i8_be(&mut self) -> Result { + let mut buf = [0u8]; + self.reader.read_exact(&mut buf)?; + Ok(i8::from_be_bytes(buf)) + } + + pub fn get_i16_be(&mut self) -> Result { + let mut buf = [0u8; 2]; + self.reader.read_exact(&mut buf)?; + Ok(i16::from_be_bytes(buf)) + } + + pub fn get_u16_be(&mut self) -> Result { + let mut buf = [0u8; 2]; + self.reader.read_exact(&mut buf)?; + Ok(u16::from_be_bytes(buf)) + } + + pub fn get_i32_be(&mut self) -> Result { + let mut buf = [0u8; 4]; + self.reader.read_exact(&mut buf)?; + Ok(i32::from_be_bytes(buf)) + } + + pub fn get_i64_be(&mut self) -> Result { + let mut buf = [0u8; 8]; + self.reader.read_exact(&mut buf)?; + Ok(i64::from_be_bytes(buf)) + } + + pub fn get_f32_be(&mut self) -> Result { + let mut buf = [0u8; 4]; + self.reader.read_exact(&mut buf)?; + Ok(f32::from_be_bytes(buf)) + } + + pub fn get_f64_be(&mut self) -> Result { + let mut buf = [0u8; 8]; + self.reader.read_exact(&mut buf)?; + Ok(f64::from_be_bytes(buf)) + } + + pub fn read_boxed_slice(&mut self, count: usize) -> Result, std::io::Error> { + let mut buf = vec![0u8; count]; + self.reader.read_exact(&mut buf)?; + Ok(buf.into()) + } + + pub fn read_into_slice(&mut self, buf: &mut [u8]) -> Result<(), std::io::Error> { + self.reader.read_exact(buf)?; + Ok(()) + } +} + +#[derive(Debug)] +pub struct WriteHelper { + writer: W, +} + +impl WriteHelper { + pub fn new(w: W) -> Self { + Self { writer: w } + } +} + +impl WriteHelper { + //TODO: Macroize this + pub fn write_u8_be(&mut self, value: u8) -> Result<(), std::io::Error> { + let buf = value.to_be_bytes(); + self.writer.write_all(&buf)?; + Ok(()) + } + + pub fn write_i8_be(&mut self, value: i8) -> Result<(), std::io::Error> { + let buf = value.to_be_bytes(); + self.writer.write_all(&buf)?; + Ok(()) + } + + pub fn write_u16_be(&mut self, value: u16) -> Result<(), std::io::Error> { + let buf = value.to_be_bytes(); + self.writer.write_all(&buf)?; + Ok(()) + } + + pub fn write_i16_be(&mut self, value: i16) -> Result<(), std::io::Error> { + let buf = value.to_be_bytes(); + self.writer.write_all(&buf)?; + Ok(()) + } + + pub fn write_i32_be(&mut self, value: i32) -> Result<(), std::io::Error> { + let buf = value.to_be_bytes(); + self.writer.write_all(&buf)?; + Ok(()) + } + + pub fn write_i64_be(&mut self, value: i64) -> Result<(), std::io::Error> { + let buf = value.to_be_bytes(); + self.writer.write_all(&buf)?; + Ok(()) + } + + pub fn write_u64_be(&mut self, value: u64) -> Result<(), std::io::Error> { + let buf = value.to_be_bytes(); + self.writer.write_all(&buf)?; + Ok(()) + } + + pub fn write_f32_be(&mut self, value: f32) -> Result<(), std::io::Error> { + let buf = value.to_be_bytes(); + self.writer.write_all(&buf)?; + Ok(()) + } + + pub fn write_f64_be(&mut self, value: f64) -> Result<(), std::io::Error> { + let buf = value.to_be_bytes(); + self.writer.write_all(&buf)?; + Ok(()) + } + + pub fn write_slice(&mut self, value: &[u8]) -> Result<(), std::io::Error> { + self.writer.write_all(value)?; + Ok(()) + } +} diff --git a/pumpkin-util/src/text/mod.rs b/pumpkin-util/src/text/mod.rs index 315a60b69..be986dc51 100644 --- a/pumpkin-util/src/text/mod.rs +++ b/pumpkin-util/src/text/mod.rs @@ -15,7 +15,7 @@ pub mod hover; pub mod style; /// Represents a Text component -#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Hash)] +#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq, Hash)] #[serde(rename_all = "camelCase")] pub struct TextComponent(pub TextComponentBase); @@ -153,29 +153,9 @@ impl TextComponent { } } -impl serde::Serialize for TextComponent { - fn serialize(&self, serializer: S) -> Result - where - S: serde::Serializer, - { - serializer.serialize_bytes(&self.encode()) - } -} - -impl pumpkin_nbt::serializer::SerializeChild for TextComponent { - fn serialize_child(&self, serializer: S) -> Result - where - S: serde::Serializer, - { - self.0.serialize(serializer) - } -} - impl TextComponent { pub fn encode(&self) -> Box<[u8]> { - let mut buf = Vec::new(); - pumpkin_nbt::serializer::to_bytes_text_component(self, &mut buf).unwrap(); - buf.into() + todo!() } pub fn color(mut self, color: Color) -> Self { diff --git a/pumpkin-world/src/chunk/mod.rs b/pumpkin-world/src/chunk/mod.rs index 12267e891..5a9404463 100644 --- a/pumpkin-world/src/chunk/mod.rs +++ b/pumpkin-world/src/chunk/mod.rs @@ -3,7 +3,7 @@ use dashmap::{ DashMap, }; use pumpkin_data::chunk::ChunkStatus; -use pumpkin_nbt::deserializer::from_bytes; +use pumpkin_nbt::{deserializer::from_bytes, NbtLongArray}; use pumpkin_util::math::{ceil_log2, vector2::Vector2}; use serde::{Deserialize, Serialize}; use std::{ @@ -167,10 +167,8 @@ struct PaletteEntry { #[derive(Deserialize, Serialize, Debug, Clone)] #[serde(rename_all = "UPPERCASE")] pub struct ChunkHeightmaps { - // #[serde(with = "LongArray")] - motion_blocking: Box<[i64]>, - // #[serde(with = "LongArray")] - world_surface: Box<[i64]>, + motion_blocking: NbtLongArray, + world_surface: NbtLongArray, } #[derive(Serialize, Deserialize, Debug)] @@ -234,8 +232,8 @@ impl Default for ChunkHeightmaps { fn default() -> Self { Self { // 0 packed into an i64 7 times. - motion_blocking: vec![0; 37].into_boxed_slice(), - world_surface: vec![0; 37].into_boxed_slice(), + motion_blocking: NbtLongArray(vec![0i64; 37].into_boxed_slice()), + world_surface: NbtLongArray(vec![0i64; 37].into_boxed_slice()), } } } diff --git a/pumpkin-world/src/world_info/anvil.rs b/pumpkin-world/src/world_info/anvil.rs index 0040b6161..02adf4074 100644 --- a/pumpkin-world/src/world_info/anvil.rs +++ b/pumpkin-world/src/world_info/anvil.rs @@ -87,7 +87,7 @@ mod test { use super::{AnvilLevelInfo, WorldInfoReader, WorldInfoWriter}; #[test] - fn test_perserve_level_dat_seed() { + fn test_preserve_level_dat_seed() { let seed = 1337; let mut data = LevelData::default();