From 90a6196443022e14c88c6275d0775d2b7dbf10ed Mon Sep 17 00:00:00 2001 From: popertots Date: Sat, 21 Mar 2026 01:36:38 +0000 Subject: [PATCH] feat: soft entity collision, dead code removal, leaf standability fix MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 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) --- Cargo.lock | 1 + Cargo.toml | 1 + assets/tileset.png | Bin 3610 -> 3604 bytes config.toml | 2 +- entity_dump_9.52.csv | 61 + full.patch | 1423 ++++++++++++++++++ src/constants.rs | 9 +- src/debug/entity_dump.rs | 74 + src/debug/mod.rs | 1 + src/entities/livestock/pig.rs | 1 + src/entities/livestock/rabbit.rs | 1 + src/entities/sentient/dorf.rs | 1 + src/entities/shared_components/ambulatory.rs | 2 + src/entities/shared_systems/mod.rs | 1 + src/entities/shared_systems/occupancy.rs | 33 + src/entities/shared_systems/pathfinding.rs | 527 +++---- src/main.rs | 2 + src/world/generation/forestry.rs | 14 +- src/world/generation/terrain.rs | 11 +- src/world/mod.rs | 11 +- src/world/tiles/benchmark.rs | 8 +- src/world/tiles/mod.rs | 4 - src/world/tiles/prefabs.rs | 199 +-- src/world/tiles/tilemap.rs | 18 + src/world/tiles/tilemap_chunk.rs | 2 +- 25 files changed, 1909 insertions(+), 498 deletions(-) create mode 100644 entity_dump_9.52.csv create mode 100644 full.patch create mode 100644 src/debug/entity_dump.rs create mode 100644 src/debug/mod.rs create mode 100644 src/entities/shared_systems/occupancy.rs diff --git a/Cargo.lock b/Cargo.lock index fb9dc22..a8e57fe 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2432,6 +2432,7 @@ name = "dorf" version = "0.1.0" dependencies = [ "ahash", + "arrayvec", "bevy", "bevy_platform", "bevy_rand", diff --git a/Cargo.toml b/Cargo.toml index 1f33281..19ee719 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,6 +17,7 @@ rustc-hash = "2.1.1" ahash = "0.8.12" nohash-hasher = "0.2.0" futures-lite = "2.6.1" +arrayvec = "0.7.6" [build-dependencies] image = "0.25.10" diff --git a/assets/tileset.png b/assets/tileset.png index 6130ddc57d3bfc63964fdbf2f3e8c3ecb39d36d8..36274f67bf4b82ef93693629620a6f4b46a970ac 100644 GIT binary patch delta 2758 zcma)+d010d8piJ>K>`YdprV3d3n*F}LaN2TZ$c za*b>38e5YLrNW8<>YVX9*mKU(4W2xW_@2Hc-GMABg4dI3U?ox-#Ap`5m13eN0S24` z0yQ~*6o!AkK~jk999#%MXw1HW-Os?^FFQKmlI(sM?DKjA3kVGLhT&mgT?B~D{3Y!; ztnJWidXNJep&+ZjHVg)$kjO10G6g_u-TylRHM*2KY#

NiPdidXW|TH4_+3(%+9) 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 Y=(HjE(i$oN7y&@Yww*z>fd{hw1J`kvrT_o{ diff --git a/config.toml b/config.toml index 419b4cd..0acfd90 100644 --- a/config.toml +++ b/config.toml @@ -1,4 +1,4 @@ -initial_chunk_radius = 15 +initial_chunk_radius = 8 [display] vsync = "mailbox" diff --git a/entity_dump_9.52.csv b/entity_dump_9.52.csv new file mode 100644 index 0000000..a028003 --- /dev/null +++ b/entity_dump_9.52.csv @@ -0,0 +1,61 @@ +timestamp,entity_id,x,y,z,has_path,path_index,path_len,target_x,target_y,target_z +9.523,14600,-16.0,32.0,0.0,true,0,56,816.0,-816.0,33.0 +9.523,14601,-0.0,32.0,0.0,true,0,60,640.0,-848.0,33.0 +9.523,14602,-16.0,0.0,0.0,true,0,38,-608.0,-144.0,17.0 +9.523,14603,0.0,-0.0,0.0,true,0,61,960.0,256.0,-15.0 +9.523,14604,16.0,-32.0,16.0,true,0,10,752.0,48.0,17.0 +9.523,14599,16.0,-16.0,16.0,true,0,46,-496.0,704.0,-15.0 +9.523,14598,-32.0,16.0,0.0,true,0,62,-832.0,800.0,-31.0 +9.523,14547,0.0,0.0,0.0,true,0,53,832.0,336.0,1.0 +9.523,14548,0.0,-0.0,0.0,true,0,55,848.0,-752.0,33.0 +9.523,14549,0.0,0.0,0.0,true,0,30,-96.0,464.0,-15.0 +9.523,14550,0.0,-0.0,0.0,true,0,52,816.0,512.0,17.0 +9.523,14551,0.0,-0.0,0.0,true,0,46,720.0,464.0,17.0 +9.523,14552,-0.0,0.0,0.0,true,0,49,768.0,-128.0,33.0 +9.523,14553,0.0,0.0,0.0,true,0,42,656.0,-400.0,49.0 +9.523,14554,-0.0,0.0,0.0,true,0,34,-512.0,-416.0,49.0 +9.523,14555,-0.0,-0.0,0.0,true,0,49,144.0,768.0,17.0 +9.523,14597,16.0,16.0,0.0,true,0,58,-256.0,928.0,-15.0 +9.523,14557,0.0,0.0,0.0,true,0,40,624.0,160.0,1.0 +9.523,14558,-0.0,0.0,0.0,true,0,44,96.0,688.0,17.0 +9.523,14559,0.0,-0.0,0.0,true,0,61,352.0,960.0,33.0 +9.523,14560,0.0,0.0,0.0,true,0,46,-704.0,-352.0,33.0 +9.523,14561,-0.0,-0.0,0.0,true,0,31,480.0,80.0,1.0 +9.523,14562,0.0,0.0,0.0,true,0,46,-272.0,-720.0,65.0 +9.523,14563,-0.0,-0.0,0.0,true,0,41,640.0,64.0,1.0 +9.523,14564,-0.0,0.0,0.0,true,0,43,672.0,176.0,1.0 +9.523,14565,0.0,0.0,0.0,true,0,54,-64.0,-848.0,49.0 +9.523,14566,-0.0,-0.0,0.0,true,0,51,-640.0,-768.0,49.0 +9.523,14596,-16.0,0.0,0.0,true,0,41,-512.0,-592.0,49.0 +9.523,14568,0.0,0.0,0.0,true,0,32,224.0,-464.0,33.0 +9.523,14569,0.0,-0.0,0.0,true,0,52,-656.0,784.0,-15.0 +9.523,14570,-0.0,-0.0,0.0,true,0,33,-512.0,256.0,-31.0 +9.523,14571,-0.0,0.0,0.0,true,0,49,176.0,-768.0,33.0 +9.523,14572,-0.0,-0.0,0.0,true,0,40,-272.0,-624.0,49.0 +9.523,14573,-0.0,0.0,0.0,true,0,61,960.0,336.0,1.0 +9.523,14595,-16.0,32.0,0.0,true,0,54,288.0,-816.0,17.0 +9.523,14575,0.0,-0.0,0.0,true,0,31,336.0,464.0,17.0 +9.523,14576,0.0,0.0,0.0,true,0,63,992.0,-64.0,1.0 +9.523,14577,-0.0,-0.0,0.0,true,0,47,-736.0,-112.0,17.0 +9.523,14578,-0.0,-0.0,0.0,true,0,58,368.0,896.0,33.0 +9.523,14579,0.0,0.0,0.0,true,0,40,-464.0,512.0,-15.0 +9.523,14580,-0.0,-0.0,0.0,true,0,42,-288.0,-656.0,65.0 +9.523,14581,0.0,-0.0,0.0,true,0,47,128.0,736.0,17.0 +9.523,14582,0.0,0.0,0.0,true,0,47,736.0,-400.0,49.0 +9.523,14583,-0.0,0.0,0.0,true,0,45,-368.0,-704.0,65.0 +9.523,14594,0.0,0.0,0.0,true,0,40,-464.0,512.0,-15.0 +9.523,14585,0.0,0.0,0.0,true,0,56,-880.0,336.0,-15.0 +9.523,14586,0.0,-0.0,0.0,true,0,64,784.0,992.0,17.0 +9.523,14587,0.0,0.0,0.0,true,0,64,896.0,-512.0,49.0 +9.523,14588,0.0,-0.0,0.0,true,0,30,-464.0,288.0,-31.0 +9.523,14592,0.0,0.0,0.0,true,0,50,48.0,-784.0,33.0 +9.523,14590,0.0,0.0,0.0,true,0,44,688.0,-224.0,49.0 +9.523,14591,-0.0,-0.0,0.0,true,0,46,-720.0,448.0,-31.0 +9.523,14545,0.0,-0.0,0.0,true,0,20,80.0,-304.0,33.0 +9.523,14546,0.0,0.0,0.0,true,0,5,368.0,576.0,17.0 +9.523,14556,0.0,0.0,0.0,true,0,9,640.0,576.0,17.0 +9.523,14567,0.0,-0.0,0.0,true,0,13,-528.0,-96.0,17.0 +9.523,14574,0.0,0.0,0.0,true,0,13,-640.0,64.0,1.0 +9.523,14584,0.0,0.0,0.0,true,0,13,-864.0,0.0,1.0 +9.523,14589,-0.0,-0.0,0.0,true,0,19,-112.0,-288.0,33.0 +9.523,14593,-0.0,-0.0,0.0,true,0,10,528.0,-32.0,17.0 diff --git a/full.patch b/full.patch new file mode 100644 index 0000000..ef294dd --- /dev/null +++ b/full.patch @@ -0,0 +1,1423 @@ +diff --git a/Cargo.lock b/Cargo.lock +index fb9dc22..a8e57fe 100644 +--- a/Cargo.lock ++++ b/Cargo.lock +@@ -2432,6 +2432,7 @@ name = "dorf" + version = "0.1.0" + dependencies = [ + "ahash", ++ "arrayvec", + "bevy", + "bevy_platform", + "bevy_rand", +diff --git a/Cargo.toml b/Cargo.toml +index 1f33281..19ee719 100644 +--- a/Cargo.toml ++++ b/Cargo.toml +@@ -17,6 +17,7 @@ rustc-hash = "2.1.1" + ahash = "0.8.12" + nohash-hasher = "0.2.0" + futures-lite = "2.6.1" ++arrayvec = "0.7.6" + + [build-dependencies] + image = "0.25.10" +diff --git a/assets/tileset.png b/assets/tileset.png +index 6130ddc..36274f6 100644 +Binary files a/assets/tileset.png and b/assets/tileset.png differ +diff --git a/config.toml b/config.toml +index 419b4cd..da69d4f 100644 +--- a/config.toml ++++ b/config.toml +@@ -1,9 +1,9 @@ +-initial_chunk_radius = 15 ++initial_chunk_radius = 8 + + [display] + vsync = "mailbox" + + [spawn_counts] +-dorfs = 5 ++dorfs = 50 + pigs = 5 + rabbits = 5 +\ No newline at end of file +diff --git a/full.patch b/full.patch +new file mode 100644 +index 0000000..e69de29 +diff --git a/src/constants.rs b/src/constants.rs +index 5025d11..83a29b1 100644 +--- a/src/constants.rs ++++ b/src/constants.rs +@@ -5,16 +5,11 @@ pub const ITILE_SIZE: i32 = TILE_SIZE as i32; + pub const SEED: u32 = 420; + + pub const PATHFINDER_SHORT_PATH_MAX_TILES: i32 = 64; +-pub const PATHFINDER_MAX_NODES: usize = 5000; +-pub const PATHFINDER_WAYPOINT_THRESHOLD_TILES: i32 = 100; +-pub const PATHFINDER_PROVISIONAL_NODE_LIMIT: usize = 64; ++pub const PATHFINDER_MAX_NODES: usize = 15000; ++pub const PATHFINDER_PROVISIONAL_NODE_LIMIT: usize = 256; + + // Hierarchical pathfinding thresholds + // Tier 1: Same/adjacent chunk -> sync A* (fast, ~87µs) + // Tier 2: 2-4 chunks away -> Provisional + full path via queue + // Tier 3: >4 chunks away -> Hierarchical chunk-path + async segmented A* + pub const PATHFINDER_HIERARCHICAL_THRESHOLD_CHUNKS: i32 = 4; +-pub const PATHFINDER_ASYNC_NODE_BUDGET_PER_FRAME: usize = 2000; +- +-// Snapshot bounds for async pathfinding (in chunks) +-pub const PATHFINDER_SNAPSHOT_CHUNK_RADIUS: i32 = 2; +diff --git a/src/debug/entity_dump.rs b/src/debug/entity_dump.rs +new file mode 100644 +index 0000000..b79403a +--- /dev/null ++++ b/src/debug/entity_dump.rs +@@ -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>, ++ time: Res