diff options
Diffstat (limited to 'azalea-client/src')
| -rw-r--r-- | azalea-client/src/account.rs | 30 | ||||
| -rw-r--r-- | azalea-client/src/plugins/chat/handler.rs | 13 | ||||
| -rw-r--r-- | azalea-client/src/plugins/chat_signing.rs | 4 | ||||
| -rw-r--r-- | azalea-client/src/plugins/disconnect.rs | 7 | ||||
| -rw-r--r-- | azalea-client/src/plugins/login.rs | 94 | ||||
| -rw-r--r-- | azalea-client/src/plugins/mod.rs | 8 |
6 files changed, 100 insertions, 56 deletions
diff --git a/azalea-client/src/account.rs b/azalea-client/src/account.rs index ab8e8e65..847029c9 100644 --- a/azalea-client/src/account.rs +++ b/azalea-client/src/account.rs @@ -2,14 +2,14 @@ use std::sync::Arc; -use azalea_auth::{ - AccessTokenResponse, - certs::{Certificates, FetchCertificatesError}, -}; +#[cfg(feature = "online-mode")] +use azalea_auth::AccessTokenResponse; +#[cfg(feature = "online-mode")] +use azalea_auth::certs::{Certificates, FetchCertificatesError}; use bevy_ecs::component::Component; use parking_lot::Mutex; +#[cfg(feature = "online-mode")] use thiserror::Error; -use tracing::trace; use uuid::Uuid; /// Something that can join Minecraft servers. @@ -58,6 +58,7 @@ pub struct Account { /// /// This is set when you call [`Self::request_certs`], but you only /// need to if the servers you're joining require it. + #[cfg(feature = "online-mode")] pub certs: Arc<Mutex<Option<Certificates>>>, } @@ -67,9 +68,11 @@ pub enum AccountOpts { Offline { username: String, }, + #[cfg(feature = "online-mode")] Microsoft { email: String, }, + #[cfg(feature = "online-mode")] MicrosoftWithAccessToken { msa: Arc<Mutex<azalea_auth::cache::ExpiringValue<AccessTokenResponse>>>, }, @@ -88,6 +91,7 @@ impl Account { account_opts: AccountOpts::Offline { username: username.to_string(), }, + #[cfg(feature = "online-mode")] certs: Arc::new(Mutex::new(None)), } } @@ -97,6 +101,7 @@ impl Account { /// /// The cache key is used for avoiding having to log in every time. This is /// typically set to the account email, but it can be any string. + #[cfg(feature = "online-mode")] pub async fn microsoft(cache_key: &str) -> Result<Self, azalea_auth::AuthError> { Self::microsoft_with_custom_client_id_and_scope(cache_key, None, None).await } @@ -105,6 +110,7 @@ impl Account { /// and `scope`. /// /// Pass `None` if you want to use default ones. + #[cfg(feature = "online-mode")] pub async fn microsoft_with_custom_client_id_and_scope( cache_key: &str, client_id: Option<&str>, @@ -162,6 +168,7 @@ impl Account { /// # Ok(()) /// # } /// ``` + #[cfg(feature = "online-mode")] pub async fn with_microsoft_access_token( msa: azalea_auth::cache::ExpiringValue<AccessTokenResponse>, ) -> Result<Self, azalea_auth::AuthError> { @@ -170,6 +177,7 @@ impl Account { /// Similar to [`Account::with_microsoft_access_token`] but you can use /// custom `client_id` and `scope`. + #[cfg(feature = "online-mode")] pub async fn with_microsoft_access_token_and_custom_client_id_and_scope( mut msa: azalea_auth::cache::ExpiringValue<AccessTokenResponse>, client_id: Option<&str>, @@ -178,6 +186,8 @@ impl Account { let client = reqwest::Client::new(); if msa.is_expired() { + use tracing::trace; + trace!("refreshing Microsoft auth token"); msa = azalea_auth::refresh_ms_auth_token( &client, @@ -209,6 +219,7 @@ impl Account { /// This requires the `auth_opts` field to be set correctly (which is done /// by default if you used the constructor functions). Note that if the /// Account is offline-mode then this function won't do anything. + #[cfg(feature = "online-mode")] pub async fn refresh(&self) -> Result<(), azalea_auth::AuthError> { match &self.account_opts { // offline mode doesn't need to refresh so just don't do anything lol @@ -240,6 +251,13 @@ impl Account { } } + /// Stub function that does nothing when the `online-mode` feature is + /// disabled. + #[cfg(not(feature = "online-mode"))] + pub async fn refresh(&self) -> Result<(), ()> { + Ok(()) + } + /// Get the UUID of this account. /// /// If the `uuid` field is None, the UUID will be determined by using @@ -250,6 +268,7 @@ impl Account { } } +#[cfg(feature = "online-mode")] #[derive(Error, Debug)] pub enum RequestCertError { #[error("Failed to fetch certificates")] @@ -261,6 +280,7 @@ pub enum RequestCertError { impl Account { /// Request the certificates used for chat signing and set it in /// [`Self::certs`]. + #[cfg(feature = "online-mode")] pub async fn request_certs(&mut self) -> Result<(), RequestCertError> { let access_token = self .access_token diff --git a/azalea-client/src/plugins/chat/handler.rs b/azalea-client/src/plugins/chat/handler.rs index 5a2a065c..49f27209 100644 --- a/azalea-client/src/plugins/chat/handler.rs +++ b/azalea-client/src/plugins/chat/handler.rs @@ -1,6 +1,5 @@ use std::time::{SystemTime, UNIX_EPOCH}; -use azalea_crypto::SignChatMessageOptions; use azalea_protocol::packets::{ Packet, game::{ServerboundChat, ServerboundChatCommand, s_chat::LastSeenMessagesUpdate}, @@ -8,7 +7,9 @@ use azalea_protocol::packets::{ use bevy_ecs::prelude::*; use super::ChatKind; -use crate::{Account, chat_signing::ChatSigningSession, packet::game::SendGamePacketEvent}; +use crate::packet::game::SendGamePacketEvent; +#[cfg(feature = "online-mode")] +use crate::{Account, chat_signing::ChatSigningSession}; /// Send a chat packet to the server of a specific kind (chat message or /// command). Usually you just want [`SendChatEvent`] instead. @@ -31,7 +32,7 @@ pub struct SendChatKindEvent { pub fn handle_send_chat_kind_event( mut events: MessageReader<SendChatKindEvent>, mut commands: Commands, - mut query: Query<(&Account, &mut ChatSigningSession)>, + #[cfg(feature = "online-mode")] mut query: Query<(&Account, &mut ChatSigningSession)>, ) { for event in events.read() { let content = event @@ -47,6 +48,7 @@ pub fn handle_send_chat_kind_event( ChatKind::Message => { let salt = azalea_crypto::make_salt(); + #[cfg(feature = "online-mode")] let signature = if let Ok((account, mut chat_session)) = query.get_mut(event.entity) { Some(create_signature( @@ -59,6 +61,8 @@ pub fn handle_send_chat_kind_event( } else { None }; + #[cfg(not(feature = "online-mode"))] + let signature = None; ServerboundChat { message: content, @@ -85,6 +89,7 @@ pub fn handle_send_chat_kind_event( } } +#[cfg(feature = "online-mode")] pub fn create_signature( account: &Account, chat_session: &mut ChatSigningSession, @@ -92,6 +97,8 @@ pub fn create_signature( timestamp: SystemTime, message: &str, ) -> azalea_crypto::MessageSignature { + use azalea_crypto::SignChatMessageOptions; + let certs = account.certs.lock(); let certs = certs.as_ref().expect("certs shouldn't be set back to None"); diff --git a/azalea-client/src/plugins/chat_signing.rs b/azalea-client/src/plugins/chat_signing.rs index 612383c2..8e612f5b 100644 --- a/azalea-client/src/plugins/chat_signing.rs +++ b/azalea-client/src/plugins/chat_signing.rs @@ -43,8 +43,8 @@ pub struct RequestCertsTask(pub Task<Result<Certificates, FetchCertificatesError pub struct OnlyRefreshCertsAfter { pub refresh_at: Instant, } -/// A component that's present when that this client has sent its certificates -/// to the server. +/// A component that's present when this client has sent its certificates to the +/// server. /// /// This should be removed if you want to re-send the certs. /// diff --git a/azalea-client/src/plugins/disconnect.rs b/azalea-client/src/plugins/disconnect.rs index 95950ae9..08fe3807 100644 --- a/azalea-client/src/plugins/disconnect.rs +++ b/azalea-client/src/plugins/disconnect.rs @@ -11,9 +11,11 @@ use derive_more::Deref; use tracing::info; use super::login::IsAuthenticated; +#[cfg(feature = "online-mode")] +use crate::chat_signing; use crate::{ - chat_signing, client::JoinedClientBundle, connection::RawConnection, - local_player::InstanceHolder, tick_counter::TicksConnected, + client::JoinedClientBundle, connection::RawConnection, local_player::InstanceHolder, + tick_counter::TicksConnected, }; pub struct DisconnectPlugin; @@ -69,6 +71,7 @@ pub struct RemoveOnDisconnectBundle { /// This makes it not send [`DisconnectEvent`] again. pub is_connection_alive: IsConnectionAlive, /// Resend our chat signing certs next time. + #[cfg(feature = "online-mode")] pub chat_signing_session: chat_signing::ChatSigningSession, /// They're not authenticated anymore if they disconnected. pub is_authenticated: IsAuthenticated, diff --git a/azalea-client/src/plugins/login.rs b/azalea-client/src/plugins/login.rs index 25919c8c..46ff8ea9 100644 --- a/azalea-client/src/plugins/login.rs +++ b/azalea-client/src/plugins/login.rs @@ -1,3 +1,4 @@ +#[cfg(feature = "online-mode")] use azalea_auth::sessionserver::ClientSessionServerError; use azalea_protocol::packets::login::{ ClientboundHello, ServerboundCustomQueryAnswer, ServerboundKey, @@ -80,8 +81,10 @@ pub struct AuthTask(Task<Result<(ServerboundKey, PrivateKey), AuthWithAccountErr pub enum AuthWithAccountError { #[error("Failed to encrypt the challenge from the server for {0:?}")] Encryption(ClientboundHello), + #[cfg(feature = "online-mode")] #[error("{0}")] SessionServer(#[from] ClientSessionServerError), + #[cfg(feature = "online-mode")] #[error("Couldn't refresh access token: {0}")] Auth(#[from] azalea_auth::AuthError), } @@ -99,49 +102,56 @@ pub async fn auth_with_account( }; let private_key = encrypt_res.secret_key; - let Some(access_token) = &account.access_token else { - // offline mode account, no need to do auth - return Ok((key_packet, private_key)); - }; - - // keep track of the number of times we tried authenticating so we can give up - // after too many - let mut attempts: usize = 1; - - while let Err(err) = { - let access_token = access_token.lock().clone(); - - let uuid = &account - .uuid - .expect("Uuid must be present if access token is present."); - - // this is necessary since reqwest usually depends on tokio and we're using - // `futures` here - async_compat::Compat::new(azalea_auth::sessionserver::join( - &access_token, - &packet.public_key, - &private_key, - uuid, - &packet.server_id, - )) - .await - } { - if attempts >= 2 { - // if this is the second attempt and we failed - // both times, give up - return Err(err.into()); - } - if matches!( - err, - ClientSessionServerError::InvalidSession | ClientSessionServerError::ForbiddenOperation - ) { - // uh oh, we got an invalid session and have - // to reauthenticate now - async_compat::Compat::new(account.refresh()).await?; - } else { - return Err(err.into()); + #[cfg(not(feature = "online-mode"))] + let _ = account; + + #[cfg(feature = "online-mode")] + if packet.should_authenticate { + let Some(access_token) = &account.access_token else { + // offline mode account, no need to do auth + return Ok((key_packet, private_key)); + }; + + // keep track of the number of times we tried authenticating so we can give up + // after too many + let mut attempts: usize = 1; + + while let Err(err) = { + let access_token = access_token.lock().clone(); + + let uuid = &account + .uuid + .expect("Uuid must be present if access token is present."); + + // this is necessary since reqwest usually depends on tokio and we're using + // `futures` here + async_compat::Compat::new(azalea_auth::sessionserver::join( + &access_token, + &packet.public_key, + &private_key, + uuid, + &packet.server_id, + )) + .await + } { + if attempts >= 2 { + // if this is the second attempt and we failed + // both times, give up + return Err(err.into()); + } + if matches!( + err, + ClientSessionServerError::InvalidSession + | ClientSessionServerError::ForbiddenOperation + ) { + // uh oh, we got an invalid session and have + // to reauthenticate now + async_compat::Compat::new(account.refresh()).await?; + } else { + return Err(err.into()); + } + attempts += 1; } - attempts += 1; } Ok((key_packet, private_key)) diff --git a/azalea-client/src/plugins/mod.rs b/azalea-client/src/plugins/mod.rs index a12d69cb..54f577e3 100644 --- a/azalea-client/src/plugins/mod.rs +++ b/azalea-client/src/plugins/mod.rs @@ -5,6 +5,7 @@ pub mod auto_reconnect; pub mod block_update; pub mod brand; pub mod chat; +#[cfg(feature = "online-mode")] pub mod chat_signing; pub mod chunks; pub mod client_information; @@ -62,8 +63,11 @@ impl PluginGroup for DefaultPlugins { .add(connection::ConnectionPlugin) .add(login::LoginPlugin) .add(join::JoinPlugin) - .add(auto_reconnect::AutoReconnectPlugin) - .add(chat_signing::ChatSigningPlugin); + .add(auto_reconnect::AutoReconnectPlugin); + #[cfg(feature = "online-mode")] + { + group = group.add(chat_signing::ChatSigningPlugin); + } #[cfg(feature = "log")] { group = group.add(bevy_log::LogPlugin::default()); |
