Fix bug: prevent multiple job assignments to same dorf in one frame

- Add assigned_this_frame HashSet to track dorfs receiving jobs
- Filter out already-assigned dorfs from subsequent job assignments
- Add debug logging for spawn position (z-level)
- Add debug logging for is_standable failures
- Add debug logging for falling/snapping movement behavior

This fixes the critical bug where one dorf could be assigned multiple
jobs in the same frame, causing earlier assignments to be lost due to
queue.clear(). Each dorf now receives at most one job per frame.
This commit is contained in:
2026-04-05 18:09:37 +01:00
parent c9d74ef49b
commit ec1ec6b7d4
3 changed files with 39 additions and 4 deletions
+12 -1
View File
@@ -45,6 +45,10 @@ pub fn job_pathfinding_system(
info!("[PATHFIND] Locked dorfs: {:?}", locked_dorfs.len());
}
// Track dorfs assigned jobs in this frame to prevent multiple assignments
let mut assigned_this_frame: std::collections::HashSet<Entity> =
std::collections::HashSet::new();
for job_idx in unclaimed.into_iter().take(MAX_JOBS_PER_TICK) {
let (kind, state, _) = match job_queue.get_job_at(job_idx) {
Some(k) => k,
@@ -80,7 +84,7 @@ pub fn job_pathfinding_system(
.filter_map(|(entity, queue, state, transform, _)| {
total_dorfs += 1;
if locked_dorfs.contains(&entity) {
if locked_dorfs.contains(&entity) || assigned_this_frame.contains(&entity) {
locked_count += 1;
return None;
}
@@ -88,6 +92,12 @@ pub fn job_pathfinding_system(
let pos = transform.translation.as_ivec3();
if !tilemap.is_standable(pos) {
not_standable_count += 1;
info!(
"[PATHFIND] Dorf {:?} NOT STANDABLE at pos={:?} z_level={}",
entity,
pos,
pos.z / crate::constants::ITILE_SIZE
);
return None;
}
@@ -296,6 +306,7 @@ pub fn job_pathfinding_system(
"[PATHFIND] SUCCESS: Assigned job {:?} to dorf {:?} with approach {:?}",
job_id, dorf_entity, approach_target
);
assigned_this_frame.insert(dorf_entity);
}
}
} else {