From 8da179b221ae4a7bfd02245b3cb6357464adbc43 Mon Sep 17 00:00:00 2001 From: mat Date: Mon, 2 Jun 2025 04:12:07 -0100 Subject: simplify some join logic so the Entity is returned even on connection error --- azalea-client/src/plugins/join.rs | 54 ++++++++------------------------------ azalea-client/src/plugins/login.rs | 19 +++++++++++--- 2 files changed, 26 insertions(+), 47 deletions(-) (limited to 'azalea-client/src/plugins') diff --git a/azalea-client/src/plugins/join.rs b/azalea-client/src/plugins/join.rs index a3447782..09eeff59 100644 --- a/azalea-client/src/plugins/join.rs +++ b/azalea-client/src/plugins/join.rs @@ -1,4 +1,4 @@ -use std::{io, net::SocketAddr, sync::Arc}; +use std::{net::SocketAddr, sync::Arc}; use azalea_entity::{LocalEntity, indexing::EntityUuidIndex}; use azalea_protocol::{ @@ -20,7 +20,7 @@ use tracing::{debug, warn}; use super::events::LocalPlayerEvents; use crate::{ - Account, JoinError, LocalPlayerBundle, + Account, LocalPlayerBundle, connection::RawConnection, packet::login::{InLoginState, SendLoginPacketEvent}, }; @@ -36,7 +36,6 @@ impl Plugin for JoinPlugin { ( handle_start_join_server_event.before(super::login::poll_auth_task), poll_create_connection_task, - handle_connection_failed_events, ) .chain(), ); @@ -53,7 +52,8 @@ pub struct StartJoinServerEvent { pub connect_opts: ConnectOpts, pub event_sender: Option>, - pub start_join_callback_tx: Option, + // this is mpsc instead of oneshot so it can be cloned (since it's sent in an event) + pub start_join_callback_tx: Option>, } /// Options for how the connection to the server will be made. These are @@ -79,11 +79,6 @@ pub struct ConnectionFailedEvent { pub error: ConnectionError, } -// this is mpsc instead of oneshot so it can be cloned (since it's sent in an -// event) -#[derive(Component, Debug, Clone)] -pub struct StartJoinCallback(pub mpsc::UnboundedSender>); - pub fn handle_start_join_server_event( mut commands: Commands, mut events: EventReader, @@ -103,7 +98,7 @@ pub fn handle_start_join_server_event( warn!( "Received StartJoinServerEvent for {entity:?} but it's already connected. Ignoring the event but replying with Ok." ); - let _ = start_join_callback_tx.0.send(Ok(entity)); + let _ = start_join_callback_tx.send(entity); } else { warn!( "Received StartJoinServerEvent for {entity:?} but it's already connected. Ignoring the event." @@ -121,6 +116,10 @@ pub fn handle_start_join_server_event( entity }; + if let Some(start_join_callback) = &event.start_join_callback_tx { + let _ = start_join_callback.send(entity); + } + let mut entity_mut = commands.entity(entity); entity_mut.insert(( @@ -141,9 +140,6 @@ pub fn handle_start_join_server_event( // handle receiving packets entity_mut.insert(LocalPlayerEvents(event_sender.clone())); } - if let Some(start_join_callback) = &event.start_join_callback_tx { - entity_mut.insert(start_join_callback.clone()); - } let task_pool = IoTaskPool::get(); let connect_opts = event.connect_opts.clone(); @@ -184,15 +180,10 @@ pub struct CreateConnectionTask(pub Task>); pub fn poll_create_connection_task( mut commands: Commands, - mut query: Query<( - Entity, - &mut CreateConnectionTask, - &Account, - Option<&StartJoinCallback>, - )>, + mut query: Query<(Entity, &mut CreateConnectionTask, &Account)>, mut connection_failed_events: EventWriter, ) { - for (entity, mut task, account, mut start_join_callback) in query.iter_mut() { + for (entity, mut task, account) in query.iter_mut() { if let Some(poll_res) = future::block_on(future::poll_once(&mut task.0)) { let mut entity_mut = commands.entity(entity); entity_mut.remove::(); @@ -238,29 +229,6 @@ pub fn poll_create_connection_task( profile_id: account.uuid_or_offline(), }, )); - - if let Some(cb) = start_join_callback.take() { - let _ = cb.0.send(Ok(entity)); - } } } } - -pub fn handle_connection_failed_events( - mut events: EventReader, - query: Query<&StartJoinCallback>, -) { - for event in events.read() { - let Ok(start_join_callback) = query.get(event.entity) else { - // the StartJoinCallback isn't required to be present, so this is fine - continue; - }; - - // io::Error isn't clonable, so we create a new one based on the `kind` and - // `to_string`, - let ConnectionError::Io(err) = &event.error; - let cloned_err = ConnectionError::Io(io::Error::new(err.kind(), err.to_string())); - - let _ = start_join_callback.0.send(Err(cloned_err.into())); - } -} diff --git a/azalea-client/src/plugins/login.rs b/azalea-client/src/plugins/login.rs index ebba5905..5cb2bce7 100644 --- a/azalea-client/src/plugins/login.rs +++ b/azalea-client/src/plugins/login.rs @@ -5,13 +5,14 @@ use azalea_protocol::packets::login::{ use bevy_app::prelude::*; use bevy_ecs::prelude::*; use bevy_tasks::{IoTaskPool, Task, futures_lite::future}; +use thiserror::Error; use tracing::{debug, error, trace}; use super::{ connection::RawConnection, packet::login::{ReceiveCustomQueryEvent, ReceiveHelloEvent, SendLoginPacketEvent}, }; -use crate::{Account, JoinError}; +use crate::Account; /// Some systems that run during the `login` state. pub struct LoginPlugin; @@ -73,14 +74,24 @@ pub fn poll_auth_task( type PrivateKey = [u8; 16]; #[derive(Component)] -pub struct AuthTask(Task>); +pub struct AuthTask(Task>); + +#[derive(Debug, Error)] +pub enum AuthWithAccountError { + #[error("Failed to encrypt the challenge from the server for {0:?}")] + Encryption(ClientboundHello), + #[error("{0}")] + SessionServer(#[from] ClientSessionServerError), + #[error("Couldn't refresh access token: {0}")] + Auth(#[from] azalea_auth::AuthError), +} pub async fn auth_with_account( account: Account, packet: ClientboundHello, -) -> Result<(ServerboundKey, PrivateKey), JoinError> { +) -> Result<(ServerboundKey, PrivateKey), AuthWithAccountError> { let Ok(encrypt_res) = azalea_crypto::encrypt(&packet.public_key, &packet.challenge) else { - return Err(JoinError::EncryptionError(packet)); + return Err(AuthWithAccountError::Encryption(packet)); }; let key_packet = ServerboundKey { key_bytes: encrypt_res.encrypted_public_key, -- cgit v1.2.3