azalea_client/plugins/packet/
login.rs1use std::{collections::HashSet, sync::Arc};
5
6use azalea_protocol::packets::{
7 Packet,
8 login::{
9 ClientboundLoginPacket, ServerboundLoginPacket,
10 s_custom_query_answer::ServerboundCustomQueryAnswer,
11 },
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
51#[derive(Component, Clone, Debug)]
54pub struct InLoginState;
55
56pub fn handle_send_packet_event(
57 mut send_packet_events: EventReader<SendLoginPacketEvent>,
58 mut query: Query<&mut LoginSendPacketQueue>,
59) {
60 for event in send_packet_events.read() {
61 if let Ok(queue) = query.get_mut(event.entity) {
62 let _ = queue.tx.send(event.packet.clone());
63 } else {
64 error!("Sent SendPacketEvent for entity that doesn't have a LoginSendPacketQueue");
65 }
66 }
67}
68
69#[derive(Component, Default, Debug, Deref, DerefMut)]
72pub struct IgnoreQueryIds(HashSet<u32>);
73
74pub fn process_packet_events(ecs: &mut World) {
75 let mut events_owned = Vec::new();
76 let mut system_state: SystemState<ResMut<Events<LoginPacketEvent>>> = SystemState::new(ecs);
77 let mut events = system_state.get_mut(ecs);
78 for LoginPacketEvent {
79 entity: player_entity,
80 packet,
81 } in events.drain()
82 {
83 events_owned.push((player_entity, packet));
85 }
86 for (player_entity, packet) in events_owned {
87 #[allow(clippy::single_match)]
88 match packet.as_ref() {
89 ClientboundLoginPacket::CustomQuery(p) => {
90 let mut system_state: SystemState<(
91 EventWriter<SendLoginPacketEvent>,
92 Query<&IgnoreQueryIds>,
93 )> = SystemState::new(ecs);
94 let (mut send_packet_events, query) = system_state.get_mut(ecs);
95
96 let ignore_query_ids = query.get(player_entity).ok().map(|x| x.0.clone());
97 if let Some(ignore_query_ids) = ignore_query_ids {
98 if ignore_query_ids.contains(&p.transaction_id) {
99 continue;
100 }
101 }
102
103 send_packet_events.send(SendLoginPacketEvent::new(
104 player_entity,
105 ServerboundCustomQueryAnswer {
106 transaction_id: p.transaction_id,
107 data: None,
108 },
109 ));
110 }
111 _ => {}
112 }
113 }
114}