From 857058752ba56321024e08244dd004347ad55cf5 Mon Sep 17 00:00:00 2001 From: Kelly Kinkade Date: Wed, 29 Jun 2016 14:54:03 -0500 Subject: [PATCH] labormanager: rework for better behavior with 43.03 The main thing here is that the process loop exits if the DF process_job or process_dig flags are set since if these are set the job list is going to change soon anyway. The plugin also sets these flags when it changes any labors, which has the side effect of effectively disabling the process loop while DF is paused, which prevents flapping while editing job preferences in-game, and also allows changing job preferences in game (although such changes may not last when the clock starts up again). --- plugins/devel/labormanager.cpp | 78 +++++++++++++++++++--------------- 1 file changed, 43 insertions(+), 35 deletions(-) diff --git a/plugins/devel/labormanager.cpp b/plugins/devel/labormanager.cpp index d78d06b97..8d614ed36 100644 --- a/plugins/devel/labormanager.cpp +++ b/plugins/devel/labormanager.cpp @@ -528,23 +528,6 @@ struct dwarf_info_t { } - - void set_labor(df::unit_labor labor) - { - if (labor >= 0 && labor <= ENUM_LAST_ITEM(unit_labor)) - { - dwarf->status.labors[labor] = true; - } - } - - void clear_labor(df::unit_labor labor) - { - if (labor >= 0 && labor <= ENUM_LAST_ITEM(unit_labor)) - { - dwarf->status.labors[labor] = false; - } - } - }; /* @@ -1621,6 +1604,8 @@ private: int plant_count; int detail_count; + bool labors_changed; + int tool_count[TOOLS_MAX]; bool reequip_needed[TOOLS_MAX]; @@ -1647,11 +1632,23 @@ private: std::list busy_dwarfs; private: + void set_labor (dwarf_info_t* dwarf, df::unit_labor labor, bool value) + { + if (labor >= 0 && labor <= ENUM_LAST_ITEM(unit_labor)) + { + bool old = dwarf->dwarf->status.labors[labor]; + dwarf->dwarf->status.labors[labor] = value; + if (old != value) + labors_changed = true; + } + } + void scan_buildings() { has_butchers = false; has_fishery = false; trader_requested = false; + labors_changed = false; for (auto b = world->buildings.all.begin(); b != world->buildings.all.end(); b++) { @@ -1821,10 +1818,10 @@ private: } df::unit_labor labor = labor_mapper->find_job_labor (j); - labor_needed[labor]++; if (labor != df::unit_labor::NONE) { + labor_needed[labor]++; if (worker == -1) { if (j->pos.isValid()) @@ -2088,7 +2085,7 @@ private: if (labor == unit_labor::NONE) continue; - dwarf->clear_labor(labor); + set_labor(dwarf, labor, false); } } else { if (state == IDLE) @@ -2152,6 +2149,9 @@ private: public: void process() { + if (*df::global::process_dig || *df::global::process_jobs) + return; + release_dwarf_list(); dig_count = tree_count = plant_count = detail_count = 0; @@ -2266,6 +2266,9 @@ public: /* set requirements to zero for labors with currently idle dwarfs, and remove from requirement dwarfs actually working */ FOR_ENUM_ITEMS(unit_labor, l) { + if (l == df::unit_labor::NONE) + continue; + if (labor_infos[l].idle_dwarfs > 0) labor_needed[l] = 0; else @@ -2309,10 +2312,7 @@ public: if (l == df::unit_labor::NONE) continue; - if (l == df::unit_labor::HAUL_FOOD) - (*bestdwarf)->set_labor(l); - else - (*bestdwarf)->clear_labor(l); + set_labor (*bestdwarf, l, l == df::unit_labor::HAUL_FOOD); } available_dwarfs.erase(bestdwarf); @@ -2337,7 +2337,7 @@ public: for (auto i = labor_needed.begin(); i != labor_needed.end(); i++) { df::unit_labor l = i->first; - if (l == df::unit_labor::NONE) + if (l == df::unit_labor::NONE) continue; if (labor_infos[l].maximum_dwarfs() > 0 && @@ -2394,7 +2394,7 @@ public: std::list::iterator bestdwarf = available_dwarfs.begin(); int best_score = INT_MIN; - df::unit_labor best_labor = df::unit_labor::CLEAN; + df::unit_labor best_labor = df::unit_labor::NONE; for (auto j = to_assign.begin(); j != to_assign.end(); j++) { @@ -2416,6 +2416,9 @@ public: } } + if (best_labor == df::unit_labor::NONE) + break; + if (print_debug) out.print("assign \"%s\" labor %s score=%d\n", (*bestdwarf)->dwarf->name.first_name.c_str(), ENUM_KEY_STR(unit_labor, best_labor).c_str(), best_score); @@ -2426,7 +2429,7 @@ public: if (l == best_labor) { - (*bestdwarf)->set_labor(l); + set_labor(*bestdwarf, l, true); tools_enum t = default_labor_infos[l].tool; if (t != TOOL_NONE) { @@ -2436,7 +2439,7 @@ public: } } else if ((*bestdwarf)->state == IDLE) - (*bestdwarf)->clear_labor(l); + set_labor(*bestdwarf, l, false); } if (best_labor == df::unit_labor::HAUL_FOOD && priority_food > 0) @@ -2479,7 +2482,7 @@ public: tools_enum t = default_labor_infos[l].tool; if (t == TOOL_NONE || (*d)->has_tool[t]) { - (*d)->set_labor (l); + set_labor(*d, l, true); if (print_debug) out.print("assign \"%s\" extra labor %s score=%d current %s score=%d\n", (*d)->dwarf->name.first_name.c_str(), @@ -2507,12 +2510,12 @@ public: { if (l >= df::unit_labor::HAUL_STONE && l <= df::unit_labor::HAUL_ANIMALS && canary & (1 << l)) - canary_dwarf->set_labor(l); + set_labor(canary_dwarf, l, true); } /* Also set the canary to remove constructions, because we have no way yet to tell if there are constructions needing removal */ - canary_dwarf->set_labor(df::unit_labor::REMOVE_CONSTRUCTION); + set_labor(canary_dwarf, df::unit_labor::REMOVE_CONSTRUCTION, true); if (print_debug) out.print ("Setting %s as the hauling canary\n", canary_dwarf->dwarf->name.first_name.c_str()); @@ -2531,11 +2534,12 @@ public: { if (l >= df::unit_labor::HAUL_STONE && l <= df::unit_labor::HAUL_ANIMALS && canary & (1 << l)) - (*d)->set_labor(l); + set_labor(*d, l, true); + else if (l == df::unit_labor::CLEAN || l == df::unit_labor::REMOVE_CONSTRUCTION) + set_labor(*d, l, true); + else + set_labor(*d, l, false); } - - (*d)->set_labor(df::unit_labor::CLEAN); - (*d)->set_labor(df::unit_labor::REMOVE_CONSTRUCTION); } /* set reequip on any dwarfs who are carrying tools needed by others */ @@ -2558,7 +2562,11 @@ public: release_dwarf_list(); - *df::global::process_jobs = true; + if (labors_changed) + { + *df::global::process_dig = true; + *df::global::process_jobs = true; + } print_debug = 0;