Fix: Allow dorfs running Idle task to be job candidates

The bug: We excluded ALL Active state dorfs, but Idle tasks get
immediately promoted from Pending to Active by task_executor_system.
So by the time job_pathfinding runs, all dorfs are Active with Idle.

The fix: Check if dorf is 'busy' = Active AND non-Idle task.
Dorfs with Idle tasks (even in Active state) can be interrupted
for real jobs.
This commit is contained in:
2026-04-04 11:53:29 +01:00
parent 196ff9cec4
commit 7cf1b83427
+16 -14
View File
@@ -73,8 +73,7 @@ pub fn job_pathfinding_system(
let mut total_dorfs = 0;
let mut locked_count = 0;
let mut not_standable_count = 0;
let mut not_idle_count = 0;
let mut active_count = 0;
let mut busy_count = 0; // Truly busy: Active AND non-Idle
let candidate_dorfs: Vec<(Entity, IVec3)> = dorf_query
.iter_mut()
@@ -92,23 +91,22 @@ pub fn job_pathfinding_system(
return None;
}
// Check if dorf is idle: queue is empty OR current task is Idle
// A dorf is available if:
// 1. Queue is empty, OR
// 2. Current task is Idle (we can replace it)
let current_task = queue.current();
let is_idle = queue.is_empty()
|| current_task
.map(|t| matches!(t, Task::Idle { .. }))
.unwrap_or(false);
if !is_idle {
not_idle_count += 1;
return None;
}
// Allow Pending state (about to run) OR Completed/Failed states
// Only exclude Active dorfs (currently executing a task)
// A dorf is "busy" if they're Active AND doing non-Idle work
// We can interrupt Idle tasks but not other tasks
let state_val: &TaskState = &*state;
if matches!(state_val, TaskState::Active) {
active_count += 1;
let is_busy = matches!(state_val, TaskState::Active) && !is_idle;
if is_busy {
busy_count += 1;
return None;
}
@@ -117,8 +115,12 @@ pub fn job_pathfinding_system(
.collect();
info!(
"[PATHFIND] Dorfs: total={} locked={} not_standable={} not_idle={} active={} candidates={}",
total_dorfs, locked_count, not_standable_count, not_idle_count, active_count, candidate_dorfs.len()
"[PATHFIND] Dorfs: total={} locked={} not_standable={} busy={} candidates={}",
total_dorfs,
locked_count,
not_standable_count,
busy_count,
candidate_dorfs.len()
);
if candidate_dorfs.is_empty() {