From 751098b636c9aee54b9ca7a465fdaa769f10be4d Mon Sep 17 00:00:00 2001 From: mat Date: Mon, 18 Apr 2022 22:38:53 -0500 Subject: [PATCH 1/4] start working on declare commands packet --- Cargo.lock | 1 + README.md | 6 +- azalea-client/src/connect.rs | 3 + azalea-protocol/Cargo.toml | 1 + azalea-protocol/src/mc_buf/read.rs | 1 - .../clientbound_declare_commands_packet.rs | 119 +++++++++++++----- azalea-protocol/src/packets/game/mod.rs | 9 ++ 7 files changed, 106 insertions(+), 34 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 67259fef..8d94c26c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -117,6 +117,7 @@ dependencies = [ "async-recursion", "async-trait", "azalea-auth", + "azalea-brigadier", "azalea-chat", "azalea-core", "azalea-nbt", diff --git a/README.md b/README.md index 3ae4b307..ed6ed46f 100644 --- a/README.md +++ b/README.md @@ -6,8 +6,8 @@ I named this Azalea because it sounds like a cool word and this is a cool librar ## Goals -- Bypass most anticheats -- Only support the latest Minecraft version - Do everything a vanilla client can do -- Be fast - Be easy to use +- Bypass most/all anticheats +- Support the latest Minecraft version +- Be fast diff --git a/azalea-client/src/connect.rs b/azalea-client/src/connect.rs index 7b1da525..bc45a121 100644 --- a/azalea-client/src/connect.rs +++ b/azalea-client/src/connect.rs @@ -73,6 +73,9 @@ pub async fn join_server(address: &ServerAddress) -> Result<(), String> { GamePacket::ClientboundChangeDifficultyPacket(p) => { println!("Got difficulty packet {:?}", p); } + GamePacket::ClientboundDeclareCommandsPacket(p) => { + println!("Got declare commands packet {:?}", p); + } }, Err(e) => { println!("Error: {:?}", e); diff --git a/azalea-protocol/Cargo.toml b/azalea-protocol/Cargo.toml index ff3bd9d4..37df8697 100644 --- a/azalea-protocol/Cargo.toml +++ b/azalea-protocol/Cargo.toml @@ -10,6 +10,7 @@ async-compression = {version = "^0.3.8", features = ["tokio", "zlib"]} async-recursion = "^0.3.2" async-trait = "0.1.51" azalea-auth = {path = "../azalea-auth"} +azalea-brigadier = {path = "../azalea-brigadier"} azalea-chat = {path = "../azalea-chat"} azalea-core = {path = "../azalea-core"} azalea-nbt = {path = "../azalea-nbt"} diff --git a/azalea-protocol/src/mc_buf/read.rs b/azalea-protocol/src/mc_buf/read.rs index 0fa1d099..20b69238 100644 --- a/azalea-protocol/src/mc_buf/read.rs +++ b/azalea-protocol/src/mc_buf/read.rs @@ -2,7 +2,6 @@ use async_trait::async_trait; use azalea_core::{ difficulty::Difficulty, game_type::GameType, resource_location::ResourceLocation, }; -use num_traits::FromPrimitive; use tokio::io::{AsyncRead, AsyncReadExt}; use super::MAX_STRING_LENGTH; diff --git a/azalea-protocol/src/packets/game/clientbound_declare_commands_packet.rs b/azalea-protocol/src/packets/game/clientbound_declare_commands_packet.rs index 1bcf0dd4..1403630d 100644 --- a/azalea-protocol/src/packets/game/clientbound_declare_commands_packet.rs +++ b/azalea-protocol/src/packets/game/clientbound_declare_commands_packet.rs @@ -1,37 +1,96 @@ -// use std::hash::Hash; +use std::hash::Hash; -// use crate::mc_buf::Readable; +use async_trait::async_trait; +use tokio::io::AsyncRead; -// use super::LoginPacket; +use crate::mc_buf::{McBufReadable, Readable}; -// #[derive(Hash, Clone, Debug)] -// pub struct ClientboundDeclareCommandsPacket { -// pub root: RootCommandNode, -// pub public_key: Vec, -// pub nonce: Vec, -// } +use super::GamePacket; -// impl ClientboundHelloPacket { -// pub fn get(self) -> LoginPacket { -// LoginPacket::ClientboundHelloPacket(self) -// } +#[derive(Hash, Clone, Debug)] +pub struct ClientboundDeclareCommandsPacket { + pub entries: Vec, + pub root_index: i32, +} -// pub fn write(&self, _buf: &mut Vec) -> Result<(), std::io::Error> { -// panic!("ClientboundHelloPacket::write not implemented") -// } +impl ClientboundDeclareCommandsPacket { + pub fn get(self) -> GamePacket { + GamePacket::ClientboundDeclareCommandsPacket(self) + } -// pub async fn read( -// buf: &mut T, -// ) -> Result { -// let server_id = buf.read_utf_with_len(20).await?; -// let public_key = buf.read_byte_array().await?; -// let nonce = buf.read_byte_array().await?; + pub fn write(&self, _buf: &mut Vec) -> Result<(), std::io::Error> { + panic!("ClientboundDeclareCommandsPacket::write not implemented") + } -// Ok(ClientboundHelloPacket { -// server_id, -// public_key, -// nonce, -// } -// .get()) -// } -// } + pub async fn read( + buf: &mut T, + ) -> Result { + let node_count = buf.read_varint().await?; + println!("node_count: {}", node_count); + let mut nodes = Vec::with_capacity(node_count as usize); + for _ in 0..node_count { + let node = BrigadierNodeStub::read_into(buf).await?; + nodes.push(node); + } + let root_index = buf.read_varint().await?; + Ok(GamePacket::ClientboundDeclareCommandsPacket( + ClientboundDeclareCommandsPacket { + entries: nodes, + root_index, + }, + )) + } +} + +#[derive(Hash, Debug, Clone)] +pub struct BrigadierNodeStub {} + +// azalea_brigadier::tree::CommandNode +#[async_trait] +impl McBufReadable for BrigadierNodeStub { + async fn read_into(buf: &mut R) -> Result + where + R: AsyncRead + std::marker::Unpin + std::marker::Send, + { + let flags = u8::read_into(buf).await?; + + let node_type = flags & 0x03; + let is_executable = flags & 0x04 != 0; + let has_redirect = flags & 0x08 != 0; + let has_suggestions_type = flags & 0x10 != 0; + println!("flags: {}, node_type: {}, is_executable: {}, has_redirect: {}, has_suggestions_type: {}", flags, node_type, is_executable, has_redirect, has_suggestions_type); + + let children = buf.read_int_id_list().await?; + println!("children: {:?}", children); + let redirect_node = if has_redirect { + buf.read_varint().await? + } else { + 0 + }; + println!("redirect_node: {}", redirect_node); + + if node_type == 2 { + let name = buf.read_utf().await?; + println!("name: {}", name); + + let resource_location = if has_suggestions_type { + Some(buf.read_resource_location().await?) + } else { + None + }; + println!( + "node_type=2, flags={}, name={}, resource_location={:?}", + flags, name, resource_location + ); + return Ok(BrigadierNodeStub {}); + } + if node_type == 1 { + let name = buf.read_utf().await?; + println!("node_type=1, flags={}, name={}", flags, name); + return Ok(BrigadierNodeStub {}); + } + println!("node_type={}, flags={}", node_type, flags); + Ok(BrigadierNodeStub {}) + // return Err("Unknown node type".to_string()); + } +} diff --git a/azalea-protocol/src/packets/game/mod.rs b/azalea-protocol/src/packets/game/mod.rs index 4efe72fb..1fd47132 100644 --- a/azalea-protocol/src/packets/game/mod.rs +++ b/azalea-protocol/src/packets/game/mod.rs @@ -1,5 +1,6 @@ pub mod clientbound_change_difficulty_packet; pub mod clientbound_custom_payload_packet; +pub mod clientbound_declare_commands_packet; pub mod clientbound_login_packet; pub mod clientbound_update_view_distance_packet; @@ -22,6 +23,9 @@ where ClientboundChangeDifficultyPacket( clientbound_change_difficulty_packet::ClientboundChangeDifficultyPacket, ), + ClientboundDeclareCommandsPacket( + clientbound_declare_commands_packet::ClientboundDeclareCommandsPacket, + ), } #[async_trait] @@ -32,6 +36,7 @@ impl ProtocolPacket for GamePacket { GamePacket::ClientboundCustomPayloadPacket(_packet) => 0x18, GamePacket::ClientboundLoginPacket(_packet) => 0x26, GamePacket::ClientboundUpdateViewDistancePacket(_packet) => 0x4a, + GamePacket::ClientboundDeclareCommandsPacket(_packet) => 0x12, } } @@ -41,6 +46,7 @@ impl ProtocolPacket for GamePacket { GamePacket::ClientboundCustomPayloadPacket(packet) => packet.write(buf), GamePacket::ClientboundLoginPacket(packet) => packet.write(buf), GamePacket::ClientboundUpdateViewDistancePacket(packet) => packet.write(buf), + GamePacket::ClientboundDeclareCommandsPacket(packet) => packet.write(buf), } } @@ -63,6 +69,9 @@ impl ProtocolPacket for GamePacket { 0x4a => clientbound_update_view_distance_packet::ClientboundUpdateViewDistancePacket ::read(buf) .await?, + 0x12 => clientbound_declare_commands_packet::ClientboundDeclareCommandsPacket + ::read(buf) + .await?, // _ => return Err(format!("Unknown ServerToClient game packet id: {}", id)), _ => panic!("Unknown ServerToClient game packet id: {}", id), }, From a45eb6deb27b8623c3d3ba9b5e21cc638272f5c8 Mon Sep 17 00:00:00 2001 From: mat Date: Tue, 19 Apr 2022 20:37:42 -0500 Subject: [PATCH 2/4] allow trailing commas in declare_state_packets --- azalea-protocol/packet-macros/src/lib.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/azalea-protocol/packet-macros/src/lib.rs b/azalea-protocol/packet-macros/src/lib.rs index 3cc3677a..d7f54d84 100644 --- a/azalea-protocol/packet-macros/src/lib.rs +++ b/azalea-protocol/packet-macros/src/lib.rs @@ -150,13 +150,16 @@ impl Parse for PacketIdMap { input.parse::()?; // ClientboundChangeDifficultyPacket let name: Ident = input.parse()?; - input.parse::()?; packets.push(PacketIdPair { id: packet_id, module, name, }); + + if input.parse::().is_err() { + break; + } } Ok(PacketIdMap { packets }) From a3fad4765b7ef2077fde0b5c87a5cf657f9f6584 Mon Sep 17 00:00:00 2001 From: mat Date: Tue, 19 Apr 2022 21:03:10 -0500 Subject: [PATCH 3/4] reorder some packets --- azalea-protocol/src/packets/game/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/azalea-protocol/src/packets/game/mod.rs b/azalea-protocol/src/packets/game/mod.rs index 904b38c8..2dbf7f24 100644 --- a/azalea-protocol/src/packets/game/mod.rs +++ b/azalea-protocol/src/packets/game/mod.rs @@ -11,9 +11,9 @@ declare_state_packets!( Serverbound => {}, Clientbound => { 0x0e: clientbound_change_difficulty_packet::ClientboundChangeDifficultyPacket, + 0x12: clientbound_declare_commands_packet::ClientboundDeclareCommandsPacket, 0x18: clientbound_custom_payload_packet::ClientboundCustomPayloadPacket, 0x26: clientbound_login_packet::ClientboundLoginPacket, - 0x4a: clientbound_update_view_distance_packet::ClientboundUpdateViewDistancePacket, - 0x12: clientbound_declare_commands_packet::ClientboundDeclareCommandsPacket + 0x4a: clientbound_update_view_distance_packet::ClientboundUpdateViewDistancePacket } ); From cafa4dd76fecc9e331f35145e10539e1f5ac85f6 Mon Sep 17 00:00:00 2001 From: mat Date: Tue, 19 Apr 2022 21:24:42 -0500 Subject: [PATCH 4/4] Fix declare_state_packets --- azalea-client/src/ping.rs | 2 +- azalea-protocol/packet-macros/src/lib.rs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/azalea-client/src/ping.rs b/azalea-client/src/ping.rs index 87ccdf66..8ecff7ca 100644 --- a/azalea-client/src/ping.rs +++ b/azalea-client/src/ping.rs @@ -38,7 +38,7 @@ pub async fn ping_server( let packet = conn.read().await.unwrap(); match packet { - StatusPacket::ClientboundStatusResponsePacket(p) => Ok(*p), + StatusPacket::ClientboundStatusResponsePacket(p) => Ok(p), _ => Err("Invalid packet type".to_string()), } } diff --git a/azalea-protocol/packet-macros/src/lib.rs b/azalea-protocol/packet-macros/src/lib.rs index d7f54d84..bdb83871 100644 --- a/azalea-protocol/packet-macros/src/lib.rs +++ b/azalea-protocol/packet-macros/src/lib.rs @@ -286,11 +286,11 @@ pub fn declare_state_packets(input: TokenStream) -> TokenStream { { Ok(match flow { crate::connect::PacketFlow::ServerToClient => match id { - #serverbound_read_match_contents + #clientbound_read_match_contents _ => panic!("Unknown ServerToClient {} packet id: {}", #state_name_litstr, id), }, crate::connect::PacketFlow::ClientToServer => match id { - #clientbound_read_match_contents + #serverbound_read_match_contents _ => return Err(format!("Unknown ClientToServer {} packet id: {}", #state_name_litstr, id)), }, })