azalea_client/plugins/packet/config/
events.rs1use std::io::Cursor;
2
3use azalea_protocol::{
4 packets::{
5 Packet,
6 config::{ClientboundConfigPacket, ServerboundConfigPacket},
7 },
8 read::deserialize_packet,
9};
10use bevy_ecs::prelude::*;
11use tracing::{debug, error};
12
13use crate::{InConfigState, raw_connection::RawConnection};
14
15#[derive(Event, Debug, Clone)]
16pub struct ReceiveConfigPacketEvent {
17 pub entity: Entity,
19 pub packet: ClientboundConfigPacket,
21}
22
23#[derive(Event, Clone)]
26pub struct SendConfigPacketEvent {
27 pub sent_by: Entity,
28 pub packet: ServerboundConfigPacket,
29}
30impl SendConfigPacketEvent {
31 pub fn new(sent_by: Entity, packet: impl Packet<ServerboundConfigPacket>) -> Self {
32 let packet = packet.into_variant();
33 Self { sent_by, packet }
34 }
35}
36
37pub fn handle_outgoing_packets_observer(
38 trigger: Trigger<SendConfigPacketEvent>,
39 mut query: Query<(&mut RawConnection, Option<&InConfigState>)>,
40) {
41 let event = trigger.event();
42 if let Ok((raw_conn, in_configuration_state)) = query.get_mut(event.sent_by) {
43 if in_configuration_state.is_none() {
44 error!(
45 "Tried to send a configuration packet {:?} while not in configuration state",
46 event.packet
47 );
48 return;
49 }
50 debug!("Sending packet: {:?}", event.packet);
51 if let Err(e) = raw_conn.write_packet(event.packet.clone()) {
52 error!("Failed to send packet: {e}");
53 }
54 }
55}
56pub fn handle_outgoing_packets(
59 mut commands: Commands,
60 mut events: EventReader<SendConfigPacketEvent>,
61) {
62 for event in events.read() {
63 commands.trigger(event.clone());
64 }
65}
66
67pub fn emit_receive_config_packet_events(
68 query: Query<(Entity, &RawConnection), With<InConfigState>>,
69 mut packet_events: ResMut<Events<ReceiveConfigPacketEvent>>,
70) {
71 packet_events.clear();
75 for (player_entity, raw_conn) in &query {
76 let packets_lock = raw_conn.incoming_packet_queue();
77 let mut packets = packets_lock.lock();
78 if !packets.is_empty() {
79 let mut packets_read = 0;
80 for raw_packet in packets.iter() {
81 packets_read += 1;
82 let packet = match deserialize_packet::<ClientboundConfigPacket>(&mut Cursor::new(
83 raw_packet,
84 )) {
85 Ok(packet) => packet,
86 Err(err) => {
87 error!("failed to read packet: {err:?}");
88 debug!("packet bytes: {raw_packet:?}");
89 continue;
90 }
91 };
92
93 let should_interrupt = packet_interrupts(&packet);
94
95 packet_events.send(ReceiveConfigPacketEvent {
96 entity: player_entity,
97 packet,
98 });
99
100 if should_interrupt {
101 break;
102 }
103 }
104 packets.drain(0..packets_read);
105 }
106 }
107}
108
109fn packet_interrupts(packet: &ClientboundConfigPacket) -> bool {
114 matches!(
115 packet,
116 ClientboundConfigPacket::FinishConfiguration(_)
117 | ClientboundConfigPacket::Disconnect(_)
118 | ClientboundConfigPacket::Transfer(_)
119 )
120}
121
122#[derive(Event, Debug, Clone)]
130pub struct ConfigPingEvent(pub azalea_protocol::packets::config::ClientboundPing);