Remove the C++ version of the job output deduction code and switch to lua.

develop
Alexander Gavrilov 2012-10-25 12:44:23 +04:00
parent 8eebfa007c
commit 79d2cb1a5c
3 changed files with 44 additions and 167 deletions

@ -79,7 +79,7 @@ keybinding add Alt-P@dwarfmode/Hauling/DefineStop/Cond/Guide gui/guide-path
keybinding add Alt-A@dwarfmode/QueryBuilding/Some/Workshop/Job gui/workshop-job
# workflow front-end
keybinding add Ctrl-W@dwarfmode/QueryBuilding/Some/Workshop/Job gui/workflow
keybinding add Alt-W@dwarfmode/QueryBuilding/Some/Workshop/Job gui/workflow
############################
# UI and game logic tweaks #

@ -64,12 +64,12 @@ function job_outputs.CustomReaction(callback, job)
end
if get_mat_prod then
local p_code = prod.get_material.product_code
local mat = dfhack.matinfo.decode(mat_type, mat_index)
mat_type, mat_index = -1, -1
if mat then
local p_code = prod.get_material.product_code
local rp = mat.material.reaction_product
local idx = utils.linear_index(rp.id, p_code)
if not idx then
@ -77,7 +77,7 @@ function job_outputs.CustomReaction(callback, job)
end
mat_type, mat_index = rp.material.mat_type[idx], rp.material.mat_index[idx]
else
if code == "SOAP_MAT" then
if p_code == "SOAP_MAT" then
mat_mask = { soap = true }
end
end
@ -106,7 +106,7 @@ local function guess_job_material(job)
local jmat = df.job_type.attrs[job.job_type].material
if jmat then
mat_type, mat_index = df.builtin_mats[jmat] or -1, -1
if mat_type < 0 and df.job_material_category[jmat] then
if mat_type < 0 and df.dfhack_material_category[jmat] then
mat_mask = { [jmat] = true }
end
end
@ -220,6 +220,18 @@ local function enum_job_outputs(callback, job)
end
end
function doEnumJobOutputs(native_cb, job)
local function cb(info)
native_cb(
info.item_type, info.item_subtype,
info.mat_mask, info.mat_type, info.mat_index,
info.is_craft
)
end
enum_job_outputs(cb, job)
end
function listJobOutputs(job)
local res = {}
enum_job_outputs(curry(table.insert, res), job)

@ -379,13 +379,6 @@ static bool isSupportedJob(df::job *job)
job->job_type == job_type::CollectSand);
}
static void enumLiveJobs(std::map<int, df::job*> &rv)
{
df::job_list_link *p = world->job_list.next;
for (; p; p = p->next)
rv[p->item->id] = p->item;
}
static bool isOptionEnabled(unsigned flag)
{
return config.isValid() && (config.ival(0) & flag) != 0;
@ -828,71 +821,6 @@ static void link_job_constraint(ProtectedJob *pj, df::item_type itype, int16_t i
}
}
static void compute_custom_job(ProtectedJob *pj, df::job *job)
{
if (pj->reaction_id < 0)
pj->reaction_id = linear_index(df::reaction::get_vector(),
&df::reaction::code, job->reaction_name);
df::reaction *r = df::reaction::find(pj->reaction_id);
if (!r)
return;
for (size_t i = 0; i < r->products.size(); i++)
{
using namespace df::enums::reaction_product_item_flags;
VIRTUAL_CAST_VAR(prod, df::reaction_product_itemst, r->products[i]);
if (!prod || (prod->item_type < (df::item_type)0 && !prod->flags.is_set(CRAFTS)))
continue;
MaterialInfo mat(prod);
df::dfhack_material_category mat_mask(0);
bool get_mat_prod = prod->flags.is_set(GET_MATERIAL_PRODUCT);
if (get_mat_prod || prod->flags.is_set(GET_MATERIAL_SAME))
{
int reagent_idx = linear_index(r->reagents, &df::reaction_reagent::code,
prod->get_material.reagent_code);
if (reagent_idx < 0)
continue;
int item_idx = linear_index(job->job_items, &df::job_item::reagent_index, reagent_idx);
if (item_idx >= 0)
mat.decode(job->job_items[item_idx]);
else
{
VIRTUAL_CAST_VAR(src, df::reaction_reagent_itemst, r->reagents[reagent_idx]);
if (!src)
continue;
mat.decode(src);
}
if (get_mat_prod)
{
std::string code = prod->get_material.product_code;
if (mat.isValid())
{
int idx = linear_index(mat.material->reaction_product.id, code);
if (idx < 0)
continue;
mat.decode(mat.material->reaction_product.material, idx);
}
else
{
if (code == "SOAP_MAT")
mat_mask.bits.soap = true;
}
}
}
link_job_constraint(pj, prod->item_type, prod->item_subtype,
mat_mask, mat.type, mat.index, prod->flags.is_set(CRAFTS));
}
}
static void guess_job_material(df::job *job, MaterialInfo &mat, df::dfhack_material_category &mat_mask)
{
using namespace df::enums::job_type;
@ -934,100 +862,24 @@ static void guess_job_material(df::job *job, MaterialInfo &mat, df::dfhack_mater
}
}
static void compute_job_outputs(color_ostream &out, ProtectedJob *pj)
static int cbEnumJobOutputs(lua_State *L)
{
using namespace df::enums::job_type;
// Custom reactions handled in another function
df::job *job = pj->job_copy;
if (job->job_type == CustomReaction)
{
compute_custom_job(pj, job);
return;
}
// Item type & subtype
df::item_type itype = ENUM_ATTR(job_type, item, job->job_type);
int16_t isubtype = job->item_subtype;
if (itype == item_type::NONE && job->job_type != MakeCrafts)
return;
// Item material & material category
MaterialInfo mat;
df::dfhack_material_category mat_mask;
guess_job_material(job, mat, mat_mask);
// Job-specific code
switch (job->job_type)
{
case SmeltOre:
if (mat.inorganic)
{
std::vector<int16_t> &ores = mat.inorganic->metal_ore.mat_index;
for (size_t i = 0; i < ores.size(); i++)
link_job_constraint(pj, item_type::BAR, -1, 0, 0, ores[i]);
}
return;
auto pj = (ProtectedJob*)lua_touserdata(L, lua_upvalueindex(1));
case ExtractMetalStrands:
if (mat.inorganic)
{
std::vector<int16_t> &threads = mat.inorganic->thread_metal.mat_index;
for (size_t i = 0; i < threads.size(); i++)
link_job_constraint(pj, item_type::THREAD, -1, 0, 0, threads[i]);
}
return;
lua_settop(L, 6);
case PrepareMeal:
if (job->mat_type != -1)
{
std::vector<df::itemdef_foodst*> &food = df::itemdef_foodst::get_vector();
for (size_t i = 0; i < food.size(); i++)
if (food[i]->level == job->mat_type)
link_job_constraint(pj, item_type::FOOD, i, 0, -1, -1);
return;
}
break;
case MakeCrafts:
link_job_constraint(pj, item_type::NONE, -1, mat_mask, mat.type, mat.index, true);
return;
#define PLANT_PROCESS_MAT(flag, tag) \
if (mat.plant && mat.plant->flags.is_set(plant_raw_flags::flag)) \
mat.decode(mat.plant->material_defs.type_##tag, \
mat.plant->material_defs.idx_##tag); \
else mat.decode(-1);
case BrewDrink:
PLANT_PROCESS_MAT(DRINK, drink);
break;
case MillPlants:
PLANT_PROCESS_MAT(MILL, mill);
break;
case ProcessPlants:
PLANT_PROCESS_MAT(THREAD, thread);
break;
case ProcessPlantsBag:
PLANT_PROCESS_MAT(LEAVES, leaves);
break;
case ProcessPlantsBarrel:
PLANT_PROCESS_MAT(EXTRACT_BARREL, extract_barrel);
break;
case ProcessPlantsVial:
PLANT_PROCESS_MAT(EXTRACT_VIAL, extract_vial);
break;
case ExtractFromPlants:
PLANT_PROCESS_MAT(EXTRACT_STILL_VIAL, extract_still_vial);
break;
#undef PLANT_PROCESS_MAT
df::dfhack_material_category mat_mask(0);
if (!lua_isnil(L, 3))
Lua::CheckDFAssign(L, &mat_mask, 3);
default:
break;
}
link_job_constraint(
pj,
(df::item_type)luaL_optint(L, 1, -1), luaL_optint(L, 2, -1),
mat_mask, luaL_optint(L, 4, -1), luaL_optint(L, 5, -1),
lua_toboolean(L, 6)
);
link_job_constraint(pj, itype, isubtype, mat_mask, mat.type, mat.index);
return 0;
}
static void map_job_constraints(color_ostream &out)
@ -1040,19 +892,32 @@ static void map_job_constraints(color_ostream &out)
constraints[i]->is_active = false;
}
auto L = Lua::Core::State;
Lua::StackUnwinder frame(L);
bool ok = Lua::PushModulePublic(out, L, "plugins.workflow", "doEnumJobOutputs");
if (!ok)
out.printerr("The workflow lua module is not available.\n");
for (TKnownJobs::const_iterator it = known_jobs.begin(); it != known_jobs.end(); ++it)
{
ProtectedJob *pj = it->second;
pj->constraints.clear();
if (!pj->isLive())
if (!ok || !pj->isLive())
continue;
if (!melt_active && pj->actual_job->job_type == job_type::MeltMetalObject)
melt_active = pj->isResumed();
compute_job_outputs(out, pj);
// Call the lua module
lua_pushvalue(L, -1);
lua_pushlightuserdata(L, pj);
lua_pushcclosure(L, cbEnumJobOutputs, 1);
Lua::PushDFObject(L, pj->job_copy);
Lua::SafeCall(out, L, 2, 0);
}
}