azalea_client/account/
mod.rs

1//! Connect to Minecraft servers.
2
3#[cfg(feature = "online-mode")]
4pub mod microsoft;
5pub mod offline;
6
7use std::{fmt::Debug, ops::Deref, pin::Pin, sync::Arc};
8
9#[cfg(feature = "online-mode")]
10use azalea_auth::sessionserver::ClientSessionServerError;
11use bevy_ecs::component::Component;
12use uuid::Uuid;
13
14/// Something that can join Minecraft servers.
15///
16/// By default, Azalea only supports either authentication with Microsoft
17/// (online-mode), or no authentication at all (offline-mode). If you'd like to
18/// do authentication in some other way, consider looking at [`AccountTrait`].
19///
20/// To join a server using this account, you can either use
21/// [`StartJoinServerEvent`] or `azalea::ClientBuilder`.
22///
23/// Note that `Account` is also an ECS component that's present on our client
24/// entities.
25///
26/// # Examples
27///
28/// ```rust,no_run
29/// # use azalea_client::Account;
30/// #
31/// # #[tokio::main]
32/// # async fn main() {
33/// let account = Account::microsoft("[email protected]").await;
34/// // or Account::offline("example");
35/// # }
36/// ```
37///
38/// [`StartJoinServerEvent`]: crate::join::StartJoinServerEvent
39/// [`azalea::ClientBuilder`]: https://docs.rs/azalea/latest/azalea/struct.ClientBuilder.html
40#[derive(Clone, Component, Debug)]
41pub struct Account(Arc<dyn AccountTrait>);
42
43impl Account {
44    #[deprecated = "moved to `uuid()`."]
45    pub fn uuid_or_offline(&self) -> Uuid {
46        self.uuid()
47    }
48}
49
50pub(crate) type BoxFuture<'a, T> = Pin<Box<dyn Future<Output = T> + Send + 'a>>;
51
52/// A trait that all types of accounts implement.
53///
54/// This can be used, for example, to join servers with a custom authentication
55/// server.
56///
57/// Anything that implements [`AccountTrait`] can be converted to an [`Account`]
58/// with `.into()`.
59///
60/// Consider reading the source code of
61/// [`MicrosoftAccount`](microsoft::MicrosoftAccount) for an example of how to
62/// implement this.
63pub trait AccountTrait: Send + Sync + Debug {
64    /// Returns the Minecraft username of the account.
65    fn username(&self) -> &str;
66    /// Returns the unique identifier for this player.
67    ///
68    /// For offline-mode accounts, this UUID is generated by calling
69    /// [`azalea_crypto::offline::generate_uuid`].
70    fn uuid(&self) -> Uuid;
71
72    /// The access token for authentication.
73    ///
74    /// You can obtain one of these manually from `azalea-auth`.
75    fn access_token(&self) -> Option<String>;
76
77    /// Refreshes the access token for this account.
78    #[cfg(feature = "online-mode")]
79    fn refresh(&self) -> BoxFuture<'_, Result<(), azalea_auth::AuthError>> {
80        Box::pin(async { Ok(()) })
81    }
82    /// Refreshes the access token for this account.
83    ///
84    /// The `online-mode` feature is disabled, so this won't do anything.
85    #[cfg(not(feature = "online-mode"))]
86    fn refresh(&self) -> BoxFuture<'_, Result<(), ()>> {
87        Box::pin(async { Ok(()) })
88    }
89
90    #[cfg(feature = "online-mode")]
91    fn certs(&self) -> Option<azalea_auth::certs::Certificates> {
92        None
93    }
94    /// Override the chat signing certificates for this account.
95    ///
96    /// You can get the certificates needed for this from
97    /// [`azalea_auth::certs::fetch_certificates`]. You typically don't need to
98    /// call this yourself, as Azalea will do it for you.
99    ///
100    /// For accounts that don't support signing (i.e. offline-mode), this won't
101    /// do anything.
102    #[cfg(feature = "online-mode")]
103    fn set_certs(&self, certs: azalea_auth::certs::Certificates) {
104        let _ = certs;
105    }
106
107    /// Typically used to tell Mojang's sessionserver that we are going to join
108    /// a server.
109    ///
110    /// This must be implemented for accounts that can join online-mode servers.
111    ///
112    /// This function is called internally by Azalea when the account tries to
113    /// join a server, but only if [`AccountTrait::access_token`] is `Some`.
114    #[cfg(feature = "online-mode")]
115    fn join<'a>(
116        &'a self,
117        public_key: &'a [u8],
118        private_key: &'a [u8; 16],
119        server_id: &'a str,
120        proxy: Option<reqwest::Proxy>,
121    ) -> BoxFuture<'a, Result<(), ClientSessionServerError>> {
122        let _ = (public_key, private_key, server_id, proxy);
123        Box::pin(async { Ok(()) })
124    }
125    /// Typically used to tell Mojang's sessionserver that we are going to join
126    /// a server.
127    ///
128    /// The `online-mode` feature is disabled, so this won't do anything.
129    #[cfg(not(feature = "online-mode"))]
130    fn join(
131        &self,
132        public_key: &[u8],
133        private_key: &[u8; 16],
134        server_id: &str,
135        proxy: Option<()>,
136    ) -> BoxFuture<'_, Result<(), ()>> {
137        let _ = (public_key, private_key, server_id, proxy);
138        Box::pin(async { Ok(()) })
139    }
140}
141impl<T: AccountTrait + 'static> From<T> for Account {
142    fn from(value: T) -> Self {
143        Account(Arc::new(value))
144    }
145}
146impl Deref for Account {
147    type Target = dyn AccountTrait;
148
149    fn deref(&self) -> &Self::Target {
150        &*self.0
151    }
152}