diff --git a/Cargo.lock b/Cargo.lock index fc25b9f..c23d326 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -160,7 +160,7 @@ checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" [[package]] name = "azalea" version = "0.12.0+mc1.21.5" -source = "git+https://github.com/azalea-rs/azalea#5d799be9dbfe2fd50aa2bdf30100f4df7e114674" +source = "git+https://github.com/azalea-rs/azalea#1493c06de597fc320b79212d133f08c678763a6b" dependencies = [ "azalea-auth", "azalea-block", @@ -197,7 +197,7 @@ dependencies = [ [[package]] name = "azalea-auth" version = "0.12.0+mc1.21.5" -source = "git+https://github.com/azalea-rs/azalea#5d799be9dbfe2fd50aa2bdf30100f4df7e114674" +source = "git+https://github.com/azalea-rs/azalea#1493c06de597fc320b79212d133f08c678763a6b" dependencies = [ "azalea-buf", "azalea-crypto", @@ -217,7 +217,7 @@ dependencies = [ [[package]] name = "azalea-block" version = "0.12.0+mc1.21.5" -source = "git+https://github.com/azalea-rs/azalea#5d799be9dbfe2fd50aa2bdf30100f4df7e114674" +source = "git+https://github.com/azalea-rs/azalea#1493c06de597fc320b79212d133f08c678763a6b" dependencies = [ "azalea-block-macros", "azalea-buf", @@ -227,7 +227,7 @@ dependencies = [ [[package]] name = "azalea-block-macros" version = "0.12.0+mc1.21.5" -source = "git+https://github.com/azalea-rs/azalea#5d799be9dbfe2fd50aa2bdf30100f4df7e114674" +source = "git+https://github.com/azalea-rs/azalea#1493c06de597fc320b79212d133f08c678763a6b" dependencies = [ "proc-macro2", "quote", @@ -237,7 +237,7 @@ dependencies = [ [[package]] name = "azalea-brigadier" version = "0.12.0+mc1.21.5" -source = "git+https://github.com/azalea-rs/azalea#5d799be9dbfe2fd50aa2bdf30100f4df7e114674" +source = "git+https://github.com/azalea-rs/azalea#1493c06de597fc320b79212d133f08c678763a6b" dependencies = [ "azalea-buf", "azalea-chat", @@ -247,7 +247,7 @@ dependencies = [ [[package]] name = "azalea-buf" version = "0.12.0+mc1.21.5" -source = "git+https://github.com/azalea-rs/azalea#5d799be9dbfe2fd50aa2bdf30100f4df7e114674" +source = "git+https://github.com/azalea-rs/azalea#1493c06de597fc320b79212d133f08c678763a6b" dependencies = [ "azalea-buf-macros", "byteorder", @@ -261,7 +261,7 @@ dependencies = [ [[package]] name = "azalea-buf-macros" version = "0.12.0+mc1.21.5" -source = "git+https://github.com/azalea-rs/azalea#5d799be9dbfe2fd50aa2bdf30100f4df7e114674" +source = "git+https://github.com/azalea-rs/azalea#1493c06de597fc320b79212d133f08c678763a6b" dependencies = [ "proc-macro2", "quote", @@ -271,7 +271,7 @@ dependencies = [ [[package]] name = "azalea-chat" version = "0.12.0+mc1.21.5" -source = "git+https://github.com/azalea-rs/azalea#5d799be9dbfe2fd50aa2bdf30100f4df7e114674" +source = "git+https://github.com/azalea-rs/azalea#1493c06de597fc320b79212d133f08c678763a6b" dependencies = [ "azalea-buf", "azalea-language", @@ -285,7 +285,7 @@ dependencies = [ [[package]] name = "azalea-client" version = "0.12.0+mc1.21.5" -source = "git+https://github.com/azalea-rs/azalea#5d799be9dbfe2fd50aa2bdf30100f4df7e114674" +source = "git+https://github.com/azalea-rs/azalea#1493c06de597fc320b79212d133f08c678763a6b" dependencies = [ "async-compat", "azalea-auth", @@ -321,7 +321,7 @@ dependencies = [ [[package]] name = "azalea-core" version = "0.12.0+mc1.21.5" -source = "git+https://github.com/azalea-rs/azalea#5d799be9dbfe2fd50aa2bdf30100f4df7e114674" +source = "git+https://github.com/azalea-rs/azalea#1493c06de597fc320b79212d133f08c678763a6b" dependencies = [ "azalea-buf", "azalea-chat", @@ -338,7 +338,7 @@ dependencies = [ [[package]] name = "azalea-crypto" version = "0.12.0+mc1.21.5" -source = "git+https://github.com/azalea-rs/azalea#5d799be9dbfe2fd50aa2bdf30100f4df7e114674" +source = "git+https://github.com/azalea-rs/azalea#1493c06de597fc320b79212d133f08c678763a6b" dependencies = [ "aes", "azalea-buf", @@ -355,7 +355,7 @@ dependencies = [ [[package]] name = "azalea-entity" version = "0.12.0+mc1.21.5" -source = "git+https://github.com/azalea-rs/azalea#5d799be9dbfe2fd50aa2bdf30100f4df7e114674" +source = "git+https://github.com/azalea-rs/azalea#1493c06de597fc320b79212d133f08c678763a6b" dependencies = [ "azalea-block", "azalea-buf", @@ -379,7 +379,7 @@ dependencies = [ [[package]] name = "azalea-inventory" version = "0.12.0+mc1.21.5" -source = "git+https://github.com/azalea-rs/azalea#5d799be9dbfe2fd50aa2bdf30100f4df7e114674" +source = "git+https://github.com/azalea-rs/azalea#1493c06de597fc320b79212d133f08c678763a6b" dependencies = [ "azalea-buf", "azalea-chat", @@ -395,7 +395,7 @@ dependencies = [ [[package]] name = "azalea-inventory-macros" version = "0.12.0+mc1.21.5" -source = "git+https://github.com/azalea-rs/azalea#5d799be9dbfe2fd50aa2bdf30100f4df7e114674" +source = "git+https://github.com/azalea-rs/azalea#1493c06de597fc320b79212d133f08c678763a6b" dependencies = [ "proc-macro2", "quote", @@ -405,7 +405,7 @@ dependencies = [ [[package]] name = "azalea-language" version = "0.12.0+mc1.21.5" -source = "git+https://github.com/azalea-rs/azalea#5d799be9dbfe2fd50aa2bdf30100f4df7e114674" +source = "git+https://github.com/azalea-rs/azalea#1493c06de597fc320b79212d133f08c678763a6b" dependencies = [ "compact_str", "serde", @@ -415,7 +415,7 @@ dependencies = [ [[package]] name = "azalea-physics" version = "0.12.0+mc1.21.5" -source = "git+https://github.com/azalea-rs/azalea#5d799be9dbfe2fd50aa2bdf30100f4df7e114674" +source = "git+https://github.com/azalea-rs/azalea#1493c06de597fc320b79212d133f08c678763a6b" dependencies = [ "azalea-block", "azalea-core", @@ -432,7 +432,7 @@ dependencies = [ [[package]] name = "azalea-protocol" version = "0.12.0+mc1.21.5" -source = "git+https://github.com/azalea-rs/azalea#5d799be9dbfe2fd50aa2bdf30100f4df7e114674" +source = "git+https://github.com/azalea-rs/azalea#1493c06de597fc320b79212d133f08c678763a6b" dependencies = [ "async-recursion", "azalea-auth", @@ -467,7 +467,7 @@ dependencies = [ [[package]] name = "azalea-protocol-macros" version = "0.12.0+mc1.21.5" -source = "git+https://github.com/azalea-rs/azalea#5d799be9dbfe2fd50aa2bdf30100f4df7e114674" +source = "git+https://github.com/azalea-rs/azalea#1493c06de597fc320b79212d133f08c678763a6b" dependencies = [ "proc-macro2", "quote", @@ -477,7 +477,7 @@ dependencies = [ [[package]] name = "azalea-registry" version = "0.12.0+mc1.21.5" -source = "git+https://github.com/azalea-rs/azalea#5d799be9dbfe2fd50aa2bdf30100f4df7e114674" +source = "git+https://github.com/azalea-rs/azalea#1493c06de597fc320b79212d133f08c678763a6b" dependencies = [ "azalea-buf", "azalea-registry-macros", @@ -488,7 +488,7 @@ dependencies = [ [[package]] name = "azalea-registry-macros" version = "0.12.0+mc1.21.5" -source = "git+https://github.com/azalea-rs/azalea#5d799be9dbfe2fd50aa2bdf30100f4df7e114674" +source = "git+https://github.com/azalea-rs/azalea#1493c06de597fc320b79212d133f08c678763a6b" dependencies = [ "quote", "syn", @@ -515,7 +515,7 @@ dependencies = [ [[package]] name = "azalea-world" version = "0.12.0+mc1.21.5" -source = "git+https://github.com/azalea-rs/azalea#5d799be9dbfe2fd50aa2bdf30100f4df7e114674" +source = "git+https://github.com/azalea-rs/azalea#1493c06de597fc320b79212d133f08c678763a6b" dependencies = [ "azalea-block", "azalea-buf", diff --git a/examples/cli.rs b/examples/cli.rs index a2c8a45..e0de279 100644 --- a/examples/cli.rs +++ b/examples/cli.rs @@ -1,7 +1,10 @@ -//! A swarm bot that allows you to modify the accounts being used and the target version and the server address from the CLI. +//! A swarm bot that allows you to modify the accounts being used and the target +//! version and the server address from the CLI. //! //! Example usage: +//! ```sh //! cargo r -r --example cli -- --account bot --server localhost --version 1.21.5 +//! ``` use std::{env, process, time::Duration}; diff --git a/examples/client.rs b/examples/client.rs index 7977771..791baea 100644 --- a/examples/client.rs +++ b/examples/client.rs @@ -1,7 +1,9 @@ -//! A super basic example of adding a `ViaVersionPlugin` to a `ClientBuilder` and connecting to a localhost server. +//! A super basic example of adding a `ViaVersionPlugin` to a `ClientBuilder` +//! and connecting to a localhost server. //! //! # Note -//! The `never_type` feature is completely optional, see how the `swarm` example does not use it. +//! The `never_type` feature is completely optional, see how the `swarm` example +//! does not use it. #![feature(never_type)] use azalea::{StartError, prelude::*}; diff --git a/examples/echo.rs b/examples/echo.rs index c9f4e9f..e5a3707 100644 --- a/examples/echo.rs +++ b/examples/echo.rs @@ -1,7 +1,8 @@ //! An [`azalea`] bot that repeats chat messages sent by other players. //! //! # Note -//! The `never_type` feature is completely optional, see how the `swarm` example does not use it. +//! The `never_type` feature is completely optional, see how the `swarm` example +//! does not use it. #![feature(never_type)] use azalea::{NoState, StartError, prelude::*}; diff --git a/examples/swarm.rs b/examples/swarm.rs index ea07b7e..505c21f 100644 --- a/examples/swarm.rs +++ b/examples/swarm.rs @@ -1,4 +1,5 @@ -//! A super basic example of adding a `ViaVersionPlugin` to a `SwarmBuilder` and connecting to a localhost server. +//! A super basic example of adding a `ViaVersionPlugin` to a `SwarmBuilder` and +//! connecting to a localhost server. use azalea::{prelude::*, swarm::SwarmBuilder}; use azalea_viaversion::ViaVersionPlugin; diff --git a/rustfmt.toml b/rustfmt.toml new file mode 100644 index 0000000..35672d0 --- /dev/null +++ b/rustfmt.toml @@ -0,0 +1,2 @@ +wrap_comments = true +group_imports = "StdExternalCrate" diff --git a/src/lib.rs b/src/lib.rs index b3a3b79..172caa6 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,17 +1,19 @@ +use std::{io::Cursor, net::SocketAddr, path::Path, process::Stdio}; + use anyhow::{Context, Result}; -use azalea::app::Update; -use azalea::bevy_tasks::{IoTaskPool, Task, futures_lite::future}; -use azalea::packet::login::{ReceiveCustomQueryEvent, SendLoginPacketEvent}; use azalea::{ - app::{App, Plugin, Startup}, + app::{App, Plugin, Startup, prelude::*}, auth::sessionserver::{ ClientSessionServerError::{ForbiddenOperation, InvalidSession}, join_with_server_id_hash, }, + bevy_tasks::{IoTaskPool, Task, futures_lite::future}, buf::AzaleaRead, ecs::prelude::*, + join::StartJoinServerEvent, + packet::login::{ReceiveCustomQueryEvent, SendLoginPacketEvent}, prelude::*, - protocol::{ServerAddress, packets::login::ServerboundCustomQueryAnswer}, + protocol::{ServerAddress, connect::Proxy, packets::login::ServerboundCustomQueryAnswer}, swarm::Swarm, }; use futures_util::StreamExt; @@ -19,7 +21,6 @@ use kdam::{BarExt, tqdm}; use lazy_regex::regex_captures; use reqwest::IntoUrl; use semver::Version; -use std::{io::Cursor, net::SocketAddr, path::Path, process::Stdio}; use tokio::{ fs::File, io::{AsyncBufReadExt, AsyncWriteExt, BufReader}, @@ -36,6 +37,7 @@ const VIA_PROXY_VERSION: Version = Version::new(3, 4, 1); pub struct ViaVersionPlugin { bind_addr: SocketAddr, mc_version: String, + proxy: Option, } impl Plugin for ViaVersionPlugin { @@ -47,6 +49,7 @@ impl Plugin for ViaVersionPlugin { ( Self::handle_oauth.before(azalea::login::reply_to_custom_queries), Self::poll_all_oam_join_tasks, + Self::warn_about_proxy.after(azalea::auto_reconnect::rejoin_after_delay), ), ); } @@ -56,15 +59,67 @@ impl ViaVersionPlugin { /// Download and start a ViaProxy instance. /// /// # Panics - /// Will panic if java fails to parse, files fail to download, or ViaProxy fails to start. + /// + /// Will panic if Java fails to parse, files fail to download, or ViaProxy + /// fails to start. pub async fn start(mc_version: impl ToString) -> Self { + let bind_addr = try_find_free_addr().await.expect("Failed to bind"); + let mc_version = mc_version.to_string(); + + let plugin = Self { + bind_addr, + mc_version, + proxy: None, + }; + plugin.start_with_self().await + } + + /// Same as [`Self::start`], but allows you to pass a Socks5 proxy. + /// + /// This is necessary if you want to use Azalea with a proxy and ViaVersion + /// at the same time. This is incompatible with `JoinOpts::proxy`. + /// + /// ```no_run + /// # use azalea::{prelude::*, protocol::connect::Proxy}; + /// # use azalea_viaversion::ViaVersionPlugin;; + /// #[tokio::main] + /// async fn main() { + /// let account = Account::offline("bot"); + /// + /// ClientBuilder::new() + /// .set_handler(handle) + /// .add_plugins( + /// ViaVersionPlugin::start_with_proxy( + /// "1.21.5", + /// Proxy::new("10.124.1.186:1080".parse().unwrap(), None), + /// ) + /// .await, + /// ) + /// .start(account, "6.tcp.ngrok.io:14910") + /// .await + /// .unwrap(); + /// } + /// # async fn handle(mut bot: Client, event: Event, state: azalea::NoState) { } + /// ``` + pub async fn start_with_proxy(mc_version: impl ToString, proxy: Proxy) -> Self { + let bind_addr = try_find_free_addr().await.expect("Failed to bind"); + let mc_version = mc_version.to_string(); + + let plugin = Self { + bind_addr, + mc_version, + proxy: Some(proxy), + }; + plugin.start_with_self().await + } + + async fn start_with_self(self) -> Self { let Some(java_version) = try_find_java_version().await.expect("Failed to parse") else { panic!( "Java installation not found! Please download Java from {JAVA_DOWNLOAD_URL} or use your system's package manager." ); }; - let mc_version = mc_version.to_string(); let mc_path = minecraft_folder_path::minecraft_dir().expect("Unsupported Platform"); #[rustfmt::skip] @@ -87,17 +142,24 @@ impl ViaVersionPlugin { .await .expect("Failed to download ViaProxyOpenAuthMod"); - let bind_addr = try_find_free_addr().await.expect("Failed to bind"); - let mut child = Command::new("java") + let mut command = Command::new("java"); + command /* Java Args */ .args(["-jar", &via_proxy_name]) /* ViaProxy Args */ .arg("cli") .args(["--auth-method", "OPENAUTHMOD"]) - .args(["--bind-address", &bind_addr.to_string()]) + .args(["--bind-address", &self.bind_addr.to_string()]) .args(["--target-address", "127.0.0.1:0"]) - .args(["--target-version", &mc_version]) - .args(["--wildcard-domain-handling", "INTERNAL"]) + .args(["--target-version", &self.mc_version]) + .args(["--wildcard-domain-handling", "INTERNAL"]); + + if let Some(proxy) = &self.proxy { + trace!("Starting ViaProxy with proxy: {proxy}"); + command.args(["--backend-proxy-url", &proxy.to_string()]); + } + + let mut child = command .current_dir(via_proxy_path) .stdout(Stdio::piped()) .spawn() @@ -123,18 +185,15 @@ impl ViaVersionPlugin { /* Wait until ViaProxy is ready */ let _ = rx.changed().await; - Self { - bind_addr, - mc_version, - } + self } #[allow(clippy::needless_pass_by_value)] pub fn handle_change_address(plugin: Res, swarm: Res) { let ServerAddress { host, port } = swarm.address.read().clone(); - // sadly, the first part of the resolved address is unused as viaproxy will resolve it on its own - // more info: https://github.com/ViaVersion/ViaProxy/issues/338 + // sadly, the first part of the resolved address is unused as viaproxy will + // resolve it on its own more info: https://github.com/ViaVersion/ViaProxy/issues/338 let data_after_null_byte = host.split_once('\x07').map(|(_, data)| data); let mut connection_host = format!( @@ -175,7 +234,8 @@ impl ViaVersionPlugin { continue; }; - // this makes it so azalea doesn't reply to the query so we can handle it ourselves + // this makes it so azalea doesn't reply to the query so we can handle it + // ourselves event.disabled = true; let Some(access_token) = &account.access_token else { @@ -242,6 +302,17 @@ impl ViaVersionPlugin { commands.trigger(SendLoginPacketEvent::new(entity, packet)) } } + + fn warn_about_proxy(mut events: EventReader) { + for event in events.read() { + if event.connect_opts.proxy.is_some() { + warn!( + "You are using JoinOpts::proxy and ViaVersionPlugin at the same time, which is not a supported configuration. \ + Please set your proxy with `ViaVersionPlugin::start_with_proxy` instead." + ); + } + } + } } #[derive(Component)]