diff options
| -rw-r--r-- | CHANGELOG.md | 2 | ||||
| -rw-r--r-- | azalea-client/src/plugins/interact/mod.rs | 4 | ||||
| -rw-r--r-- | azalea-client/src/plugins/movement.rs | 14 | ||||
| -rw-r--r-- | azalea-client/src/plugins/packet/game/mod.rs | 16 | ||||
| -rw-r--r-- | azalea-core/src/math.rs | 2 | ||||
| -rw-r--r-- | azalea-entity/src/lib.rs | 56 | ||||
| -rw-r--r-- | azalea-entity/src/plugin/mod.rs | 4 | ||||
| -rw-r--r-- | azalea-physics/src/lib.rs | 2 | ||||
| -rw-r--r-- | azalea-protocol/src/common/movements.rs | 8 | ||||
| -rw-r--r-- | azalea-world/src/heightmap.rs | 19 | ||||
| -rw-r--r-- | azalea/examples/testbot/commands/debug.rs | 3 | ||||
| -rw-r--r-- | azalea/src/bot.rs | 12 |
12 files changed, 100 insertions, 42 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index 6c79ac58..2a03250c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,6 +23,7 @@ is breaking anyways, semantic versioning is not followed. - Moved functions and types related to hit results from `azalea::interact` to `azalea::interact::pick`. - `Client::attack` now takes `Entity` instead of `MinecraftEntityId`. - `ItemStackData::components` was renamed to `component_patch`. +- The fields in `LookDirection` have been replaced with getters. ### Fixed @@ -33,6 +34,7 @@ is breaking anyways, semantic versioning is not followed. - Inventories now use the correct max stack sizes. - Clients now send the correct data component checksums when interacting with items. - Fix parsing some metadata fields of Display entities. +- Look directions are now rounded based on the default Minecraft sensitivity, which may help avoid flagging anticheats. ## [0.13.0+mc1.21.5] - 2025-06-15 diff --git a/azalea-client/src/plugins/interact/mod.rs b/azalea-client/src/plugins/interact/mod.rs index f02c05d5..634d492c 100644 --- a/azalea-client/src/plugins/interact/mod.rs +++ b/azalea-client/src/plugins/interact/mod.rs @@ -297,8 +297,8 @@ pub fn handle_start_use_item_queued( ServerboundUseItem { hand: start_use_item.hand, seq, - x_rot: look_direction.x_rot, - y_rot: look_direction.y_rot, + x_rot: look_direction.x_rot(), + y_rot: look_direction.y_rot(), }, )); } else { diff --git a/azalea-client/src/plugins/movement.rs b/azalea-client/src/plugins/movement.rs index aeb946fa..c27a67ce 100644 --- a/azalea-client/src/plugins/movement.rs +++ b/azalea-client/src/plugins/movement.rs @@ -105,15 +105,15 @@ impl Client { let mut ecs = self.ecs.lock(); let mut look_direction = self.query::<&mut LookDirection>(&mut ecs); - (look_direction.y_rot, look_direction.x_rot) = (y_rot, x_rot); + look_direction.update(LookDirection::new(y_rot, x_rot)); } /// Returns the direction the client is looking. The first value is the y /// rotation (ie. yaw, looking to the side) and the second value is the x /// rotation (ie. pitch, looking up and down). pub fn direction(&self) -> (f32, f32) { - let look_direction = self.component::<LookDirection>(); - (look_direction.y_rot, look_direction.x_rot) + let look_direction: LookDirection = self.component::<LookDirection>(); + (look_direction.y_rot(), look_direction.x_rot()) } } @@ -176,8 +176,8 @@ pub fn send_position( let x_delta = position.x - last_sent_position.x; let y_delta = position.y - last_sent_position.y; let z_delta = position.z - last_sent_position.z; - let y_rot_delta = (direction.y_rot - last_direction.y_rot) as f64; - let x_rot_delta = (direction.x_rot - last_direction.x_rot) as f64; + let y_rot_delta = (direction.y_rot() - last_direction.y_rot) as f64; + let x_rot_delta = (direction.x_rot() - last_direction.x_rot) as f64; physics_state.position_remainder += 1; @@ -231,8 +231,8 @@ pub fn send_position( physics_state.position_remainder = 0; } if sending_direction { - last_direction.y_rot = direction.y_rot; - last_direction.x_rot = direction.x_rot; + last_direction.y_rot = direction.y_rot(); + last_direction.x_rot = direction.x_rot(); } let on_ground = physics.on_ground(); diff --git a/azalea-client/src/plugins/packet/game/mod.rs b/azalea-client/src/plugins/packet/game/mod.rs index 1fa3e109..fe294ad0 100644 --- a/azalea-client/src/plugins/packet/game/mod.rs +++ b/azalea-client/src/plugins/packet/game/mod.rs @@ -900,10 +900,10 @@ impl GamePacketHandler<'_> { }; let new_delta = p.delta.clone(); - let new_look_direction = LookDirection { - x_rot: (p.x_rot as i32 * 360) as f32 / 256., - y_rot: (p.y_rot as i32 * 360) as f32 / 256., - }; + let new_look_direction = LookDirection::new( + (p.y_rot as i32 * 360) as f32 / 256., + (p.x_rot as i32 * 360) as f32 / 256., + ); let new_on_ground = p.on_ground; @@ -938,10 +938,10 @@ impl GamePacketHandler<'_> { let entity = entity_id_index.get_by_minecraft_entity(p.entity_id); if let Some(entity) = entity { - let new_look_direction = LookDirection { - x_rot: (p.x_rot as i32 * 360) as f32 / 256., - y_rot: (p.y_rot as i32 * 360) as f32 / 256., - }; + let new_look_direction = LookDirection::new( + (p.y_rot as i32 * 360) as f32 / 256., + (p.x_rot as i32 * 360) as f32 / 256., + ); let new_on_ground = p.on_ground; commands.entity(entity).queue(RelativeEntityUpdate::new( diff --git a/azalea-core/src/math.rs b/azalea-core/src/math.rs index d5fe5af9..105069ef 100644 --- a/azalea-core/src/math.rs +++ b/azalea-core/src/math.rs @@ -63,7 +63,7 @@ pub fn lerp<T: num_traits::Float>(amount: T, a: T, b: T) -> T { } pub fn ceil_log2(x: u32) -> u32 { - u32::BITS - x.leading_zeros() + u32::BITS - x.saturating_sub(1).leading_zeros() } pub fn fract(x: f64) -> f64 { diff --git a/azalea-entity/src/lib.rs b/azalea-entity/src/lib.rs index 984cce27..8758c258 100644 --- a/azalea-entity/src/lib.rs +++ b/azalea-entity/src/lib.rs @@ -217,13 +217,16 @@ impl From<&LastSentPosition> for BlockPos { #[derive(Debug, Component, Copy, Clone, Deref, DerefMut, Default, PartialEq, Eq)] pub struct Jumping(pub bool); -/// A component that contains the direction an entity is looking. +/// A component that contains the direction an entity is looking, in degrees. +/// +/// To avoid flagging anticheats, consider using [`Self::update`] when updating +/// the values of this struct. #[derive(Debug, Component, Copy, Clone, Default, PartialEq, AzBuf)] pub struct LookDirection { - /// Left and right. AKA yaw. - pub y_rot: f32, - /// Up and down. AKA pitch. - pub x_rot: f32, + /// Left and right. AKA yaw. In degrees. + y_rot: f32, + /// Up and down. AKA pitch. In degrees. + x_rot: f32, } impl LookDirection { @@ -232,6 +235,49 @@ impl LookDirection { pub fn new(y_rot: f32, x_rot: f32) -> Self { apply_clamp_look_direction(Self { y_rot, x_rot }) } + /// Returns yaw (left and right) in degrees. + /// + /// Minecraft allows this to go outside of ±360°, so it won't necessarily be + /// in any range. + pub fn y_rot(&self) -> f32 { + self.y_rot + } + /// Returns pitch (up and down) in degrees. + /// + /// Clamped to ±90°. + pub fn x_rot(&self) -> f32 { + self.x_rot + } + + /// Update this look direction to the new value, while handling relative + /// rotations correctly and with the default Minecraft sensitivity to avoid + /// triggering anticheats. + pub fn update(&mut self, new: LookDirection) { + self.update_with_sensitivity(new, 1.); + } + + /// Update this look direction to the new value, using the given + /// sensitivity value. + /// + /// Consider using [`Self::set`] instead, which uses 1.0 as the sensitivity + /// (equivalent to 100% sensitivity in Minecraft). + pub fn update_with_sensitivity(&mut self, new: LookDirection, sensitivity: f32) { + let mut delta_y_rot = new.y_rot.rem_euclid(360.) - self.y_rot.rem_euclid(360.); + let delta_x_rot = new.x_rot - self.x_rot; + + if delta_y_rot > 180. { + delta_y_rot -= 360.; + } else if delta_y_rot < -180. { + delta_y_rot += 360.; + } + + let sensitivity = sensitivity * 0.15; + let delta_y_rot = (delta_y_rot / sensitivity).round() * sensitivity; + let delta_x_rot = (delta_x_rot / sensitivity).round() * sensitivity; + + self.y_rot += delta_y_rot; + self.x_rot += delta_x_rot; + } } impl From<LookDirection> for (f32, f32) { diff --git a/azalea-entity/src/plugin/mod.rs b/azalea-entity/src/plugin/mod.rs index 88e87de1..924a6f53 100644 --- a/azalea-entity/src/plugin/mod.rs +++ b/azalea-entity/src/plugin/mod.rs @@ -191,8 +191,8 @@ pub fn clamp_look_direction(mut query: Query<&mut LookDirection>) { } } pub fn apply_clamp_look_direction(mut look_direction: LookDirection) -> LookDirection { - look_direction.y_rot = look_direction.y_rot.rem_euclid(360.0); - look_direction.x_rot = look_direction.x_rot.clamp(-90.0, 90.0) % 360.0; + look_direction.x_rot = look_direction.x_rot.clamp(-90., 90.); + look_direction } diff --git a/azalea-physics/src/lib.rs b/azalea-physics/src/lib.rs index 779ee067..2063f0f0 100644 --- a/azalea-physics/src/lib.rs +++ b/azalea-physics/src/lib.rs @@ -341,7 +341,7 @@ pub fn jump_from_ground( }; if *sprinting { // sprint jumping gives some extra velocity - let y_rot = look_direction.y_rot * 0.017453292; + let y_rot = look_direction.y_rot() * 0.017453292; physics.velocity += Vec3 { x: (-math::sin(y_rot) * 0.2) as f64, y: 0., diff --git a/azalea-protocol/src/common/movements.rs b/azalea-protocol/src/common/movements.rs index 6475b46f..265b4b65 100644 --- a/azalea-protocol/src/common/movements.rs +++ b/azalea-protocol/src/common/movements.rs @@ -63,14 +63,14 @@ impl RelativeMovements { ); let new_look_direction = LookDirection::new( - apply_change(direction.y_rot, self.y_rot, change.look_direction.y_rot), - apply_change(direction.x_rot, self.x_rot, change.look_direction.x_rot), + apply_change(direction.y_rot(), self.y_rot, change.look_direction.y_rot()), + apply_change(direction.x_rot(), self.x_rot, change.look_direction.x_rot()), ); let mut new_delta = physics.velocity; if self.rotate_delta { - let y_rot_delta = direction.y_rot - new_look_direction.y_rot; - let x_rot_delta = direction.x_rot - new_look_direction.x_rot; + let y_rot_delta = direction.y_rot() - new_look_direction.y_rot(); + let x_rot_delta = direction.x_rot() - new_look_direction.x_rot(); new_delta = new_delta .x_rot(math::to_radians(x_rot_delta as f64) as f32) .y_rot(math::to_radians(y_rot_delta as f64) as f32); diff --git a/azalea-world/src/heightmap.rs b/azalea-world/src/heightmap.rs index dbe7d78f..d3b2b071 100644 --- a/azalea-world/src/heightmap.rs +++ b/azalea-world/src/heightmap.rs @@ -7,6 +7,7 @@ use azalea_block::BlockState; use azalea_buf::AzBuf; use azalea_core::{math, position::ChunkBlockPos}; use azalea_registry::tags::blocks::LEAVES; +use tracing::warn; use crate::{BitStorage, Section, chunk_storage::get_block_state_from_sections}; @@ -62,8 +63,22 @@ impl HeightmapKind { impl Heightmap { pub fn new(kind: HeightmapKind, dimension_height: u32, min_y: i32, data: Box<[u64]>) -> Self { let bits = math::ceil_log2(dimension_height + 1); - let data = BitStorage::new(bits as usize, 16 * 16, Some(data)).unwrap(); - Self { kind, data, min_y } + let mut bit_storage = BitStorage::new(bits as usize, 16 * 16, None) + .expect("data is empty, so this can't fail"); + if bit_storage.data.len() != data.len() { + warn!( + "Ignoring heightmap data, size does not match; expected: {}, got: {}", + bit_storage.data.len(), + data.len() + ); + } else { + bit_storage.data.copy_from_slice(&data); + } + Self { + kind, + data: bit_storage, + min_y, + } } pub fn get_index(x: u8, z: u8) -> usize { diff --git a/azalea/examples/testbot/commands/debug.rs b/azalea/examples/testbot/commands/debug.rs index 92a5b92e..46f1ed33 100644 --- a/azalea/examples/testbot/commands/debug.rs +++ b/azalea/examples/testbot/commands/debug.rs @@ -90,7 +90,8 @@ pub fn register(commands: &mut CommandDispatcher<Mutex<CommandSource>>) { let direction = source.bot.component::<LookDirection>(); source.reply(format!( "I'm looking at {}, {}", - direction.y_rot, direction.x_rot + direction.y_rot(), + direction.x_rot() )); 1 })); diff --git a/azalea/src/bot.rs b/azalea/src/bot.rs index 745f3fdb..8784cb31 100644 --- a/azalea/src/bot.rs +++ b/azalea/src/bot.rs @@ -230,8 +230,9 @@ fn look_at_listener( if let Ok((position, eye_height, mut look_direction)) = query.get_mut(event.entity) { let new_look_direction = direction_looking_at(position.up(eye_height.into()), event.position); + trace!("look at {} (currently at {})", event.position, **position); - *look_direction = new_look_direction; + look_direction.update(new_look_direction); } } } @@ -245,14 +246,7 @@ pub fn direction_looking_at(current: Vec3, target: Vec3) -> LookDirection { let ground_distance = f64::sqrt(delta.x * delta.x + delta.z * delta.z); let x_rot = f64::atan2(delta.y, ground_distance) * -(180.0 / PI); - // clamp - let y_rot = y_rot.rem_euclid(360.0); - let x_rot = x_rot.clamp(-90.0, 90.0) % 360.0; - - LookDirection { - x_rot: x_rot as f32, - y_rot: y_rot as f32, - } + LookDirection::new(y_rot as f32, x_rot as f32) } /// A [`PluginGroup`] for the plugins that add extra bot functionality to the |
