azalea_client/plugins/packet/login/
mod.rs1mod events;
5
6use azalea_protocol::packets::{
7 ConnectionProtocol,
8 login::{
9 ClientboundCookieRequest, ClientboundCustomQuery, ClientboundHello,
10 ClientboundLoginCompression, ClientboundLoginDisconnect, ClientboundLoginFinished,
11 ClientboundLoginPacket, ServerboundCookieResponse, ServerboundLoginAcknowledged,
12 },
13};
14use bevy_ecs::prelude::*;
15pub use events::*;
16use tracing::{debug, error};
17
18use super::as_system;
19use crate::{
20 Account, GameProfileComponent, InConfigState, connection::RawConnection,
21 declare_packet_handlers, disconnect::DisconnectEvent,
22};
23
24pub fn process_packet(ecs: &mut World, player: Entity, packet: &ClientboundLoginPacket) {
25 let mut handler = LoginPacketHandler { player, ecs };
26
27 declare_packet_handlers!(
28 ClientboundLoginPacket,
29 packet,
30 handler,
31 [
32 hello,
33 login_disconnect,
34 login_finished,
35 login_compression,
36 custom_query,
37 cookie_request
38 ]
39 );
40}
41
42#[derive(Component, Clone, Debug)]
45pub struct InLoginState;
46
47pub struct LoginPacketHandler<'a> {
48 pub ecs: &'a mut World,
49 pub player: Entity,
50}
51impl LoginPacketHandler<'_> {
52 pub fn hello(&mut self, p: &ClientboundHello) {
53 debug!("Got encryption request {p:?}");
54
55 as_system::<(Commands, Query<&Account>)>(self.ecs, |(mut commands, query)| {
56 let Ok(account) = query.get(self.player) else {
57 error!(
58 "Expected Account component to be present on player when receiving hello packet."
59 );
60 return;
61 };
62 commands.trigger_targets(
63 ReceiveHelloEvent {
64 account: account.clone(),
65 packet: p.clone(),
66 },
67 self.player,
68 );
69 });
70 }
71 pub fn login_disconnect(&mut self, p: &ClientboundLoginDisconnect) {
72 debug!("Got disconnect {:?}", p);
73
74 as_system::<EventWriter<_>>(self.ecs, |mut events| {
75 events.write(DisconnectEvent {
76 entity: self.player,
77 reason: Some(p.reason.clone()),
78 });
79 });
80 }
81 pub fn login_finished(&mut self, p: &ClientboundLoginFinished) {
82 debug!(
83 "Got profile {:?}. login is finished and we're now switching to the config state",
84 p.game_profile
85 );
86
87 as_system::<(Commands, Query<&mut RawConnection>)>(
88 self.ecs,
89 |(mut commands, mut query)| {
90 commands.trigger(SendLoginPacketEvent::new(
91 self.player,
92 ServerboundLoginAcknowledged,
93 ));
94
95 commands
96 .entity(self.player)
97 .remove::<InLoginState>()
98 .insert(InConfigState)
99 .insert(GameProfileComponent(p.game_profile.clone()));
100
101 let mut conn = query
102 .get_mut(self.player)
103 .expect("RawConnection component should be present when receiving packets");
104 conn.state = ConnectionProtocol::Configuration;
105 },
106 );
107 }
108 pub fn login_compression(&mut self, p: &ClientboundLoginCompression) {
109 debug!("Got compression request {p:?}");
110
111 as_system::<Query<&mut RawConnection>>(self.ecs, |mut query| {
112 let mut conn = query
113 .get_mut(self.player)
114 .expect("RawConnection component should be present when receiving packets");
115 if let Some(net_conn) = &mut conn.net_conn() {
116 net_conn.set_compression_threshold(Some(p.compression_threshold as u32));
117 }
118 })
119 }
120 pub fn custom_query(&mut self, p: &ClientboundCustomQuery) {
121 debug!("Got custom query {p:?}");
122
123 as_system::<EventWriter<ReceiveCustomQueryEvent>>(self.ecs, |mut events| {
124 events.write(ReceiveCustomQueryEvent {
125 entity: self.player,
126 packet: p.clone(),
127 disabled: false,
128 });
129 });
130 }
131 pub fn cookie_request(&mut self, p: &ClientboundCookieRequest) {
132 debug!("Got cookie request {p:?}");
133
134 as_system::<Commands>(self.ecs, |mut commands| {
135 commands.trigger(SendLoginPacketEvent::new(
136 self.player,
137 ServerboundCookieResponse {
138 key: p.key.clone(),
139 payload: None,
141 },
142 ));
143 });
144 }
145}