Bound height cache invalidation per explosion

Co-authored-by: Codex <codex@openai.com>
This commit is contained in:
2026-11-03 11:20:19 +03:00
parent 10f24b5df8
commit 1f28f8361f
2 changed files with 24 additions and 1 deletions
+7 -1
View File
@@ -509,7 +509,13 @@ impl Ground {
/// Explosions change the land: forget what was known round them.
fn forget(&mut self, at: DVec3, radius: i32) {
let (cx, cz) = (at.x.floor() as i32, at.z.floor() as i32);
self.known.retain(|&(x, z), _| (x - cx).abs() > radius || (z - cz).abs() > radius);
// A blast affects a small square. Removing those columns directly avoids scanning the
// entire height cache once per explosion (and again when its confirmation times out).
for x in cx.saturating_sub(radius)..=cx.saturating_add(radius) {
for z in cz.saturating_sub(radius)..=cz.saturating_add(radius) {
self.known.remove(&(x, z));
}
}
self.world.touched(at, f64::from(radius) + 2.0);
}
}
+17
View File
@@ -1989,3 +1989,20 @@ fn cold_ejection_power_and_coast_use_their_own_speed_rules() {
assert!((fly(spec.cold + kind.burn_ticks(), 2.0) - 2.0 * 0.995).abs() < 1e-9, "coast drag");
assert!((fly(0, 0.2) - 0.4).abs() < 1e-9, "cold ejection minimum");
}
#[test]
fn blast_forget_removes_only_columns_in_the_same_square() {
let mut ground = Ground::default();
for x in -25..=25 {
for z in -25..=25 {
ground.known.insert((x, z), (x * 100 + z, 123));
}
}
let before = ground.known.clone();
let at = DVec3::new(-3.2, 70.0, 4.9);
ground.forget(at, 8);
let expected: std::collections::HashMap<_, _> = before.into_iter()
.filter(|&((x, z), _)| (x + 4_i32).abs() > 8 || (z - 4_i32).abs() > 8)
.collect();
assert_eq!(ground.known, expected);
}