pumpkin-protocol: added codecs

This commit is contained in:
Alexander Medvedev 2024-12-21 17:03:52 +01:00
parent 55e8cd696e
commit 0633197b62
61 changed files with 307 additions and 611 deletions

View File

@ -1,11 +1,11 @@
use std::fmt::Display; use std::fmt::Display;
use super::{ByteBuf, ReadingError}; use super::{ByteBuf, ReadingError};
use bytes::Bytes; use bytes::Buf;
use serde::de::{self, DeserializeSeed, SeqAccess}; use serde::de::{self, DeserializeSeed, SeqAccess};
pub struct Deserializer<'a> { pub struct Deserializer<'a, B: Buf> {
inner: &'a mut Bytes, inner: &'a mut B,
} }
impl de::Error for ReadingError { impl de::Error for ReadingError {
@ -14,13 +14,13 @@ impl de::Error for ReadingError {
} }
} }
impl<'a> Deserializer<'a> { impl<'a, B: Buf> Deserializer<'a, B> {
pub fn new(buf: &'a mut Bytes) -> Self { pub fn new(buf: &'a mut B) -> Self {
Self { inner: buf } Self { inner: buf }
} }
} }
impl<'de> de::Deserializer<'de> for Deserializer<'_> { impl<'de, B: Buf> de::Deserializer<'de> for Deserializer<'_, B> {
type Error = ReadingError; type Error = ReadingError;
fn deserialize_any<V>(self, _visitor: V) -> Result<V::Value, Self::Error> fn deserialize_any<V>(self, _visitor: V) -> Result<V::Value, Self::Error>
@ -184,11 +184,11 @@ impl<'de> de::Deserializer<'de> for Deserializer<'_> {
where where
V: de::Visitor<'de>, V: de::Visitor<'de>,
{ {
struct Access<'a, 'b> { struct Access<'a, 'b, B: Buf> {
deserializer: &'a mut Deserializer<'b>, deserializer: &'a mut Deserializer<'b, B>,
} }
impl<'de, 'a, 'b: 'a> SeqAccess<'de> for Access<'a, 'b> { impl<'de, 'a, 'b: 'a, B: Buf> SeqAccess<'de> for Access<'a, 'b, B> {
type Error = ReadingError; type Error = ReadingError;
fn next_element_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>, Self::Error> fn next_element_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>, Self::Error>
@ -216,12 +216,12 @@ impl<'de> de::Deserializer<'de> for Deserializer<'_> {
where where
V: de::Visitor<'de>, V: de::Visitor<'de>,
{ {
struct Access<'a, 'b> { struct Access<'a, 'b, B: Buf> {
deserializer: &'a mut Deserializer<'b>, deserializer: &'a mut Deserializer<'b, B>,
len: usize, len: usize,
} }
impl<'de, 'a, 'b: 'a> SeqAccess<'de> for Access<'a, 'b> { impl<'de, 'a, 'b: 'a, B: Buf> SeqAccess<'de> for Access<'a, 'b, B> {
type Error = ReadingError; type Error = ReadingError;
fn next_element_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>, Self::Error> fn next_element_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>, Self::Error>

View File

@ -1,6 +1,12 @@
use core::str; use core::str;
use crate::{BitSet, FixedBitSet, VarInt, VarLong}; use crate::{
codec::{
bit_set::BitSet, identifier::Identifier, var_int::VarInt, var_long::VarLong, Codec,
DecodeError,
},
FixedBitSet,
};
use bytes::{Buf, BufMut}; use bytes::{Buf, BufMut};
mod deserializer; mod deserializer;
@ -54,9 +60,11 @@ pub trait ByteBuf: Buf {
fn try_get_var_long(&mut self) -> Result<VarLong, ReadingError>; fn try_get_var_long(&mut self) -> Result<VarLong, ReadingError>;
fn try_get_identifer(&mut self) -> Result<Identifier, ReadingError>;
fn try_get_string(&mut self) -> Result<String, ReadingError>; fn try_get_string(&mut self) -> Result<String, ReadingError>;
fn try_get_string_len(&mut self, max_size: u32) -> Result<String, ReadingError>; fn try_get_string_len(&mut self, max_size: usize) -> Result<String, ReadingError>;
/// Reads a boolean. If true, the closure is called, and the returned value is /// Reads a boolean. If true, the closure is called, and the returned value is
/// wrapped in Some. Otherwise, this returns None. /// wrapped in Some. Otherwise, this returns None.
@ -181,12 +189,8 @@ impl<T: Buf> ByteBuf for T {
match VarInt::decode(self) { match VarInt::decode(self) {
Ok(var_int) => Ok(var_int), Ok(var_int) => Ok(var_int),
Err(error) => match error { Err(error) => match error {
crate::VarIntDecodeError::Incomplete => { DecodeError::Incomplete => Err(ReadingError::Incomplete("varint".to_string())),
Err(ReadingError::Incomplete("varint".to_string())) DecodeError::TooLarge => Err(ReadingError::TooLarge("varint".to_string())),
}
crate::VarIntDecodeError::TooLarge => {
Err(ReadingError::TooLarge("varint".to_string()))
}
}, },
} }
} }
@ -194,28 +198,24 @@ impl<T: Buf> ByteBuf for T {
match VarLong::decode(self) { match VarLong::decode(self) {
Ok(var_long) => Ok(var_long), Ok(var_long) => Ok(var_long),
Err(error) => match error { Err(error) => match error {
crate::VarLongDecodeError::Incomplete => { DecodeError::Incomplete => Err(ReadingError::Incomplete("varint".to_string())),
Err(ReadingError::Incomplete("varint".to_string())) DecodeError::TooLarge => Err(ReadingError::TooLarge("varlong".to_string())),
}
crate::VarLongDecodeError::TooLarge => {
Err(ReadingError::TooLarge("varlong".to_string()))
}
}, },
} }
} }
fn try_get_string(&mut self) -> Result<String, ReadingError> { fn try_get_string(&mut self) -> Result<String, ReadingError> {
self.try_get_string_len(i16::MAX as u32) self.try_get_string_len(i16::MAX as usize)
} }
fn try_get_string_len(&mut self, max_size: u32) -> Result<String, ReadingError> { fn try_get_string_len(&mut self, max_size: usize) -> Result<String, ReadingError> {
let size = self.try_get_var_int()?.0; let size = self.try_get_var_int()?.0;
if size as u32 > max_size { if size as usize > max_size {
return Err(ReadingError::TooLarge("string".to_string())); return Err(ReadingError::TooLarge("string".to_string()));
} }
let data = self.try_copy_to_bytes(size as usize)?; let data = self.try_copy_to_bytes(size as usize)?;
if data.len() as u32 > max_size { if data.len() > max_size {
return Err(ReadingError::TooLarge("string".to_string())); return Err(ReadingError::TooLarge("string".to_string()));
} }
match str::from_utf8(&data) { match str::from_utf8(&data) {
@ -256,6 +256,16 @@ impl<T: Buf> ByteBuf for T {
fn try_get_fixed_bitset(&mut self, bits: usize) -> Result<FixedBitSet, ReadingError> { fn try_get_fixed_bitset(&mut self, bits: usize) -> Result<FixedBitSet, ReadingError> {
self.try_copy_to_bytes(bits.div_ceil(8)) self.try_copy_to_bytes(bits.div_ceil(8))
} }
fn try_get_identifer(&mut self) -> Result<Identifier, ReadingError> {
match Identifier::decode(self) {
Ok(identifer) => Ok(identifer),
Err(error) => match error {
DecodeError::Incomplete => Err(ReadingError::Incomplete("identifer".to_string())),
DecodeError::TooLarge => Err(ReadingError::TooLarge("identifer".to_string())),
},
}
}
} }
pub trait ByteBufMut { pub trait ByteBufMut {
@ -265,7 +275,7 @@ pub trait ByteBufMut {
fn put_string(&mut self, val: &str); fn put_string(&mut self, val: &str);
fn put_string_len(&mut self, val: &str, max_size: u32); fn put_string_len(&mut self, val: &str, max_size: usize);
fn put_string_array(&mut self, array: &[String]); fn put_string_array(&mut self, array: &[String]);
@ -277,6 +287,8 @@ pub trait ByteBufMut {
fn put_list<G>(&mut self, list: &[G], write: impl Fn(&mut Self, &G)); fn put_list<G>(&mut self, list: &[G], write: impl Fn(&mut Self, &G));
fn put_identifier(&mut self, val: &Identifier);
fn put_var_int(&mut self, value: &VarInt); fn put_var_int(&mut self, value: &VarInt);
fn put_varint_arr(&mut self, v: &[i32]); fn put_varint_arr(&mut self, v: &[i32]);
@ -299,11 +311,11 @@ impl<T: BufMut> ByteBufMut for T {
} }
fn put_string(&mut self, val: &str) { fn put_string(&mut self, val: &str) {
self.put_string_len(val, i16::MAX as u32); self.put_string_len(val, i16::MAX as usize);
} }
fn put_string_len(&mut self, val: &str, max_size: u32) { fn put_string_len(&mut self, val: &str, max_size: usize) {
if val.len() as u32 > max_size { if val.len() > max_size {
// Should be panic?, I mean its our fault // Should be panic?, I mean its our fault
panic!("String is too big"); panic!("String is too big");
} }
@ -317,15 +329,12 @@ impl<T: BufMut> ByteBufMut for T {
} }
} }
fn put_var_int(&mut self, value: &VarInt) { fn put_var_int(&mut self, var_int: &VarInt) {
value.encode(self); var_int.encode(self);
} }
fn put_bit_set(&mut self, set: &BitSet) { fn put_bit_set(&mut self, bit_set: &BitSet) {
self.put_var_int(&set.0); bit_set.encode(self);
for b in set.1 {
self.put_i64(*b);
}
} }
fn put_option<G>(&mut self, val: &Option<G>, write: impl FnOnce(&mut Self, &G)) { fn put_option<G>(&mut self, val: &Option<G>, write: impl FnOnce(&mut Self, &G)) {
@ -345,6 +354,10 @@ impl<T: BufMut> ByteBufMut for T {
fn put_varint_arr(&mut self, v: &[i32]) { fn put_varint_arr(&mut self, v: &[i32]) {
self.put_list(v, |p, &v| p.put_var_int(&v.into())) self.put_list(v, |p, &v| p.put_var_int(&v.into()))
} }
fn put_identifier(&mut self, val: &Identifier) {
val.encode(self);
}
} }
#[cfg(test)] #[cfg(test)]
@ -364,14 +377,12 @@ mod test {
bar: i32, bar: i32,
} }
let foo = Foo { bar: 69 }; let foo = Foo { bar: 69 };
let mut serializer = serializer::Serializer::new(BytesMut::new()); let mut bytes = BytesMut::new();
let mut serializer = serializer::Serializer::new(&mut bytes);
foo.serialize(&mut serializer).unwrap(); foo.serialize(&mut serializer).unwrap();
let serialized: BytesMut = serializer.into(); let deserialized: Foo =
let deserialized: Foo = Foo::deserialize(deserializer::Deserializer::new( Foo::deserialize(deserializer::Deserializer::new(&mut Bytes::from(bytes))).unwrap();
&mut Bytes::from(serialized),
))
.unwrap();
assert_eq!(foo, deserialized); assert_eq!(foo, deserialized);
} }
@ -383,14 +394,12 @@ mod test {
bar: VarInt, bar: VarInt,
} }
let foo = Foo { bar: 69.into() }; let foo = Foo { bar: 69.into() };
let mut serializer = serializer::Serializer::new(BytesMut::new()); let mut bytes = BytesMut::new();
let mut serializer = serializer::Serializer::new(&mut bytes);
foo.serialize(&mut serializer).unwrap(); foo.serialize(&mut serializer).unwrap();
let serialized: BytesMut = serializer.into(); let deserialized: Foo =
let deserialized: Foo = Foo::deserialize(deserializer::Deserializer::new( Foo::deserialize(deserializer::Deserializer::new(&mut Bytes::from(bytes))).unwrap();
&mut Bytes::from(serialized),
))
.unwrap();
assert_eq!(foo, deserialized); assert_eq!(foo, deserialized);
} }

View File

@ -1,7 +1,7 @@
use bytes::{BufMut, Bytes, BytesMut}; use bytes::{Buf, BufMut};
use serde::{de::DeserializeOwned, Serialize}; use serde::{de::DeserializeOwned, Serialize};
use crate::{ClientPacket, ServerPacket, VarIntType}; use crate::{codec::var_int::VarIntType, ClientPacket, ServerPacket};
use super::{deserializer, serializer, ReadingError}; use super::{deserializer, serializer, ReadingError};
@ -13,14 +13,10 @@ impl<P> ClientPacket for P
where where
P: Packet + Serialize, P: Packet + Serialize,
{ {
fn write(&self, bytebuf: &mut BytesMut) { fn write(&self, bytebuf: &mut impl BufMut) {
let mut serializer = serializer::Serializer::new(BytesMut::new()); let mut serializer = serializer::Serializer::new(bytebuf);
self.serialize(&mut serializer) self.serialize(&mut serializer)
.expect("Could not serialize packet"); .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);
} }
} }
@ -28,7 +24,7 @@ impl<P> ServerPacket for P
where where
P: Packet + DeserializeOwned, P: Packet + DeserializeOwned,
{ {
fn read(bytebuf: &mut Bytes) -> Result<P, ReadingError> { fn read(bytebuf: &mut impl Buf) -> Result<P, ReadingError> {
let deserializer = deserializer::Deserializer::new(bytebuf); let deserializer = deserializer::Deserializer::new(bytebuf);
P::deserialize(deserializer) P::deserialize(deserializer)
} }

View File

@ -1,6 +1,6 @@
use std::fmt::Display; use std::fmt::Display;
use bytes::{BufMut, BytesMut}; use bytes::BufMut;
use serde::{ use serde::{
ser::{self}, ser::{self},
Serialize, Serialize,
@ -9,34 +9,16 @@ use thiserror::Error;
use super::ByteBufMut; use super::ByteBufMut;
pub struct Serializer { pub struct Serializer<B: BufMut> {
pub output: BytesMut, pub output: B,
} }
impl Serializer { impl<B: BufMut> Serializer<B> {
pub fn new(buf: BytesMut) -> Self { pub fn new(buf: B) -> Self {
Self { output: buf } Self { output: buf }
} }
} }
impl From<Serializer> for BytesMut {
fn from(val: Serializer) -> Self {
val.output
}
}
impl AsRef<BytesMut> for Serializer {
fn as_ref(&self) -> &BytesMut {
&self.output
}
}
impl AsMut<BytesMut> for Serializer {
fn as_mut(&mut self) -> &mut BytesMut {
&mut self.output
}
}
#[derive(Debug, Error)] #[derive(Debug, Error)]
pub enum SerializerError { pub enum SerializerError {
#[error("serializer error {0}")] #[error("serializer error {0}")]
@ -57,7 +39,7 @@ impl ser::Error for SerializerError {
// Structs are ignored // Structs are ignored
// Iterables' values are written in order, but NO information (e.g. size) about the // Iterables' values are written in order, but NO information (e.g. size) about the
// iterable itself is written (list sizes should be a separate field) // iterable itself is written (list sizes should be a separate field)
impl ser::Serializer for &mut Serializer { impl<B: BufMut> ser::Serializer for &mut Serializer<B> {
type Ok = (); type Ok = ();
type Error = SerializerError; type Error = SerializerError;
@ -227,7 +209,7 @@ impl ser::Serializer for &mut Serializer {
} }
} }
impl ser::SerializeSeq for &mut Serializer { impl<B: BufMut> ser::SerializeSeq for &mut Serializer<B> {
// Must match the `Ok` type of the serializer. // Must match the `Ok` type of the serializer.
type Ok = (); type Ok = ();
// Must match the `Error` type of the serializer. // Must match the `Error` type of the serializer.
@ -247,7 +229,7 @@ impl ser::SerializeSeq for &mut Serializer {
} }
} }
impl ser::SerializeTuple for &mut Serializer { impl<B: BufMut> ser::SerializeTuple for &mut Serializer<B> {
type Ok = (); type Ok = ();
type Error = SerializerError; type Error = SerializerError;
@ -264,7 +246,7 @@ impl ser::SerializeTuple for &mut Serializer {
} }
// Same thing but for tuple structs. // Same thing but for tuple structs.
impl ser::SerializeTupleStruct for &mut Serializer { impl<B: BufMut> ser::SerializeTupleStruct for &mut Serializer<B> {
type Ok = (); type Ok = ();
type Error = SerializerError; type Error = SerializerError;
@ -289,7 +271,7 @@ impl ser::SerializeTupleStruct for &mut Serializer {
// //
// So the `end` method in this impl is responsible for closing both the `]` and // So the `end` method in this impl is responsible for closing both the `]` and
// the `}`. // the `}`.
impl ser::SerializeTupleVariant for &mut Serializer { impl<B: BufMut> ser::SerializeTupleVariant for &mut Serializer<B> {
type Ok = (); type Ok = ();
type Error = SerializerError; type Error = SerializerError;
@ -313,7 +295,7 @@ impl ser::SerializeTupleVariant for &mut Serializer {
// `serialize_entry` method allows serializers to optimize for the case where // `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 // key and value are both available simultaneously. In JSON it doesn't make a
// difference so the default behavior for `serialize_entry` is fine. // difference so the default behavior for `serialize_entry` is fine.
impl ser::SerializeMap for &mut Serializer { impl<B: BufMut> ser::SerializeMap for &mut Serializer<B> {
type Ok = (); type Ok = ();
type Error = SerializerError; type Error = SerializerError;
@ -349,7 +331,7 @@ impl ser::SerializeMap for &mut Serializer {
// Structs are like maps in which the keys are constrained to be compile-time // Structs are like maps in which the keys are constrained to be compile-time
// constant strings. // constant strings.
impl ser::SerializeStruct for &mut Serializer { impl<B: BufMut> ser::SerializeStruct for &mut Serializer<B> {
type Ok = (); type Ok = ();
type Error = SerializerError; type Error = SerializerError;
@ -372,7 +354,7 @@ impl ser::SerializeStruct for &mut Serializer {
// Similar to `SerializeTupleVariant`, here the `end` method is responsible for // Similar to `SerializeTupleVariant`, here the `end` method is responsible for
// closing both of the curly braces opened by `serialize_struct_variant`. // closing both of the curly braces opened by `serialize_struct_variant`.
impl ser::SerializeStructVariant for &mut Serializer { impl<B: BufMut> ser::SerializeStructVariant for &mut Serializer<B> {
type Ok = (); type Ok = ();
type Error = SerializerError; type Error = SerializerError;

View File

@ -1,6 +1,6 @@
use pumpkin_macros::client_packet; use pumpkin_macros::client_packet;
use crate::Identifier; use crate::codec::identifier::Identifier;
#[derive(serde::Serialize)] #[derive(serde::Serialize)]
#[client_packet("config:cookie_request")] #[client_packet("config:cookie_request")]

View File

@ -1,4 +1,4 @@
use bytes::BytesMut; use bytes::BufMut;
use pumpkin_macros::client_packet; use pumpkin_macros::client_packet;
use crate::{bytebuf::ByteBufMut, ClientPacket, KnownPack}; use crate::{bytebuf::ByteBufMut, ClientPacket, KnownPack};
@ -15,7 +15,7 @@ impl<'a> CKnownPacks<'a> {
} }
impl ClientPacket for CKnownPacks<'_> { impl ClientPacket for CKnownPacks<'_> {
fn write(&self, bytebuf: &mut BytesMut) { fn write(&self, bytebuf: &mut impl BufMut) {
bytebuf.put_list::<KnownPack>(self.known_packs, |p, v| { bytebuf.put_list::<KnownPack>(self.known_packs, |p, v| {
p.put_string(v.namespace); p.put_string(v.namespace);
p.put_string(v.id); p.put_string(v.id);

View File

@ -1,16 +1,16 @@
use bytes::{BufMut, BytesMut}; use bytes::{BufMut, BytesMut};
use pumpkin_macros::client_packet; use pumpkin_macros::client_packet;
use crate::{bytebuf::ByteBufMut, ClientPacket}; use crate::{bytebuf::ByteBufMut, codec::identifier::Identifier, ClientPacket};
#[client_packet("config:registry_data")] #[client_packet("config:registry_data")]
pub struct CRegistryData<'a> { pub struct CRegistryData<'a> {
registry_id: &'a str, registry_id: &'a Identifier,
entries: &'a [RegistryEntry<'a>], entries: &'a [RegistryEntry],
} }
impl<'a> CRegistryData<'a> { 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 { Self {
registry_id, registry_id,
entries, entries,
@ -18,18 +18,17 @@ impl<'a> CRegistryData<'a> {
} }
} }
pub struct RegistryEntry<'a> { pub struct RegistryEntry {
pub entry_id: &'a str, pub entry_id: Identifier,
pub data: BytesMut, pub data: Option<BytesMut>,
} }
impl ClientPacket for CRegistryData<'_> { impl ClientPacket for CRegistryData<'_> {
fn write(&self, bytebuf: &mut BytesMut) { fn write(&self, bytebuf: &mut impl BufMut) {
bytebuf.put_string(self.registry_id); bytebuf.put_identifier(self.registry_id);
bytebuf.put_list::<RegistryEntry>(self.entries, |p, v| { bytebuf.put_list::<RegistryEntry>(self.entries, |p, v| {
p.put_string(v.entry_id); p.put_identifier(&v.entry_id);
p.put_bool(!v.data.is_empty()); p.put_option(&v.data, |p, v| p.put_slice(v));
p.put_slice(&v.data);
}); });
} }
} }

View File

@ -1,4 +1,4 @@
use crate::{Identifier, VarInt}; use crate::{codec::identifier::Identifier, VarInt};
use pumpkin_macros::client_packet; use pumpkin_macros::client_packet;
#[derive(serde::Serialize)] #[derive(serde::Serialize)]

View File

@ -1,7 +1,8 @@
use crate::Identifier;
use pumpkin_macros::client_packet; use pumpkin_macros::client_packet;
use serde::Serialize; use serde::Serialize;
use crate::codec::identifier::Identifier;
#[derive(Serialize)] #[derive(Serialize)]
#[client_packet("login:cookie_request")] #[client_packet("login:cookie_request")]
/// Requests a cookie that was previously stored. /// Requests a cookie that was previously stored.

View File

@ -1,4 +1,4 @@
use bytes::BytesMut; use bytes::BufMut;
use pumpkin_macros::client_packet; use pumpkin_macros::client_packet;
use crate::{bytebuf::ByteBufMut, ClientPacket, Property}; use crate::{bytebuf::ByteBufMut, ClientPacket, Property};
@ -21,7 +21,7 @@ impl<'a> CLoginSuccess<'a> {
} }
impl ClientPacket for CLoginSuccess<'_> { impl ClientPacket for CLoginSuccess<'_> {
fn write(&self, bytebuf: &mut BytesMut) { fn write(&self, bytebuf: &mut impl BufMut) {
bytebuf.put_uuid(self.uuid); bytebuf.put_uuid(self.uuid);
bytebuf.put_string(self.username); bytebuf.put_string(self.username);
bytebuf.put_list::<Property>(self.properties, |p, v| { bytebuf.put_list::<Property>(self.properties, |p, v| {

View File

@ -1,7 +1,7 @@
use crate::bytebuf::ByteBufMut; use crate::bytebuf::ByteBufMut;
use crate::client::play::bossevent_action::BosseventAction; use crate::client::play::bossevent_action::BosseventAction;
use crate::{ClientPacket, VarInt}; use crate::{ClientPacket, VarInt};
use bytes::{BufMut, BytesMut}; use bytes::BufMut;
use pumpkin_macros::client_packet; use pumpkin_macros::client_packet;
#[client_packet("play:boss_event")] #[client_packet("play:boss_event")]
@ -17,7 +17,7 @@ impl<'a> CBossEvent<'a> {
} }
impl ClientPacket for CBossEvent<'_> { impl ClientPacket for CBossEvent<'_> {
fn write(&self, bytebuf: &mut BytesMut) { fn write(&self, bytebuf: &mut impl BufMut) {
bytebuf.put_uuid(&self.uuid); bytebuf.put_uuid(&self.uuid);
let action = &self.action; let action = &self.action;
match action { match action {

View File

@ -1,4 +1,4 @@
use crate::{bytebuf::ByteBufMut, BitSet, ClientPacket, VarInt}; use crate::{bytebuf::ByteBufMut, codec::bit_set::BitSet, ClientPacket, VarInt};
use bytes::{BufMut, BytesMut}; use bytes::{BufMut, BytesMut};
use pumpkin_macros::client_packet; use pumpkin_macros::client_packet;
@ -8,7 +8,7 @@ use pumpkin_world::{chunk::ChunkData, DIRECT_PALETTE_BITS};
pub struct CChunkData<'a>(pub &'a ChunkData); pub struct CChunkData<'a>(pub &'a ChunkData);
impl ClientPacket for CChunkData<'_> { impl ClientPacket for CChunkData<'_> {
fn write(&self, buf: &mut BytesMut) { fn write(&self, buf: &mut impl BufMut) {
// Chunk X // Chunk X
buf.put_i32(self.0.position.x); buf.put_i32(self.0.position.x);
// Chunk Z // Chunk Z
@ -113,13 +113,13 @@ impl ClientPacket for CChunkData<'_> {
// Sky Light Mask // Sky Light Mask
// All of the chunks, this is not optimal and uses way more data than needed but will be // All of the chunks, this is not optimal and uses way more data than needed but will be
// overhauled with full lighting system. // 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 // Block Light Mask
buf.put_bit_set(&BitSet(VarInt(1), &[0])); buf.put_bit_set(&BitSet(VarInt(1), vec![0]));
// Empty Sky Light Mask // 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 // 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)); buf.put_var_int(&VarInt(self.0.blocks.subchunks_len() as i32));
self.0.blocks.iter_subchunks().for_each(|chunk| { self.0.blocks.iter_subchunks().for_each(|chunk| {

View File

@ -1,4 +1,4 @@
use bytes::{BufMut, BytesMut}; use bytes::BufMut;
use pumpkin_core::text::TextComponent; use pumpkin_core::text::TextComponent;
use pumpkin_macros::client_packet; use pumpkin_macros::client_packet;
@ -29,7 +29,7 @@ impl<'a> CCommandSuggestions<'a> {
} }
impl ClientPacket for CCommandSuggestions<'_> { impl ClientPacket for CCommandSuggestions<'_> {
fn write(&self, bytebuf: &mut BytesMut) { fn write(&self, bytebuf: &mut impl BufMut) {
bytebuf.put_var_int(&self.id); bytebuf.put_var_int(&self.id);
bytebuf.put_var_int(&self.start); bytebuf.put_var_int(&self.start);
bytebuf.put_var_int(&self.length); bytebuf.put_var_int(&self.length);

View File

@ -1,4 +1,4 @@
use bytes::{BufMut, BytesMut}; use bytes::BufMut;
use pumpkin_macros::client_packet; use pumpkin_macros::client_packet;
use crate::{bytebuf::ByteBufMut, ClientPacket, VarInt}; use crate::{bytebuf::ByteBufMut, ClientPacket, VarInt};
@ -19,7 +19,7 @@ impl<'a> CCommands<'a> {
} }
impl ClientPacket for CCommands<'_> { impl ClientPacket for CCommands<'_> {
fn write(&self, bytebuf: &mut BytesMut) { fn write(&self, bytebuf: &mut impl BufMut) {
bytebuf.put_list(&self.nodes, |bytebuf, node: &ProtoNode| { bytebuf.put_list(&self.nodes, |bytebuf, node: &ProtoNode| {
node.write_to(bytebuf) node.write_to(bytebuf)
}); });
@ -52,7 +52,7 @@ impl ProtoNode<'_> {
const FLAG_HAS_REDIRECT: u8 = 8; const FLAG_HAS_REDIRECT: u8 = 8;
const FLAG_HAS_SUGGESTION_TYPE: u8 = 16; const FLAG_HAS_SUGGESTION_TYPE: u8 = 16;
pub fn write_to(&self, bytebuf: &mut BytesMut) { pub fn write_to(&self, bytebuf: &mut impl BufMut) {
// flags // flags
let flags = match self.node_type { let flags = match self.node_type {
ProtoNodeType::Root => 0, ProtoNodeType::Root => 0,
@ -188,7 +188,7 @@ impl ProtoCmdArgParser<'_> {
pub const SCORE_HOLDER_FLAG_ALLOW_MULTIPLE: u8 = 1; pub const SCORE_HOLDER_FLAG_ALLOW_MULTIPLE: u8 = 1;
pub fn write_to_buffer(&self, bytebuf: &mut BytesMut) { pub fn write_to_buffer(&self, bytebuf: &mut impl BufMut) {
match self { match self {
Self::Bool => bytebuf.put_var_int(&0.into()), Self::Bool => bytebuf.put_var_int(&0.into()),
Self::Float { min, max } => Self::write_number_arg(&1.into(), *min, *max, bytebuf), Self::Float { min, max } => Self::write_number_arg(&1.into(), *min, *max, bytebuf),
@ -270,7 +270,7 @@ impl ProtoCmdArgParser<'_> {
id: &VarInt, id: &VarInt,
min: Option<T>, min: Option<T>,
max: Option<T>, max: Option<T>,
bytebuf: &mut BytesMut, bytebuf: &mut impl BufMut,
) { ) {
let mut flags: u8 = 0; let mut flags: u8 = 0;
if min.is_some() { if min.is_some() {
@ -291,13 +291,13 @@ impl ProtoCmdArgParser<'_> {
} }
} }
fn write_with_flags(id: &VarInt, flags: u8, bytebuf: &mut BytesMut) { fn write_with_flags(id: &VarInt, flags: u8, bytebuf: &mut impl BufMut) {
bytebuf.put_var_int(id); bytebuf.put_var_int(id);
bytebuf.put_u8(flags); bytebuf.put_u8(flags);
} }
fn write_with_identifier(id: &VarInt, extra_identifier: &str, bytebuf: &mut BytesMut) { fn write_with_identifier(id: &VarInt, extra_identifier: &str, bytebuf: &mut impl BufMut) {
bytebuf.put_var_int(id); bytebuf.put_var_int(id);
bytebuf.put_string(extra_identifier); bytebuf.put_string(extra_identifier);
@ -313,29 +313,29 @@ pub enum StringProtoArgBehavior {
} }
trait NumberCmdArg { trait NumberCmdArg {
fn write(self, bytebuf: &mut BytesMut); fn write(self, bytebuf: &mut impl BufMut);
} }
impl NumberCmdArg for f32 { impl NumberCmdArg for f32 {
fn write(self, bytebuf: &mut BytesMut) { fn write(self, bytebuf: &mut impl BufMut) {
bytebuf.put_f32(self); bytebuf.put_f32(self);
} }
} }
impl NumberCmdArg for f64 { impl NumberCmdArg for f64 {
fn write(self, bytebuf: &mut BytesMut) { fn write(self, bytebuf: &mut impl BufMut) {
bytebuf.put_f64(self); bytebuf.put_f64(self);
} }
} }
impl NumberCmdArg for i32 { impl NumberCmdArg for i32 {
fn write(self, bytebuf: &mut BytesMut) { fn write(self, bytebuf: &mut impl BufMut) {
bytebuf.put_i32(self); bytebuf.put_i32(self);
} }
} }
impl NumberCmdArg for i64 { impl NumberCmdArg for i64 {
fn write(self, bytebuf: &mut BytesMut) { fn write(self, bytebuf: &mut impl BufMut) {
bytebuf.put_i64(self); bytebuf.put_i64(self);
} }
} }

View File

@ -1,7 +1,8 @@
use crate::Identifier;
use pumpkin_macros::client_packet; use pumpkin_macros::client_packet;
use serde::Serialize; use serde::Serialize;
use crate::codec::identifier::Identifier;
#[derive(Serialize)] #[derive(Serialize)]
#[client_packet("play:cookie_request")] #[client_packet("play:cookie_request")]
/// Requests a cookie that was previously stored. /// Requests a cookie that was previously stored.

View File

@ -1,4 +1,4 @@
use bytes::{BufMut, BytesMut}; use bytes::BufMut;
use pumpkin_macros::client_packet; use pumpkin_macros::client_packet;
use crate::{bytebuf::ByteBufMut, ClientPacket, IDOrSoundEvent, SoundCategory, SoundEvent, VarInt}; use crate::{bytebuf::ByteBufMut, ClientPacket, IDOrSoundEvent, SoundCategory, SoundEvent, VarInt};
@ -39,11 +39,11 @@ impl CEntitySoundEffect {
} }
impl ClientPacket for CEntitySoundEffect { impl ClientPacket for CEntitySoundEffect {
fn write(&self, bytebuf: &mut BytesMut) { fn write(&self, bytebuf: &mut impl BufMut) {
bytebuf.put_var_int(&self.sound_event.id); bytebuf.put_var_int(&self.sound_event.id);
if self.sound_event.id.0 == 0 { if self.sound_event.id.0 == 0 {
if let Some(test) = &self.sound_event.sound_event { 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| { bytebuf.put_option(&test.range, |p, v| {
p.put_f32(*v); p.put_f32(*v);

View File

@ -1,7 +1,7 @@
use pumpkin_macros::client_packet; use pumpkin_macros::client_packet;
use serde::Serialize; use serde::Serialize;
use crate::{VarInt, VarLong}; use crate::{codec::var_long::VarLong, VarInt};
#[derive(Serialize)] #[derive(Serialize)]
#[client_packet("play:initialize_border")] #[client_packet("play:initialize_border")]

View File

@ -3,7 +3,7 @@ use pumpkin_core::math::position::WorldPosition;
use pumpkin_macros::client_packet; use pumpkin_macros::client_packet;
use serde::Serialize; use serde::Serialize;
use crate::VarInt; use crate::{codec::identifier::Identifier, VarInt};
#[derive(Serialize)] #[derive(Serialize)]
#[client_packet("play:login")] #[client_packet("play:login")]
@ -11,7 +11,7 @@ pub struct CLogin<'a> {
entity_id: i32, entity_id: i32,
is_hardcore: bool, is_hardcore: bool,
dimension_count: VarInt, dimension_count: VarInt,
dimension_names: &'a [&'a str], dimension_names: &'a [Identifier],
max_players: VarInt, max_players: VarInt,
view_distance: VarInt, view_distance: VarInt,
simulated_distance: VarInt, simulated_distance: VarInt,
@ -20,13 +20,13 @@ pub struct CLogin<'a> {
limited_crafting: bool, limited_crafting: bool,
// Spawn Info // Spawn Info
dimension_type: VarInt, dimension_type: VarInt,
dimension_name: &'a str, dimension_name: Identifier,
hashed_seed: i64, hashed_seed: i64,
game_mode: u8, game_mode: u8,
previous_gamemode: i8, previous_gamemode: i8,
debug: bool, debug: bool,
is_flat: bool, is_flat: bool,
death_dimension_name: Option<(&'a str, WorldPosition)>, death_dimension_name: Option<(Identifier, WorldPosition)>,
portal_cooldown: VarInt, portal_cooldown: VarInt,
sealevel: VarInt, sealevel: VarInt,
enforce_secure_chat: bool, enforce_secure_chat: bool,
@ -37,7 +37,7 @@ impl<'a> CLogin<'a> {
pub fn new( pub fn new(
entity_id: i32, entity_id: i32,
is_hardcore: bool, is_hardcore: bool,
dimension_names: &'a [&'a str], dimension_names: &'a [Identifier],
max_players: VarInt, max_players: VarInt,
view_distance: VarInt, view_distance: VarInt,
simulated_distance: VarInt, simulated_distance: VarInt,
@ -45,13 +45,13 @@ impl<'a> CLogin<'a> {
enabled_respawn_screen: bool, enabled_respawn_screen: bool,
limited_crafting: bool, limited_crafting: bool,
dimension_type: VarInt, dimension_type: VarInt,
dimension_name: &'a str, dimension_name: Identifier,
hashed_seed: i64, hashed_seed: i64,
game_mode: u8, game_mode: u8,
previous_gamemode: i8, previous_gamemode: i8,
debug: bool, debug: bool,
is_flat: bool, is_flat: bool,
death_dimension_name: Option<(&'a str, WorldPosition)>, death_dimension_name: Option<(Identifier, WorldPosition)>,
portal_cooldown: VarInt, portal_cooldown: VarInt,
sealevel: VarInt, sealevel: VarInt,
enforce_secure_chat: bool, enforce_secure_chat: bool,

View File

@ -3,7 +3,7 @@ use pumpkin_core::text::TextComponent;
use pumpkin_macros::client_packet; use pumpkin_macros::client_packet;
use serde::Serialize; use serde::Serialize;
use crate::{BitSet, VarInt}; use crate::{codec::bit_set::BitSet, VarInt};
#[derive(Serialize)] #[derive(Serialize)]
#[client_packet("play:player_chat")] #[client_packet("play:player_chat")]
@ -18,7 +18,7 @@ pub struct CPlayerChatMessage<'a> {
previous_messages_count: VarInt, previous_messages_count: VarInt,
previous_messages: &'a [PreviousMessage<'a>], // max 20 previous_messages: &'a [PreviousMessage<'a>], // max 20
unsigned_content: Option<TextComponent<'a>>, unsigned_content: Option<TextComponent<'a>>,
filter_type: FilterType<'a>, filter_type: FilterType,
chat_type: VarInt, chat_type: VarInt,
sender_name: TextComponent<'a>, sender_name: TextComponent<'a>,
target_name: Option<TextComponent<'a>>, target_name: Option<TextComponent<'a>>,
@ -35,7 +35,7 @@ impl<'a> CPlayerChatMessage<'a> {
salt: i64, salt: i64,
previous_messages: &'a [PreviousMessage<'a>], previous_messages: &'a [PreviousMessage<'a>],
unsigned_content: Option<TextComponent<'a>>, unsigned_content: Option<TextComponent<'a>>,
filter_type: FilterType<'a>, filter_type: FilterType,
chat_type: VarInt, chat_type: VarInt,
sender_name: TextComponent<'a>, sender_name: TextComponent<'a>,
target_name: Option<TextComponent<'a>>, target_name: Option<TextComponent<'a>>,
@ -66,11 +66,11 @@ pub struct PreviousMessage<'a> {
#[derive(Serialize)] #[derive(Serialize)]
#[repr(i32)] #[repr(i32)]
pub enum FilterType<'a> { pub enum FilterType {
/// Message is not filtered at all /// Message is not filtered at all
PassThrough = 0, PassThrough = 0,
/// Message is fully filtered /// Message is fully filtered
FullyFiltered = 1, FullyFiltered = 1,
/// Only some characters in the message are filtered /// Only some characters in the message are filtered
PartiallyFiltered(BitSet<'a>) = 2, PartiallyFiltered(BitSet) = 2,
} }

View File

@ -1,4 +1,4 @@
use bytes::{BufMut, BytesMut}; use bytes::BufMut;
use pumpkin_macros::client_packet; use pumpkin_macros::client_packet;
use crate::{bytebuf::ByteBufMut, ClientPacket, Property}; use crate::{bytebuf::ByteBufMut, ClientPacket, Property};
@ -23,7 +23,7 @@ impl<'a> CPlayerInfoUpdate<'a> {
} }
impl ClientPacket for CPlayerInfoUpdate<'_> { impl ClientPacket for CPlayerInfoUpdate<'_> {
fn write(&self, bytebuf: &mut BytesMut) { fn write(&self, bytebuf: &mut impl BufMut) {
bytebuf.put_i8(self.actions); bytebuf.put_i8(self.actions);
bytebuf.put_list::<Player>(self.players, |p, v| { bytebuf.put_list::<Player>(self.players, |p, v| {
p.put_uuid(&v.uuid); p.put_uuid(&v.uuid);

View File

@ -1,4 +1,4 @@
use bytes::{BufMut, BytesMut}; use bytes::BufMut;
use pumpkin_core::math::vector3::Vector3; use pumpkin_core::math::vector3::Vector3;
use pumpkin_macros::client_packet; use pumpkin_macros::client_packet;
@ -35,7 +35,7 @@ impl<'a> CPlayerPosition<'a> {
} }
impl ClientPacket for CPlayerPosition<'_> { impl ClientPacket for CPlayerPosition<'_> {
fn write(&self, bytebuf: &mut BytesMut) { fn write(&self, bytebuf: &mut impl BufMut) {
bytebuf.put_var_int(&self.teleport_id); bytebuf.put_var_int(&self.teleport_id);
bytebuf.put_f64(self.position.x); bytebuf.put_f64(self.position.x);
bytebuf.put_f64(self.position.y); bytebuf.put_f64(self.position.y);

View File

@ -2,35 +2,35 @@ use pumpkin_core::math::position::WorldPosition;
use pumpkin_macros::client_packet; use pumpkin_macros::client_packet;
use serde::Serialize; use serde::Serialize;
use crate::VarInt; use crate::{codec::identifier::Identifier, VarInt};
#[derive(Serialize)] #[derive(Serialize)]
#[client_packet("play:respawn")] #[client_packet("play:respawn")]
pub struct CRespawn<'a> { pub struct CRespawn {
dimension_type: VarInt, dimension_type: VarInt,
dimension_name: &'a str, dimension_name: Identifier,
hashed_seed: i64, hashed_seed: i64,
game_mode: u8, game_mode: u8,
previous_gamemode: i8, previous_gamemode: i8,
debug: bool, debug: bool,
is_flat: bool, is_flat: bool,
death_dimension_name: Option<(&'a str, WorldPosition)>, death_dimension_name: Option<(Identifier, WorldPosition)>,
portal_cooldown: VarInt, portal_cooldown: VarInt,
sealevel: VarInt, sealevel: VarInt,
data_kept: u8, data_kept: u8,
} }
impl<'a> CRespawn<'a> { impl CRespawn {
#[expect(clippy::too_many_arguments)] #[expect(clippy::too_many_arguments)]
pub fn new( pub fn new(
dimension_type: VarInt, dimension_type: VarInt,
dimension_name: &'a str, dimension_name: Identifier,
hashed_seed: i64, hashed_seed: i64,
game_mode: u8, game_mode: u8,
previous_gamemode: i8, previous_gamemode: i8,
debug: bool, debug: bool,
is_flat: bool, is_flat: bool,
death_dimension_name: Option<(&'a str, WorldPosition)>, death_dimension_name: Option<(Identifier, WorldPosition)>,
portal_cooldown: VarInt, portal_cooldown: VarInt,
sealevel: VarInt, sealevel: VarInt,
data_kept: u8, data_kept: u8,

View File

@ -1,7 +1,7 @@
use pumpkin_macros::client_packet; use pumpkin_macros::client_packet;
use serde::Serialize; use serde::Serialize;
use crate::VarLong; use crate::codec::var_long::VarLong;
#[derive(Serialize)] #[derive(Serialize)]
#[client_packet("play:set_border_lerp_size")] #[client_packet("play:set_border_lerp_size")]

View File

@ -1,4 +1,4 @@
use bytes::{BufMut, BytesMut}; use bytes::BufMut;
use pumpkin_macros::client_packet; use pumpkin_macros::client_packet;
use crate::{bytebuf::ByteBufMut, ClientPacket, IDOrSoundEvent, SoundCategory, SoundEvent, VarInt}; use crate::{bytebuf::ByteBufMut, ClientPacket, IDOrSoundEvent, SoundCategory, SoundEvent, VarInt};
@ -45,11 +45,11 @@ impl CSoundEffect {
} }
impl ClientPacket for CSoundEffect { impl ClientPacket for CSoundEffect {
fn write(&self, bytebuf: &mut BytesMut) { fn write(&self, bytebuf: &mut impl BufMut) {
bytebuf.put_var_int(&self.sound_event.id); bytebuf.put_var_int(&self.sound_event.id);
if self.sound_event.id.0 == 0 { if self.sound_event.id.0 == 0 {
if let Some(test) = &self.sound_event.sound_event { 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| { bytebuf.put_option(&test.range, |p, v| {
p.put_f32(*v); p.put_f32(*v);

View File

@ -1,4 +1,4 @@
use crate::{Identifier, VarInt}; use crate::{codec::identifier::Identifier, VarInt};
use pumpkin_macros::client_packet; use pumpkin_macros::client_packet;
use serde::Serialize; use serde::Serialize;

View File

@ -1,4 +1,4 @@
use bytes::{BufMut, BytesMut}; use bytes::BufMut;
use pumpkin_core::math::vector3::Vector3; use pumpkin_core::math::vector3::Vector3;
use pumpkin_macros::client_packet; use pumpkin_macros::client_packet;
@ -38,7 +38,7 @@ impl<'a> CTeleportEntity<'a> {
} }
impl ClientPacket for CTeleportEntity<'_> { impl ClientPacket for CTeleportEntity<'_> {
fn write(&self, bytebuf: &mut BytesMut) { fn write(&self, bytebuf: &mut impl BufMut) {
bytebuf.put_var_int(&self.entity_id); bytebuf.put_var_int(&self.entity_id);
bytebuf.put_f64(self.position.x); bytebuf.put_f64(self.position.x);
bytebuf.put_f64(self.position.y); bytebuf.put_f64(self.position.y);

View File

@ -1,4 +1,4 @@
use bytes::{BufMut, BytesMut}; use bytes::BufMut;
use pumpkin_core::text::TextComponent; use pumpkin_core::text::TextComponent;
use pumpkin_macros::client_packet; use pumpkin_macros::client_packet;
@ -32,7 +32,7 @@ impl<'a> CUpdateObjectives<'a> {
} }
impl ClientPacket for CUpdateObjectives<'_> { impl ClientPacket for CUpdateObjectives<'_> {
fn write(&self, bytebuf: &mut BytesMut) { fn write(&self, bytebuf: &mut impl BufMut) {
bytebuf.put_string(self.objective_name); bytebuf.put_string(self.objective_name);
bytebuf.put_u8(self.mode); bytebuf.put_u8(self.mode);
if self.mode == 0 || self.mode == 2 { if self.mode == 0 || self.mode == 2 {

View File

@ -1,48 +1,28 @@
use std::num::NonZeroU16; use std::num::NonZeroU16;
use bytebuf::{packet_id::Packet, ReadingError}; use bytebuf::{packet_id::Packet, ReadingError};
use bytes::{Bytes, BytesMut}; use bytes::{Buf, BufMut, Bytes};
use codec::{identifier::Identifier, var_int::VarInt};
use pumpkin_core::text::{style::Style, TextComponent}; use pumpkin_core::text::{style::Style, TextComponent};
use serde::{Deserialize, Serialize, Serializer}; use serde::{Deserialize, Serialize};
pub mod bytebuf; pub mod bytebuf;
pub mod client; pub mod client;
pub mod codec;
pub mod packet_decoder; pub mod packet_decoder;
pub mod packet_encoder; pub mod packet_encoder;
pub mod query; pub mod query;
pub mod server; pub mod server;
pub mod slot; pub mod slot;
mod var_int;
pub use var_int::*;
mod var_long;
pub use var_long::*;
/// To current Minecraft protocol /// To current Minecraft protocol
/// Don't forget to change this when porting /// Don't forget to change this when porting
pub const CURRENT_MC_PROTOCOL: NonZeroU16 = unsafe { NonZeroU16::new_unchecked(769) }; pub const CURRENT_MC_PROTOCOL: NonZeroU16 = unsafe { NonZeroU16::new_unchecked(769) };
pub const MAX_PACKET_SIZE: i32 = 2097152; pub const MAX_PACKET_SIZE: i32 = 2097152;
/// usally uses a namespace like "minecraft:thing"
pub type Identifier = String;
pub type VarIntType = i32;
pub type VarLongType = i64;
pub type FixedBitSet = bytes::Bytes; pub type FixedBitSet = bytes::Bytes;
pub struct BitSet<'a>(pub VarInt, pub &'a [i64]);
impl Serialize for BitSet<'_> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
// TODO: make this right
(&self.0, self.1).serialize(serializer)
}
}
#[derive(Debug, PartialEq, Clone, Copy)] #[derive(Debug, PartialEq, Clone, Copy)]
pub enum ConnectionState { pub enum ConnectionState {
HandShake, HandShake,
@ -89,7 +69,7 @@ pub struct IDOrSoundEvent {
#[derive(Serialize)] #[derive(Serialize)]
pub struct SoundEvent { pub struct SoundEvent {
pub sound_name: String, pub sound_name: Identifier,
pub range: Option<f32>, pub range: Option<f32>,
} }
@ -99,11 +79,11 @@ pub struct RawPacket {
} }
pub trait ClientPacket: Packet { pub trait ClientPacket: Packet {
fn write(&self, bytebuf: &mut BytesMut); fn write(&self, bytebuf: &mut impl BufMut);
} }
pub trait ServerPacket: Packet + Sized { pub trait ServerPacket: Packet + Sized {
fn read(bytebuf: &mut Bytes) -> Result<Self, ReadingError>; fn read(bytebuf: &mut impl Buf) -> Result<Self, ReadingError>;
} }
#[derive(Serialize)] #[derive(Serialize)]

View File

@ -3,7 +3,10 @@ use bytes::{Buf, Bytes, BytesMut};
use libdeflater::{DecompressionError, Decompressor}; use libdeflater::{DecompressionError, Decompressor};
use thiserror::Error; use thiserror::Error;
use crate::{RawPacket, VarInt, VarIntDecodeError, MAX_PACKET_SIZE}; use crate::{
codec::{Codec, DecodeError},
RawPacket, VarInt, MAX_PACKET_SIZE,
};
type Cipher = cfb8::Decryptor<aes::Aes128>; type Cipher = cfb8::Decryptor<aes::Aes128>;
@ -38,8 +41,8 @@ impl PacketDecoder {
let packet_len = match VarInt::decode(&mut r) { let packet_len = match VarInt::decode(&mut r) {
Ok(len) => len, Ok(len) => len,
Err(VarIntDecodeError::Incomplete) => return Ok(None), Err(DecodeError::Incomplete) => return Ok(None),
Err(VarIntDecodeError::TooLarge) => Err(PacketDecodeError::MalformedLength)?, Err(DecodeError::TooLarge) => Err(PacketDecodeError::MalformedLength)?,
}; };
let packet_len = packet_len.0; let packet_len = packet_len.0;

View File

@ -5,7 +5,7 @@ use thiserror::Error;
use libdeflater::{CompressionLvl, Compressor}; use libdeflater::{CompressionLvl, Compressor};
use crate::{ClientPacket, VarInt, MAX_PACKET_SIZE}; use crate::{codec::Codec, ClientPacket, VarInt, MAX_PACKET_SIZE};
type Cipher = cfb8::Encryptor<aes::Aes128>; type Cipher = cfb8::Encryptor<aes::Aes128>;
@ -221,9 +221,8 @@ pub enum PacketEncodeError {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
use crate::bytebuf::packet_id::Packet;
use crate::client::status::CStatusResponse; use crate::client::status::CStatusResponse;
use crate::VarIntDecodeError; use crate::{bytebuf::packet_id::Packet, codec::DecodeError};
use aes::Aes128; use aes::Aes128;
use cfb8::cipher::AsyncStreamCipher; use cfb8::cipher::AsyncStreamCipher;
use cfb8::Decryptor as Cfb8Decryptor; use cfb8::Decryptor as Cfb8Decryptor;
@ -247,7 +246,7 @@ mod tests {
} }
/// Helper function to decode a VarInt from bytes /// Helper function to decode a VarInt from bytes
fn decode_varint(buffer: &mut &[u8]) -> Result<i32, VarIntDecodeError> { fn decode_varint(buffer: &mut &[u8]) -> Result<i32, DecodeError> {
VarInt::decode(buffer).map(|varint| varint.0) VarInt::decode(buffer).map(|varint| varint.0)
} }

View File

@ -1,10 +1,11 @@
use bytes::Bytes; use bytes::Buf;
use pumpkin_macros::server_packet; use pumpkin_macros::server_packet;
use serde::de; use serde::de;
use crate::{ use crate::{
bytebuf::{ByteBuf, ReadingError}, bytebuf::{ByteBuf, ReadingError},
Identifier, ServerPacket, VarInt, codec::identifier::Identifier,
ServerPacket, VarInt,
}; };
#[server_packet("config:cookie_response")] #[server_packet("config:cookie_response")]
@ -20,8 +21,8 @@ pub struct SCookieResponse {
const MAX_PAYLOAD_SIZE: i32 = 5120; const MAX_PAYLOAD_SIZE: i32 = 5120;
impl ServerPacket for SCookieResponse { impl ServerPacket for SCookieResponse {
fn read(bytebuf: &mut Bytes) -> Result<Self, ReadingError> { fn read(bytebuf: &mut impl Buf) -> Result<Self, ReadingError> {
let key = bytebuf.try_get_string()?; let key = bytebuf.try_get_identifer()?;
let has_payload = bytebuf.try_get_bool()?; let has_payload = bytebuf.try_get_bool()?;
if !has_payload { if !has_payload {

View File

@ -1,9 +1,10 @@
use bytes::Bytes; use bytes::Buf;
use pumpkin_macros::server_packet; use pumpkin_macros::server_packet;
use crate::{ use crate::{
bytebuf::{ByteBuf, ReadingError}, bytebuf::{ByteBuf, ReadingError},
Identifier, ServerPacket, codec::identifier::Identifier,
ServerPacket,
}; };
#[server_packet("config:custom_payload")] #[server_packet("config:custom_payload")]
@ -13,10 +14,10 @@ pub struct SPluginMessage {
} }
impl ServerPacket for SPluginMessage { impl ServerPacket for SPluginMessage {
fn read(bytebuf: &mut Bytes) -> Result<Self, ReadingError> { fn read(bytebuf: &mut impl Buf) -> Result<Self, ReadingError> {
Ok(Self { Ok(Self {
channel: bytebuf.try_get_string()?, channel: bytebuf.try_get_identifer()?,
data: bytebuf.split_to(bytebuf.len()), data: bytebuf.try_copy_to_bytes(bytebuf.remaining())?,
}) })
} }
} }

View File

@ -1,4 +1,4 @@
use bytes::Bytes; use bytes::Buf;
use pumpkin_macros::server_packet; use pumpkin_macros::server_packet;
use crate::{ use crate::{
@ -15,7 +15,7 @@ pub struct SHandShake {
} }
impl ServerPacket for SHandShake { impl ServerPacket for SHandShake {
fn read(bytebuf: &mut Bytes) -> Result<Self, ReadingError> { fn read(bytebuf: &mut impl Buf) -> Result<Self, ReadingError> {
Ok(Self { Ok(Self {
protocol_version: bytebuf.try_get_var_int()?, protocol_version: bytebuf.try_get_var_int()?,
server_address: bytebuf.try_get_string_len(255)?, server_address: bytebuf.try_get_string_len(255)?,

View File

@ -1,8 +1,9 @@
use crate::{ use crate::{
bytebuf::{ByteBuf, ReadingError}, bytebuf::{ByteBuf, ReadingError},
Identifier, ServerPacket, VarInt, codec::identifier::Identifier,
ServerPacket, VarInt,
}; };
use bytes::Bytes; use bytes::Buf;
use pumpkin_macros::server_packet; use pumpkin_macros::server_packet;
use serde::de; use serde::de;
@ -19,8 +20,8 @@ pub struct SCookieResponse {
const MAX_PAYLOAD_SIZE: i32 = 5120; const MAX_PAYLOAD_SIZE: i32 = 5120;
impl ServerPacket for SCookieResponse { impl ServerPacket for SCookieResponse {
fn read(bytebuf: &mut Bytes) -> Result<Self, ReadingError> { fn read(bytebuf: &mut impl Buf) -> Result<Self, ReadingError> {
let key = bytebuf.try_get_string()?; let key = bytebuf.try_get_identifer()?;
let has_payload = bytebuf.try_get_bool()?; let has_payload = bytebuf.try_get_bool()?;
if !has_payload { if !has_payload {

View File

@ -1,4 +1,4 @@
use bytes::Bytes; use bytes::Buf;
use pumpkin_macros::server_packet; use pumpkin_macros::server_packet;
use crate::{ use crate::{
@ -15,7 +15,7 @@ pub struct SEncryptionResponse {
} }
impl ServerPacket for SEncryptionResponse { impl ServerPacket for SEncryptionResponse {
fn read(bytebuf: &mut Bytes) -> Result<Self, ReadingError> { fn read(bytebuf: &mut impl Buf) -> Result<Self, ReadingError> {
let shared_secret_length = bytebuf.try_get_var_int()?; let shared_secret_length = bytebuf.try_get_var_int()?;
let shared_secret = bytebuf.try_copy_to_bytes(shared_secret_length.0 as usize)?; let shared_secret = bytebuf.try_copy_to_bytes(shared_secret_length.0 as usize)?;
let verify_token_length = bytebuf.try_get_var_int()?; let verify_token_length = bytebuf.try_get_var_int()?;

View File

@ -1,4 +1,4 @@
use bytes::Bytes; use bytes::Buf;
use pumpkin_macros::server_packet; use pumpkin_macros::server_packet;
use crate::{ use crate::{
@ -13,7 +13,7 @@ pub struct SLoginStart {
} }
impl ServerPacket for SLoginStart { impl ServerPacket for SLoginStart {
fn read(bytebuf: &mut Bytes) -> Result<Self, ReadingError> { fn read(bytebuf: &mut impl Buf) -> Result<Self, ReadingError> {
Ok(Self { Ok(Self {
name: bytebuf.try_get_string_len(16)?, name: bytebuf.try_get_string_len(16)?,
uuid: bytebuf.try_get_uuid()?, uuid: bytebuf.try_get_uuid()?,

View File

@ -2,7 +2,7 @@ use crate::{
bytebuf::{ByteBuf, ReadingError}, bytebuf::{ByteBuf, ReadingError},
ServerPacket, VarInt, ServerPacket, VarInt,
}; };
use bytes::Bytes; use bytes::{Buf, Bytes};
use pumpkin_macros::server_packet; use pumpkin_macros::server_packet;
#[server_packet("login:custom_query_answer")] #[server_packet("login:custom_query_answer")]
@ -12,10 +12,10 @@ pub struct SLoginPluginResponse {
} }
impl ServerPacket for SLoginPluginResponse { impl ServerPacket for SLoginPluginResponse {
fn read(bytebuf: &mut Bytes) -> Result<Self, ReadingError> { fn read(bytebuf: &mut impl Buf) -> Result<Self, ReadingError> {
Ok(Self { Ok(Self {
message_id: bytebuf.try_get_var_int()?, message_id: bytebuf.try_get_var_int()?,
data: bytebuf.try_get_option(|v| Ok(v.split_to(v.len())))?, data: bytebuf.try_get_option(|v| v.try_copy_to_bytes(v.remaining()))?,
}) })
} }
} }

View File

@ -1,4 +1,4 @@
use bytes::Bytes; use bytes::{Buf, Bytes};
use pumpkin_macros::server_packet; use pumpkin_macros::server_packet;
use crate::{ use crate::{
@ -19,7 +19,7 @@ pub struct SChatMessage {
// TODO // TODO
impl ServerPacket for SChatMessage { impl ServerPacket for SChatMessage {
fn read(bytebuf: &mut Bytes) -> Result<Self, ReadingError> { fn read(bytebuf: &mut impl Buf) -> Result<Self, ReadingError> {
Ok(Self { Ok(Self {
message: bytebuf.try_get_string()?, message: bytebuf.try_get_string()?,
timestamp: bytebuf.try_get_i64()?, timestamp: bytebuf.try_get_i64()?,

View File

@ -1,8 +1,9 @@
use crate::{ use crate::{
bytebuf::{ByteBuf, ReadingError}, bytebuf::{ByteBuf, ReadingError},
Identifier, ServerPacket, VarInt, codec::identifier::Identifier,
ServerPacket, VarInt,
}; };
use bytes::Bytes; use bytes::Buf;
use pumpkin_macros::server_packet; use pumpkin_macros::server_packet;
use serde::de; use serde::de;
@ -19,8 +20,8 @@ pub struct SCookieResponse {
const MAX_PAYLOAD_SIZE: i32 = 5120; const MAX_PAYLOAD_SIZE: i32 = 5120;
impl ServerPacket for SCookieResponse { impl ServerPacket for SCookieResponse {
fn read(bytebuf: &mut Bytes) -> Result<Self, ReadingError> { fn read(bytebuf: &mut impl Buf) -> Result<Self, ReadingError> {
let key = bytebuf.try_get_string()?; let key = bytebuf.try_get_identifer()?;
let has_payload = bytebuf.try_get_bool()?; let has_payload = bytebuf.try_get_bool()?;
if !has_payload { if !has_payload {

View File

@ -1,4 +1,4 @@
use bytes::Bytes; use bytes::Buf;
use num_derive::FromPrimitive; use num_derive::FromPrimitive;
use num_traits::FromPrimitive; use num_traits::FromPrimitive;
use pumpkin_core::math::vector3::Vector3; use pumpkin_core::math::vector3::Vector3;
@ -20,7 +20,7 @@ pub struct SInteract {
// Great job Mojang ;D // Great job Mojang ;D
impl ServerPacket for SInteract { impl ServerPacket for SInteract {
fn read(bytebuf: &mut Bytes) -> Result<Self, ReadingError> { fn read(bytebuf: &mut impl Buf) -> Result<Self, ReadingError> {
let entity_id = bytebuf.try_get_var_int()?; let entity_id = bytebuf.try_get_var_int()?;
let typ = bytebuf.try_get_var_int()?; let typ = bytebuf.try_get_var_int()?;
let action = ActionType::from_i32(typ.0) let action = ActionType::from_i32(typ.0)

View File

@ -1,4 +1,4 @@
use bytes::Bytes; use bytes::Buf;
use num_derive::FromPrimitive; use num_derive::FromPrimitive;
use pumpkin_macros::server_packet; use pumpkin_macros::server_packet;
@ -27,7 +27,7 @@ pub enum Action {
} }
impl ServerPacket for SPlayerCommand { impl ServerPacket for SPlayerCommand {
fn read(bytebuf: &mut Bytes) -> Result<Self, ReadingError> { fn read(bytebuf: &mut impl Buf) -> Result<Self, ReadingError> {
Ok(Self { Ok(Self {
entity_id: bytebuf.try_get_var_int()?, entity_id: bytebuf.try_get_var_int()?,
action: bytebuf.try_get_var_int()?, action: bytebuf.try_get_var_int()?,

View File

@ -1,151 +0,0 @@
use std::num::NonZeroUsize;
use bytes::{Buf, BufMut};
use serde::{
de::{SeqAccess, Visitor},
Deserialize, Deserializer, Serialize, Serializer,
};
use thiserror::Error;
pub type VarIntType = i32;
/**
* A variable-length integer type used by the Minecraft network protocol.
*/
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct VarInt(pub VarIntType);
impl VarInt {
/// The maximum number of bytes a `VarInt` can occupy.
pub const MAX_SIZE: NonZeroUsize = unsafe { NonZeroUsize::new_unchecked(5) };
/// Returns the exact number of bytes this varint will write when
/// [`Encode::encode`] is called, assuming no error occurs.
pub const fn written_size(self) -> usize {
match self.0 {
0 => 1,
n => (31 - n.leading_zeros() as usize) / 7 + 1,
}
}
pub fn encode(&self, w: &mut impl BufMut) {
let mut val = self.0;
for _ in 0..Self::MAX_SIZE.get() {
let b: u8 = val as u8 & 0b01111111;
val >>= 7;
w.put_u8(if val == 0 { b } else { b | 0b10000000 });
if val == 0 {
break;
}
}
}
pub fn decode(r: &mut impl Buf) -> Result<Self, VarIntDecodeError> {
let mut val = 0;
for i in 0..Self::MAX_SIZE.get() {
if !r.has_remaining() {
return Err(VarIntDecodeError::Incomplete);
}
let byte = r.get_u8();
val |= (i32::from(byte) & 0x7F) << (i * 7);
if byte & 0x80 == 0 {
return Ok(VarInt(val));
}
}
Err(VarIntDecodeError::TooLarge)
}
}
impl From<i32> for VarInt {
fn from(value: i32) -> Self {
VarInt(value)
}
}
impl From<u32> for VarInt {
fn from(value: u32) -> Self {
VarInt(value as i32)
}
}
impl From<u8> for VarInt {
fn from(value: u8) -> Self {
VarInt(value as i32)
}
}
impl From<usize> for VarInt {
fn from(value: usize) -> Self {
VarInt(value as i32)
}
}
impl From<VarInt> for i32 {
fn from(value: VarInt) -> Self {
value.0
}
}
#[derive(Copy, Clone, PartialEq, Eq, Debug, Error)]
pub enum VarIntDecodeError {
#[error("Incomplete VarInt decode")]
Incomplete,
#[error("VarInt is too large")]
TooLarge,
}
impl Serialize for VarInt {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let mut value = self.0 as u32;
let mut buf = Vec::new();
while value > 0x7F {
buf.put_u8(value as u8 | 0x80);
value >>= 7;
}
buf.put_u8(value as u8);
serializer.serialize_bytes(&buf)
}
}
impl<'de> Deserialize<'de> for VarInt {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
struct VarIntVisitor;
impl<'de> Visitor<'de> for VarIntVisitor {
type Value = VarInt;
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
formatter.write_str("a valid VarInt encoded in a byte sequence")
}
fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
where
A: SeqAccess<'de>,
{
let mut val = 0;
for i in 0..VarInt::MAX_SIZE.get() {
if let Some(byte) = seq.next_element::<u8>()? {
val |= (i32::from(byte) & 0b01111111) << (i * 7);
if byte & 0b10000000 == 0 {
return Ok(VarInt(val));
}
} else {
break;
}
}
Err(serde::de::Error::custom("VarInt was too large"))
}
}
deserializer.deserialize_seq(VarIntVisitor)
}
}

View File

@ -1,152 +0,0 @@
use std::num::NonZeroUsize;
use bytes::{Buf, BufMut};
use serde::{
de::{self, SeqAccess, Visitor},
Deserialize, Deserializer, Serialize, Serializer,
};
use thiserror::Error;
pub type VarLongType = i64;
/**
* A variable-length long type used by the Minecraft network protocol.
*/
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct VarLong(pub VarLongType);
impl VarLong {
/// The maximum number of bytes a `VarLong`
pub const MAX_SIZE: NonZeroUsize = unsafe { NonZeroUsize::new_unchecked(10) };
/// Returns the exact number of bytes this varlong will write when
/// [`Encode::encode`] is called, assuming no error occurs.
pub const fn written_size(self) -> usize {
match self.0 {
0 => 1,
n => (31 - n.leading_zeros() as usize) / 7 + 1,
}
}
pub fn encode(&self, w: &mut impl BufMut) {
let mut x = self.0;
for _ in 0..Self::MAX_SIZE.get() {
let byte = (x & 0x7F) as u8;
x >>= 7;
if x == 0 {
w.put_slice(&[byte]);
break;
}
w.put_slice(&[byte | 0x80]);
}
}
pub fn decode(r: &mut impl Buf) -> Result<Self, VarLongDecodeError> {
let mut val = 0;
for i in 0..Self::MAX_SIZE.get() {
if !r.has_remaining() {
return Err(VarLongDecodeError::Incomplete);
}
let byte = r.get_u8();
val |= (i64::from(byte) & 0b01111111) << (i * 7);
if byte & 0b10000000 == 0 {
return Ok(VarLong(val));
}
}
Err(VarLongDecodeError::TooLarge)
}
}
impl From<i64> for VarLong {
fn from(value: i64) -> Self {
VarLong(value)
}
}
impl From<u32> for VarLong {
fn from(value: u32) -> Self {
VarLong(value as i64)
}
}
impl From<u8> for VarLong {
fn from(value: u8) -> Self {
VarLong(value as i64)
}
}
impl From<usize> for VarLong {
fn from(value: usize) -> Self {
VarLong(value as i64)
}
}
impl From<VarLong> for i64 {
fn from(value: VarLong) -> Self {
value.0
}
}
#[derive(Copy, Clone, PartialEq, Eq, Debug, Error)]
pub enum VarLongDecodeError {
#[error("incomplete VarLong decode")]
Incomplete,
#[error("VarLong is too large")]
TooLarge,
}
impl Serialize for VarLong {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let mut value = self.0 as u64;
let mut buf = Vec::new();
while value > 0x7F {
buf.put_u8(value as u8 | 0x80);
value >>= 7;
}
buf.put_u8(value as u8);
serializer.serialize_bytes(&buf)
}
}
impl<'de> Deserialize<'de> for VarLong {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
struct VarLongVisitor;
impl<'de> Visitor<'de> for VarLongVisitor {
type Value = VarLong;
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
formatter.write_str("a valid VarInt encoded in a byte sequence")
}
fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
where
A: SeqAccess<'de>,
{
let mut val = 0;
for i in 0..VarLong::MAX_SIZE.get() {
if let Some(byte) = seq.next_element::<u8>()? {
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)
}
}

View File

@ -1,7 +1,8 @@
use pumpkin_protocol::codec::identifier::Identifier;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
pub struct BannerPattern { pub struct BannerPattern {
asset_id: String, asset_id: Identifier,
translation_key: String, translation_key: String,
} }

View File

@ -1,4 +1,4 @@
use pumpkin_protocol::VarInt; use pumpkin_protocol::codec::var_int::VarInt;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]

View File

@ -10,7 +10,7 @@ use indexmap::IndexMap;
use instrument::Instrument; use instrument::Instrument;
use jukebox_song::JukeboxSong; use jukebox_song::JukeboxSong;
use paint::Painting; use paint::Painting;
use pumpkin_protocol::client::config::RegistryEntry; use pumpkin_protocol::{client::config::RegistryEntry, codec::identifier::Identifier};
pub use recipe::{ pub use recipe::{
flatten_3x3, IngredientSlot, IngredientType, Recipe, RecipeResult, RecipeType, RECIPES, flatten_3x3, IngredientSlot, IngredientType, Recipe, RecipeResult, RecipeType, RECIPES,
}; };
@ -41,8 +41,8 @@ pub static SYNCED_REGISTRIES: LazyLock<SyncedRegistry> = LazyLock::new(|| {
}); });
pub struct Registry { pub struct Registry {
pub registry_id: String, pub registry_id: Identifier,
pub registry_entries: Vec<RegistryEntry<'static>>, pub registry_entries: Vec<RegistryEntry>,
} }
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize)]
@ -78,12 +78,12 @@ struct DataPool<T> {
} }
impl DimensionType { impl DimensionType {
pub fn name(&self) -> &str { pub fn name(&self) -> Identifier {
match self { match self {
Self::Overworld => "minecraft:overworld", Self::Overworld => Identifier::vanilla("overworld"),
Self::OverworldCaves => "minecraft:overworld_caves", Self::OverworldCaves => Identifier::vanilla("overworld_caves"),
Self::TheEnd => "minecraft:the_end", Self::TheEnd => Identifier::vanilla("the_end"),
Self::TheNether => "minecraft:the_nether", Self::TheNether => Identifier::vanilla("the_nether"),
} }
} }
} }
@ -94,12 +94,12 @@ impl Registry {
.biome .biome
.iter() .iter()
.map(|s| RegistryEntry { .map(|s| RegistryEntry {
entry_id: s.0, entry_id: Identifier::vanilla(s.0),
data: pumpkin_nbt::serializer::to_bytes_unnamed(&s.1).unwrap(), data: Some(pumpkin_nbt::serializer::to_bytes_unnamed(&s.1).unwrap()),
}) })
.collect(); .collect();
let biome = Registry { let biome = Registry {
registry_id: "minecraft:worldgen/biome".to_string(), registry_id: Identifier::vanilla("worldgen/biome"),
registry_entries, registry_entries,
}; };
@ -107,12 +107,12 @@ impl Registry {
.chat_type .chat_type
.iter() .iter()
.map(|s| RegistryEntry { .map(|s| RegistryEntry {
entry_id: s.0, entry_id: Identifier::vanilla(s.0),
data: pumpkin_nbt::serializer::to_bytes_unnamed(&s.1).unwrap(), data: Some(pumpkin_nbt::serializer::to_bytes_unnamed(&s.1).unwrap()),
}) })
.collect(); .collect();
let chat_type = Registry { let chat_type = Registry {
registry_id: "minecraft:chat_type".to_string(), registry_id: Identifier::vanilla("chat_type"),
registry_entries, registry_entries,
}; };
@ -120,7 +120,7 @@ impl Registry {
// .trim_pattern // .trim_pattern
// .iter() // .iter()
// .map(|s| RegistryEntry { // .map(|s| RegistryEntry {
// entry_id: s.0, // entry_id: Identifier::vanilla(s.0),
// data: pumpkin_nbt::serializer::to_bytes_unnamed(&s.1).unwrap(), // data: pumpkin_nbt::serializer::to_bytes_unnamed(&s.1).unwrap(),
// }) // })
// .collect(); // .collect();
@ -133,7 +133,7 @@ impl Registry {
// .trim_material // .trim_material
// .iter() // .iter()
// .map(|s| RegistryEntry { // .map(|s| RegistryEntry {
// entry_id: s.0, // entry_id: Identifier::vanilla(s.0),
// data: pumpkin_nbt::serializer::to_bytes_unnamed(&s.1).unwrap(), // data: pumpkin_nbt::serializer::to_bytes_unnamed(&s.1).unwrap(),
// }) // })
// .collect(); // .collect();
@ -148,13 +148,13 @@ impl Registry {
.map(|s| { .map(|s| {
let variant = s.1.clone(); let variant = s.1.clone();
RegistryEntry { RegistryEntry {
entry_id: s.0, entry_id: Identifier::vanilla(s.0),
data: pumpkin_nbt::serializer::to_bytes_unnamed(&variant).unwrap(), data: Some(pumpkin_nbt::serializer::to_bytes_unnamed(&variant).unwrap()),
} }
}) })
.collect(); .collect();
let wolf_variant = Registry { let wolf_variant = Registry {
registry_id: "minecraft:wolf_variant".to_string(), registry_id: Identifier::vanilla("wolf_variant"),
registry_entries, registry_entries,
}; };
@ -162,12 +162,12 @@ impl Registry {
.painting_variant .painting_variant
.iter() .iter()
.map(|s| RegistryEntry { .map(|s| RegistryEntry {
entry_id: s.0, entry_id: Identifier::vanilla(s.0),
data: pumpkin_nbt::serializer::to_bytes_unnamed(&s.1).unwrap(), data: Some(pumpkin_nbt::serializer::to_bytes_unnamed(&s.1).unwrap()),
}) })
.collect(); .collect();
let painting_variant = Registry { let painting_variant = Registry {
registry_id: "minecraft:painting_variant".to_string(), registry_id: Identifier::vanilla("painting_variant"),
registry_entries, registry_entries,
}; };
@ -175,12 +175,12 @@ impl Registry {
.dimension_type .dimension_type
.iter() .iter()
.map(|s| RegistryEntry { .map(|s| RegistryEntry {
entry_id: s.0, entry_id: Identifier::vanilla(s.0),
data: pumpkin_nbt::serializer::to_bytes_unnamed(&s.1).unwrap(), data: Some(pumpkin_nbt::serializer::to_bytes_unnamed(&s.1).unwrap()),
}) })
.collect(); .collect();
let dimension_type = Registry { let dimension_type = Registry {
registry_id: "minecraft:dimension_type".to_string(), registry_id: Identifier::vanilla("dimension_type"),
registry_entries, registry_entries,
}; };
@ -188,12 +188,12 @@ impl Registry {
.damage_type .damage_type
.iter() .iter()
.map(|s| RegistryEntry { .map(|s| RegistryEntry {
entry_id: s.0, entry_id: Identifier::vanilla(s.0),
data: pumpkin_nbt::serializer::to_bytes_unnamed(&s.1).unwrap(), data: Some(pumpkin_nbt::serializer::to_bytes_unnamed(&s.1).unwrap()),
}) })
.collect(); .collect();
let damage_type = Registry { let damage_type = Registry {
registry_id: "minecraft:damage_type".to_string(), registry_id: Identifier::vanilla("damage_type"),
registry_entries, registry_entries,
}; };
@ -201,12 +201,12 @@ impl Registry {
.banner_pattern .banner_pattern
.iter() .iter()
.map(|s| RegistryEntry { .map(|s| RegistryEntry {
entry_id: s.0, entry_id: Identifier::vanilla(s.0),
data: pumpkin_nbt::serializer::to_bytes_unnamed(&s.1).unwrap(), data: Some(pumpkin_nbt::serializer::to_bytes_unnamed(&s.1).unwrap()),
}) })
.collect(); .collect();
let banner_pattern = Registry { let banner_pattern = Registry {
registry_id: "minecraft:banner_pattern".to_string(), registry_id: Identifier::vanilla("banner_pattern"),
registry_entries, registry_entries,
}; };
@ -215,7 +215,7 @@ impl Registry {
// .enchantment // .enchantment
// .iter() // .iter()
// .map(|s| RegistryEntry { // .map(|s| RegistryEntry {
// entry_id: s.0, // entry_id: Identifier::vanilla(s.0),
// data: pumpkin_nbt::serializer::to_bytes_unnamed(&s.1).unwrap(), // data: pumpkin_nbt::serializer::to_bytes_unnamed(&s.1).unwrap(),
// }) // })
// .collect(); // .collect();
@ -228,12 +228,12 @@ impl Registry {
.jukebox_song .jukebox_song
.iter() .iter()
.map(|s| RegistryEntry { .map(|s| RegistryEntry {
entry_id: s.0, entry_id: Identifier::vanilla(s.0),
data: pumpkin_nbt::serializer::to_bytes_unnamed(&s.1).unwrap(), data: Some(pumpkin_nbt::serializer::to_bytes_unnamed(&s.1).unwrap()),
}) })
.collect(); .collect();
let jukebox_song = Registry { let jukebox_song = Registry {
registry_id: "minecraft:jukebox_song".to_string(), registry_id: Identifier::vanilla("jukebox_song"),
registry_entries, registry_entries,
}; };
@ -241,7 +241,7 @@ impl Registry {
// .instrument // .instrument
// .iter() // .iter()
// .map(|s| RegistryEntry { // .map(|s| RegistryEntry {
// entry_id: s.0, // entry_id: Identifier::vanilla(s.0),
// data: pumpkin_nbt::serializer::to_bytes_unnamed(&s.1).unwrap(), // data: pumpkin_nbt::serializer::to_bytes_unnamed(&s.1).unwrap(),
// }) // })
// .collect(); // .collect();

View File

@ -1,8 +1,9 @@
use pumpkin_protocol::codec::identifier::Identifier;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Painting { pub struct Painting {
asset_id: String, asset_id: Identifier,
// #[serde(skip_serializing_if = "Option::is_none")] // #[serde(skip_serializing_if = "Option::is_none")]
// title: Option<TextComponent<'static>>, // title: Option<TextComponent<'static>>,
// #[serde(skip_serializing_if = "Option::is_none")] // #[serde(skip_serializing_if = "Option::is_none")]

View File

@ -1,8 +1,9 @@
use pumpkin_protocol::codec::identifier::Identifier;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TrimPattern { pub struct TrimPattern {
asset_id: String, asset_id: Identifier,
template_item: String, template_item: String,
// description: TextComponent<'static>, // description: TextComponent<'static>,
decal: bool, decal: bool,

View File

@ -57,6 +57,15 @@ pub struct Modifier {
pub type_val: String, pub type_val: String,
pub id: String, pub id: String,
pub amount: f64, pub amount: f64,
pub operation: String, pub operation: Operation,
// TODO: Make this an enum
pub slot: String, pub slot: String,
} }
#[derive(Deserialize, Clone, Debug, PartialEq)]
#[serde(rename_all = "snake_case")]
pub enum Operation {
AddValue,
AddMultipliedBase,
AddMultipliedTotal,
}

View File

@ -12,9 +12,12 @@ use core::str;
use num_traits::FromPrimitive; use num_traits::FromPrimitive;
use pumpkin_config::{ADVANCED_CONFIG, BASIC_CONFIG}; use pumpkin_config::{ADVANCED_CONFIG, BASIC_CONFIG};
use pumpkin_core::text::TextComponent; use pumpkin_core::text::TextComponent;
use pumpkin_protocol::client::config::{CServerLinks, Label, Link, LinkType};
use pumpkin_protocol::server::config::SCookieResponse as SCCookieResponse; use pumpkin_protocol::server::config::SCookieResponse as SCCookieResponse;
use pumpkin_protocol::server::login::SCookieResponse as SLCookieResponse; use pumpkin_protocol::server::login::SCookieResponse as SLCookieResponse;
use pumpkin_protocol::{
client::config::{CServerLinks, Label, Link, LinkType},
codec::var_int::VarInt,
};
use pumpkin_protocol::{ use pumpkin_protocol::{
client::{ client::{
config::{CConfigAddResourcePack, CFinishConfig, CKnownPacks, CRegistryData}, config::{CConfigAddResourcePack, CFinishConfig, CKnownPacks, CRegistryData},
@ -27,7 +30,7 @@ use pumpkin_protocol::{
login::{SEncryptionResponse, SLoginPluginResponse, SLoginStart}, login::{SEncryptionResponse, SLoginPluginResponse, SLoginStart},
status::SStatusPingRequest, status::SStatusPingRequest,
}, },
ConnectionState, KnownPack, VarInt, CURRENT_MC_PROTOCOL, ConnectionState, KnownPack, CURRENT_MC_PROTOCOL,
}; };
use std::{ use std::{
num::{NonZeroI32, NonZeroU8}, num::{NonZeroI32, NonZeroU8},
@ -318,7 +321,7 @@ impl Client {
// TODO: allow plugins to access this // TODO: allow plugins to access this
log::debug!( log::debug!(
"Received cookie_response[login]: key: \"{}\", has_payload: \"{}\", payload_length: \"{}\"", "Received cookie_response[login]: key: \"{}\", has_payload: \"{}\", payload_length: \"{}\"",
packet.key, packet.key.to_string(),
packet.has_payload, packet.has_payload,
packet.payload_length.unwrap_or(VarInt::from(0)).0 packet.payload_length.unwrap_or(VarInt::from(0)).0
); );
@ -417,8 +420,10 @@ impl Client {
pub async fn handle_plugin_message(&self, plugin_message: SPluginMessage) { pub async fn handle_plugin_message(&self, plugin_message: SPluginMessage) {
log::debug!("Handling plugin message"); log::debug!("Handling plugin message");
if plugin_message.channel.starts_with("minecraft:brand") if plugin_message
|| plugin_message.channel.starts_with("MC|Brand") .channel
.to_string()
.starts_with("minecraft:brand")
{ {
log::debug!("got a client brand"); log::debug!("got a client brand");
match str::from_utf8(&plugin_message.data) { match str::from_utf8(&plugin_message.data) {
@ -432,7 +437,7 @@ impl Client {
// TODO: allow plugins to access this // TODO: allow plugins to access this
log::debug!( log::debug!(
"Received cookie_response[config]: key: \"{}\", has_payload: \"{}\", payload_length: \"{}\"", "Received cookie_response[config]: key: \"{}\", has_payload: \"{}\", payload_length: \"{}\"",
packet.key, packet.key.to_string(),
packet.has_payload, packet.has_payload,
packet.payload_length.unwrap_or(VarInt::from(0)).0 packet.payload_length.unwrap_or(VarInt::from(0)).0
); );

View File

@ -4,7 +4,8 @@ use pumpkin_core::math::vector3::Vector3;
use pumpkin_macros::{particle, sound}; use pumpkin_macros::{particle, sound};
use pumpkin_protocol::{ use pumpkin_protocol::{
client::play::{CEntityVelocity, CParticle}, client::play::{CEntityVelocity, CParticle},
SoundCategory, VarInt, codec::var_int::VarInt,
SoundCategory,
}; };
use pumpkin_world::item::ItemStack; use pumpkin_world::item::ItemStack;

View File

@ -12,9 +12,9 @@ use pumpkin_inventory::{Container, WindowType};
use pumpkin_protocol::client::play::{ use pumpkin_protocol::client::play::{
CCloseContainer, COpenScreen, CSetContainerContent, CSetContainerProperty, CSetContainerSlot, CCloseContainer, COpenScreen, CSetContainerContent, CSetContainerProperty, CSetContainerSlot,
}; };
use pumpkin_protocol::codec::var_int::VarInt;
use pumpkin_protocol::server::play::SClickContainer; use pumpkin_protocol::server::play::SClickContainer;
use pumpkin_protocol::slot::Slot; use pumpkin_protocol::slot::Slot;
use pumpkin_protocol::VarInt;
use pumpkin_world::item::item_registry::Item; use pumpkin_world::item::item_registry::Item;
use pumpkin_world::item::ItemStack; use pumpkin_world::item::ItemStack;
use std::sync::Arc; use std::sync::Arc;

View File

@ -296,8 +296,8 @@ impl Client {
/// ///
/// # Arguments /// # Arguments
/// ///
/// * `server`: A reference to the `Arc<Server>` instance. /// * `server`: A reference to the `Server` instance.
pub async fn process_packets(&self, server: &Arc<Server>) { pub async fn process_packets(&self, server: &Server) {
let mut packet_queue = self.client_packets_queue.lock().await; let mut packet_queue = self.client_packets_queue.lock().await;
while let Some(mut packet) = packet_queue.pop_front() { while let Some(mut packet) = packet_queue.pop_front() {
if self.closed.load(std::sync::atomic::Ordering::Relaxed) { if self.closed.load(std::sync::atomic::Ordering::Relaxed) {
@ -330,7 +330,7 @@ impl Client {
/// ///
/// # Arguments /// # Arguments
/// ///
/// * `server`: A reference to the `Arc<Server>` instance. /// * `server`: A reference to the `Server` instance.
/// * `packet`: A mutable reference to the `RawPacket` to be processed. /// * `packet`: A mutable reference to the `RawPacket` to be processed.
/// ///
/// # Returns /// # Returns
@ -342,7 +342,7 @@ impl Client {
/// Returns a `DeserializerError` if an error occurs during packet deserialization. /// Returns a `DeserializerError` if an error occurs during packet deserialization.
pub async fn handle_packet( pub async fn handle_packet(
&self, &self,
server: &Arc<Server>, server: &Server,
packet: &mut RawPacket, packet: &mut RawPacket,
) -> Result<(), ReadingError> { ) -> Result<(), ReadingError> {
match self.connection_state.load() { match self.connection_state.load() {
@ -386,7 +386,7 @@ impl Client {
async fn handle_status_packet( async fn handle_status_packet(
&self, &self,
server: &Arc<Server>, server: &Server,
packet: &mut RawPacket, packet: &mut RawPacket,
) -> Result<(), ReadingError> { ) -> Result<(), ReadingError> {
log::debug!("Handling status group"); log::debug!("Handling status group");
@ -412,7 +412,7 @@ impl Client {
async fn handle_login_packet( async fn handle_login_packet(
&self, &self,
server: &Arc<Server>, server: &Server,
packet: &mut RawPacket, packet: &mut RawPacket,
) -> Result<(), ReadingError> { ) -> Result<(), ReadingError> {
log::debug!("Handling login group for id"); log::debug!("Handling login group for id");
@ -448,7 +448,7 @@ impl Client {
async fn handle_config_packet( async fn handle_config_packet(
&self, &self,
server: &Arc<Server>, server: &Server,
packet: &mut RawPacket, packet: &mut RawPacket,
) -> Result<(), ReadingError> { ) -> Result<(), ReadingError> {
log::debug!("Handling config group"); log::debug!("Handling config group");

View File

@ -19,11 +19,11 @@ use pumpkin_core::{
GameMode, GameMode,
}; };
use pumpkin_inventory::{InventoryError, WindowType}; use pumpkin_inventory::{InventoryError, WindowType};
use pumpkin_protocol::codec::var_int::VarInt;
use pumpkin_protocol::server::play::SCookieResponse as SPCookieResponse; use pumpkin_protocol::server::play::SCookieResponse as SPCookieResponse;
use pumpkin_protocol::{ use pumpkin_protocol::{
client::play::CCommandSuggestions, client::play::CCommandSuggestions,
server::play::{SCloseContainer, SCommandSuggestion, SKeepAlive, SSetPlayerGround, SUseItem}, server::play::{SCloseContainer, SCommandSuggestion, SKeepAlive, SSetPlayerGround, SUseItem},
VarInt,
}; };
use pumpkin_protocol::{ use pumpkin_protocol::{
client::play::{ client::play::{
@ -896,7 +896,7 @@ impl Player {
// TODO: allow plugins to access this // TODO: allow plugins to access this
log::debug!( log::debug!(
"Received cookie_response[play]: key: \"{}\", has_payload: \"{}\", payload_length: \"{}\"", "Received cookie_response[play]: key: \"{}\", has_payload: \"{}\", payload_length: \"{}\"",
packet.key, packet.key.to_string(),
packet.has_payload, packet.has_payload,
packet.payload_length.unwrap_or(VarInt::from(0)).0 packet.payload_length.unwrap_or(VarInt::from(0)).0
); );

View File

@ -2,7 +2,7 @@ use async_trait::async_trait;
use pumpkin_core::text::color::{Color, NamedColor}; use pumpkin_core::text::color::{Color, NamedColor};
use pumpkin_core::text::TextComponent; use pumpkin_core::text::TextComponent;
use pumpkin_protocol::client::play::CTransfer; use pumpkin_protocol::client::play::CTransfer;
use pumpkin_protocol::VarInt; use pumpkin_protocol::codec::var_int::VarInt;
use crate::command::args::arg_bounded_num::BoundedNumArgumentConsumer; use crate::command::args::arg_bounded_num::BoundedNumArgumentConsumer;
use crate::command::args::arg_players::PlayersArgumentConsumer; use crate::command::args::arg_players::PlayersArgumentConsumer;

View File

@ -12,7 +12,7 @@ use pumpkin_core::math::{
use pumpkin_entity::{entity_type::EntityType, pose::EntityPose, EntityId}; use pumpkin_entity::{entity_type::EntityType, pose::EntityPose, EntityId};
use pumpkin_protocol::{ use pumpkin_protocol::{
client::play::{CSetEntityMetadata, CTeleportEntity, Metadata}, client::play::{CSetEntityMetadata, CTeleportEntity, Metadata},
VarInt, codec::var_int::VarInt,
}; };
use crate::world::World; use crate::world::World;

View File

@ -24,7 +24,6 @@ use pumpkin_core::{
use pumpkin_entity::{entity_type::EntityType, EntityId}; use pumpkin_entity::{entity_type::EntityType, EntityId};
use pumpkin_inventory::player::PlayerInventory; use pumpkin_inventory::player::PlayerInventory;
use pumpkin_macros::sound; use pumpkin_macros::sound;
use pumpkin_protocol::client::play::CUpdateTime;
use pumpkin_protocol::server::play::{ use pumpkin_protocol::server::play::{
SCloseContainer, SCookieResponse as SPCookieResponse, SPlayPingRequest, SCloseContainer, SCookieResponse as SPCookieResponse, SPlayPingRequest,
}; };
@ -41,15 +40,19 @@ use pumpkin_protocol::{
SPlayerCommand, SPlayerInput, SPlayerPosition, SPlayerPositionRotation, SPlayerRotation, SPlayerCommand, SPlayerInput, SPlayerPosition, SPlayerPositionRotation, SPlayerRotation,
SSetCreativeSlot, SSetHeldItem, SSetPlayerGround, SSwingArm, SUseItem, SUseItemOn, SSetCreativeSlot, SSetHeldItem, SSetPlayerGround, SSwingArm, SUseItem, SUseItemOn,
}, },
RawPacket, ServerPacket, SoundCategory, VarInt, RawPacket, ServerPacket, SoundCategory,
}; };
use pumpkin_protocol::{client::play::CUpdateTime, codec::var_int::VarInt};
use pumpkin_protocol::{ use pumpkin_protocol::{
client::play::{CSetEntityMetadata, Metadata}, client::play::{CSetEntityMetadata, Metadata},
server::play::{SClickContainer, SKeepAlive}, server::play::{SClickContainer, SKeepAlive},
}; };
use pumpkin_world::{ use pumpkin_world::{
cylindrical_chunk_iterator::Cylindrical, cylindrical_chunk_iterator::Cylindrical,
item::{item_registry::get_item_by_id, ItemStack}, item::{
item_registry::{get_item_by_id, Operation},
ItemStack,
},
}; };
use tokio::sync::{Mutex, Notify}; use tokio::sync::{Mutex, Notify};
@ -257,7 +260,7 @@ impl Player {
// TODO: this should be cached in memory // TODO: this should be cached in memory
if let Some(modifiers) = &item.components.attribute_modifiers { if let Some(modifiers) = &item.components.attribute_modifiers {
for item_mod in &modifiers.modifiers { for item_mod in &modifiers.modifiers {
if item_mod.operation == "add_value" { if item_mod.operation == Operation::AddValue {
if item_mod.id == "minecraft:base_attack_damage" { if item_mod.id == "minecraft:base_attack_damage" {
add_damage = item_mod.amount; add_damage = item_mod.amount;
} }

View File

@ -10,7 +10,8 @@ use base64::{engine::general_purpose, Engine as _};
use pumpkin_config::{BasicConfiguration, BASIC_CONFIG}; use pumpkin_config::{BasicConfiguration, BASIC_CONFIG};
use pumpkin_protocol::{ use pumpkin_protocol::{
client::{config::CPluginMessage, status::CStatusResponse}, client::{config::CPluginMessage, status::CStatusResponse},
Players, StatusResponse, VarInt, Version, CURRENT_MC_PROTOCOL, codec::{var_int::VarInt, Codec},
Players, StatusResponse, Version, CURRENT_MC_PROTOCOL,
}; };
use super::CURRENT_MC_VERSION; use super::CURRENT_MC_VERSION;

View File

@ -71,8 +71,6 @@ impl Server {
#[allow(clippy::new_without_default)] #[allow(clippy::new_without_default)]
#[must_use] #[must_use]
pub fn new() -> Self { pub fn new() -> Self {
// TODO: only create when needed
let auth_client = BASIC_CONFIG.online_mode.then(|| { let auth_client = BASIC_CONFIG.online_mode.then(|| {
reqwest::Client::builder() reqwest::Client::builder()
.timeout(Duration::from_millis(5000)) .timeout(Duration::from_millis(5000))

View File

@ -15,7 +15,10 @@ use pumpkin_core::math::vector2::Vector2;
use pumpkin_core::math::{position::WorldPosition, vector3::Vector3}; use pumpkin_core::math::{position::WorldPosition, vector3::Vector3};
use pumpkin_core::text::{color::NamedColor, TextComponent}; use pumpkin_core::text::{color::NamedColor, TextComponent};
use pumpkin_entity::{entity_type::EntityType, EntityId}; use pumpkin_entity::{entity_type::EntityType, EntityId};
use pumpkin_protocol::client::play::CLevelEvent; use pumpkin_protocol::{
client::play::CLevelEvent,
codec::{identifier::Identifier, var_int::VarInt},
};
use pumpkin_protocol::{ use pumpkin_protocol::{
client::play::{CBlockUpdate, CRespawn, CSoundEffect, CWorldEvent}, client::play::{CBlockUpdate, CRespawn, CSoundEffect, CWorldEvent},
SoundCategory, SoundCategory,
@ -25,7 +28,7 @@ use pumpkin_protocol::{
CChunkData, CGameEvent, CLogin, CPlayerInfoUpdate, CRemoveEntities, CRemovePlayerInfo, CChunkData, CGameEvent, CLogin, CPlayerInfoUpdate, CRemoveEntities, CRemovePlayerInfo,
CSetEntityMetadata, CSpawnEntity, GameEvent, Metadata, PlayerAction, CSetEntityMetadata, CSpawnEntity, GameEvent, Metadata, PlayerAction,
}, },
ClientPacket, VarInt, ClientPacket,
}; };
use pumpkin_registry::DimensionType; use pumpkin_registry::DimensionType;
use pumpkin_world::chunk::ChunkData; use pumpkin_world::chunk::ChunkData;
@ -223,7 +226,8 @@ impl World {
server: &Server, server: &Server,
) { ) {
let command_dispatcher = &server.command_dispatcher; let command_dispatcher = &server.command_dispatcher;
let dimensions: Vec<&str> = server.dimensions.iter().map(DimensionType::name).collect(); let dimensions: Vec<Identifier> =
server.dimensions.iter().map(DimensionType::name).collect();
// This code follows the vanilla packet order // This code follows the vanilla packet order
let entity_id = player.entity_id(); let entity_id = player.entity_id();

View File

@ -3,7 +3,8 @@ use std::collections::HashMap;
use pumpkin_core::text::TextComponent; use pumpkin_core::text::TextComponent;
use pumpkin_protocol::{ use pumpkin_protocol::{
client::play::{CDisplayObjective, CUpdateObjectives, CUpdateScore, RenderType}, client::play::{CDisplayObjective, CUpdateObjectives, CUpdateScore, RenderType},
NumberFormat, VarInt, codec::var_int::VarInt,
NumberFormat,
}; };
use super::World; use super::World;