fix: treat absent tiles as air in visibility, full-column occlusion refresh

- calculate_visibility: None from floor_tiles.get() now breaks touches_air=true.
  Absent tile = open space = air for visibility purposes. Previously, removed
  tiles left their below-neighbours with all-zero visible_range (black).
- rabbit_dig_system: fire TileOcclusionEvent for full Z_BELOW+1 level column
  below the dug tile + 8 XY neighbours each, not just 3x3x3. calculate_visibility
  traces up to Z_TOTAL+Z_BELOW+1 tiles above each tile, so removing one tile
  can expose visibility arbitrarily deep below.
This commit is contained in:
2026-03-21 12:30:56 +00:00
parent 0ebc48ff40
commit 36f068bf0c
2 changed files with 7 additions and 5 deletions
+5 -4
View File
@@ -134,14 +134,15 @@ pub fn rabbit_dig_system(
if tilemap.remove_floor(&below_pos).is_some() { if tilemap.remove_floor(&below_pos).is_some() {
tile_changed.write(TileChangedEvent { pos: below_pos }); tile_changed.write(TileChangedEvent { pos: below_pos });
// Refresh visibility for the dug tile and all 26 neighbours. // Refresh the full column below the dig and its XY neighbours.
// Removing a tile changes what is visible from every adjacent position. // calculate_visibility traces up to Z_TOTAL+Z_BELOW+1 tiles above each tile,
for dz in -1..=1i32 { // so removing one tile can affect visibility arbitrarily deep below.
for dz in 0..=crate::world::chunks::Z_BELOW as i32 {
for dy in -1..=1i32 { for dy in -1..=1i32 {
for dx in -1..=1i32 { for dx in -1..=1i32 {
occlusion.write(TileOcclusionEvent { occlusion.write(TileOcclusionEvent {
tile_position: below_pos tile_position: below_pos
+ IVec3::new(dx * ITILE_SIZE, dy * ITILE_SIZE, dz * ITILE_SIZE), - IVec3::new(dx * ITILE_SIZE, dy * ITILE_SIZE, dz * ITILE_SIZE),
}); });
} }
} }
+2 -1
View File
@@ -144,7 +144,8 @@ pub fn calculate_visibility(pos: IVec3, tilemap: &TileMap) -> [u32; 8] {
); );
match tilemap.floor_tiles.get(&neighbor_pos) { match tilemap.floor_tiles.get(&neighbor_pos) {
Some(tile) if tile.id == 0 => break 'neighbor_check true, Some(tile) if tile.id == 0 => break 'neighbor_check true,
None => {} // Absent tile means open space — treat as air for visibility.
None => break 'neighbor_check true,
_ => {} _ => {}
} }
} }