Merge pull request #275 from eswald/stockflow-40

Stockflow Improvements
develop
Quietust 2014-08-14 16:33:46 -05:00
commit 28d89db1fd
4 changed files with 68 additions and 21 deletions

@ -2433,7 +2433,8 @@ instantly duplicates the job.</li>
</div> </div>
<div class="section" id="stockflow"> <div class="section" id="stockflow">
<h3><a class="toc-backref" href="#id109">stockflow</a></h3> <h3><a class="toc-backref" href="#id109">stockflow</a></h3>
<p>Allows the fortress bookkeeper to queue jobs through the manager.</p> <p>Allows the fortress bookkeeper to queue jobs through the manager,
based on space or items available in stockpiles.</p>
<p>Usage:</p> <p>Usage:</p>
<blockquote> <blockquote>
<dl class="docutils"> <dl class="docutils">

@ -1478,7 +1478,8 @@ Duplicate the selected job in a workshop:
stockflow stockflow
--------- ---------
Allows the fortress bookkeeper to queue jobs through the manager. Allows the fortress bookkeeper to queue jobs through the manager,
based on space or items available in stockpiles.
Usage: Usage:
@ -1486,12 +1487,15 @@ Usage:
Enable the plugin. Enable the plugin.
``stockflow disable`` ``stockflow disable``
Disable the plugin. Disable the plugin.
``stockflow fast``
Enable the plugin in fast mode.
``stockflow list`` ``stockflow list``
List any work order settings for your stockpiles. List any work order settings for your stockpiles.
``stockflow status`` ``stockflow status``
Display whether the plugin is enabled. Display whether the plugin is enabled.
While enabled, the 'q' menu of each stockpile will have two new options: While enabled, the 'q' menu of each stockpile will have two new options:
* j: Select a job to order, from an interface like the manager's screen. * j: Select a job to order, from an interface like the manager's screen.
* J: Cycle between several options for how many such jobs to order. * J: Cycle between several options for how many such jobs to order.
@ -1499,6 +1503,9 @@ Whenever the bookkeeper updates stockpile records, new work orders will
be placed on the manager's queue for each such selection, reduced by the be placed on the manager's queue for each such selection, reduced by the
number of identical orders already in the queue. number of identical orders already in the queue.
In fast mode, new work orders will be enqueued once per day, instead of
waiting for the bookkeeper.
workflow workflow
-------- --------
Manage control of repeat jobs. Manage control of repeat jobs.

@ -19,8 +19,6 @@ triggers = {
{name = "Never"}, {name = "Never"},
} }
local job_types = df.job_type
entry_ints = { entry_ints = {
stockpile_id = 1, stockpile_id = 1,
order_number = 2, order_number = 2,
@ -75,7 +73,7 @@ end
-- Save the stockpile jobs for later creation. -- Save the stockpile jobs for later creation.
-- Called when the bookkeeper starts updating stockpile records. -- Called when the bookkeeper starts updating stockpile records.
function start_bookkeeping() function start_bookkeeping()
result = {} local result = {}
for reaction_id, quantity in pairs(check_stockpiles()) do for reaction_id, quantity in pairs(check_stockpiles()) do
local amount = order_quantity(reaction_list[reaction_id].order, quantity) local amount = order_quantity(reaction_list[reaction_id].order, quantity)
if amount > 0 then if amount > 0 then
@ -123,11 +121,22 @@ function collect_orders()
local spid = entry.ints[entry_ints.stockpile_id] local spid = entry.ints[entry_ints.stockpile_id]
local stockpile = utils.binsearch(stockpiles, spid, "id") local stockpile = utils.binsearch(stockpiles, spid, "id")
if stockpile then if stockpile then
-- Todo: What if entry.value ~= reaction_list[order_number].name? local order_number = entry.ints[entry_ints.order_number]
result[spid] = { if reaction_list[order_number] and entry.value == reaction_list[order_number].name then
stockpile = stockpile, result[spid] = {
entry = entry, stockpile = stockpile,
} entry = entry,
}
else
-- It might be worth searching reaction_list for the name.
-- Then again, this should only happen in unusual situations.
print("Mismatched stockflow entry for stockpile #"..stockpile.stockpile_number..": "..entry.value.." ("..order_number..")")
end
else
-- The stockpile no longer exists.
-- Perhaps it has been deleted, or perhaps this is a different fortress.
-- print("Missing stockflow pile "..spid)
entry:delete()
end end
end end
end end
@ -203,6 +212,7 @@ end
function clothing_reactions(reactions, mat_info, filter) function clothing_reactions(reactions, mat_info, filter)
local resources = df.historical_entity.find(df.global.ui.civ_id).resources local resources = df.historical_entity.find(df.global.ui.civ_id).resources
local itemdefs = df.global.world.raws.itemdefs local itemdefs = df.global.world.raws.itemdefs
local job_types = df.job_type
resource_reactions(reactions, job_types.MakeArmor, mat_info, resources.armor_type, itemdefs.armor, {permissible = filter}) resource_reactions(reactions, job_types.MakeArmor, mat_info, resources.armor_type, itemdefs.armor, {permissible = filter})
resource_reactions(reactions, job_types.MakePants, mat_info, resources.pants_type, itemdefs.pants, {permissible = filter}) resource_reactions(reactions, job_types.MakePants, mat_info, resources.pants_type, itemdefs.pants, {permissible = filter})
resource_reactions(reactions, job_types.MakeGloves, mat_info, resources.gloves_type, itemdefs.gloves, {permissible = filter}) resource_reactions(reactions, job_types.MakeGloves, mat_info, resources.gloves_type, itemdefs.gloves, {permissible = filter})
@ -218,6 +228,12 @@ function collect_reactions()
-- Even that list doesn't seem to include their names. -- Even that list doesn't seem to include their names.
local result = {} local result = {}
-- A few task types are obsolete in newer DF versions.
local v34 = string.match(dfhack.getDFVersion(), "v0.34")
-- Caching the enumeration might not be important, but saves lookups.
local job_types = df.job_type
local materials = { local materials = {
rock = { rock = {
adjective = "rock", adjective = "rock",
@ -320,7 +336,7 @@ function collect_reactions()
table.insert(result, reaction_entry(job_types.DyeCloth)) table.insert(result, reaction_entry(job_types.DyeCloth))
-- Sew Image -- Sew Image
cloth_mats = {materials.cloth, materials.silk, materials.yarn, materials.leather} local cloth_mats = {materials.cloth, materials.silk, materials.yarn, materials.leather}
for _, material in ipairs(cloth_mats) do for _, material in ipairs(cloth_mats) do
material_reactions(result, {{job_types.SewImage, "Sew", "Image"}}, material) material_reactions(result, {{job_types.SewImage, "Sew", "Image"}}, material)
end end
@ -340,8 +356,10 @@ function collect_reactions()
table.insert(result, reaction_entry(job_types.PrepareMeal, {mat_type = 3}, "Prepare Fine Meal")) table.insert(result, reaction_entry(job_types.PrepareMeal, {mat_type = 3}, "Prepare Fine Meal"))
table.insert(result, reaction_entry(job_types.PrepareMeal, {mat_type = 4}, "Prepare Lavish Meal")) table.insert(result, reaction_entry(job_types.PrepareMeal, {mat_type = 4}, "Prepare Lavish Meal"))
-- Brew Drink if v34 then
table.insert(result, reaction_entry(job_types.BrewDrink)) -- Brew Drink
table.insert(result, reaction_entry(job_types.BrewDrink))
end
-- Weaving -- Weaving
table.insert(result, reaction_entry(job_types.WeaveCloth, {material_category = {plant = true}}, "Weave Thread into Cloth")) table.insert(result, reaction_entry(job_types.WeaveCloth, {material_category = {plant = true}}, "Weave Thread into Cloth"))
@ -359,7 +377,9 @@ function collect_reactions()
table.insert(result, reaction_entry(job_types.SpinThread)) table.insert(result, reaction_entry(job_types.SpinThread))
table.insert(result, reaction_entry(job_types.MakeLye)) table.insert(result, reaction_entry(job_types.MakeLye))
table.insert(result, reaction_entry(job_types.ProcessPlants)) table.insert(result, reaction_entry(job_types.ProcessPlants))
table.insert(result, reaction_entry(job_types.ProcessPlantsBag)) if v34 then
table.insert(result, reaction_entry(job_types.ProcessPlantsBag))
end
table.insert(result, reaction_entry(job_types.ProcessPlantsVial)) table.insert(result, reaction_entry(job_types.ProcessPlantsVial))
table.insert(result, reaction_entry(job_types.ProcessPlantsBarrel)) table.insert(result, reaction_entry(job_types.ProcessPlantsBarrel))
table.insert(result, reaction_entry(job_types.MakeCharcoal)) table.insert(result, reaction_entry(job_types.MakeCharcoal))
@ -656,7 +676,7 @@ function collect_reactions()
end end
-- Boxes, Bags, and Ropes -- Boxes, Bags, and Ropes
boxmats = { local boxmats = {
{mats = {materials.wood}, box = "Chest"}, {mats = {materials.wood}, box = "Chest"},
{mats = {materials.rock}, box = "Coffer"}, {mats = {materials.rock}, box = "Coffer"},
{mats = glasses, box = "Box", flask = "Vial"}, {mats = glasses, box = "Box", flask = "Vial"},

@ -31,12 +31,15 @@ DFHACK_PLUGIN_IS_ENABLED(enabled);
bool enabled = false; bool enabled = false;
#endif #endif
bool fast = false;
const char *tagline = "Allows the fortress bookkeeper to queue jobs through the manager."; const char *tagline = "Allows the fortress bookkeeper to queue jobs through the manager.";
const char *usage = ( const char *usage = (
" stockflow enable\n" " stockflow enable\n"
" Enable the plugin.\n" " Enable the plugin.\n"
" stockflow disable\n" " stockflow disable\n"
" Disable the plugin.\n" " Disable the plugin.\n"
" stockflow fast\n"
" Enable the plugin in fast mode.\n"
" stockflow list\n" " stockflow list\n"
" List any work order settings for your stockpiles.\n" " List any work order settings for your stockpiles.\n"
" stockflow status\n" " stockflow status\n"
@ -49,6 +52,9 @@ const char *usage = (
"Whenever the bookkeeper updates stockpile records, new work orders will\n" "Whenever the bookkeeper updates stockpile records, new work orders will\n"
"be placed on the manager's queue for each such selection, reduced by the\n" "be placed on the manager's queue for each such selection, reduced by the\n"
"number of identical orders already in the queue.\n" "number of identical orders already in the queue.\n"
"\n"
"In fast mode, new work orders will be enqueued once per day, instead of\n"
"waiting for the bookkeeper.\n"
); );
/* /*
@ -59,11 +65,19 @@ class LuaHelper {
public: public:
void cycle(color_ostream &out) { void cycle(color_ostream &out) {
bool found = false; bool found = false;
for (df::job_list_link* link = &df::global::world->job_list; link != NULL; link = link->next) {
if (link->item == NULL) continue; if (fast) {
if (link->item->job_type == job_type::UpdateStockpileRecords) { // Ignore the bookkeeper; either gather or enqueue orders every cycle.
found = true; found = !bookkeeping;
break; } else {
// Gather orders when the bookkeeper starts updating stockpile records,
// and enqueue them when the job is done.
for (df::job_list_link* link = &df::global::world->job_list; link != NULL; link = link->next) {
if (link->item == NULL) continue;
if (link->item->job_type == job_type::UpdateStockpileRecords) {
found = true;
break;
}
} }
} }
@ -307,8 +321,13 @@ static command_result stockflow_cmd(color_ostream &out, vector <string> & parame
if (parameters.size() == 1) { if (parameters.size() == 1) {
if (parameters[0] == "enable" || parameters[0] == "on" || parameters[0] == "1") { if (parameters[0] == "enable" || parameters[0] == "on" || parameters[0] == "1") {
desired = true; desired = true;
fast = false;
} else if (parameters[0] == "disable" || parameters[0] == "off" || parameters[0] == "0") { } else if (parameters[0] == "disable" || parameters[0] == "off" || parameters[0] == "0") {
desired = false; desired = false;
fast = false;
} else if (parameters[0] == "fast" || parameters[0] == "always" || parameters[0] == "2") {
desired = true;
fast = true;
} else if (parameters[0] == "usage" || parameters[0] == "help" || parameters[0] == "?") { } else if (parameters[0] == "usage" || parameters[0] == "help" || parameters[0] == "?") {
out.print("%s: %s\nUsage:\n%s", name, tagline, usage); out.print("%s: %s\nUsage:\n%s", name, tagline, usage);
return CR_OK; return CR_OK;
@ -338,7 +357,7 @@ static command_result stockflow_cmd(color_ostream &out, vector <string> & parame
} }
} }
out.print("Stockflow is %s %s.\n", (desired == enabled)? "currently": "now", desired? "enabled": "disabled"); out.print("Stockflow is %s %s%s.\n", (desired == enabled)? "currently": "now", desired? "enabled": "disabled", fast? ", in fast mode": "");
enabled = desired; enabled = desired;
return CR_OK; return CR_OK;
} }