()? {
- val |= (i64::from(byte) & 0b01111111) << (i * 7);
- if byte & 0b10000000 == 0 {
- return Ok(VarLong(val));
- }
- } else {
- break;
- }
- }
- Err(de::Error::custom("VarInt was too large"))
- }
- }
-
- deserializer.deserialize_seq(VarLongVisitor)
- }
-}
+use super::{deserializer, serializer, ReadingError};
pub trait Packet {
const PACKET_ID: VarIntType;
@@ -138,14 +13,10 @@ impl ClientPacket for P
where
P: Packet + Serialize,
{
- fn write(&self, bytebuf: &mut ByteBuffer) {
- let mut serializer = serializer::Serializer::new(ByteBuffer::empty());
+ fn write(&self, bytebuf: &mut impl BufMut) {
+ let mut serializer = serializer::Serializer::new(bytebuf);
self.serialize(&mut serializer)
.expect("Could not serialize packet");
- // We write the packet in an empty bytebuffer and then put it into our current one.
- // In the future we may do packet batching thats the reason i don't let every packet create a new bytebuffer and use
- // an existing instead
- bytebuf.put(serializer.output.buf());
}
}
@@ -153,7 +24,7 @@ impl
ServerPacket for P
where
P: Packet + DeserializeOwned,
{
- fn read(bytebuf: &mut ByteBuffer) -> Result
{
+ fn read(bytebuf: &mut impl Buf) -> Result
{
let deserializer = deserializer::Deserializer::new(bytebuf);
P::deserialize(deserializer)
}
diff --git a/pumpkin-protocol/src/bytebuf/serializer.rs b/pumpkin-protocol/src/bytebuf/serializer.rs
index cb2f78660..5682aa7b8 100644
--- a/pumpkin-protocol/src/bytebuf/serializer.rs
+++ b/pumpkin-protocol/src/bytebuf/serializer.rs
@@ -1,41 +1,24 @@
use std::fmt::Display;
+use bytes::BufMut;
use serde::{
ser::{self},
Serialize,
};
use thiserror::Error;
-use super::ByteBuffer;
+use super::ByteBufMut;
-pub struct Serializer {
- pub output: ByteBuffer,
+pub struct Serializer {
+ pub output: B,
}
-impl Serializer {
- pub fn new(buf: ByteBuffer) -> Self {
+impl Serializer {
+ pub fn new(buf: B) -> Self {
Self { output: buf }
}
}
-impl From for ByteBuffer {
- fn from(val: Serializer) -> Self {
- val.output
- }
-}
-
-impl AsRef for Serializer {
- fn as_ref(&self) -> &ByteBuffer {
- &self.output
- }
-}
-
-impl AsMut for Serializer {
- fn as_mut(&mut self) -> &mut ByteBuffer {
- &mut self.output
- }
-}
-
#[derive(Debug, Error)]
pub enum SerializerError {
#[error("serializer error {0}")]
@@ -55,8 +38,8 @@ impl ser::Error for SerializerError {
// Enums are written as a varint of the index
// Structs are ignored
// Iterables' values are written in order, but NO information (e.g. size) about the
-// iterable itself is written (list sizes should be a seperate field)
-impl ser::Serializer for &mut Serializer {
+// iterable itself is written (list sizes should be a separate field)
+impl ser::Serializer for &mut Serializer {
type Ok = ();
type Error = SerializerError;
@@ -137,7 +120,7 @@ impl ser::Serializer for &mut Serializer {
Ok(())
}
fn serialize_seq(self, _len: Option) -> Result {
- // here is where all arrays/list getting written, usally we prefix the length of every length with an var int. The problem is
+ // here is where all arrays/list getting written, usually we prefix the length of every length with an var int. The problem is
// that byte arrays also getting thrown in here, and we don't want to prefix them
Ok(self)
}
@@ -226,7 +209,7 @@ impl ser::Serializer for &mut Serializer {
}
}
-impl ser::SerializeSeq for &mut Serializer {
+impl ser::SerializeSeq for &mut Serializer {
// Must match the `Ok` type of the serializer.
type Ok = ();
// Must match the `Error` type of the serializer.
@@ -246,7 +229,7 @@ impl ser::SerializeSeq for &mut Serializer {
}
}
-impl ser::SerializeTuple for &mut Serializer {
+impl ser::SerializeTuple for &mut Serializer {
type Ok = ();
type Error = SerializerError;
@@ -263,7 +246,7 @@ impl ser::SerializeTuple for &mut Serializer {
}
// Same thing but for tuple structs.
-impl ser::SerializeTupleStruct for &mut Serializer {
+impl ser::SerializeTupleStruct for &mut Serializer {
type Ok = ();
type Error = SerializerError;
@@ -288,7 +271,7 @@ impl ser::SerializeTupleStruct for &mut Serializer {
//
// So the `end` method in this impl is responsible for closing both the `]` and
// the `}`.
-impl ser::SerializeTupleVariant for &mut Serializer {
+impl ser::SerializeTupleVariant for &mut Serializer {
type Ok = ();
type Error = SerializerError;
@@ -312,7 +295,7 @@ impl ser::SerializeTupleVariant for &mut Serializer {
// `serialize_entry` method allows serializers to optimize for the case where
// key and value are both available simultaneously. In JSON it doesn't make a
// difference so the default behavior for `serialize_entry` is fine.
-impl ser::SerializeMap for &mut Serializer {
+impl ser::SerializeMap for &mut Serializer {
type Ok = ();
type Error = SerializerError;
@@ -348,7 +331,7 @@ impl ser::SerializeMap for &mut Serializer {
// Structs are like maps in which the keys are constrained to be compile-time
// constant strings.
-impl ser::SerializeStruct for &mut Serializer {
+impl ser::SerializeStruct for &mut Serializer {
type Ok = ();
type Error = SerializerError;
@@ -371,7 +354,7 @@ impl ser::SerializeStruct for &mut Serializer {
// Similar to `SerializeTupleVariant`, here the `end` method is responsible for
// closing both of the curly braces opened by `serialize_struct_variant`.
-impl ser::SerializeStructVariant for &mut Serializer {
+impl ser::SerializeStructVariant for &mut Serializer {
type Ok = ();
type Error = SerializerError;
diff --git a/pumpkin-protocol/src/client/config/c_cookie_request.rs b/pumpkin-protocol/src/client/config/c_cookie_request.rs
index 08bdcedb6..71fb9aca3 100644
--- a/pumpkin-protocol/src/client/config/c_cookie_request.rs
+++ b/pumpkin-protocol/src/client/config/c_cookie_request.rs
@@ -1,6 +1,6 @@
use pumpkin_macros::client_packet;
-use crate::Identifier;
+use crate::codec::identifier::Identifier;
#[derive(serde::Serialize)]
#[client_packet("config:cookie_request")]
diff --git a/pumpkin-protocol/src/client/config/c_known_packs.rs b/pumpkin-protocol/src/client/config/c_known_packs.rs
index 80b375808..7622b93ef 100644
--- a/pumpkin-protocol/src/client/config/c_known_packs.rs
+++ b/pumpkin-protocol/src/client/config/c_known_packs.rs
@@ -1,6 +1,7 @@
+use bytes::BufMut;
use pumpkin_macros::client_packet;
-use crate::{bytebuf::ByteBuffer, ClientPacket, KnownPack};
+use crate::{bytebuf::ByteBufMut, ClientPacket, KnownPack};
#[client_packet("config:select_known_packs")]
pub struct CKnownPacks<'a> {
@@ -14,7 +15,7 @@ impl<'a> CKnownPacks<'a> {
}
impl ClientPacket for CKnownPacks<'_> {
- fn write(&self, bytebuf: &mut ByteBuffer) {
+ fn write(&self, bytebuf: &mut impl BufMut) {
bytebuf.put_list::(self.known_packs, |p, v| {
p.put_string(v.namespace);
p.put_string(v.id);
diff --git a/pumpkin-protocol/src/client/config/c_registry_data.rs b/pumpkin-protocol/src/client/config/c_registry_data.rs
index d346ca45e..5a04e6823 100644
--- a/pumpkin-protocol/src/client/config/c_registry_data.rs
+++ b/pumpkin-protocol/src/client/config/c_registry_data.rs
@@ -1,16 +1,16 @@
-use bytes::BytesMut;
+use bytes::{BufMut, BytesMut};
use pumpkin_macros::client_packet;
-use crate::{bytebuf::ByteBuffer, ClientPacket};
+use crate::{bytebuf::ByteBufMut, codec::identifier::Identifier, ClientPacket};
#[client_packet("config:registry_data")]
pub struct CRegistryData<'a> {
- registry_id: &'a str,
- entries: &'a [RegistryEntry<'a>],
+ registry_id: &'a Identifier,
+ entries: &'a [RegistryEntry],
}
impl<'a> CRegistryData<'a> {
- pub fn new(registry_id: &'a str, entries: &'a [RegistryEntry]) -> Self {
+ pub fn new(registry_id: &'a Identifier, entries: &'a [RegistryEntry]) -> Self {
Self {
registry_id,
entries,
@@ -18,18 +18,17 @@ impl<'a> CRegistryData<'a> {
}
}
-pub struct RegistryEntry<'a> {
- pub entry_id: &'a str,
- pub data: BytesMut,
+pub struct RegistryEntry {
+ pub entry_id: Identifier,
+ pub data: Option,
}
impl ClientPacket for CRegistryData<'_> {
- fn write(&self, bytebuf: &mut ByteBuffer) {
- bytebuf.put_string(self.registry_id);
+ fn write(&self, bytebuf: &mut impl BufMut) {
+ bytebuf.put_identifier(self.registry_id);
bytebuf.put_list::(self.entries, |p, v| {
- p.put_string(v.entry_id);
- p.put_bool(!v.data.is_empty());
- p.put_slice(&v.data);
+ p.put_identifier(&v.entry_id);
+ p.put_option(&v.data, |p, v| p.put_slice(v));
});
}
}
diff --git a/pumpkin-protocol/src/client/config/c_server_links.rs b/pumpkin-protocol/src/client/config/c_server_links.rs
index b4150d8ef..b14547ca5 100644
--- a/pumpkin-protocol/src/client/config/c_server_links.rs
+++ b/pumpkin-protocol/src/client/config/c_server_links.rs
@@ -1,87 +1,16 @@
-use crate::VarInt;
-use pumpkin_core::text::TextComponent;
+use crate::{Link, VarInt};
use pumpkin_macros::client_packet;
-use serde::{Serialize, Serializer};
+use serde::Serialize;
#[derive(Serialize)]
#[client_packet("config:server_links")]
-pub struct CServerLinks<'a> {
+pub struct CConfigServerLinks<'a> {
links_count: &'a VarInt,
links: &'a [Link<'a>],
}
-impl<'a> CServerLinks<'a> {
+impl<'a> CConfigServerLinks<'a> {
pub fn new(links_count: &'a VarInt, links: &'a [Link<'a>]) -> Self {
Self { links_count, links }
}
}
-
-pub enum Label<'a> {
- BuiltIn(LinkType),
- TextComponent(TextComponent<'a>),
-}
-
-impl Serialize for Label<'_> {
- fn serialize(&self, serializer: S) -> Result
- where
- S: Serializer,
- {
- match self {
- Label::BuiltIn(link_type) => link_type.serialize(serializer),
- Label::TextComponent(component) => component.serialize(serializer),
- }
- }
-}
-
-#[derive(Serialize)]
-pub struct Link<'a> {
- pub is_built_in: bool,
- pub label: Label<'a>,
- pub url: &'a String,
-}
-
-impl<'a> Link<'a> {
- pub fn new(label: Label<'a>, url: &'a String) -> Self {
- Self {
- is_built_in: match label {
- Label::BuiltIn(_) => true,
- Label::TextComponent(_) => false,
- },
- label,
- url,
- }
- }
-}
-
-pub enum LinkType {
- BugReport,
- CommunityGuidelines,
- Support,
- Status,
- Feedback,
- Community,
- Website,
- Forums,
- News,
- Announcements,
-}
-
-impl Serialize for LinkType {
- fn serialize(&self, serializer: S) -> Result
- where
- S: Serializer,
- {
- match self {
- LinkType::BugReport => VarInt(0).serialize(serializer),
- LinkType::CommunityGuidelines => VarInt(1).serialize(serializer),
- LinkType::Support => VarInt(2).serialize(serializer),
- LinkType::Status => VarInt(3).serialize(serializer),
- LinkType::Feedback => VarInt(4).serialize(serializer),
- LinkType::Community => VarInt(5).serialize(serializer),
- LinkType::Website => VarInt(6).serialize(serializer),
- LinkType::Forums => VarInt(7).serialize(serializer),
- LinkType::News => VarInt(8).serialize(serializer),
- LinkType::Announcements => VarInt(9).serialize(serializer),
- }
- }
-}
diff --git a/pumpkin-protocol/src/client/config/c_store_cookie.rs b/pumpkin-protocol/src/client/config/c_store_cookie.rs
index 511bdd0d1..0334df2d1 100644
--- a/pumpkin-protocol/src/client/config/c_store_cookie.rs
+++ b/pumpkin-protocol/src/client/config/c_store_cookie.rs
@@ -1,4 +1,4 @@
-use crate::{Identifier, VarInt};
+use crate::{codec::identifier::Identifier, VarInt};
use pumpkin_macros::client_packet;
#[derive(serde::Serialize)]
diff --git a/pumpkin-protocol/src/client/login/c_cookie_request.rs b/pumpkin-protocol/src/client/login/c_cookie_request.rs
index df592625d..174e85691 100644
--- a/pumpkin-protocol/src/client/login/c_cookie_request.rs
+++ b/pumpkin-protocol/src/client/login/c_cookie_request.rs
@@ -1,15 +1,16 @@
-use crate::Identifier;
use pumpkin_macros::client_packet;
use serde::Serialize;
+use crate::codec::identifier::Identifier;
+
#[derive(Serialize)]
#[client_packet("login:cookie_request")]
/// Requests a cookie that was previously stored.
-pub struct CCookieRequest<'a> {
+pub struct CLoginCookieRequest<'a> {
key: &'a Identifier,
}
-impl<'a> CCookieRequest<'a> {
+impl<'a> CLoginCookieRequest<'a> {
pub fn new(key: &'a Identifier) -> Self {
Self { key }
}
diff --git a/pumpkin-protocol/src/client/login/c_login_success.rs b/pumpkin-protocol/src/client/login/c_login_success.rs
index 462fcce5a..290ca4c28 100644
--- a/pumpkin-protocol/src/client/login/c_login_success.rs
+++ b/pumpkin-protocol/src/client/login/c_login_success.rs
@@ -1,6 +1,7 @@
+use bytes::BufMut;
use pumpkin_macros::client_packet;
-use crate::{bytebuf::ByteBuffer, ClientPacket, Property};
+use crate::{bytebuf::ByteBufMut, ClientPacket, Property};
#[client_packet("login:login_finished")]
pub struct CLoginSuccess<'a> {
@@ -20,7 +21,7 @@ impl<'a> CLoginSuccess<'a> {
}
impl ClientPacket for CLoginSuccess<'_> {
- fn write(&self, bytebuf: &mut ByteBuffer) {
+ fn write(&self, bytebuf: &mut impl BufMut) {
bytebuf.put_uuid(self.uuid);
bytebuf.put_string(self.username);
bytebuf.put_list::(self.properties, |p, v| {
diff --git a/pumpkin-protocol/src/client/play/c_boss_event.rs b/pumpkin-protocol/src/client/play/c_boss_event.rs
index 344526545..e5b2292d5 100644
--- a/pumpkin-protocol/src/client/play/c_boss_event.rs
+++ b/pumpkin-protocol/src/client/play/c_boss_event.rs
@@ -1,6 +1,7 @@
-use crate::bytebuf::ByteBuffer;
+use crate::bytebuf::ByteBufMut;
use crate::client::play::bossevent_action::BosseventAction;
use crate::{ClientPacket, VarInt};
+use bytes::BufMut;
use pumpkin_macros::client_packet;
#[client_packet("play:boss_event")]
@@ -16,7 +17,7 @@ impl<'a> CBossEvent<'a> {
}
impl ClientPacket for CBossEvent<'_> {
- fn write(&self, bytebuf: &mut ByteBuffer) {
+ fn write(&self, bytebuf: &mut impl BufMut) {
bytebuf.put_uuid(&self.uuid);
let action = &self.action;
match action {
@@ -28,7 +29,7 @@ impl ClientPacket for CBossEvent<'_> {
flags,
} => {
bytebuf.put_var_int(&VarInt::from(0u8));
- bytebuf.put_slice(title.encode().as_slice());
+ bytebuf.put_slice(&title.encode());
bytebuf.put_f32(*health);
bytebuf.put_var_int(color);
bytebuf.put_var_int(division);
@@ -43,7 +44,7 @@ impl ClientPacket for CBossEvent<'_> {
}
BosseventAction::UpdateTile(title) => {
bytebuf.put_var_int(&VarInt::from(3u8));
- bytebuf.put_slice(title.encode().as_slice());
+ bytebuf.put_slice(&title.encode());
}
BosseventAction::UpdateStyle { color, dividers } => {
bytebuf.put_var_int(&VarInt::from(4u8));
diff --git a/pumpkin-protocol/src/client/play/c_chunk_data.rs b/pumpkin-protocol/src/client/play/c_chunk_data.rs
index cd98d1cf0..1356508f7 100644
--- a/pumpkin-protocol/src/client/play/c_chunk_data.rs
+++ b/pumpkin-protocol/src/client/play/c_chunk_data.rs
@@ -1,6 +1,6 @@
-use crate::{bytebuf::ByteBuffer, BitSet, ClientPacket, VarInt};
-use itertools::Itertools;
+use crate::{bytebuf::ByteBufMut, codec::bit_set::BitSet, ClientPacket, VarInt};
+use bytes::{BufMut, BytesMut};
use pumpkin_macros::client_packet;
use pumpkin_world::{chunk::ChunkData, DIRECT_PALETTE_BITS};
@@ -8,7 +8,7 @@ use pumpkin_world::{chunk::ChunkData, DIRECT_PALETTE_BITS};
pub struct CChunkData<'a>(pub &'a ChunkData);
impl ClientPacket for CChunkData<'_> {
- fn write(&self, buf: &mut crate::bytebuf::ByteBuffer) {
+ fn write(&self, buf: &mut impl BufMut) {
// Chunk X
buf.put_i32(self.0.position.x);
// Chunk Z
@@ -19,14 +19,14 @@ impl ClientPacket for CChunkData<'_> {
// Heightmaps
buf.put_slice(&heightmap_nbt);
- let mut data_buf = ByteBuffer::empty();
+ let mut data_buf = BytesMut::new();
self.0.blocks.iter_subchunks().for_each(|chunk| {
let block_count = chunk.len() as i16;
// Block count
data_buf.put_i16(block_count);
//// Block states
- let palette = chunk.iter().dedup().collect_vec();
+ let palette = chunk;
// TODO: make dynamic block_size work
// TODO: make direct block_size work
enum PaletteType {
@@ -55,7 +55,7 @@ impl ClientPacket for CChunkData<'_> {
palette.iter().for_each(|id| {
// Palette
- data_buf.put_var_int(&VarInt(**id as i32));
+ data_buf.put_var_int(&VarInt(*id as i32));
});
// Data array length
let data_array_len = chunk.len().div_ceil(64 / block_size as usize);
@@ -67,7 +67,7 @@ impl ClientPacket for CChunkData<'_> {
for block in block_clump.iter().rev() {
let index = palette
.iter()
- .position(|b| *b == block)
+ .position(|b| b == block)
.expect("Its just got added, ofc it should be there");
out_long = out_long << block_size | (index as i64);
}
@@ -103,9 +103,9 @@ impl ClientPacket for CChunkData<'_> {
});
// Size
- buf.put_var_int(&VarInt(data_buf.buf().len() as i32));
+ buf.put_var_int(&VarInt(data_buf.len() as i32));
// Data
- buf.put_slice(data_buf.buf());
+ buf.put_slice(&data_buf);
// TODO: block entities
buf.put_var_int(&VarInt(0));
@@ -113,13 +113,13 @@ impl ClientPacket for CChunkData<'_> {
// Sky Light Mask
// All of the chunks, this is not optimal and uses way more data than needed but will be
// overhauled with full lighting system.
- buf.put_bit_set(&BitSet(VarInt(1), &[0b01111111111111111111111110]));
+ buf.put_bit_set(&BitSet(VarInt(1), vec![0b01111111111111111111111110]));
// Block Light Mask
- buf.put_bit_set(&BitSet(VarInt(1), &[0]));
+ buf.put_bit_set(&BitSet(VarInt(1), vec![0]));
// Empty Sky Light Mask
- buf.put_bit_set(&BitSet(VarInt(1), &[0b0]));
+ buf.put_bit_set(&BitSet(VarInt(1), vec![0b0]));
// Empty Block Light Mask
- buf.put_bit_set(&BitSet(VarInt(1), &[0]));
+ buf.put_bit_set(&BitSet(VarInt(1), vec![0]));
buf.put_var_int(&VarInt(self.0.blocks.subchunks_len() as i32));
self.0.blocks.iter_subchunks().for_each(|chunk| {
diff --git a/pumpkin-protocol/src/client/play/c_command_suggestions.rs b/pumpkin-protocol/src/client/play/c_command_suggestions.rs
index fae9b04f3..c137b9ad7 100644
--- a/pumpkin-protocol/src/client/play/c_command_suggestions.rs
+++ b/pumpkin-protocol/src/client/play/c_command_suggestions.rs
@@ -1,7 +1,8 @@
+use bytes::BufMut;
use pumpkin_core::text::TextComponent;
use pumpkin_macros::client_packet;
-use crate::{ClientPacket, VarInt};
+use crate::{bytebuf::ByteBufMut, ClientPacket, VarInt};
#[client_packet("play:command_suggestions")]
pub struct CCommandSuggestions<'a> {
@@ -28,13 +29,13 @@ impl<'a> CCommandSuggestions<'a> {
}
impl ClientPacket for CCommandSuggestions<'_> {
- fn write(&self, bytebuf: &mut crate::bytebuf::ByteBuffer) {
+ fn write(&self, bytebuf: &mut impl BufMut) {
bytebuf.put_var_int(&self.id);
bytebuf.put_var_int(&self.start);
bytebuf.put_var_int(&self.length);
bytebuf.put_list(&self.matches, |bytebuf, suggestion| {
- bytebuf.put_string(suggestion.suggestion);
+ bytebuf.put_string(&suggestion.suggestion);
bytebuf.put_bool(suggestion.tooltip.is_some());
if let Some(tooltip) = &suggestion.tooltip {
bytebuf.put_slice(&tooltip.encode());
@@ -45,12 +46,12 @@ impl ClientPacket for CCommandSuggestions<'_> {
#[derive(PartialEq, Eq, Hash, Debug)]
pub struct CommandSuggestion<'a> {
- pub suggestion: &'a str,
+ pub suggestion: String,
pub tooltip: Option>,
}
impl<'a> CommandSuggestion<'a> {
- pub fn new(suggestion: &'a str, tooltip: Option>) -> Self {
+ pub fn new(suggestion: String, tooltip: Option>) -> Self {
Self {
suggestion,
tooltip,
diff --git a/pumpkin-protocol/src/client/play/c_commands.rs b/pumpkin-protocol/src/client/play/c_commands.rs
index 32dc71df9..264a51331 100644
--- a/pumpkin-protocol/src/client/play/c_commands.rs
+++ b/pumpkin-protocol/src/client/play/c_commands.rs
@@ -1,6 +1,7 @@
+use bytes::BufMut;
use pumpkin_macros::client_packet;
-use crate::{bytebuf::ByteBuffer, ClientPacket, VarInt};
+use crate::{bytebuf::ByteBufMut, ClientPacket, VarInt};
#[client_packet("play:commands")]
pub struct CCommands<'a> {
@@ -18,7 +19,7 @@ impl<'a> CCommands<'a> {
}
impl ClientPacket for CCommands<'_> {
- fn write(&self, bytebuf: &mut ByteBuffer) {
+ fn write(&self, bytebuf: &mut impl BufMut) {
bytebuf.put_list(&self.nodes, |bytebuf, node: &ProtoNode| {
node.write_to(bytebuf)
});
@@ -51,7 +52,7 @@ impl ProtoNode<'_> {
const FLAG_HAS_REDIRECT: u8 = 8;
const FLAG_HAS_SUGGESTION_TYPE: u8 = 16;
- pub fn write_to(&self, bytebuf: &mut ByteBuffer) {
+ pub fn write_to(&self, bytebuf: &mut impl BufMut) {
// flags
let flags = match self.node_type {
ProtoNodeType::Root => 0,
@@ -69,10 +70,10 @@ impl ProtoNode<'_> {
name: _,
is_executable,
parser: _,
- override_suggestion_type: override_suggestion_tpye,
+ override_suggestion_type,
} => {
let mut n = 2;
- if override_suggestion_tpye.is_some() {
+ if override_suggestion_type.is_some() {
n |= Self::FLAG_HAS_SUGGESTION_TYPE
}
if is_executable {
@@ -187,7 +188,7 @@ impl ProtoCmdArgParser<'_> {
pub const SCORE_HOLDER_FLAG_ALLOW_MULTIPLE: u8 = 1;
- pub fn write_to_buffer(&self, bytebuf: &mut ByteBuffer) {
+ pub fn write_to_buffer(&self, bytebuf: &mut impl BufMut) {
match self {
Self::Bool => bytebuf.put_var_int(&0.into()),
Self::Float { min, max } => Self::write_number_arg(&1.into(), *min, *max, bytebuf),
@@ -269,7 +270,7 @@ impl ProtoCmdArgParser<'_> {
id: &VarInt,
min: Option,
max: Option,
- bytebuf: &mut ByteBuffer,
+ bytebuf: &mut impl BufMut,
) {
let mut flags: u8 = 0;
if min.is_some() {
@@ -290,13 +291,13 @@ impl ProtoCmdArgParser<'_> {
}
}
- fn write_with_flags(id: &VarInt, flags: u8, bytebuf: &mut ByteBuffer) {
+ fn write_with_flags(id: &VarInt, flags: u8, bytebuf: &mut impl BufMut) {
bytebuf.put_var_int(id);
bytebuf.put_u8(flags);
}
- fn write_with_identifier(id: &VarInt, extra_identifier: &str, bytebuf: &mut ByteBuffer) {
+ fn write_with_identifier(id: &VarInt, extra_identifier: &str, bytebuf: &mut impl BufMut) {
bytebuf.put_var_int(id);
bytebuf.put_string(extra_identifier);
@@ -312,29 +313,29 @@ pub enum StringProtoArgBehavior {
}
trait NumberCmdArg {
- fn write(self, bytebuf: &mut ByteBuffer);
+ fn write(self, bytebuf: &mut impl BufMut);
}
impl NumberCmdArg for f32 {
- fn write(self, bytebuf: &mut ByteBuffer) {
+ fn write(self, bytebuf: &mut impl BufMut) {
bytebuf.put_f32(self);
}
}
impl NumberCmdArg for f64 {
- fn write(self, bytebuf: &mut ByteBuffer) {
+ fn write(self, bytebuf: &mut impl BufMut) {
bytebuf.put_f64(self);
}
}
impl NumberCmdArg for i32 {
- fn write(self, bytebuf: &mut ByteBuffer) {
+ fn write(self, bytebuf: &mut impl BufMut) {
bytebuf.put_i32(self);
}
}
impl NumberCmdArg for i64 {
- fn write(self, bytebuf: &mut ByteBuffer) {
+ fn write(self, bytebuf: &mut impl BufMut) {
bytebuf.put_i64(self);
}
}
diff --git a/pumpkin-protocol/src/client/play/c_cookie_request.rs b/pumpkin-protocol/src/client/play/c_cookie_request.rs
index 58d494942..fb9bc806a 100644
--- a/pumpkin-protocol/src/client/play/c_cookie_request.rs
+++ b/pumpkin-protocol/src/client/play/c_cookie_request.rs
@@ -1,15 +1,16 @@
-use crate::Identifier;
use pumpkin_macros::client_packet;
use serde::Serialize;
+use crate::codec::identifier::Identifier;
+
#[derive(Serialize)]
#[client_packet("play:cookie_request")]
/// Requests a cookie that was previously stored.
-pub struct CCookieRequest<'a> {
+pub struct CPlayCookieRequest<'a> {
key: &'a Identifier,
}
-impl<'a> CCookieRequest<'a> {
+impl<'a> CPlayCookieRequest<'a> {
pub fn new(key: &'a Identifier) -> Self {
Self { key }
}
diff --git a/pumpkin-protocol/src/client/play/c_entity_sound_effect.rs b/pumpkin-protocol/src/client/play/c_entity_sound_effect.rs
index 62afd46d2..27de764fe 100644
--- a/pumpkin-protocol/src/client/play/c_entity_sound_effect.rs
+++ b/pumpkin-protocol/src/client/play/c_entity_sound_effect.rs
@@ -1,6 +1,7 @@
+use bytes::BufMut;
use pumpkin_macros::client_packet;
-use crate::{ClientPacket, IDOrSoundEvent, SoundCategory, SoundEvent, VarInt};
+use crate::{bytebuf::ByteBufMut, ClientPacket, IDOrSoundEvent, SoundCategory, SoundEvent, VarInt};
#[client_packet("play:sound_entity")]
pub struct CEntitySoundEffect {
@@ -38,11 +39,11 @@ impl CEntitySoundEffect {
}
impl ClientPacket for CEntitySoundEffect {
- fn write(&self, bytebuf: &mut crate::bytebuf::ByteBuffer) {
+ fn write(&self, bytebuf: &mut impl BufMut) {
bytebuf.put_var_int(&self.sound_event.id);
if self.sound_event.id.0 == 0 {
if let Some(test) = &self.sound_event.sound_event {
- bytebuf.put_string(&test.sound_name);
+ bytebuf.put_identifier(&test.sound_name);
bytebuf.put_option(&test.range, |p, v| {
p.put_f32(*v);
diff --git a/pumpkin-protocol/src/client/play/c_initialize_world_border.rs b/pumpkin-protocol/src/client/play/c_initialize_world_border.rs
index f4d6663a7..f2ab72f6c 100644
--- a/pumpkin-protocol/src/client/play/c_initialize_world_border.rs
+++ b/pumpkin-protocol/src/client/play/c_initialize_world_border.rs
@@ -1,7 +1,7 @@
use pumpkin_macros::client_packet;
use serde::Serialize;
-use crate::{VarInt, VarLong};
+use crate::{codec::var_long::VarLong, VarInt};
#[derive(Serialize)]
#[client_packet("play:initialize_border")]
diff --git a/pumpkin-protocol/src/client/play/c_login.rs b/pumpkin-protocol/src/client/play/c_login.rs
index 12a594f88..ec6e23bb4 100644
--- a/pumpkin-protocol/src/client/play/c_login.rs
+++ b/pumpkin-protocol/src/client/play/c_login.rs
@@ -3,7 +3,7 @@ use pumpkin_core::math::position::WorldPosition;
use pumpkin_macros::client_packet;
use serde::Serialize;
-use crate::VarInt;
+use crate::{codec::identifier::Identifier, VarInt};
#[derive(Serialize)]
#[client_packet("play:login")]
@@ -11,7 +11,7 @@ pub struct CLogin<'a> {
entity_id: i32,
is_hardcore: bool,
dimension_count: VarInt,
- dimension_names: &'a [&'a str],
+ dimension_names: &'a [Identifier],
max_players: VarInt,
view_distance: VarInt,
simulated_distance: VarInt,
@@ -20,13 +20,13 @@ pub struct CLogin<'a> {
limited_crafting: bool,
// Spawn Info
dimension_type: VarInt,
- dimension_name: &'a str,
+ dimension_name: Identifier,
hashed_seed: i64,
game_mode: u8,
previous_gamemode: i8,
debug: bool,
is_flat: bool,
- death_dimension_name: Option<(&'a str, WorldPosition)>,
+ death_dimension_name: Option<(Identifier, WorldPosition)>,
portal_cooldown: VarInt,
sealevel: VarInt,
enforce_secure_chat: bool,
@@ -37,7 +37,7 @@ impl<'a> CLogin<'a> {
pub fn new(
entity_id: i32,
is_hardcore: bool,
- dimension_names: &'a [&'a str],
+ dimension_names: &'a [Identifier],
max_players: VarInt,
view_distance: VarInt,
simulated_distance: VarInt,
@@ -45,13 +45,13 @@ impl<'a> CLogin<'a> {
enabled_respawn_screen: bool,
limited_crafting: bool,
dimension_type: VarInt,
- dimension_name: &'a str,
+ dimension_name: Identifier,
hashed_seed: i64,
game_mode: u8,
previous_gamemode: i8,
debug: bool,
is_flat: bool,
- death_dimension_name: Option<(&'a str, WorldPosition)>,
+ death_dimension_name: Option<(Identifier, WorldPosition)>,
portal_cooldown: VarInt,
sealevel: VarInt,
enforce_secure_chat: bool,
diff --git a/pumpkin-protocol/src/client/play/c_player_chat_message.rs b/pumpkin-protocol/src/client/play/c_player_chat_message.rs
index b774a2f28..0db6c3df0 100644
--- a/pumpkin-protocol/src/client/play/c_player_chat_message.rs
+++ b/pumpkin-protocol/src/client/play/c_player_chat_message.rs
@@ -3,7 +3,7 @@ use pumpkin_core::text::TextComponent;
use pumpkin_macros::client_packet;
use serde::Serialize;
-use crate::{BitSet, VarInt};
+use crate::{codec::bit_set::BitSet, VarInt};
#[derive(Serialize)]
#[client_packet("play:player_chat")]
@@ -18,7 +18,7 @@ pub struct CPlayerChatMessage<'a> {
previous_messages_count: VarInt,
previous_messages: &'a [PreviousMessage<'a>], // max 20
unsigned_content: Option>,
- filter_type: FilterType<'a>,
+ filter_type: FilterType,
chat_type: VarInt,
sender_name: TextComponent<'a>,
target_name: Option>,
@@ -35,7 +35,7 @@ impl<'a> CPlayerChatMessage<'a> {
salt: i64,
previous_messages: &'a [PreviousMessage<'a>],
unsigned_content: Option>,
- filter_type: FilterType<'a>,
+ filter_type: FilterType,
chat_type: VarInt,
sender_name: TextComponent<'a>,
target_name: Option>,
@@ -66,11 +66,11 @@ pub struct PreviousMessage<'a> {
#[derive(Serialize)]
#[repr(i32)]
-pub enum FilterType<'a> {
+pub enum FilterType {
/// Message is not filtered at all
PassThrough = 0,
/// Message is fully filtered
FullyFiltered = 1,
/// Only some characters in the message are filtered
- PartiallyFiltered(BitSet<'a>) = 2,
+ PartiallyFiltered(BitSet) = 2,
}
diff --git a/pumpkin-protocol/src/client/play/c_player_info_update.rs b/pumpkin-protocol/src/client/play/c_player_info_update.rs
index 09fbff949..72d912cbf 100644
--- a/pumpkin-protocol/src/client/play/c_player_info_update.rs
+++ b/pumpkin-protocol/src/client/play/c_player_info_update.rs
@@ -1,6 +1,7 @@
+use bytes::BufMut;
use pumpkin_macros::client_packet;
-use crate::{bytebuf::ByteBuffer, ClientPacket, Property};
+use crate::{bytebuf::ByteBufMut, ClientPacket, Property};
use super::PlayerAction;
@@ -22,7 +23,7 @@ impl<'a> CPlayerInfoUpdate<'a> {
}
impl ClientPacket for CPlayerInfoUpdate<'_> {
- fn write(&self, bytebuf: &mut ByteBuffer) {
+ fn write(&self, bytebuf: &mut impl BufMut) {
bytebuf.put_i8(self.actions);
bytebuf.put_list::(self.players, |p, v| {
p.put_uuid(&v.uuid);
diff --git a/pumpkin-protocol/src/client/play/c_player_position.rs b/pumpkin-protocol/src/client/play/c_player_position.rs
index 0a99a9e09..287c1b2ff 100644
--- a/pumpkin-protocol/src/client/play/c_player_position.rs
+++ b/pumpkin-protocol/src/client/play/c_player_position.rs
@@ -1,7 +1,8 @@
+use bytes::BufMut;
use pumpkin_core::math::vector3::Vector3;
use pumpkin_macros::client_packet;
-use crate::{ClientPacket, PositionFlag, VarInt};
+use crate::{bytebuf::ByteBufMut, ClientPacket, PositionFlag, VarInt};
#[client_packet("play:player_position")]
pub struct CPlayerPosition<'a> {
@@ -34,7 +35,7 @@ impl<'a> CPlayerPosition<'a> {
}
impl ClientPacket for CPlayerPosition<'_> {
- fn write(&self, bytebuf: &mut crate::bytebuf::ByteBuffer) {
+ fn write(&self, bytebuf: &mut impl BufMut) {
bytebuf.put_var_int(&self.teleport_id);
bytebuf.put_f64(self.position.x);
bytebuf.put_f64(self.position.y);
diff --git a/pumpkin-protocol/src/client/play/c_respawn.rs b/pumpkin-protocol/src/client/play/c_respawn.rs
index b892d53ec..9d68b059c 100644
--- a/pumpkin-protocol/src/client/play/c_respawn.rs
+++ b/pumpkin-protocol/src/client/play/c_respawn.rs
@@ -2,35 +2,35 @@ use pumpkin_core::math::position::WorldPosition;
use pumpkin_macros::client_packet;
use serde::Serialize;
-use crate::VarInt;
+use crate::{codec::identifier::Identifier, VarInt};
#[derive(Serialize)]
#[client_packet("play:respawn")]
-pub struct CRespawn<'a> {
+pub struct CRespawn {
dimension_type: VarInt,
- dimension_name: &'a str,
+ dimension_name: Identifier,
hashed_seed: i64,
game_mode: u8,
previous_gamemode: i8,
debug: bool,
is_flat: bool,
- death_dimension_name: Option<(&'a str, WorldPosition)>,
+ death_dimension_name: Option<(Identifier, WorldPosition)>,
portal_cooldown: VarInt,
sealevel: VarInt,
data_kept: u8,
}
-impl<'a> CRespawn<'a> {
+impl CRespawn {
#[expect(clippy::too_many_arguments)]
pub fn new(
dimension_type: VarInt,
- dimension_name: &'a str,
+ dimension_name: Identifier,
hashed_seed: i64,
game_mode: u8,
previous_gamemode: i8,
debug: bool,
is_flat: bool,
- death_dimension_name: Option<(&'a str, WorldPosition)>,
+ death_dimension_name: Option<(Identifier, WorldPosition)>,
portal_cooldown: VarInt,
sealevel: VarInt,
data_kept: u8,
diff --git a/pumpkin-protocol/src/client/play/c_server_links.rs b/pumpkin-protocol/src/client/play/c_server_links.rs
index 7619a0c65..a2cb76fa6 100644
--- a/pumpkin-protocol/src/client/play/c_server_links.rs
+++ b/pumpkin-protocol/src/client/play/c_server_links.rs
@@ -1,87 +1,16 @@
-use crate::VarInt;
-use pumpkin_core::text::TextComponent;
+use crate::{Link, VarInt};
use pumpkin_macros::client_packet;
-use serde::{Serialize, Serializer};
+use serde::Serialize;
#[derive(Serialize)]
#[client_packet("play:server_links")]
-pub struct CServerLinks<'a> {
+pub struct CPlayServerLinks<'a> {
links_count: &'a VarInt,
links: &'a [Link<'a>],
}
-impl<'a> CServerLinks<'a> {
+impl<'a> CPlayServerLinks<'a> {
pub fn new(links_count: &'a VarInt, links: &'a [Link<'a>]) -> Self {
Self { links_count, links }
}
}
-
-pub enum Label<'a> {
- BuiltIn(LinkType),
- TextComponent(TextComponent<'a>),
-}
-
-impl Serialize for Label<'_> {
- fn serialize(&self, serializer: S) -> Result
- where
- S: Serializer,
- {
- match self {
- Label::BuiltIn(link_type) => link_type.serialize(serializer),
- Label::TextComponent(component) => component.serialize(serializer),
- }
- }
-}
-
-#[derive(Serialize)]
-pub struct Link<'a> {
- pub is_built_in: bool,
- pub label: Label<'a>,
- pub url: &'a String,
-}
-
-impl<'a> Link<'a> {
- pub fn new(label: Label<'a>, url: &'a String) -> Self {
- Self {
- is_built_in: match label {
- Label::BuiltIn(_) => true,
- Label::TextComponent(_) => false,
- },
- label,
- url,
- }
- }
-}
-
-pub enum LinkType {
- BugReport,
- CommunityGuidelines,
- Support,
- Status,
- Feedback,
- Community,
- Website,
- Forums,
- News,
- Announcements,
-}
-
-impl Serialize for LinkType {
- fn serialize(&self, serializer: S) -> Result
- where
- S: Serializer,
- {
- match self {
- LinkType::BugReport => VarInt(0).serialize(serializer),
- LinkType::CommunityGuidelines => VarInt(1).serialize(serializer),
- LinkType::Support => VarInt(2).serialize(serializer),
- LinkType::Status => VarInt(3).serialize(serializer),
- LinkType::Feedback => VarInt(4).serialize(serializer),
- LinkType::Community => VarInt(5).serialize(serializer),
- LinkType::Website => VarInt(6).serialize(serializer),
- LinkType::Forums => VarInt(7).serialize(serializer),
- LinkType::News => VarInt(8).serialize(serializer),
- LinkType::Announcements => VarInt(9).serialize(serializer),
- }
- }
-}
diff --git a/pumpkin-protocol/src/client/play/c_set_border_lerp_size.rs b/pumpkin-protocol/src/client/play/c_set_border_lerp_size.rs
index 0d15ab9bc..5f8861a71 100644
--- a/pumpkin-protocol/src/client/play/c_set_border_lerp_size.rs
+++ b/pumpkin-protocol/src/client/play/c_set_border_lerp_size.rs
@@ -1,7 +1,7 @@
use pumpkin_macros::client_packet;
use serde::Serialize;
-use crate::VarLong;
+use crate::codec::var_long::VarLong;
#[derive(Serialize)]
#[client_packet("play:set_border_lerp_size")]
diff --git a/pumpkin-protocol/src/client/play/c_set_container_content.rs b/pumpkin-protocol/src/client/play/c_set_container_content.rs
index 38e6b39ac..275739f23 100644
--- a/pumpkin-protocol/src/client/play/c_set_container_content.rs
+++ b/pumpkin-protocol/src/client/play/c_set_container_content.rs
@@ -1,4 +1,4 @@
-use crate::slot::Slot;
+use crate::codec::slot::Slot;
use crate::VarInt;
use pumpkin_macros::client_packet;
diff --git a/pumpkin-protocol/src/client/play/c_set_container_slot.rs b/pumpkin-protocol/src/client/play/c_set_container_slot.rs
index 19e6b484a..e632da4e0 100644
--- a/pumpkin-protocol/src/client/play/c_set_container_slot.rs
+++ b/pumpkin-protocol/src/client/play/c_set_container_slot.rs
@@ -1,4 +1,4 @@
-use crate::slot::Slot;
+use crate::codec::slot::Slot;
use crate::VarInt;
use pumpkin_macros::client_packet;
diff --git a/pumpkin-protocol/src/client/play/c_sound_effect.rs b/pumpkin-protocol/src/client/play/c_sound_effect.rs
index 14e92ec94..d34af9711 100644
--- a/pumpkin-protocol/src/client/play/c_sound_effect.rs
+++ b/pumpkin-protocol/src/client/play/c_sound_effect.rs
@@ -1,6 +1,7 @@
+use bytes::BufMut;
use pumpkin_macros::client_packet;
-use crate::{ClientPacket, IDOrSoundEvent, SoundCategory, SoundEvent, VarInt};
+use crate::{bytebuf::ByteBufMut, ClientPacket, IDOrSoundEvent, SoundCategory, SoundEvent, VarInt};
#[client_packet("play:sound")]
pub struct CSoundEffect {
@@ -44,11 +45,11 @@ impl CSoundEffect {
}
impl ClientPacket for CSoundEffect {
- fn write(&self, bytebuf: &mut crate::bytebuf::ByteBuffer) {
+ fn write(&self, bytebuf: &mut impl BufMut) {
bytebuf.put_var_int(&self.sound_event.id);
if self.sound_event.id.0 == 0 {
if let Some(test) = &self.sound_event.sound_event {
- bytebuf.put_string(&test.sound_name);
+ bytebuf.put_identifier(&test.sound_name);
bytebuf.put_option(&test.range, |p, v| {
p.put_f32(*v);
diff --git a/pumpkin-protocol/src/client/play/c_store_cookie.rs b/pumpkin-protocol/src/client/play/c_store_cookie.rs
index b9fc02cea..da715f22b 100644
--- a/pumpkin-protocol/src/client/play/c_store_cookie.rs
+++ b/pumpkin-protocol/src/client/play/c_store_cookie.rs
@@ -1,4 +1,4 @@
-use crate::{Identifier, VarInt};
+use crate::{codec::identifier::Identifier, VarInt};
use pumpkin_macros::client_packet;
use serde::Serialize;
diff --git a/pumpkin-protocol/src/client/play/c_teleport_entity.rs b/pumpkin-protocol/src/client/play/c_teleport_entity.rs
index 4327ed658..2ec004922 100644
--- a/pumpkin-protocol/src/client/play/c_teleport_entity.rs
+++ b/pumpkin-protocol/src/client/play/c_teleport_entity.rs
@@ -1,10 +1,11 @@
+use bytes::BufMut;
use pumpkin_core::math::vector3::Vector3;
use pumpkin_macros::client_packet;
-use crate::{ClientPacket, PositionFlag, VarInt};
+use crate::{bytebuf::ByteBufMut, ClientPacket, PositionFlag, VarInt};
#[client_packet("play:teleport_entity")]
-pub struct CTeleportEntitiy<'a> {
+pub struct CTeleportEntity<'a> {
entity_id: VarInt,
position: Vector3,
delta: Vector3,
@@ -14,7 +15,7 @@ pub struct CTeleportEntitiy<'a> {
on_ground: bool,
}
-impl<'a> CTeleportEntitiy<'a> {
+impl<'a> CTeleportEntity<'a> {
pub fn new(
entity_id: VarInt,
position: Vector3,
@@ -36,8 +37,8 @@ impl<'a> CTeleportEntitiy<'a> {
}
}
-impl ClientPacket for CTeleportEntitiy<'_> {
- fn write(&self, bytebuf: &mut crate::bytebuf::ByteBuffer) {
+impl ClientPacket for CTeleportEntity<'_> {
+ fn write(&self, bytebuf: &mut impl BufMut) {
bytebuf.put_var_int(&self.entity_id);
bytebuf.put_f64(self.position.x);
bytebuf.put_f64(self.position.y);
diff --git a/pumpkin-protocol/src/client/play/c_update_objectives.rs b/pumpkin-protocol/src/client/play/c_update_objectives.rs
index e5ae2e2d1..41c45ff58 100644
--- a/pumpkin-protocol/src/client/play/c_update_objectives.rs
+++ b/pumpkin-protocol/src/client/play/c_update_objectives.rs
@@ -1,7 +1,8 @@
+use bytes::BufMut;
use pumpkin_core::text::TextComponent;
use pumpkin_macros::client_packet;
-use crate::{ClientPacket, NumberFormat, VarInt};
+use crate::{bytebuf::ByteBufMut, ClientPacket, NumberFormat, VarInt};
#[client_packet("play:set_objective")]
pub struct CUpdateObjectives<'a> {
@@ -31,7 +32,7 @@ impl<'a> CUpdateObjectives<'a> {
}
impl ClientPacket for CUpdateObjectives<'_> {
- fn write(&self, bytebuf: &mut crate::bytebuf::ByteBuffer) {
+ fn write(&self, bytebuf: &mut impl BufMut) {
bytebuf.put_string(self.objective_name);
bytebuf.put_u8(self.mode);
if self.mode == 0 || self.mode == 2 {
diff --git a/pumpkin-protocol/src/codec/bit_set.rs b/pumpkin-protocol/src/codec/bit_set.rs
new file mode 100644
index 000000000..27aa329d3
--- /dev/null
+++ b/pumpkin-protocol/src/codec/bit_set.rs
@@ -0,0 +1,53 @@
+use std::num::NonZeroUsize;
+
+use bytes::{Buf, BufMut};
+use serde::{Serialize, Serializer};
+
+use crate::bytebuf::ByteBuf;
+use crate::bytebuf::ByteBufMut;
+
+use super::{var_int::VarInt, Codec, DecodeError};
+
+pub struct BitSet(pub VarInt, pub Vec);
+
+impl Codec for BitSet {
+ /// The maximum size of the BitSet is `remaining / 8`.
+ const MAX_SIZE: NonZeroUsize = unsafe { NonZeroUsize::new_unchecked(usize::MAX) };
+
+ fn written_size(&self) -> usize {
+ todo!()
+ }
+
+ fn encode(&self, write: &mut impl BufMut) {
+ write.put_var_int(&self.0);
+ for b in &self.1 {
+ write.put_i64(*b);
+ }
+ }
+
+ fn decode(read: &mut impl Buf) -> Result {
+ // read length
+ let length = read
+ .try_get_var_int()
+ .map_err(|_| DecodeError::Incomplete)?;
+ // vanilla uses remaining / 8
+ if length.0 as usize >= read.remaining() / 8 {
+ return Err(DecodeError::TooLarge);
+ }
+ let mut array: Vec = Vec::with_capacity(size_of::() * length.0 as usize);
+ for _ in 0..length.0 {
+ let long = read.try_get_i64().map_err(|_| DecodeError::Incomplete)?;
+ array.push(long);
+ }
+ Ok(BitSet(length, array))
+ }
+}
+
+impl Serialize for BitSet {
+ fn serialize(&self, _serializer: S) -> Result
+ where
+ S: Serializer,
+ {
+ todo!()
+ }
+}
diff --git a/pumpkin-protocol/src/codec/identifier.rs b/pumpkin-protocol/src/codec/identifier.rs
new file mode 100644
index 000000000..6be5675c7
--- /dev/null
+++ b/pumpkin-protocol/src/codec/identifier.rs
@@ -0,0 +1,101 @@
+use std::num::NonZeroUsize;
+
+use bytes::{Buf, BufMut};
+use serde::{de::Visitor, Deserialize, Deserializer, Serialize, Serializer};
+
+use crate::bytebuf::{ByteBuf, ByteBufMut};
+
+use super::{Codec, DecodeError};
+
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct Identifier {
+ pub namespace: String,
+ pub path: String,
+}
+
+impl Identifier {
+ pub fn vanilla(path: &str) -> Self {
+ Self {
+ namespace: "minecraft".to_string(),
+ path: path.to_string(),
+ }
+ }
+}
+impl Codec for Identifier {
+ /// The maximum number of bytes a `Identifer` is the same as for a normal String.
+ const MAX_SIZE: NonZeroUsize = unsafe { NonZeroUsize::new_unchecked(i16::MAX as usize) };
+
+ fn written_size(&self) -> usize {
+ todo!()
+ }
+
+ fn encode(&self, write: &mut impl BufMut) {
+ write.put_string_len(&self.to_string(), Self::MAX_SIZE.get());
+ }
+
+ fn decode(read: &mut impl Buf) -> Result {
+ let identifer = read
+ .try_get_string_len(Self::MAX_SIZE.get())
+ .map_err(|_| DecodeError::Incomplete)?;
+ match identifer.split_once(":") {
+ Some((namespace, path)) => Ok(Identifier {
+ namespace: namespace.to_string(),
+ path: path.to_string(),
+ }),
+ None => Err(DecodeError::Incomplete),
+ }
+ }
+}
+
+impl Serialize for Identifier {
+ fn serialize(&self, serializer: S) -> Result
+ where
+ S: Serializer,
+ {
+ serializer.serialize_str(&self.to_string())
+ }
+}
+
+impl<'de> Deserialize<'de> for Identifier {
+ fn deserialize(deserializer: D) -> Result