Skip to content

Commit

Permalink
Added deserialization
Browse files Browse the repository at this point in the history
Also replaced i8 bool's with bool's
  • Loading branch information
Snowiiii committed Nov 16, 2024
1 parent a8a3ef8 commit e5baa7d
Show file tree
Hide file tree
Showing 15 changed files with 21,638 additions and 21,395 deletions.
24,116 changes: 12,058 additions & 12,058 deletions assets/items.json

Large diffs are not rendered by default.

352 changes: 176 additions & 176 deletions assets/synced_registries.json

Large diffs are not rendered by default.

18,156 changes: 9,078 additions & 9,078 deletions assets/tags.json

Large diffs are not rendered by default.

10 changes: 5 additions & 5 deletions pumpkin-core/src/text/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,31 +112,31 @@ impl<'a> TextComponent<'a> {

/// Makes the text bold
pub fn bold(mut self) -> Self {
self.style.bold = Some(1);
self.style.bold = Some(true);
self
}

/// Makes the text italic
pub fn italic(mut self) -> Self {
self.style.italic = Some(1);
self.style.italic = Some(true);
self
}

/// Makes the text underlined
pub fn underlined(mut self) -> Self {
self.style.underlined = Some(1);
self.style.underlined = Some(true);
self
}

/// Makes the text strikethrough
pub fn strikethrough(mut self) -> Self {
self.style.strikethrough = Some(1);
self.style.strikethrough = Some(true);
self
}

/// Makes the text obfuscated
pub fn obfuscated(mut self) -> Self {
self.style.obfuscated = Some(1);
self.style.obfuscated = Some(true);
self
}

Expand Down
24 changes: 10 additions & 14 deletions pumpkin-core/src/text/style.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,23 +13,19 @@ pub struct Style<'a> {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub color: Option<Color>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub bold: Option<u8>,
pub bold: Option<bool>,
/// Whether to render the content in italic.
/// Keep in mind that booleans are represented as bytes in nbt
#[serde(default, skip_serializing_if = "Option::is_none")]
pub italic: Option<u8>,
pub italic: Option<bool>,
/// Whether to render the content in underlined.
/// Keep in mind that booleans are represented as bytes in nbt
#[serde(default, skip_serializing_if = "Option::is_none")]
pub underlined: Option<u8>,
pub underlined: Option<bool>,
/// Whether to render the content in strikethrough.
/// Keep in mind that booleans are represented as bytes in nbt
#[serde(default, skip_serializing_if = "Option::is_none")]
pub strikethrough: Option<u8>,
pub strikethrough: Option<bool>,
/// Whether to render the content in obfuscated.
/// Keep in mind that booleans are represented as bytes in nbt
#[serde(default, skip_serializing_if = "Option::is_none")]
pub obfuscated: Option<u8>,
pub obfuscated: Option<bool>,
/// When the text is shift-clicked by a player, this string is inserted in their chat input. It does not overwrite any existing text the player was writing. This only works in chat messages
#[serde(default, skip_serializing_if = "Option::is_none")]
pub insertion: Option<String>,
Expand All @@ -54,31 +50,31 @@ impl<'a> Style<'a> {

/// Makes the text bold
pub fn bold(mut self) -> Self {
self.bold = Some(1);
self.bold = Some(true);
self
}

/// Makes the text italic
pub fn italic(mut self) -> Self {
self.italic = Some(1);
self.italic = Some(true);
self
}

/// Makes the text underlined
pub fn underlined(mut self) -> Self {
self.underlined = Some(1);
self.underlined = Some(true);
self
}

/// Makes the text strikethrough
pub fn strikethrough(mut self) -> Self {
self.strikethrough = Some(1);
self.strikethrough = Some(true);
self
}

/// Makes the text obfuscated
pub fn obfuscated(mut self) -> Self {
self.obfuscated = Some(1);
self.obfuscated = Some(true);
self
}

Expand Down
8 changes: 4 additions & 4 deletions pumpkin-nbt/src/compound.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::tag::NbtTag;
use crate::{get_nbt_string, Nbt, ReadingError, END_ID};
use crate::{get_nbt_string, Error, Nbt, END_ID};
use bytes::{Buf, BufMut, Bytes, BytesMut};
use std::io::{Cursor, Write};
use std::vec::IntoIter;
Expand All @@ -16,7 +16,7 @@ impl NbtCompound {
}
}

pub fn deserialize_content(bytes: &mut impl Buf) -> Result<NbtCompound, ReadingError> {
pub fn deserialize_content(bytes: &mut impl Buf) -> Result<NbtCompound, Error> {
let mut compound = NbtCompound::new();

while bytes.has_remaining() {
Expand All @@ -25,7 +25,7 @@ impl NbtCompound {
break;
}

let name = get_nbt_string(bytes)?;
let name = get_nbt_string(bytes).map_err(|_| Error::Cesu8DecodingError)?;

if let Ok(tag) = NbtTag::deserialize_data(bytes, tag_id) {
compound.put(name, tag);
Expand All @@ -39,7 +39,7 @@ impl NbtCompound {

pub fn deserialize_content_from_cursor(
cursor: &mut Cursor<&[u8]>,
) -> Result<NbtCompound, ReadingError> {
) -> Result<NbtCompound, Error> {
Self::deserialize_content(cursor)
}

Expand Down
212 changes: 212 additions & 0 deletions pumpkin-nbt/src/deserializer.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,212 @@
use crate::*;
use bytes::{Buf, BytesMut};
use serde::de::{self, DeserializeSeed, MapAccess, SeqAccess, Visitor};
use serde::{forward_to_deserialize_any, Deserialize};
use std::io::Cursor;

pub type Result<T> = std::result::Result<T, Error>;

#[derive(Debug)]
pub struct Deserializer<'de, T> {
input: &'de mut T,
tag_to_deserialize: Option<u8>,
is_named: bool,
}

impl<'de, T: Buf> Deserializer<'de, T> {
pub fn new(input: &'de mut T, is_named: bool) -> Self {
Deserializer {
input,
tag_to_deserialize: None,
is_named,
}
}
}

/// Deserializes struct using Serde Deserializer from unnamed (network) NBT
pub fn from_bytes<'a, T>(s: &'a mut BytesMut) -> Result<T>
where
T: Deserialize<'a>,
{
let mut deserializer = Deserializer::new(s, true);
T::deserialize(&mut deserializer)
}

pub fn from_cursor<'a, T>(cursor: &'a mut Cursor<&[u8]>) -> Result<T>
where
T: Deserialize<'a>,
{
let mut deserializer = Deserializer::new(cursor, true);
T::deserialize(&mut deserializer)
}

/// Deserializes struct using Serde Deserializer from normal NBT
pub fn from_bytes_unnamed<'a, T>(s: &'a mut BytesMut) -> Result<T>
where
T: Deserialize<'a>,
{
let mut deserializer = Deserializer::new(s, false);
T::deserialize(&mut deserializer)
}

pub fn from_cursor_unnamed<'a, T>(cursor: &'a mut Cursor<&[u8]>) -> Result<T>
where
T: Deserialize<'a>,
{
let mut deserializer = Deserializer::new(cursor, false);
T::deserialize(&mut deserializer)
}

impl<'de, 'a, T: Buf> de::Deserializer<'de> for &'a mut Deserializer<'de, T> {
type Error = Error;

forward_to_deserialize_any!(i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 seq char str string bytes byte_buf tuple tuple_struct enum ignored_any unit unit_struct option newtype_struct);

fn deserialize_any<V>(self, visitor: V) -> Result<V::Value>
where
V: Visitor<'de>,
{
let tag_to_deserialize = self.tag_to_deserialize.unwrap();

let list_type = match tag_to_deserialize {
LIST_ID => Some(self.input.get_u8()),
INT_ARRAY_ID => Some(INT_ID),
LONG_ARRAY_ID => Some(LONG_ID),
BYTE_ARRAY_ID => Some(BYTE_ID),
_ => None,
};

if let Some(list_type) = list_type {
let remaining_values = self.input.get_u32();
return visitor.visit_seq(ListAccess {
de: self,
list_type,
remaining_values,
});
}

let result: Result<V::Value> = Ok(
match NbtTag::deserialize_data(self.input, tag_to_deserialize)? {
NbtTag::Byte(value) => visitor.visit_i8::<Error>(value)?,
NbtTag::Short(value) => visitor.visit_i16::<Error>(value)?,
NbtTag::Int(value) => visitor.visit_i32::<Error>(value)?,
NbtTag::Long(value) => visitor.visit_i64::<Error>(value)?,
NbtTag::Float(value) => visitor.visit_f32::<Error>(value)?,
NbtTag::Double(value) => visitor.visit_f64::<Error>(value)?,
NbtTag::String(value) => visitor.visit_string::<Error>(value)?,
_ => unreachable!(),
},
);
self.tag_to_deserialize = None;
result
}

fn deserialize_bool<V>(self, visitor: V) -> Result<V::Value>
where
V: Visitor<'de>,
{
if self.tag_to_deserialize.unwrap() == BYTE_ID {
let value = self.input.get_u8();
if value != 0 {
return visitor.visit_bool(true);
}
}
visitor.visit_bool(false)
}

fn deserialize_map<V>(self, visitor: V) -> Result<V::Value>
where
V: Visitor<'de>,
{
if self.tag_to_deserialize.is_none() {
let next_byte = self.input.get_u8();
if next_byte != COMPOUND_ID {
return Err(Error::NoRootCompound(next_byte));
}

if self.is_named {
// Consume struct name
NbtTag::deserialize(self.input)?;
}
}

let value = visitor.visit_map(CompoundAccess { de: self })?;
Ok(value)
}

fn deserialize_struct<V>(
self,
_name: &'static str,
_fields: &'static [&'static str],
visitor: V,
) -> Result<V::Value>
where
V: Visitor<'de>,
{
self.deserialize_map(visitor)
}

fn deserialize_identifier<V>(self, visitor: V) -> Result<V::Value>
where
V: Visitor<'de>,
{
let str = get_nbt_string(&mut self.input).map_err(|_| Error::Cesu8DecodingError)?;
visitor.visit_string(str)
}

fn is_human_readable(&self) -> bool {
false
}
}

struct CompoundAccess<'a, 'de: 'a, T: Buf> {
de: &'a mut Deserializer<'de, T>,
}

impl<'de, 'a, T: Buf> MapAccess<'de> for CompoundAccess<'a, 'de, T> {
type Error = Error;

fn next_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>>
where
K: DeserializeSeed<'de>,
{
let tag = self.de.input.get_u8();
self.de.tag_to_deserialize = Some(tag);

if tag == END_ID {
return Ok(None);
}

seed.deserialize(&mut *self.de).map(Some)
}

fn next_value_seed<V>(&mut self, seed: V) -> Result<V::Value>
where
V: DeserializeSeed<'de>,
{
seed.deserialize(&mut *self.de)
}
}

struct ListAccess<'a, 'de: 'a, T: Buf> {
de: &'a mut Deserializer<'de, T>,
remaining_values: u32,
list_type: u8,
}

impl<'a, 'de, T: Buf> SeqAccess<'de> for ListAccess<'a, 'de, T> {
type Error = Error;

fn next_element_seed<E>(&mut self, seed: E) -> Result<Option<E::Value>>
where
E: DeserializeSeed<'de>,
{
if self.remaining_values == 0 {
return Ok(None);
}

self.remaining_values -= 1;
self.de.tag_to_deserialize = Some(self.list_type);
seed.deserialize(&mut *self.de).map(Some)
}
}
Loading

0 comments on commit e5baa7d

Please sign in to comment.