use std::sync::Arc; use azalea_protocol::packets::{ Packet, config::{ClientboundConfigPacket, ServerboundConfigPacket}, }; use bevy_ecs::prelude::*; use tracing::{debug, error}; use crate::{InConfigState, connection::RawConnection}; #[derive(Clone, Debug, Message)] pub struct ReceiveConfigPacketEvent { /// The client entity that received the packet. pub entity: Entity, /// The packet that was actually received. pub packet: Arc, } /// An event for sending a packet to the server while we're in the /// `configuration` state. #[derive(Clone, EntityEvent)] pub struct SendConfigPacketEvent { #[event_target] pub sent_by: Entity, pub packet: ServerboundConfigPacket, } impl SendConfigPacketEvent { pub fn new(sent_by: Entity, packet: impl Packet) -> Self { let packet = packet.into_variant(); Self { sent_by, packet } } } pub fn handle_outgoing_packets_observer( send_config_packet: On, mut query: Query<(&mut RawConnection, Option<&InConfigState>)>, ) { if let Ok((mut raw_conn, in_configuration_state)) = query.get_mut(send_config_packet.sent_by) { if in_configuration_state.is_none() { error!( "Tried to send a configuration packet {:?} while not in configuration state", send_config_packet.packet ); return; } debug!("Sending config packet: {:?}", send_config_packet.packet); if let Err(e) = raw_conn.write(send_config_packet.packet.clone()) { error!("Failed to send packet: {e}"); } } } /// A Bevy trigger that's sent when our client receives a [`ClientboundPing`] /// packet in the config state. /// /// Also see [`GamePingEvent`]. /// /// [`ClientboundPing`]: azalea_protocol::packets::config::ClientboundPing /// [`GamePingEvent`]: crate::packet::game::GamePingEvent #[derive(Clone, Debug, Event)] pub struct ConfigPingEvent { pub entity: Entity, pub packet: azalea_protocol::packets::config::ClientboundPing, }