diff options
| author | mat <27899617+mat-1@users.noreply.github.com> | 2025-02-22 21:45:26 -0600 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-02-22 21:45:26 -0600 |
| commit | e21e1b97bf9337e9f4747cd1b545b1b3a03e2ce7 (patch) | |
| tree | add6f8bfce40d0c07845d8aa4c9945a0b918444c /azalea-client/src/plugins/packet/login.rs | |
| parent | f8130c3c92946d2293634ba4e252d6bc93026c3c (diff) | |
| download | azalea-drasl-e21e1b97bf9337e9f4747cd1b545b1b3a03e2ce7.tar.xz | |
Refactor azalea-client (#205)
* start organizing packet_handling more by moving packet handlers into their own functions
* finish writing all the handler functions for packets
* use macro for generating match statement for packet handler functions
* fix set_entity_data
* update config state to also use handler functions
* organize az-client file structure by moving things into plugins directory
* fix merge issues
Diffstat (limited to 'azalea-client/src/plugins/packet/login.rs')
| -rw-r--r-- | azalea-client/src/plugins/packet/login.rs | 114 |
1 files changed, 114 insertions, 0 deletions
diff --git a/azalea-client/src/plugins/packet/login.rs b/azalea-client/src/plugins/packet/login.rs new file mode 100644 index 00000000..1bb07266 --- /dev/null +++ b/azalea-client/src/plugins/packet/login.rs @@ -0,0 +1,114 @@ +// login packets aren't actually handled here because compression/encryption +// would make packet handling a lot messier + +use std::{collections::HashSet, sync::Arc}; + +use azalea_protocol::packets::{ + Packet, + login::{ + ClientboundLoginPacket, ServerboundLoginPacket, + s_custom_query_answer::ServerboundCustomQueryAnswer, + }, +}; +use bevy_ecs::{prelude::*, system::SystemState}; +use derive_more::{Deref, DerefMut}; +use tokio::sync::mpsc; +use tracing::error; + +// this struct is defined here anyways though so it's consistent with the other +// ones + +/// An event that's sent when we receive a login packet from the server. Note +/// that if you want to handle this in a system, you must add +/// `.before(azalea::packet::login::process_packet_events)` to it +/// because that system clears the events. +#[derive(Event, Debug, Clone)] +pub struct LoginPacketEvent { + /// The client entity that received the packet. + pub entity: Entity, + /// The packet that was actually received. + pub packet: Arc<ClientboundLoginPacket>, +} + +/// Event for sending a login packet to the server. +#[derive(Event)] +pub struct SendLoginPacketEvent { + pub entity: Entity, + pub packet: ServerboundLoginPacket, +} +impl SendLoginPacketEvent { + pub fn new(entity: Entity, packet: impl Packet<ServerboundLoginPacket>) -> Self { + let packet = packet.into_variant(); + Self { entity, packet } + } +} + +#[derive(Component)] +pub struct LoginSendPacketQueue { + pub tx: mpsc::UnboundedSender<ServerboundLoginPacket>, +} + +/// A marker component for local players that are currently in the +/// `login` state. +#[derive(Component, Clone, Debug)] +pub struct InLoginState; + +pub fn handle_send_packet_event( + mut send_packet_events: EventReader<SendLoginPacketEvent>, + mut query: Query<&mut LoginSendPacketQueue>, +) { + for event in send_packet_events.read() { + if let Ok(queue) = query.get_mut(event.entity) { + let _ = queue.tx.send(event.packet.clone()); + } else { + error!("Sent SendPacketEvent for entity that doesn't have a LoginSendPacketQueue"); + } + } +} + +/// Plugins can add to this set if they want to handle a custom query packet +/// themselves. This component removed after the login state ends. +#[derive(Component, Default, Debug, Deref, DerefMut)] +pub struct IgnoreQueryIds(HashSet<u32>); + +pub fn process_packet_events(ecs: &mut World) { + let mut events_owned = Vec::new(); + let mut system_state: SystemState<ResMut<Events<LoginPacketEvent>>> = SystemState::new(ecs); + let mut events = system_state.get_mut(ecs); + for LoginPacketEvent { + entity: player_entity, + packet, + } in events.drain() + { + // we do this so `ecs` isn't borrowed for the whole loop + events_owned.push((player_entity, packet)); + } + for (player_entity, packet) in events_owned { + #[allow(clippy::single_match)] + match packet.as_ref() { + ClientboundLoginPacket::CustomQuery(p) => { + let mut system_state: SystemState<( + EventWriter<SendLoginPacketEvent>, + Query<&IgnoreQueryIds>, + )> = SystemState::new(ecs); + let (mut send_packet_events, query) = system_state.get_mut(ecs); + + let ignore_query_ids = query.get(player_entity).ok().map(|x| x.0.clone()); + if let Some(ignore_query_ids) = ignore_query_ids { + if ignore_query_ids.contains(&p.transaction_id) { + continue; + } + } + + send_packet_events.send(SendLoginPacketEvent::new( + player_entity, + ServerboundCustomQueryAnswer { + transaction_id: p.transaction_id, + data: None, + }, + )); + } + _ => {} + } + } +} |
