static void start_protect(color_ostream &out) { check_lost_jobs(out, 0); if (!known_jobs.empty()) out.print("Protecting %d jobs.\n", known_jobs.size()); }
static void map_job_constraints(color_ostream &out) { melt_active = false; for (size_t i = 0; i < constraints.size(); i++) { constraints[i]->jobs.clear(); constraints[i]->is_active = false; } for (TKnownJobs::const_iterator it = known_jobs.begin(); it != known_jobs.end(); ++it) { ProtectedJob *pj = it->second; pj->constraints.clear(); if (!pj->isLive()) continue; if (!melt_active && pj->actual_job->job_type == job_type::MeltMetalObject) melt_active = pj->isResumed(); compute_job_outputs(out, pj); } }
static void start_protect(Core *c) { check_lost_jobs(c, 0); if (!known_jobs.empty()) c->con.print("Protecting %d jobs.\n", known_jobs.size()); }
static void stop_protect(color_ostream &out) { pending_recover.clear(); if (!known_jobs.empty()) out.print("Unprotecting %d jobs.\n", known_jobs.size()); for (TKnownJobs::iterator it = known_jobs.begin(); it != known_jobs.end(); ++it) delete it->second; known_jobs.clear(); }
static void check_lost_jobs(color_ostream &out, int ticks) { ProtectedJob::cur_tick_idx++; if (ticks < 0) ticks = 0; df::job_list_link *p = world->job_list.next; for (; p; p = p->next) { df::job *job = p->item; ProtectedJob *pj = get_known(job->id); if (pj) { if (!job->flags.bits.repeat) forget_job(out, pj); else pj->tick_job(job, ticks); } else if (job->flags.bits.repeat && isSupportedJob(job)) { pj = new ProtectedJob(job); assert(pj->holder); known_jobs[pj->id] = pj; } } for (TKnownJobs::const_iterator it = known_jobs.begin(); it != known_jobs.end(); ++it) { if (it->second->tick_idx == ProtectedJob::cur_tick_idx || !it->second->isLive()) continue; it->second->actual_job = NULL; pending_recover.push_back(it->second); } }
static void forget_job(color_ostream &out, ProtectedJob *pj) { known_jobs.erase(pj->id); delete pj; }
static ProtectedJob *get_known(int id) { TKnownJobs::iterator it = known_jobs.find(id); return (it != known_jobs.end()) ? it->second : NULL; }
static command_result workflow_cmd(color_ostream &out, vector <string> & parameters) { CoreSuspender suspend; if (!Core::getInstance().isWorldLoaded()) { out.printerr("World is not loaded: please load a game first.\n"); return CR_FAILURE; } if (enabled) { check_lost_jobs(out, 0); recover_jobs(out); update_job_data(out); map_job_constraints(out); map_job_items(out); } df::building *workshop = NULL; //FIXME: unused variable! //df::job *job = NULL; if (Gui::dwarfmode_hotkey(Core::getTopViewscreen()) && ui->main.mode == ui_sidebar_mode::QueryBuilding) { workshop = world->selected_building; //job = Gui::getSelectedWorkshopJob(out, true); } std::string cmd = parameters.empty() ? "list" : parameters[0]; if (cmd == "enable" || cmd == "disable") { bool enable = (cmd == "enable"); if (enable && !enabled) { enable_plugin(out); } else if (!enable && parameters.size() == 1) { if (enabled) { enabled = false; setOptionEnabled(CF_ENABLED, false); stop_protect(out); } out << "The plugin is disabled." << endl; return CR_OK; } for (size_t i = 1; i < parameters.size(); i++) { if (parameters[i] == "drybuckets") setOptionEnabled(CF_DRYBUCKETS, enable); else if (parameters[i] == "auto-melt") setOptionEnabled(CF_AUTOMELT, enable); else return CR_WRONG_USAGE; } if (enabled) out << "The plugin is enabled." << endl; else out << "The plugin is disabled." << endl; if (isOptionEnabled(CF_DRYBUCKETS)) out << "Option drybuckets is enabled." << endl; if (isOptionEnabled(CF_AUTOMELT)) out << "Option auto-melt is enabled." << endl; return CR_OK; } else if (cmd == "count" || cmd == "amount") { if (!enabled) enable_plugin(out); } if (!enabled) out << "Note: the plugin is not enabled." << endl; if (cmd == "jobs") { if (workshop) { for (size_t i = 0; i < workshop->jobs.size(); i++) print_job(out, get_known(workshop->jobs[i]->id)); } else { for (TKnownJobs::iterator it = known_jobs.begin(); it != known_jobs.end(); ++it) if (it->second->isLive()) print_job(out, it->second); } bool pending = false; for (size_t i = 0; i < pending_recover.size(); i++) { if (!workshop || pending_recover[i]->holder == workshop) { if (!pending) { out.print("\nPending recovery:\n"); pending = true; } Job::printJobDetails(out, pending_recover[i]->job_copy); } } return CR_OK; } else if (cmd == "list") { for (size_t i = 0; i < constraints.size(); i++) print_constraint(out, constraints[i]); return CR_OK; } else if (cmd == "list-commands") { for (size_t i = 0; i < constraints.size(); i++) { auto cv = constraints[i]; out << "workflow " << (cv->goalByCount() ? "count " : "amount ") << cv->config.val() << " " << cv->goalCount() << " " << cv->goalGap() << endl; } return CR_OK; } else if (cmd == "count" || cmd == "amount") { if (parameters.size() < 3) return CR_WRONG_USAGE; int limit = atoi(parameters[2].c_str()); if (limit <= 0) { out.printerr("Invalid limit value.\n"); return CR_FAILURE; } ItemConstraint *icv = get_constraint(out, parameters[1]); if (!icv) return CR_FAILURE; icv->setGoalByCount(cmd == "count"); icv->setGoalCount(limit); if (parameters.size() >= 4) icv->setGoalGap(atoi(parameters[3].c_str())); else icv->setGoalGap(-1); process_constraints(out); print_constraint(out, icv); return CR_OK; } else if (cmd == "unlimit") { if (parameters.size() != 2) return CR_WRONG_USAGE; for (size_t i = 0; i < constraints.size(); i++) { if (constraints[i]->config.val() != parameters[1]) continue; delete_constraint(constraints[i]); return CR_OK; } out.printerr("Constraint not found: %s\n", parameters[1].c_str()); return CR_FAILURE; } else if (cmd == "unlimit-all") { if (parameters.size() != 1) return CR_WRONG_USAGE; while (!constraints.empty()) delete_constraint(constraints[0]); out.print("Removed all constraints.\n"); return CR_OK; } else return CR_WRONG_USAGE; }
static void update_jobs_by_constraints(color_ostream &out) { for (TKnownJobs::const_iterator it = known_jobs.begin(); it != known_jobs.end(); ++it) { ProtectedJob *pj = it->second; if (!pj->isLive()) continue; if (pj->actual_job->job_type == job_type::MeltMetalObject && isOptionEnabled(CF_AUTOMELT)) { setJobResumed(out, pj, meltable_count > 0); continue; } if (pj->constraints.empty()) continue; int resume_weight = -1; int suspend_weight = -1; for (size_t i = 0; i < pj->constraints.size(); i++) { if (pj->constraints[i]->request_resume) resume_weight = std::max(resume_weight, pj->constraints[i]->weight); if (pj->constraints[i]->request_suspend) suspend_weight = std::max(suspend_weight, pj->constraints[i]->weight); } bool goal = pj->isResumed(); if (resume_weight >= 0 && resume_weight >= suspend_weight) goal = true; else if (suspend_weight >= 0 && suspend_weight >= resume_weight) goal = false; setJobResumed(out, pj, goal); } for (size_t i = 0; i < constraints.size(); i++) { ItemConstraint *ct = constraints[i]; bool is_running = false; for (size_t j = 0; j < ct->jobs.size(); j++) if (!!(is_running = ct->jobs[j]->isResumed())) break; std::string info = ct->item.toString(); if (ct->is_craft) info = "crafts"; if (ct->material.isValid()) info = ct->material.toString() + " " + info; else if (ct->mat_mask.whole) info = bitfield_to_string(ct->mat_mask) + " " + info; if (is_running != ct->is_active) { if (is_running && ct->request_resume) Gui::showAnnouncement("Resuming production: " + info, 2, false); else if (!is_running && !ct->request_resume) Gui::showAnnouncement("Stopping production: " + info, 3, false); } if (ct->request_resume && !is_running) { if (!ct->cant_resume_reported) Gui::showAnnouncement("Cannot produce: " + info, 6, true); ct->cant_resume_reported = true; } else { ct->cant_resume_reported = false; } } }
static void forget_job(Core *c, ProtectedJob *pj) { known_jobs.erase(pj->id); delete pj; }