Skip to content

Commit

Permalink
implement filtering and serialization changes
Browse files Browse the repository at this point in the history
  • Loading branch information
kralverde committed Aug 21, 2024
1 parent 8bc55e8 commit cd6defe
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 72 deletions.
25 changes: 19 additions & 6 deletions pumpkin-protocol/src/bytebuf/serializer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,14 @@ impl ser::Error for SerializerError {
}
}

// General notes on the serializer:
//
// Primitives are written as-is
// Strings automatically pre-pend a varint
// 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<'a> ser::Serializer for &'a mut Serializer {
type Ok = ();
type Error = SerializerError;
Expand Down Expand Up @@ -121,7 +129,8 @@ impl<'a> ser::Serializer for &'a mut Serializer {
where
T: ?Sized + Serialize,
{
unimplemented!()
self.output.put_var_int(&_variant_index.into());
_value.serialize(self)
}
fn serialize_none(self) -> Result<Self::Ok, Self::Error> {
self.output.put_bool(false);
Expand Down Expand Up @@ -160,7 +169,7 @@ impl<'a> ser::Serializer for &'a mut Serializer {
unimplemented!()
}
fn serialize_tuple(self, _len: usize) -> Result<Self::SerializeTuple, Self::Error> {
unimplemented!()
Ok(self)
}
fn serialize_tuple_struct(
self,
Expand All @@ -176,7 +185,9 @@ impl<'a> ser::Serializer for &'a mut Serializer {
_variant: &'static str,
_len: usize,
) -> Result<Self::SerializeTupleVariant, Self::Error> {
unimplemented!()
// Serialize ENUM index as varint
self.output.put_var_int(&_variant_index.into());
Ok(self)
}
fn serialize_u128(self, _v: u128) -> Result<Self::Ok, Self::Error> {
unimplemented!()
Expand Down Expand Up @@ -209,7 +220,9 @@ impl<'a> ser::Serializer for &'a mut Serializer {
_variant_index: u32,
_variant: &'static str,
) -> Result<Self::Ok, Self::Error> {
todo!()
// For ENUMs, only write enum index as varint
self.output.put_var_int(&_variant_index.into());
Ok(())
}
}

Expand Down Expand Up @@ -241,11 +254,11 @@ impl<'a> ser::SerializeTuple for &'a mut Serializer {
where
T: ?Sized + Serialize,
{
todo!()
_value.serialize(&mut **self)
}

fn end(self) -> Result<(), Self::Error> {
todo!()
Ok(())
}
}

Expand Down
74 changes: 10 additions & 64 deletions pumpkin-protocol/src/client/play/c_player_chat_message.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
use num_derive::{FromPrimitive, ToPrimitive};
use num_traits::FromPrimitive;
use pumpkin_core::text::TextComponent;
use pumpkin_macros::packet;
use serde::Serialize;

use crate::{bytebuf::ByteBuffer, uuid::UUID, BitSet, ClientPacket, VarInt};

use crate::{uuid::UUID, BitSet, VarInt};
#[derive(Serialize)]
#[packet(0x39)]
pub struct CPlayerChatMessage<'a> {
sender: UUID,
Expand All @@ -17,12 +15,7 @@ pub struct CPlayerChatMessage<'a> {
previous_messages_count: VarInt,
previous_messages: &'a [PreviousMessage<'a>], // max 20
unsigned_content: Option<TextComponent<'a>>,
/// See `FilterType`
filter_type: VarInt,

// TODO: Implement
#[allow(dead_code)]
filter_type_bits: Option<BitSet<'a>>,
filter_type: FilterType<'a>,
chat_type: VarInt,
sender_name: TextComponent<'a>,
target_name: Option<TextComponent<'a>>,
Expand All @@ -39,8 +32,7 @@ impl<'a> CPlayerChatMessage<'a> {
salt: i64,
previous_messages: &'a [PreviousMessage<'a>],
unsigned_content: Option<TextComponent<'a>>,
filter_type: VarInt,
filter_type_bits: Option<BitSet<'a>>,
filter_type: FilterType<'a>,
chat_type: VarInt,
sender_name: TextComponent<'a>,
target_name: Option<TextComponent<'a>>,
Expand All @@ -56,72 +48,26 @@ impl<'a> CPlayerChatMessage<'a> {
previous_messages,
unsigned_content,
filter_type,
filter_type_bits,
chat_type,
sender_name,
target_name,
}
}
}

impl<'a> ClientPacket for CPlayerChatMessage<'a> {
fn write(&self, bytebuf: &mut ByteBuffer) {
bytebuf.put_uuid(self.sender.0);
bytebuf.put_var_int(&self.index);
bytebuf.put_option(&self.message_signature, |p, v| p.put_slice(v));
bytebuf.put_string(self.message);
bytebuf.put_i64(self.timestamp);
bytebuf.put_i64(self.salt);

if self.previous_messages_count.0 > 20 {
// TODO: Assert this is <=20
}

bytebuf.put_var_int(&self.previous_messages_count);
for previous_message in self.previous_messages {
bytebuf.put_var_int(&previous_message.message_id);
if let Some(prev_sig) = previous_message.signature {
// TODO: validate whether this should be None or not
bytebuf.put_slice(prev_sig);
}
}

bytebuf.put_option(&self.unsigned_content, |p, v| {
p.put_slice(v.encode().as_slice())
});

bytebuf.put_var_int(&self.filter_type);
match FilterType::from_i32(self.filter_type.0) {
Some(FilterType::PassThrough) => (),
Some(FilterType::FullyFiltered) => {
// TODO: Implement
}
Some(FilterType::PartiallyFiltered) => {
// TODO: Implement
}
None => {
// TODO: Implement
}
}

bytebuf.put_var_int(&self.chat_type);
bytebuf.put_slice(self.sender_name.encode().as_slice());
bytebuf.put_option(&self.target_name, |p, v| p.put_slice(v.encode().as_slice()));
}
}

#[derive(Serialize)]
pub struct PreviousMessage<'a> {
message_id: VarInt,
signature: Option<&'a [u8]>,
}

#[derive(FromPrimitive, ToPrimitive)]
pub enum FilterType {
#[derive(Serialize)]
#[repr(i32)]
pub enum FilterType<'a> {
/// Message is not filtered at all
PassThrough,
PassThrough = 0,
/// Message is fully filtered
FullyFiltered,
FullyFiltered = 1,
/// Only some characters in the message are filtered
PartiallyFiltered,
PartiallyFiltered(BitSet<'a>) = 2,
}
3 changes: 1 addition & 2 deletions pumpkin/src/client/player_packet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -233,8 +233,7 @@ impl Client {
chat_message.salt,
&[],
Some(TextComponent::text(&message)),
pumpkin_protocol::VarInt(FilterType::PassThrough as i32),
None,
FilterType::PassThrough,
1.into(),
TextComponent::text(&gameprofile.name.clone()),
None,
Expand Down

0 comments on commit cd6defe

Please sign in to comment.