feat: soft entity collision, dead code removal, leaf standability fix

- Add TileOccupancy resource and rebuild_tile_occupancy system to track
  per-tile entity counts for soft collision avoidance
- Add collision_delay to Ambulatory; entities try relative-left step on
  occupied tiles, wait 1 tick, then push through
- Fix leaf canopy standability: leaves are now can_stand_in=true,
  can_stand_on=false (walkable, not standable-on)
- Delete FloorTilePrefab / FixtureTilePrefab / FloorTile / FixtureTile /
  TileState (all fully dead — TileMap + ChunkData are sole truth)
- Delete tile_spawns from TerrainBlob (populated but never consumed)
- Delete leaf ghost entity spawn in forestry (orphaned invisible ECS entity)
- Replace log prefab spawn with inline commands.spawn(Transform, Visibility)
- Add TileMap::remove_fixture for future digging/explosion use
- Skip collision avoidance when current tile has >2 entities (handles spawn
  cluster deadlock)
This commit is contained in:
2026-03-21 01:36:38 +00:00
parent 1fe4781bab
commit 90a6196443
25 changed files with 1909 additions and 498 deletions
+74
View File
@@ -0,0 +1,74 @@
use bevy::prelude::*;
use std::fs::OpenOptions;
use std::io::Write;
use crate::entities::shared_components::Ambulatory;
pub fn dump_entity_positions(
keys: Res<ButtonInput<KeyCode>>,
time: Res<Time>,
query: Query<(Entity, &Transform, Option<&Ambulatory>), With<Ambulatory>>,
) {
if !keys.just_pressed(KeyCode::Space) {
return;
}
let timestamp = time.elapsed_secs();
let filename = format!("entity_dump_{:.2}.csv", timestamp);
let mut file = match OpenOptions::new()
.create(true)
.write(true)
.truncate(true)
.open(&filename)
{
Ok(f) => f,
Err(e) => {
eprintln!("Failed to create dump file: {}", e);
return;
}
};
writeln!(
file,
"timestamp,entity_id,x,y,z,has_path,path_index,path_len,target_x,target_y,target_z"
)
.ok();
let mut count = 0;
for (entity, transform, ambulatory) in query.iter() {
let pos = transform.translation;
let (has_path, path_index, path_len, tx, ty, tz) = match ambulatory {
Some(a) => {
let path_len = a.current_path.as_ref().map(|p| p.len()).unwrap_or(0);
let has_path = path_len > 0;
let (tx, ty, tz) = match a.target {
Some(t) => (t.x, t.y, t.z),
None => (0.0, 0.0, 0.0),
};
(has_path, a.path_index, path_len, tx, ty, tz)
}
None => (false, 0, 0, 0.0, 0.0, 0.0),
};
writeln!(
file,
"{:.3},{},{:.1},{:.1},{:.1},{},{},{},{:.1},{:.1},{:.1}",
timestamp,
entity.index(),
pos.x,
pos.y,
pos.z,
has_path,
path_index,
path_len,
tx,
ty,
tz,
)
.ok();
count += 1;
}
println!("[DUMP] {} entities written to {}", count, filename);
}
+1
View File
@@ -0,0 +1 @@
pub mod entity_dump;