diff --git a/src/bin/src/packet_handlers/chat_message.rs b/src/bin/src/packet_handlers/chat_message.rs new file mode 100644 index 00000000..5e5ccb58 --- /dev/null +++ b/src/bin/src/packet_handlers/chat_message.rs @@ -0,0 +1,18 @@ +use ferrumc_core::identity::player_identity::PlayerIdentity; +use ferrumc_macros::event_handler; +use ferrumc_net::{packets::{incoming::chat_message::ChatMessageEvent, outgoing::system_message::SystemMessagePacket}, utils::broadcast::{BroadcastOptions, BroadcastToAll}, NetResult}; +use ferrumc_state::GlobalState; +use ferrumc_text::TextComponentBuilder; + +#[event_handler] +async fn chat_message( + event: ChatMessageEvent, + state: GlobalState +) -> NetResult { + let identity = state.universe.get::(event.player_conn_id)?; + let message = TextComponentBuilder::new(format!("<{}> {}", identity.username, event.message)).build(); + let packet = SystemMessagePacket::new(message, false); + state.broadcast(&packet, BroadcastOptions::default().all()).await?; + + Ok(event) +} \ No newline at end of file diff --git a/src/bin/src/packet_handlers/mod.rs b/src/bin/src/packet_handlers/mod.rs index b6362dcc..2a2c1551 100644 --- a/src/bin/src/packet_handlers/mod.rs +++ b/src/bin/src/packet_handlers/mod.rs @@ -3,3 +3,4 @@ mod handshake; mod login_process; mod tick_handler; mod transform; +mod chat_message; diff --git a/src/lib/net/crates/codec/src/decode/primitives.rs b/src/lib/net/crates/codec/src/decode/primitives.rs index 3e00e794..99bb8244 100644 --- a/src/lib/net/crates/codec/src/decode/primitives.rs +++ b/src/lib/net/crates/codec/src/decode/primitives.rs @@ -83,6 +83,24 @@ where } } +/// This implementation assumes that the optional was written using PacketByteBuf#writeNullable and has a leading bool. +impl NetDecode for Option +where + T: NetDecode, +{ + fn decode(reader: &mut R, opts: &NetDecodeOpts) -> NetDecodeResult { + let is_some = ::decode(reader, opts)?; + + if !is_some { + return Ok(None) + } + + let value = ::decode(reader, opts)?; + + Ok(Some(value)) + } +} + /// This isn't actually a type in the Minecraft Protocol. This is just for saving data/ or for general use. /// It was created for saving/reading chunks! impl NetDecode for HashMap diff --git a/src/lib/net/src/packets/incoming/chat_message.rs b/src/lib/net/src/packets/incoming/chat_message.rs new file mode 100644 index 00000000..1441911f --- /dev/null +++ b/src/lib/net/src/packets/incoming/chat_message.rs @@ -0,0 +1,42 @@ +use std::sync::Arc; + +use ferrumc_events::infrastructure::Event; +use ferrumc_macros::{packet, Event, NetDecode}; +use ferrumc_net_codec::net_types::var_int::VarInt; +use ferrumc_state::ServerState; + +use crate::packets::IncomingPacket; + +#[derive(NetDecode, Debug, Clone)] +#[packet(packet_id = 0x06, state = "play")] +pub struct ChatMessagePacket { + pub message: String, + pub timestamp: u64, + pub salt: u64, + pub has_signature: bool, + pub signature: Option>, + pub message_count: VarInt, + pub acknowledged: Vec +} + +impl IncomingPacket for ChatMessagePacket { + async fn handle( + self, + conn_id: usize, + state: Arc, + ) -> crate::NetResult<()> { + ChatMessageEvent::trigger(ChatMessageEvent::new(conn_id, self.message), state).await + } +} + +#[derive(Debug, Event, Clone)] +pub struct ChatMessageEvent { + pub player_conn_id: usize, + pub message: String, +} + +impl ChatMessageEvent { + pub fn new(player_conn_id: usize, message: String) -> Self { + Self { player_conn_id, message } + } +} diff --git a/src/lib/net/src/packets/incoming/mod.rs b/src/lib/net/src/packets/incoming/mod.rs index b7994e38..ffefae69 100644 --- a/src/lib/net/src/packets/incoming/mod.rs +++ b/src/lib/net/src/packets/incoming/mod.rs @@ -16,3 +16,4 @@ pub mod set_player_position_and_rotation; pub mod set_player_rotation; pub mod command; +pub mod chat_message;