static void push_matinfo(lua_State *state, MaterialInfo &info) { if (!info.isValid()) { lua_pushnil(state); return; } lua_newtable(state); lua_pushvalue(state, lua_upvalueindex(1)); lua_setmetatable(state, -2); lua_pushinteger(state, info.type); lua_setfield(state, -2, "type"); lua_pushinteger(state, info.index); lua_setfield(state, -2, "index"); #define SETOBJ(name) { \ Lua::PushDFObject(state, info.name); \ lua_setfield(state, -2, #name); \ } SETOBJ(material); if (info.plant) SETOBJ(plant); if (info.creature) SETOBJ(creature); if (info.inorganic) SETOBJ(inorganic); if (info.figure) SETOBJ(figure); #undef SETOBJ if (info.mode != MaterialInfo::Builtin) { lua_pushinteger(state, info.subtype); lua_setfield(state, -2, "subtype"); } const char *id = "builtin"; switch (info.mode) { case MaterialInfo::Plant: id = "plant"; break; case MaterialInfo::Creature: id = "creature"; break; case MaterialInfo::Inorganic: id = "inorganic"; break; default: break; } lua_pushstring(state, id); lua_setfield(state, -2, "mode"); }
static std::string shortJobDescription(df::job *job) { std::string rv = stl_sprintf("job %d: ", job->id); if (job->job_type != job_type::CustomReaction) rv += ENUM_KEY_STR(job_type, job->job_type); else rv += job->reaction_name; MaterialInfo mat; df::dfhack_material_category mat_mask; guess_job_material(job, mat, mat_mask); if (mat.isValid()) rv += " [" + mat.toString() + "]"; else if (mat_mask.whole) rv += " [" + bitfield_to_string(mat_mask) + "]"; return rv; }
static void guess_job_material(df::job *job, MaterialInfo &mat, df::dfhack_material_category &mat_mask) { using namespace df::enums::job_type; if (job->job_type == PrepareMeal) mat.decode(-1); else mat.decode(job); mat_mask.whole = job->material_category.whole; // Material from the job enum const char *job_material = ENUM_ATTR(job_type, material, job->job_type); if (job_material) { MaterialInfo info; if (info.findBuiltin(job_material)) mat = info; else parseJobMaterialCategory(&mat_mask, job_material); } // Material from the job reagent if (!mat.isValid() && !job->job_items.empty() && (job->job_items.size() == 1 || job->job_items[0]->item_type == item_type::PLANT)) { mat.decode(job->job_items[0]); switch (job->job_items[0]->item_type) { case item_type::WOOD: mat_mask.bits.wood = mat_mask.bits.wood2 = true; break; default: break; } } }
void DFHack::describeMaterial(BasicMaterialInfo *info, const MaterialInfo &mat, const BasicMaterialInfoMask *mask) { assert(mat.isValid()); info->set_type(mat.type); info->set_index(mat.index); describeMaterial(info, mat.material, mask); switch (mat.mode) { case MaterialInfo::Inorganic: info->set_token(mat.inorganic->id); if (mask && mask->flags()) flagarray_to_ints(info->mutable_inorganic_flags(), mat.inorganic->flags); break; case MaterialInfo::Creature: info->set_subtype(mat.subtype); if (mat.figure) { info->set_histfig_id(mat.index); info->set_creature_id(mat.figure->race); } else info->set_creature_id(mat.index); break; case MaterialInfo::Plant: info->set_plant_id(mat.index); break; default: break; } }
static ItemConstraint *get_constraint(color_ostream &out, const std::string &str, PersistentDataItem *cfg) { std::vector<std::string> tokens; split_string(&tokens, str, "/"); if (tokens.size() > 4) return NULL; int weight = 0; bool is_craft = false; ItemTypeInfo item; if (tokens[0] == "ANY_CRAFT" || tokens[0] == "CRAFTS") { is_craft = true; } else if (!item.find(tokens[0]) || !item.isValid()) { out.printerr("Cannot find item type: %s\n", tokens[0].c_str()); return NULL; } if (item.subtype >= 0) weight += 10000; df::dfhack_material_category mat_mask; std::string maskstr = vector_get(tokens,1); if (!maskstr.empty() && !parseJobMaterialCategory(&mat_mask, maskstr)) { out.printerr("Cannot decode material mask: %s\n", maskstr.c_str()); return NULL; } if (mat_mask.whole != 0) weight += 100; MaterialInfo material; std::string matstr = vector_get(tokens,2); if (!matstr.empty() && (!material.find(matstr) || !material.isValid())) { out.printerr("Cannot find material: %s\n", matstr.c_str()); return NULL; } item_quality::item_quality minqual = item_quality::Ordinary; std::string qualstr = vector_get(tokens, 3); if(!qualstr.empty()) { if(qualstr == "ordinary") minqual = item_quality::Ordinary; else if(qualstr == "wellcrafted") minqual = item_quality::WellCrafted; else if(qualstr == "finelycrafted") minqual = item_quality::FinelyCrafted; else if(qualstr == "superior") minqual = item_quality::Superior; else if(qualstr == "exceptional") minqual = item_quality::Exceptional; else if(qualstr == "masterful") minqual = item_quality::Masterful; else { out.printerr("Cannot find quality: %s\nKnown qualities: ordinary, wellcrafted, finelycrafted, superior, exceptional, masterful\n", qualstr.c_str()); return NULL; } } if (material.type >= 0) weight += (material.index >= 0 ? 5000 : 1000); if (mat_mask.whole && material.isValid() && !material.matches(mat_mask)) { out.printerr("Material %s doesn't match mask %s\n", matstr.c_str(), maskstr.c_str()); return NULL; } for (size_t i = 0; i < constraints.size(); i++) { ItemConstraint *ct = constraints[i]; if (ct->is_craft == is_craft && ct->item == item && ct->material == material && ct->mat_mask.whole == mat_mask.whole && ct->min_quality == minqual) return ct; } ItemConstraint *nct = new ItemConstraint; nct->is_craft = is_craft; nct->item = item; nct->material = material; nct->mat_mask = mat_mask; nct->min_quality = minqual; nct->weight = weight; if (cfg) nct->config = *cfg; else { nct->config = Core::getInstance().getWorld()->AddPersistentData("workflow/constraints"); nct->init(str); } constraints.push_back(nct); return nct; }
static ItemConstraint *get_constraint(Core *c, const std::string &str, PersistentDataItem *cfg) { std::vector<std::string> tokens; split_string(&tokens, str, "/"); if (tokens.size() > 3) return NULL; int weight = 0; ItemTypeInfo item; if (!item.find(tokens[0]) || !item.isValid()) { c->con.printerr("Cannot find item type: %s\n", tokens[0].c_str()); return NULL; } if (item.subtype >= 0) weight += 10000; df::dfhack_material_category mat_mask; std::string maskstr = vector_get(tokens,1); if (!maskstr.empty() && !parseJobMaterialCategory(&mat_mask, maskstr)) { c->con.printerr("Cannot decode material mask: %s\n", maskstr.c_str()); return NULL; } if (mat_mask.whole != 0) weight += 100; MaterialInfo material; std::string matstr = vector_get(tokens,2); if (!matstr.empty() && (!material.find(matstr) || !material.isValid())) { c->con.printerr("Cannot find material: %s\n", matstr.c_str()); return NULL; } if (material.type >= 0) weight += (material.index >= 0 ? 5000 : 1000); if (mat_mask.whole && material.isValid() && !material.matches(mat_mask)) { c->con.printerr("Material %s doesn't match mask %s\n", matstr.c_str(), maskstr.c_str()); return NULL; } for (size_t i = 0; i < constraints.size(); i++) { ItemConstraint *ct = constraints[i]; if (ct->item == item && ct->material == material && ct->mat_mask.whole == mat_mask.whole) return ct; } ItemConstraint *nct = new ItemConstraint; nct->item = item; nct->material = material; nct->mat_mask = mat_mask; nct->weight = weight; if (cfg) nct->config = *cfg; else { nct->config = c->getWorld()->AddPersistentData("workflow/constraints"); nct->init(str); } constraints.push_back(nct); return nct; }
static command_result job_cmd(Core * c, vector <string> & parameters) { CoreSuspender suspend(c); std::string cmd = (parameters.empty() ? "query" : parameters[0]); if (cmd == "query" || cmd == "list") { df::job *job = getSelectedJob(c); if (!job) return CR_WRONG_USAGE; if (cmd == "query") { printJobDetails(c, job); } else { if (!workshop_job_hotkey(c, c->getTopViewscreen())) return CR_WRONG_USAGE; df::building *selected = world->selected_building; for (size_t i = 0; i < selected->jobs.size(); i++) printJobDetails(c, selected->jobs[i]); } } else if (cmd == "item-material") { if (parameters.size() != 3) return CR_WRONG_USAGE; df::job *job = getSelectedJob(c); df::job_item *item = getJobItem(c, job, parameters[1]); if (!item) return CR_WRONG_USAGE; ItemTypeInfo iinfo(item); MaterialInfo minfo; if (!minfo.find(parameters[2])) { c->con.printerr("Could not find the specified material.\n"); return CR_FAILURE; } if (minfo.isValid() && !iinfo.matches(*item, &minfo)) { c->con.printerr("Material does not match the requirements.\n"); printJobDetails(c, job); return CR_FAILURE; } if (job->mat_type != -1 && job->mat_type == item->mat_type && job->mat_index == item->mat_index) { job->mat_type = minfo.type; job->mat_index = minfo.index; } item->mat_type = minfo.type; item->mat_index = minfo.index; c->con << "Job item updated." << endl; if (item->item_type < 0 && minfo.isValid()) c->con.printerr("WARNING: Due to a probable bug, creature & plant material subtype\n" " is ignored unless the item type is also specified.\n"); printJobDetails(c, job); return CR_OK; } else if (cmd == "item-type") { if (parameters.size() != 3) return CR_WRONG_USAGE; df::job *job = getSelectedJob(c); df::job_item *item = getJobItem(c, job, parameters[1]); if (!item) return CR_WRONG_USAGE; ItemTypeInfo iinfo; MaterialInfo minfo(item); if (!iinfo.find(parameters[2])) { c->con.printerr("Could not find the specified item type.\n"); return CR_FAILURE; } if (iinfo.isValid() && !iinfo.matches(*item, &minfo)) { c->con.printerr("Item type does not match the requirements.\n"); printJobDetails(c, job); return CR_FAILURE; } item->item_type = iinfo.type; item->item_subtype = iinfo.subtype; c->con << "Job item updated." << endl; printJobDetails(c, job); return CR_OK; } else return CR_WRONG_USAGE; return CR_OK; }
static command_result job_material_in_job(Core *c, MaterialInfo &new_mat) { df::job *job = getSelectedWorkshopJob(c); if (!job) return CR_FAILURE; if (!new_mat.isValid() || new_mat.type != 0) { c->con.printerr("New job material isn't inorganic: %s\n", new_mat.toString().c_str()); return CR_FAILURE; } MaterialInfo cur_mat(job); if (!cur_mat.isValid() || cur_mat.type != 0) { c->con.printerr("Current job material isn't inorganic: %s\n", cur_mat.toString().c_str()); return CR_FAILURE; } df::craft_material_class old_class = cur_mat.getCraftClass(); if (old_class == craft_material_class::None) { c->con.printerr("Unexpected current material type: %s\n", cur_mat.toString().c_str()); return CR_FAILURE; } if (new_mat.getCraftClass() != old_class) { c->con.printerr("New material %s does not satisfy requirement: %s\n", new_mat.toString().c_str(), ENUM_KEY_STR(craft_material_class, old_class)); return CR_FAILURE; } for (size_t i = 0; i < job->job_items.size(); i++) { df::job_item *item = job->job_items[i]; MaterialInfo item_mat(item); if (item_mat != cur_mat) { c->con.printerr("Job item %d has different material: %s\n", i, item_mat.toString().c_str()); return CR_FAILURE; } if (!new_mat.matches(*item)) { c->con.printerr("Job item %d requirements not satisfied by %s.\n", i, new_mat.toString().c_str()); return CR_FAILURE; } } // Apply the substitution job->mat_type = new_mat.type; job->mat_index = new_mat.index; for (size_t i = 0; i < job->job_items.size(); i++) { df::job_item *item = job->job_items[i]; item->mat_type = new_mat.type; item->mat_index = new_mat.index; } c->con << "Applied material '" << new_mat.toString() << "' to job " << ENUM_KEY_STR(job_type,job->job_type) << endl; return CR_OK; }