fix: insert_floor syncs ChunkData, rabbit replaces dug tile with air

- TileMap::insert_floor now syncs ChunkData bits (set_floor_tile) so is_standable
  returns correct values for tiles inserted via insert_floor. Previously the
  HashMap was updated but ChunkData remained stale, causing is_standable to
  return false for valid tiles.
- rabbit_dig_system inserts air tile at the dug position after remove_floor.
  Without this, the HashMap entry is absent and ChunkData bits stay 0 (both
  false), making is_standable return false at that position. The entity then
  falls through multiple levels. Air's can_stand_in=true means the space is
  passable — the entity falls through it and lands on solid ground below.
This commit is contained in:
2026-03-21 15:09:40 +00:00
parent 2c92bdfe28
commit 9d2f41faed
2 changed files with 41 additions and 2 deletions
+20 -2
View File
@@ -1,11 +1,11 @@
use crate::config::GameConfig; use crate::config::{GameConfig, TileRegistry};
use crate::constants::ITILE_SIZE; use crate::constants::ITILE_SIZE;
use crate::constants::TILE_SIZE; use crate::constants::TILE_SIZE;
use crate::constants::*; use crate::constants::*;
use crate::entities::shared_components::Ambulatory; use crate::entities::shared_components::Ambulatory;
use crate::game::SpawnDelay; use crate::game::SpawnDelay;
use crate::world::tiles::visibility::TileOcclusionEvent; use crate::world::tiles::visibility::TileOcclusionEvent;
use crate::world::tiles::{TileChangedEvent, TileMap}; use crate::world::tiles::{FloorTileData, TileChangedEvent, TileMap};
use crate::world::VisibleGameEntity; use crate::world::VisibleGameEntity;
use bevy::prelude::*; use bevy::prelude::*;
use bevy_rand::prelude::*; use bevy_rand::prelude::*;
@@ -169,6 +169,24 @@ pub fn rabbit_dig_system(
); );
let removed = tilemap.remove_floor(&below_pos); let removed = tilemap.remove_floor(&below_pos);
// Replace the dug tile with air. The slot must become passable — if the entry
// is simply absent, ChunkData bits remain 0 (impassable), and is_standable
// returns false. Air has can_stand_in=true so entities can fall through it.
if removed.is_some() {
let air = TileRegistry::global().floor("air");
tilemap.insert_floor(
below_pos,
FloorTileData::new(
air.id,
air.can_stand_in,
air.can_stand_on,
air.transparent,
air.astar_weight,
[0; 8],
),
);
}
println!( println!(
"[DIG] remove_floor({:?}) => {}", "[DIG] remove_floor({:?}) => {}",
below_pos, below_pos,
+21
View File
@@ -190,6 +190,27 @@ impl TileMap {
#[inline] #[inline]
pub fn insert_floor(&mut self, pos: IVec3, tile: FloorTileData) { pub fn insert_floor(&mut self, pos: IVec3, tile: FloorTileData) {
let chunk_pos = world_to_chunk(pos);
if let Some(chunk) = self.chunks.get_mut(&chunk_pos) {
let (lx, ly, z) = ChunkData::world_to_local(pos);
if z >= -(Z_BELOW as i32)
&& z <= Z_ABOVE as i32
&& lx >= 0
&& lx < CHUNK_SIZE
&& ly >= 0
&& ly < CHUNK_SIZE
{
chunk.set_floor_tile(
lx,
ly,
z,
tile.id,
tile.can_stand_in(),
tile.can_stand_on(),
tile.astar_weight,
);
}
}
self.floor_tiles.insert(pos, tile); self.floor_tiles.insert(pos, tile);
} }