Sound broadcasts leave out a guest exactly on the radius

PlayerList.broadcast compares the squared distances with `<`, so vanilla's sound
packet does not reach a player standing exactly at SoundEvent.getRange(volume).
Hub::broadcast_near used `<=`; the boundary is now the same strict test, in a
helper the unit test can call.

The rest-020 row for SoundEvent.getRange said missing: it is folded into that
broadcast, and no 26.3 sound event has a fixed range, so 16 * max(volume, 1) is
the whole formula.
This commit is contained in:
MSedgeMC committed 2026-11-02 06:52:05 +00:00
1 parent 4c908814b1
commit 99deb65138
2 files changed
+23 -5

No files matched your search

+22 -4
View File
@@ -33,7 +33,8 @@ impl Hub {
}
}
/// Send to every placed guest within `range` blocks of `at`.
/// Send to every placed guest within `range` blocks of `at`
/// (`PlayerList.broadcast`, which leaves out a player exactly at `range`).
pub fn broadcast_near(&self, at: [f64; 3], range: f64, packet: &C, except: Option<u32>) {
let body = packet.encode();
for g in self
@@ -41,8 +42,7 @@ impl Hub {
.iter()
.filter(|g| self.here(g) && Some(g.conn) != except)
{
let d: f64 = (0..3).map(|k| (g.position[k] - at[k]).powi(2)).sum();
if d <= range * range {
if within_range(at, g.position, range) {
g.sender.send(body.clone());
}
}
@@ -886,9 +886,16 @@ fn next_sound_seed(g: &mut impl RandomSource) -> i64 {
g.next_long()
}
/// `PlayerList.broadcast`'s distance test: the summed squared axis distances
/// against the squared radius, and a player exactly at the radius is out.
fn within_range(at: [f64; 3], pos: [f64; 3], range: f64) -> bool {
let d: f64 = (0..3).map(|k| (pos[k] - at[k]).powi(2)).sum();
d < range * range
}
#[cfg(test)]
mod tests {
use super::next_sound_seed;
use super::{next_sound_seed, within_range};
use horizon_core::random::LegacyRandom;
#[test]
@@ -907,4 +914,15 @@ mod tests {
let mut g = LegacyRandom::new(0);
assert_ne!(next_sound_seed(&mut g), ticks);
}
/// `PlayerList.broadcast` compares the squared distances with `ifge`, so a
/// player exactly on the radius gets no packet while one a hair inside does.
#[test]
fn a_guest_exactly_on_the_radius_hears_nothing() {
let at = [10.0, 64.0, -3.0];
let at_radius = [at[0] + 16.0, at[1], at[2]];
assert!(!within_range(at, at_radius, 16.0));
assert!(within_range(at, [at[0] + 15.99, at[1], at[2]], 16.0));
assert!(within_range(at, at, 16.0));
}
}
+1 -1
View File
@@ -72,7 +72,7 @@ ServerWaypointManager.remakeConnections inline crates/horizon-client/src/lan/way
ServerWaypointManager.createConnection port crates/horizon-client/src/lan/waypoints.rs::Waypoints::create_connection
ServerWaypointManager.updateConnection port crates/horizon-client/src/lan/waypoints.rs::Waypoints::update_or_create
SoundEvent.create skip:data registry object construction; Horizon's sound_events.rs models sounds.json entries, not SoundEvent objects
SoundEvent.getRange missing minor: no fixed-range sound events (fixed_range is not read anywhere); attenuation comes from the sounds.json value (Sound::attenuation_distance)
SoundEvent.getRange inline crates/horizon-client/src/lan/containers.rs::Hub::broadcast_near 16*max(volume,1) is the whole formula: no 26.3 event sets a fixed range (SoundEvents never calls createFixedRangeEvent), and a player exactly on it is left out
SoundEvents.register skip:data registry bootstrap of sound events and variant sets; Horizon has no registry layer
SoundEvents.registerForHolder skip:data registry bootstrap of sound events and variant sets; Horizon has no registry layer
SoundEvents.registerGoatHornSoundVariants skip:data registry bootstrap of sound events and variant sets; Horizon has no registry layer
1 PlayerList.updateEntireScoreboard port crates/horizon-client/src/lan/scoreboard.rs::View::changes the join is View::changes against the guest's empty view, sent from game/scoreboard.rs lan_sync_scoreboard
72 ServerWaypointManager.createConnection port crates/horizon-client/src/lan/waypoints.rs::Waypoints::create_connection
73 ServerWaypointManager.updateConnection port crates/horizon-client/src/lan/waypoints.rs::Waypoints::update_or_create
74 SoundEvent.create skip:data registry object construction; Horizon's sound_events.rs models sounds.json entries, not SoundEvent objects
75 SoundEvent.getRange missing inline crates/horizon-client/src/lan/containers.rs::Hub::broadcast_near minor: no fixed-range sound events (fixed_range is not read anywhere); attenuation comes from the sounds.json value (Sound::attenuation_distance) 16*max(volume,1) is the whole formula: no 26.3 event sets a fixed range (SoundEvents never calls createFixedRangeEvent), and a player exactly on it is left out
76 SoundEvents.register skip:data registry bootstrap of sound events and variant sets; Horizon has no registry layer
77 SoundEvents.registerForHolder skip:data registry bootstrap of sound events and variant sets; Horizon has no registry layer
78 SoundEvents.registerGoatHornSoundVariants skip:data registry bootstrap of sound events and variant sets; Horizon has no registry layer