aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG.md2
-rw-r--r--azalea-client/src/plugins/interact/mod.rs4
-rw-r--r--azalea-client/src/plugins/movement.rs14
-rw-r--r--azalea-client/src/plugins/packet/game/mod.rs16
-rw-r--r--azalea-core/src/math.rs2
-rw-r--r--azalea-entity/src/lib.rs56
-rw-r--r--azalea-entity/src/plugin/mod.rs4
-rw-r--r--azalea-physics/src/lib.rs2
-rw-r--r--azalea-protocol/src/common/movements.rs8
-rw-r--r--azalea-world/src/heightmap.rs19
-rw-r--r--azalea/examples/testbot/commands/debug.rs3
-rw-r--r--azalea/src/bot.rs12
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