From 39f4d68e1ff1f0fa0d45663335d83299d5d37790 Mon Sep 17 00:00:00 2001 From: mat Date: Thu, 5 Dec 2024 06:30:47 +0000 Subject: [PATCH] fix container_set_content, player_position, and recipe_book_remove packets --- Cargo.toml | 2 - azalea-client/src/movement.rs | 4 +- azalea-client/src/packet_handling/game.rs | 105 +++++++++--------- azalea-core/src/math.rs | 9 ++ azalea-core/src/position.rs | 18 +++ azalea-entity/src/lib.rs | 3 +- azalea-inventory/src/slot.rs | 6 +- .../packets/game/c_container_set_content.rs | 26 +++++ .../src/packets/game/c_player_position.rs | 53 ++++++--- .../src/packets/game/c_recipe_book_remove.rs | 6 +- .../src/packets/game/s_move_player_pos_rot.rs | 5 +- 11 files changed, 149 insertions(+), 88 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index d163c1069..7ea37cf5e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -50,7 +50,6 @@ env_logger = "0.11.5" flate2 = "1.0.35" futures = "0.3.31" futures-lite = "2.5.0" -#futures-util = "0.3.31" log = "0.4.22" md-5 = "0.10.6" minecraft_folder_path = "0.1.2" @@ -72,7 +71,6 @@ serde_json = "1.0.133" sha-1 = "0.10.1" sha2 = "0.10.8" simdnbt = "0.6" -#smallvec = "1.13.2" socks5-impl = "0.5.17" syn = "2.0.90" thiserror = "2.0.3" diff --git a/azalea-client/src/movement.rs b/azalea-client/src/movement.rs index 3304e27d8..03183e244 100644 --- a/azalea-client/src/movement.rs +++ b/azalea-client/src/movement.rs @@ -192,9 +192,7 @@ pub fn send_position( let packet = if sending_position && sending_direction { Some( ServerboundMovePlayerPosRot { - x: position.x, - y: position.y, - z: position.z, + pos: **position, x_rot: direction.x_rot, y_rot: direction.y_rot, on_ground: physics.on_ground, diff --git a/azalea-client/src/packet_handling/game.rs b/azalea-client/src/packet_handling/game.rs index e9be45c74..d4d84f758 100644 --- a/azalea-client/src/packet_handling/game.rs +++ b/azalea-client/src/packet_handling/game.rs @@ -1,12 +1,14 @@ use std::{ collections::HashSet, io::Cursor, + ops::Add, sync::{Arc, Weak}, }; use azalea_chat::FormattedText; use azalea_core::{ game_type::GameMode, + math, position::{ChunkPos, Vec3}, resource_location::ResourceLocation, }; @@ -435,64 +437,63 @@ pub fn process_packet_events(ecs: &mut World) { continue; }; - let delta_movement = physics.velocity; + **last_sent_position = **position; - let is_x_relative = p.relative_arguments.x; - let is_y_relative = p.relative_arguments.y; - let is_z_relative = p.relative_arguments.z; + fn apply_change>(base: T, condition: bool, change: T) -> T { + if condition { + base + change + } else { + change + } + } - let (delta_x, new_pos_x) = if is_x_relative { - last_sent_position.x += p.pos.x; - (delta_movement.x, position.x + p.pos.x) - } else { - last_sent_position.x = p.pos.x; - (0.0, p.pos.x) - }; - let (delta_y, new_pos_y) = if is_y_relative { - last_sent_position.y += p.pos.y; - (delta_movement.y, position.y + p.pos.y) - } else { - last_sent_position.y = p.pos.y; - (0.0, p.pos.y) - }; - let (delta_z, new_pos_z) = if is_z_relative { - last_sent_position.z += p.pos.z; - (delta_movement.z, position.z + p.pos.z) - } else { - last_sent_position.z = p.pos.z; - (0.0, p.pos.z) - }; + let new_x = apply_change(position.x, p.relative.x, p.change.pos.x); + let new_y = apply_change(position.y, p.relative.y, p.change.pos.y); + let new_z = apply_change(position.z, p.relative.z, p.change.pos.z); - let mut y_rot = p.y_rot; - let mut x_rot = p.x_rot; - if p.relative_arguments.x_rot { - x_rot += direction.x_rot; - } - if p.relative_arguments.y_rot { - y_rot += direction.y_rot; + let new_y_rot = apply_change(direction.y_rot, p.relative.y_rot, p.change.y_rot); + let new_x_rot = apply_change(direction.x_rot, p.relative.x_rot, p.change.x_rot); + + let mut new_delta_from_rotations = physics.velocity; + if p.relative.rotate_delta { + let y_rot_delta = direction.y_rot - new_y_rot; + let x_rot_delta = direction.x_rot - new_x_rot; + new_delta_from_rotations = new_delta_from_rotations + .x_rot(math::to_radians(x_rot_delta as f64) as f32) + .y_rot(math::to_radians(y_rot_delta as f64) as f32); } - physics.velocity = Vec3 { - x: delta_x, - y: delta_y, - z: delta_z, - }; - // we call a function instead of setting the fields ourself since the - // function makes sure the rotations stay in their - // ranges - (direction.y_rot, direction.x_rot) = (y_rot, x_rot); - // TODO: minecraft sets "xo", "yo", and "zo" here but idk what that means - // so investigate that ig - let new_pos = Vec3 { - x: new_pos_x, - y: new_pos_y, - z: new_pos_z, - }; + let new_delta = Vec3::new( + apply_change( + new_delta_from_rotations.x, + p.relative.delta_x, + p.change.delta.x, + ), + apply_change( + new_delta_from_rotations.y, + p.relative.delta_y, + p.change.delta.y, + ), + apply_change( + new_delta_from_rotations.z, + p.relative.delta_z, + p.change.delta.z, + ), + ); + // apply the updates + + physics.velocity = new_delta; + + (direction.y_rot, direction.x_rot) = (new_y_rot, new_x_rot); + + let new_pos = Vec3::new(new_x, new_y, new_z); if new_pos != **position { **position = new_pos; } + // send the relevant packets + send_packet_events.send(SendPacketEvent::new( player_entity, ServerboundAcceptTeleportation { id: p.id }, @@ -500,11 +501,9 @@ pub fn process_packet_events(ecs: &mut World) { send_packet_events.send(SendPacketEvent::new( player_entity, ServerboundMovePlayerPosRot { - x: new_pos.x, - y: new_pos.y, - z: new_pos.z, - y_rot, - x_rot, + pos: new_pos, + y_rot: new_y_rot, + x_rot: new_x_rot, // this is always false on_ground: false, }, diff --git a/azalea-core/src/math.rs b/azalea-core/src/math.rs index 7c0ac7b42..622157494 100644 --- a/azalea-core/src/math.rs +++ b/azalea-core/src/math.rs @@ -68,6 +68,15 @@ pub fn fract(x: f64) -> f64 { x - floor } +// these are copied from the java standard library, we don't calculate the +// consts ourself to make sure it's the same as java +pub fn to_radians(degrees: f64) -> f64 { + degrees * 0.017453292519943295 +} +pub fn to_degrees(radians: f64) -> f64 { + radians * 57.29577951308232 +} + #[cfg(test)] mod tests { use super::*; diff --git a/azalea-core/src/position.rs b/azalea-core/src/position.rs index 5948203fa..9b800e288 100755 --- a/azalea-core/src/position.rs +++ b/azalea-core/src/position.rs @@ -13,6 +13,7 @@ use std::{ use azalea_buf::{AzBuf, AzaleaRead, AzaleaWrite, BufReadError}; +use crate::math; use crate::resource_location::ResourceLocation; macro_rules! vec3_impl { @@ -233,6 +234,23 @@ impl Vec3 { pub fn distance_to(&self, other: &Self) -> f64 { (self - other).length() } + + pub fn x_rot(self, radians: f32) -> Vec3 { + let x_delta = math::cos(radians); + let y_delta = math::sin(radians); + let x = self.x; + let y = self.y * (x_delta as f64) + self.z * (y_delta as f64); + let z = self.z * (x_delta as f64) - self.y * (y_delta as f64); + Vec3 { x, y, z } + } + pub fn y_rot(self, radians: f32) -> Vec3 { + let x_delta = math::cos(radians); + let y_delta = math::sin(radians); + let x = self.x * (x_delta as f64) + self.z * (y_delta as f64); + let y = self.y; + let z = self.z * (x_delta as f64) - self.x * (y_delta as f64); + Vec3 { x, y, z } + } } /// The coordinates of a block in the world. For entities (if the coordinate diff --git a/azalea-entity/src/lib.rs b/azalea-entity/src/lib.rs index c009198c9..1334ee0fd 100644 --- a/azalea-entity/src/lib.rs +++ b/azalea-entity/src/lib.rs @@ -172,7 +172,8 @@ impl From<&Position> for BlockPos { } } -/// The last position of the entity that was sent over the network. +/// The second most recent position of the entity that was sent over the +/// network. This is currently only updated for our own local player entities. #[derive(Component, Clone, Copy, Debug, Default, PartialEq, Deref, DerefMut)] pub struct LastSentPosition(Vec3); impl From<&LastSentPosition> for Vec3 { diff --git a/azalea-inventory/src/slot.rs b/azalea-inventory/src/slot.rs index 757dc92d8..568ca441f 100644 --- a/azalea-inventory/src/slot.rs +++ b/azalea-inventory/src/slot.rs @@ -161,7 +161,7 @@ impl AzaleaRead for ItemStack { impl AzaleaWrite for ItemStack { fn azalea_write(&self, buf: &mut impl Write) -> Result<(), std::io::Error> { match self { - ItemStack::Empty => 0.azalea_write_var(buf)?, + ItemStack::Empty => 0_i32.azalea_write_var(buf)?, ItemStack::Present(i) => { i.count.azalea_write_var(buf)?; i.kind.azalea_write(buf)?; @@ -262,8 +262,8 @@ impl AzaleaWrite for DataComponentPatch { } } - components_with_data_count.azalea_write(buf)?; - components_without_data_count.azalea_write(buf)?; + components_with_data_count.azalea_write_var(buf)?; + components_without_data_count.azalea_write_var(buf)?; for (kind, component) in &self.components { if let Some(component) = component { diff --git a/azalea-protocol/src/packets/game/c_container_set_content.rs b/azalea-protocol/src/packets/game/c_container_set_content.rs index 852ce60fd..d4bd91840 100755 --- a/azalea-protocol/src/packets/game/c_container_set_content.rs +++ b/azalea-protocol/src/packets/game/c_container_set_content.rs @@ -10,3 +10,29 @@ pub struct ClientboundContainerSetContent { pub items: Vec, pub carried_item: ItemStack, } + +#[cfg(test)] +mod tests { + use std::io::Cursor; + + use super::ClientboundContainerSetContent; + use crate::packets::ProtocolPacket; + + #[test] + fn test_read_write_container_set_content() { + let contents = [ + 1, 2, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1, 196, 6, 0, 0, 0, + ]; + let mut buf = Cursor::new(contents.as_slice()); + let packet = ClientboundContainerSetContent::read(&mut buf).unwrap(); + println!("{:?}", packet); + + assert_eq!(buf.position(), contents.len() as u64); + + let mut buf = Vec::new(); + packet.write(&mut buf).unwrap(); + assert_eq!(buf, contents); + } +} diff --git a/azalea-protocol/src/packets/game/c_player_position.rs b/azalea-protocol/src/packets/game/c_player_position.rs index aa030fc57..e742df225 100755 --- a/azalea-protocol/src/packets/game/c_player_position.rs +++ b/azalea-protocol/src/packets/game/c_player_position.rs @@ -8,11 +8,19 @@ use azalea_protocol_macros::ClientboundGamePacket; pub struct ClientboundPlayerPosition { #[var] pub id: u32, + pub change: PositionMoveRotation, + pub relative: RelativeMovements, +} + +/// These values are either absolute or relative, depending on the fields from +/// the [`RelativeMovements`]. +#[derive(Clone, Debug, AzBuf)] +pub struct PositionMoveRotation { pub pos: Vec3, - pub delta_movement: Vec3, + /// The updated delta movement (velocity). + pub delta: Vec3, pub y_rot: f32, pub x_rot: f32, - pub relative_arguments: RelativeMovements, } #[derive(Debug, Clone)] @@ -22,6 +30,10 @@ pub struct RelativeMovements { pub z: bool, pub y_rot: bool, pub x_rot: bool, + pub delta_x: bool, + pub delta_y: bool, + pub delta_z: bool, + pub rotate_delta: bool, } impl AzaleaRead for RelativeMovements { @@ -34,28 +46,33 @@ impl AzaleaRead for RelativeMovements { z: set.index(2), y_rot: set.index(3), x_rot: set.index(4), + delta_x: set.index(5), + delta_y: set.index(6), + delta_z: set.index(7), + rotate_delta: set.index(8), }) } } impl AzaleaWrite for RelativeMovements { fn azalea_write(&self, buf: &mut impl Write) -> Result<(), std::io::Error> { - let mut set = FixedBitSet::<5>::new(); - if self.x { - set.set(0); - } - if self.y { - set.set(1); - } - if self.z { - set.set(2); - } - if self.y_rot { - set.set(3); - } - if self.x_rot { - set.set(4); - } + let mut set = FixedBitSet::<32>::new(); + let mut set_bit = |index: usize, value: bool| { + if value { + set.set(index); + } + }; + + set_bit(0, self.x); + set_bit(1, self.y); + set_bit(2, self.z); + set_bit(3, self.y_rot); + set_bit(4, self.x_rot); + set_bit(5, self.delta_x); + set_bit(6, self.delta_y); + set_bit(7, self.delta_z); + set_bit(8, self.rotate_delta); + set.azalea_write(buf) } } diff --git a/azalea-protocol/src/packets/game/c_recipe_book_remove.rs b/azalea-protocol/src/packets/game/c_recipe_book_remove.rs index aa5a09fe3..983c5e12a 100755 --- a/azalea-protocol/src/packets/game/c_recipe_book_remove.rs +++ b/azalea-protocol/src/packets/game/c_recipe_book_remove.rs @@ -1,12 +1,8 @@ use azalea_buf::AzBuf; use azalea_protocol_macros::ClientboundGamePacket; -use super::{c_entity_position_sync::PositionMoveRotation, c_player_position::RelativeMovements}; - #[derive(Clone, Debug, AzBuf, ClientboundGamePacket)] pub struct ClientboundRecipeBookRemove { #[var] - pub id: u32, - pub change: PositionMoveRotation, - pub relatives: RelativeMovements, + pub recipes: Vec, } diff --git a/azalea-protocol/src/packets/game/s_move_player_pos_rot.rs b/azalea-protocol/src/packets/game/s_move_player_pos_rot.rs index cb0e0633b..2cf186da2 100755 --- a/azalea-protocol/src/packets/game/s_move_player_pos_rot.rs +++ b/azalea-protocol/src/packets/game/s_move_player_pos_rot.rs @@ -1,11 +1,10 @@ use azalea_buf::AzBuf; +use azalea_core::position::Vec3; use azalea_protocol_macros::ServerboundGamePacket; #[derive(Clone, Debug, AzBuf, ServerboundGamePacket)] pub struct ServerboundMovePlayerPosRot { - pub x: f64, - pub y: f64, - pub z: f64, + pub pos: Vec3, pub y_rot: f32, pub x_rot: f32, pub on_ground: bool,