azalea_client/plugins/packet/config/
mod.rs

1mod events;
2
3use std::io::Cursor;
4
5use azalea_entity::LocalEntity;
6use azalea_protocol::{
7    packets::{ConnectionProtocol, config::*},
8    read::{ReadPacketError, deserialize_packet},
9};
10use bevy_ecs::prelude::*;
11pub use events::*;
12use tracing::{debug, warn};
13
14use super::{as_system, declare_packet_handlers};
15use crate::{
16    client::InConfigState,
17    connection::RawConnection,
18    cookies::{RequestCookieEvent, StoreCookieEvent},
19    disconnect::DisconnectEvent,
20    local_player::InstanceHolder,
21    packet::game::{KeepAliveEvent, ResourcePackEvent},
22};
23
24pub fn process_raw_packet(
25    ecs: &mut World,
26    player: Entity,
27    raw_packet: &[u8],
28) -> Result<(), Box<ReadPacketError>> {
29    let packet = deserialize_packet(&mut Cursor::new(raw_packet))?;
30    process_packet(ecs, player, &packet);
31    Ok(())
32}
33
34pub fn process_packet(ecs: &mut World, player: Entity, packet: &ClientboundConfigPacket) {
35    let mut handler = ConfigPacketHandler { player, ecs };
36
37    declare_packet_handlers!(
38        ClientboundConfigPacket,
39        packet,
40        handler,
41        [
42            cookie_request,
43            custom_payload,
44            disconnect,
45            finish_configuration,
46            keep_alive,
47            ping,
48            reset_chat,
49            registry_data,
50            resource_pack_pop,
51            resource_pack_push,
52            store_cookie,
53            transfer,
54            update_enabled_features,
55            update_tags,
56            select_known_packs,
57            custom_report_details,
58            server_links,
59            clear_dialog,
60            show_dialog,
61            code_of_conduct,
62        ]
63    );
64}
65
66pub struct ConfigPacketHandler<'a> {
67    pub ecs: &'a mut World,
68    pub player: Entity,
69}
70impl ConfigPacketHandler<'_> {
71    pub fn registry_data(&mut self, p: &ClientboundRegistryData) {
72        as_system::<Query<&InstanceHolder>>(self.ecs, |mut query| {
73            let instance_holder = query.get_mut(self.player).unwrap();
74            let mut instance = instance_holder.instance.write();
75
76            // add the new registry data
77            instance
78                .registries
79                .append(p.registry_id.clone(), p.entries.clone());
80        });
81    }
82
83    pub fn custom_payload(&mut self, p: &ClientboundCustomPayload) {
84        debug!("Got custom payload packet {p:?}");
85    }
86
87    pub fn disconnect(&mut self, p: &ClientboundDisconnect) {
88        warn!("Got disconnect packet {p:?}");
89        as_system::<MessageWriter<_>>(self.ecs, |mut events| {
90            events.write(DisconnectEvent {
91                entity: self.player,
92                reason: Some(p.reason.clone()),
93            });
94        });
95    }
96
97    pub fn finish_configuration(&mut self, _p: &ClientboundFinishConfiguration) {
98        debug!("got FinishConfiguration packet");
99
100        as_system::<(Commands, Query<&mut RawConnection>)>(
101            self.ecs,
102            |(mut commands, mut query)| {
103                let mut raw_conn = query.get_mut(self.player).unwrap();
104                raw_conn.state = ConnectionProtocol::Game;
105
106                commands.trigger(SendConfigPacketEvent::new(
107                    self.player,
108                    ServerboundFinishConfiguration,
109                ));
110
111                // these components are added now that we're going to be in the Game state
112                commands
113                    .entity(self.player)
114                    .remove::<InConfigState>()
115                    .insert((
116                        crate::JoinedClientBundle::default(),
117                        // localentity should already be added, but in case the user forgot or
118                        // something we also add it here
119                        LocalEntity,
120                    ));
121            },
122        );
123    }
124
125    pub fn keep_alive(&mut self, p: &ClientboundKeepAlive) {
126        debug!(
127            "Got keep alive packet (in configuration) {p:?} for {:?}",
128            self.player
129        );
130
131        as_system::<(Commands, MessageWriter<_>)>(self.ecs, |(mut commands, mut events)| {
132            events.write(KeepAliveEvent {
133                entity: self.player,
134                id: p.id,
135            });
136            commands.trigger(SendConfigPacketEvent::new(
137                self.player,
138                ServerboundKeepAlive { id: p.id },
139            ));
140        });
141    }
142
143    pub fn ping(&mut self, p: &ClientboundPing) {
144        debug!("Got ping packet (in configuration) {p:?}");
145
146        as_system::<Commands>(self.ecs, |mut commands| {
147            commands.trigger(ConfigPingEvent {
148                entity: self.player,
149                packet: p.clone(),
150            });
151        });
152    }
153
154    pub fn resource_pack_push(&mut self, p: &ClientboundResourcePackPush) {
155        debug!("Got resource pack push packet {p:?}");
156
157        as_system::<MessageWriter<_>>(self.ecs, |mut events| {
158            events.write(ResourcePackEvent {
159                entity: self.player,
160                id: p.id,
161                url: p.url.to_owned(),
162                hash: p.hash.to_owned(),
163                required: p.required,
164                prompt: p.prompt.to_owned(),
165            });
166        });
167    }
168
169    pub fn resource_pack_pop(&mut self, p: &ClientboundResourcePackPop) {
170        debug!("Got resource pack pop packet {p:?}");
171    }
172
173    pub fn update_enabled_features(&mut self, p: &ClientboundUpdateEnabledFeatures) {
174        debug!("Got update enabled features packet {p:?}");
175    }
176
177    pub fn update_tags(&mut self, _p: &ClientboundUpdateTags) {
178        debug!("Got update tags packet");
179    }
180
181    pub fn cookie_request(&mut self, p: &ClientboundCookieRequest) {
182        debug!("Got cookie request packet {p:?}");
183        as_system::<Commands>(self.ecs, |mut commands| {
184            commands.trigger(RequestCookieEvent {
185                entity: self.player,
186                key: p.key.clone(),
187            });
188        });
189    }
190    pub fn store_cookie(&mut self, p: &ClientboundStoreCookie) {
191        debug!("Got store cookie packet {p:?}");
192        as_system::<Commands>(self.ecs, |mut commands| {
193            commands.trigger(StoreCookieEvent {
194                entity: self.player,
195                key: p.key.clone(),
196                payload: p.payload.clone(),
197            });
198        });
199    }
200
201    pub fn reset_chat(&mut self, p: &ClientboundResetChat) {
202        debug!("Got reset chat packet {p:?}");
203    }
204
205    pub fn transfer(&mut self, p: &ClientboundTransfer) {
206        debug!("Got transfer packet {p:?}");
207    }
208
209    pub fn select_known_packs(&mut self, p: &ClientboundSelectKnownPacks) {
210        debug!("Got select known packs packet {p:?}");
211
212        as_system::<Commands>(self.ecs, |mut commands| {
213            // resource pack management isn't implemented
214            commands.trigger(SendConfigPacketEvent::new(
215                self.player,
216                ServerboundSelectKnownPacks {
217                    known_packs: vec![],
218                },
219            ));
220        });
221    }
222
223    pub fn server_links(&mut self, p: &ClientboundServerLinks) {
224        debug!("Got server links packet {p:?}");
225    }
226
227    pub fn custom_report_details(&mut self, p: &ClientboundCustomReportDetails) {
228        debug!("Got custom report details packet {p:?}");
229    }
230
231    pub fn clear_dialog(&mut self, p: &ClientboundClearDialog) {
232        debug!("Got clear dialog packet {p:?}");
233    }
234    pub fn show_dialog(&mut self, p: &ClientboundShowDialog) {
235        debug!("Got show dialog packet {p:?}");
236    }
237    pub fn code_of_conduct(&mut self, p: &ClientboundCodeOfConduct) {
238        debug!("Got code of conduct packet {p:?}");
239    }
240}