//! Connect to Minecraft servers. #[cfg(feature = "online-mode")] pub mod microsoft; pub mod offline; #[cfg(feature = "online-mode")] pub mod yggdrasil; use std::{fmt::Debug, ops::Deref, pin::Pin, sync::Arc}; #[cfg(feature = "online-mode")] use azalea_auth::sessionserver::ClientSessionServerError; use bevy_ecs::component::Component; use uuid::Uuid; /// Something that can join Minecraft servers. /// /// By default, Azalea only supports either authentication with Microsoft /// (online-mode), or no authentication at all (offline-mode). If you'd like to /// do authentication in some other way, consider looking at [`AccountTrait`]. /// /// To join a server using this account, you can either use /// [`StartJoinServerEvent`] or `azalea::ClientBuilder`. /// /// Note that `Account` is also an ECS component that's present on our client /// entities. /// /// # Examples /// /// ```rust,no_run /// # use azalea_client::Account; /// # /// # #[tokio::main] /// # async fn main() { /// let account = Account::microsoft("example@example.com").await; /// // or Account::offline("example"); /// # } /// ``` /// /// [`StartJoinServerEvent`]: crate::join::StartJoinServerEvent /// [`azalea::ClientBuilder`]: https://docs.rs/azalea/latest/azalea/struct.ClientBuilder.html #[derive(Clone, Component, Debug)] pub struct Account(Arc); impl Account { #[deprecated = "moved to `uuid()`."] pub fn uuid_or_offline(&self) -> Uuid { self.uuid() } } pub(crate) type BoxFuture<'a, T> = Pin + Send + 'a>>; /// A trait that all types of accounts implement. /// /// This can be used, for example, to join servers with a custom authentication /// server. /// /// Anything that implements [`AccountTrait`] can be converted to an [`Account`] /// with `.into()`. /// /// Consider reading the source code of /// [`MicrosoftAccount`](microsoft::MicrosoftAccount) for an example of how to /// implement this. pub trait AccountTrait: Send + Sync + Debug { /// Returns the Minecraft username of the account. fn username(&self) -> &str; /// Returns the unique identifier for this player. /// /// For offline-mode accounts, this UUID is generated by calling /// [`azalea_crypto::offline::generate_uuid`]. fn uuid(&self) -> Uuid; /// The access token for authentication. /// /// You can obtain one of these manually from `azalea-auth`. fn access_token(&self) -> Option; /// Refreshes the access token for this account. #[cfg(feature = "online-mode")] fn refresh(&self) -> BoxFuture<'_, Result<(), azalea_auth::AuthError>> { Box::pin(async { Ok(()) }) } /// Refreshes the access token for this account. /// /// The `online-mode` feature is disabled, so this won't do anything. #[cfg(not(feature = "online-mode"))] fn refresh(&self) -> BoxFuture<'_, Result<(), ()>> { Box::pin(async { Ok(()) }) } #[cfg(feature = "online-mode")] fn certs(&self) -> Option { None } /// Override the chat signing certificates for this account. /// /// You can get the certificates needed for this from /// [`azalea_auth::certs::fetch_certificates`]. You typically don't need to /// call this yourself, as Azalea will do it for you. /// /// For accounts that don't support signing (i.e. offline-mode), this won't /// do anything. #[cfg(feature = "online-mode")] fn set_certs(&self, certs: azalea_auth::certs::Certificates) { let _ = certs; } fn certs_backend(&self) -> Option<&str> { None } /// Typically used to tell Mojang's sessionserver that we are going to join /// a server. /// /// This must be implemented for accounts that can join online-mode servers. /// /// This function is called internally by Azalea when the account tries to /// join a server, but only if [`AccountTrait::access_token`] is `Some`. #[cfg(feature = "online-mode")] fn join<'a>( &'a self, public_key: &'a [u8], private_key: &'a [u8; 16], server_id: &'a str, proxy: Option, ) -> BoxFuture<'a, Result<(), ClientSessionServerError>> { let _ = (public_key, private_key, server_id, proxy); Box::pin(async { Ok(()) }) } /// Typically used to tell Mojang's sessionserver that we are going to join /// a server. /// /// The `online-mode` feature is disabled, so this won't do anything. #[cfg(not(feature = "online-mode"))] fn join( &self, public_key: &[u8], private_key: &[u8; 16], server_id: &str, proxy: Option<()>, ) -> BoxFuture<'_, Result<(), ()>> { let _ = (public_key, private_key, server_id, proxy); Box::pin(async { Ok(()) }) } } impl From for Account { fn from(value: T) -> Self { Account(Arc::new(value)) } } impl Deref for Account { type Target = dyn AccountTrait; fn deref(&self) -> &Self::Target { &*self.0 } }