fix: correct sound packet position encoding (was multiplied by 8 twice) (#2440)

CSoundEffect::new() scales the position by * 8 to convert from
fixed-point. write_packet_data was applying * 8 a second time,
resulting in positions being multiplied by 64.

Add regression test asserting the encoded X/Y/Z are exactly
floor(input_pos * 8), preventing this bug from reappearing.
This commit is contained in:
Jamie Little
2026-07-27 04:06:00 +01:00
committed by GitHub
parent 5f127823ae
commit ad31ce9889

View File

@@ -60,9 +60,9 @@ impl ClientPacket for CSoundEffect {
w.write_option(&e.range, |w2, r| w2.write_f32_be(*r))
})?;
write.write_var_int(&self.sound_category)?;
write.write_i32_be(self.position.x * 8)?;
write.write_i32_be(self.position.y * 8)?;
write.write_i32_be(self.position.z * 8)?;
write.write_i32_be(self.position.x)?;
write.write_i32_be(self.position.y)?;
write.write_i32_be(self.position.z)?;
write.write_f32_be(self.volume)?;
write.write_f32_be(self.pitch)?;
write.write_i64_be(self.seed as i64)
@@ -77,7 +77,7 @@ mod tests {
use pumpkin_data::sound_id_remap::remap_sound_id_for_version;
use pumpkin_util::{math::vector3::Vector3, version::JavaMinecraftVersion};
use crate::{ClientPacket, IdOr, SoundEvent, VarInt};
use crate::{ClientPacket, IdOr, SoundEvent, VarInt, ser::NetworkReadExt};
use super::CSoundEffect;
@@ -155,4 +155,37 @@ mod tests {
assert_eq!(first_var_int(bytes), VarInt::from(0));
}
#[test]
fn position_scaling_is_applied_only_once() {
let packet = CSoundEffect::new(
IdOr::Id(0),
SoundCategory::Players,
&Vector3::new(2.5, 3.5, 4.5),
1.0,
1.0,
42.0,
);
let mut bytes = Vec::new();
packet
.write_packet_data(&mut bytes, &JavaMinecraftVersion::V_26_2)
.unwrap();
let mut cursor = Cursor::new(bytes);
// skip sound ID varint
VarInt::decode(&mut cursor).unwrap();
// skip sound category varint
VarInt::decode(&mut cursor).unwrap();
// read position
let x = cursor.get_i32_be().unwrap();
let y = cursor.get_i32_be().unwrap();
let z = cursor.get_i32_be().unwrap();
// position should be floor(input * 8), applied exactly once
// (2.5 * 8 = 20, 3.5 * 8 = 28, 4.5 * 8 = 36)
assert_eq!(x, 20);
assert_eq!(y, 28);
assert_eq!(z, 36);
}
}