Merge pull request #11637 from horizon-rust/fix/lightning-fire-radius-11376

🤖 Agent: lightning now places fire (and draws its extra-source offsets) only when canSpreadFireAround passes at the bolt, so fire_spread_radius_around_player holds for strikes far from every player.
This commit is contained in:
Ludovic Marie authored and GitHub committed 2026-11-07 07:40:30 +01:00
commit ebcfa2263a
1 file changed
+56 -1
+56 -1
View File
@@ -300,7 +300,8 @@ impl Game<'_> {
});
}
/// `spawnFire`: fire at the strike point and `extra` random neighbours,
/// wherever `BaseFireBlock.getState` fire can survive. Returns how many
/// wherever `BaseFireBlock.getState` fire can survive, when a player is
/// within the fire-spread radius. Returns how many
/// blocks it set on fire.
fn bolt_fire(&mut self, at: [f64; 3], extra: i32) -> i32 {
let mut set = 0;
@@ -309,6 +310,14 @@ impl Game<'_> {
at[1].floor() as i32,
at[2].floor() as i32,
];
// ServerLevel.canSpreadFireAround at the bolt: no fire at all, and no
// draws for the extra sources, away from every player (#11376).
let origin = BlockPos::new(base[0], base[1], base[2]);
if !self.with_level(|_, level, _| {
horizon_world::level::LevelAccess::can_spread_fire_around(level, origin)
}) {
return 0;
}
let mut spots = vec![base];
for _ in 0..extra {
let r = &mut self.world.random;
@@ -756,6 +765,52 @@ mod tests {
use horizon_core::geometry::Vec3;
use std::sync::Arc;
/// `LightningBolt.spawnFire` places nothing, and draws no extra sources,
/// unless `canSpreadFireAround` passes at the bolt (#11376).
#[test]
#[ignore = "needs prepared resources (HORIZON_TEST_RESOURCES)"]
fn a_bolt_away_from_players_starts_no_fire() {
use horizon_client::gamerules::Value;
let mut game = super::super::native_machines::tests::server_game();
let stone = game
.pack
.assets
.registry
.default_state("minecraft:stone")
.unwrap();
let air = game.res.facts().air;
game.world.set(8, 64, 8, stone).unwrap();
let bolt = [8.5, 65.0, 8.5];
// (radius, player's x): fires expected at the strike.
for (radius, player_x, fires) in [
(128, 12.5, true),
(1, 12.5, false),
(0, 8.5, false),
(-1, 1000.0, true),
] {
game.world.set(8, 65, 8, air).unwrap();
game.ui
.rules
.set("fire_spread_radius_around_player", Value::Int(radius));
game.player = Some(
horizon_client::motion::PlayerMotion::new(
game.motion,
Vec3::new(player_x, 65.0, 8.5),
)
.unwrap(),
);
let random = game.world.random.clone();
let set = game.bolt_fire(bolt, 4);
let burning = game.world.block(8, 65, 8) != air;
assert_eq!((set > 0, burning), (fires, fires), "radius {radius}");
if !fires {
// No offset draws either.
let mut before = random;
assert_eq!(game.world.random.next_long(), before.next_long());
}
}
}
#[test]
fn viewer_box_reaches_15_around_and_down_and_21_up() {
let bolt = [0.0, 64.0, 0.0];