azalea_client/packet_handling/
login.rs1use std::{collections::HashSet, sync::Arc};
5
6use azalea_protocol::packets::{
7 login::{
8 s_custom_query_answer::ServerboundCustomQueryAnswer, ClientboundLoginPacket,
9 ServerboundLoginPacket,
10 },
11 Packet,
12};
13use bevy_ecs::{prelude::*, system::SystemState};
14use derive_more::{Deref, DerefMut};
15use tokio::sync::mpsc;
16use tracing::error;
17
18#[derive(Event, Debug, Clone)]
26pub struct LoginPacketEvent {
27 pub entity: Entity,
29 pub packet: Arc<ClientboundLoginPacket>,
31}
32
33#[derive(Event)]
35pub struct SendLoginPacketEvent {
36 pub entity: Entity,
37 pub packet: ServerboundLoginPacket,
38}
39impl SendLoginPacketEvent {
40 pub fn new(entity: Entity, packet: impl Packet<ServerboundLoginPacket>) -> Self {
41 let packet = packet.into_variant();
42 Self { entity, packet }
43 }
44}
45
46#[derive(Component)]
47pub struct LoginSendPacketQueue {
48 pub tx: mpsc::UnboundedSender<ServerboundLoginPacket>,
49}
50
51pub fn handle_send_packet_event(
52 mut send_packet_events: EventReader<SendLoginPacketEvent>,
53 mut query: Query<&mut LoginSendPacketQueue>,
54) {
55 for event in send_packet_events.read() {
56 if let Ok(queue) = query.get_mut(event.entity) {
57 let _ = queue.tx.send(event.packet.clone());
58 } else {
59 error!("Sent SendPacketEvent for entity that doesn't have a LoginSendPacketQueue");
60 }
61 }
62}
63
64#[derive(Component, Default, Debug, Deref, DerefMut)]
67pub struct IgnoreQueryIds(HashSet<u32>);
68
69pub fn process_packet_events(ecs: &mut World) {
70 let mut events_owned = Vec::new();
71 let mut system_state: SystemState<ResMut<Events<LoginPacketEvent>>> = SystemState::new(ecs);
72 let mut events = system_state.get_mut(ecs);
73 for LoginPacketEvent {
74 entity: player_entity,
75 packet,
76 } in events.drain()
77 {
78 events_owned.push((player_entity, packet));
80 }
81 for (player_entity, packet) in events_owned {
82 #[allow(clippy::single_match)]
83 match packet.as_ref() {
84 ClientboundLoginPacket::CustomQuery(p) => {
85 let mut system_state: SystemState<(
86 EventWriter<SendLoginPacketEvent>,
87 Query<&IgnoreQueryIds>,
88 )> = SystemState::new(ecs);
89 let (mut send_packet_events, query) = system_state.get_mut(ecs);
90
91 let ignore_query_ids = query.get(player_entity).ok().map(|x| x.0.clone());
92 if let Some(ignore_query_ids) = ignore_query_ids {
93 if ignore_query_ids.contains(&p.transaction_id) {
94 continue;
95 }
96 }
97
98 send_packet_events.send(SendLoginPacketEvent::new(
99 player_entity,
100 ServerboundCustomQueryAnswer {
101 transaction_id: p.transaction_id,
102 data: None,
103 },
104 ));
105 }
106 _ => {}
107 }
108 }
109}