diff --git a/azalea-client/src/account.rs b/azalea-client/src/account.rs index f63d342e..715f2fba 100644 --- a/azalea-client/src/account.rs +++ b/azalea-client/src/account.rs @@ -34,7 +34,13 @@ impl Account { /// a key for the cache, but it's recommended to use the real email to /// avoid confusion. pub async fn microsoft(email: &str) -> Result { - let minecraft_dir = get_mc_dir::minecraft_dir().unwrap(); + let minecraft_dir = get_mc_dir::minecraft_dir().expect( + format!( + "No {} environment variable found", + get_mc_dir::home_env_var() + ) + .as_str(), + ); let auth_result = azalea_auth::auth( email, azalea_auth::AuthOpts { diff --git a/azalea-client/src/get_mc_dir.rs b/azalea-client/src/get_mc_dir.rs index abc5b3c8..a8bddb1b 100644 --- a/azalea-client/src/get_mc_dir.rs +++ b/azalea-client/src/get_mc_dir.rs @@ -10,25 +10,52 @@ use std::path::PathBuf; /// Mac: `$HOME/Library/Application Support/minecraft`\ /// Linux: `$HOME/.minecraft` /// -/// Anywhere else it'll return None. +/// If the environment variable is not set, this will return `None`. pub fn minecraft_dir() -> Option { + let env_var = home_env_var(); + let home = std::env::var(env_var)?; + let path = PathBuf::from(home).join(minecraft_dir_relative()); + Some(path) +} + +/// Return the name of the environment variable that's used for the home folder +/// on the user's operating system. +pub fn home_env_var() -> &'static str { #[cfg(target_os = "windows")] { - let appdata = std::env::var("APPDATA").ok()?; - Some(PathBuf::from(appdata).join(".minecraft")) + "USERPROFILE" } #[cfg(target_os = "macos")] { - let home = std::env::var("HOME").ok()?; - Some(PathBuf::from(home).join("Library/Application Support/minecraft")) + "HOME" } #[cfg(target_os = "linux")] { - let home = std::env::var("HOME").ok()?; - Some(PathBuf::from(home).join(".minecraft")) + "HOME" } #[cfg(not(any(target_os = "windows", target_os = "macos", target_os = "linux")))] { - None + "HOME" + } +} + +/// Return the path relative to the home folder where we expect to find the +/// .minecraft directory. +pub fn minecraft_dir_relative() -> &'static str { + #[cfg(target_os = "windows")] + { + ".minecraft" + } + #[cfg(target_os = "macos")] + { + "Library/Application Support/minecraft" + } + #[cfg(target_os = "linux")] + { + ".minecraft" + } + #[cfg(not(any(target_os = "windows", target_os = "macos", target_os = "linux")))] + { + ".minecraft" } } diff --git a/azalea-protocol/src/connect.rs b/azalea-protocol/src/connect.rs index 06aedef9..c0c1a622 100644 --- a/azalea-protocol/src/connect.rs +++ b/azalea-protocol/src/connect.rs @@ -55,26 +55,24 @@ pub struct WriteConnection { /// hostname: address.host.to_string(), /// port: address.port, /// intention: ConnectionProtocol::Login, -/// } -/// .get(), -/// ) -/// .await?; -/// let mut conn = conn.login(); +/// }.get()); /// -/// // login -/// conn.write( -/// ServerboundHelloPacket { -/// username, -/// public_key: None, -/// profile_id: None, -/// } -/// .get(), -/// ) -/// .await?; +/// .await?; +/// let mut conn = conn.login(); /// -/// let (conn, game_profile) = loop { -/// let packet_result = conn.read().await; -/// match packet_result { +/// // login +/// conn.write( +/// ServerboundHelloPacket { +/// username, +/// public_key: None, +/// profile_id: None, +/// } +/// .get(), +/// ) +/// .await?; +/// +/// let (conn, game_profile) = loop { +/// let packet_result = conn.read().await?; /// Ok(packet) => match packet { /// ClientboundLoginPacket::Hello(p) => { /// let e = azalea_crypto::encrypt(&p.public_key, &p.nonce).unwrap(); @@ -87,7 +85,8 @@ pub struct WriteConnection { /// .get(), /// ) /// .await?; -/// conn.set_encryption_key(e.secret_key); } +/// conn.set_encryption_key(e.secret_key); +/// } /// ClientboundLoginPacket::LoginCompression(p) => { /// conn.set_compression_threshold(p.compression_threshold); /// } diff --git a/azalea-protocol/src/lib.rs b/azalea-protocol/src/lib.rs index ab447210..84306142 100755 --- a/azalea-protocol/src/lib.rs +++ b/azalea-protocol/src/lib.rs @@ -3,6 +3,9 @@ //! You should probably use [`azalea`] or [`azalea_client`] instead, as //! azalea_protocol delegates much of the work, such as auth, to the user of //! the crate. +//! +//! [`azalea`]: https://crates.io/crates/azalea +//! [`azalea_client`]: https://crates.io/crates/azalea-client // these two are necessary for thiserror backtraces #![feature(error_generic_member_access)]