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:
@@ -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,
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user