Merge pull request #6451 from xFedeT/fix/hand-sway-yaw-wrap

🤖 Agent: queued: reviewed, union-tested green at this head.
This commit is contained in:
Ludovic Marie authored and GitHub committed 2026-11-02 00:24:21 +01:00
commit 3310fcafb9
1 file changed
+36 -2
+36 -2
View File
@@ -520,6 +520,17 @@ pub fn equip_displacement(height: f32, swap_animation_scale: f32) -> f32 {
swap_animation_scale * (1.0 - height)
}
/// `Mth.wrapDegrees`: an angle difference in -180..=180.
fn wrap_degrees(d: f32) -> f32 {
let d = d % 360.0;
if d >= 180.0 {
d - 360.0
} else if d < -180.0 {
d + 360.0
} else {
d
}
}
/// `LocalPlayer.xBob` and `yBob`: the hands lag behind the view when it
/// turns. `LocalPlayer.applyInput` eases them halfway to the rotation every
/// tick; `FirstPersonHandsAndItemsRenderer` turns the hands by a tenth of
@@ -537,7 +548,9 @@ impl HandSway {
self.y_bob_o = self.y_bob;
self.x_bob_o = self.x_bob;
self.x_bob += (x_rot - self.x_bob) * 0.5;
self.y_bob += (y_rot - self.y_bob) * 0.5;
// Vanilla's yaw runs on without wrapping, so `yRot - yBob` is the short way round. Ours
// is kept in -180..180 (a boat turns its rider through it), so take the short way here.
self.y_bob += wrap_degrees(y_rot - self.y_bob) * 0.5;
}
/// The degrees the hands turn about X, then Y, before either is drawn:
/// `(viewXRot - xBob) * 0.1` and `(viewYRot - yBob) * 0.1`, the bobs
@@ -545,7 +558,10 @@ impl HandSway {
pub fn rotation(&self, partial: f32, view_x_rot: f32, view_y_rot: f32) -> [f32; 2] {
let x_bob = crate::camera::lerp(partial, self.x_bob_o, self.x_bob);
let y_bob = crate::camera::lerp(partial, self.y_bob_o, self.y_bob);
[(view_x_rot - x_bob) * 0.1, (view_y_rot - y_bob) * 0.1]
[
(view_x_rot - x_bob) * 0.1,
wrap_degrees(view_y_rot - y_bob) * 0.1,
]
}
/// The hands' view space to camera-relative world space, turned by the
/// sway. The hand pass draws with the camera's view, whose rotation a
@@ -1384,4 +1400,22 @@ mod action_result_tests {
);
}
}
/// The hands' sway turns the short way round when the yaw wraps from 179 to -179 degrees (a
/// boat turning its rider), instead of swinging them 36 degrees the long way.
#[test]
fn hand_sway_takes_the_short_way_over_the_yaw_wrap() {
let mut sway = HandSway::default();
sway.tick(0.0, 179.0);
for _ in 0..20 {
sway.tick(0.0, 179.0);
}
// The view is still at 179; one tick later it reads -179 (2 degrees on).
sway.tick(0.0, -179.0);
let [_, y] = sway.rotation(1.0, 0.0, -179.0);
assert!(
y.abs() < 0.5,
"a 2 degree turn sways the hands by under half a degree: {y}"
);
}
}