chunkedge_server/
message.rs

1// TODO: delete this module in favor of chunkedge_chat.
2
3use bevy_app::prelude::*;
4use bevy_ecs::prelude::*;
5use chunkedge_protocol::encode::WritePacket;
6use chunkedge_protocol::packets::play::{ChatC2s, SystemChatS2c};
7use chunkedge_protocol::text::IntoText;
8use chunkedge_protocol::IntoTextComponent;
9
10use crate::event_loop::{EventLoopPreUpdate, PacketEvent};
11
12pub struct MessagePlugin;
13
14impl Plugin for MessagePlugin {
15    fn build(&self, app: &mut App) {
16        app.add_event::<ChatMessageEvent>()
17            .add_systems(EventLoopPreUpdate, handle_chat_message);
18    }
19}
20
21pub trait SendMessage {
22    /// Sends a system message visible in the chat.
23    fn send_chat_message<'a>(&mut self, msg: impl IntoText<'a>);
24    /// Displays a message in the player's action bar (text above the hotbar).
25    fn send_action_bar_message<'a>(&mut self, msg: impl IntoText<'a>);
26}
27
28impl<T: WritePacket> SendMessage for T {
29    fn send_chat_message<'a>(&mut self, msg: impl IntoText<'a>) {
30        self.write_packet(&SystemChatS2c {
31            chat: msg.into_cow_text_component(),
32            overlay: false,
33        });
34    }
35
36    fn send_action_bar_message<'a>(&mut self, msg: impl IntoText<'a>) {
37        self.write_packet(&SystemChatS2c {
38            chat: msg.into_cow_text_component(),
39            overlay: true,
40        });
41    }
42}
43
44#[derive(Event, Clone, Debug)]
45pub struct ChatMessageEvent {
46    pub client: Entity,
47    pub message: Box<str>,
48    pub timestamp: u64,
49}
50
51pub fn handle_chat_message(
52    mut packets: EventReader<PacketEvent>,
53    mut events: EventWriter<ChatMessageEvent>,
54) {
55    for packet in packets.read() {
56        if let Some(pkt) = packet.decode::<ChatC2s>() {
57            events.send(ChatMessageEvent {
58                client: packet.client,
59                message: pkt.message.0.into(),
60                timestamp: pkt.timestamp,
61            });
62        }
63    }
64}