From bfcaca92663bdabd9621384abeaabb0edaa13761 Mon Sep 17 00:00:00 2001 From: Alexander Gavrilov Date: Mon, 2 Jan 2012 15:18:23 +0400 Subject: [PATCH 01/82] Update xml defs with more ui info. --- Memory.xml | 3 +++ library/include/DataDefs.h | 1 + library/xml | 2 +- 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/Memory.xml b/Memory.xml index 5360d6481..729759445 100644 --- a/Memory.xml +++ b/Memory.xml @@ -1093,6 +1093,7 @@
+
@@ -2343,6 +2344,7 @@
+
cmake @@ -3227,6 +3229,7 @@
+
diff --git a/library/include/DataDefs.h b/library/include/DataDefs.h index 75b2ab2e5..9f3bcf34d 100644 --- a/library/include/DataDefs.h +++ b/library/include/DataDefs.h @@ -178,6 +178,7 @@ namespace df { GLOBAL(d_init,d_init) \ SIMPLE_GLOBAL(ui_look_cursor,int) \ SIMPLE_GLOBAL(ui_workshop_job_cursor,int) \ + SIMPLE_GLOBAL(ui_workshop_in_add,bool) \ GLOBAL(ui_sidebar_menus,ui_sidebar_menus) \ GLOBAL(ui_build_selector,ui_build_selector) \ GLOBAL(ui_look_list,ui_look_list) diff --git a/library/xml b/library/xml index 7a730830c..7b89e5958 160000 --- a/library/xml +++ b/library/xml @@ -1 +1 @@ -Subproject commit 7a730830c515fea701ff73b33cb604f48a4531fc +Subproject commit 7b89e595811ed81b012a805131aa10a89d451e76 From 326c58f7935cb39206c52646a38ff19502ebb966 Mon Sep 17 00:00:00 2001 From: Alexander Gavrilov Date: Mon, 2 Jan 2012 18:46:24 +0400 Subject: [PATCH 02/82] Add a plugin to tweak inorganic materials in jobs. It also auto-seeks in the build item list if used in that context. --- library/MiscUtils.cpp | 27 ++- library/include/DataDefs.h | 4 + library/include/MiscUtils.h | 3 + plugins/CMakeLists.txt | 1 + plugins/jobutils.cpp | 402 ++++++++++++++++++++++++++++++++++++ 5 files changed, 435 insertions(+), 2 deletions(-) create mode 100644 plugins/jobutils.cpp diff --git a/library/MiscUtils.cpp b/library/MiscUtils.cpp index 47deea04c..72e3eae28 100644 --- a/library/MiscUtils.cpp +++ b/library/MiscUtils.cpp @@ -27,8 +27,6 @@ distribution. #include "Core.h" #include "MiscUtils.h" - - #ifndef LINUX_BUILD #include #else @@ -36,6 +34,31 @@ distribution. #include #endif +#include + +std::string stl_sprintf(const char *fmt, ...) { + va_list lst; + va_start(lst, fmt); + std::string rv = stl_vsprintf(fmt, lst); + va_end(lst); + return rv; +} + +std::string stl_vsprintf(const char *fmt, va_list args) { + std::vector buf; + buf.resize(4096); + for (;;) { + int rsz = vsnprintf(&buf[0], buf.size(), fmt, args); + + if (rsz < 0) + buf.resize(buf.size()*2); + else if (unsigned(rsz) > buf.size()) + buf.resize(rsz+1); + else + return std::string(&buf[0], rsz); + } +} + #ifdef LINUX_BUILD // Linux uint64_t GetTimeMs64() { diff --git a/library/include/DataDefs.h b/library/include/DataDefs.h index 9f3bcf34d..d869f12aa 100644 --- a/library/include/DataDefs.h +++ b/library/include/DataDefs.h @@ -111,11 +111,15 @@ namespace DFHack return T::_identity.is_instance(ptr) ? static_cast(ptr) : NULL; } +#define VIRTUAL_CAST_VAR(var,type,input) type *var = virtual_cast(input) + template inline T *strict_virtual_cast(virtual_ptr ptr) { return T::_identity.is_direct_instance(ptr) ? static_cast(ptr) : NULL; } +#define STRICT_VIRTUAL_CAST_VAR(var,type,input) type *var = strict_virtual_cast(input) + void InitDataDefGlobals(Core *core); template diff --git a/library/include/MiscUtils.h b/library/include/MiscUtils.h index 833e74104..8959a766b 100644 --- a/library/include/MiscUtils.h +++ b/library/include/MiscUtils.h @@ -102,3 +102,6 @@ CT *binsearch_in_vector(std::vector &vec, FT CT::*field, AT value) * source: http://stackoverflow.com/questions/1861294/how-to-calculate-execution-time-of-a-code-snippet-in-c */ DFHACK_EXPORT uint64_t GetTimeMs64(); + +DFHACK_EXPORT std::string stl_sprintf(const char *fmt, ...); +DFHACK_EXPORT std::string stl_vsprintf(const char *fmt, va_list args); diff --git a/plugins/CMakeLists.txt b/plugins/CMakeLists.txt index 133905727..d28baeb6f 100644 --- a/plugins/CMakeLists.txt +++ b/plugins/CMakeLists.txt @@ -61,6 +61,7 @@ DFHACK_PLUGIN(initflags initflags.cpp) DFHACK_PLUGIN(stockpiles stockpiles.cpp) DFHACK_PLUGIN(rename rename.cpp) DFHACK_PLUGIN(fixwagons fixwagons.cpp) +DFHACK_PLUGIN(jobutils jobutils.cpp) #DFHACK_PLUGIN(versionosd versionosd.cpp) # this is the skeleton plugin. If you want to make your own, make a copy and then change it diff --git a/plugins/jobutils.cpp b/plugins/jobutils.cpp new file mode 100644 index 000000000..1e0971dff --- /dev/null +++ b/plugins/jobutils.cpp @@ -0,0 +1,402 @@ +#include "Core.h" +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using std::vector; +using std::string; +using std::endl; +using namespace DFHack; +using namespace df::enums; + +/* + * TODO: This should be in core: + */ + +struct MaterialInfo { + int16_t type; + int32_t index; + + df::material *material; + + enum Mode { + Builtin, + Inorganic, + Creature, + Plant + }; + Mode mode; + + int16_t subtype; + df::inorganic_raw *inorganic; + df::creature_raw *creature; + df::plant_raw *plant; + + df::historical_figure *figure; + + MaterialInfo(int16_t type = -1, int32_t index = -1) { + decode(type, index); + } + + bool isValid() const { return material != NULL; } + bool decode(int16_t type, int32_t index = -1); + + bool findInorganic(const std::string &token); + + std::string toString(uint16_t temp = 10015, bool named = true); +}; + +inline bool operator== (const MaterialInfo &a, const MaterialInfo &b) { + return a.type == b.type && a.index == b.index; +} +inline bool operator!= (const MaterialInfo &a, const MaterialInfo &b) { + return a.type != b.type || a.index != b.index; +} + +bool MaterialInfo::decode(int16_t type, int32_t index) +{ + this->type = type; + this->index = index; + + material = NULL; + mode = Builtin; subtype = 0; + inorganic = NULL; plant = NULL; creature = NULL; + figure = NULL; + + if (type < 0 || type >= 659) + return false; + + df::world_raws &raws = df::global::world->raws; + + if (index < 0) + { + material = raws.mat_table.builtin[type]; + } + else if (type == 0) + { + mode = Inorganic; + inorganic = df::inorganic_raw::find(index); + if (!inorganic) + return false; + material = &inorganic->material; + } + else if (type < 19) + { + material = raws.mat_table.builtin[type]; + } + else if (type < 219) + { + mode = Creature; + subtype = type-19; + creature = df::creature_raw::find(index); + if (!creature || subtype >= creature->material.size()) + return false; + material = creature->material[subtype]; + } + else if (type < 419) + { + mode = Creature; + subtype = type-219; + figure = df::historical_figure::find(index); + if (!figure) + return false; + creature = df::creature_raw::find(figure->race); + if (!creature || subtype >= creature->material.size()) + return false; + material = creature->material[subtype]; + } + else if (type < 619) + { + mode = Plant; + subtype = type-419; + plant = df::plant_raw::find(index); + if (!plant || subtype >= plant->material.size()) + return false; + material = plant->material[subtype]; + } + else + { + material = raws.mat_table.builtin[type]; + } + + return (material != NULL); +} + +bool MaterialInfo::findInorganic(const std::string &token) +{ + df::world_raws &raws = df::global::world->raws; + for (unsigned i = 0; i < raws.inorganics.size(); i++) + { + df::inorganic_raw *p = raws.inorganics[i]; + if (p->id == token) + return decode(0, i); + } + return decode(-1); +} + +std::string MaterialInfo::toString(uint16_t temp, bool named) +{ + if (type == -1) + return "NONE"; + if (!material) + return stl_sprintf("INVALID %d:%d", type, index); + + int idx = 0; + if (temp >= material->heat.melting_point) + idx = 1; + if (temp >= material->heat.boiling_point) + idx = 2; + std::string name = material->state_name[idx]; + if (!material->prefix.empty()) + name = material->prefix + " " + name; + + if (named && figure) + name += stl_sprintf(" of HF %d", index); + return name; +} + +/* + * Plugin-specific code starts here. + */ + +using df::global::world; +using df::global::ui; +using df::global::ui_build_selector; +using df::global::ui_workshop_job_cursor; + +static bool job_material_hotkey(Core *c, df::viewscreen *top); +static command_result job_material(Core *c, vector & parameters); + +DFhackCExport const char * plugin_name ( void ) +{ + return "jobutils"; +} + +DFhackCExport command_result plugin_init (Core *c, std::vector &commands) +{ + commands.clear(); + if (world && ui && (ui_workshop_job_cursor || ui_build_selector)) { + commands.push_back( + PluginCommand( + "job-material", "Alter the material of the selected job.", + job_material, job_material_hotkey, + " job-material \n" + "Intended to be used as a keybinding:\n" + " - In 'q' mode, when a job is highlighted within a workshop\n" + " or furnace, changes the material of the job.\n" + " - In 'b' mode, during selection of building components\n" + " positions the cursor over the first available choice\n" + " with the matching material.\n" + ) + ); + } + return CR_OK; +} + +DFhackCExport command_result plugin_shutdown ( Core * c ) +{ + return CR_OK; +} + +static bool job_material_hotkey(Core *c, df::viewscreen *top) +{ + using namespace ui_sidebar_mode; + + if (!dwarfmode_hotkey(c,top)) + return false; + + switch (ui->main.mode) { + case QueryBuilding: + { + if (!ui_workshop_job_cursor) // allow missing + return false; + + df::building *selected = world->selected_building; + if (!virtual_cast(selected) && + !virtual_cast(selected)) + return false; + + // No jobs? + if (selected->jobs.empty() || + selected->jobs[0]->job_id == job_type::DestroyBuilding) + return false; + + // Add job gui activated? + if (df::global::ui_workshop_in_add && // allow missing + *df::global::ui_workshop_in_add) + return false; + + return true; + }; + case Build: + { + if (!ui_build_selector) // allow missing + return false; + + // Not selecting, or no choices? + if (ui_build_selector->building_type < 0 || + ui_build_selector->stage != 2 || + ui_build_selector->choices.empty()) + return false; + + return true; + }; + default: + return false; + } +} + +static command_result job_material_in_job(Core *c, MaterialInfo &new_mat) +{ + df::building *selected = world->selected_building; + int idx = *ui_workshop_job_cursor; + + if (idx < 0 || idx >= selected->jobs.size()) + { + c->con.printerr("Invalid job cursor index: %d\n", idx); + return CR_FAILURE; + } + + df::job *job = selected->jobs[idx]; + MaterialInfo cur_mat(job->matType, job->matIndex); + + 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; + } + + // Verify that the new material matches the old one + df::material_flags rq_flag = material_flags::IS_STONE; + if (cur_mat.mode != MaterialInfo::Builtin) + { + if (cur_mat.material->flags.is_set(material_flags::IS_GEM)) + rq_flag = material_flags::IS_GEM; + else if (cur_mat.material->flags.is_set(material_flags::IS_METAL)) + rq_flag = material_flags::IS_METAL; + else if (!cur_mat.material->flags.is_set(rq_flag)) + { + c->con.printerr("Unexpected current material type: %s\n", + cur_mat.toString().c_str()); + return CR_FAILURE; + } + } + + if (!new_mat.material->flags.is_set(rq_flag)) + { + c->con.printerr("New material %s does not satisfy requirement: %s\n", + new_mat.toString().c_str(), ENUM_KEY_STR(material_flags, rq_flag)); + return CR_FAILURE; + } + + for (unsigned i = 0; i < job->job_items.size(); i++) + { + df::job_item *item = job->job_items[i]; + MaterialInfo item_mat(item->matType, item->matIndex); + + 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; + } + } + + // Apply the substitution + job->matType = new_mat.type; + job->matIndex = new_mat.index; + + for (unsigned i = 0; i < job->job_items.size(); i++) + { + df::job_item *item = job->job_items[i]; + item->matType = new_mat.type; + item->matIndex = new_mat.index; + } + + c->con << "Applied material '" << new_mat.toString() + << " jo job " << ENUM_KEY_STR(job_type,job->job_id) << endl; + return CR_OK; +} + +static command_result job_material_in_build(Core *c, MaterialInfo &new_mat) +{ + df::ui_build_item_req *req = ui_build_selector->requirements[ui_build_selector->req_index]; + + for (unsigned i = 0; i < ui_build_selector->choices.size(); i++) + { + df::build_req_choicest *choice = ui_build_selector->choices[i]; + bool found = false; + + if (VIRTUAL_CAST_VAR(gen, df::build_req_choice_genst, choice)) + { + if (gen->matType == new_mat.type && + gen->matIndex == new_mat.index && + gen->used_count < gen->candidates.size()) + { + found = true; + } + } + else if (VIRTUAL_CAST_VAR(spec, df::build_req_choice_specst, choice)) + { + if (spec->candidate && + spec->candidate->getActualMaterial() == new_mat.type && + spec->candidate->getActualMaterialIndex() == new_mat.index && + !req->candidate_selected[spec->candidate_id]) + { + found = true; + } + } + + if (found) + { + ui_build_selector->sel_index = i; + return CR_OK; + } + } + + c->con.printerr("Could not find material in list: %s\n", new_mat.toString().c_str()); + return CR_FAILURE; +} + +static command_result job_material(Core * c, vector & parameters) +{ + // HOTKEY COMMAND: CORE ALREADY SUSPENDED + + MaterialInfo new_mat; + if (parameters.size() == 1) + { + if (!new_mat.findInorganic(parameters[0])) { + c->con.printerr("Could not find inorganic material: %s\n", parameters[0].c_str()); + return CR_WRONG_USAGE; + } + } + else + return CR_WRONG_USAGE; + + if (ui->main.mode == ui_sidebar_mode::QueryBuilding) + return job_material_in_job(c, new_mat); + if (ui->main.mode == ui_sidebar_mode::Build) + return job_material_in_build(c, new_mat); + + return CR_WRONG_USAGE; +} From 2af3b49e0993f55822624ee7ea7be157fc3b9b30 Mon Sep 17 00:00:00 2001 From: Quietust Date: Mon, 2 Jan 2012 20:13:27 -0600 Subject: [PATCH 03/82] Add "regrass" plugin, regrows grass for pre-0.31.19 fortresses --- plugins/CMakeLists.txt | 1 + plugins/regrass.cpp | 83 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 84 insertions(+) create mode 100644 plugins/regrass.cpp diff --git a/plugins/CMakeLists.txt b/plugins/CMakeLists.txt index 133905727..671036626 100644 --- a/plugins/CMakeLists.txt +++ b/plugins/CMakeLists.txt @@ -61,6 +61,7 @@ DFHACK_PLUGIN(initflags initflags.cpp) DFHACK_PLUGIN(stockpiles stockpiles.cpp) DFHACK_PLUGIN(rename rename.cpp) DFHACK_PLUGIN(fixwagons fixwagons.cpp) +DFHACK_PLUGIN(regrass regrass.cpp) #DFHACK_PLUGIN(versionosd versionosd.cpp) # this is the skeleton plugin. If you want to make your own, make a copy and then change it diff --git a/plugins/regrass.cpp b/plugins/regrass.cpp new file mode 100644 index 000000000..bd227638e --- /dev/null +++ b/plugins/regrass.cpp @@ -0,0 +1,83 @@ +// All above-ground soil not covered by buildings will be covered with grass. +// Necessary for worlds generated prior to version 0.31.19 - otherwise, outdoor shrubs and trees no longer grow. + +#include "Core.h" +#include +#include +#include + +#include +#include +#include +#include + +using std::string; +using std::vector; +using namespace DFHack; + +using df::global::world; +using df::map_block; + +DFhackCExport command_result df_regrass (Core * c, vector & parameters) +{ + if (!parameters.empty()) + return CR_WRONG_USAGE; + + CoreSuspender suspend(c); + + int count = 0; + for (int i = 0; i < world->map.map_blocks.size(); i++) + { + map_block *cur = world->map.map_blocks[i]; + for (int x = 0; x < 16; x++) + { + for (int y = 0; y < 16; y++) + { + if (DFHack::tileShape(cur->tiletype[x][y]) != DFHack::FLOOR) + continue; + if (DFHack::tileMaterial(cur->tiletype[x][y]) != DFHack::SOIL) + continue; + if (cur->designation[x][y].bits.subterranean) + continue; + if (cur->occupancy[x][y].bits.building) + continue; + + switch (rand() % 8) + { + // light grass + case 0: cur->tiletype[x][y] = 0x015C; break; + case 1: cur->tiletype[x][y] = 0x015D; break; + case 2: cur->tiletype[x][y] = 0x015E; break; + case 3: cur->tiletype[x][y] = 0x015F; break; + // dark grass + case 4: cur->tiletype[x][y] = 0x018E; break; + case 5: cur->tiletype[x][y] = 0x018F; break; + case 6: cur->tiletype[x][y] = 0x0190; break; + case 7: cur->tiletype[x][y] = 0x0191; break; + } + count++; + } + } + } + + if (count) + c->con.print("Regrew %d tiles of grass.\n", count); + return CR_OK; +} + +DFhackCExport const char *plugin_name ( void ) +{ + return "regrass"; +} + +DFhackCExport command_result plugin_init (Core *c, std::vector &commands) +{ + commands.clear(); + commands.push_back(PluginCommand("regrass", "Regrows all surface grass, restoring outdoor plant growth for pre-0.31.19 worlds.", df_regrass)); + return CR_OK; +} + +DFhackCExport command_result plugin_shutdown ( Core * c ) +{ + return CR_OK; +} From fb736a85567b643c900c5057490c3c568455de0b Mon Sep 17 00:00:00 2001 From: Alexander Gavrilov Date: Tue, 3 Jan 2012 13:07:49 +0400 Subject: [PATCH 04/82] Support more ways to binsearch in a vector. --- library/include/MiscUtils.h | 110 +++++++++++++++++++++++++++++++----- library/xml | 2 +- 2 files changed, 96 insertions(+), 16 deletions(-) diff --git a/library/include/MiscUtils.h b/library/include/MiscUtils.h index 8959a766b..05be881ee 100644 --- a/library/include/MiscUtils.h +++ b/library/include/MiscUtils.h @@ -66,36 +66,116 @@ void print_bits ( T val, DFHack::Console& out ) out.print(strs.str().c_str()); } -//FIXME: Error 8 error C4519: default template arguments are only allowed on a class template -template -CT *binsearch_in_vector(std::vector &vec, FT CT::*field, AT value) +/* + * Binary search in vectors. + */ + +template +int binsearch_index(const std::vector &vec, FT key, bool exact = true) +{ + // Returns the index of the value >= the key + int min = -1, max = (int)vec.size(); + const FT *p = vec.data(); + for (;;) + { + int mid = (min + max)>>1; + if (mid == min) + return exact ? -1 : max; + FT midv = p[mid]; + if (midv == key) + return mid; + else if (midv < key) + min = mid; + else + max = mid; + } +} + +template +int binsearch_index(const std::vector &vec, FT CT::*field, FT key, bool exact = true) { + // Returns the index of the value >= the key int min = -1, max = (int)vec.size(); - CT **p = vec.data(); - FT key = (FT)value; + CT *const *p = vec.data(); for (;;) { int mid = (min + max)>>1; if (mid == min) - { - return NULL; - } + return exact ? -1 : max; FT midv = p[mid]->*field; if (midv == key) - { - return p[mid]; - } + return mid; else if (midv < key) - { min = mid; - } else - { max = mid; - } } } +template +inline int binsearch_index(const std::vector &vec, typename CT::key_field_type key, bool exact = true) +{ + return CT::binsearch_index(vec, key, exact); +} + +template +inline int binsearch_index(const std::vector &vec, typename CT::key_pointer_type key, bool exact = true) +{ + return CT::binsearch_index(vec, key, exact); +} + +template +inline bool vector_contains(const std::vector &vec, KT key) +{ + return binsearch_index(vec, key) >= 0; +} + +template +inline bool vector_contains(const std::vector &vec, FT CT::*field, FT key) +{ + return binsearch_index(vec, field, key) >= 0; +} + +template +unsigned insert_into_vector(std::vector &vec, FT key, bool *inserted = NULL) +{ + unsigned pos = (unsigned)binsearch_index(vec, key, false); + bool to_ins = (pos >= vec.size() || vec[pos] != key); + if (inserted) *inserted = to_ins; + if (to_ins) + vec.insert(vec.begin()+pos,key); + return pos; +} + +template +unsigned insert_into_vector(std::vector &vec, FT CT::*field, CT *obj, bool *inserted = NULL) +{ + unsigned pos = (unsigned)binsearch_index(vec, field, obj->*field, false); + bool to_ins = (pos >= vec.size() || vec[pos] != obj); + if (inserted) *inserted = to_ins; + if (to_ins) + vec.insert(vec.begin()+pos,obj); + return pos; +} + +template +CT *binsearch_in_vector(const std::vector &vec, KT value) +{ + int idx = binsearch_index(vec, value); + return idx < 0 ? NULL : vec[idx]; +} + +template +CT *binsearch_in_vector(const std::vector &vec, FT CT::*field, FT value) +{ + int idx = binsearch_index(vec, field, value); + return idx < 0 ? NULL : vec[idx]; +} + +/* + * MISC + */ + /** * Returns the amount of milliseconds elapsed since the UNIX epoch. * Works on both windows and linux. diff --git a/library/xml b/library/xml index 7b89e5958..c99be2349 160000 --- a/library/xml +++ b/library/xml @@ -1 +1 @@ -Subproject commit 7b89e595811ed81b012a805131aa10a89d451e76 +Subproject commit c99be2349fef32db026af7541676e2e4f24e4636 From f8814909a95597ac05380f274361651a9ce8e499 Mon Sep 17 00:00:00 2001 From: Alexander Gavrilov Date: Tue, 3 Jan 2012 19:25:55 +0400 Subject: [PATCH 05/82] Move the MaterialInfo class to the main library. --- library/include/DataDefs.h | 11 ++ library/include/modules/Materials.h | 69 +++++++++ library/modules/Materials.cpp | 232 ++++++++++++++++++++++++++++ library/xml | 2 +- plugins/initflags.cpp | 7 +- plugins/jobutils.cpp | 232 +++++----------------------- 6 files changed, 352 insertions(+), 201 deletions(-) diff --git a/library/include/DataDefs.h b/library/include/DataDefs.h index d869f12aa..05be18e31 100644 --- a/library/include/DataDefs.h +++ b/library/include/DataDefs.h @@ -124,6 +124,12 @@ namespace DFHack template T *ifnull(T *a, T *b) { return a ? a : b; } + + template + inline T next_enum_item_(T v) { + v = T(int(v) + 1); + return isvalid(v) ? v : start; + } } namespace df @@ -171,6 +177,11 @@ namespace df #define ENUM_FIRST_ITEM(enum) (df::enums::enum::_first_item_of_##enum) #define ENUM_LAST_ITEM(enum) (df::enums::enum::_last_item_of_##enum) +#define ENUM_NEXT_ITEM(enum,val) \ + (DFHack::next_enum_item_(val)) +#define FOR_ENUM_ITEMS(enum,iter) \ + for(df::enum iter = ENUM_FIRST_ITEM(enum); iter < ENUM_LAST_ITEM(enum); iter = df::enum(1+int(iter))) + namespace df { #define DF_KNOWN_GLOBALS \ GLOBAL(cursor,cursor) \ diff --git a/library/include/modules/Materials.h b/library/include/modules/Materials.h index 8c3ce6846..372d9d491 100644 --- a/library/include/modules/Materials.h +++ b/library/include/modules/Materials.h @@ -34,11 +34,80 @@ distribution. #include "Types.h" #include "BitArray.h" +#include "DataDefs.h" +#include "df/material.h" + #include #include +namespace df +{ + struct item; + struct inorganic_raw; + struct plant_raw; + struct creature_raw; + struct historical_figure; + union job_material_category; +} + namespace DFHack { + struct DFHACK_EXPORT MaterialInfo { + static const int NUM_BUILTIN = 19; + static const int GROUP_SIZE = 200; + static const int CREATURE_BASE = NUM_BUILTIN; + static const int FIGURE_BASE = NUM_BUILTIN + GROUP_SIZE; + static const int PLANT_BASE = NUM_BUILTIN + GROUP_SIZE*2; + static const int END_BASE = NUM_BUILTIN + GROUP_SIZE*3; + + int16_t type; + int32_t index; + + df::material *material; + + enum Mode { + Builtin, + Inorganic, + Creature, + Plant + }; + Mode mode; + + int16_t subtype; + df::inorganic_raw *inorganic; + df::creature_raw *creature; + df::plant_raw *plant; + + df::historical_figure *figure; + + public: + MaterialInfo(int16_t type = -1, int32_t index = -1) { decode(type, index); } + MaterialInfo(df::item *item) { decode(item); } + + bool isValid() const { return material != NULL; } + + bool decode(int16_t type, int32_t index = -1); + bool decode(df::item *item); + + bool find(const std::string &token, const std::string &subtoken = std::string()); + bool findBuiltin(const std::string &token); + bool findInorganic(const std::string &token); + bool findPlant(const std::string &token, const std::string &subtoken); + bool findCreature(const std::string &token, const std::string &subtoken); + + std::string toString(uint16_t temp = 10015, bool named = true); + + df::craft_material_class getCraftClass(); + bool matches(const df::job_material_category &cat); + }; + + inline bool operator== (const MaterialInfo &a, const MaterialInfo &b) { + return a.type == b.type && a.index == b.index; + } + inline bool operator!= (const MaterialInfo &a, const MaterialInfo &b) { + return a.type != b.type || a.index != b.index; + } + typedef int32_t t_materialIndex; typedef int16_t t_materialType, t_itemType, t_itemSubtype; diff --git a/library/modules/Materials.cpp b/library/modules/Materials.cpp index c77a62bd7..2e333f5f9 100644 --- a/library/modules/Materials.cpp +++ b/library/modules/Materials.cpp @@ -40,7 +40,239 @@ using namespace std; #include "ModuleFactory.h" #include "Core.h" +#include "MiscUtils.h" + +#include "df/world.h" +#include "df/item.h" +#include "df/inorganic_raw.h" +#include "df/plant_raw.h" +#include "df/creature_raw.h" +#include "df/historical_figure.h" + +#include "df/job_material_category.h" +#include "df/matter_state.h" + using namespace DFHack; +using namespace df::enums; + +bool MaterialInfo::decode(df::item *item) +{ + if (!item) + decode(-1); + else + decode(item->getActualMaterial(), item->getActualMaterialIndex()); +} + +bool MaterialInfo::decode(int16_t type, int32_t index) +{ + this->type = type; + this->index = index; + + material = NULL; + mode = Builtin; subtype = 0; + inorganic = NULL; plant = NULL; creature = NULL; + figure = NULL; + + df::world_raws &raws = df::global::world->raws; + + if (type < 0 || type >= sizeof(raws.mat_table.builtin)/sizeof(void*)) + return false; + + if (index < 0) + { + material = raws.mat_table.builtin[type]; + } + else if (type == 0) + { + mode = Inorganic; + inorganic = df::inorganic_raw::find(index); + if (!inorganic) + return false; + material = &inorganic->material; + } + else if (type < CREATURE_BASE) + { + material = raws.mat_table.builtin[type]; + } + else if (type < FIGURE_BASE) + { + mode = Creature; + subtype = type-CREATURE_BASE; + creature = df::creature_raw::find(index); + if (!creature || subtype >= creature->material.size()) + return false; + material = creature->material[subtype]; + } + else if (type < PLANT_BASE) + { + mode = Creature; + subtype = type-FIGURE_BASE; + figure = df::historical_figure::find(index); + if (!figure) + return false; + creature = df::creature_raw::find(figure->race); + if (!creature || subtype >= creature->material.size()) + return false; + material = creature->material[subtype]; + } + else if (type < END_BASE) + { + mode = Plant; + subtype = type-PLANT_BASE; + plant = df::plant_raw::find(index); + if (!plant || subtype >= plant->material.size()) + return false; + material = plant->material[subtype]; + } + else + { + material = raws.mat_table.builtin[type]; + } + + return (material != NULL); +} + +bool MaterialInfo::find(const std::string &token, const std::string &subtoken) +{ + if (findBuiltin(token)) + return true; + if (subtoken.empty()) + { + if (findInorganic(token)) + return true; + } + else + { + if (findPlant(token, subtoken)) + return true; + if (findCreature(token, subtoken)) + return true; + } + return false; +} + +bool MaterialInfo::findBuiltin(const std::string &token) +{ + df::world_raws &raws = df::global::world->raws; + for (int i = 1; i < NUM_BUILTIN; i++) + if (raws.mat_table.builtin[i]->id == token) + return decode(i, -1); + return decode(-1); +} + +bool MaterialInfo::findInorganic(const std::string &token) +{ + df::world_raws &raws = df::global::world->raws; + for (unsigned i = 0; i < raws.inorganics.size(); i++) + { + df::inorganic_raw *p = raws.inorganics[i]; + if (p->id == token) + return decode(0, i); + } + return decode(-1); +} + +bool MaterialInfo::findPlant(const std::string &token, const std::string &subtoken) +{ + df::world_raws &raws = df::global::world->raws; + for (unsigned i = 0; i < raws.plants.all.size(); i++) + { + df::plant_raw *p = raws.plants.all[i]; + if (p->id != token) + continue; + + for (unsigned j = 0; j < p->material.size(); j++) + if (p->material[j]->id == subtoken) + return decode(PLANT_BASE+j, i); + + break; + } + return decode(-1); +} + +bool MaterialInfo::findCreature(const std::string &token, const std::string &subtoken) +{ + df::world_raws &raws = df::global::world->raws; + for (unsigned i = 0; i < raws.creatures.all.size(); i++) + { + df::creature_raw *p = raws.creatures.all[i]; + if (p->creature_id != token) + continue; + + for (unsigned j = 0; j < p->material.size(); j++) + if (p->material[j]->id == subtoken) + return decode(CREATURE_BASE+j, i); + + break; + } + return decode(-1); +} + +std::string MaterialInfo::toString(uint16_t temp, bool named) +{ + if (type == -1) + return "NONE"; + if (!material) + return stl_sprintf("INVALID %d:%d", type, index); + + df::matter_state state = matter_state::Solid; + if (temp >= material->heat.melting_point) + state = matter_state::Liquid; + if (temp >= material->heat.boiling_point) + state = matter_state::Gas; + + std::string name = material->state_name[state]; + if (!material->prefix.empty()) + name = material->prefix + " " + name; + + if (named && figure) + name += stl_sprintf(" of HF %d", index); + return name; +} + +df::craft_material_class MaterialInfo::getCraftClass() +{ + if (!material) + return craft_material_class::None; + + if (type == 0 && index == -1) + return craft_material_class::Stone; + + FOR_ENUM_ITEMS(material_flags, i) + { + df::craft_material_class ccv = ENUM_ATTR(material_flags, type, i); + if (ccv == craft_material_class::None) + continue; + if (material->flags.is_set(i)) + return ccv; + } + + return craft_material_class::None; +} + +bool MaterialInfo::matches(const df::job_material_category &cat) +{ + if (!material) + return false; + + using namespace df::enums::material_flags; +#define TEST(bit,flag) if (cat.bits.bit && material->flags.is_set(flag)) return true; + TEST(plant, STRUCTURAL_PLANT_MAT); + TEST(wood, WOOD); + TEST(cloth, THREAD_PLANT); + TEST(silk, SILK); + TEST(leather, LEATHER); + TEST(bone, BONE); + TEST(shell, SHELL); + TEST(wood2, WOOD); + TEST(soap, SOAP); + TEST(tooth, TOOTH); + TEST(horn, HORN); + TEST(pearl, PEARL); + TEST(yarn, YARN); +#undef TEST + return false; +} Module* DFHack::createMaterials() { diff --git a/library/xml b/library/xml index c99be2349..f50bf32d3 160000 --- a/library/xml +++ b/library/xml @@ -1 +1 @@ -Subproject commit c99be2349fef32db026af7541676e2e4f24e4636 +Subproject commit f50bf32d3d4d29667720d648bf455896072c77f9 diff --git a/plugins/initflags.cpp b/plugins/initflags.cpp index 5671619e8..c7a634b78 100644 --- a/plugins/initflags.cpp +++ b/plugins/initflags.cpp @@ -51,10 +51,7 @@ DFhackCExport command_result twaterlvl(Core * c, vector & parameters) DFhackCExport command_result tidlers(Core * c, vector & parameters) { // HOTKEY COMMAND: CORE ALREADY SUSPENDED - df::d_init_idlers iv = df::d_init_idlers(int(d_init->idlers) + 1); - if (!d_init_idlers::is_valid(iv)) - iv = ENUM_FIRST_ITEM(d_init_idlers); - d_init->idlers = iv; - c->con << "Toggled the display of idlers to " << ENUM_KEY_STR(d_init_idlers, iv) << endl; + d_init->idlers = ENUM_NEXT_ITEM(d_init_idlers, d_init->idlers); + c->con << "Toggled the display of idlers to " << ENUM_KEY_STR(d_init_idlers, d_init->idlers) << endl; return CR_OK; } diff --git a/plugins/jobutils.cpp b/plugins/jobutils.cpp index 1e0971dff..005797ae7 100644 --- a/plugins/jobutils.cpp +++ b/plugins/jobutils.cpp @@ -4,6 +4,8 @@ #include #include +#include + #include #include #include @@ -13,11 +15,6 @@ #include #include #include -#include -#include -#include -#include -#include #include #include #include @@ -28,156 +25,6 @@ using std::endl; using namespace DFHack; using namespace df::enums; -/* - * TODO: This should be in core: - */ - -struct MaterialInfo { - int16_t type; - int32_t index; - - df::material *material; - - enum Mode { - Builtin, - Inorganic, - Creature, - Plant - }; - Mode mode; - - int16_t subtype; - df::inorganic_raw *inorganic; - df::creature_raw *creature; - df::plant_raw *plant; - - df::historical_figure *figure; - - MaterialInfo(int16_t type = -1, int32_t index = -1) { - decode(type, index); - } - - bool isValid() const { return material != NULL; } - bool decode(int16_t type, int32_t index = -1); - - bool findInorganic(const std::string &token); - - std::string toString(uint16_t temp = 10015, bool named = true); -}; - -inline bool operator== (const MaterialInfo &a, const MaterialInfo &b) { - return a.type == b.type && a.index == b.index; -} -inline bool operator!= (const MaterialInfo &a, const MaterialInfo &b) { - return a.type != b.type || a.index != b.index; -} - -bool MaterialInfo::decode(int16_t type, int32_t index) -{ - this->type = type; - this->index = index; - - material = NULL; - mode = Builtin; subtype = 0; - inorganic = NULL; plant = NULL; creature = NULL; - figure = NULL; - - if (type < 0 || type >= 659) - return false; - - df::world_raws &raws = df::global::world->raws; - - if (index < 0) - { - material = raws.mat_table.builtin[type]; - } - else if (type == 0) - { - mode = Inorganic; - inorganic = df::inorganic_raw::find(index); - if (!inorganic) - return false; - material = &inorganic->material; - } - else if (type < 19) - { - material = raws.mat_table.builtin[type]; - } - else if (type < 219) - { - mode = Creature; - subtype = type-19; - creature = df::creature_raw::find(index); - if (!creature || subtype >= creature->material.size()) - return false; - material = creature->material[subtype]; - } - else if (type < 419) - { - mode = Creature; - subtype = type-219; - figure = df::historical_figure::find(index); - if (!figure) - return false; - creature = df::creature_raw::find(figure->race); - if (!creature || subtype >= creature->material.size()) - return false; - material = creature->material[subtype]; - } - else if (type < 619) - { - mode = Plant; - subtype = type-419; - plant = df::plant_raw::find(index); - if (!plant || subtype >= plant->material.size()) - return false; - material = plant->material[subtype]; - } - else - { - material = raws.mat_table.builtin[type]; - } - - return (material != NULL); -} - -bool MaterialInfo::findInorganic(const std::string &token) -{ - df::world_raws &raws = df::global::world->raws; - for (unsigned i = 0; i < raws.inorganics.size(); i++) - { - df::inorganic_raw *p = raws.inorganics[i]; - if (p->id == token) - return decode(0, i); - } - return decode(-1); -} - -std::string MaterialInfo::toString(uint16_t temp, bool named) -{ - if (type == -1) - return "NONE"; - if (!material) - return stl_sprintf("INVALID %d:%d", type, index); - - int idx = 0; - if (temp >= material->heat.melting_point) - idx = 1; - if (temp >= material->heat.boiling_point) - idx = 2; - std::string name = material->state_name[idx]; - if (!material->prefix.empty()) - name = material->prefix + " " + name; - - if (named && figure) - name += stl_sprintf(" of HF %d", index); - return name; -} - -/* - * Plugin-specific code starts here. - */ - using df::global::world; using df::global::ui; using df::global::ui_build_selector; @@ -277,6 +124,7 @@ static command_result job_material_in_job(Core *c, MaterialInfo &new_mat) } df::job *job = selected->jobs[idx]; + MaterialInfo cur_mat(job->matType, job->matIndex); if (!cur_mat.isValid() || cur_mat.type != 0) @@ -286,26 +134,17 @@ static command_result job_material_in_job(Core *c, MaterialInfo &new_mat) return CR_FAILURE; } - // Verify that the new material matches the old one - df::material_flags rq_flag = material_flags::IS_STONE; - if (cur_mat.mode != MaterialInfo::Builtin) + df::craft_material_class old_class = cur_mat.getCraftClass(); + if (old_class == craft_material_class::None) { - if (cur_mat.material->flags.is_set(material_flags::IS_GEM)) - rq_flag = material_flags::IS_GEM; - else if (cur_mat.material->flags.is_set(material_flags::IS_METAL)) - rq_flag = material_flags::IS_METAL; - else if (!cur_mat.material->flags.is_set(rq_flag)) - { - c->con.printerr("Unexpected current material type: %s\n", - cur_mat.toString().c_str()); - return CR_FAILURE; - } + c->con.printerr("Unexpected current material type: %s\n", + cur_mat.toString().c_str()); + return CR_FAILURE; } - - if (!new_mat.material->flags.is_set(rq_flag)) + 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(material_flags, rq_flag)); + new_mat.toString().c_str(), ENUM_KEY_STR(craft_material_class, old_class)); return CR_FAILURE; } @@ -334,40 +173,43 @@ static command_result job_material_in_job(Core *c, MaterialInfo &new_mat) } c->con << "Applied material '" << new_mat.toString() - << " jo job " << ENUM_KEY_STR(job_type,job->job_id) << endl; + << "' to job " << ENUM_KEY_STR(job_type,job->job_id) << endl; return CR_OK; } -static command_result job_material_in_build(Core *c, MaterialInfo &new_mat) +static bool build_choice_matches(df::ui_build_item_req *req, df::build_req_choicest *choice, + MaterialInfo &new_mat) { - df::ui_build_item_req *req = ui_build_selector->requirements[ui_build_selector->req_index]; - - for (unsigned i = 0; i < ui_build_selector->choices.size(); i++) + if (VIRTUAL_CAST_VAR(gen, df::build_req_choice_genst, choice)) { - df::build_req_choicest *choice = ui_build_selector->choices[i]; - bool found = false; - - if (VIRTUAL_CAST_VAR(gen, df::build_req_choice_genst, choice)) + if (gen->matType == new_mat.type && + gen->matIndex == new_mat.index && + gen->used_count < gen->candidates.size()) { - if (gen->matType == new_mat.type && - gen->matIndex == new_mat.index && - gen->used_count < gen->candidates.size()) - { - found = true; - } + return true; } - else if (VIRTUAL_CAST_VAR(spec, df::build_req_choice_specst, choice)) + } + else if (VIRTUAL_CAST_VAR(spec, df::build_req_choice_specst, choice)) + { + if (spec->candidate && + spec->candidate->getActualMaterial() == new_mat.type && + spec->candidate->getActualMaterialIndex() == new_mat.index && + !req->candidate_selected[spec->candidate_id]) { - if (spec->candidate && - spec->candidate->getActualMaterial() == new_mat.type && - spec->candidate->getActualMaterialIndex() == new_mat.index && - !req->candidate_selected[spec->candidate_id]) - { - found = true; - } + return true; } + } + + return false; +} - if (found) +static command_result job_material_in_build(Core *c, MaterialInfo &new_mat) +{ + df::ui_build_item_req *req = ui_build_selector->requirements[ui_build_selector->req_index]; + + for (unsigned i = 0; i < ui_build_selector->choices.size(); i++) + { + if (build_choice_matches(req, ui_build_selector->choices[i], new_mat)) { ui_build_selector->sel_index = i; return CR_OK; From 1d1cd638003a74d4543ff7348ee29c27f03ed78a Mon Sep 17 00:00:00 2001 From: Alexander Gavrilov Date: Tue, 3 Jan 2012 22:56:05 +0400 Subject: [PATCH 06/82] Implement printing job details. --- library/DataDefs.cpp | 37 ++++++++++ library/include/DataDefs.h | 13 ++++ library/xml | 2 +- plugins/jobutils.cpp | 139 +++++++++++++++++++++++++++++++++++-- 4 files changed, 185 insertions(+), 6 deletions(-) diff --git a/library/DataDefs.cpp b/library/DataDefs.cpp index bcdb388b5..eb05038ef 100644 --- a/library/DataDefs.cpp +++ b/library/DataDefs.cpp @@ -35,6 +35,8 @@ distribution. // must be last due to MS stupidity #include "DataDefs.h" +#include "MiscUtils.h" + using namespace DFHack; /* The order of global object constructor calls is @@ -160,6 +162,41 @@ void virtual_identity::Init(Core *core) } } +std::string DFHack::bitfieldToString(const void *p, int size, const bitfield_item_info *items) +{ + std::string res; + const char *data = (const char*)p; + + for (int i = 0; i < size*8; i++) { + unsigned v; + + if (items[i].size > 1) { + unsigned pdv = *(unsigned*)&data[i/8]; + v = (pdv >> (i%8)) & ((1 << items[i].size)-1); + } else { + v = (data[i/8]>>(i%8)) & 1; + } + + if (v) { + if (!res.empty()) + res += ' '; + + if (items[i].name) + res += items[i].name; + else + res += stl_sprintf("UNK_%d", i); + + if (items[i].size > 1) + res += stl_sprintf("=%u", v); + } + + if (items[i].size > 1) + i += items[i].size-1; + } + + return res; +} + #define SIMPLE_GLOBAL(name,tname) \ tname *df::global::name = NULL; #define GLOBAL(name,tname) SIMPLE_GLOBAL(name,df::tname) diff --git a/library/include/DataDefs.h b/library/include/DataDefs.h index 05be18e31..d3899854d 100644 --- a/library/include/DataDefs.h +++ b/library/include/DataDefs.h @@ -130,6 +130,18 @@ namespace DFHack v = T(int(v) + 1); return isvalid(v) ? v : start; } + + struct bitfield_item_info { + const char *name; + int size; + }; + + DFHACK_EXPORT std::string bitfieldToString(const void *p, int size, const bitfield_item_info *items); + + template + inline std::string bitfieldToString(const T &val) { + return bitfieldToString(&val.whole, sizeof(val.whole), val.get_items()); + } } namespace df @@ -137,6 +149,7 @@ namespace df using DFHack::virtual_ptr; using DFHack::virtual_identity; using DFHack::virtual_class; + using DFHack::bitfield_item_info; using DFHack::BitArray; template diff --git a/library/xml b/library/xml index f50bf32d3..3455acedc 160000 --- a/library/xml +++ b/library/xml @@ -1 +1 @@ -Subproject commit f50bf32d3d4d29667720d648bf455896072c77f9 +Subproject commit 3455acedc525473cd8c5403d225a6078b661dfc8 diff --git a/plugins/jobutils.cpp b/plugins/jobutils.cpp index 005797ae7..83503ddc9 100644 --- a/plugins/jobutils.cpp +++ b/plugins/jobutils.cpp @@ -30,9 +30,14 @@ using df::global::ui; using df::global::ui_build_selector; using df::global::ui_workshop_job_cursor; +static bool wokshop_job_hotkey(Core *c, df::viewscreen *top); +static bool build_selector_hotkey(Core *c, df::viewscreen *top); + static bool job_material_hotkey(Core *c, df::viewscreen *top); static command_result job_material(Core *c, vector & parameters); +static command_result job_cmd(Core *c, vector & parameters); + DFhackCExport const char * plugin_name ( void ) { return "jobutils"; @@ -41,7 +46,19 @@ DFhackCExport const char * plugin_name ( void ) DFhackCExport command_result plugin_init (Core *c, std::vector &commands) { commands.clear(); - if (world && ui && (ui_workshop_job_cursor || ui_build_selector)) { + if (!world || !ui) + return CR_FAILURE; + + commands.push_back( + PluginCommand( + "job", "General job query and manipulation.", + job_cmd, false, + " job query - Print details of the current job.\n" + " job list - Print details of all jobs in the workshop.\n" + ) + ); + + if (ui_workshop_job_cursor || ui_build_selector) { commands.push_back( PluginCommand( "job-material", "Alter the material of the selected job.", @@ -56,6 +73,7 @@ DFhackCExport command_result plugin_init (Core *c, std::vector & ) ); } + return CR_OK; } @@ -64,7 +82,7 @@ DFhackCExport command_result plugin_shutdown ( Core * c ) return CR_OK; } -static bool job_material_hotkey(Core *c, df::viewscreen *top) +static bool workshop_job_hotkey(Core *c, df::viewscreen *top) { using namespace ui_sidebar_mode; @@ -94,6 +112,19 @@ static bool job_material_hotkey(Core *c, df::viewscreen *top) return true; }; + default: + return false; + } +} + +static bool build_selector_hotkey(Core *c, df::viewscreen *top) +{ + using namespace ui_sidebar_mode; + + if (!dwarfmode_hotkey(c,top)) + return false; + + switch (ui->main.mode) { case Build: { if (!ui_build_selector) // allow missing @@ -112,7 +143,13 @@ static bool job_material_hotkey(Core *c, df::viewscreen *top) } } -static command_result job_material_in_job(Core *c, MaterialInfo &new_mat) +static bool job_material_hotkey(Core *c, df::viewscreen *top) +{ + return workshop_job_hotkey(c, top) || + build_selector_hotkey(c, top); +} + +static df::job *getWorkshopJob(Core *c) { df::building *selected = world->selected_building; int idx = *ui_workshop_job_cursor; @@ -120,10 +157,17 @@ static command_result job_material_in_job(Core *c, MaterialInfo &new_mat) if (idx < 0 || idx >= selected->jobs.size()) { c->con.printerr("Invalid job cursor index: %d\n", idx); - return CR_FAILURE; + return NULL; } - df::job *job = selected->jobs[idx]; + return selected->jobs[idx]; +} + +static command_result job_material_in_job(Core *c, MaterialInfo &new_mat) +{ + df::job *job = getWorkshopJob(c); + if (!job) + return CR_FAILURE; MaterialInfo cur_mat(job->matType, job->matIndex); @@ -242,3 +286,88 @@ static command_result job_material(Core * c, vector & parameters) return CR_WRONG_USAGE; } + +static void print_job_item_details(Core *c, df::job *job, df::job_item *item) +{ + c->con << " Input Item: " << ENUM_KEY_STR(item_type,item->itemType); + if (item->itemSubtype != -1) + c->con << " [" << item->itemSubtype << "]"; + c->con << "; count=" << item->count << endl; + + MaterialInfo mat(item->matType, item->matIndex); + if (mat.isValid()) + c->con << " material: " << mat.toString() << endl; + + if (item->flags1.whole) + c->con << " flags1: " << bitfieldToString(item->flags1) << endl; + if (item->flags2.whole) + c->con << " flags2: " << bitfieldToString(item->flags2) << endl; + if (item->flags3.whole) + c->con << " flags3: " << bitfieldToString(item->flags3) << endl; + + if (!item->reaction_class.empty()) + c->con << " reaction class: " << item->reaction_class << endl; + if (!item->has_material_reaction_product.empty()) + c->con << " reaction product: " << item->has_material_reaction_product << endl; +} + +static void print_job_details(Core *c, df::job *job) +{ + c->con << "Job " << job->id << ": " << ENUM_KEY_STR(job_type,job->job_id) + << " [" << job->x << "," << job->y << "," << job->z << "] (" + << bitfieldToString(job->flags) << ")" << endl; + + MaterialInfo mat(job->matType, job->matIndex); + if (mat.isValid() || job->material_category.whole) + { + c->con << " material: " << mat.toString(); + if (job->material_category.whole) + c->con << " (" << bitfieldToString(job->material_category) << ")"; + c->con << endl; + } + + if (job->item_subtype >= 0 || job->item_category.whole) + c->con << " item: " << job->item_subtype + << " (" << bitfieldToString(job->item_category) << ")" << endl; + + if (job->hist_figure_id >= 0) + c->con << " figure: " << job->hist_figure_id << endl; + + if (!job->reaction_name.empty()) + c->con << " reaction: " << job->reaction_name << endl; + + for (unsigned i = 0; i < job->job_items.size(); i++) + print_job_item_details(c, job, job->job_items[i]); +} + +static command_result job_cmd(Core * c, vector & parameters) +{ + CoreSuspender suspend(c); + + if (parameters.empty()) + return CR_WRONG_USAGE; + + std::string cmd = parameters[0]; + if (cmd == "query" || cmd == "list") + { + if (!workshop_job_hotkey(c, c->getTopViewscreen())) { + c->con.printerr("No job is highlighted.\n"); + return CR_WRONG_USAGE; + } + + if (cmd == "query") { + df::job *job = getWorkshopJob(c); + if (!job) + return CR_FAILURE; + print_job_details(c, job); + } else { + df::building *selected = world->selected_building; + for (unsigned i = 0; i < selected->jobs.size(); i++) + print_job_details(c, selected->jobs[i]); + } + } + else + return CR_WRONG_USAGE; + + return CR_OK; +} From 86464b99cca06f9e3cf7dd05c6441136c6ab442f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Mr=C3=A1zek?= Date: Wed, 4 Jan 2012 01:45:11 +0100 Subject: [PATCH 07/82] Remove DfVector, break MSVC builds until further notice. --- library/CMakeLists.txt | 1 - library/DataDefs.cpp | 6 +- library/Process-linux.cpp | 10 +-- library/VersionInfo.cpp | 54 +++++++------- library/include/MemAccess.h | 59 ++++++++------- library/include/Vector.h | 96 ------------------------- library/include/VersionInfo.h | 6 +- library/include/modules/Buildings.h | 2 +- library/include/modules/Constructions.h | 2 +- library/include/modules/Engravings.h | 2 +- library/include/modules/Maps.h | 2 +- library/include/modules/Vermin.h | 2 +- library/modules/Buildings.cpp | 51 +++++-------- library/modules/Constructions.cpp | 26 ++----- library/modules/Engravings.cpp | 24 ++----- library/modules/Graphic.cpp | 1 - library/modules/Gui.cpp | 57 ++++++++++----- library/modules/Items.cpp | 3 +- library/modules/Maps.cpp | 63 ++++++++-------- library/modules/Materials.cpp | 47 ++++++------ library/modules/Translation.cpp | 17 +++-- library/modules/Units.cpp | 9 ++- library/modules/Vegetation.cpp | 1 - library/modules/Vermin.cpp | 6 +- library/modules/World.cpp | 16 ++--- library/modules/kitchen.cpp | 5 +- plugins/Dfusion/include/hexsearch.h | 10 +-- plugins/Dfusion/src/hexsearch.cpp | 12 ++-- plugins/Dfusion/src/lua_Hexsearch.cpp | 10 +-- plugins/Dfusion/src/lua_Misc.cpp | 2 +- plugins/Dfusion/src/lua_Process.cpp | 30 ++++---- plugins/Dfusion/src/lua_VersionInfo.cpp | 10 +-- plugins/devel/memview.cpp | 8 +-- plugins/devel/vectors.cpp | 24 +++---- 34 files changed, 281 insertions(+), 393 deletions(-) delete mode 100644 library/include/Vector.h diff --git a/library/CMakeLists.txt b/library/CMakeLists.txt index f24e21fd3..808c13a18 100644 --- a/library/CMakeLists.txt +++ b/library/CMakeLists.txt @@ -39,7 +39,6 @@ include/SDL_keyboard.h include/SDL_keysym.h include/TileTypes.h include/Types.h -include/Vector.h include/VersionInfo.h include/VersionInfoFactory.h include/Virtual.h diff --git a/library/DataDefs.cpp b/library/DataDefs.cpp index bcdb388b5..312252b40 100644 --- a/library/DataDefs.cpp +++ b/library/DataDefs.cpp @@ -154,9 +154,9 @@ void virtual_identity::Init(Core *core) // Read pre-filled vtable ptrs OffsetGroup *ptr_table = core->vinfo->getGroup("vtable"); for (virtual_identity *p = list; p; p = p->next) { - uint32_t tmp; + void * tmp; if (ptr_table->getSafeAddress(p->getName(),tmp)) - p->vtable_ptr = (void*)tmp; + p->vtable_ptr = tmp; } } @@ -169,7 +169,7 @@ DF_KNOWN_GLOBALS void DFHack::InitDataDefGlobals(Core *core) { OffsetGroup *global_table = core->vinfo->getGroup("global"); - uint32_t tmp; + void * tmp; #define SIMPLE_GLOBAL(name,tname) \ if (global_table->getSafeAddress(#name,tmp)) df::global::name = (tname*)tmp; diff --git a/library/Process-linux.cpp b/library/Process-linux.cpp index ee64c2740..d2c04e105 100644 --- a/library/Process-linux.cpp +++ b/library/Process-linux.cpp @@ -111,8 +111,8 @@ Process::~Process() string Process::doReadClassName (void * vptr) { //FIXME: BAD!!!!! - int typeinfo = Process::readDWord((uint32_t)vptr - 0x4); - int typestring = Process::readDWord(typeinfo + 0x4); + void * typeinfo = Process::readPtr(vptr - 0x4); + void * typestring = Process::readPtr(typeinfo + 0x4); string raw = readCString(typestring); size_t start = raw.find_first_of("abcdefghijklmnopqrstuvwxyz");// trim numbers size_t end = raw.length(); @@ -138,8 +138,8 @@ void Process::getMemRanges( vector & ranges ) (char*)&permissions, &offset, &device1, &device2, &node, (char*)&temp.name); - temp.start = start; - temp.end = end; + temp.start = (void *) start; + temp.end = (void *) end; temp.read = permissions[0] == 'r'; temp.write = permissions[1] == 'w'; temp.execute = permissions[2] == 'x'; @@ -214,7 +214,7 @@ bool Process::setPermisions(const t_memrange & range,const t_memrange &trgrange) if(trgrange.read)protect|=PROT_READ; if(trgrange.write)protect|=PROT_WRITE; if(trgrange.execute)protect|=PROT_EXEC; - result=mprotect((void *)range.start, range.end-range.start,protect); + result=mprotect((void *)range.start, (size_t)range.end-(size_t)range.start,protect); return result==0; } \ No newline at end of file diff --git a/library/VersionInfo.cpp b/library/VersionInfo.cpp index 0f0764d60..430553e9e 100644 --- a/library/VersionInfo.cpp +++ b/library/VersionInfo.cpp @@ -158,6 +158,8 @@ namespace DFHack { typedef pair nullableUint32; typedef map ::iterator uint32_Iter; + typedef pair nullableVoidPtr; + typedef map ::iterator voidptr_Iter; typedef pair nullableInt32; typedef map ::iterator int32_Iter; typedef pair nullableString; @@ -166,7 +168,7 @@ namespace DFHack class OffsetGroupPrivate { public: - map addresses; + map addresses; map hexvals; map offsets; map strings; @@ -183,7 +185,7 @@ void OffsetGroup::createOffset(const string & key) void OffsetGroup::createAddress(const string & key) { - OGd->addresses[key] = nullableUint32(NOT_SET, 0); + OGd->addresses[key] = nullableVoidPtr(NOT_SET, 0); } void OffsetGroup::createHexValue(const string & key) @@ -227,10 +229,10 @@ void OffsetGroup::setOffsetValidity (const string & key, const INVAL_TYPE inval) void OffsetGroup::setAddress (const string & key, const string & value, const INVAL_TYPE inval) { - uint32_Iter it = OGd->addresses.find(key); + voidptr_Iter it = OGd->addresses.find(key); if(it != OGd->addresses.end()) { - uint32_t address = strtol(value.c_str(), NULL, 16); + void * address = (void *) strtol(value.c_str(), NULL, 16); if((*it).second.second == address) std::cout << "Pointless address setting: " << this->getFullName() + key << endl; (*it).second.second = address; @@ -244,7 +246,7 @@ void OffsetGroup::setAddressValidity (const string & key, const INVAL_TYPE inval { if(inval != NOT_SET) { - uint32_Iter it = OGd->addresses.find(key); + voidptr_Iter it = OGd->addresses.find(key); if(it != OGd->addresses.end()) { (*it).second.first = inval; @@ -305,9 +307,9 @@ void OffsetGroup::setStringValidity (const string & key, const INVAL_TYPE inval) } // Get named address -uint32_t OffsetGroup::getAddress (const string & key) +void * OffsetGroup::getAddress (const string & key) { - uint32_Iter iter = OGd->addresses.find(key); + voidptr_Iter iter = OGd->addresses.find(key); if(iter != OGd->addresses.end()) { @@ -321,9 +323,9 @@ uint32_t OffsetGroup::getAddress (const string & key) } // Get named offset, return bool instead of throwing exceptions -bool OffsetGroup::getSafeAddress (const string & key, uint32_t & out) +bool OffsetGroup::getSafeAddress (const string & key, void * & out) { - uint32_Iter iter = OGd->addresses.find(key); + voidptr_Iter iter = OGd->addresses.find(key); if(iter != OGd->addresses.end() && (*iter).second.first == IS_VALID) { out = (*iter).second.second; @@ -410,7 +412,7 @@ OffsetGroup * OffsetGroup::createGroup(const std::string &name) void OffsetGroup::RebaseAddresses(int32_t offset) { - for(uint32_Iter iter = OGd->addresses.begin(); iter != OGd->addresses.end(); iter++) + for(voidptr_Iter iter = OGd->addresses.begin(); iter != OGd->addresses.end(); iter++) { if(iter->second.first) OGd->addresses[iter->first].second = iter->second.second + offset; @@ -470,18 +472,19 @@ std::string OffsetGroup::getFullName() std::string OffsetGroup::PrintOffsets(int indentation) { + voidptr_Iter addriter; uint32_Iter iter; ostringstream ss; indentr i(indentation); - typedef pair > horrible; + typedef pair > horrible; vector < horrible > addrsorter; - for(iter = OGd->addresses.begin(); iter != OGd->addresses.end(); iter++) + for(addriter = OGd->addresses.begin(); addriter != OGd->addresses.end(); addriter++) { - if(!(*iter).second.first) - addrsorter.push_back( make_pair( 0, *iter ) ); + if(!(*addriter).second.first) + addrsorter.push_back( make_pair( (void *)0, *addriter ) ); else { - addrsorter.push_back( make_pair( (*iter).second.second, *iter ) ); + addrsorter.push_back( make_pair( (*addriter).second.second, *addriter ) ); } } std::sort(addrsorter.begin(), addrsorter.end(), compare_pair_first<>()); @@ -569,7 +572,7 @@ void OffsetGroup::setInvalid(INVAL_TYPE invalidity) if(invalidity == NOT_SET) return; - uint32_Iter iter; + voidptr_Iter iter; for(iter = OGd->addresses.begin(); iter != OGd->addresses.end(); iter++) { if((*iter).second.first) @@ -581,17 +584,18 @@ void OffsetGroup::setInvalid(INVAL_TYPE invalidity) if((*iter2).second.first) (*iter2).second.first = invalidity; } - for(iter = OGd->hexvals.begin(); iter != OGd->hexvals.end(); iter++) - { - if((*iter).second.first) - (*iter).second.first = invalidity; - } - strings_Iter iter3; - for(iter3 = OGd->strings.begin(); iter3 != OGd->strings.end(); iter3++) + uint32_Iter iter3; + for(iter3 = OGd->hexvals.begin(); iter3 != OGd->hexvals.end(); iter3++) { if((*iter3).second.first) (*iter3).second.first = invalidity; } + strings_Iter iter5; + for(iter5 = OGd->strings.begin(); iter5 != OGd->strings.end(); iter5++) + { + if((*iter5).second.first) + (*iter5).second.first = invalidity; + } groups_Iter iter4; for(iter4 = OGd->groups.begin(); iter4 != OGd->groups.end(); iter4++) { @@ -603,7 +607,7 @@ std::vector OffsetGroup::getKeys() const std::vector ret; OffsetKey K; K.keytype=IS_ADDRESS; - for(uint32_Iter iter = OGd->addresses.begin(); iter != OGd->addresses.end(); iter++) + for(voidptr_Iter iter = OGd->addresses.begin(); iter != OGd->addresses.end(); iter++) { K.key=iter->first; K.inval=iter->second.first; @@ -1015,7 +1019,7 @@ void VersionInfo::setClassChild (t_class * parent, const char * name, const char // FIXME: This in now DEPRECATED! -bool VersionInfo::resolveObjectToClassID(const uint32_t address, int32_t & classid) +bool VersionInfo::resolveObjectToClassID(const void * address, int32_t & classid) { uint32_t vtable = d->p->readDWord(address); // try to find the vtable in our cache diff --git a/library/include/MemAccess.h b/library/include/MemAccess.h index 7da132c8a..30a194bb3 100644 --- a/library/include/MemAccess.h +++ b/library/include/MemAccess.h @@ -72,8 +72,8 @@ namespace DFHack */ struct DFHACK_EXPORT t_memrange { - uint64_t start; - uint64_t end; + void * start; + void * end; // memory range name (if any) char name[1024]; // permission to read @@ -84,7 +84,7 @@ namespace DFHack bool execute : 1; // is a shared region bool shared : 1; - inline bool isInRange( uint64_t address) + inline bool isInRange( void * address) { if (address >= start && address < end) return true; return false; @@ -104,99 +104,110 @@ namespace DFHack Process(VersionInfoFactory * known_versions); ~Process(); /// read a 8-byte integer - uint64_t readQuad(const uint32_t address) + uint64_t readQuad(const void * address) { return *(uint64_t *)address; } /// read a 8-byte integer - void readQuad(const uint32_t address, uint64_t & value) + void readQuad(const void * address, uint64_t & value) { value = *(uint64_t *)address; }; /// write a 8-byte integer - void writeQuad(const uint32_t address, const uint64_t value) + void writeQuad(const void * address, const uint64_t value) { (*(uint64_t *)address) = value; }; /// read a 4-byte integer - uint32_t readDWord(const uint32_t address) + uint32_t readDWord(const void * address) { return *(uint32_t *)address; } /// read a 4-byte integer - void readDWord(const uint32_t address, uint32_t & value) + void readDWord(const void * address, uint32_t & value) { value = *(uint32_t *)address; }; /// write a 4-byte integer - void writeDWord(const uint32_t address, const uint32_t value) + void writeDWord(const void * address, const uint32_t value) { (*(uint32_t *)address) = value; }; + /// read a pointer + void * readPtr(const void * address) + { + return *(void **)address; + } + /// read a pointer + void readPtr(const void * address, void * & value) + { + value = *(void **)address; + }; + /// read a float - float readFloat(const uint32_t address) + float readFloat(const void * address) { return *(float*)address; } /// write a float - void readFloat(const uint32_t address, float & value) + void readFloat(const void * address, float & value) { value = *(float*)address; }; /// read a 2-byte integer - uint16_t readWord(const uint32_t address) + uint16_t readWord(const void * address) { return *(uint16_t *)address; } /// read a 2-byte integer - void readWord(const uint32_t address, uint16_t & value) + void readWord(const void * address, uint16_t & value) { value = *(uint16_t *)address; }; /// write a 2-byte integer - void writeWord(const uint32_t address, const uint16_t value) + void writeWord(const void * address, const uint16_t value) { (*(uint16_t *)address) = value; }; /// read a byte - uint8_t readByte(const uint32_t address) + uint8_t readByte(const void * address) { return *(uint8_t *)address; } /// read a byte - void readByte(const uint32_t address, uint8_t & value) + void readByte(const void * address, uint8_t & value) { value = *(uint8_t *)address; }; /// write a byte - void writeByte(const uint32_t address, const uint8_t value) + void writeByte(const void * address, const uint8_t value) { (*(uint8_t *)address) = value; }; /// read an arbitrary amount of bytes - void read( uint32_t address, uint32_t length, uint8_t* buffer) + void read(void * address, uint32_t length, uint8_t* buffer) { memcpy(buffer, (void *) address, length); }; /// write an arbitrary amount of bytes - void write(uint32_t address, uint32_t length, uint8_t* buffer) + void write(void * address, uint32_t length, uint8_t* buffer) { memcpy((void *) address, buffer, length); }; /// read an STL string - const std::string readSTLString (uint32_t offset) + const std::string readSTLString (void * offset) { std::string * str = (std::string *) offset; return *str; }; /// read an STL string - size_t readSTLString (uint32_t offset, char * buffer, size_t bufcapacity) + size_t readSTLString (void * offset, char * buffer, size_t bufcapacity) { if(!bufcapacity || bufcapacity == 1) return 0; @@ -209,7 +220,7 @@ namespace DFHack * write an STL string * @return length written */ - size_t writeSTLString(const uint32_t address, const std::string writeString) + size_t writeSTLString(const void * address, const std::string writeString) { std::string * str = (std::string *) address; str->assign(writeString); @@ -219,7 +230,7 @@ namespace DFHack * attempt to copy a string from source address to target address. may truncate or leak, depending on platform * @return length copied */ - size_t copySTLString(const uint32_t address, const uint32_t target) + size_t copySTLString(const void * address, const uint32_t target) { std::string * strsrc = (std::string *) address; std::string * str = (std::string *) target; @@ -239,7 +250,7 @@ namespace DFHack } /// read a null-terminated C string - const std::string readCString (uint32_t offset) + const std::string readCString (void * offset) { return std::string((char *) offset); }; diff --git a/library/include/Vector.h b/library/include/Vector.h deleted file mode 100644 index 4ba9dd152..000000000 --- a/library/include/Vector.h +++ /dev/null @@ -1,96 +0,0 @@ -/* -https://github.com/peterix/dfhack -Copyright (c) 2009-2011 Petr Mrázek (peterix@gmail.com) - -This software is provided 'as-is', without any express or implied -warranty. In no event will the authors be held liable for any -damages arising from the use of this software. - -Permission is granted to anyone to use this software for any -purpose, including commercial applications, and to alter it and -redistribute it freely, subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must -not claim that you wrote the original software. If you use this -software in a product, an acknowledgment in the product documentation -would be appreciated but is not required. - -2. Altered source versions must be plainly marked as such, and -must not be misrepresented as being the original software. - -3. This notice may not be removed or altered from any source -distribution. -*/ - - -#pragma once - -#ifndef DFVECTOR_H_INCLUDED -#define DFVECTOR_H_INCLUDED - -#include "Pragma.h" -#include "Export.h" -#include "VersionInfo.h" -#include "MemAccess.h" - -#include -#include - -namespace DFHack -{ - template - class DFHACK_EXPORT DfVector - { - private: - std::vector * real_vec; - public: - DfVector(uint32_t address) - { - real_vec = (std::vector *) address; - }; - ~DfVector() - { - }; - // get offset of the specified index - inline const T& operator[] (uint32_t index) - { - // FIXME: vector out of bounds exception - //assert(index < size); - return real_vec->at(index); - }; - // get offset of the specified index - inline const T& at (uint32_t index) - { - //assert(index < size); - return real_vec->at(index); - }; - // update value at index - bool set(uint32_t index, T value) - { - if (index >= real_vec->size()) - return false; - real_vec->at(index) = value; - return true; - } - // remove value - bool remove(uint32_t index) - { - if (index >= real_vec->size()) - return false; - // Remove the item - real_vec->erase(real_vec->begin() + index); - return true; - } - // get vector size - inline uint32_t size () - { - return real_vec->size(); - }; - // get vector start - inline const T * start () - { - return real_vec->data(); - }; - }; -} -#endif // DFVECTOR_H_INCLUDED diff --git a/library/include/VersionInfo.h b/library/include/VersionInfo.h index 47c9ba211..b46866a4a 100644 --- a/library/include/VersionInfo.h +++ b/library/include/VersionInfo.h @@ -88,13 +88,13 @@ namespace DFHack OffsetGroup * createGroup ( const std::string & name ); int32_t getOffset (const std::string & key); - uint32_t getAddress (const std::string & key); + void * getAddress (const std::string & key); uint32_t getHexValue (const std::string & key); std::string getString (const std::string & key); OffsetGroup * getGroup ( const std::string & name ); bool getSafeOffset (const std::string & key, int32_t & out); - bool getSafeAddress (const std::string & key, uint32_t & out); + bool getSafeAddress (const std::string & key, void * & out); void setOffset (const std::string& key, const std::string& value, const DFHack::INVAL_TYPE inval = IS_VALID); void setOffsetValidity(const std::string& key, const DFHack::INVAL_TYPE inval = IS_VALID); @@ -189,7 +189,7 @@ namespace DFHack * uses memory reading directly, needs suspend. input = address of the object * fails if it's unable to read from memory */ - bool resolveObjectToClassID (const uint32_t address, int32_t & classID); + bool resolveObjectToClassID (const void * address, int32_t & classID); /** * Get a ClassID when you know the classname. can fail if the class is not in the cache diff --git a/library/include/modules/Buildings.h b/library/include/modules/Buildings.h index 330c151dc..d4f90d016 100644 --- a/library/include/modules/Buildings.h +++ b/library/include/modules/Buildings.h @@ -42,7 +42,7 @@ namespace DFHack */ struct t_building { - uint32_t origin; + void * origin; uint32_t vtable; uint32_t x1; uint32_t y1; diff --git a/library/include/modules/Constructions.h b/library/include/modules/Constructions.h index c7cd693e8..85c9175dc 100644 --- a/library/include/modules/Constructions.h +++ b/library/include/modules/Constructions.h @@ -74,7 +74,7 @@ namespace DFHack uint32_t unk6; /// Address of the read object in DF memory. Added by DFHack. - uint32_t origin; + t_construction * origin; }; #pragma pack (pop) class DFContextShared; diff --git a/library/include/modules/Engravings.h b/library/include/modules/Engravings.h index 7e145959b..ffd050229 100644 --- a/library/include/modules/Engravings.h +++ b/library/include/modules/Engravings.h @@ -97,7 +97,7 @@ namespace DFHack struct dfh_engraving { t_engraving s; - uint32_t origin; + t_engraving * origin; }; /** * The Engravings module - allows reading engravings :D diff --git a/library/include/modules/Maps.h b/library/include/modules/Maps.h index 7e01a03d1..9d60f33e5 100644 --- a/library/include/modules/Maps.h +++ b/library/include/modules/Maps.h @@ -149,7 +149,7 @@ namespace DFHack /// placeholder bool discovered; /// this is NOT part of the DF feature, but an address of the feature as seen by DFhack. - uint32_t origin; + void * origin; }; diff --git a/library/include/modules/Vermin.h b/library/include/modules/Vermin.h index 01ef3d4ae..3c5506fc1 100644 --- a/library/include/modules/Vermin.h +++ b/library/include/modules/Vermin.h @@ -18,7 +18,7 @@ namespace DFHack */ struct t_spawnPoint { - uint32_t origin; + void * origin; int16_t race; uint16_t type; uint16_t x; diff --git a/library/modules/Buildings.cpp b/library/modules/Buildings.cpp index fbef81315..a162549b4 100644 --- a/library/modules/Buildings.cpp +++ b/library/modules/Buildings.cpp @@ -32,7 +32,6 @@ using namespace std; #include "VersionInfo.h" #include "MemAccess.h" -#include "Vector.h" #include "Types.h" #include "Error.h" #include "modules/Buildings.h" @@ -58,13 +57,12 @@ struct t_building_df40d struct Buildings::Private { - uint32_t buildings_vector; - uint32_t custom_workshop_vector; + vector * custom_workshop_vector; uint32_t building_custom_workshop_type; uint32_t custom_workshop_type; uint32_t custom_workshop_name; int32_t custom_workshop_id; - DfVector * p_bld; + vector * p_bld; Process * owner; bool Inited; bool hasCustomWorkshops; @@ -88,7 +86,7 @@ Buildings::Buildings() d->Inited = true; try { - d->buildings_vector = OG_build->getAddress ("buildings_vector"); + d->p_bld = (decltype(d->p_bld)) OG_build->getAddress ("buildings_vector"); } catch(DFHack::Error::AllMemdef &e) { @@ -99,7 +97,7 @@ Buildings::Buildings() { try { - d->custom_workshop_vector = OG_build->getAddress("custom_workshop_vector"); + d->custom_workshop_vector =(decltype(d->custom_workshop_vector)) OG_build->getAddress ("custom_workshop_vector"); d->building_custom_workshop_type = OG_build->getOffset("building_custom_workshop_type"); d->custom_workshop_type = OG_build->getOffset("custom_workshop_type"); d->custom_workshop_name = OG_build->getOffset("custom_workshop_name"); @@ -124,7 +122,6 @@ bool Buildings::Start(uint32_t & numbuildings) { if(!d->Inited) return false; - d->p_bld = new DfVector (d->buildings_vector); numbuildings = d->p_bld->size(); d->Started = true; return true; @@ -134,37 +131,25 @@ bool Buildings::Read (const uint32_t index, t_building & building) { if(!d->Started) return false; - t_building_df40d bld_40d; - - // read pointer from vector at position - uint32_t temp = d->p_bld->at (index); - //d->p_bld->read(index,(uint8_t *)&temp); - - //read building from memory - d->owner->read (temp, sizeof (t_building_df40d), (uint8_t *) &bld_40d); + t_building_df40d *bld_40d = d->p_bld->at (index); // transform int32_t type = -1; - d->owner->getDescriptor()->resolveObjectToClassID (temp, type); - building.origin = temp; - building.vtable = bld_40d.vtable; - building.x1 = bld_40d.x1; - building.x2 = bld_40d.x2; - building.y1 = bld_40d.y1; - building.y2 = bld_40d.y2; - building.z = bld_40d.z; - building.material = bld_40d.material; + d->owner->getDescriptor()->resolveObjectToClassID (bld_40d, type); + building.origin = bld_40d; + building.vtable = bld_40d->vtable; + building.x1 = bld_40d->x1; + building.x2 = bld_40d->x2; + building.y1 = bld_40d->y1; + building.y2 = bld_40d->y2; + building.z = bld_40d->z; + building.material = bld_40d->material; building.type = type; return true; } bool Buildings::Finish() { - if(d->p_bld) - { - delete d->p_bld; - d->p_bld = NULL; - } d->Started = false; return true; } @@ -177,14 +162,14 @@ bool Buildings::ReadCustomWorkshopTypes(map & btypes) return false; Process * p = d->owner; - DfVector p_matgloss (d->custom_workshop_vector); - uint32_t size = p_matgloss.size(); + uint32_t size = d->custom_workshop_vector->size(); btypes.clear(); for (uint32_t i = 0; i < size;i++) { - string out = p->readSTLString (p_matgloss[i] + d->custom_workshop_name); - uint32_t type = p->readDWord (p_matgloss[i] + d->custom_workshop_type); + void * obj = d->custom_workshop_vector->at(i); + string out = p->readSTLString (obj + d->custom_workshop_name); + uint32_t type = p->readDWord (obj + d->custom_workshop_type); #ifdef DEBUG cout << out << ": " << type << endl; #endif diff --git a/library/modules/Constructions.cpp b/library/modules/Constructions.cpp index 8081560ae..1ae5f8337 100644 --- a/library/modules/Constructions.cpp +++ b/library/modules/Constructions.cpp @@ -33,7 +33,6 @@ using namespace std; #include "VersionInfo.h" #include "MemAccess.h" -#include "Vector.h" #include "Types.h" #include "modules/Constructions.h" #include "ModuleFactory.h" @@ -43,10 +42,7 @@ using namespace DFHack; struct Constructions::Private { - uint32_t construction_vector; - // translation - DfVector * p_cons; - + vector * p_cons; Process * owner; bool Inited; bool Started; @@ -62,10 +58,9 @@ Constructions::Constructions() Core & c = Core::getInstance(); d = new Private; d->owner = c.p; - d->p_cons = 0; d->Inited = d->Started = false; VersionInfo * mem = c.vinfo; - d->construction_vector = mem->getGroup("Constructions")->getAddress ("vector"); + d->p_cons = (decltype(d->p_cons)) mem->getGroup("Constructions")->getAddress ("vector"); d->Inited = true; } @@ -78,7 +73,6 @@ Constructions::~Constructions() bool Constructions::Start(uint32_t & numconstructions) { - d->p_cons = new DfVector (d->construction_vector); numconstructions = d->p_cons->size(); d->Started = true; return true; @@ -89,24 +83,14 @@ bool Constructions::Read (const uint32_t index, t_construction & construction) { if(!d->Started) return false; - // read pointer from vector at position - uint32_t temp = d->p_cons->at (index); - - //read construction from memory - d->owner->read (temp, sizeof (t_construction), (uint8_t *) &construction); - - // transform - construction.origin = temp; + t_construction * orig = d->p_cons->at(index); + construction = *orig; + construction.origin = orig; return true; } bool Constructions::Finish() { - if(d->p_cons) - { - delete d->p_cons; - d->p_cons = NULL; - } d->Started = false; return true; } diff --git a/library/modules/Engravings.cpp b/library/modules/Engravings.cpp index 7f3b286bf..49588517e 100644 --- a/library/modules/Engravings.cpp +++ b/library/modules/Engravings.cpp @@ -31,8 +31,7 @@ distribution. using namespace std; #include "VersionInfo.h" -//#include "MemAccess.h" -#include "Vector.h" +#include "MemAccess.h" #include "Types.h" #include "modules/Engravings.h" #include "ModuleFactory.h" @@ -43,8 +42,7 @@ using namespace DFHack; struct Engravings::Private { uint32_t engraving_vector; - // translation - DfVector * p_engr; + vector * p_engr; Process * owner; bool Inited; @@ -61,9 +59,8 @@ Engravings::Engravings() Core & c = Core::getInstance(); d = new Private; d->owner = c.p; - d->p_engr = 0; d->Inited = d->Started = false; - d->engraving_vector = c.vinfo->getGroup("Engravings")->getAddress ("vector"); + d->p_engr = (decltype(d->p_engr)) c.vinfo->getGroup("Engravings")->getAddress ("vector"); d->Inited = true; } @@ -76,7 +73,8 @@ Engravings::~Engravings() bool Engravings::Start(uint32_t & numengravings) { - d->p_engr = new DfVector (d->engraving_vector); + if(!d->Inited) + return false; numengravings = d->p_engr->size(); d->Started = true; return true; @@ -88,13 +86,10 @@ bool Engravings::Read (const uint32_t index, dfh_engraving & engraving) if(!d->Started) return false; // read pointer from vector at position - uint32_t temp = d->p_engr->at (index); - - //read construction from memory - d->owner->read (temp, sizeof (t_engraving), (uint8_t *) &(engraving.s)); + engraving.s = *d->p_engr->at (index); // transform - engraving.origin = temp; + engraving.origin = d->p_engr->at (index); return true; } @@ -108,11 +103,6 @@ bool Engravings::Write (const dfh_engraving & engraving) bool Engravings::Finish() { - if(d->p_engr) - { - delete d->p_engr; - d->p_engr = NULL; - } d->Started = false; return true; } diff --git a/library/modules/Graphic.cpp b/library/modules/Graphic.cpp index b482b8e4f..2d288a1ef 100644 --- a/library/modules/Graphic.cpp +++ b/library/modules/Graphic.cpp @@ -37,7 +37,6 @@ using namespace std; #include "Error.h" #include "VersionInfo.h" #include "MemAccess.h" -#include "Vector.h" #include "ModuleFactory.h" #include "Core.h" diff --git a/library/modules/Gui.cpp b/library/modules/Gui.cpp index cd6f46f25..1a970deeb 100644 --- a/library/modules/Gui.cpp +++ b/library/modules/Gui.cpp @@ -91,16 +91,23 @@ struct Gui::Private } bool Started; - uint32_t window_x_offset; - uint32_t window_y_offset; - uint32_t window_z_offset; - uint32_t cursor_xyz_offset; - uint32_t designation_xyz_offset; - uint32_t mouse_xy_offset; - uint32_t window_dims_offset; + int32_t * window_x_offset; + int32_t * window_y_offset; + int32_t * window_z_offset; + struct xyz + { + int32_t x; + int32_t y; + int32_t z; + } * cursor_xyz_offset, * designation_xyz_offset; + struct xy + { + int32_t x; + int32_t y; + } * mouse_xy_offset, * window_dims_offset; bool StartedScreen; - uint32_t screen_tiles_ptr_offset; + void * screen_tiles_ptr_offset; Process * owner; }; @@ -157,19 +164,33 @@ Gui::Gui() try { OG_Position = mem->getGroup("Position"); - d->window_x_offset = OG_Position->getAddress ("window_x"); - d->window_y_offset = OG_Position->getAddress ("window_y"); - d->window_z_offset = OG_Position->getAddress ("window_z"); - d->cursor_xyz_offset = OG_Position->getAddress ("cursor_xyz"); - d->window_dims_offset = OG_Position->getAddress ("window_dims"); + d->window_x_offset = (int32_t *) OG_Position->getAddress ("window_x"); + d->window_y_offset = (int32_t *) OG_Position->getAddress ("window_y"); + d->window_z_offset = (int32_t *) OG_Position->getAddress ("window_z"); + d->cursor_xyz_offset = (Private::xyz *) OG_Position->getAddress ("cursor_xyz"); + d->window_dims_offset = (Private::xy *) OG_Position->getAddress ("window_dims"); d->Started = true; } catch(Error::All &){}; - OG_Position->getSafeAddress("mouse_xy", d->mouse_xy_offset); - OG_Position->getSafeAddress("designation_xyz", d->designation_xyz_offset); try { - d->screen_tiles_ptr_offset = OG_Position->getAddress ("screen_tiles_pointer"); + d->mouse_xy_offset = (Private::xy *) OG_Position->getAddress ("mouse_xy"); + } + catch(Error::All &) + { + d->mouse_xy_offset = 0; + }; + try + { + d->designation_xyz_offset = (Private::xyz *) OG_Position->getAddress ("designation_xyz"); + } + catch(Error::All &) + { + d->designation_xyz_offset = 0; + }; + try + { + d->screen_tiles_ptr_offset = (void *) OG_Position->getAddress ("screen_tiles_pointer"); d->StartedScreen = true; } catch(Error::All &){}; @@ -299,10 +320,10 @@ bool Gui::getScreenTiles (int32_t width, int32_t height, t_screen screen[]) { if(!d->StartedScreen) return false; - uint32_t screen_addr = d->owner->readDWord(d->screen_tiles_ptr_offset); + void * screen_addr = (void *) d->owner->readDWord(d->screen_tiles_ptr_offset); uint8_t* tiles = new uint8_t[width*height*4/* + 80 + width*height*4*/]; - d->owner->read (screen_addr, (width*height*4/* + 80 + width*height*4*/), (uint8_t *) tiles); + d->owner->read (screen_addr, (width*height*4/* + 80 + width*height*4*/), tiles); for(int32_t iy=0; iy idLookupTable; uint32_t refVectorOffset; uint32_t idFieldOffset; - uint32_t itemVectorAddress; + void * itemVectorAddress; ClassNameCheck isOwnerRefClass; ClassNameCheck isContainerRefClass; diff --git a/library/modules/Maps.cpp b/library/modules/Maps.cpp index 6cb34d6af..ebb0e4d79 100644 --- a/library/modules/Maps.cpp +++ b/library/modules/Maps.cpp @@ -37,7 +37,6 @@ using namespace std; #include "Error.h" #include "VersionInfo.h" #include "MemAccess.h" -#include "Vector.h" #include "ModuleFactory.h" #include "Core.h" @@ -96,7 +95,7 @@ struct Maps::Private FEATURES */ // FIXME: replace with a struct pointer, eventually. needs to be mapped out first - uint32_t world_data; + void * world_data; uint32_t local_f_start; // offset from world_data // FIXME: replace by virtual function call uint32_t local_material; @@ -122,7 +121,7 @@ struct Maps::Private set unknown_veins; // map between feature address and the read object - map local_feature_store; + map local_feature_store; map > m_local_feature; vector v_global_feature; @@ -142,7 +141,7 @@ Maps::Maps() // get the offsets once here OffsetGroup *OG_Maps = mem->getGroup("Maps"); - off.world_data = OG_Maps->getAddress("world_data"); + off.world_data = (void *) OG_Maps->getAddress("world_data"); { mdata = (map_data *) OG_Maps->getAddress ("map_data"); off.world_size_x = OG_Maps->getOffset ("world_size_x_from_wdata"); @@ -508,13 +507,13 @@ bool Maps::StartFeatures() Process * p = d->owner; Private::t_offsets &off = d->offsets; - uint32_t base = 0; - uint32_t global_feature_vector = 0; + void * base = 0; + void * global_feature_vector = 0; - uint32_t world = p->readDWord(off.world_data); + void * world = p->readPtr( (void *) off.world_data); if(!world) return false; - base = p->readDWord(world + off.local_f_start); - global_feature_vector = p->readDWord(off.world_data) + off.global_vector; + base = p->readPtr(world + off.local_f_start); + global_feature_vector = p->readDWord(off.world_data) + (void *) off.global_vector; // deref pointer to the humongo-structure if(!base) @@ -549,22 +548,21 @@ bool Maps::StartFeatures() // base = pointer to local feature structure (inside world data struct) // bigregion is 16x16 regions. for each bigregion in X dimension: - uint32_t mega_column = p->readDWord(base + bigregion_x * 4); + void * mega_column = p->readPtr(base + bigregion_x * 4); // 16B structs, second DWORD of the struct is a pointer - uint32_t loc_f_array16x16 = p->readDWord(mega_column + offset_elem + (sizeof_elem * bigregion_y)); + void * loc_f_array16x16 = p->readPtr(mega_column + offset_elem + (sizeof_elem * bigregion_y)); if(loc_f_array16x16) { - uint32_t feat_vector = loc_f_array16x16 + sizeof_16vec * sub_x + sizeof_vec * sub_y; - DfVector p_features(feat_vector); - uint32_t size = p_features.size(); + vector * p_features = (vector *) (loc_f_array16x16 + sizeof_16vec * sub_x + sizeof_vec * sub_y); + uint32_t size = p_features->size(); DFCoord pc(blockX,blockY); std::vector tempvec; for(uint32_t i = 0; i < size; i++) { - uint32_t cur_ptr = p_features[i]; + void * cur_ptr = p_features->at(i); - map ::iterator it; + map ::iterator it; it = d->local_feature_store.find(cur_ptr); // do we already have the feature? if(it != d->local_feature_store.end()) @@ -579,7 +577,7 @@ bool Maps::StartFeatures() // create, add to store t_feature tftemp; tftemp.discovered = false; //= p->readDWord(cur_ptr + 4); - tftemp.origin = cur_ptr; + tftemp.origin = (t_feature *) cur_ptr; string name = p->readClassName((void *)p->readDWord( cur_ptr )); if(name == "feature_init_deep_special_tubest") { @@ -611,17 +609,15 @@ bool Maps::StartFeatures() const uint32_t global_feature_funcptr = off.global_funcptr; const uint32_t glob_main_mat_offset = off.global_material; const uint32_t glob_sub_mat_offset = off.global_submaterial; - DfVector p_features (global_feature_vector); - + vector * p_features = (vector *) global_feature_vector; d->v_global_feature.clear(); - uint32_t size = p_features.size(); + uint32_t size = p_features->size(); d->v_global_feature.reserve(size); for(uint32_t i = 0; i < size; i++) { t_feature temp; - uint32_t feat_ptr = p->readDWord(p_features[i] + global_feature_funcptr ); + void * feat_ptr = p->readPtr(p_features->at(i) + global_feature_funcptr ); temp.origin = feat_ptr; - //temp.discovered = p->readDWord( feat_ptr + 4 ); // maybe, placeholder temp.discovered = false; // FIXME: use the memory_info cache mechanisms @@ -887,8 +883,8 @@ bool Maps::RemoveBlockEvent(uint32_t x, uint32_t y, uint32_t z, t_virtual * whic } /* - * Layer geology - */ +* Layer geology +*/ bool Maps::ReadGeology (vector < vector >& assign) { MAPS_GUARD @@ -896,17 +892,18 @@ bool Maps::ReadGeology (vector < vector >& assign) Process *p = d->owner; // get needed addresses and offsets. Now this is what I call crazy. uint16_t worldSizeX, worldSizeY; - uint32_t regions, geoblocks_vector_addr; + void *regions; + void *geoblocks_vector_addr; Private::t_offsets &off = d->offsets; // get world size - uint32_t world = p->readDWord(off.world_data); + void * world = p->readPtr(off.world_data); p->readWord (world + off.world_size_x, worldSizeX); p->readWord (world + off.world_size_y, worldSizeY); - regions = p->readDWord ( world + off.world_regions); // ptr2_region_array + regions = p->readPtr ( world + off.world_regions); // ptr2_region_array geoblocks_vector_addr = world + off.world_geoblocks_vector; // read the geoblock vector - DfVector geoblocks (geoblocks_vector_addr); + vector & geoblocks = *(vector *)(geoblocks_vector_addr); // iterate over 8 surrounding regions + local region for (int i = eNorthWest; i < eBiomeCount; i++) @@ -925,8 +922,8 @@ bool Maps::ReadGeology (vector < vector >& assign) /// regions are a 2d array. consists of pointers to arrays of regions /// regions are of region_size size // get pointer to column of regions - uint32_t geoX; - p->readDWord (regions + bioRX*4, geoX); + void * geoX; + p->readPtr (regions + bioRX*4, geoX); // get index into geoblock vector uint16_t geoindex; @@ -935,11 +932,11 @@ bool Maps::ReadGeology (vector < vector >& assign) /// geology blocks are assigned to regions from a vector // get the geoblock from the geoblock vector using the geoindex // read the matgloss pointer from the vector into temp - uint32_t geoblock_off = geoblocks[geoindex]; + void * geoblock_off = geoblocks[geoindex]; /// geology blocks have a vector of layer descriptors // get the vector with pointer to layers - DfVector geolayers (geoblock_off + off.geolayer_geoblock_offset); // let's hope + vector & geolayers = *(vector *)(geoblock_off + off.geolayer_geoblock_offset); // make sure we don't load crap assert (geolayers.size() > 0 && geolayers.size() <= 16); @@ -949,7 +946,7 @@ bool Maps::ReadGeology (vector < vector >& assign) for (uint32_t j = 0;j < geolayers.size();j++) { // read pointer to a layer - uint32_t geol_offset = geolayers[j]; + void * geol_offset = geolayers[j]; // read word at pointer + 2, store in our geology vectors d->v_geology[i].push_back (p->readWord (geol_offset + off.type_inside_geolayer)); } diff --git a/library/modules/Materials.cpp b/library/modules/Materials.cpp index c77a62bd7..18170eff5 100644 --- a/library/modules/Materials.cpp +++ b/library/modules/Materials.cpp @@ -35,7 +35,6 @@ using namespace std; #include "modules/Materials.h" #include "VersionInfo.h" #include "MemAccess.h" -#include "Vector.h" #include "Error.h" #include "ModuleFactory.h" #include "Core.h" @@ -52,8 +51,8 @@ class Materials::Private public: Process * owner; OffsetGroup * OG_Materials; - uint32_t vector_races; - uint32_t vector_other; + void * vector_races; + void * vector_other; }; Materials::Materials() @@ -67,10 +66,10 @@ Materials::Materials() df_inorganic = 0; OffsetGroup *OG_Materials = d->OG_Materials = c.vinfo->getGroup("Materials"); { - OG_Materials->getSafeAddress("inorganics",(uint32_t &)df_inorganic); - OG_Materials->getSafeAddress("organics_all",(uint32_t &)df_organic); - OG_Materials->getSafeAddress("organics_plants",(uint32_t &)df_plants); - OG_Materials->getSafeAddress("organics_trees",(uint32_t &)df_trees); + OG_Materials->getSafeAddress("inorganics",(void * &)df_inorganic); + OG_Materials->getSafeAddress("organics_all",(void * &)df_organic); + OG_Materials->getSafeAddress("organics_plants",(void * &)df_plants); + OG_Materials->getSafeAddress("organics_trees",(void * &)df_trees); d->vector_races = OG_Materials->getAddress("creature_type_vector"); } } @@ -111,16 +110,16 @@ bool t_matglossInorganic::isGem() } // good for now -inline bool ReadNamesOnly(Process* p, uint32_t address, vector & names) +inline bool ReadNamesOnly(Process* p, void * address, vector & names) { - DfVector p_matgloss (address); - uint32_t size = p_matgloss.size(); + vector * p_names = (vector *) address; + uint32_t size = p_names->size(); names.clear(); names.reserve (size); for (uint32_t i = 0; i < size;i++) { t_matgloss mat; - mat.id = *(std::string *)p_matgloss[i]; + mat.id = *p_names->at(i); names.push_back(mat); } return true; @@ -159,21 +158,21 @@ bool Materials::CopyInorganicMaterials (std::vector & inorg bool Materials::CopyOrganicMaterials (std::vector & organic) { if(df_organic) - return ReadNamesOnly(d->owner, (uint32_t) df_organic, organic ); + return ReadNamesOnly(d->owner, (void *) df_organic, organic ); else return false; } bool Materials::CopyWoodMaterials (std::vector & tree) { if(df_trees) - return ReadNamesOnly(d->owner, (uint32_t) df_trees, tree ); + return ReadNamesOnly(d->owner, (void *) df_trees, tree ); else return false; } bool Materials::CopyPlantMaterials (std::vector & plant) { if(df_plants) - return ReadNamesOnly(d->owner, (uint32_t) df_plants, plant ); + return ReadNamesOnly(d->owner, (void *) df_plants, plant ); else return false; } @@ -185,7 +184,7 @@ bool Materials::ReadCreatureTypes (void) bool Materials::ReadOthers(void) { Process * p = d->owner; - uint32_t matBase = d->OG_Materials->getAddress ("other"); + void * matBase = d->OG_Materials->getAddress ("other"); uint32_t i = 0; std::string * ptr; @@ -194,7 +193,7 @@ bool Materials::ReadOthers(void) while(1) { t_matglossOther mat; - ptr = (std::string *) p->readDWord(matBase + i*4); + ptr = (std::string *) p->readPtr(matBase + i*4); if(ptr==0) break; mat.id = *ptr; @@ -208,7 +207,7 @@ bool Materials::ReadDescriptorColors (void) { Process * p = d->owner; OffsetGroup * OG_Descriptors = p->getDescriptor()->getGroup("Materials")->getGroup("descriptors"); - DfVector p_colors (OG_Descriptors->getAddress ("colors_vector")); + vector & p_colors = *(vector *) OG_Descriptors->getAddress ("colors_vector"); uint32_t size = p_colors.size(); color.clear(); @@ -237,7 +236,7 @@ bool Materials::ReadCreatureTypesEx (void) uint32_t sizeof_string = OG_string->getHexValue ("sizeof"); OffsetGroup * OG_Mats = mem->getGroup("Materials"); - DfVector p_races (OG_Mats->getAddress ("creature_type_vector")); + vector & p_races = *(vector *) OG_Mats->getAddress ("creature_type_vector"); OffsetGroup * OG_Creature = OG_Mats->getGroup("creature"); uint32_t castes_vector_offset = OG_Creature->getOffset ("caste_vector"); @@ -287,13 +286,13 @@ bool Materials::ReadCreatureTypesEx (void) mat.tilecolor.back = p->readWord( p_races[i] + tile_color_offset + 2 ); mat.tilecolor.bright = p->readWord( p_races[i] + tile_color_offset + 4 ); - DfVector p_castes(p_races[i] + castes_vector_offset); + vector & p_castes = *(vector *) (p_races[i] + castes_vector_offset); sizecas = p_castes.size(); for (uint32_t j = 0; j < sizecas;j++) { /* caste name */ t_creaturecaste caste; - uint32_t caste_start = p_castes[j]; + void * caste_start = p_castes[j]; caste.id = p->readSTLString (caste_start); caste.singular = p->readSTLString (caste_start + sizeof_string); caste.plural = p->readSTLString (caste_start + 2 * sizeof_string); @@ -303,13 +302,13 @@ bool Materials::ReadCreatureTypesEx (void) { /* color mod reading */ // Caste + offset > color mod vector - DfVector p_colormod(caste_start + caste_colormod_offset); + vector & p_colormod = *(vector *) (caste_start + caste_colormod_offset); sizecolormod = p_colormod.size(); caste.ColorModifier.resize(sizecolormod); for(uint32_t k = 0; k < sizecolormod;k++) { // color mod [0] -> color list - DfVector p_colorlist(p_colormod[k]); + vector & p_colorlist = *(vector *) (p_colormod[k]); sizecolorlist = p_colorlist.size(); caste.ColorModifier[k].colorlist.resize(sizecolorlist); for(uint32_t l = 0; l < sizecolorlist; l++) @@ -320,7 +319,7 @@ bool Materials::ReadCreatureTypesEx (void) caste.ColorModifier[k].enddate = p->readDWord( p_colormod[k] + color_modifier_enddate_offset ); } /* body parts */ - DfVector p_bodypart(caste_start + caste_bodypart_offset); + vector & p_bodypart = *(vector *) (caste_start + caste_bodypart_offset); caste.bodypart.empty(); sizebp = p_bodypart.size(); for(uint32_t k = 0; k < sizebp; k++) @@ -338,7 +337,7 @@ bool Materials::ReadCreatureTypesEx (void) } mat.castes.push_back(caste); } - DfVector p_extract(p_races[i] + extract_vector_offset); + vector & p_extract = *(vector *) (p_races[i] + extract_vector_offset); for(uint32_t j = 0; j < p_extract.size(); j++) { t_creatureextract extract; diff --git a/library/modules/Translation.cpp b/library/modules/Translation.cpp index 9c2af7901..210186e41 100644 --- a/library/modules/Translation.cpp +++ b/library/modules/Translation.cpp @@ -33,7 +33,6 @@ using namespace std; #include "modules/Translation.h" #include "VersionInfo.h" #include "MemAccess.h" -#include "Vector.h" #include "Types.h" #include "ModuleFactory.h" #include "Core.h" @@ -46,8 +45,8 @@ Module* DFHack::createTranslation() struct Translation::Private { - uint32_t genericAddress; - uint32_t transAddress; + void * genericAddress; + void * transAddress; uint32_t word_table_offset; uint32_t sizeof_string; @@ -97,15 +96,15 @@ bool Translation::Start() return false; Process * p = c.p; Finish(); - DfVector genericVec (d->genericAddress); - DfVector transVec (d->transAddress); + vector & genericVec = *(vector *) d->genericAddress; + vector & transVec = *(vector *) d->transAddress; DFDict & translations = d->dicts.translations; DFDict & foreign_languages = d->dicts.foreign_languages; translations.resize(10); for (uint32_t i = 0;i < genericVec.size();i++) { - uint32_t genericNamePtr = genericVec.at(i); + void * genericNamePtr = genericVec[i]; for(int j=0; j<10;j++) { string word = p->readSTLString (genericNamePtr + j * d->sizeof_string); @@ -116,11 +115,11 @@ bool Translation::Start() foreign_languages.resize(transVec.size()); for (uint32_t i = 0; i < transVec.size();i++) { - uint32_t transPtr = transVec.at(i); - DfVector trans_names_vec (transPtr + d->word_table_offset); + void * transPtr = transVec.at(i); + vector & trans_names_vec = *(vector *) (transPtr + d->word_table_offset); for (uint32_t j = 0;j < trans_names_vec.size();j++) { - uint32_t transNamePtr = trans_names_vec.at(j); + void * transNamePtr = trans_names_vec[j]; string name = p->readSTLString (transNamePtr); foreign_languages[i].push_back (name); } diff --git a/library/modules/Units.cpp b/library/modules/Units.cpp index 368a198ec..2d68be559 100644 --- a/library/modules/Units.cpp +++ b/library/modules/Units.cpp @@ -36,7 +36,6 @@ using namespace std; #include "VersionInfo.h" #include "MemAccess.h" -#include "Vector.h" #include "Error.h" #include "Types.h" @@ -54,8 +53,8 @@ struct Units::Private bool Inited; bool Started; - uint32_t dwarf_race_index_addr; - uint32_t dwarf_civ_id_addr; + void * dwarf_race_index_addr; + void * dwarf_civ_id_addr; bool IdMapReady; std::map IdMap; @@ -86,8 +85,8 @@ Units::Units() try { creatures = (vector *) OG_Creatures->getAddress ("vector"); - d->dwarf_race_index_addr = OG_Creatures->getAddress("current_race"); - d->dwarf_civ_id_addr = OG_Creatures->getAddress("current_civ"); + d->dwarf_race_index_addr = (void *) OG_Creatures->getAddress("current_race"); + d->dwarf_civ_id_addr = (void *) OG_Creatures->getAddress("current_civ"); } catch(Error::All&){}; d->Inited = true; diff --git a/library/modules/Vegetation.cpp b/library/modules/Vegetation.cpp index c30e26157..fe07d97b8 100644 --- a/library/modules/Vegetation.cpp +++ b/library/modules/Vegetation.cpp @@ -32,7 +32,6 @@ using namespace std; #include "VersionInfo.h" #include "MemAccess.h" -#include "Vector.h" #include "Types.h" #include "modules/Vegetation.h" #include "modules/Translation.h" diff --git a/library/modules/Vermin.cpp b/library/modules/Vermin.cpp index f685c4eed..3cad35300 100644 --- a/library/modules/Vermin.cpp +++ b/library/modules/Vermin.cpp @@ -40,7 +40,7 @@ using namespace DFHack; struct Vermin::Private { - uint32_t spawn_points_vector; + void * spawn_points_vector; uint32_t race_offset; uint32_t type_offset; uint32_t position_offset; @@ -140,7 +140,7 @@ bool SpawnPoints::Read (const uint32_t index, t_spawnPoint & sp) return false; // read pointer from vector at position - uint32_t temp = (uint32_t) p_sp->at (index); + void * temp = p_sp->at (index); sp.origin = temp; sp.race = v->d->owner->readWord(temp + v->d->race_offset); @@ -161,7 +161,7 @@ bool SpawnPoints::Write (const uint32_t index, t_spawnPoint & sp) return false; // read pointer from vector at position - uint32_t temp = (uint32_t) p_sp->at (index); + void * temp = p_sp->at (index); v->d->owner->writeWord(temp + v->d->race_offset, sp.race); v->d->owner->writeWord(temp + v->d->type_offset, sp.type); diff --git a/library/modules/World.cpp b/library/modules/World.cpp index 0402c7f18..18e70fbde 100644 --- a/library/modules/World.cpp +++ b/library/modules/World.cpp @@ -54,22 +54,22 @@ struct World::Private bool Inited; bool PauseInited; - uint32_t pause_state_offset; + void * pause_state_offset; bool StartedTime; - uint32_t year_offset; - uint32_t tick_offset; + void * year_offset; + void * tick_offset; bool StartedWeather; - uint32_t weather_offset; + void * weather_offset; bool StartedMode; - uint32_t gamemode_offset; - uint32_t controlmode_offset; - uint32_t controlmodecopy_offset; + void * gamemode_offset; + void * controlmode_offset; + void * controlmodecopy_offset; bool StartedFolder; - uint32_t folder_name_offset; + void * folder_name_offset; Process * owner; }; diff --git a/library/modules/kitchen.cpp b/library/modules/kitchen.cpp index 78869ae26..c127f67c5 100644 --- a/library/modules/kitchen.cpp +++ b/library/modules/kitchen.cpp @@ -12,7 +12,6 @@ using namespace std; #include "Types.h" #include "VersionInfo.h" #include "MemAccess.h" -#include "Vector.h" #include "modules/Materials.h" #include "modules/Items.h" #include "modules/Units.h" @@ -44,9 +43,9 @@ namespace Kitchen std::vector& materialIndices; // the material index vector of the kitchen exclusion list std::vector& exclusionTypes; // the exclusion type vector of the kitchen excluions list - static uint32_t addr(const DFHack::Core& core, int index) + static void * addr(const DFHack::Core& core, int index) { - static uint32_t start = core.vinfo->getAddress("kitchen_limits"); + static void * start = core.vinfo->getAddress("kitchen_limits"); return start + sizeof(std::vector) * index; }; }; diff --git a/plugins/Dfusion/include/hexsearch.h b/plugins/Dfusion/include/hexsearch.h index 3a939b088..41223dee7 100644 --- a/plugins/Dfusion/include/hexsearch.h +++ b/plugins/Dfusion/include/hexsearch.h @@ -15,20 +15,20 @@ public: ANYBYTE=0x101,DWORD_,ANYDWORD,ADDRESS }; - Hexsearch(const SearchArgType &args,uint64_t startpos,uint64_t endpos); + Hexsearch(const SearchArgType &args,void * startpos,void * endpos); ~Hexsearch(); void Reset(){pos_=startpos_;}; - void SetStart(uint64_t pos){pos_=pos;}; + void SetStart(void * pos){pos_=pos;}; - uint64_t FindNext(); - std::vector FindAll(); + void * FindNext(); + std::vector FindAll(); private: bool Compare(int a,int b); void ReparseArgs(); SearchArgType args_; - uint64_t pos_,startpos_,endpos_; + void * pos_,* startpos_,* endpos_; std::vector BadCharShifts,GoodSuffixShift; void PrepareGoodSuffixTable(); void PrepareBadCharShift(); diff --git a/plugins/Dfusion/src/hexsearch.cpp b/plugins/Dfusion/src/hexsearch.cpp index 1958086ce..4c58f236d 100644 --- a/plugins/Dfusion/src/hexsearch.cpp +++ b/plugins/Dfusion/src/hexsearch.cpp @@ -1,7 +1,7 @@ #include "hexsearch.h" -Hexsearch::Hexsearch(const SearchArgType &args,uint64_t startpos,uint64_t endpos):args_(args),pos_(startpos),startpos_(startpos),endpos_(endpos) +Hexsearch::Hexsearch(const SearchArgType &args,void * startpos,void * endpos):args_(args),pos_(startpos),startpos_(startpos),endpos_(endpos) { ReparseArgs(); } @@ -52,7 +52,7 @@ void Hexsearch::ReparseArgs() } } } -uint64_t Hexsearch::FindNext() //TODO rewrite using Boyer-Moore algorithm +void * Hexsearch::FindNext() //TODO rewrite using Boyer-Moore algorithm { DFHack::Core &inst=DFHack::Core::getInstance(); DFHack::Process *p=inst.p; @@ -81,16 +81,16 @@ uint64_t Hexsearch::FindNext() //TODO rewrite using Boyer-Moore algorithm return pos_-args_.size(); } } - pos_++; + pos_ = pos_ + 1; } delete [] buf; return 0; } -std::vector Hexsearch::FindAll() +std::vector Hexsearch::FindAll() { - std::vector ret; - uint64_t cpos=pos_; + std::vector ret; + void * cpos=pos_; while(cpos!=0) { cpos=FindNext(); diff --git a/plugins/Dfusion/src/lua_Hexsearch.cpp b/plugins/Dfusion/src/lua_Hexsearch.cpp index 49a8edc02..b7d785495 100644 --- a/plugins/Dfusion/src/lua_Hexsearch.cpp +++ b/plugins/Dfusion/src/lua_Hexsearch.cpp @@ -2,14 +2,14 @@ int lua::Hexsearch::find(lua_State *L) { lua::state st(L); - uint64_t pos=p->FindNext(); + void * pos=p->FindNext(); st.push(pos); return 1; } int lua::Hexsearch::findall(lua_State *L) { lua::state st(L); - std::vector pos=p->FindAll(); + std::vector pos=p->FindAll(); st.newtable(); for(unsigned i=0;i(1); - end=st.as(2); + start= (void *)st.as(1); + end=(void *)st.as(2); for(int i=3;i<=st.gettop();i++) { args.push_back(st.as(i)); diff --git a/plugins/Dfusion/src/lua_Misc.cpp b/plugins/Dfusion/src/lua_Misc.cpp index 13eb618f8..895f1cb61 100644 --- a/plugins/Dfusion/src/lua_Misc.cpp +++ b/plugins/Dfusion/src/lua_Misc.cpp @@ -32,7 +32,7 @@ static int LoadMod(lua_State *L) buf=new char[size]; f.GetText(buf); //std::cout<<"poking @:"<write(pos,size,(uint8_t*)buf); + DFHack::Core::getInstance().p->write((void *) pos,size,(uint8_t*)buf); delete [] buf; st.push(pos); st.push(size); diff --git a/plugins/Dfusion/src/lua_Process.cpp b/plugins/Dfusion/src/lua_Process.cpp index ea96f8ac8..8ea73e973 100644 --- a/plugins/Dfusion/src/lua_Process.cpp +++ b/plugins/Dfusion/src/lua_Process.cpp @@ -14,7 +14,7 @@ static int lua_Process_readDWord(lua_State *S) { lua::state st(S); DFHack::Process* c=GetProcessPtr(st); - uint32_t ret=c->readDWord(st.as(1)); + uint32_t ret=c->readDWord( (void *) st.as(1)); st.push(ret); return 1; } @@ -22,14 +22,14 @@ static int lua_Process_writeDWord(lua_State *S) { lua::state st(S); DFHack::Process* c=GetProcessPtr(st); - c->writeDWord(st.as(1),st.as(2)); + c->writeDWord((void *) st.as(1),st.as(2)); return 0; } static int lua_Process_readFloat(lua_State *S) { lua::state st(S); DFHack::Process* c=GetProcessPtr(st); - float ret=c->readFloat(st.as(1)); + float ret=c->readFloat((void *) st.as(1)); st.push(ret); return 1; } @@ -38,7 +38,7 @@ static int lua_Process_readWord(lua_State *S) { lua::state st(S); DFHack::Process* c=GetProcessPtr(st); - uint16_t ret=c->readWord(st.as(1)); + uint16_t ret=c->readWord((void *) st.as(1)); st.push(ret); return 1; } @@ -47,14 +47,14 @@ static int lua_Process_writeWord(lua_State *S) { lua::state st(S); DFHack::Process* c=GetProcessPtr(st); - c->writeWord(st.as(1),st.as(2)); + c->writeWord((void *) st.as(1),st.as(2)); return 0; } static int lua_Process_readByte(lua_State *S) { lua::state st(S); DFHack::Process* c=GetProcessPtr(st); - uint8_t ret=c->readByte(st.as(1)); + uint8_t ret=c->readByte((void *) st.as(1)); st.push(ret); return 1; } @@ -63,7 +63,7 @@ static int lua_Process_writeByte(lua_State *S) { lua::state st(S); DFHack::Process* c=GetProcessPtr(st); - c->writeByte(st.as(1),st.as(2)); + c->writeByte((void *) st.as(1),st.as(2)); return 0; } static int lua_Process_read(lua_State *S) @@ -77,7 +77,7 @@ static int lua_Process_read(lua_State *S) buf=(uint8_t*)lua_touserdata(st,3); else buf=new uint8_t[len]; - c->read(st.as(1),len,buf); + c->read((void *) st.as(1),len,buf); st.pushlightuserdata(buf); return 1; } @@ -85,14 +85,14 @@ static int lua_Process_write(lua_State *S) { lua::state st(S); DFHack::Process* c=GetProcessPtr(st); - c-> write(st.as(1),st.as(2),static_cast(lua_touserdata(st,3))); + c-> write((void *) st.as(1),st.as(2),static_cast(lua_touserdata(st,3))); return 0; } static int lua_Process_readSTLString (lua_State *S) { lua::state st(S); DFHack::Process* c=GetProcessPtr(st); - std::string r=c->readSTLString(st.as(1)); + std::string r=c->readSTLString((void *) st.as(1)); st.push(r); return 1; } @@ -101,14 +101,14 @@ static int lua_Process_writeSTLString(lua_State *S) { lua::state st(S); DFHack::Process* c=GetProcessPtr(st); - c->writeSTLString(st.as(1),st.as(2)); + c->writeSTLString((void *) st.as(1),st.as(2)); return 0; } static int lua_Process_copySTLString(lua_State *S) { lua::state st(S); DFHack::Process* c=GetProcessPtr(st); - c->copySTLString(st.as(1),st.as(2)); + c->copySTLString((void *) st.as(1),st.as(2)); return 0; } static int lua_Process_doReadClassName(lua_State *S) @@ -131,7 +131,7 @@ static int lua_Process_readCString (lua_State *S) { lua::state st(S); DFHack::Process* c=GetProcessPtr(st); - std::string r=c->readCString(st.as(1)); + std::string r=c->readCString((void *) st.as(1)); st.push(r); return 1; } @@ -226,10 +226,10 @@ static int lua_Process_setPermisions(lua_State *S) DFHack::t_memrange range,trange; st.getfield("start",1); - range.start=st.as(); + range.start= (void *)st.as(); st.pop(); st.getfield("end",1); - range.end=st.as(); + range.end= (void *)st.as(); st.pop(); st.getfield("read",2); diff --git a/plugins/Dfusion/src/lua_VersionInfo.cpp b/plugins/Dfusion/src/lua_VersionInfo.cpp index d6f90be15..4d463bb49 100644 --- a/plugins/Dfusion/src/lua_VersionInfo.cpp +++ b/plugins/Dfusion/src/lua_VersionInfo.cpp @@ -16,7 +16,7 @@ int OffsetGroup::getOffset(lua_State *L) int OffsetGroup::getAddress(lua_State *L) { lua::state st(L); - uint32_t ret=p->getAddress(st.as(1)); + uint32_t ret= (uint32_t)p->getAddress(st.as(1)); st.push(ret); return 1; } @@ -57,7 +57,7 @@ int OffsetGroup::getSafeOffset(lua_State *L) int OffsetGroup::getSafeAddress(lua_State *L) { lua::state st(L); - uint32_t out; + void * out; bool ret=p->getSafeAddress(st.as(1),out); st.push(ret); st.push(out); @@ -286,7 +286,7 @@ static int __lua_resolveObjectToClassID(lua_State *S) { lua::state st(S); int32_t ret; - bool output=DFHack::Core::getInstance().vinfo->resolveObjectToClassID(st.as(1),ret); + bool output=DFHack::Core::getInstance().vinfo->resolveObjectToClassID((void *)st.as(1),ret); st.push(output); st.push(ret); return 2; @@ -329,7 +329,7 @@ static int __lua_getOffset(lua_State *S) static int __lua_getAddress(lua_State *S) { lua::state st(S); - uint32_t ret=DFHack::Core::getInstance().vinfo->getAddress(st.as(1)); + void * ret=DFHack::Core::getInstance().vinfo->getAddress(st.as(1)); st.push(ret); return 1; } @@ -392,7 +392,7 @@ static int __lua_getSafeOffset(lua_State *S) static int __lua_getSafeAddress(lua_State *S) { lua::state st(S); - uint32_t out; + void * out; bool ret=DFHack::Core::getInstance().vinfo->getSafeAddress(st.as(1),out); st.push(ret); st.push(out); diff --git a/plugins/devel/memview.cpp b/plugins/devel/memview.cpp index a5c721101..030eb4cdc 100644 --- a/plugins/devel/memview.cpp +++ b/plugins/devel/memview.cpp @@ -17,7 +17,7 @@ static tthread::mutex* mymutex=0; struct memory_data { - size_t addr; + void * addr; size_t len; size_t refresh; int state; @@ -57,7 +57,7 @@ bool isAddr(uint32_t *trg,vector & ranges) { if(trg[0]%4==0) for(size_t i=0;ip->read(memdata.addr,memdata.len,memdata.buf); - outputHex(memdata.buf,memdata.lbuf,memdata.len,memdata.addr,c,memdata.ranges); + outputHex(memdata.buf,memdata.lbuf,memdata.len,(size_t)memdata.addr,c,memdata.ranges); memcpy(memdata.lbuf, memdata.buf, memdata.len); if(memdata.refresh==0) Deinit(); @@ -143,7 +143,7 @@ DFhackCExport command_result memview (Core * c, vector & parameters) { mymutex->lock(); c->p->getMemRanges(memdata.ranges); - memdata.addr=convert(parameters[0],true); + memdata.addr=(void *)convert(parameters[0],true); if(memdata.addr==0) { Deinit(); diff --git a/plugins/devel/vectors.cpp b/plugins/devel/vectors.cpp index 216b69868..777d661e7 100644 --- a/plugins/devel/vectors.cpp +++ b/plugins/devel/vectors.cpp @@ -19,9 +19,9 @@ using namespace DFHack; struct t_vecTriplet { - uint32_t start; - uint32_t end; - uint32_t alloc_end; + void * start; + void * end; + void * alloc_end; }; DFhackCExport command_result df_vectors (Core * c, @@ -74,7 +74,7 @@ static bool mightBeVec(vector &heap_ranges, // Vector length might not be a multiple of 4 if, for example, // it's a vector of uint8_t or uint16_t. However, the actual memory // allocated to the vector should be 4 byte aligned. - if ((vec->start % 4 != 0) || (vec->alloc_end % 4 != 0)) + if (((int)vec->start % 4 != 0) || ((int)vec->alloc_end % 4 != 0)) return false; for (size_t i = 0; i < heap_ranges.size(); i++) @@ -88,7 +88,7 @@ static bool mightBeVec(vector &heap_ranges, return false; } -static bool inAnyRange(vector &ranges, uint32_t ptr) +static bool inAnyRange(vector &ranges, void * ptr) { for (size_t i = 0; i < ranges.size(); i++) { @@ -141,7 +141,7 @@ static void vectorsUsage(Console &con) static void printVec(Console &con, const char* msg, t_vecTriplet *vec, uint32_t start, uint32_t pos) { - uint32_t length = vec->end - vec->start; + uint32_t length = (int)vec->end - (int)vec->start; uint32_t offset = pos - start; con.print("%8s offset %06p, addr %010p, start %010p, length %u\n", @@ -193,15 +193,15 @@ DFhackCExport command_result df_vectors (Core * c, vector & parameters) { t_memrange &range = heap_ranges[i]; - if (!range.isInRange(start)) + if (!range.isInRange((void *)start)) continue; // Found the range containing the start - if (!range.isInRange(end)) + if (!range.isInRange((void *)end)) { con.print("Scanning %u bytes would read past end of memory " "range.\n", bytes); - uint32_t diff = end - range.end; + uint32_t diff = end - (int)range.end; con.print("Cutting bytes down by %u.\n", diff); end = (uint32_t) range.end; @@ -242,7 +242,7 @@ DFhackCExport command_result df_vectors (Core * c, vector & parameters) { uint32_t ptr = * ( (uint32_t*) pos); - if (inAnyRange(heap_ranges, ptr)) + if (inAnyRange(heap_ranges, (void *) ptr)) { t_vecTriplet* vec = (t_vecTriplet*) ptr; @@ -320,7 +320,7 @@ DFhackCExport command_result df_clearvec (Core * c, vector & parameters continue; } - if (!inAnyRange(heap_ranges, addr)) + if (!inAnyRange(heap_ranges, (void *) addr)) { con << addr_str << " not in any valid address range." << std::endl; continue; @@ -338,7 +338,7 @@ DFhackCExport command_result df_clearvec (Core * c, vector & parameters addr = * ( (uint32_t*) addr); vec = (t_vecTriplet*) addr; - if (inAnyRange(heap_ranges, addr) && mightBeVec(heap_ranges, vec)) + if (inAnyRange(heap_ranges, (void *) addr) && mightBeVec(heap_ranges, vec)) { valid = true; ptr = true; From 99dda069de241920b19ad99ba8dbc88f166f1d91 Mon Sep 17 00:00:00 2001 From: Alexander Gavrilov Date: Wed, 4 Jan 2012 18:46:39 +0400 Subject: [PATCH 08/82] Update data definitions. --- library/include/modules/Materials.h | 9 ++++- library/modules/Materials.cpp | 13 +++++-- library/xml | 2 +- plugins/jobutils.cpp | 54 +++++++++++++++++------------ 4 files changed, 52 insertions(+), 26 deletions(-) diff --git a/library/include/modules/Materials.h b/library/include/modules/Materials.h index 372d9d491..c5f54cd91 100644 --- a/library/include/modules/Materials.h +++ b/library/include/modules/Materials.h @@ -47,6 +47,7 @@ namespace df struct plant_raw; struct creature_raw; struct historical_figure; + struct material_vec_ref; union job_material_category; } @@ -82,12 +83,18 @@ namespace DFHack public: MaterialInfo(int16_t type = -1, int32_t index = -1) { decode(type, index); } - MaterialInfo(df::item *item) { decode(item); } + template MaterialInfo(T *ptr) { decode(ptr); } bool isValid() const { return material != NULL; } bool decode(int16_t type, int32_t index = -1); bool decode(df::item *item); + bool decode(const df::material_vec_ref &vr, int idx); + + template bool decode(T *ptr) { + // Assume and exploit a certain naming convention + return ptr ? decode(ptr->mat_type, ptr->mat_index) : decode(-1); + } bool find(const std::string &token, const std::string &subtoken = std::string()); bool findBuiltin(const std::string &token); diff --git a/library/modules/Materials.cpp b/library/modules/Materials.cpp index 2e333f5f9..0faf26030 100644 --- a/library/modules/Materials.cpp +++ b/library/modules/Materials.cpp @@ -51,6 +51,7 @@ using namespace std; #include "df/job_material_category.h" #include "df/matter_state.h" +#include "df/material_vec_ref.h" using namespace DFHack; using namespace df::enums; @@ -58,9 +59,17 @@ using namespace df::enums; bool MaterialInfo::decode(df::item *item) { if (!item) - decode(-1); + return decode(-1); else - decode(item->getActualMaterial(), item->getActualMaterialIndex()); + return decode(item->getActualMaterial(), item->getActualMaterialIndex()); +} + +bool MaterialInfo::decode(const df::material_vec_ref &vr, int idx) +{ + if (idx < 0 || idx >= vr.mat_type.size() || idx >= vr.mat_index.size()) + return decode(-1); + else + return decode(vr.mat_type[idx], vr.mat_index[idx]); } bool MaterialInfo::decode(int16_t type, int32_t index) diff --git a/library/xml b/library/xml index 3455acedc..4857a4f5a 160000 --- a/library/xml +++ b/library/xml @@ -1 +1 @@ -Subproject commit 3455acedc525473cd8c5403d225a6078b661dfc8 +Subproject commit 4857a4f5af1a4174e5478f1221552826a60b36c5 diff --git a/plugins/jobutils.cpp b/plugins/jobutils.cpp index 83503ddc9..71ecc2b2c 100644 --- a/plugins/jobutils.cpp +++ b/plugins/jobutils.cpp @@ -18,6 +18,7 @@ #include #include #include +#include using std::vector; using std::string; @@ -102,7 +103,7 @@ static bool workshop_job_hotkey(Core *c, df::viewscreen *top) // No jobs? if (selected->jobs.empty() || - selected->jobs[0]->job_id == job_type::DestroyBuilding) + selected->jobs[0]->job_type == job_type::DestroyBuilding) return false; // Add job gui activated? @@ -169,7 +170,7 @@ static command_result job_material_in_job(Core *c, MaterialInfo &new_mat) if (!job) return CR_FAILURE; - MaterialInfo cur_mat(job->matType, job->matIndex); + MaterialInfo cur_mat(job); if (!cur_mat.isValid() || cur_mat.type != 0) { @@ -195,7 +196,7 @@ static command_result job_material_in_job(Core *c, MaterialInfo &new_mat) for (unsigned i = 0; i < job->job_items.size(); i++) { df::job_item *item = job->job_items[i]; - MaterialInfo item_mat(item->matType, item->matIndex); + MaterialInfo item_mat(item); if (item_mat != cur_mat) { @@ -206,18 +207,18 @@ static command_result job_material_in_job(Core *c, MaterialInfo &new_mat) } // Apply the substitution - job->matType = new_mat.type; - job->matIndex = new_mat.index; + job->mat_type = new_mat.type; + job->mat_index = new_mat.index; for (unsigned i = 0; i < job->job_items.size(); i++) { df::job_item *item = job->job_items[i]; - item->matType = new_mat.type; - item->matIndex = new_mat.index; + 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_id) << endl; + << "' to job " << ENUM_KEY_STR(job_type,job->job_type) << endl; return CR_OK; } @@ -226,8 +227,8 @@ static bool build_choice_matches(df::ui_build_item_req *req, df::build_req_choic { if (VIRTUAL_CAST_VAR(gen, df::build_req_choice_genst, choice)) { - if (gen->matType == new_mat.type && - gen->matIndex == new_mat.index && + if (gen->mat_type == new_mat.type && + gen->mat_index == new_mat.index && gen->used_count < gen->candidates.size()) { return true; @@ -289,14 +290,22 @@ static command_result job_material(Core * c, vector & parameters) static void print_job_item_details(Core *c, df::job *job, df::job_item *item) { - c->con << " Input Item: " << ENUM_KEY_STR(item_type,item->itemType); - if (item->itemSubtype != -1) - c->con << " [" << item->itemSubtype << "]"; - c->con << "; count=" << item->count << endl; - - MaterialInfo mat(item->matType, item->matIndex); - if (mat.isValid()) - c->con << " material: " << mat.toString() << endl; + c->con << " Input Item: " << ENUM_KEY_STR(item_type,item->item_type); + if (item->item_subtype != -1) + c->con << " [" << item->item_subtype << "]"; + if (item->quantity != 1) + c->con << "; quantity=" << item->quantity; + if (item->min_dimension >= 0) + c->con << "; min_dimension=" << item->min_dimension; + c->con << endl; + + MaterialInfo mat(item); + if (mat.isValid() || item->metal_ore >= 0) { + c->con << " material: " << mat.toString(); + if (item->metal_ore >= 0) + c->con << "; ore of " << MaterialInfo(0,item->metal_ore).toString(); + c->con << endl; + } if (item->flags1.whole) c->con << " flags1: " << bitfieldToString(item->flags1) << endl; @@ -309,15 +318,16 @@ static void print_job_item_details(Core *c, df::job *job, df::job_item *item) c->con << " reaction class: " << item->reaction_class << endl; if (!item->has_material_reaction_product.empty()) c->con << " reaction product: " << item->has_material_reaction_product << endl; + if (item->has_tool_use >= 0) + c->con << " tool use: " << ENUM_KEY_STR(tool_uses, item->has_tool_use) << endl; } static void print_job_details(Core *c, df::job *job) { - c->con << "Job " << job->id << ": " << ENUM_KEY_STR(job_type,job->job_id) - << " [" << job->x << "," << job->y << "," << job->z << "] (" - << bitfieldToString(job->flags) << ")" << endl; + c->con << "Job " << job->id << ": " << ENUM_KEY_STR(job_type,job->job_type) + << " (" << bitfieldToString(job->flags) << ")" << endl; - MaterialInfo mat(job->matType, job->matIndex); + MaterialInfo mat(job); if (mat.isValid() || job->material_category.whole) { c->con << " material: " << mat.toString(); From 284009e873b95eed32fae62703ab3bc59e8e905b Mon Sep 17 00:00:00 2001 From: Alexander Gavrilov Date: Wed, 4 Jan 2012 19:39:38 +0400 Subject: [PATCH 09/82] Add a hotkey command to duplicate jobs in workshops. --- Memory.xml | 5 ++ library/include/DataDefs.h | 1 + library/include/MiscUtils.h | 14 +++++ plugins/jobutils.cpp | 100 ++++++++++++++++++++++++++++++++++-- 4 files changed, 117 insertions(+), 3 deletions(-) diff --git a/Memory.xml b/Memory.xml index 729759445..62f20f9ab 100644 --- a/Memory.xml +++ b/Memory.xml @@ -1094,6 +1094,7 @@
+
@@ -2345,6 +2346,8 @@
+ +
cmake @@ -3230,6 +3233,8 @@
+ +
diff --git a/library/include/DataDefs.h b/library/include/DataDefs.h index d3899854d..ff61d08f5 100644 --- a/library/include/DataDefs.h +++ b/library/include/DataDefs.h @@ -204,6 +204,7 @@ namespace df { GLOBAL(gview,interface) \ GLOBAL(init,init) \ GLOBAL(d_init,d_init) \ + SIMPLE_GLOBAL(job_next_id,int) \ SIMPLE_GLOBAL(ui_look_cursor,int) \ SIMPLE_GLOBAL(ui_workshop_job_cursor,int) \ SIMPLE_GLOBAL(ui_workshop_in_add,bool) \ diff --git a/library/include/MiscUtils.h b/library/include/MiscUtils.h index 05be881ee..961904e5c 100644 --- a/library/include/MiscUtils.h +++ b/library/include/MiscUtils.h @@ -172,6 +172,20 @@ CT *binsearch_in_vector(const std::vector &vec, FT CT::*field, FT value) return idx < 0 ? NULL : vec[idx]; } +/* + * List + */ + +template +Link *linked_list_append(Link *head, Link *tail) +{ + while (head->next) + head = head->next; + head->next = tail; + tail->prev = head; + return tail; +} + /* * MISC */ diff --git a/plugins/jobutils.cpp b/plugins/jobutils.cpp index 71ecc2b2c..bca8696f5 100644 --- a/plugins/jobutils.cpp +++ b/plugins/jobutils.cpp @@ -17,8 +17,11 @@ #include #include #include +#include #include #include +#include +#include using std::vector; using std::string; @@ -30,13 +33,16 @@ using df::global::world; using df::global::ui; using df::global::ui_build_selector; using df::global::ui_workshop_job_cursor; +using df::global::job_next_id; -static bool wokshop_job_hotkey(Core *c, df::viewscreen *top); -static bool build_selector_hotkey(Core *c, df::viewscreen *top); +/* Plugin registration */ +static bool workshop_job_hotkey(Core *c, df::viewscreen *top); +static bool build_selector_hotkey(Core *c, df::viewscreen *top); static bool job_material_hotkey(Core *c, df::viewscreen *top); -static command_result job_material(Core *c, vector & parameters); +static command_result job_material(Core *c, vector & parameters); +static command_result job_duplicate(Core *c, vector & parameters); static command_result job_cmd(Core *c, vector & parameters); DFhackCExport const char * plugin_name ( void ) @@ -75,6 +81,17 @@ DFhackCExport command_result plugin_init (Core *c, std::vector & ); } + if (ui_workshop_job_cursor && job_next_id) { + commands.push_back( + PluginCommand( + "job-duplicate", "Duplicate the selected job in a workshop.", + job_duplicate, workshop_job_hotkey, + " - In 'q' mode, when a job is highlighted within a workshop\n" + " or furnace building, instantly duplicates the job.\n" + ) + ); + } + return CR_OK; } @@ -83,6 +100,8 @@ DFhackCExport command_result plugin_shutdown ( Core * c ) return CR_OK; } +/* UI state guards */ + static bool workshop_job_hotkey(Core *c, df::viewscreen *top) { using namespace ui_sidebar_mode; @@ -150,6 +169,8 @@ static bool job_material_hotkey(Core *c, df::viewscreen *top) build_selector_hotkey(c, top); } +/* job-material implementation */ + static df::job *getWorkshopJob(Core *c) { df::building *selected = world->selected_building; @@ -288,6 +309,79 @@ static command_result job_material(Core * c, vector & parameters) return CR_WRONG_USAGE; } +/* job-duplicate implementation */ + +static df::job *clone_job(df::job *job) +{ + df::job *pnew = new df::job(*job); + + pnew->id = (*job_next_id)++; + + // Clean out transient fields + pnew->flags.whole = 0; + pnew->flags.bits.repeat = job->flags.bits.repeat; + + pnew->completion_timer = -1; + pnew->items.clear(); + pnew->misc_links.clear(); + + // Link the job into the global list + pnew->list_link = new df::job_list_link(); + pnew->list_link->item = pnew; + + linked_list_append(&world->job_list, pnew->list_link); + + // Clone refs + for (int i = pnew->references.size()-1; i >= 0; i--) + { + df::general_ref *ref = pnew->references[i]; + + if (virtual_cast(ref)) + pnew->references.erase(pnew->references.begin()+i); + else + pnew->references[i] = ref->clone(); + } + + // Clone items + for (int i = pnew->job_items.size()-1; i >= 0; i--) + pnew->job_items[i] = new df::job_item(*pnew->job_items[i]); + + return pnew; +} + +static command_result job_duplicate(Core * c, vector & parameters) +{ + if (!parameters.empty()) + return CR_WRONG_USAGE; + + df::job *job = getWorkshopJob(c); + if (!job) + return CR_FAILURE; + + if (!job->misc_links.empty() || job->job_items.empty()) + { + c->con.printerr("Cannot duplicate job %s\n", ENUM_KEY_STR(job_type,job->job_type)); + return CR_FAILURE; + } + + df::building *building = world->selected_building; + if (building->jobs.size() >= 10) + { + c->con.printerr("Job list is already full.\n"); + return CR_FAILURE; + } + + // Actually clone + df::job *pnew = clone_job(job); + + int pos = ++*ui_workshop_job_cursor; + building->jobs.insert(building->jobs.begin()+pos, pnew); + + return CR_OK; +} + +/* Main job command implementation */ + static void print_job_item_details(Core *c, df::job *job, df::job_item *item) { c->con << " Input Item: " << ENUM_KEY_STR(item_type,item->item_type); From 4a596909684b261f9d22f2911abf86e7e9f5b6fc Mon Sep 17 00:00:00 2001 From: Alexander Gavrilov Date: Wed, 4 Jan 2012 20:22:56 +0400 Subject: [PATCH 10/82] Don't print empty parentheses without any flags to fill them. --- library/xml | 2 +- plugins/jobutils.cpp | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/library/xml b/library/xml index 4857a4f5a..e61e696e2 160000 --- a/library/xml +++ b/library/xml @@ -1 +1 @@ -Subproject commit 4857a4f5af1a4174e5478f1221552826a60b36c5 +Subproject commit e61e696e2a2bb6b24a86c9c01a26f3133509585e diff --git a/plugins/jobutils.cpp b/plugins/jobutils.cpp index bca8696f5..c89ca2f40 100644 --- a/plugins/jobutils.cpp +++ b/plugins/jobutils.cpp @@ -418,8 +418,10 @@ static void print_job_item_details(Core *c, df::job *job, df::job_item *item) static void print_job_details(Core *c, df::job *job) { - c->con << "Job " << job->id << ": " << ENUM_KEY_STR(job_type,job->job_type) - << " (" << bitfieldToString(job->flags) << ")" << endl; + c->con << "Job " << job->id << ": " << ENUM_KEY_STR(job_type,job->job_type); + if (job->flags.whole) + c->con << " (" << bitfieldToString(job->flags) << ")"; + c->con << endl; MaterialInfo mat(job); if (mat.isValid() || job->material_category.whole) From d612db09359f18712a5f217651c57a4f89355eb9 Mon Sep 17 00:00:00 2001 From: Warmist Date: Thu, 5 Jan 2012 10:58:53 +0200 Subject: [PATCH 11/82] Added binding to suspend/resume (engine.suspend and engine.resume in lua) --- plugins/Dfusion/src/lua_Misc.cpp | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/plugins/Dfusion/src/lua_Misc.cpp b/plugins/Dfusion/src/lua_Misc.cpp index 13eb618f8..1c7de39d1 100644 --- a/plugins/Dfusion/src/lua_Misc.cpp +++ b/plugins/Dfusion/src/lua_Misc.cpp @@ -183,6 +183,18 @@ static int Call_Df(lua_State *L) st.push(f.CallFunction(ptr,conv,args)); return 1; } +static int Suspend_Df(lua_State *L) +{ + lua::state st(L); + DFHack::Core::getInstance().Suspend(); + return 0; +} +static int Resume_Df(lua_State *L) +{ + lua::state st(L); + DFHack::Core::getInstance().Resume(); + return 0; +} const luaL_Reg lua_misc_func[]= { {"loadmod",LoadMod}, @@ -193,6 +205,8 @@ const luaL_Reg lua_misc_func[]= {"newmod",NewMod}, {"getpushvalue",Get_PushValue}, {"calldf",Call_Df}, + {"suspend",Suspend_Df}, + {"resume",Resume_Df}, {NULL,NULL} }; void lua::RegisterMisc(lua::state &st) From 687245abd92f11db0f6fdff405c77f708344eb07 Mon Sep 17 00:00:00 2001 From: Alexander Gavrilov Date: Thu, 5 Jan 2012 22:04:05 +0400 Subject: [PATCH 12/82] Allow setting job item materials. --- library/include/MiscUtils.h | 27 +++++++ library/include/modules/Materials.h | 13 ++++ library/modules/Materials.cpp | 111 ++++++++++++++++++++++++++++ library/xml | 2 +- plugins/jobutils.cpp | 77 ++++++++++++++++--- 5 files changed, 218 insertions(+), 12 deletions(-) diff --git a/library/include/MiscUtils.h b/library/include/MiscUtils.h index 961904e5c..5897994e3 100644 --- a/library/include/MiscUtils.h +++ b/library/include/MiscUtils.h @@ -70,6 +70,24 @@ void print_bits ( T val, DFHack::Console& out ) * Binary search in vectors. */ +template +int linear_index(const std::vector &vec, FT key) +{ + for (unsigned i = 0; i < vec.size(); i++) + if (vec[i] == key) + return i; + return -1; +} + +template +int linear_index(const std::vector &vec, const FT &key) +{ + for (unsigned i = 0; i < vec.size(); i++) + if (vec[i] && *vec[i] == key) + return i; + return -1; +} + template int binsearch_index(const std::vector &vec, FT key, bool exact = true) { @@ -91,6 +109,15 @@ int binsearch_index(const std::vector &vec, FT key, bool exact = true) } } +template +int linear_index(const std::vector &vec, FT CT::*field, FT key) +{ + for (unsigned i = 0; i < vec.size(); i++) + if (vec[i]->*field == key) + return i; + return -1; +} + template int binsearch_index(const std::vector &vec, FT CT::*field, FT key, bool exact = true) { diff --git a/library/include/modules/Materials.h b/library/include/modules/Materials.h index c5f54cd91..25becc400 100644 --- a/library/include/modules/Materials.h +++ b/library/include/modules/Materials.h @@ -48,7 +48,12 @@ namespace df struct creature_raw; struct historical_figure; struct material_vec_ref; + struct job_item; + union job_material_category; + union job_item_flags1; + union job_item_flags2; + union job_item_flags3; } namespace DFHack @@ -104,8 +109,16 @@ namespace DFHack std::string toString(uint16_t temp = 10015, bool named = true); + bool isAnyCloth(); + + void getMatchBits(df::job_item_flags1 &ok, df::job_item_flags1 &mask); + void getMatchBits(df::job_item_flags2 &ok, df::job_item_flags2 &mask); + void getMatchBits(df::job_item_flags3 &ok, df::job_item_flags3 &mask); + df::craft_material_class getCraftClass(); + bool matches(const df::job_material_category &cat); + bool matches(const df::job_item &item); }; inline bool operator== (const MaterialInfo &a, const MaterialInfo &b) { diff --git a/library/modules/Materials.cpp b/library/modules/Materials.cpp index 0faf26030..8e9d30cc1 100644 --- a/library/modules/Materials.cpp +++ b/library/modules/Materials.cpp @@ -43,12 +43,15 @@ using namespace std; #include "MiscUtils.h" #include "df/world.h" +#include "df/ui.h" #include "df/item.h" #include "df/inorganic_raw.h" #include "df/plant_raw.h" +#include "df/plant_raw_flags.h" #include "df/creature_raw.h" #include "df/historical_figure.h" +#include "df/job_item.h" #include "df/job_material_category.h" #include "df/matter_state.h" #include "df/material_vec_ref.h" @@ -259,6 +262,17 @@ df::craft_material_class MaterialInfo::getCraftClass() return craft_material_class::None; } +bool MaterialInfo::isAnyCloth() +{ + using namespace df::enums::material_flags; + + return material && ( + material->flags.is_set(THREAD_PLANT) || + material->flags.is_set(SILK) || + material->flags.is_set(YARN) + ); +} + bool MaterialInfo::matches(const df::job_material_category &cat) { if (!material) @@ -283,6 +297,103 @@ bool MaterialInfo::matches(const df::job_material_category &cat) return false; } +bool MaterialInfo::matches(const df::job_item &item) +{ + if (!isValid()) return false; + + df::job_item_flags1 ok1, mask1; + getMatchBits(ok1, mask1); + + df::job_item_flags2 ok2, mask2; + getMatchBits(ok2, mask2); + + df::job_item_flags3 ok3, mask3; + getMatchBits(ok3, mask3); + + return ((item.flags1.whole & mask1.whole) == (item.flags1.whole & ok1.whole)) && + ((item.flags2.whole & mask2.whole) == (item.flags2.whole & ok2.whole)) && + ((item.flags3.whole & mask3.whole) == (item.flags3.whole & ok3.whole)); +} + +void MaterialInfo::getMatchBits(df::job_item_flags1 &ok, df::job_item_flags1 &mask) +{ + ok.whole = mask.whole = 0; + if (!isValid()) return; + +#define MAT_FLAG(name) material->flags.is_set(df::enums::material_flags::name) +#define FLAG(field, name) (field && field->flags.is_set(name)) +#define TEST(bit, check) \ + mask.bits.bit = true; ok.bits.bit = !!(check); + + bool structural = MAT_FLAG(STRUCTURAL_PLANT_MAT); + + TEST(millable, structural && FLAG(plant, plant_raw_flags::MILL)); + TEST(sharpenable, MAT_FLAG(IS_STONE)); + TEST(distillable, structural && FLAG(plant, plant_raw_flags::DRINK)); + TEST(processable, structural && FLAG(plant, plant_raw_flags::THREAD)); + TEST(bag, isAnyCloth()); + TEST(cookable, MAT_FLAG(EDIBLE_COOKED)); + TEST(extract_bearing_plant, structural && FLAG(plant, plant_raw_flags::EXTRACT_STILL_VIAL)); + TEST(extract_bearing_fish, false); + TEST(extract_bearing_vermin, false); + TEST(processable_to_vial, structural && FLAG(plant, plant_raw_flags::EXTRACT_VIAL)); + TEST(processable_to_bag, structural && FLAG(plant, plant_raw_flags::LEAVES)); + TEST(processable_to_barrel, structural && FLAG(plant, plant_raw_flags::EXTRACT_BARREL)); + TEST(solid, !(MAT_FLAG(ALCOHOL_PLANT) || + MAT_FLAG(ALCOHOL_CREATURE) || + MAT_FLAG(LIQUID_MISC_PLANT) || + MAT_FLAG(LIQUID_MISC_CREATURE) || + MAT_FLAG(LIQUID_MISC_OTHER))); + TEST(tameable_vermin, false); + TEST(sharpenable, MAT_FLAG(IS_GLASS)); + TEST(milk, linear_index(material->reaction_product.id, std::string("CHEESE_MAT")) >= 0); + //04000000 - "milkable" - vtable[107],1,1 +} + +void MaterialInfo::getMatchBits(df::job_item_flags2 &ok, df::job_item_flags2 &mask) +{ + ok.whole = mask.whole = 0; + if (!isValid()) return; + + bool is_cloth = isAnyCloth(); + + TEST(dye, MAT_FLAG(IS_DYE)); + TEST(dyeable, is_cloth); + TEST(dyed, is_cloth); + TEST(sewn_imageless, is_cloth); + TEST(glass_making, MAT_FLAG(CRYSTAL_GLASSABLE)); + + TEST(fire_safe, material->heat.melting_point > 11000); + TEST(magma_safe, material->heat.melting_point > 12000); + TEST(deep_material, FLAG(inorganic, df::enums::inorganic_flags::DEEP_ANY)); + TEST(non_economic, inorganic && !(df::global::ui && df::global::ui->economic_stone[index])); + + TEST(plant, plant); + TEST(silk, MAT_FLAG(SILK)); + TEST(leather, MAT_FLAG(LEATHER)); + TEST(bone, MAT_FLAG(BONE)); + TEST(shell, MAT_FLAG(SHELL)); + TEST(totemable, false); + TEST(horn, MAT_FLAG(HORN)); + TEST(pearl, MAT_FLAG(PEARL)); + TEST(soap, MAT_FLAG(SOAP)); + TEST(ivory_tooth, MAT_FLAG(TOOTH)); + //TEST(hair_wool, MAT_FLAG(YARN)); + TEST(yarn, MAT_FLAG(YARN)); +} + +void MaterialInfo::getMatchBits(df::job_item_flags3 &ok, df::job_item_flags3 &mask) +{ + ok.whole = mask.whole = 0; + if (!isValid()) return; + + TEST(hard, MAT_FLAG(ITEMS_HARD)); +} + +#undef MAT_FLAG +#undef FLAG +#undef TEST + Module* DFHack::createMaterials() { return new Materials(); diff --git a/library/xml b/library/xml index e61e696e2..f20758b0a 160000 --- a/library/xml +++ b/library/xml @@ -1 +1 @@ -Subproject commit e61e696e2a2bb6b24a86c9c01a26f3133509585e +Subproject commit f20758b0a3ef5aebcbf5896cbb7a824cbdf7b218 diff --git a/plugins/jobutils.cpp b/plugins/jobutils.cpp index c89ca2f40..66ed00024 100644 --- a/plugins/jobutils.cpp +++ b/plugins/jobutils.cpp @@ -60,8 +60,12 @@ DFhackCExport command_result plugin_init (Core *c, std::vector & PluginCommand( "job", "General job query and manipulation.", job_cmd, false, - " job query - Print details of the current job.\n" - " job list - Print details of all jobs in the workshop.\n" + " job query\n" + " Print details of the current job.\n" + " job list\n" + " Print details of all jobs in the workshop.\n" + " job item-material [submaterial]\n" + " Replace the exact material id in the job item.\n" ) ); @@ -382,9 +386,9 @@ static command_result job_duplicate(Core * c, vector & parameters) /* Main job command implementation */ -static void print_job_item_details(Core *c, df::job *job, df::job_item *item) +static void print_job_item_details(Core *c, df::job *job, unsigned idx, df::job_item *item) { - c->con << " Input Item: " << ENUM_KEY_STR(item_type,item->item_type); + c->con << " Input Item " << (idx+1) << ": " << ENUM_KEY_STR(item_type,item->item_type); if (item->item_subtype != -1) c->con << " [" << item->item_subtype << "]"; if (item->quantity != 1) @@ -443,7 +447,17 @@ static void print_job_details(Core *c, df::job *job) c->con << " reaction: " << job->reaction_name << endl; for (unsigned i = 0; i < job->job_items.size(); i++) - print_job_item_details(c, job, job->job_items[i]); + print_job_item_details(c, job, i, job->job_items[i]); +} + +static df::job *getWorkshopJobSafe(Core *c) +{ + if (!workshop_job_hotkey(c, c->getTopViewscreen())) { + c->con.printerr("No job is highlighted.\n"); + return NULL; + } + + return getWorkshopJob(c); } static command_result job_cmd(Core * c, vector & parameters) @@ -456,15 +470,11 @@ static command_result job_cmd(Core * c, vector & parameters) std::string cmd = parameters[0]; if (cmd == "query" || cmd == "list") { - if (!workshop_job_hotkey(c, c->getTopViewscreen())) { - c->con.printerr("No job is highlighted.\n"); + df::job *job = getWorkshopJobSafe(c); + if (!job) return CR_WRONG_USAGE; - } if (cmd == "query") { - df::job *job = getWorkshopJob(c); - if (!job) - return CR_FAILURE; print_job_details(c, job); } else { df::building *selected = world->selected_building; @@ -472,6 +482,51 @@ static command_result job_cmd(Core * c, vector & parameters) print_job_details(c, selected->jobs[i]); } } + else if (cmd == "item-material") + { + if (parameters.size() < 1+1+1) + return CR_WRONG_USAGE; + + df::job *job = getWorkshopJobSafe(c); + if (!job) + return CR_WRONG_USAGE; + + int v = atoi(parameters[1].c_str()); + if (v < 1 || v > job->job_items.size()) { + c->con.printerr("Invalid item index.\n"); + return CR_WRONG_USAGE; + } + + df::job_item *item = job->job_items[v-1]; + + std::string subtoken = (parameters.size()>3 ? parameters[3] : ""); + MaterialInfo info; + if (!info.find(parameters[2], subtoken)) { + c->con.printerr("Could not find the specified material.\n"); + return CR_FAILURE; + } + + if (!info.matches(*item)) { + c->con.printerr("Material does not match the requirements.\n"); + print_job_details(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 = info.type; + job->mat_index = info.index; + } + + item->mat_type = info.type; + item->mat_index = info.index; + + c->con << "Job item " << v << " updated." << endl; + print_job_details(c, job); + return CR_OK; + } else return CR_WRONG_USAGE; From 78a98de37e439ae4343195880136575421e38625 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Mr=C3=A1zek?= Date: Thu, 5 Jan 2012 23:39:14 +0100 Subject: [PATCH 13/82] Fix MSVC builds, break buildings :D --- build/build-release.bat | 3 +- library/Process-linux.cpp | 4 +- library/Process-windows.cpp | 36 +++++----- library/VersionInfo.cpp | 32 ++++----- library/include/MemAccess.h | 8 +-- library/include/VersionInfo.h | 4 +- library/include/modules/Buildings.h | 5 +- library/include/modules/Vermin.h | 2 +- library/modules/Buildings.cpp | 87 +++++++++---------------- library/modules/Maps.cpp | 40 ++++++------ library/modules/Materials.cpp | 14 ++-- library/modules/Translation.cpp | 8 +-- library/modules/Vermin.cpp | 6 +- library/modules/World.cpp | 2 +- library/modules/kitchen.cpp | 2 +- plugins/Dfusion/include/hexsearch.h | 6 +- plugins/Dfusion/src/hexsearch.cpp | 2 +- plugins/Dfusion/src/lua_Hexsearch.cpp | 6 +- plugins/Dfusion/src/lua_VersionInfo.cpp | 2 +- plugins/stonesense | 2 +- 20 files changed, 123 insertions(+), 148 deletions(-) diff --git a/build/build-release.bat b/build/build-release.bat index 95c15596c..e1ad315e5 100644 --- a/build/build-release.bat +++ b/build/build-release.bat @@ -1,4 +1,5 @@ call "%VS100COMNTOOLS%vsvars32.bat" cd VC2010 msbuild /m /p:Platform=Win32 /p:Configuration=Release ALL_BUILD.vcxproj -cd .. \ No newline at end of file +cd .. +pause \ No newline at end of file diff --git a/library/Process-linux.cpp b/library/Process-linux.cpp index d2c04e105..1a2669286 100644 --- a/library/Process-linux.cpp +++ b/library/Process-linux.cpp @@ -111,8 +111,8 @@ Process::~Process() string Process::doReadClassName (void * vptr) { //FIXME: BAD!!!!! - void * typeinfo = Process::readPtr(vptr - 0x4); - void * typestring = Process::readPtr(typeinfo + 0x4); + char * typeinfo = Process::readPtr(((char *)vptr - 0x4)); + char * typestring = Process::readPtr(typeinfo + 0x4); string raw = readCString(typestring); size_t start = raw.find_first_of("abcdefghijklmnopqrstuvwxyz");// trim numbers size_t end = raw.length(); diff --git a/library/Process-windows.cpp b/library/Process-windows.cpp index 1fba8b28a..b02e3011f 100644 --- a/library/Process-windows.cpp +++ b/library/Process-windows.cpp @@ -112,7 +112,7 @@ namespace DFHack uint32_t my_pid; IMAGE_NT_HEADERS pe_header; IMAGE_SECTION_HEADER * sections; - uint32_t base; + char * base; }; } Process::Process(VersionInfoFactory * factory) @@ -134,7 +134,7 @@ Process::Process(VersionInfoFactory * factory) } // got base ;) - d->base = (uint32_t)hmod; + d->base = (char *)hmod; // read from this process try @@ -161,7 +161,7 @@ Process::Process(VersionInfoFactory * factory) identified = true; // give the process a data model and memory layout fixed for the base of first module my_descriptor = new VersionInfo(*vinfo); - my_descriptor->RebaseAll(d->base); + my_descriptor->RebaseAll((uint32_t)d->base); // keep track of created memory_info object so we can destroy it later my_descriptor->setParentProcess(this); for(size_t i = 0; i < threads_ids.size();i++) @@ -236,7 +236,7 @@ struct HeapBlock ULONG reserved; }; */ -void HeapNodes(DWORD pid, map & heaps) +void HeapNodes(DWORD pid, map & heaps) { // Create debug buffer PDEBUG_BUFFER db = RtlCreateQueryDebugBuffer(0, FALSE); @@ -247,7 +247,7 @@ void HeapNodes(DWORD pid, map & heaps) // Go through each of the heap nodes and dispaly the information for (unsigned int i = 0; i < heapNodeCount; i++) { - heaps[heapInfo[i].Base] = i; + heaps[(char *)heapInfo[i].Base] = i; } // Clean up the buffer RtlDestroyQueryDebugBuffer( db ); @@ -257,9 +257,9 @@ void HeapNodes(DWORD pid, map & heaps) void Process::getMemRanges( vector & ranges ) { MEMORY_BASIC_INFORMATION MBI; - map heaps; + map heaps; uint64_t movingStart = 0; - map nameMap; + map nameMap; // get page size SYSTEM_INFO si; @@ -277,18 +277,18 @@ void Process::getMemRanges( vector & ranges ) if( !(MBI.State & MEM_COMMIT) /*|| !(MBI.Type & MEM_PRIVATE)*/ ) continue; t_memrange temp; - temp.start = (uint64_t) MBI.BaseAddress; - temp.end = ((uint64_t)MBI.BaseAddress + (uint64_t)MBI.RegionSize); + temp.start = (char *) MBI.BaseAddress; + temp.end = ((char *)MBI.BaseAddress + (uint64_t)MBI.RegionSize); temp.read = MBI.Protect & PAGE_EXECUTE_READ || MBI.Protect & PAGE_EXECUTE_READWRITE || MBI.Protect & PAGE_READONLY || MBI.Protect & PAGE_READWRITE; temp.write = MBI.Protect & PAGE_EXECUTE_READWRITE || MBI.Protect & PAGE_READWRITE; temp.execute = MBI.Protect & PAGE_EXECUTE_READ || MBI.Protect & PAGE_EXECUTE_READWRITE || MBI.Protect & PAGE_EXECUTE; temp.valid = true; if(!GetModuleBaseName(d->my_handle, (HMODULE) temp.start, temp.name, 1024)) { - if(nameMap.count(temp.start)) + if(nameMap.count((char *)temp.start)) { // potential buffer overflow... - strcpy(temp.name, nameMap[temp.start].c_str()); + strcpy(temp.name, nameMap[(char *)temp.start].c_str()); } else { @@ -298,9 +298,9 @@ void Process::getMemRanges( vector & ranges ) else { // could be a heap? - if(heaps.count(temp.start)) + if(heaps.count((char *)temp.start)) { - sprintf(temp.name,"HEAP %d",heaps[temp.start]); + sprintf(temp.name,"HEAP %d",heaps[(char*)temp.start]); } else temp.name[0]=0; } @@ -320,7 +320,7 @@ void Process::getMemRanges( vector & ranges ) nm.append(temp.name); nm.append(" : "); nm.append(sectionName); - nameMap[temp.start + d->sections[i].VirtualAddress] = nm; + nameMap[(char *)temp.start + d->sections[i].VirtualAddress] = nm; } } else @@ -333,14 +333,14 @@ void Process::getMemRanges( vector & ranges ) uint32_t Process::getBase() { if(d) - return d->base; + return (uint32_t) d->base; return 0x400000; } string Process::doReadClassName (void * vptr) { - int rtti = readDWord((uint32_t)vptr - 0x4); - int typeinfo = readDWord(rtti + 0xC); + char * rtti = readPtr((char *)vptr - 0x4); + char * typeinfo = readPtr(rtti + 0xC); string raw = readCString(typeinfo + 0xC); // skips the .?AV raw.resize(raw.length() - 2);// trim @@ from end return raw; @@ -367,7 +367,7 @@ bool Process::setPermisions(const t_memrange & range,const t_memrange &trgrange) if(trgrange.read && trgrange.write && trgrange.execute)newprotect=PAGE_EXECUTE_READWRITE; DWORD oldprotect=0; bool result; - result=VirtualProtect((LPVOID)range.start,range.end-range.start,newprotect,&oldprotect); + result=VirtualProtect((LPVOID)range.start,(char *)range.end-(char *)range.start,newprotect,&oldprotect); return result; } diff --git a/library/VersionInfo.cpp b/library/VersionInfo.cpp index 430553e9e..6bda6d669 100644 --- a/library/VersionInfo.cpp +++ b/library/VersionInfo.cpp @@ -158,8 +158,8 @@ namespace DFHack { typedef pair nullableUint32; typedef map ::iterator uint32_Iter; - typedef pair nullableVoidPtr; - typedef map ::iterator voidptr_Iter; + typedef pair nullableBytePtr; + typedef map ::iterator byteptr_Iter; typedef pair nullableInt32; typedef map ::iterator int32_Iter; typedef pair nullableString; @@ -168,7 +168,7 @@ namespace DFHack class OffsetGroupPrivate { public: - map addresses; + map addresses; map hexvals; map offsets; map strings; @@ -185,7 +185,7 @@ void OffsetGroup::createOffset(const string & key) void OffsetGroup::createAddress(const string & key) { - OGd->addresses[key] = nullableVoidPtr(NOT_SET, 0); + OGd->addresses[key] = nullableBytePtr(NOT_SET, (char*) 0); } void OffsetGroup::createHexValue(const string & key) @@ -229,10 +229,10 @@ void OffsetGroup::setOffsetValidity (const string & key, const INVAL_TYPE inval) void OffsetGroup::setAddress (const string & key, const string & value, const INVAL_TYPE inval) { - voidptr_Iter it = OGd->addresses.find(key); + byteptr_Iter it = OGd->addresses.find(key); if(it != OGd->addresses.end()) { - void * address = (void *) strtol(value.c_str(), NULL, 16); + char * address = (char *) strtol(value.c_str(), NULL, 16); if((*it).second.second == address) std::cout << "Pointless address setting: " << this->getFullName() + key << endl; (*it).second.second = address; @@ -246,7 +246,7 @@ void OffsetGroup::setAddressValidity (const string & key, const INVAL_TYPE inval { if(inval != NOT_SET) { - voidptr_Iter it = OGd->addresses.find(key); + byteptr_Iter it = OGd->addresses.find(key); if(it != OGd->addresses.end()) { (*it).second.first = inval; @@ -307,9 +307,9 @@ void OffsetGroup::setStringValidity (const string & key, const INVAL_TYPE inval) } // Get named address -void * OffsetGroup::getAddress (const string & key) +char * OffsetGroup::getAddress (const string & key) { - voidptr_Iter iter = OGd->addresses.find(key); + byteptr_Iter iter = OGd->addresses.find(key); if(iter != OGd->addresses.end()) { @@ -325,7 +325,7 @@ void * OffsetGroup::getAddress (const string & key) // Get named offset, return bool instead of throwing exceptions bool OffsetGroup::getSafeAddress (const string & key, void * & out) { - voidptr_Iter iter = OGd->addresses.find(key); + byteptr_Iter iter = OGd->addresses.find(key); if(iter != OGd->addresses.end() && (*iter).second.first == IS_VALID) { out = (*iter).second.second; @@ -412,7 +412,7 @@ OffsetGroup * OffsetGroup::createGroup(const std::string &name) void OffsetGroup::RebaseAddresses(int32_t offset) { - for(voidptr_Iter iter = OGd->addresses.begin(); iter != OGd->addresses.end(); iter++) + for(byteptr_Iter iter = OGd->addresses.begin(); iter != OGd->addresses.end(); iter++) { if(iter->second.first) OGd->addresses[iter->first].second = iter->second.second + offset; @@ -472,11 +472,11 @@ std::string OffsetGroup::getFullName() std::string OffsetGroup::PrintOffsets(int indentation) { - voidptr_Iter addriter; + byteptr_Iter addriter; uint32_Iter iter; ostringstream ss; indentr i(indentation); - typedef pair > horrible; + typedef pair > horrible; vector < horrible > addrsorter; for(addriter = OGd->addresses.begin(); addriter != OGd->addresses.end(); addriter++) { @@ -572,7 +572,7 @@ void OffsetGroup::setInvalid(INVAL_TYPE invalidity) if(invalidity == NOT_SET) return; - voidptr_Iter iter; + byteptr_Iter iter; for(iter = OGd->addresses.begin(); iter != OGd->addresses.end(); iter++) { if((*iter).second.first) @@ -607,7 +607,7 @@ std::vector OffsetGroup::getKeys() const std::vector ret; OffsetKey K; K.keytype=IS_ADDRESS; - for(voidptr_Iter iter = OGd->addresses.begin(); iter != OGd->addresses.end(); iter++) + for(byteptr_Iter iter = OGd->addresses.begin(); iter != OGd->addresses.end(); iter++) { K.key=iter->first; K.inval=iter->second.first; @@ -1019,7 +1019,7 @@ void VersionInfo::setClassChild (t_class * parent, const char * name, const char // FIXME: This in now DEPRECATED! -bool VersionInfo::resolveObjectToClassID(const void * address, int32_t & classid) +bool VersionInfo::resolveObjectToClassID(const char * address, int32_t & classid) { uint32_t vtable = d->p->readDWord(address); // try to find the vtable in our cache diff --git a/library/include/MemAccess.h b/library/include/MemAccess.h index 30a194bb3..531b83353 100644 --- a/library/include/MemAccess.h +++ b/library/include/MemAccess.h @@ -136,14 +136,14 @@ namespace DFHack }; /// read a pointer - void * readPtr(const void * address) + char * readPtr(const void * address) { - return *(void **)address; + return *(char **)address; } /// read a pointer - void readPtr(const void * address, void * & value) + void readPtr(const void * address, char * & value) { - value = *(void **)address; + value = *(char **)address; }; /// read a float diff --git a/library/include/VersionInfo.h b/library/include/VersionInfo.h index b46866a4a..02d526730 100644 --- a/library/include/VersionInfo.h +++ b/library/include/VersionInfo.h @@ -88,7 +88,7 @@ namespace DFHack OffsetGroup * createGroup ( const std::string & name ); int32_t getOffset (const std::string & key); - void * getAddress (const std::string & key); + char * getAddress (const std::string & key); uint32_t getHexValue (const std::string & key); std::string getString (const std::string & key); OffsetGroup * getGroup ( const std::string & name ); @@ -189,7 +189,7 @@ namespace DFHack * uses memory reading directly, needs suspend. input = address of the object * fails if it's unable to read from memory */ - bool resolveObjectToClassID (const void * address, int32_t & classID); + bool resolveObjectToClassID (const char * address, int32_t & classID); /** * Get a ClassID when you know the classname. can fail if the class is not in the cache diff --git a/library/include/modules/Buildings.h b/library/include/modules/Buildings.h index d4f90d016..7a3266c9e 100644 --- a/library/include/modules/Buildings.h +++ b/library/include/modules/Buildings.h @@ -42,8 +42,6 @@ namespace DFHack */ struct t_building { - void * origin; - uint32_t vtable; uint32_t x1; uint32_t y1; uint32_t x2; @@ -51,7 +49,8 @@ namespace DFHack uint32_t z; t_matglossPair material; uint32_t type; - // FIXME: not complete, we need building presence bitmaps for stuff like farm plots and stockpiles, orientation (N,E,S,W) and state (open/closed) + int32_t custom_type; + void * origin; }; #ifdef __cplusplus diff --git a/library/include/modules/Vermin.h b/library/include/modules/Vermin.h index 3c5506fc1..324714f5d 100644 --- a/library/include/modules/Vermin.h +++ b/library/include/modules/Vermin.h @@ -76,7 +76,7 @@ namespace DFHack private: Vermin* v; - std::vector * p_sp; + std::vector * p_sp; friend class Vermin; }; diff --git a/library/modules/Buildings.cpp b/library/modules/Buildings.cpp index a162549b4..6de803c3c 100644 --- a/library/modules/Buildings.cpp +++ b/library/modules/Buildings.cpp @@ -39,6 +39,17 @@ using namespace std; #include "Core.h" using namespace DFHack; +#include "DataDefs.h" +#include "df/world.h" +#include "df/world_raws.h" +#include "df/building_def.h" +#include "df/building.h" +#include "df/building_workshopst.h" + +using namespace df::enums; +using df::global::world; +using df::building_def; + //raw struct t_building_df40d { @@ -57,16 +68,10 @@ struct t_building_df40d struct Buildings::Private { - vector * custom_workshop_vector; - uint32_t building_custom_workshop_type; - uint32_t custom_workshop_type; - uint32_t custom_workshop_name; - int32_t custom_workshop_id; - vector * p_bld; Process * owner; bool Inited; - bool hasCustomWorkshops; bool Started; + int32_t custom_workshop_id; }; Module* DFHack::createBuildings() @@ -78,37 +83,10 @@ Buildings::Buildings() { Core & c = Core::getInstance(); d = new Private; - d->p_bld = NULL; - d->Inited = d->Started = d->hasCustomWorkshops = false; - VersionInfo * mem = c.vinfo; + d->Started = false; d->owner = c.p; - OffsetGroup * OG_build = mem->getGroup("Buildings"); d->Inited = true; - try - { - d->p_bld = (decltype(d->p_bld)) OG_build->getAddress ("buildings_vector"); - } - catch(DFHack::Error::AllMemdef &e) - { - cerr << "Buildings not available... " << e.what() << endl; - d->Inited = false; - } - if(d->Inited) - { - try - { - d->custom_workshop_vector =(decltype(d->custom_workshop_vector)) OG_build->getAddress ("custom_workshop_vector"); - d->building_custom_workshop_type = OG_build->getOffset("building_custom_workshop_type"); - d->custom_workshop_type = OG_build->getOffset("custom_workshop_type"); - d->custom_workshop_name = OG_build->getOffset("custom_workshop_name"); - mem->resolveClassnameToClassID("building_custom_workshop", d->custom_workshop_id); - d->hasCustomWorkshops = true; - } - catch(DFHack::Error::AllMemdef &e) - { - cerr << "Custom workshops not available. Memory Definition: " << e.what() << endl; - } - } + c.vinfo->resolveClassnameToClassID("building_custom_workshop", d->custom_workshop_id); } Buildings::~Buildings() @@ -122,7 +100,7 @@ bool Buildings::Start(uint32_t & numbuildings) { if(!d->Inited) return false; - numbuildings = d->p_bld->size(); + numbuildings = world->buildings.all.size(); d->Started = true; return true; } @@ -131,20 +109,20 @@ bool Buildings::Read (const uint32_t index, t_building & building) { if(!d->Started) return false; - t_building_df40d *bld_40d = d->p_bld->at (index); + df::building *bld_40d = world->buildings.all[index]; // transform int32_t type = -1; - d->owner->getDescriptor()->resolveObjectToClassID (bld_40d, type); - building.origin = bld_40d; - building.vtable = bld_40d->vtable; + d->owner->getDescriptor()->resolveObjectToClassID ( (char *)bld_40d, type); building.x1 = bld_40d->x1; building.x2 = bld_40d->x2; building.y1 = bld_40d->y1; building.y2 = bld_40d->y2; building.z = bld_40d->z; - building.material = bld_40d->material; + building.material.index = bld_40d->materialIndex; + building.material.type = bld_40d->materialType; building.type = type; + building.origin = (void *) &bld_40d; return true; } @@ -158,38 +136,35 @@ bool Buildings::ReadCustomWorkshopTypes(map & btypes) { if(!d->Inited) return false; - if(!d->hasCustomWorkshops) - return false; + Core & c = Core::getInstance(); Process * p = d->owner; - uint32_t size = d->custom_workshop_vector->size(); + vector & bld_def = world->raws.buildings.all; + uint32_t size = bld_def.size(); btypes.clear(); - for (uint32_t i = 0; i < size;i++) + c.con.print("Probing vector at 0x%x for custom workshops.\n", &bld_def); + for (auto iter = bld_def.begin(); iter != bld_def.end();iter++) { - void * obj = d->custom_workshop_vector->at(i); - string out = p->readSTLString (obj + d->custom_workshop_name); - uint32_t type = p->readDWord (obj + d->custom_workshop_type); - #ifdef DEBUG - cout << out << ": " << type << endl; - #endif - btypes[type] = out; + building_def * temp = *iter; + btypes[temp->id] = temp->code; + c.con.print("%d : %s\n",temp->id, temp->code.c_str()); } return true; } +// FIXME: ugly hack int32_t Buildings::GetCustomWorkshopType(t_building & building) { if(!d->Inited) return false; - if(!d->hasCustomWorkshops) - return false; int32_t type = (int32_t)building.type; int32_t ret = -1; if(type != -1 && type == d->custom_workshop_id) { // read the custom workshop subtype - ret = (int32_t) d->owner->readDWord(building.origin + d->building_custom_workshop_type); + df::building_workshopst * workshop = (df::building_workshopst *) building.origin; + ret = workshop->custom_type; } return ret; } diff --git a/library/modules/Maps.cpp b/library/modules/Maps.cpp index ebb0e4d79..4d3dc1506 100644 --- a/library/modules/Maps.cpp +++ b/library/modules/Maps.cpp @@ -95,7 +95,7 @@ struct Maps::Private FEATURES */ // FIXME: replace with a struct pointer, eventually. needs to be mapped out first - void * world_data; + char * world_data; uint32_t local_f_start; // offset from world_data // FIXME: replace by virtual function call uint32_t local_material; @@ -141,7 +141,7 @@ Maps::Maps() // get the offsets once here OffsetGroup *OG_Maps = mem->getGroup("Maps"); - off.world_data = (void *) OG_Maps->getAddress("world_data"); + off.world_data = OG_Maps->getAddress("world_data"); { mdata = (map_data *) OG_Maps->getAddress ("map_data"); off.world_size_x = OG_Maps->getOffset ("world_size_x_from_wdata"); @@ -507,13 +507,13 @@ bool Maps::StartFeatures() Process * p = d->owner; Private::t_offsets &off = d->offsets; - void * base = 0; - void * global_feature_vector = 0; + char * base = 0; + char * global_feature_vector = 0; - void * world = p->readPtr( (void *) off.world_data); + char * world = p->readPtr( (void *) off.world_data); if(!world) return false; base = p->readPtr(world + off.local_f_start); - global_feature_vector = p->readDWord(off.world_data) + (void *) off.global_vector; + global_feature_vector = p->readPtr(off.world_data) + off.global_vector; // deref pointer to the humongo-structure if(!base) @@ -548,19 +548,19 @@ bool Maps::StartFeatures() // base = pointer to local feature structure (inside world data struct) // bigregion is 16x16 regions. for each bigregion in X dimension: - void * mega_column = p->readPtr(base + bigregion_x * 4); + char * mega_column = p->readPtr(base + bigregion_x * 4); // 16B structs, second DWORD of the struct is a pointer - void * loc_f_array16x16 = p->readPtr(mega_column + offset_elem + (sizeof_elem * bigregion_y)); + char * loc_f_array16x16 = p->readPtr(mega_column + offset_elem + (sizeof_elem * bigregion_y)); if(loc_f_array16x16) { - vector * p_features = (vector *) (loc_f_array16x16 + sizeof_16vec * sub_x + sizeof_vec * sub_y); + vector * p_features = (vector *) (loc_f_array16x16 + sizeof_16vec * sub_x + sizeof_vec * sub_y); uint32_t size = p_features->size(); DFCoord pc(blockX,blockY); std::vector tempvec; for(uint32_t i = 0; i < size; i++) { - void * cur_ptr = p_features->at(i); + char * cur_ptr = p_features->at(i); map ::iterator it; it = d->local_feature_store.find(cur_ptr); @@ -609,14 +609,14 @@ bool Maps::StartFeatures() const uint32_t global_feature_funcptr = off.global_funcptr; const uint32_t glob_main_mat_offset = off.global_material; const uint32_t glob_sub_mat_offset = off.global_submaterial; - vector * p_features = (vector *) global_feature_vector; + vector * p_features = (vector *) global_feature_vector; d->v_global_feature.clear(); uint32_t size = p_features->size(); d->v_global_feature.reserve(size); for(uint32_t i = 0; i < size; i++) { t_feature temp; - void * feat_ptr = p->readPtr(p_features->at(i) + global_feature_funcptr ); + char * feat_ptr = p->readPtr(p_features->at(i) + global_feature_funcptr ); temp.origin = feat_ptr; temp.discovered = false; @@ -892,18 +892,18 @@ bool Maps::ReadGeology (vector < vector >& assign) Process *p = d->owner; // get needed addresses and offsets. Now this is what I call crazy. uint16_t worldSizeX, worldSizeY; - void *regions; - void *geoblocks_vector_addr; + char *regions; + char *geoblocks_vector_addr; Private::t_offsets &off = d->offsets; // get world size - void * world = p->readPtr(off.world_data); + char * world = p->readPtr(off.world_data); p->readWord (world + off.world_size_x, worldSizeX); p->readWord (world + off.world_size_y, worldSizeY); regions = p->readPtr ( world + off.world_regions); // ptr2_region_array geoblocks_vector_addr = world + off.world_geoblocks_vector; // read the geoblock vector - vector & geoblocks = *(vector *)(geoblocks_vector_addr); + vector & geoblocks = *(vector *)(geoblocks_vector_addr); // iterate over 8 surrounding regions + local region for (int i = eNorthWest; i < eBiomeCount; i++) @@ -922,7 +922,7 @@ bool Maps::ReadGeology (vector < vector >& assign) /// regions are a 2d array. consists of pointers to arrays of regions /// regions are of region_size size // get pointer to column of regions - void * geoX; + char * geoX; p->readPtr (regions + bioRX*4, geoX); // get index into geoblock vector @@ -932,11 +932,11 @@ bool Maps::ReadGeology (vector < vector >& assign) /// geology blocks are assigned to regions from a vector // get the geoblock from the geoblock vector using the geoindex // read the matgloss pointer from the vector into temp - void * geoblock_off = geoblocks[geoindex]; + char * geoblock_off = geoblocks[geoindex]; /// geology blocks have a vector of layer descriptors // get the vector with pointer to layers - vector & geolayers = *(vector *)(geoblock_off + off.geolayer_geoblock_offset); + vector & geolayers = *(vector *)(geoblock_off + off.geolayer_geoblock_offset); // make sure we don't load crap assert (geolayers.size() > 0 && geolayers.size() <= 16); @@ -946,7 +946,7 @@ bool Maps::ReadGeology (vector < vector >& assign) for (uint32_t j = 0;j < geolayers.size();j++) { // read pointer to a layer - void * geol_offset = geolayers[j]; + char * geol_offset = geolayers[j]; // read word at pointer + 2, store in our geology vectors d->v_geology[i].push_back (p->readWord (geol_offset + off.type_inside_geolayer)); } diff --git a/library/modules/Materials.cpp b/library/modules/Materials.cpp index 18170eff5..fdd9a0e36 100644 --- a/library/modules/Materials.cpp +++ b/library/modules/Materials.cpp @@ -184,7 +184,7 @@ bool Materials::ReadCreatureTypes (void) bool Materials::ReadOthers(void) { Process * p = d->owner; - void * matBase = d->OG_Materials->getAddress ("other"); + char * matBase = d->OG_Materials->getAddress ("other"); uint32_t i = 0; std::string * ptr; @@ -207,7 +207,7 @@ bool Materials::ReadDescriptorColors (void) { Process * p = d->owner; OffsetGroup * OG_Descriptors = p->getDescriptor()->getGroup("Materials")->getGroup("descriptors"); - vector & p_colors = *(vector *) OG_Descriptors->getAddress ("colors_vector"); + vector & p_colors = *(vector *) OG_Descriptors->getAddress ("colors_vector"); uint32_t size = p_colors.size(); color.clear(); @@ -236,7 +236,7 @@ bool Materials::ReadCreatureTypesEx (void) uint32_t sizeof_string = OG_string->getHexValue ("sizeof"); OffsetGroup * OG_Mats = mem->getGroup("Materials"); - vector & p_races = *(vector *) OG_Mats->getAddress ("creature_type_vector"); + vector & p_races = *(vector *) OG_Mats->getAddress ("creature_type_vector"); OffsetGroup * OG_Creature = OG_Mats->getGroup("creature"); uint32_t castes_vector_offset = OG_Creature->getOffset ("caste_vector"); @@ -286,13 +286,13 @@ bool Materials::ReadCreatureTypesEx (void) mat.tilecolor.back = p->readWord( p_races[i] + tile_color_offset + 2 ); mat.tilecolor.bright = p->readWord( p_races[i] + tile_color_offset + 4 ); - vector & p_castes = *(vector *) (p_races[i] + castes_vector_offset); + vector & p_castes = *(vector *) (p_races[i] + castes_vector_offset); sizecas = p_castes.size(); for (uint32_t j = 0; j < sizecas;j++) { /* caste name */ t_creaturecaste caste; - void * caste_start = p_castes[j]; + char * caste_start = p_castes[j]; caste.id = p->readSTLString (caste_start); caste.singular = p->readSTLString (caste_start + sizeof_string); caste.plural = p->readSTLString (caste_start + 2 * sizeof_string); @@ -302,7 +302,7 @@ bool Materials::ReadCreatureTypesEx (void) { /* color mod reading */ // Caste + offset > color mod vector - vector & p_colormod = *(vector *) (caste_start + caste_colormod_offset); + vector & p_colormod = *(vector *) (caste_start + caste_colormod_offset); sizecolormod = p_colormod.size(); caste.ColorModifier.resize(sizecolormod); for(uint32_t k = 0; k < sizecolormod;k++) @@ -319,7 +319,7 @@ bool Materials::ReadCreatureTypesEx (void) caste.ColorModifier[k].enddate = p->readDWord( p_colormod[k] + color_modifier_enddate_offset ); } /* body parts */ - vector & p_bodypart = *(vector *) (caste_start + caste_bodypart_offset); + vector & p_bodypart = *(vector *) (caste_start + caste_bodypart_offset); caste.bodypart.empty(); sizebp = p_bodypart.size(); for(uint32_t k = 0; k < sizebp; k++) diff --git a/library/modules/Translation.cpp b/library/modules/Translation.cpp index 210186e41..6df7c7f24 100644 --- a/library/modules/Translation.cpp +++ b/library/modules/Translation.cpp @@ -96,15 +96,15 @@ bool Translation::Start() return false; Process * p = c.p; Finish(); - vector & genericVec = *(vector *) d->genericAddress; - vector & transVec = *(vector *) d->transAddress; + vector & genericVec = *(vector *) d->genericAddress; + vector & transVec = *(vector *) d->transAddress; DFDict & translations = d->dicts.translations; DFDict & foreign_languages = d->dicts.foreign_languages; translations.resize(10); for (uint32_t i = 0;i < genericVec.size();i++) { - void * genericNamePtr = genericVec[i]; + char * genericNamePtr = genericVec[i]; for(int j=0; j<10;j++) { string word = p->readSTLString (genericNamePtr + j * d->sizeof_string); @@ -115,7 +115,7 @@ bool Translation::Start() foreign_languages.resize(transVec.size()); for (uint32_t i = 0; i < transVec.size();i++) { - void * transPtr = transVec.at(i); + char * transPtr = transVec.at(i); vector & trans_names_vec = *(vector *) (transPtr + d->word_table_offset); for (uint32_t j = 0;j < trans_names_vec.size();j++) { diff --git a/library/modules/Vermin.cpp b/library/modules/Vermin.cpp index 3cad35300..215815eb0 100644 --- a/library/modules/Vermin.cpp +++ b/library/modules/Vermin.cpp @@ -119,7 +119,7 @@ SpawnPoints::SpawnPoints(Vermin* v_) cerr << "Couldn't get spawn points: Vermin module not inited" << endl; return; } - p_sp = (vector *) (v->d->spawn_points_vector); + p_sp = (vector *) (v->d->spawn_points_vector); } SpawnPoints::~SpawnPoints() @@ -140,7 +140,7 @@ bool SpawnPoints::Read (const uint32_t index, t_spawnPoint & sp) return false; // read pointer from vector at position - void * temp = p_sp->at (index); + char * temp = p_sp->at (index); sp.origin = temp; sp.race = v->d->owner->readWord(temp + v->d->race_offset); @@ -161,7 +161,7 @@ bool SpawnPoints::Write (const uint32_t index, t_spawnPoint & sp) return false; // read pointer from vector at position - void * temp = p_sp->at (index); + char * temp = p_sp->at (index); v->d->owner->writeWord(temp + v->d->race_offset, sp.race); v->d->owner->writeWord(temp + v->d->type_offset, sp.type); diff --git a/library/modules/World.cpp b/library/modules/World.cpp index 18e70fbde..5d1292a9e 100644 --- a/library/modules/World.cpp +++ b/library/modules/World.cpp @@ -61,7 +61,7 @@ struct World::Private void * tick_offset; bool StartedWeather; - void * weather_offset; + char * weather_offset; bool StartedMode; void * gamemode_offset; diff --git a/library/modules/kitchen.cpp b/library/modules/kitchen.cpp index c127f67c5..fbf11a079 100644 --- a/library/modules/kitchen.cpp +++ b/library/modules/kitchen.cpp @@ -45,7 +45,7 @@ namespace Kitchen static void * addr(const DFHack::Core& core, int index) { - static void * start = core.vinfo->getAddress("kitchen_limits"); + static char * start = core.vinfo->getAddress("kitchen_limits"); return start + sizeof(std::vector) * index; }; }; diff --git a/plugins/Dfusion/include/hexsearch.h b/plugins/Dfusion/include/hexsearch.h index 41223dee7..6cbc978ce 100644 --- a/plugins/Dfusion/include/hexsearch.h +++ b/plugins/Dfusion/include/hexsearch.h @@ -15,11 +15,11 @@ public: ANYBYTE=0x101,DWORD_,ANYDWORD,ADDRESS }; - Hexsearch(const SearchArgType &args,void * startpos,void * endpos); + Hexsearch(const SearchArgType &args,char * startpos,char * endpos); ~Hexsearch(); void Reset(){pos_=startpos_;}; - void SetStart(void * pos){pos_=pos;}; + void SetStart(char * pos){pos_=pos;}; void * FindNext(); std::vector FindAll(); @@ -28,7 +28,7 @@ private: bool Compare(int a,int b); void ReparseArgs(); SearchArgType args_; - void * pos_,* startpos_,* endpos_; + char * pos_,* startpos_,* endpos_; std::vector BadCharShifts,GoodSuffixShift; void PrepareGoodSuffixTable(); void PrepareBadCharShift(); diff --git a/plugins/Dfusion/src/hexsearch.cpp b/plugins/Dfusion/src/hexsearch.cpp index 4c58f236d..30dcf26f8 100644 --- a/plugins/Dfusion/src/hexsearch.cpp +++ b/plugins/Dfusion/src/hexsearch.cpp @@ -1,7 +1,7 @@ #include "hexsearch.h" -Hexsearch::Hexsearch(const SearchArgType &args,void * startpos,void * endpos):args_(args),pos_(startpos),startpos_(startpos),endpos_(endpos) +Hexsearch::Hexsearch(const SearchArgType &args,char * startpos,char * endpos):args_(args),pos_(startpos),startpos_(startpos),endpos_(endpos) { ReparseArgs(); } diff --git a/plugins/Dfusion/src/lua_Hexsearch.cpp b/plugins/Dfusion/src/lua_Hexsearch.cpp index b7d785495..8ee7eb9c2 100644 --- a/plugins/Dfusion/src/lua_Hexsearch.cpp +++ b/plugins/Dfusion/src/lua_Hexsearch.cpp @@ -22,10 +22,10 @@ int lua::Hexsearch::findall(lua_State *L) lua::Hexsearch::Hexsearch(lua_State *L,int id):tblid(id) { lua::state st(L); - void * start,* end; + char * start,* end; ::Hexsearch::SearchArgType args; - start= (void *)st.as(1); - end=(void *)st.as(2); + start= (char *)st.as(1); + end=(char *)st.as(2); for(int i=3;i<=st.gettop();i++) { args.push_back(st.as(i)); diff --git a/plugins/Dfusion/src/lua_VersionInfo.cpp b/plugins/Dfusion/src/lua_VersionInfo.cpp index 4d463bb49..8dd6b5f23 100644 --- a/plugins/Dfusion/src/lua_VersionInfo.cpp +++ b/plugins/Dfusion/src/lua_VersionInfo.cpp @@ -286,7 +286,7 @@ static int __lua_resolveObjectToClassID(lua_State *S) { lua::state st(S); int32_t ret; - bool output=DFHack::Core::getInstance().vinfo->resolveObjectToClassID((void *)st.as(1),ret); + bool output=DFHack::Core::getInstance().vinfo->resolveObjectToClassID((char *)st.as(1),ret); st.push(output); st.push(ret); return 2; diff --git a/plugins/stonesense b/plugins/stonesense index 1b28039e2..45b11988b 160000 --- a/plugins/stonesense +++ b/plugins/stonesense @@ -1 +1 @@ -Subproject commit 1b28039e2c93daa3c2f69f5e2a000ff8c96ee1f8 +Subproject commit 45b11988bccfeb059f55ded6e4ad0d317e802714 From 8e993fedc3c4498c4f1f089851c8c2ee50126df5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Mr=C3=A1zek?= Date: Thu, 5 Jan 2012 23:51:47 +0100 Subject: [PATCH 14/82] Update df structures. --- library/xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/xml b/library/xml index 7a730830c..a38b76f39 160000 --- a/library/xml +++ b/library/xml @@ -1 +1 @@ -Subproject commit 7a730830c515fea701ff73b33cb604f48a4531fc +Subproject commit a38b76f3937850f7253bafe6a128956d5f7c5fe1 From 756b8131c1e30aeeebbe4859cea94e9a83b8b52d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Mr=C3=A1zek?= Date: Fri, 6 Jan 2012 00:09:49 +0100 Subject: [PATCH 15/82] Small fix in Buildings, update stonesense. --- library/modules/Buildings.cpp | 4 ++-- plugins/stonesense | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/library/modules/Buildings.cpp b/library/modules/Buildings.cpp index 6de803c3c..d48a5564d 100644 --- a/library/modules/Buildings.cpp +++ b/library/modules/Buildings.cpp @@ -119,8 +119,8 @@ bool Buildings::Read (const uint32_t index, t_building & building) building.y1 = bld_40d->y1; building.y2 = bld_40d->y2; building.z = bld_40d->z; - building.material.index = bld_40d->materialIndex; - building.material.type = bld_40d->materialType; + building.material.index = bld_40d->mat_index; + building.material.type = bld_40d->mat_type; building.type = type; building.origin = (void *) &bld_40d; return true; diff --git a/plugins/stonesense b/plugins/stonesense index 45b11988b..39a27d73e 160000 --- a/plugins/stonesense +++ b/plugins/stonesense @@ -1 +1 @@ -Subproject commit 45b11988bccfeb059f55ded6e4ad0d317e802714 +Subproject commit 39a27d73e75b7ee22d93d31a9040322b0ceaa512 From e520a1d43bd2efcb9cc978c8a109964a1abab42d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Mr=C3=A1zek?= Date: Fri, 6 Jan 2012 00:24:00 +0100 Subject: [PATCH 16/82] Fix building coord variables. --- library/xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/xml b/library/xml index a38b76f39..d03375ddb 160000 --- a/library/xml +++ b/library/xml @@ -1 +1 @@ -Subproject commit a38b76f3937850f7253bafe6a128956d5f7c5fe1 +Subproject commit d03375ddbd695fda2deb42dd13aa352efccebc60 From a2cad00dbbac8b286c6d3ce8ce4709110de47a45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Mr=C3=A1zek?= Date: Fri, 6 Jan 2012 01:08:30 +0100 Subject: [PATCH 17/82] Remove GetCustomWorkshopType, custom workshop types are now saner. --- library/include/modules/Buildings.h | 5 ++--- library/modules/Buildings.cpp | 17 +---------------- plugins/df2mc | 2 +- plugins/stonesense | 2 +- 4 files changed, 5 insertions(+), 21 deletions(-) diff --git a/library/include/modules/Buildings.h b/library/include/modules/Buildings.h index 7a3266c9e..8089fd4b1 100644 --- a/library/include/modules/Buildings.h +++ b/library/include/modules/Buildings.h @@ -69,10 +69,9 @@ namespace DFHack bool Read (const uint32_t index, t_building & building); bool Finish(); - // read a vector of names + // read mapping from custom_type value to building RAW name + // custom_type of -1 implies ordinary building bool ReadCustomWorkshopTypes(std::map & btypes); - // returns -1 on error, >= 0 for real value - int32_t GetCustomWorkshopType(t_building & building); private: struct Private; diff --git a/library/modules/Buildings.cpp b/library/modules/Buildings.cpp index d48a5564d..6f2b4a3f3 100644 --- a/library/modules/Buildings.cpp +++ b/library/modules/Buildings.cpp @@ -122,6 +122,7 @@ bool Buildings::Read (const uint32_t index, t_building & building) building.material.index = bld_40d->mat_index; building.material.type = bld_40d->mat_type; building.type = type; + building.custom_type = bld_40d->getCustomType(); building.origin = (void *) &bld_40d; return true; } @@ -153,19 +154,3 @@ bool Buildings::ReadCustomWorkshopTypes(map & btypes) return true; } -// FIXME: ugly hack -int32_t Buildings::GetCustomWorkshopType(t_building & building) -{ - if(!d->Inited) - return false; - int32_t type = (int32_t)building.type; - int32_t ret = -1; - if(type != -1 && type == d->custom_workshop_id) - { - // read the custom workshop subtype - df::building_workshopst * workshop = (df::building_workshopst *) building.origin; - ret = workshop->custom_type; - } - return ret; -} - diff --git a/plugins/df2mc b/plugins/df2mc index 355674a50..3277c6b29 160000 --- a/plugins/df2mc +++ b/plugins/df2mc @@ -1 +1 @@ -Subproject commit 355674a508d72349983455f04791b4481b6c1515 +Subproject commit 3277c6b29ddbb5d800ccb65eba27fed200236f3d diff --git a/plugins/stonesense b/plugins/stonesense index 39a27d73e..545b2730e 160000 --- a/plugins/stonesense +++ b/plugins/stonesense @@ -1 +1 @@ -Subproject commit 39a27d73e75b7ee22d93d31a9040322b0ceaa512 +Subproject commit 545b2730ed137935643778f1b8ba115ae11c50a2 From 890824dd38c0cf7f86aabdd3d9b85b9c52a5835e Mon Sep 17 00:00:00 2001 From: Tim Walberg Date: Fri, 6 Jan 2012 02:27:27 +0100 Subject: [PATCH 18/82] =?UTF-8?q?Merge=20patch=20with=20new=20dig=20patter?= =?UTF-8?q?ns=20for=20vdig=20plugin=20Signed-off-by:=20Petr=20Mr=C3=A1zek?= =?UTF-8?q?=20?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- plugins/vdig.cpp | 194 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 192 insertions(+), 2 deletions(-) diff --git a/plugins/vdig.cpp b/plugins/vdig.cpp index 290b3b933..fbbd36e46 100644 --- a/plugins/vdig.cpp +++ b/plugins/vdig.cpp @@ -459,6 +459,100 @@ static digmask diag5[5] = }, }; +static digmask diag5r[5] = +{ + { + {0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0}, + {0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0}, + {0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0}, + {0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0}, + {1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1}, + {0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0}, + {0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0}, + {0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0}, + {0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0}, + {1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1}, + {0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0}, + {0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0}, + {0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0}, + {0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0}, + {1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1}, + {0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0}, + }, + { + {0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0}, + {0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0}, + {0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0}, + {1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1}, + {0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0}, + {0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0}, + {0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0}, + {0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0}, + {1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1}, + {0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0}, + {0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0}, + {0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0}, + {0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0}, + {1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1}, + {0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0}, + {0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0}, + }, + { + {0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0}, + {0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0}, + {1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1}, + {0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0}, + {0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0}, + {0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0}, + {0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0}, + {1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1}, + {0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0}, + {0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0}, + {0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0}, + {0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0}, + {1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1}, + {0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0}, + {0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0}, + {0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0}, + }, + { + {0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0}, + {1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1}, + {0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0}, + {0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0}, + {0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0}, + {0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0}, + {1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1}, + {0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0}, + {0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0}, + {0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0}, + {0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0}, + {1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1}, + {0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0}, + {0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0}, + {0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0}, + {0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0}, + }, + { + {1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1}, + {0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0}, + {0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0}, + {0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0}, + {0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0}, + {1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1}, + {0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0}, + {0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0}, + {0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0}, + {0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0}, + {1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1}, + {0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0}, + {0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0}, + {0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0}, + {0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0}, + {1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1}, + }, +}; + static digmask ladder[3] = { { @@ -517,6 +611,64 @@ static digmask ladder[3] = }, }; +static digmask ladderr[3] = +{ + { + {0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0}, + {0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0}, + {0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1}, + {0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0}, + {0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0}, + {0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0}, + {0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0}, + {0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0}, + {0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1}, + {0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0}, + {0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0}, + {0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0}, + {0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0}, + {0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0}, + {0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1}, + {0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0}, + }, + { + {0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0}, + {0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0}, + {0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0}, + {0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0}, + {0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1}, + {0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0}, + {0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0}, + {0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0}, + {0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0}, + {0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0}, + {0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1}, + {0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0}, + {0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0}, + {0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0}, + {0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0}, + {0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0}, + }, + { + {0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1}, + {0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0}, + {0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0}, + {0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0}, + {0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0}, + {0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0}, + {0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1}, + {0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0}, + {0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0}, + {0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0}, + {0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0}, + {0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0}, + {0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1}, + {0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0}, + {0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0}, + {0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0}, + }, +}; + static digmask all_tiles = { {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, @@ -560,7 +712,9 @@ enum explo_how { EXPLO_NOTHING, EXPLO_DIAG5, + EXPLO_DIAG5R, EXPLO_LADDER, + EXPLO_LADDERR, EXPLO_CLEAR, EXPLO_CROSS, }; @@ -653,6 +807,10 @@ DFhackCExport command_result expdig (Core * c, vector & parameters) { how = EXPLO_DIAG5; } + else if(parameters[i] == "diag5r") + { + how = EXPLO_DIAG5R; + } else if(parameters[i] == "clear") { how = EXPLO_CLEAR; @@ -661,6 +819,10 @@ DFhackCExport command_result expdig (Core * c, vector & parameters) { how = EXPLO_LADDER; } + else if(parameters[i] == "ladderr") + { + how = EXPLO_LADDERR; + } else if(parameters[i] == "cross") { how = EXPLO_CROSS; @@ -674,7 +836,9 @@ DFhackCExport command_result expdig (Core * c, vector & parameters) "There are two variables that can be set: pattern and filter.\n" "Patterns:\n" " diag5 = diagonals separated by 5 tiles\n" - " ladder = A 'ladder' pattern\n" + " diag5r = diag5 rotated 90 degrees\n" + " ladder = A 'ladder' pattern\n" + "ladderr = ladder rotated 90 degrees\n" " clear = Just remove all dig designations\n" " cross = A cross, exactly in the middle of the map.\n" "Filters:\n" @@ -719,6 +883,19 @@ DFhackCExport command_result expdig (Core * c, vector & parameters) } } } + else if(how == EXPLO_DIAG5R) + { + int which; + for(uint32_t x = 0; x < x_max; x++) + { + for(int32_t y = 0 ; y < y_max; y++) + { + which = (4*x + 1000-y) % 5; + stamp_pattern(maps, x,y_max - 1 - y, z_level, diag5r[which], + how, what, x_max, y_max); + } + } + } else if(how == EXPLO_LADDER) { int which; @@ -732,6 +909,19 @@ DFhackCExport command_result expdig (Core * c, vector & parameters) } } } + else if(how == EXPLO_LADDERR) + { + int which; + for(int32_t y = 0 ; y < y_max; y++) + { + which = y % 3; + for(uint32_t x = 0; x < x_max; x++) + { + stamp_pattern(maps, x, y, z_level, ladderr[which], + how, what, x_max, y_max); + } + } + } else if(how == EXPLO_CROSS) { // middle + recentering for the image @@ -941,4 +1131,4 @@ DFhackCExport command_result vdig (Core * c, vector & parameters) DFhackCExport command_result autodig (Core * c, vector & parameters) { return CR_NOT_IMPLEMENTED; -} \ No newline at end of file +} From 571c2495229f5c38446887955cf3cac9dca64be5 Mon Sep 17 00:00:00 2001 From: Warmist Date: Fri, 6 Jan 2012 10:25:58 +0200 Subject: [PATCH 19/82] Fixed crash with dfusion migrants plugin. --- plugins/Dfusion/luafiles/migrants/init.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/Dfusion/luafiles/migrants/init.lua b/plugins/Dfusion/luafiles/migrants/init.lua index 85463fe7e..b2472b08c 100644 --- a/plugins/Dfusion/luafiles/migrants/init.lua +++ b/plugins/Dfusion/luafiles/migrants/init.lua @@ -20,7 +20,7 @@ if mypos then engine.poked(modpos+0x1c,count) --max size for div else - modpos,modsize=engine.loadmod("dfusion/migrants/migrants.o","Migrants") + modpos,modsize=engine.loadmod("dfusion/migrants/migrants.o","Migrants",400) print(string.format("Loaded module @:%x",modpos)) count=0 for _,v in pairs(names) do From 0e90e6b78e58aacd964a57290481410728b8b256 Mon Sep 17 00:00:00 2001 From: Alexander Gavrilov Date: Fri, 6 Jan 2012 22:08:09 +0400 Subject: [PATCH 20/82] Support multi-valued enum attributes. --- library/include/DataDefs.h | 7 +++++++ library/xml | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/library/include/DataDefs.h b/library/include/DataDefs.h index ff61d08f5..5d942c46a 100644 --- a/library/include/DataDefs.h +++ b/library/include/DataDefs.h @@ -135,6 +135,12 @@ namespace DFHack const char *name; int size; }; + + template + struct enum_list_attr { + int size; + const T *items; + }; DFHACK_EXPORT std::string bitfieldToString(const void *p, int size, const bitfield_item_info *items); @@ -150,6 +156,7 @@ namespace df using DFHack::virtual_identity; using DFHack::virtual_class; using DFHack::bitfield_item_info; + using DFHack::enum_list_attr; using DFHack::BitArray; template diff --git a/library/xml b/library/xml index d03375ddb..e5713a6ad 160000 --- a/library/xml +++ b/library/xml @@ -1 +1 @@ -Subproject commit d03375ddbd695fda2deb42dd13aa352efccebc60 +Subproject commit e5713a6add0c21477d3bfa5e228ecdb4b3a2c33d From f5e121a1963da0fc923b04db3ca99fdbd4328ad6 Mon Sep 17 00:00:00 2001 From: Alexander Gavrilov Date: Sat, 7 Jan 2012 19:21:07 +0400 Subject: [PATCH 21/82] Move a bunch of stuff from the jobutils plugin into the core. --- library/CMakeLists.txt | 2 + library/include/DataDefs.h | 12 ++ library/include/modules/Gui.h | 12 ++ library/include/modules/Job.h | 54 +++++++++ library/modules/Gui.cpp | 97 +++++++++++++++ library/modules/Job.cpp | 201 +++++++++++++++++++++++++++++++ library/xml | 2 +- plugins/jobutils.cpp | 220 +++++----------------------------- 8 files changed, 409 insertions(+), 191 deletions(-) create mode 100644 library/include/modules/Job.h create mode 100644 library/modules/Job.cpp diff --git a/library/CMakeLists.txt b/library/CMakeLists.txt index 808c13a18..e940264b7 100644 --- a/library/CMakeLists.txt +++ b/library/CMakeLists.txt @@ -48,6 +48,7 @@ include/modules/Units.h include/modules/Engravings.h include/modules/Gui.h include/modules/Items.h +include/modules/Job.h include/modules/kitchen.h include/modules/Maps.h include/modules/MapCache.h @@ -88,6 +89,7 @@ modules/Units.cpp modules/Engravings.cpp modules/Gui.cpp modules/Items.cpp +modules/Job.cpp modules/kitchen.cpp modules/Maps.cpp modules/Materials.cpp diff --git a/library/include/DataDefs.h b/library/include/DataDefs.h index 5d942c46a..a7fb956ed 100644 --- a/library/include/DataDefs.h +++ b/library/include/DataDefs.h @@ -188,6 +188,18 @@ namespace df } }; + template + inline bool operator== (enum_field a, enum_field b) + { + return EnumType(a) == EnumType(b); + } + + template + inline bool operator!= (enum_field a, enum_field b) + { + return EnumType(a) != EnumType(b); + } + namespace enums {} } diff --git a/library/include/modules/Gui.h b/library/include/modules/Gui.h index 3d3fe81c7..2da6cdbe7 100644 --- a/library/include/modules/Gui.h +++ b/library/include/modules/Gui.h @@ -32,6 +32,11 @@ distribution. #include "BitArray.h" #include +namespace df { + struct viewscreen; + struct job; +}; + /** * \defgroup grp_gui query DF's GUI state * @ingroup grp_modules @@ -39,6 +44,13 @@ distribution. namespace DFHack { + class Core; + + bool workshop_job_hotkey(Core *c, df::viewscreen *top); + bool build_selector_hotkey(Core *c, df::viewscreen *top); + + df::job *getSelectedWorkshopJob(Core *c, bool quiet = false); + class DFContextShared; /** * A GUI screen diff --git a/library/include/modules/Job.h b/library/include/modules/Job.h new file mode 100644 index 000000000..7136971ce --- /dev/null +++ b/library/include/modules/Job.h @@ -0,0 +1,54 @@ +/* +https://github.com/peterix/dfhack +Copyright (c) 2009-2011 Petr Mrázek (peterix@gmail.com) + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any +damages arising from the use of this software. + +Permission is granted to anyone to use this software for any +purpose, including commercial applications, and to alter it and +redistribute it freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must +not claim that you wrote the original software. If you use this +software in a product, an acknowledgment in the product documentation +would be appreciated but is not required. + +2. Altered source versions must be plainly marked as such, and +must not be misrepresented as being the original software. + +3. This notice may not be removed or altered from any source +distribution. +*/ + +#pragma once +#ifndef CL_MOD_JOB +#define CL_MOD_JOB + +#include "Export.h" +#include "Module.h" +#include + +namespace df +{ + struct job; + struct job_item; + struct job_item_filter; +} + +namespace DFHack +{ + // Duplicate the job structure. It is not linked into any DF lists. + df::job *cloneJobStruct(df::job *job); + + // Delete a cloned structure. + void deleteJobStruct(df::job *job); + + bool operator== (const df::job_item &a, const df::job_item &b); + bool operator== (const df::job &a, const df::job &b); + + void printJobDetails(Core *c, df::job *job); +} +#endif + diff --git a/library/modules/Gui.cpp b/library/modules/Gui.cpp index 1a970deeb..04f23ccba 100644 --- a/library/modules/Gui.cpp +++ b/library/modules/Gui.cpp @@ -41,8 +41,16 @@ using namespace std; using namespace DFHack; #include "DataDefs.h" +#include "df/world.h" #include "df/cursor.h" #include "df/viewscreen_dwarfmodest.h" +#include "df/ui.h" +#include "df/job.h" +#include "df/ui_build_selector.h" +#include "df/building_workshopst.h" +#include "df/building_furnacest.h" + +using namespace df::enums; // Predefined common guard functions @@ -73,6 +81,95 @@ bool DFHack::cursor_hotkey(Core *c, df::viewscreen *top) return true; } +bool DFHack::workshop_job_hotkey(Core *c, df::viewscreen *top) +{ + using namespace ui_sidebar_mode; + using df::global::ui; + using df::global::world; + using df::global::ui_workshop_in_add; + using df::global::ui_workshop_job_cursor; + + if (!dwarfmode_hotkey(c,top)) + return false; + + switch (ui->main.mode) { + case QueryBuilding: + { + if (!ui_workshop_job_cursor) // allow missing + return false; + + df::building *selected = world->selected_building; + if (!virtual_cast(selected) && + !virtual_cast(selected)) + return false; + + // No jobs? + if (selected->jobs.empty() || + selected->jobs[0]->job_type == job_type::DestroyBuilding) + return false; + + // Add job gui activated? + if (ui_workshop_in_add && *ui_workshop_in_add) + return false; + + return true; + }; + default: + return false; + } +} + +bool DFHack::build_selector_hotkey(Core *c, df::viewscreen *top) +{ + using namespace ui_sidebar_mode; + using df::global::ui; + using df::global::ui_build_selector; + + if (!dwarfmode_hotkey(c,top)) + return false; + + switch (ui->main.mode) { + case Build: + { + if (!ui_build_selector) // allow missing + return false; + + // Not selecting, or no choices? + if (ui_build_selector->building_type < 0 || + ui_build_selector->stage != 2 || + ui_build_selector->choices.empty()) + return false; + + return true; + }; + default: + return false; + } +} + +df::job *DFHack::getSelectedWorkshopJob(Core *c, bool quiet) +{ + using df::global::world; + using df::global::ui_workshop_job_cursor; + + if (!workshop_job_hotkey(c, c->getTopViewscreen())) { + if (!quiet) + c->con.printerr("Not in a workshop, or no job is highlighted.\n"); + return NULL; + } + + df::building *selected = world->selected_building; + int idx = *ui_workshop_job_cursor; + + if (idx < 0 || idx >= selected->jobs.size()) + { + c->con.printerr("Invalid job cursor index: %d\n", idx); + return NULL; + } + + return selected->jobs[idx]; +} + // Module* DFHack::createGui() diff --git a/library/modules/Job.cpp b/library/modules/Job.cpp new file mode 100644 index 000000000..a91146c98 --- /dev/null +++ b/library/modules/Job.cpp @@ -0,0 +1,201 @@ +/* +https://github.com/peterix/dfhack +Copyright (c) 2009-2011 Petr Mrázek (peterix@gmail.com) + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any +damages arising from the use of this software. + +Permission is granted to anyone to use this software for any +purpose, including commercial applications, and to alter it and +redistribute it freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must +not claim that you wrote the original software. If you use this +software in a product, an acknowledgment in the product documentation +would be appreciated but is not required. + +2. Altered source versions must be plainly marked as such, and +must not be misrepresented as being the original software. + +3. This notice may not be removed or altered from any source +distribution. +*/ + + +#include "Internal.h" + +#include +#include +#include +#include +using namespace std; + +#include "Core.h" +#include "PluginManager.h" + +#include "modules/Job.h" +#include "modules/Materials.h" + +#include "DataDefs.h" +#include +#include +#include +#include +#include +#include +#include + +using namespace DFHack; +using namespace df::enums; + +df::job *DFHack::cloneJobStruct(df::job *job) +{ + df::job *pnew = new df::job(*job); + + // Clean out transient fields + pnew->flags.whole = 0; + pnew->flags.bits.repeat = job->flags.bits.repeat; + pnew->flags.bits.suspend = job->flags.bits.suspend; + + pnew->list_link = NULL; + pnew->completion_timer = -1; + pnew->items.clear(); + pnew->misc_links.clear(); + + // Clone refs + for (int i = pnew->references.size()-1; i >= 0; i--) + { + df::general_ref *ref = pnew->references[i]; + + if (virtual_cast(ref)) + pnew->references.erase(pnew->references.begin()+i); + else + pnew->references[i] = ref->clone(); + } + + // Clone items + for (int i = pnew->job_items.size()-1; i >= 0; i--) + pnew->job_items[i] = new df::job_item(*pnew->job_items[i]); + + return pnew; +} + +void DFHack::deleteJobStruct(df::job *job) +{ + if (!job) + return; + + // Only allow free-floating job structs + assert(!job->list_link && job->items.empty() && job->misc_links.empty()); + + for (int i = job->references.size()-1; i >= 0; i--) + delete job->references[i]; + + for (int i = job->job_items.size()-1; i >= 0; i--) + delete job->job_items[i]; + + delete job; +} + +#define CMP(field) (a.field == b.field) + +bool DFHack::operator== (const df::job_item &a, const df::job_item &b) +{ + if (!(CMP(item_type) && CMP(item_subtype) && + CMP(mat_type) && CMP(mat_index) && + CMP(flags1.whole) && CMP(quantity) && CMP(vector_id) && + CMP(flags2.whole) && CMP(flags3.whole) && + CMP(metal_ore) && CMP(reaction_class) && + CMP(has_material_reaction_product) && + CMP(min_dimension) && CMP(reagent_index) && + CMP(reaction_id) && CMP(has_tool_use) && + CMP(contains.size()))) + return false; + + for (int i = a.contains.size()-1; i >= 0; i--) + if (a.contains[i] != b.contains[i]) + return false; + + return true; +} + +bool DFHack::operator== (const df::job &a, const df::job &b) +{ + if (!(CMP(job_type) && CMP(unk2) && + CMP(mat_type) && CMP(mat_index) && + CMP(item_subtype) && CMP(item_category.whole) && + CMP(hist_figure_id) && CMP(material_category.whole) && + CMP(reaction_name) && CMP(job_items.size()))) + return false; + + for (int i = a.job_items.size()-1; i >= 0; i--) + if (!(*a.job_items[i] == *b.job_items[i])) + return false; + + return true; +} + +static void print_job_item_details(Core *c, df::job *job, unsigned idx, df::job_item *item) +{ + c->con << " Input Item " << (idx+1) << ": " << ENUM_KEY_STR(item_type,item->item_type); + if (item->item_subtype != -1) + c->con << " [" << item->item_subtype << "]"; + if (item->quantity != 1) + c->con << "; quantity=" << item->quantity; + if (item->min_dimension >= 0) + c->con << "; min_dimension=" << item->min_dimension; + c->con << endl; + + MaterialInfo mat(item); + if (mat.isValid() || item->metal_ore >= 0) { + c->con << " material: " << mat.toString(); + if (item->metal_ore >= 0) + c->con << "; ore of " << MaterialInfo(0,item->metal_ore).toString(); + c->con << endl; + } + + if (item->flags1.whole) + c->con << " flags1: " << bitfieldToString(item->flags1) << endl; + if (item->flags2.whole) + c->con << " flags2: " << bitfieldToString(item->flags2) << endl; + if (item->flags3.whole) + c->con << " flags3: " << bitfieldToString(item->flags3) << endl; + + if (!item->reaction_class.empty()) + c->con << " reaction class: " << item->reaction_class << endl; + if (!item->has_material_reaction_product.empty()) + c->con << " reaction product: " << item->has_material_reaction_product << endl; + if (item->has_tool_use >= 0) + c->con << " tool use: " << ENUM_KEY_STR(tool_uses, item->has_tool_use) << endl; +} + +void DFHack::printJobDetails(Core *c, df::job *job) +{ + c->con << "Job " << job->id << ": " << ENUM_KEY_STR(job_type,job->job_type); + if (job->flags.whole) + c->con << " (" << bitfieldToString(job->flags) << ")"; + c->con << endl; + + MaterialInfo mat(job); + if (mat.isValid() || job->material_category.whole) + { + c->con << " material: " << mat.toString(); + if (job->material_category.whole) + c->con << " (" << bitfieldToString(job->material_category) << ")"; + c->con << endl; + } + + if (job->item_subtype >= 0 || job->item_category.whole) + c->con << " item: " << job->item_subtype + << " (" << bitfieldToString(job->item_category) << ")" << endl; + + if (job->hist_figure_id >= 0) + c->con << " figure: " << job->hist_figure_id << endl; + + if (!job->reaction_name.empty()) + c->con << " reaction: " << job->reaction_name << endl; + + for (unsigned i = 0; i < job->job_items.size(); i++) + print_job_item_details(c, job, i, job->job_items[i]); +} diff --git a/library/xml b/library/xml index e5713a6ad..30d6b3330 160000 --- a/library/xml +++ b/library/xml @@ -1 +1 @@ -Subproject commit e5713a6add0c21477d3bfa5e228ecdb4b3a2c33d +Subproject commit 30d6b333037b2f5d968aad738b67d5bed42993d3 diff --git a/plugins/jobutils.cpp b/plugins/jobutils.cpp index 66ed00024..a89fa99cd 100644 --- a/plugins/jobutils.cpp +++ b/plugins/jobutils.cpp @@ -5,6 +5,8 @@ #include #include +#include +#include #include #include @@ -37,8 +39,6 @@ using df::global::job_next_id; /* Plugin registration */ -static bool workshop_job_hotkey(Core *c, df::viewscreen *top); -static bool build_selector_hotkey(Core *c, df::viewscreen *top); static bool job_material_hotkey(Core *c, df::viewscreen *top); static command_result job_material(Core *c, vector & parameters); @@ -106,67 +106,6 @@ DFhackCExport command_result plugin_shutdown ( Core * c ) /* UI state guards */ -static bool workshop_job_hotkey(Core *c, df::viewscreen *top) -{ - using namespace ui_sidebar_mode; - - if (!dwarfmode_hotkey(c,top)) - return false; - - switch (ui->main.mode) { - case QueryBuilding: - { - if (!ui_workshop_job_cursor) // allow missing - return false; - - df::building *selected = world->selected_building; - if (!virtual_cast(selected) && - !virtual_cast(selected)) - return false; - - // No jobs? - if (selected->jobs.empty() || - selected->jobs[0]->job_type == job_type::DestroyBuilding) - return false; - - // Add job gui activated? - if (df::global::ui_workshop_in_add && // allow missing - *df::global::ui_workshop_in_add) - return false; - - return true; - }; - default: - return false; - } -} - -static bool build_selector_hotkey(Core *c, df::viewscreen *top) -{ - using namespace ui_sidebar_mode; - - if (!dwarfmode_hotkey(c,top)) - return false; - - switch (ui->main.mode) { - case Build: - { - if (!ui_build_selector) // allow missing - return false; - - // Not selecting, or no choices? - if (ui_build_selector->building_type < 0 || - ui_build_selector->stage != 2 || - ui_build_selector->choices.empty()) - return false; - - return true; - }; - default: - return false; - } -} - static bool job_material_hotkey(Core *c, df::viewscreen *top) { return workshop_job_hotkey(c, top) || @@ -175,23 +114,9 @@ static bool job_material_hotkey(Core *c, df::viewscreen *top) /* job-material implementation */ -static df::job *getWorkshopJob(Core *c) -{ - df::building *selected = world->selected_building; - int idx = *ui_workshop_job_cursor; - - if (idx < 0 || idx >= selected->jobs.size()) - { - c->con.printerr("Invalid job cursor index: %d\n", idx); - return NULL; - } - - return selected->jobs[idx]; -} - static command_result job_material_in_job(Core *c, MaterialInfo &new_mat) { - df::job *job = getWorkshopJob(c); + df::job *job = getSelectedWorkshopJob(c); if (!job) return CR_FAILURE; @@ -248,13 +173,13 @@ static command_result job_material_in_job(Core *c, MaterialInfo &new_mat) } static bool build_choice_matches(df::ui_build_item_req *req, df::build_req_choicest *choice, - MaterialInfo &new_mat) + MaterialInfo &new_mat, bool ignore_select) { if (VIRTUAL_CAST_VAR(gen, df::build_req_choice_genst, choice)) { if (gen->mat_type == new_mat.type && gen->mat_index == new_mat.index && - gen->used_count < gen->candidates.size()) + (ignore_select || gen->used_count < gen->candidates.size())) { return true; } @@ -264,7 +189,7 @@ static bool build_choice_matches(df::ui_build_item_req *req, df::build_req_choic if (spec->candidate && spec->candidate->getActualMaterial() == new_mat.type && spec->candidate->getActualMaterialIndex() == new_mat.index && - !req->candidate_selected[spec->candidate_id]) + (ignore_select || !req->candidate_selected[spec->candidate_id])) { return true; } @@ -275,13 +200,22 @@ static bool build_choice_matches(df::ui_build_item_req *req, df::build_req_choic static command_result job_material_in_build(Core *c, MaterialInfo &new_mat) { - df::ui_build_item_req *req = ui_build_selector->requirements[ui_build_selector->req_index]; + df::ui_build_selector *sel = ui_build_selector; + df::ui_build_item_req *req = sel->requirements[ui_build_selector->req_index]; + + // Loop through matching choices + bool matches = build_choice_matches(req, sel->choices[sel->sel_index], new_mat, true); + + int size = sel->choices.size(); + int base = (matches ? sel->sel_index + 1 : 0); - for (unsigned i = 0; i < ui_build_selector->choices.size(); i++) + for (unsigned i = 0; i < size; i++) { - if (build_choice_matches(req, ui_build_selector->choices[i], new_mat)) + int idx = (base + i) % size; + + if (build_choice_matches(req, sel->choices[idx], new_mat, false)) { - ui_build_selector->sel_index = i; + sel->sel_index = idx; return CR_OK; } } @@ -317,39 +251,16 @@ static command_result job_material(Core * c, vector & parameters) static df::job *clone_job(df::job *job) { - df::job *pnew = new df::job(*job); + df::job *pnew = cloneJobStruct(job); pnew->id = (*job_next_id)++; - // Clean out transient fields - pnew->flags.whole = 0; - pnew->flags.bits.repeat = job->flags.bits.repeat; - - pnew->completion_timer = -1; - pnew->items.clear(); - pnew->misc_links.clear(); - // Link the job into the global list pnew->list_link = new df::job_list_link(); pnew->list_link->item = pnew; linked_list_append(&world->job_list, pnew->list_link); - // Clone refs - for (int i = pnew->references.size()-1; i >= 0; i--) - { - df::general_ref *ref = pnew->references[i]; - - if (virtual_cast(ref)) - pnew->references.erase(pnew->references.begin()+i); - else - pnew->references[i] = ref->clone(); - } - - // Clone items - for (int i = pnew->job_items.size()-1; i >= 0; i--) - pnew->job_items[i] = new df::job_item(*pnew->job_items[i]); - return pnew; } @@ -358,7 +269,7 @@ static command_result job_duplicate(Core * c, vector & parameters) if (!parameters.empty()) return CR_WRONG_USAGE; - df::job *job = getWorkshopJob(c); + df::job *job = getSelectedWorkshopJob(c); if (!job) return CR_FAILURE; @@ -386,80 +297,6 @@ static command_result job_duplicate(Core * c, vector & parameters) /* Main job command implementation */ -static void print_job_item_details(Core *c, df::job *job, unsigned idx, df::job_item *item) -{ - c->con << " Input Item " << (idx+1) << ": " << ENUM_KEY_STR(item_type,item->item_type); - if (item->item_subtype != -1) - c->con << " [" << item->item_subtype << "]"; - if (item->quantity != 1) - c->con << "; quantity=" << item->quantity; - if (item->min_dimension >= 0) - c->con << "; min_dimension=" << item->min_dimension; - c->con << endl; - - MaterialInfo mat(item); - if (mat.isValid() || item->metal_ore >= 0) { - c->con << " material: " << mat.toString(); - if (item->metal_ore >= 0) - c->con << "; ore of " << MaterialInfo(0,item->metal_ore).toString(); - c->con << endl; - } - - if (item->flags1.whole) - c->con << " flags1: " << bitfieldToString(item->flags1) << endl; - if (item->flags2.whole) - c->con << " flags2: " << bitfieldToString(item->flags2) << endl; - if (item->flags3.whole) - c->con << " flags3: " << bitfieldToString(item->flags3) << endl; - - if (!item->reaction_class.empty()) - c->con << " reaction class: " << item->reaction_class << endl; - if (!item->has_material_reaction_product.empty()) - c->con << " reaction product: " << item->has_material_reaction_product << endl; - if (item->has_tool_use >= 0) - c->con << " tool use: " << ENUM_KEY_STR(tool_uses, item->has_tool_use) << endl; -} - -static void print_job_details(Core *c, df::job *job) -{ - c->con << "Job " << job->id << ": " << ENUM_KEY_STR(job_type,job->job_type); - if (job->flags.whole) - c->con << " (" << bitfieldToString(job->flags) << ")"; - c->con << endl; - - MaterialInfo mat(job); - if (mat.isValid() || job->material_category.whole) - { - c->con << " material: " << mat.toString(); - if (job->material_category.whole) - c->con << " (" << bitfieldToString(job->material_category) << ")"; - c->con << endl; - } - - if (job->item_subtype >= 0 || job->item_category.whole) - c->con << " item: " << job->item_subtype - << " (" << bitfieldToString(job->item_category) << ")" << endl; - - if (job->hist_figure_id >= 0) - c->con << " figure: " << job->hist_figure_id << endl; - - if (!job->reaction_name.empty()) - c->con << " reaction: " << job->reaction_name << endl; - - for (unsigned i = 0; i < job->job_items.size(); i++) - print_job_item_details(c, job, i, job->job_items[i]); -} - -static df::job *getWorkshopJobSafe(Core *c) -{ - if (!workshop_job_hotkey(c, c->getTopViewscreen())) { - c->con.printerr("No job is highlighted.\n"); - return NULL; - } - - return getWorkshopJob(c); -} - static command_result job_cmd(Core * c, vector & parameters) { CoreSuspender suspend(c); @@ -470,16 +307,16 @@ static command_result job_cmd(Core * c, vector & parameters) std::string cmd = parameters[0]; if (cmd == "query" || cmd == "list") { - df::job *job = getWorkshopJobSafe(c); + df::job *job = getSelectedWorkshopJob(c); if (!job) return CR_WRONG_USAGE; if (cmd == "query") { - print_job_details(c, job); + printJobDetails(c, job); } else { df::building *selected = world->selected_building; for (unsigned i = 0; i < selected->jobs.size(); i++) - print_job_details(c, selected->jobs[i]); + printJobDetails(c, selected->jobs[i]); } } else if (cmd == "item-material") @@ -487,7 +324,7 @@ static command_result job_cmd(Core * c, vector & parameters) if (parameters.size() < 1+1+1) return CR_WRONG_USAGE; - df::job *job = getWorkshopJobSafe(c); + df::job *job = getSelectedWorkshopJob(c); if (!job) return CR_WRONG_USAGE; @@ -508,7 +345,7 @@ static command_result job_cmd(Core * c, vector & parameters) if (!info.matches(*item)) { c->con.printerr("Material does not match the requirements.\n"); - print_job_details(c, job); + printJobDetails(c, job); return CR_FAILURE; } @@ -524,9 +361,12 @@ static command_result job_cmd(Core * c, vector & parameters) item->mat_index = info.index; c->con << "Job item " << v << " updated." << endl; - print_job_details(c, job); + printJobDetails(c, job); return CR_OK; } + else if (cmd == "item-type") + { + } else return CR_WRONG_USAGE; From 07ad9ad97296c0ed0e223729e428d25589148686 Mon Sep 17 00:00:00 2001 From: Alexander Gavrilov Date: Sat, 7 Jan 2012 19:21:31 +0400 Subject: [PATCH 22/82] Add persistent data storage in fake historical figure names. --- library/include/modules/World.h | 32 ++++++++++++++ library/modules/World.cpp | 74 +++++++++++++++++++++++++++++++++ 2 files changed, 106 insertions(+) diff --git a/library/include/modules/World.h b/library/include/modules/World.h index 01ad231d0..50feb1495 100644 --- a/library/include/modules/World.h +++ b/library/include/modules/World.h @@ -80,6 +80,30 @@ namespace DFHack GameType g_type; }; class DFContextShared; + + class DFHACK_EXPORT PersistentDataItem { + friend class World; + + int id; + std::string key_value; + + std::string *str_value; + int *int_values; + public: + static const int NumInts = 7; + + bool isValid() { return id != 0; } + + const std::string &key() { return key_value; } + + std::string &val() { return *str_value; } + int &ival(int i) { return int_values[i]; } + + PersistentDataItem() : id(0), str_value(0), int_values(0) {} + PersistentDataItem(int id, const std::string &key, std::string *sv, int *iv) + : id(id), key_value(key), str_value(sv), int_values(iv) {} + }; + /** * The World module * \ingroup grp_modules @@ -108,6 +132,14 @@ namespace DFHack bool ReadGameMode(t_gamemodes& rd); bool WriteGameMode(const t_gamemodes & wr); // this is very dangerous std::string ReadWorldFolder(); + + // Store data in fake historical figure names. + // This ensures that the values are stored in save games. + PersistentDataItem AddPersistentData(const std::string &key); + PersistentDataItem GetPersistentData(const std::string &key); + void GetPersistentData(std::vector *vec, const std::string &key); + void DeletePersistentData(const PersistentDataItem &item); + private: struct Private; Private *d; diff --git a/library/modules/World.cpp b/library/modules/World.cpp index 5d1292a9e..4dea79c2b 100644 --- a/library/modules/World.cpp +++ b/library/modules/World.cpp @@ -38,6 +38,12 @@ using namespace std; #include "ModuleFactory.h" #include "Core.h" +#include "MiscUtils.h" + +#include "DataDefs.h" +#include "df/world.h" +#include "df/historical_figure.h" + using namespace DFHack; Module* DFHack::createWorld() @@ -241,3 +247,71 @@ string World::ReadWorldFolder() } return string(""); } + +static PersistentDataItem dataFromHFig(df::historical_figure *hfig) +{ + return PersistentDataItem(hfig->id, hfig->name.first_name, &hfig->name.nickname, hfig->name.words); +} + +PersistentDataItem World::AddPersistentData(const std::string &key) +{ + std::vector &hfvec = df::historical_figure::get_vector(); + + int new_id = -100; + if (hfvec.size() > 0 && hfvec[0]->id <= new_id) + new_id = hfvec[0]->id-1; + + df::historical_figure *hfig = new df::historical_figure(); + hfig->id = new_id; + hfig->name.has_name = true; + hfig->name.first_name = key; + memset(hfig->name.words, 0, sizeof(hfig->name.words)); + + hfvec.insert(hfvec.begin(), hfig); + return dataFromHFig(hfig); +} + +PersistentDataItem World::GetPersistentData(const std::string &key) +{ + std::vector &hfvec = df::historical_figure::get_vector(); + for (unsigned i = 0; i < hfvec.size(); i++) + { + df::historical_figure *hfig = hfvec[i]; + + if (hfig->id >= 0) + break; + + if (hfig->name.has_name && hfig->name.first_name == key) + return dataFromHFig(hfig); + } + + return PersistentDataItem(); +} + +void World::GetPersistentData(std::vector *vec, const std::string &key) +{ + std::vector &hfvec = df::historical_figure::get_vector(); + for (unsigned i = 0; i < hfvec.size(); i++) + { + df::historical_figure *hfig = hfvec[i]; + + if (hfig->id >= 0) + break; + + if (hfig->name.has_name && hfig->name.first_name == key) + vec->push_back(dataFromHFig(hfig)); + } +} + +void World::DeletePersistentData(const PersistentDataItem &item) +{ + if (item.id > -100) + return; + + std::vector &hfvec = df::historical_figure::get_vector(); + int idx = binsearch_index(hfvec, item.id); + if (idx >= 0) { + delete hfvec[idx]; + hfvec.erase(hfvec.begin()+idx); + } +} From 87009c0535edae3acf2c95c3f4f8b1e6f6f8ba5c Mon Sep 17 00:00:00 2001 From: Alexander Gavrilov Date: Sat, 7 Jan 2012 21:47:23 +0400 Subject: [PATCH 23/82] Add a plugin that protects specific repeat jobs from disappearing. If they do disappear, they are re-added in a suspended state. --- library/include/modules/Gui.h | 6 +- library/include/modules/Job.h | 10 +- library/xml | 2 +- plugins/CMakeLists.txt | 1 + plugins/workflow.cpp | 536 ++++++++++++++++++++++++++++++++++ 5 files changed, 546 insertions(+), 9 deletions(-) create mode 100644 plugins/workflow.cpp diff --git a/library/include/modules/Gui.h b/library/include/modules/Gui.h index 2da6cdbe7..7e07cbd4d 100644 --- a/library/include/modules/Gui.h +++ b/library/include/modules/Gui.h @@ -46,10 +46,10 @@ namespace DFHack { class Core; - bool workshop_job_hotkey(Core *c, df::viewscreen *top); - bool build_selector_hotkey(Core *c, df::viewscreen *top); + DFHACK_EXPORT bool workshop_job_hotkey(Core *c, df::viewscreen *top); + DFHACK_EXPORT bool build_selector_hotkey(Core *c, df::viewscreen *top); - df::job *getSelectedWorkshopJob(Core *c, bool quiet = false); + DFHACK_EXPORT df::job *getSelectedWorkshopJob(Core *c, bool quiet = false); class DFContextShared; /** diff --git a/library/include/modules/Job.h b/library/include/modules/Job.h index 7136971ce..35f4fdc39 100644 --- a/library/include/modules/Job.h +++ b/library/include/modules/Job.h @@ -40,15 +40,15 @@ namespace df namespace DFHack { // Duplicate the job structure. It is not linked into any DF lists. - df::job *cloneJobStruct(df::job *job); + DFHACK_EXPORT df::job *cloneJobStruct(df::job *job); // Delete a cloned structure. - void deleteJobStruct(df::job *job); + DFHACK_EXPORT void deleteJobStruct(df::job *job); - bool operator== (const df::job_item &a, const df::job_item &b); - bool operator== (const df::job &a, const df::job &b); + DFHACK_EXPORT bool operator== (const df::job_item &a, const df::job_item &b); + DFHACK_EXPORT bool operator== (const df::job &a, const df::job &b); - void printJobDetails(Core *c, df::job *job); + DFHACK_EXPORT void printJobDetails(Core *c, df::job *job); } #endif diff --git a/library/xml b/library/xml index 30d6b3330..731fd6ca6 160000 --- a/library/xml +++ b/library/xml @@ -1 +1 @@ -Subproject commit 30d6b333037b2f5d968aad738b67d5bed42993d3 +Subproject commit 731fd6ca6fb5bd8be8172b35c417aab092ca305d diff --git a/plugins/CMakeLists.txt b/plugins/CMakeLists.txt index 2e60e9b34..7b9ea0d10 100644 --- a/plugins/CMakeLists.txt +++ b/plugins/CMakeLists.txt @@ -63,6 +63,7 @@ DFHACK_PLUGIN(rename rename.cpp) DFHACK_PLUGIN(fixwagons fixwagons.cpp) DFHACK_PLUGIN(jobutils jobutils.cpp) DFHACK_PLUGIN(regrass regrass.cpp) +DFHACK_PLUGIN(workflow workflow.cpp) #DFHACK_PLUGIN(versionosd versionosd.cpp) # this is the skeleton plugin. If you want to make your own, make a copy and then change it diff --git a/plugins/workflow.cpp b/plugins/workflow.cpp new file mode 100644 index 000000000..99d7dc411 --- /dev/null +++ b/plugins/workflow.cpp @@ -0,0 +1,536 @@ +#include "Core.h" +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using std::vector; +using std::string; +using std::endl; +using namespace DFHack; +using namespace df::enums; + +using df::global::world; +using df::global::ui; +using df::global::ui_workshop_job_cursor; +using df::global::job_next_id; + +/* Plugin registration */ + +static command_result protect_job(Core *c, vector & parameters); + +static void init_state(Core *c); +static void cleanup_state(Core *c); + +DFhackCExport const char * plugin_name ( void ) +{ + return "workflow"; +} + +DFhackCExport command_result plugin_init (Core *c, std::vector &commands) +{ + commands.clear(); + if (!world || !ui) + return CR_FAILURE; + + if (ui_workshop_job_cursor && job_next_id) { + commands.push_back( + PluginCommand( + "protect-job", "Manage protection of workshop jobs from removal.", + protect_job, false, + " protect-job list\n" + " List protected jobs. If a workshop is selected, filters by it.\n" + " protect-job add [all]\n" + " Protect the selected job, or any repeat jobs (possibly in the workshop).\n" + " protect-job remove [all]\n" + " Unprotect the selected job, or any repeat jobs (possibly in the workshop).\n" + ) + ); + } + + init_state(c); + + return CR_OK; +} + +DFhackCExport command_result plugin_shutdown ( Core * c ) +{ + cleanup_state(c); + + return CR_OK; +} + +DFhackCExport command_result plugin_onstatechange(Core* c, state_change_event event) +{ + switch (event) { + case SC_GAME_LOADED: + cleanup_state(c); + init_state(c); + break; + case SC_GAME_UNLOADED: + cleanup_state(c); + break; + default: + break; + } + + return CR_OK; +} + +/*******************************/ + +static df::building *getJobHolder(df::job *job) +{ + for (unsigned i = 0; i < job->references.size(); i++) + { + VIRTUAL_CAST_VAR(ref, df::general_ref_building_holderst, job->references[i]); + if (ref) + return ref->getBuilding(); + } + + return NULL; +}; + +struct ProtectedJob { + int id; + int building_id; + int check_idx; + + bool live; + df::building *holder; + df::job *job_copy; + + ProtectedJob(df::job *job) : id(job->id), live(true) + { + check_idx = 0; + holder = getJobHolder(job); + building_id = holder ? holder->id : -1; + job_copy = cloneJobStruct(job); + } + + ~ProtectedJob() + { + deleteJobStruct(job_copy); + } + + void update(df::job *job) + { + if (*job == *job_copy) + return; + + deleteJobStruct(job_copy); + job_copy = cloneJobStruct(job); + } +}; + +PersistentDataItem config; +static std::vector protected_cfg; + +typedef std::map TKnownJobs; +static TKnownJobs known_jobs; + +static std::vector pending_recover; + +static ProtectedJob *get_known(int id) +{ + TKnownJobs::iterator it = known_jobs.find(id); + return (it != known_jobs.end()) ? it->second : NULL; +} + +static void enumLiveJobs(std::map &rv) +{ + df::job_list_link *p = world->job_list.next; + for (; p; p = p->next) + rv[p->item->id] = p->item; +} + +static void cleanup_state(Core *) +{ + config = PersistentDataItem(); + protected_cfg.clear(); + + pending_recover.clear(); + + for (TKnownJobs::iterator it = known_jobs.begin(); it != known_jobs.end(); ++it) + delete it->second; + + known_jobs.clear(); +} + +static void init_state(Core *c) +{ + config = c->getWorld()->GetPersistentData("workflow/config"); + c->getWorld()->GetPersistentData(&protected_cfg, "workflow/protected-jobs"); + + std::map jobs; + enumLiveJobs(jobs); + + for (unsigned i = 0; i < protected_cfg.size(); i++) + { + PersistentDataItem &item = protected_cfg[i]; + for (int j = 0; j < PersistentDataItem::NumInts; j++) + { + int id = item.ival(j); + if (id <= 0) + continue; + + if (get_known(id)) // duplicate + { + item.ival(j) = -1; + continue; + } + + df::job *job = jobs[id]; + if (!job) + { + c->con.printerr("Protected job lost: %d\n", id); + item.ival(j) = -1; + continue; + } + + if (!job->misc_links.empty() || job->job_items.empty()) + { + c->con.printerr("Protected job unsupported: %d (%s)\n", + id, ENUM_KEY_STR(job_type, job->job_type)); + item.ival(j) = -1; + continue; + } + + ProtectedJob *pj = new ProtectedJob(job); + if (!pj->holder) + { + c->con.printerr("Protected job not in building: %d (%s)\n", + id, ENUM_KEY_STR(job_type, job->job_type)); + delete pj; + item.ival(j) = -1; + continue; + } + + known_jobs[id] = pj; + + if (!job->flags.bits.repeat) { + c->con.printerr("Protected job not repeating: %d\n", id); + job->flags.bits.repeat = true; + } + } + } + + if (!known_jobs.empty()) + c->con.print("Protecting %d jobs.\n", known_jobs.size()); +} + +static int *find_protected_id_slot(Core *c, int key) +{ + for (unsigned i = 0; i < protected_cfg.size(); i++) + { + PersistentDataItem &item = protected_cfg[i]; + for (int j = 0; j < PersistentDataItem::NumInts; j++) + { + if (item.ival(j) == key) + return &item.ival(j); + } + } + + if (key == -1) { + protected_cfg.push_back(c->getWorld()->AddPersistentData("workflow/protected-jobs")); + PersistentDataItem &item = protected_cfg.back(); + for (int j = 0; j < PersistentDataItem::NumInts; j++) + item.ival(j) = -1; + return &item.ival(0); + } + + return NULL; +} + +static void forget_job(Core *c, ProtectedJob *pj) +{ + known_jobs.erase(pj->id); + + if (int *p = find_protected_id_slot(c, pj->id)) + *p = -1; + + delete pj; +} + +static void remember_job(Core *c, df::job *job) +{ + if (get_known(job->id)) + return; + + if (!job->misc_links.empty() || job->job_items.empty()) + { + c->con.printerr("Unsupported job type: %d (%s)\n", + job->id, ENUM_KEY_STR(job_type, job->job_type)); + return; + } + + known_jobs[job->id] = new ProtectedJob(job); + + *find_protected_id_slot(c, -1) = job->id; +} + +static bool recover_job(Core *c, ProtectedJob *pj) +{ + // Check that the building exists + pj->holder = df::building::find(pj->building_id); + if (!pj->holder) + { + c->con.printerr("Forgetting job %d (%s): holder building lost.", + pj->id, ENUM_KEY_STR(job_type, pj->job_copy->job_type)); + forget_job(c, pj); + return true; + } + + // Check its state and postpone or cancel if invalid + if (pj->holder->jobs.size() >= 10) + { + c->con.printerr("Forgetting job %d (%s): holder building has too many jobs.", + pj->id, ENUM_KEY_STR(job_type, pj->job_copy->job_type)); + forget_job(c, pj); + return true; + } + + if (!pj->holder->jobs.empty()) + { + df::job_type ftype = pj->holder->jobs[0]->job_type; + if (ftype == job_type::DestroyBuilding) + return false; + + if (ENUM_ATTR(job_type,type,ftype) == job_type_class::StrangeMood) + return false; + } + + // Find the position in the job list + df::job_list_link *ins_pos = &world->job_list; + while (ins_pos->next && ins_pos->next->item->id < pj->id) + ins_pos = ins_pos->next; + + if (ins_pos->next && ins_pos->next->item->id == pj->id) + { + c->con.printerr("Inconsistency: job %d (%s) already in list.", + pj->id, ENUM_KEY_STR(job_type, pj->job_copy->job_type)); + pj->live = true; + return true; + } + + // Create the actual job structure + df::job *recovered = cloneJobStruct(pj->job_copy); + + recovered->flags.bits.repeat = true; + recovered->flags.bits.suspend = true; + + // Link the job into the global list + df::job_list_link *link = new df::job_list_link(); + recovered->list_link = link; + + link->item = recovered; + link->next = ins_pos->next; + if (ins_pos->next) + ins_pos->next->prev = link; + link->prev = ins_pos; + ins_pos->next = link; + + // Add to building jobs + pj->holder->jobs.push_back(recovered); + + // Done + pj->live = true; + return true; +} + +static void check_lost_jobs(Core *c) +{ + static int check = 1; + check++; + + df::job_list_link *p = world->job_list.next; + for (; p; p = p->next) + { + ProtectedJob *pj = get_known(p->item->id); + if (!pj) + continue; + pj->check_idx = check; + + // force repeat + p->item->flags.bits.repeat = true; + } + + for (TKnownJobs::const_iterator it = known_jobs.begin(); it != known_jobs.end(); ++it) + { + if (it->second->check_idx == check || !it->second->live) + continue; + + it->second->live = false; + pending_recover.push_back(it->second); + } +} + +static void update_job_data(Core *c) +{ + df::job_list_link *p = world->job_list.next; + for (; p; p = p->next) + { + ProtectedJob *pj = get_known(p->item->id); + if (!pj) + continue; + pj->update(p->item); + } +} + +DFhackCExport command_result plugin_onupdate(Core* c) +{ + if (known_jobs.empty()) + return CR_OK; + + static unsigned cnt = 0; + cnt++; + + if ((cnt % 10) == 0) + { + for (int i = pending_recover.size()-1; i >= 0; i--) + if (recover_job(c, pending_recover[i])) + pending_recover.erase(pending_recover.begin()+i); + + check_lost_jobs(c); + } + + if ((cnt % 500) == 0) + update_job_data(c); + + return CR_OK; +} + +static command_result protect_job(Core *c, vector & parameters) +{ + CoreSuspender suspend(c); + + if (parameters.empty()) + return CR_WRONG_USAGE; + + df::building *workshop = NULL; + df::job *job = NULL; + + if (dwarfmode_hotkey(c, c->getTopViewscreen()) && + ui->main.mode == ui_sidebar_mode::QueryBuilding) + { + workshop = world->selected_building; + job = getSelectedWorkshopJob(c, true); + } + + std::map jobs; + enumLiveJobs(jobs); + update_job_data(c); + + std::string cmd = parameters[0]; + if (cmd == "list") + { + if (workshop) + { + for (unsigned i = 0; i < workshop->jobs.size(); i++) + if (get_known(workshop->jobs[i]->id)) + printJobDetails(c, workshop->jobs[i]); + } + else + { + for (TKnownJobs::iterator it = known_jobs.begin(); it != known_jobs.end(); ++it) + if (df::job *job = jobs[it->first]) + printJobDetails(c, job); + } + + bool pending = false; + + for (unsigned i = 0; i < pending_recover.size(); i++) + { + if (!workshop || pending_recover[i]->holder == workshop) + { + if (!pending) + { + c->con.print("\nPending recovery:\n"); + pending = true; + } + + printJobDetails(c, pending_recover[i]->job_copy); + } + } + } + else if (cmd == "add" || cmd == "remove") + { + bool add = (cmd == "add"); + bool all = (parameters.size() >= 2 && parameters[1] == "all"); + if (parameters.size() >= 2 && !all) + return CR_WRONG_USAGE; + + if (workshop && all) + { + for (unsigned i = 0; i < workshop->jobs.size(); i++) + { + df::job *job = workshop->jobs[i]; + if (add) + { + if (!job->flags.bits.repeat) + continue; + remember_job(c, job); + } + else + { + if (ProtectedJob *pj = get_known(job->id)) + forget_job(c, pj); + } + } + } + else if (workshop) + { + if (!job) { + c->con.printerr("No job is selected in the current building.\n"); + return CR_FAILURE; + } + + if (add) + remember_job(c, job); + else if (ProtectedJob *pj = get_known(job->id)) + forget_job(c, pj); + } + else + { + if (!all) { + c->con.printerr("Please either select a job, or specify 'all'.\n"); + return CR_WRONG_USAGE; + } + + if (add) + { + for (std::map::iterator it = jobs.begin(); it != jobs.end(); it++) + if (it->second->flags.bits.repeat) + remember_job(c, it->second); + } + else + { + pending_recover.clear(); + + while (!known_jobs.empty()) + forget_job(c, known_jobs.begin()->second); + } + } + } + else + return CR_WRONG_USAGE; +} From 72016d9188835cd4df92c4ed230a416aff3b9c83 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Mr=C3=A1zek?= Date: Sun, 8 Jan 2012 02:22:13 +0100 Subject: [PATCH 24/82] Buildings aren't a module anymore, fix probe segfaults. --- library/Core.cpp | 1 - library/include/Core.h | 4 -- library/include/modules/Buildings.h | 88 +++++++++++++---------------- library/modules/Buildings.cpp | 70 ++--------------------- plugins/df2mc | 2 +- plugins/probe.cpp | 6 +- plugins/stonesense | 2 +- 7 files changed, 50 insertions(+), 123 deletions(-) diff --git a/library/Core.cpp b/library/Core.cpp index 4a3dacd25..4531370b8 100644 --- a/library/Core.cpp +++ b/library/Core.cpp @@ -1097,7 +1097,6 @@ MODULE_GETTER(Materials); MODULE_GETTER(Items); MODULE_GETTER(Translation); MODULE_GETTER(Vegetation); -MODULE_GETTER(Buildings); MODULE_GETTER(Constructions); MODULE_GETTER(Vermin); MODULE_GETTER(Notes); diff --git a/library/include/Core.h b/library/include/Core.h index a368e360d..c6cf73b0d 100644 --- a/library/include/Core.h +++ b/library/include/Core.h @@ -61,7 +61,6 @@ namespace DFHack class Items; class Translation; class Vegetation; - class Buildings; class Constructions; class Vermin; class Notes; @@ -119,8 +118,6 @@ namespace DFHack Translation * getTranslation(); /// get the vegetation module Vegetation * getVegetation(); - /// get the buildings module - Buildings * getBuildings(); /// get the constructions module Constructions * getConstructions(); /// get the vermin module @@ -182,7 +179,6 @@ namespace DFHack Items * pItems; Translation * pTranslation; Vegetation * pVegetation; - Buildings * pBuildings; Constructions * pConstructions; Vermin * pVermin; Notes * pNotes; diff --git a/library/include/modules/Buildings.h b/library/include/modules/Buildings.h index 8089fd4b1..7da2ad9dc 100644 --- a/library/include/modules/Buildings.h +++ b/library/include/modules/Buildings.h @@ -23,61 +23,49 @@ distribution. */ #pragma once -#ifndef CL_MOD_BUILDINGS -#define CL_MOD_BUILDINGS -/** - * \defgroup grp_buildings Building module parts - also includes zones and stockpiles - * @ingroup grp_modules - */ #include "Export.h" -#include "Module.h" -#ifdef __cplusplus namespace DFHack { -#endif - /** - * Structure for holding a read DF building object - * \ingroup grp_buildings - */ - struct t_building - { - uint32_t x1; - uint32_t y1; - uint32_t x2; - uint32_t y2; - uint32_t z; - t_matglossPair material; - uint32_t type; - int32_t custom_type; - void * origin; - }; +namespace Simple +{ +namespace Buildings +{ +/** + * Structure for holding a read DF building object + * \ingroup grp_buildings + */ +struct t_building +{ + uint32_t x1; + uint32_t y1; + uint32_t x2; + uint32_t y2; + uint32_t z; + t_matglossPair material; + uint32_t type; + int32_t custom_type; + void * origin; +}; -#ifdef __cplusplus - /** - * The Buildings module - allows reading DF buildings - * \ingroup grp_modules - * \ingroup grp_buildings - */ - class DFHACK_EXPORT Buildings : public Module - { - public: - Buildings(); - ~Buildings(); - bool Start(uint32_t & numBuildings); - // read one building at offset - bool Read (const uint32_t index, t_building & building); - bool Finish(); +/** + * The Buildings module - allows reading DF buildings + * \ingroup grp_modules + * \ingroup grp_buildings + */ +DFHACK_EXPORT uint32_t getNumBuildings (); - // read mapping from custom_type value to building RAW name - // custom_type of -1 implies ordinary building - bool ReadCustomWorkshopTypes(std::map & btypes); +/** + * read building by index + */ +DFHACK_EXPORT bool Read (const uint32_t index, t_building & building); - private: - struct Private; - Private *d; - }; -} -#endif // __cplusplus +/** + * read mapping from custom_type value to building RAW name + * custom_type of -1 implies ordinary building + */ +DFHACK_EXPORT bool ReadCustomWorkshopTypes(std::map & btypes); -#endif +} +} +} diff --git a/library/modules/Buildings.cpp b/library/modules/Buildings.cpp index 6f2b4a3f3..2213abd35 100644 --- a/library/modules/Buildings.cpp +++ b/library/modules/Buildings.cpp @@ -38,10 +38,10 @@ using namespace std; #include "ModuleFactory.h" #include "Core.h" using namespace DFHack; +using namespace DFHack::Simple; #include "DataDefs.h" #include "df/world.h" -#include "df/world_raws.h" #include "df/building_def.h" #include "df/building.h" #include "df/building_workshopst.h" @@ -50,70 +50,19 @@ using namespace df::enums; using df::global::world; using df::building_def; -//raw -struct t_building_df40d +uint32_t Buildings::getNumBuildings() { - uint32_t vtable; - uint32_t x1; - uint32_t y1; - uint32_t centerx; - uint32_t x2; - uint32_t y2; - uint32_t centery; - uint32_t z; - uint32_t height; - t_matglossPair material; - // not complete -}; - -struct Buildings::Private -{ - Process * owner; - bool Inited; - bool Started; - int32_t custom_workshop_id; -}; - -Module* DFHack::createBuildings() -{ - return new Buildings(); -} - -Buildings::Buildings() -{ - Core & c = Core::getInstance(); - d = new Private; - d->Started = false; - d->owner = c.p; - d->Inited = true; - c.vinfo->resolveClassnameToClassID("building_custom_workshop", d->custom_workshop_id); -} - -Buildings::~Buildings() -{ - if(d->Started) - Finish(); - delete d; -} - -bool Buildings::Start(uint32_t & numbuildings) -{ - if(!d->Inited) - return false; - numbuildings = world->buildings.all.size(); - d->Started = true; - return true; + return world->buildings.all.size(); } bool Buildings::Read (const uint32_t index, t_building & building) { - if(!d->Started) - return false; + Core & c = Core::getInstance(); df::building *bld_40d = world->buildings.all[index]; // transform int32_t type = -1; - d->owner->getDescriptor()->resolveObjectToClassID ( (char *)bld_40d, type); + c.vinfo->resolveObjectToClassID ( (char *)bld_40d, type); building.x1 = bld_40d->x1; building.x2 = bld_40d->x2; building.y1 = bld_40d->y1; @@ -127,19 +76,10 @@ bool Buildings::Read (const uint32_t index, t_building & building) return true; } -bool Buildings::Finish() -{ - d->Started = false; - return true; -} - bool Buildings::ReadCustomWorkshopTypes(map & btypes) { - if(!d->Inited) - return false; Core & c = Core::getInstance(); - Process * p = d->owner; vector & bld_def = world->raws.buildings.all; uint32_t size = bld_def.size(); btypes.clear(); diff --git a/plugins/df2mc b/plugins/df2mc index 3277c6b29..c114ec5f9 160000 --- a/plugins/df2mc +++ b/plugins/df2mc @@ -1 +1 @@ -Subproject commit 3277c6b29ddbb5d800ccb65eba27fed200236f3d +Subproject commit c114ec5f995aec69631187212254309464f82775 diff --git a/plugins/probe.cpp b/plugins/probe.cpp index a000d9e31..d70a6dbaf 100644 --- a/plugins/probe.cpp +++ b/plugins/probe.cpp @@ -135,7 +135,7 @@ DFhackCExport command_result df_probe (Core * c, vector & parameters) MapExtras::Block * b = mc.BlockAt(cursor/16); mapblock40d & block = b->raw; - if(b) + if(b && b->valid) { con.print("block addr: 0x%x\n\n", block.origin); /* @@ -285,6 +285,10 @@ DFhackCExport command_result df_probe (Core * c, vector & parameters) con << "mystery: " << block.mystery << endl; con << std::endl; } + else + { + con.printerr("No data.\n"); + } } } c->Resume(); diff --git a/plugins/stonesense b/plugins/stonesense index 545b2730e..92627e39c 160000 --- a/plugins/stonesense +++ b/plugins/stonesense @@ -1 +1 @@ -Subproject commit 545b2730ed137935643778f1b8ba115ae11c50a2 +Subproject commit 92627e39cb3502812cd5a131716d3d1da8ef625a From 2ccb15524bdc67683414e78592472f6d339c2f3e Mon Sep 17 00:00:00 2001 From: Quietust Date: Sat, 7 Jan 2012 23:04:31 -0600 Subject: [PATCH 25/82] Cleanup "cleaners" plugin, minimize reliance on modules --- plugins/cleaners.cpp | 268 ++++++++++++++++++++----------------------- 1 file changed, 122 insertions(+), 146 deletions(-) diff --git a/plugins/cleaners.cpp b/plugins/cleaners.cpp index 8992b2078..c25a1ed33 100644 --- a/plugins/cleaners.cpp +++ b/plugins/cleaners.cpp @@ -2,99 +2,69 @@ #include #include #include -#include -#include -#include -#include -using namespace DFHack; +#include "DataDefs.h" +#include "df/world.h" +#include "df/map_block.h" +#include "df/block_square_event.h" +#include "df/block_square_event_material_spatterst.h" +#include "df/item_actual.h" +#include "df/unit.h" +#include "df/matter_state.h" +#include "df/cursor.h" + +#include "modules/Materials.h" -#include -#include -#include using std::vector; using std::string; +using namespace DFHack; -DFhackCExport command_result clean (Core * c, vector & parameters); -DFhackCExport command_result spotclean (Core * c, vector & parameters); - -DFhackCExport const char * plugin_name ( void ) -{ - return "cleaners"; -} - -DFhackCExport command_result plugin_init ( Core * c, std::vector &commands) -{ - commands.clear(); - commands.push_back(PluginCommand("clean","Removes contaminants from map tiles, items and creatures.",clean)); - commands.push_back(PluginCommand("spotclean","Cleans map tile under cursor.",spotclean,cursor_hotkey)); - return CR_OK; -} - -DFhackCExport command_result plugin_shutdown ( Core * c ) -{ - return CR_OK; -} +using df::global::world; +using df::global::cursor; command_result cleanmap (Core * c, bool snow, bool mud) { - const uint32_t water_idx = 6; - const uint32_t mud_idx = 12; - vector splatter; - DFHack::Maps *Mapz = c->getMaps(); - - // init the map - if(!Mapz->Start()) - { - c->con << "Can't init map." << std::endl; - c->Resume(); - return CR_FAILURE; - } - - uint32_t x_max,y_max,z_max; - Mapz->getSize(x_max,y_max,z_max); - int num_blocks = 0; - int blocks_total = 0; - // walk the map - for(uint32_t x = 0; x< x_max;x++) + // Invoked from clean(), already suspended + int num_blocks = 0, blocks_total = world->map.map_blocks.size(); + for (int i = 0; i < blocks_total; i++) { - for(uint32_t y = 0; y< y_max;y++) + df::map_block *block = world->map.map_blocks[i]; + bool cleaned = false; + for(int x = 0; x < 16; x++) { - for(uint32_t z = 0; z< z_max;z++) + for(int y = 0; y < 16; y++) { - df_block * block = Mapz->getBlock(x,y,z); - if(block) - { - blocks_total ++; - bool cleaned = false; - Mapz->SortBlockEvents(x,y,z,0,0,&splatter); - for(int i = 0; i < 16; i++) - for(int j = 0; j < 16; j++) - { - block->occupancy[i][j].bits.arrow_color = 0; - block->occupancy[i][j].bits.broken_arrows_variant = 0; - } - for(uint32_t i = 0; i < splatter.size(); i++) - { - DFHack::t_spattervein * vein = splatter[i]; - // filter snow - if(!snow - && vein->mat1 == DFHack::Materials::WATER - && vein->matter_state == DFHack::state_powder) - continue; - // filter mud - if(!mud - && vein->mat1 == DFHack::Materials::MUD - && vein->matter_state == DFHack::state_solid) - continue; - Mapz->RemoveBlockEvent(x,y,z,(t_virtual *) vein); - cleaned = true; - } - num_blocks += cleaned; - } + block->occupancy[x][y].bits.arrow_color = 0; + block->occupancy[x][y].bits.arrow_variant = 0; } } + for (int j = 0; j < block->block_events.size(); j++) + { + df::block_square_event *evt = block->block_events[j]; + if (evt->getType() != df::block_square_event_type::material_spatter) + continue; + // type verified - recast to subclass + df::block_square_event_material_spatterst *spatter = (df::block_square_event_material_spatterst *)evt; + + // filter snow + if(!snow + && spatter->mat_type == DFHack::Materials::WATER + && spatter->mat_state == df::matter_state::Powder) + continue; + // filter mud + if(!mud + && spatter->mat_type == DFHack::Materials::MUD + && spatter->mat_state == df::matter_state::Solid) + continue; + + delete evt; + block->block_events.erase(block->block_events.begin() + j); + j--; + cleaned = true; + } + num_blocks += cleaned; } + if(num_blocks) c->con.print("Cleaned %d of %d map blocks.\n", num_blocks, blocks_total); return CR_OK; @@ -102,94 +72,82 @@ command_result cleanmap (Core * c, bool snow, bool mud) command_result cleanitems (Core * c) { - DFHack::Items * Items = c->getItems(); - - vector p_items; - if(!Items->readItemVector(p_items)) - { - c->con.printerr("Can't access the item vector.\n"); - c->Resume(); - return CR_FAILURE; - } - std::size_t numItems = p_items.size(); - + // Invoked from clean(), already suspended int cleaned_items = 0, cleaned_total = 0; - for (std::size_t i = 0; i < numItems; i++) + for (int i = 0; i < world->items.all.size(); i++) { - df_item * itm = p_items[i]; - if(!itm->contaminants) - continue; - if (itm->contaminants->size()) + // currently, all item classes extend item_actual, so this should be safe + df::item_actual *item = (df::item_actual *)world->items.all[i]; + if (item->contaminants && item->contaminants->size()) { - for(int j = 0; j < itm->contaminants->size(); j++) - delete itm->contaminants->at(j); + for (int j = 0; j < item->contaminants->size(); j++) + delete item->contaminants->at(j); cleaned_items++; - cleaned_total += itm->contaminants->size(); - itm->contaminants->clear(); + cleaned_total += item->contaminants->size(); + item->contaminants->clear(); } } - if(cleaned_total) + if (cleaned_total) c->con.print("Removed %d contaminants from %d items.\n", cleaned_total, cleaned_items); return CR_OK; } command_result cleanunits (Core * c) { - DFHack::Units * Creatures = c->getUnits(); - - uint32_t num_creatures; - if (!Creatures->Start(num_creatures)) - { - c->con.printerr("Can't read unit list!\n"); - c->Resume(); - return CR_FAILURE; - } + // Invoked from clean(), already suspended + int num_units = world->units.all.size(); int cleaned_units = 0, cleaned_total = 0; - for (std::size_t i = 0; i < num_creatures; i++) + for (int i = 0; i < num_units; i++) { - df_unit *unit = Creatures->creatures->at(i); - int num = unit->contaminants.size(); - if (num) + df::unit *unit = world->units.all[i]; + if (unit->body.spatters.size()) { - for(int j = 0; j < unit->contaminants.size(); j++) - delete unit->contaminants.at(j); + for (int j = 0; j < unit->body.spatters.size(); j++) + delete unit->body.spatters[j]; cleaned_units++; - cleaned_total += num; - unit->contaminants.clear(); + cleaned_total += unit->body.spatters.size(); + unit->body.spatters.clear(); } } - if(cleaned_total) + if (cleaned_total) c->con.print("Removed %d contaminants from %d creatures.\n", cleaned_total, cleaned_units); return CR_OK; } +// This is slightly different from what's in the Maps module - it takes tile coordinates rather than block coordinates +df::map_block *getBlock (int32_t x, int32_t y, int32_t z) +{ + if ((x < 0) || (y < 0) || (z < 0)) + return NULL; + if ((x >= world->map.x_count) || (y >= world->map.y_count) || (z >= world->map.z_count)) + return NULL; + // block_index isn't declared correctly - needs one more level of indirection + return ((df::map_block ****)world->map.block_index)[x >> 4][y >> 4][z]; +} + DFhackCExport command_result spotclean (Core * c, vector & parameters) { // HOTKEY COMMAND: CORE ALREADY SUSPENDED - vector splatter; - DFHack::Maps *Mapz = c->getMaps(); - DFHack::Gui *Gui = c->getGui(); - // init the map - if(!Mapz->Start()) + if (cursor->x == -30000) { - c->con.printerr("Can't init map.\n"); + c->con.printerr("The cursor is not active.\n"); return CR_FAILURE; } - int32_t cursorX, cursorY, cursorZ; - Gui->getCursorCoords(cursorX,cursorY,cursorZ); - if(cursorX == -30000) + df::map_block *block = getBlock(cursor->x, cursor->y, cursor->z); + if (block == NULL) { - c->con.printerr("The cursor is not active.\n"); + c->con.printerr("Invalid map block selected!\n"); return CR_FAILURE; } - int32_t blockX = cursorX / 16, blockY = cursorY / 16; - int32_t tileX = cursorX % 16, tileY = cursorY % 16; - df_block *b = Mapz->getBlock(blockX,blockY,cursorZ); - vector spatters; - Mapz->SortBlockEvents(blockX, blockY, cursorZ, 0,0, &spatters); - for(int i = 0; i < spatters.size(); i++) + + for (int i = 0; i < block->block_events.size(); i++) { - spatters[i]->intensity[tileX][tileY] = 0; + df::block_square_event *evt = block->block_events[i]; + if (evt->getType() != df::block_square_event_type::material_spatter) + continue; + // type verified - recast to subclass + df::block_square_event_material_spatterst *spatter = (df::block_square_event_material_spatterst *)evt; + spatter->amount[cursor->x % 16][cursor->y % 16] = 0; } return CR_OK; } @@ -230,17 +188,17 @@ DFhackCExport command_result clean (Core * c, vector & parameters) if(help) { c->con.print("Removes contaminants from map tiles, items and creatures.\n" - "Options:\n" - "map - clean the map tiles\n" - "items - clean all items\n" - "units - clean all creatures\n" - "all - clean everything.\n" - "More options for 'map':\n" - "snow - also remove snow\n" - "mud - also remove mud\n" - "Example: clean all mud snow\n" - "This removes all spatter, including mud and snow from map tiles." - ); + "Options:\n" + "map - clean the map tiles\n" + "items - clean all items\n" + "units - clean all creatures\n" + "all - clean everything.\n" + "More options for 'map':\n" + "snow - also remove snow\n" + "mud - also remove mud\n" + "Example: clean all mud snow\n" + "This removes all spatter, including mud and snow from map tiles." + ); return CR_OK; } c->Suspend(); @@ -253,3 +211,21 @@ DFhackCExport command_result clean (Core * c, vector & parameters) c->Resume(); return CR_OK; } + +DFhackCExport const char * plugin_name ( void ) +{ + return "cleaners"; +} + +DFhackCExport command_result plugin_init ( Core * c, std::vector &commands) +{ + commands.clear(); + commands.push_back(PluginCommand("clean","Removes contaminants from map tiles, items and creatures.",clean)); + commands.push_back(PluginCommand("spotclean","Cleans map tile under cursor.",spotclean,cursor_hotkey)); + return CR_OK; +} + +DFhackCExport command_result plugin_shutdown ( Core * c ) +{ + return CR_OK; +} \ No newline at end of file From 153efe9a69eb7e831b2d54ecae7c69e2739d3e00 Mon Sep 17 00:00:00 2001 From: Quietust Date: Sat, 7 Jan 2012 23:04:49 -0600 Subject: [PATCH 26/82] Cleanup "drybuckets" plugin, minimize reliance on modules --- plugins/drybuckets.cpp | 81 ++++++++++++++++-------------------------- 1 file changed, 31 insertions(+), 50 deletions(-) diff --git a/plugins/drybuckets.cpp b/plugins/drybuckets.cpp index 0ea079c0c..09456c01c 100644 --- a/plugins/drybuckets.cpp +++ b/plugins/drybuckets.cpp @@ -1,24 +1,43 @@ // Dry Buckets : Remove all "water" objects from buckets scattered around the fortress -#include -#include -#include -#include -#include -#include -using namespace std; #include "Core.h" #include #include #include -#include -#include -#include -#include +#include +#include "df/world.h" +#include "df/item.h" + +#include "modules/Materials.h" + +using std::string; +using std::vector; using namespace DFHack; -DFhackCExport command_result df_drybuckets (Core * c, vector & parameters); +using df::global::world; + +DFhackCExport command_result df_drybuckets (Core * c, vector & parameters) +{ + if (!parameters.empty()) + return CR_WRONG_USAGE; + + CoreSuspender suspend(c); + + int dried_total = 0; + for (int i = 0; i < world->items.all.size(); i++) + { + df::item *item = world->items.all[i]; + if ((item->getType() == df::item_type::LIQUID_MISC) && (item->getMaterial() == DFHack::Materials::WATER)) + { + item->flags.bits.garbage_colect = 1; + dried_total++; + } + } + if (dried_total) + c->con.print("Done. %d buckets of water marked for emptying.\n", dried_total); + return CR_OK; +} DFhackCExport const char * plugin_name ( void ) { @@ -35,42 +54,4 @@ DFhackCExport command_result plugin_init ( Core * c, std::vector DFhackCExport command_result plugin_shutdown ( Core * c ) { return CR_OK; -} - -DFhackCExport command_result df_drybuckets (Core * c, vector & parameters) -{ - if(parameters.size() > 0) - { - string & p = parameters[0]; - if(p == "?" || p == "help") - { - c->con.print("This utility removes all objects of type LIQUID_MISC:NONE and material WATER:NONE - that is, water stored in buckets.\n"); - return CR_OK; - } - } - c->Suspend(); - DFHack::Items * Items = c->getItems(); - - vector p_items; - if(!Items->readItemVector(p_items)) - { - c->con.printerr("Can't access the item vector.\n"); - c->Resume(); - return CR_FAILURE; - } - std::size_t numItems = p_items.size(); - - int dried_total = 0; - for (std::size_t i = 0; i < numItems; i++) - { - df_item *item = p_items[i]; - if ((item->getType() == Items::LIQUID_MISC) && (item->getMaterial() == Materials::WATER)) - { - item->flags.garbage_colect = 1; - dried_total++; - } - } - c->Resume(); - c->con.print("Done. %d buckets of water emptied.\n", dried_total); - return CR_OK; } \ No newline at end of file From c484d7ceaeb57cf950d1fa04edbfcb417c409a01 Mon Sep 17 00:00:00 2001 From: Quietust Date: Sat, 7 Jan 2012 23:28:37 -0600 Subject: [PATCH 27/82] Cleanup "fixwagons" plugin --- plugins/fixwagons.cpp | 26 +++++++++++--------------- 1 file changed, 11 insertions(+), 15 deletions(-) diff --git a/plugins/fixwagons.cpp b/plugins/fixwagons.cpp index 29253880e..3d7c5ff9b 100644 --- a/plugins/fixwagons.cpp +++ b/plugins/fixwagons.cpp @@ -6,21 +6,17 @@ #include #include -#include -#include -#include -#include -#include +#include "df/world.h" +#include "df/historical_entity.h" +#include "df/entity_raw.h" +#include "df/creature_raw.h" +#include "df/caste_raw.h" using std::string; using std::vector; using namespace DFHack; using df::global::world; -using df::historical_entity; -using df::entity_raw_flags; -using df::creature_raw; -using df::creature_raw_flags; command_result df_fixwagons (Core *c, vector ¶meters) { @@ -29,11 +25,11 @@ command_result df_fixwagons (Core *c, vector ¶meters) CoreSuspender suspend(c); int32_t wagon_creature = -1, wagon_puller_creature = -1; - creature_raw *wagon, *wagon_puller; + df::creature_raw *wagon, *wagon_puller; for (int i = 0; i < world->raws.creatures.all.size(); i++) { - creature_raw *cr = world->raws.creatures.all[i]; - if (cr->flags.is_set(creature_raw_flags::EQUIPMENT_WAGON) && (wagon_creature == -1)) + df::creature_raw *cr = world->raws.creatures.all[i]; + if (cr->flags.is_set(df::creature_raw_flags::EQUIPMENT_WAGON) && (wagon_creature == -1)) { wagon = cr; wagon_creature = i; @@ -58,8 +54,8 @@ command_result df_fixwagons (Core *c, vector ¶meters) for (int i = 0; i < world->entities.all.size(); i++) { bool updated = false; - historical_entity *ent = world->entities.all[i]; - if (!ent->entity_raw->flags.is_set(entity_raw_flags::COMMON_DOMESTIC_PULL)) + df::historical_entity *ent = world->entities.all[i]; + if (!ent->entity_raw->flags.is_set(df::entity_raw_flags::COMMON_DOMESTIC_PULL)) continue; if (ent->resources.animals.wagon_races.size() == 0) { @@ -107,4 +103,4 @@ DFhackCExport command_result plugin_init ( Core * c, std::vector DFhackCExport command_result plugin_shutdown ( Core * c ) { return CR_OK; -} +} \ No newline at end of file From fd2563d0d5d4abd65fb62dd9ff8a7f608771faeb Mon Sep 17 00:00:00 2001 From: Quietust Date: Sat, 7 Jan 2012 23:31:23 -0600 Subject: [PATCH 28/82] Cleanup "getplants" plugin, minimize reliance on modules --- plugins/getplants.cpp | 198 +++++++++++++++++------------------------- 1 file changed, 78 insertions(+), 120 deletions(-) diff --git a/plugins/getplants.cpp b/plugins/getplants.cpp index 14fb8b90c..e35c3d517 100644 --- a/plugins/getplants.cpp +++ b/plugins/getplants.cpp @@ -1,56 +1,34 @@ // Designate all matching plants for gathering/cutting -#include -#include -#include -#include -#include -#include -#include - #include "Core.h" #include #include #include -#include -#include -#include -#include -using namespace std; -using namespace DFHack; - -DFhackCExport command_result df_getplants (Core * c, vector & parameters); +#include +#include +#include "df/world.h" +#include "df/map_block.h" +#include "df/tile_dig_designation.h" +#include "df/plant_raw.h" -DFhackCExport const char * plugin_name ( void ) -{ - return "getplants"; -} +#include "modules/Vegetation.h" +#include -DFhackCExport command_result plugin_init ( Core * c, vector &commands) -{ - commands.clear(); - commands.push_back(PluginCommand("getplants", "Cut down all of the specified trees or gather all of the specified shrubs", df_getplants)); - return CR_OK; -} +using std::string; +using std::vector; +using std::set; +using namespace DFHack; -DFhackCExport command_result plugin_shutdown ( Core * c ) -{ - return CR_OK; -} +using df::global::world; DFhackCExport command_result df_getplants (Core * c, vector & parameters) { - uint32_t x_max,y_max,z_max; - designations40d designations; - tiletypes40d tiles; - t_blockflags blockflags; string plantMatStr = ""; set plantIDs; set plantNames; bool deselect = false, exclude = false, treesonly = false, shrubsonly = false; - bool dirty = false; int count = 0; for (size_t i = 0; i < parameters.size(); i++) { @@ -77,16 +55,16 @@ DFhackCExport command_result df_getplants (Core * c, vector & parameter exclude = true; else plantNames.insert(parameters[i]); } - c->Suspend(); - Materials *mats = c->getMaterials(); - for (vector::const_iterator it = mats->df_organic->begin(); it != mats->df_organic->end(); it++) + CoreSuspender suspend(c); + + for (int i = 0; i < world->raws.plants.all.size(); i++) { - df_plant_type &plant = **it; - if (plantNames.find(plant.ID) != plantNames.end()) + df::plant_raw *plant = world->raws.plants.all[i]; + if (plantNames.find(plant->id) != plantNames.end()) { - plantNames.erase(plant.ID); - plantIDs.insert(it - mats->df_organic->begin()); + plantNames.erase(plant->id); + plantIDs.insert(i); } } if (plantNames.size() > 0) @@ -95,103 +73,83 @@ DFhackCExport command_result df_getplants (Core * c, vector & parameter for (set::const_iterator it = plantNames.begin(); it != plantNames.end(); it++) c->con.printerr(" %s", it->c_str()); c->con.printerr("\n"); - c->Resume(); return CR_FAILURE; } if (plantIDs.size() == 0) { c->con.print("Valid plant IDs:\n"); - for (vector::const_iterator it = mats->df_organic->begin(); it != mats->df_organic->end(); it++) + for (int i = 0; i < world->raws.plants.all.size(); i++) { - df_plant_type &plant = **it; - if (plant.flags.is_set(PLANT_GRASS)) + df::plant_raw *plant = world->raws.plants.all[i]; + if (plant->flags.is_set(df::plant_raw_flags::GRASS)) continue; - c->con.print("* (%s) %s - %s\n", plant.flags.is_set(PLANT_TREE) ? "tree" : "shrub", plant.ID.c_str(), plant.name.c_str()); + c->con.print("* (%s) %s - %s\n", plant->flags.is_set(df::plant_raw_flags::TREE) ? "tree" : "shrub", plant->id.c_str(), plant->name.c_str()); } - c->Resume(); return CR_OK; } - Maps *maps = c->getMaps(); - - // init the map - if (!maps->Start()) - { - c->con.printerr("Can't init map.\n"); - c->Resume(); - return CR_FAILURE; - } - - maps->getSize(x_max,y_max,z_max); - // walk the map - for (uint32_t x = 0; x < x_max; x++) + int count = 0; + for (int i = 0; i < world->map.map_blocks.size(); i++) { - for (uint32_t y = 0; y < y_max; y++) + df::map_block *cur = world->map.map_blocks[i]; + bool dirty = false; + for (int j = 0; j < cur->plants.size(); j++) { - for (uint32_t z = 0; z < z_max; z++) + const df_plant *plant = (df_plant *)cur->plants[i]; + int x = plant->x % 16; + int y = plant->y % 16; + if (plantIDs.find(plant->material) != plantIDs.end()) { - if (maps->getBlock(x,y,z)) - { - dirty = false; - maps->ReadDesignations(x,y,z, &designations); - maps->ReadTileTypes(x,y,z, &tiles); - maps->ReadBlockFlags(x,y,z, blockflags); - - vector *plants; - if (maps->ReadVegetation(x, y, z, plants)) - { - for (vector::const_iterator it = plants->begin(); it != plants->end(); it++) - { - const df_plant &plant = **it; - uint32_t tx = plant.x % 16; - uint32_t ty = plant.y % 16; - if (plantIDs.find(plant.material) != plantIDs.end()) - { - if (exclude) - continue; - } - else - { - if (!exclude) - continue; - } - - TileShape shape = tileShape(tiles[tx][ty]); - if (plant.is_shrub && (treesonly || shape != SHRUB_OK)) - continue; - if (!plant.is_shrub && (shrubsonly || (shape != TREE_OK && shape != TREE_DEAD))) - continue; - if (designations[tx][ty].bits.hidden) - continue; - if (deselect && designations[tx][ty].bits.dig != designation_no) - { - designations[tx][ty].bits.dig = designation_no; - dirty = true; - ++count; - } - if (!deselect && designations[tx][ty].bits.dig != designation_default) - { - designations[tx][ty].bits.dig = designation_default; - dirty = true; - ++count; - } - } - } - // If anything was changed, write it all. - if (dirty) - { - blockflags.bits.designated = 1; - maps->WriteDesignations(x,y,z, &designations); - maps->WriteBlockFlags(x,y,z, blockflags); - dirty = false; - } - } + if (exclude) + continue; + } + else + { + if (!exclude) + continue; + } + TileShape shape = tileShape(cur->tiletype[x][y]); + if (plant->is_shrub && (treesonly || shape != SHRUB_OK)) + continue; + if (!plant->is_shrub && (shrubsonly || (shape != TREE_OK && shape != TREE_DEAD))) + continue; + if (cur->designation[x][y].bits.hidden) + continue; + if (deselect && cur->designation[x][y].bits.dig != df::tile_dig_designation::No) + { + cur->designation[x][y].bits.dig = df::tile_dig_designation::No; + dirty = true; + ++count; + } + if (!deselect && cur->designation[x][y].bits.dig != df::tile_dig_designation::Default) + { + cur->designation[x][y].bits.dig = df::tile_dig_designation::Default; + dirty = true; + ++count; } } + if (dirty) + cur->flags.set(df::block_flags::Designated); } - c->Resume(); if (count) c->con.print("Updated %d plant designations.\n", count); return CR_OK; } + +DFhackCExport const char * plugin_name ( void ) +{ + return "getplants"; +} + +DFhackCExport command_result plugin_init ( Core * c, vector &commands) +{ + commands.clear(); + commands.push_back(PluginCommand("getplants", "Cut down all of the specified trees or gather all of the specified shrubs", df_getplants)); + return CR_OK; +} + +DFhackCExport command_result plugin_shutdown ( Core * c ) +{ + return CR_OK; +} \ No newline at end of file From 8a463865029be165139a8d1fe73bc0b2ec27a109 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Mr=C3=A1zek?= Date: Sun, 8 Jan 2012 06:59:52 +0100 Subject: [PATCH 29/82] Dissolve vermin module. --- library/Core.cpp | 1 - library/include/Core.h | 4 - library/include/ModuleFactory.h | 1 - library/include/modules/Vermin.h | 80 ++++------------ library/modules/Vermin.cpp | 154 ++++++------------------------- plugins/colonies.cpp | 62 +++++-------- 6 files changed, 71 insertions(+), 231 deletions(-) diff --git a/library/Core.cpp b/library/Core.cpp index 4531370b8..9404fdb5b 100644 --- a/library/Core.cpp +++ b/library/Core.cpp @@ -1098,6 +1098,5 @@ MODULE_GETTER(Items); MODULE_GETTER(Translation); MODULE_GETTER(Vegetation); MODULE_GETTER(Constructions); -MODULE_GETTER(Vermin); MODULE_GETTER(Notes); MODULE_GETTER(Graphic); diff --git a/library/include/Core.h b/library/include/Core.h index c6cf73b0d..3366b990b 100644 --- a/library/include/Core.h +++ b/library/include/Core.h @@ -62,7 +62,6 @@ namespace DFHack class Translation; class Vegetation; class Constructions; - class Vermin; class Notes; class VersionInfo; class VersionInfoFactory; @@ -120,8 +119,6 @@ namespace DFHack Vegetation * getVegetation(); /// get the constructions module Constructions * getConstructions(); - /// get the vermin module - Vermin * getVermin(); /// get the notes module Notes * getNotes(); /// get the graphic module @@ -180,7 +177,6 @@ namespace DFHack Translation * pTranslation; Vegetation * pVegetation; Constructions * pConstructions; - Vermin * pVermin; Notes * pNotes; Graphic * pGraphic; } s_mods; diff --git a/library/include/ModuleFactory.h b/library/include/ModuleFactory.h index 3677d3554..0ee5b178f 100644 --- a/library/include/ModuleFactory.h +++ b/library/include/ModuleFactory.h @@ -41,7 +41,6 @@ namespace DFHack Module* createBuildings(); Module* createConstructions(); Module* createMaps(); - Module* createVermin(); Module* createNotes(); Module* createGraphic(); } diff --git a/library/include/modules/Vermin.h b/library/include/modules/Vermin.h index 324714f5d..bcec96b51 100644 --- a/library/include/modules/Vermin.h +++ b/library/include/modules/Vermin.h @@ -1,22 +1,15 @@ #pragma once -#ifndef CL_MOD_VERMIN -#define CL_MOD_VERMIN /** * \defgroup grp_vermin Wild vermin (ants, bees, etc) - * @ingroup grp_vermin */ #include "Export.h" -#include "Module.h" - -#ifdef __cplusplus -namespace DFHack +namespace DFHack { namespace Simple { namespace Vermin { -#endif /** * Structure for holding a read DF vermin spawn point object * \ingroup grp_vermin */ - struct t_spawnPoint + struct t_vermin { void * origin; int16_t race; @@ -29,58 +22,21 @@ namespace DFHack uint32_t countdown; }; -#ifdef __cplusplus - class DFContextShared; - class SpawnPoints; - + static const uint16_t TYPE_WILD_COLONY = 0xFFFF; /** - * The Vermin module - allows reading DF vermin - * \ingroup grp_modules - * \ingroup grp_vermin + * Get number of vermin objects */ - class DFHACK_EXPORT Vermin : public Module - { - public: - Vermin(); - ~Vermin(); - - bool Finish(); - - // NOTE: caller must call delete on result when done. - SpawnPoints* getSpawnPoints(); - - private: - struct Private; - Private *d; - - friend class SpawnPoints; - }; - - class DFHACK_EXPORT SpawnPoints - { - public: - static const uint16_t TYPE_WILD_COLONY = 0xFFFF; - - protected: - SpawnPoints(Vermin * v); - - public: - ~SpawnPoints(); - - size_t size(); - bool Read (const uint32_t index, t_spawnPoint & point); - bool Write (const uint32_t index, t_spawnPoint & point); - bool isValid(); - - static bool isWildColony(t_spawnPoint & point); - - private: - Vermin* v; - std::vector * p_sp; - - friend class Vermin; - }; -} -#endif // __cplusplus - -#endif + DFHACK_EXPORT uint32_t getNumVermin(); + /** + * Read from vermin object + */ + DFHACK_EXPORT bool Read (const uint32_t index, t_vermin & point); + /** + * Write into vermin object + */ + DFHACK_EXPORT bool Write (const uint32_t index, t_vermin & point); + /** + * Is vermin object a colony? + */ + DFHACK_EXPORT bool isWildColony(t_vermin & point); +} } } // end DFHack::Simple::Vermin diff --git a/library/modules/Vermin.cpp b/library/modules/Vermin.cpp index 215815eb0..365bfe542 100644 --- a/library/modules/Vermin.cpp +++ b/library/modules/Vermin.cpp @@ -37,150 +37,54 @@ using namespace std; #include "ModuleFactory.h" #include "Core.h" using namespace DFHack; +using namespace DFHack::Simple; -struct Vermin::Private -{ - void * spawn_points_vector; - uint32_t race_offset; - uint32_t type_offset; - uint32_t position_offset; - uint32_t in_use_offset; - uint32_t unknown_offset; - uint32_t countdown_offset; - Process * owner; - bool Inited; - bool Started; -}; - -Module* DFHack::createVermin() -{ - return new Vermin(); -} - -#include - -Vermin::Vermin() -{ - Core & c = Core::getInstance(); - - d = new Private; - d->owner = c.p; - d->Inited = d->Started = false; - VersionInfo * mem = c.vinfo; - OffsetGroup * OG_vermin = mem->getGroup("Vermin"); - OffsetGroup * OG_spawn = OG_vermin->getGroup("Spawn Points"); - d->Inited = true; - try - { - d->spawn_points_vector = OG_spawn->getAddress("vector"); - - d->race_offset = OG_spawn->getOffset("race"); - d->type_offset = OG_spawn->getOffset("type"); - d->position_offset = OG_spawn->getOffset("position"); - d->in_use_offset = OG_spawn->getOffset("in_use"); - d->unknown_offset = OG_spawn->getOffset("unknown"); - d->countdown_offset = OG_spawn->getOffset("countdown"); - } - catch(DFHack::Error::AllMemdef &e) - { - cerr << "Vermin not available... " << e.what() << endl; - d->Inited = false; - } -} - -bool Vermin::Finish() -{ - return true; -} - -Vermin::~Vermin() -{ - delete d; -} +#include "DataDefs.h" +#include "df/world.h" +using namespace df::enums; +using df::global::world; -// NOTE: caller must call delete on result when done. -SpawnPoints* Vermin::getSpawnPoints() +uint32_t Vermin::getNumVermin() { - if (!d->Inited) - { - cerr << "Couldn't get spawn points: Vermin module not inited" << endl; - return NULL; - } - return new SpawnPoints(this); + return world->vermin.size(); } -SpawnPoints::SpawnPoints(Vermin* v_) +bool Vermin::Read (const uint32_t index, t_vermin & sp) { - v = v_; - p_sp = NULL; - - if (!v->d->Inited) - { - cerr << "Couldn't get spawn points: Vermin module not inited" << endl; - return; - } - p_sp = (vector *) (v->d->spawn_points_vector); -} - -SpawnPoints::~SpawnPoints() -{ -} - -size_t SpawnPoints::size() -{ - if (!isValid()) - return 0; - - return p_sp->size(); -} - -bool SpawnPoints::Read (const uint32_t index, t_spawnPoint & sp) -{ - if(!isValid()) + if(index >= world->vermin.size()) return false; - // read pointer from vector at position - char * temp = p_sp->at (index); - - sp.origin = temp; - sp.race = v->d->owner->readWord(temp + v->d->race_offset); - sp.type = v->d->owner->readWord(temp + v->d->type_offset); - sp.in_use = v->d->owner->readByte(temp + v->d->in_use_offset); - sp.unknown = v->d->owner->readByte(temp + v->d->unknown_offset); - sp.countdown = v->d->owner->readDWord(temp + v->d->countdown_offset); - - // Three consecutive 16 bit numbers for x/y/z - v->d->owner->read(temp + v->d->position_offset, 6, (uint8_t*) &sp.x); + df::world::T_vermin * verm = world->vermin[index]; + sp.origin = verm; + sp.race = verm->race; + sp.type = verm->type; + sp.in_use = verm->in_use; + sp.countdown = verm->countdown; + sp.x = verm->x; + sp.y = verm->y; + sp.z = verm->z; return true; } -bool SpawnPoints::Write (const uint32_t index, t_spawnPoint & sp) +bool Vermin::Write (const uint32_t index, t_vermin & sp) { - if(!isValid()) + if(index >= world->vermin.size()) return false; - // read pointer from vector at position - char * temp = p_sp->at (index); - - v->d->owner->writeWord(temp + v->d->race_offset, sp.race); - v->d->owner->writeWord(temp + v->d->type_offset, sp.type); - v->d->owner->writeByte(temp + v->d->in_use_offset, sp.in_use); - v->d->owner->writeByte(temp + v->d->unknown_offset, sp.unknown); - v->d->owner->writeDWord(temp + v->d->countdown_offset, sp.countdown); - - // Three consecutive 16 bit numbers for x/y/z - v->d->owner->write(temp + v->d->position_offset, 6, (uint8_t*) &sp.x); + df::world::T_vermin * verm = world->vermin[index]; + verm->race = sp.race; + verm->type = sp.type; + verm->in_use = sp.in_use; + verm->countdown = sp.countdown; + verm->x = sp.x; + verm->y = sp.y; + verm->z = sp.z; return true; } -bool SpawnPoints::isWildColony(t_spawnPoint & point) +bool Vermin::isWildColony(t_vermin & point) { return (point.type == TYPE_WILD_COLONY); } - -bool SpawnPoints::isValid() -{ - return (v != NULL && v->d->Inited && p_sp != NULL); -} diff --git a/plugins/colonies.cpp b/plugins/colonies.cpp index 6b2d8a1d2..73106b966 100644 --- a/plugins/colonies.cpp +++ b/plugins/colonies.cpp @@ -9,6 +9,7 @@ using std::vector; using std::string; using namespace DFHack; +using namespace DFHack::Simple; #include DFhackCExport command_result colonies (Core * c, vector & parameters); @@ -32,10 +33,9 @@ DFhackCExport command_result plugin_shutdown ( Core * c ) return CR_OK; } -void destroyColonies(DFHack::SpawnPoints *points); -void convertColonies(DFHack::SpawnPoints *points, DFHack::Materials *Materials); -void showColonies(Core *c, DFHack::SpawnPoints *points, - DFHack::Materials *Materials); +void destroyColonies(); +void convertColonies(DFHack::Materials *Materials); +void showColonies(Core *c, DFHack::Materials *Materials); DFhackCExport command_result colonies (Core * c, vector & parameters) { @@ -71,54 +71,41 @@ DFhackCExport command_result colonies (Core * c, vector & parameters) } c->Suspend(); - Vermin * vermin = c->getVermin(); Materials * materials = c->getMaterials(); - SpawnPoints *points = vermin->getSpawnPoints(); - - if(!points || !points->isValid()) - { - c->con.printerr("vermin not supported for this DF version\n"); - c->Resume(); - return CR_FAILURE; - } - materials->ReadCreatureTypesEx(); if (destroy) - destroyColonies(points); + destroyColonies(); else if (convert) - convertColonies(points, materials); + convertColonies(materials); else - showColonies(c, points, materials); - - delete points; + showColonies(c, materials); - vermin->Finish(); materials->Finish(); c->Resume(); return CR_OK; } -void destroyColonies(DFHack::SpawnPoints *points) +void destroyColonies() { - uint32_t numSpawnPoints = points->size(); + uint32_t numSpawnPoints = Vermin::getNumVermin(); for (uint32_t i = 0; i < numSpawnPoints; i++) { - DFHack::t_spawnPoint sp; - points->Read(i, sp); + Vermin::t_vermin sp; + Vermin::Read(i, sp); - if (sp.in_use && DFHack::SpawnPoints::isWildColony(sp)) + if (sp.in_use && Vermin::isWildColony(sp)) { sp.in_use = false; - points->Write(i, sp); + Vermin::Write(i, sp); } } } // Convert all colonies to honey bees. -void convertColonies(DFHack::SpawnPoints *points, DFHack::Materials *Materials) +void convertColonies(DFHack::Materials *Materials) { int bee_idx = -1; for (size_t i = 0; i < Materials->raceEx.size(); i++) @@ -134,32 +121,31 @@ void convertColonies(DFHack::SpawnPoints *points, DFHack::Materials *Materials) return; } - uint32_t numSpawnPoints = points->size(); + uint32_t numSpawnPoints = Vermin::getNumVermin(); for (uint32_t i = 0; i < numSpawnPoints; i++) { - DFHack::t_spawnPoint sp; - points->Read(i, sp); + Vermin::t_vermin sp; + Vermin::Read(i, sp); - if (sp.in_use && DFHack::SpawnPoints::isWildColony(sp)) + if (sp.in_use && Vermin::isWildColony(sp)) { sp.race = bee_idx; - points->Write(i, sp); + Vermin::Write(i, sp); } } } -void showColonies(Core *c, DFHack::SpawnPoints *points, - DFHack::Materials *Materials) +void showColonies(Core *c, DFHack::Materials *Materials) { - uint32_t numSpawnPoints = points->size(); + uint32_t numSpawnPoints = Vermin::getNumVermin(); int numColonies = 0; for (uint32_t i = 0; i < numSpawnPoints; i++) { - DFHack::t_spawnPoint sp; + Vermin::t_vermin sp; - points->Read(i, sp); + Vermin::Read(i, sp); - if (sp.in_use && DFHack::SpawnPoints::isWildColony(sp)) + if (sp.in_use && Vermin::isWildColony(sp)) { numColonies++; string race="(no race)"; From da2b00d4803993234eb88f3ded810434ae02eb86 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Mr=C3=A1zek?= Date: Sun, 8 Jan 2012 07:02:05 +0100 Subject: [PATCH 30/82] Sync structures --- library/xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/xml b/library/xml index d03375ddb..d3b1dc7a0 160000 --- a/library/xml +++ b/library/xml @@ -1 +1 @@ -Subproject commit d03375ddbd695fda2deb42dd13aa352efccebc60 +Subproject commit d3b1dc7a033d35ff497a06f45ff48f4746c82fc5 From 22071e2d5158da723c8ed771e9a1e336acdcbda7 Mon Sep 17 00:00:00 2001 From: Alexander Gavrilov Date: Sun, 8 Jan 2012 16:10:38 +0400 Subject: [PATCH 31/82] Update data defs. --- library/xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/xml b/library/xml index 731fd6ca6..aeb25a2e8 160000 --- a/library/xml +++ b/library/xml @@ -1 +1 @@ -Subproject commit 731fd6ca6fb5bd8be8172b35c417aab092ca305d +Subproject commit aeb25a2e804aa8459f80b5d84d5cb811414d6305 From 175b3ed0600f1016a56b09c1ddcd5093474eb6c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Mr=C3=A1zek?= Date: Sun, 8 Jan 2012 16:18:31 +0100 Subject: [PATCH 32/82] Fix getplants - duplicate variable. --- library/xml | 2 +- plugins/getplants.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/library/xml b/library/xml index b93b61a98..c2caba7eb 160000 --- a/library/xml +++ b/library/xml @@ -1 +1 @@ -Subproject commit b93b61a988020a4aaa0103cefcee0217c37ce7b0 +Subproject commit c2caba7eb15896d56163620e9ace1fb67ae953cb diff --git a/plugins/getplants.cpp b/plugins/getplants.cpp index e35c3d517..5643676aa 100644 --- a/plugins/getplants.cpp +++ b/plugins/getplants.cpp @@ -89,7 +89,7 @@ DFhackCExport command_result df_getplants (Core * c, vector & parameter return CR_OK; } - int count = 0; + count = 0; for (int i = 0; i < world->map.map_blocks.size(); i++) { df::map_block *cur = world->map.map_blocks[i]; From ea790f1346a3dff8df6331dc84a16a7915bca4fd Mon Sep 17 00:00:00 2001 From: Alexander Gavrilov Date: Sun, 8 Jan 2012 20:02:12 +0400 Subject: [PATCH 33/82] Move a few functions into the core, and add some more. --- library/DataDefs.cpp | 10 ++++++ library/MiscUtils.cpp | 40 +++++++++++++++++++++ library/include/DataDefs.h | 6 ++++ library/include/MiscUtils.h | 44 +++++++++++++++++++++-- library/include/modules/Job.h | 5 +++ library/include/modules/Materials.h | 5 ++- library/modules/Job.cpp | 45 +++++++++++++++++++++++- library/modules/Materials.cpp | 54 ++++++++++++++++++++++++----- library/modules/World.cpp | 2 +- plugins/jobutils.cpp | 26 +++----------- plugins/workflow.cpp | 16 +-------- 11 files changed, 204 insertions(+), 49 deletions(-) diff --git a/library/DataDefs.cpp b/library/DataDefs.cpp index 6c40ec819..cd8a8ed7c 100644 --- a/library/DataDefs.cpp +++ b/library/DataDefs.cpp @@ -197,6 +197,16 @@ std::string DFHack::bitfieldToString(const void *p, int size, const bitfield_ite return res; } +int DFHack::findBitfieldField(const std::string &name, int size, const bitfield_item_info *items) +{ + for (int i = 0; i < size*8; i++) { + if (items[i].name && items[i].name == name) + return i; + } + + return -1; +} + #define SIMPLE_GLOBAL(name,tname) \ tname *df::global::name = NULL; #define GLOBAL(name,tname) SIMPLE_GLOBAL(name,df::tname) diff --git a/library/MiscUtils.cpp b/library/MiscUtils.cpp index 72e3eae28..aa141313b 100644 --- a/library/MiscUtils.cpp +++ b/library/MiscUtils.cpp @@ -34,6 +34,7 @@ distribution. #include #endif +#include #include std::string stl_sprintf(const char *fmt, ...) { @@ -59,6 +60,45 @@ std::string stl_vsprintf(const char *fmt, va_list args) { } } +bool split_string(std::vector *out, + const std::string &str, const std::string &separator, bool squash_empty) +{ + out->clear(); + + size_t start = 0, pos; + + if (!separator.empty()) + { + while ((pos = str.find(separator,start)) != std::string::npos) + { + if (pos > start || !squash_empty) + out->push_back(str.substr(start, pos-start)); + start = pos + separator.size(); + } + } + + if (start < str.size() || !squash_empty) + out->push_back(str.substr(start)); + + return out->size() > 1; +} + +std::string toUpper(const std::string &str) +{ + std::string rv(str.size(),' '); + for (unsigned i = 0; i < str.size(); ++i) + rv[i] = toupper(str[i]); + return rv; +} + +std::string toLower(const std::string &str) +{ + std::string rv(str.size(),' '); + for (unsigned i = 0; i < str.size(); ++i) + rv[i] = tolower(str[i]); + return rv; +} + #ifdef LINUX_BUILD // Linux uint64_t GetTimeMs64() { diff --git a/library/include/DataDefs.h b/library/include/DataDefs.h index a7fb956ed..b4bc516d0 100644 --- a/library/include/DataDefs.h +++ b/library/include/DataDefs.h @@ -143,6 +143,12 @@ namespace DFHack }; DFHACK_EXPORT std::string bitfieldToString(const void *p, int size, const bitfield_item_info *items); + DFHACK_EXPORT int findBitfieldField(const std::string &name, int size, const bitfield_item_info *items); + + template + inline int findBitfieldField(const T &val, const std::string &name) { + return findBitfieldField(name, sizeof(val.whole), val.get_items()); + } template inline std::string bitfieldToString(const T &val) { diff --git a/library/include/MiscUtils.h b/library/include/MiscUtils.h index 5897994e3..c744f587c 100644 --- a/library/include/MiscUtils.h +++ b/library/include/MiscUtils.h @@ -163,6 +163,28 @@ inline bool vector_contains(const std::vector &vec, FT CT::*field, FT key) return binsearch_index(vec, field, key) >= 0; } +template +inline T vector_get(const std::vector &vec, unsigned idx, const T &defval = T()) +{ + if (idx < vec.size()) + return vec[idx]; + else + return defval; +} + +template +inline void vector_insert_at(std::vector &vec, unsigned idx, const T &val) +{ + vec.insert(vec.begin()+idx, val); +} + +template +inline void vector_erase_at(std::vector &vec, unsigned idx) +{ + if (idx < vec.size()) + vec.erase(vec.begin()+idx); +} + template unsigned insert_into_vector(std::vector &vec, FT key, bool *inserted = NULL) { @@ -170,7 +192,7 @@ unsigned insert_into_vector(std::vector &vec, FT key, bool *inserted = NULL) bool to_ins = (pos >= vec.size() || vec[pos] != key); if (inserted) *inserted = to_ins; if (to_ins) - vec.insert(vec.begin()+pos,key); + vector_insert_at(vec, pos, key); return pos; } @@ -181,7 +203,7 @@ unsigned insert_into_vector(std::vector &vec, FT CT::*field, CT *obj, bool bool to_ins = (pos >= vec.size() || vec[pos] != obj); if (inserted) *inserted = to_ins; if (to_ins) - vec.insert(vec.begin()+pos,obj); + vector_insert_at(vec, pos, obj); return pos; } @@ -213,10 +235,28 @@ Link *linked_list_append(Link *head, Link *tail) return tail; } +template +Link *linked_list_insert_after(Link *pos, Link *link) +{ + link->next = pos->next; + if (pos->next) + pos->next->prev = link; + link->prev = pos; + pos->next = link; + return link; +} + /* * MISC */ +DFHACK_EXPORT bool split_string(std::vector *out, + const std::string &str, const std::string &separator, + bool squash_empty = false); + +DFHACK_EXPORT std::string toUpper(const std::string &str); +DFHACK_EXPORT std::string toLower(const std::string &str); + /** * Returns the amount of milliseconds elapsed since the UNIX epoch. * Works on both windows and linux. diff --git a/library/include/modules/Job.h b/library/include/modules/Job.h index 35f4fdc39..5534a9d4f 100644 --- a/library/include/modules/Job.h +++ b/library/include/modules/Job.h @@ -35,6 +35,7 @@ namespace df struct job; struct job_item; struct job_item_filter; + struct building; } namespace DFHack @@ -49,6 +50,10 @@ namespace DFHack DFHACK_EXPORT bool operator== (const df::job &a, const df::job &b); DFHACK_EXPORT void printJobDetails(Core *c, df::job *job); + + DFHACK_EXPORT df::building *getJobHolder(df::job *job); + + DFHACK_EXPORT bool linkJobIntoWorld(df::job *job, bool new_id = true); } #endif diff --git a/library/include/modules/Materials.h b/library/include/modules/Materials.h index 25becc400..e1455c158 100644 --- a/library/include/modules/Materials.h +++ b/library/include/modules/Materials.h @@ -101,7 +101,8 @@ namespace DFHack return ptr ? decode(ptr->mat_type, ptr->mat_index) : decode(-1); } - bool find(const std::string &token, const std::string &subtoken = std::string()); + bool find(const std::string &token); + bool findBuiltin(const std::string &token); bool findInorganic(const std::string &token); bool findPlant(const std::string &token, const std::string &subtoken); @@ -121,6 +122,8 @@ namespace DFHack bool matches(const df::job_item &item); }; + DFHACK_EXPORT bool parseJobMaterialCategory(df::job_material_category *cat, const std::string &token); + inline bool operator== (const MaterialInfo &a, const MaterialInfo &b) { return a.type == b.type && a.index == b.index; } diff --git a/library/modules/Job.cpp b/library/modules/Job.cpp index a91146c98..3e3016e1f 100644 --- a/library/modules/Job.cpp +++ b/library/modules/Job.cpp @@ -33,6 +33,7 @@ using namespace std; #include "Core.h" #include "PluginManager.h" +#include "MiscUtils.h" #include "modules/Job.h" #include "modules/Materials.h" @@ -45,6 +46,7 @@ using namespace std; #include #include #include +#include using namespace DFHack; using namespace df::enums; @@ -69,7 +71,7 @@ df::job *DFHack::cloneJobStruct(df::job *job) df::general_ref *ref = pnew->references[i]; if (virtual_cast(ref)) - pnew->references.erase(pnew->references.begin()+i); + vector_erase_at(pnew->references, i); else pnew->references[i] = ref->clone(); } @@ -199,3 +201,44 @@ void DFHack::printJobDetails(Core *c, df::job *job) for (unsigned i = 0; i < job->job_items.size(); i++) print_job_item_details(c, job, i, job->job_items[i]); } + +df::building *DFHack::getJobHolder(df::job *job) +{ + for (unsigned i = 0; i < job->references.size(); i++) + { + VIRTUAL_CAST_VAR(ref, df::general_ref_building_holderst, job->references[i]); + if (ref) + return ref->getBuilding(); + } + + return NULL; +} + +bool DFHack::linkJobIntoWorld(df::job *job, bool new_id) +{ + using df::global::world; + using df::global::job_next_id; + + assert(!job->list_link); + + if (new_id) { + job->id = (*job_next_id)++; + + job->list_link = new df::job_list_link(); + job->list_link->item = job; + linked_list_append(&world->job_list, job->list_link); + return true; + } else { + df::job_list_link *ins_pos = &world->job_list; + while (ins_pos->next && ins_pos->next->item->id < job->id) + ins_pos = ins_pos->next; + + if (ins_pos->next && ins_pos->next->item->id == job->id) + return false; + + job->list_link = new df::job_list_link(); + job->list_link->item = job; + linked_list_insert_after(ins_pos, job->list_link); + return true; + } +} diff --git a/library/modules/Materials.cpp b/library/modules/Materials.cpp index 92149342f..32145cc90 100644 --- a/library/modules/Materials.cpp +++ b/library/modules/Materials.cpp @@ -143,27 +143,40 @@ bool MaterialInfo::decode(int16_t type, int32_t index) return (material != NULL); } -bool MaterialInfo::find(const std::string &token, const std::string &subtoken) +bool MaterialInfo::find(const std::string &token) { - if (findBuiltin(token)) - return true; - if (subtoken.empty()) + std::vector items; + split_string(&items, token, ":"); + + if (items[0] == "INORGANIC") + return findInorganic(vector_get(items,1)); + if (items[0] == "CREATURE_MAT" || items[0] == "CREATURE") + return findCreature(vector_get(items,1), vector_get(items,2)); + if (items[0] == "PLANT_MAT" || items[0] == "PLANT") + return findPlant(vector_get(items,1), vector_get(items,2)); + + if (items.size() == 1) { - if (findInorganic(token)) + if (findBuiltin(items[0])) + return true; + if (findInorganic(items[0])) return true; } - else + else if (items.size() == 2) { - if (findPlant(token, subtoken)) + if (findPlant(items[0], items[1])) return true; - if (findCreature(token, subtoken)) + if (findCreature(items[0], items[1])) return true; } + return false; } bool MaterialInfo::findBuiltin(const std::string &token) { + if (token.empty()) + return decode(-1); df::world_raws &raws = df::global::world->raws; for (int i = 1; i < NUM_BUILTIN; i++) if (raws.mat_table.builtin[i]->id == token) @@ -173,6 +186,8 @@ bool MaterialInfo::findBuiltin(const std::string &token) bool MaterialInfo::findInorganic(const std::string &token) { + if (token.empty()) + return decode(-1); df::world_raws &raws = df::global::world->raws; for (unsigned i = 0; i < raws.inorganics.size(); i++) { @@ -185,6 +200,8 @@ bool MaterialInfo::findInorganic(const std::string &token) bool MaterialInfo::findPlant(const std::string &token, const std::string &subtoken) { + if (token.empty() || subtoken.empty()) + return decode(-1); df::world_raws &raws = df::global::world->raws; for (unsigned i = 0; i < raws.plants.all.size(); i++) { @@ -203,6 +220,8 @@ bool MaterialInfo::findPlant(const std::string &token, const std::string &subtok bool MaterialInfo::findCreature(const std::string &token, const std::string &subtoken) { + if (token.empty() || subtoken.empty()) + return decode(-1); df::world_raws &raws = df::global::world->raws; for (unsigned i = 0; i < raws.creatures.all.size(); i++) { @@ -393,6 +412,25 @@ void MaterialInfo::getMatchBits(df::job_item_flags3 &ok, df::job_item_flags3 &ma #undef FLAG #undef TEST +bool DFHack::parseJobMaterialCategory(df::job_material_category *cat, const std::string &token) +{ + cat->whole = 0; + + std::vector items; + split_string(&items, toLower(token), ",", true); + + for (unsigned i = 0; i < items.size(); i++) + { + int id = findBitfieldField(*cat, items[i]); + if (id < 0) + return false; + + cat->whole |= (1 << id); + } + + return true; +} + Module* DFHack::createMaterials() { return new Materials(); diff --git a/library/modules/World.cpp b/library/modules/World.cpp index 4dea79c2b..31dfb7e6a 100644 --- a/library/modules/World.cpp +++ b/library/modules/World.cpp @@ -265,7 +265,7 @@ PersistentDataItem World::AddPersistentData(const std::string &key) hfig->id = new_id; hfig->name.has_name = true; hfig->name.first_name = key; - memset(hfig->name.words, 0, sizeof(hfig->name.words)); + memset(hfig->name.words, 0xFF, sizeof(hfig->name.words)); hfvec.insert(hfvec.begin(), hfig); return dataFromHFig(hfig); diff --git a/plugins/jobutils.cpp b/plugins/jobutils.cpp index a89fa99cd..a908b7607 100644 --- a/plugins/jobutils.cpp +++ b/plugins/jobutils.cpp @@ -64,7 +64,7 @@ DFhackCExport command_result plugin_init (Core *c, std::vector & " Print details of the current job.\n" " job list\n" " Print details of all jobs in the workshop.\n" - " job item-material [submaterial]\n" + " job item-material \n" " Replace the exact material id in the job item.\n" ) ); @@ -249,21 +249,6 @@ static command_result job_material(Core * c, vector & parameters) /* job-duplicate implementation */ -static df::job *clone_job(df::job *job) -{ - df::job *pnew = cloneJobStruct(job); - - pnew->id = (*job_next_id)++; - - // Link the job into the global list - pnew->list_link = new df::job_list_link(); - pnew->list_link->item = pnew; - - linked_list_append(&world->job_list, pnew->list_link); - - return pnew; -} - static command_result job_duplicate(Core * c, vector & parameters) { if (!parameters.empty()) @@ -287,10 +272,10 @@ static command_result job_duplicate(Core * c, vector & parameters) } // Actually clone - df::job *pnew = clone_job(job); + df::job *pnew = cloneJobStruct(job); - int pos = ++*ui_workshop_job_cursor; - building->jobs.insert(building->jobs.begin()+pos, pnew); + linkJobIntoWorld(pnew); + vector_insert_at(building->jobs, ++*ui_workshop_job_cursor, pnew); return CR_OK; } @@ -336,9 +321,8 @@ static command_result job_cmd(Core * c, vector & parameters) df::job_item *item = job->job_items[v-1]; - std::string subtoken = (parameters.size()>3 ? parameters[3] : ""); MaterialInfo info; - if (!info.find(parameters[2], subtoken)) { + if (!info.find(parameters[2])) { c->con.printerr("Could not find the specified material.\n"); return CR_FAILURE; } diff --git a/plugins/workflow.cpp b/plugins/workflow.cpp index 99d7dc411..0a1319d2c 100644 --- a/plugins/workflow.cpp +++ b/plugins/workflow.cpp @@ -98,18 +98,6 @@ DFhackCExport command_result plugin_onstatechange(Core* c, state_change_event ev /*******************************/ -static df::building *getJobHolder(df::job *job) -{ - for (unsigned i = 0; i < job->references.size(); i++) - { - VIRTUAL_CAST_VAR(ref, df::general_ref_building_holderst, job->references[i]); - if (ref) - return ref->getBuilding(); - } - - return NULL; -}; - struct ProtectedJob { int id; int building_id; @@ -253,8 +241,6 @@ static int *find_protected_id_slot(Core *c, int key) if (key == -1) { protected_cfg.push_back(c->getWorld()->AddPersistentData("workflow/protected-jobs")); PersistentDataItem &item = protected_cfg.back(); - for (int j = 0; j < PersistentDataItem::NumInts; j++) - item.ival(j) = -1; return &item.ival(0); } @@ -408,7 +394,7 @@ DFhackCExport command_result plugin_onupdate(Core* c) { for (int i = pending_recover.size()-1; i >= 0; i--) if (recover_job(c, pending_recover[i])) - pending_recover.erase(pending_recover.begin()+i); + vector_erase_at(pending_recover, i); check_lost_jobs(c); } From f687844c5be14d95db43c345d178c9b370db5160 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Mr=C3=A1zek?= Date: Sun, 8 Jan 2012 17:53:53 +0100 Subject: [PATCH 34/82] Update structures. --- library/xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/xml b/library/xml index c2caba7eb..73a02e7c4 160000 --- a/library/xml +++ b/library/xml @@ -1 +1 @@ -Subproject commit c2caba7eb15896d56163620e9ace1fb67ae953cb +Subproject commit 73a02e7c4cbb06eb439c8d489196cebbab64f1f8 From 50386f66a3651ec08086257aa37f3e8d532fcffa Mon Sep 17 00:00:00 2001 From: Alexander Gavrilov Date: Mon, 9 Jan 2012 16:20:17 +0400 Subject: [PATCH 35/82] Update structures and implement modifying the job_item item type. --- library/include/DataDefs.h | 27 ++- library/include/MiscUtils.h | 5 + library/include/modules/Items.h | 45 +++++ library/modules/Items.cpp | 330 ++++++++++++++++++++++++++++++++ library/modules/Job.cpp | 18 +- library/modules/Materials.cpp | 32 +++- library/xml | 2 +- plugins/jobutils.cpp | 93 ++++++--- 8 files changed, 513 insertions(+), 39 deletions(-) diff --git a/library/include/DataDefs.h b/library/include/DataDefs.h index b4bc516d0..4acf19c35 100644 --- a/library/include/DataDefs.h +++ b/library/include/DataDefs.h @@ -125,23 +125,25 @@ namespace DFHack template T *ifnull(T *a, T *b) { return a ? a : b; } + // Enums template inline T next_enum_item_(T v) { v = T(int(v) + 1); return isvalid(v) ? v : start; } - struct bitfield_item_info { - const char *name; - int size; - }; - template struct enum_list_attr { int size; const T *items; }; + // Bitfields + struct bitfield_item_info { + const char *name; + int size; + }; + DFHACK_EXPORT std::string bitfieldToString(const void *p, int size, const bitfield_item_info *items); DFHACK_EXPORT int findBitfieldField(const std::string &name, int size, const bitfield_item_info *items); @@ -156,6 +158,21 @@ namespace DFHack } } +template +int linear_index(const DFHack::enum_list_attr &lst, T val) { + for (int i = 0; i < lst.size; i++) + if (lst.items[i] == val) + return i; + return -1; +} + +inline int linear_index(const DFHack::enum_list_attr &lst, const std::string &val) { + for (int i = 0; i < lst.size; i++) + if (lst.items[i] == val) + return i; + return -1; +} + namespace df { using DFHack::virtual_ptr; diff --git a/library/include/MiscUtils.h b/library/include/MiscUtils.h index c744f587c..b3d70f6b9 100644 --- a/library/include/MiscUtils.h +++ b/library/include/MiscUtils.h @@ -257,6 +257,11 @@ DFHACK_EXPORT bool split_string(std::vector *out, DFHACK_EXPORT std::string toUpper(const std::string &str); DFHACK_EXPORT std::string toLower(const std::string &str); +inline bool bits_match(unsigned required, unsigned ok, unsigned mask) +{ + return (required & mask) == (required & mask & ok); +} + /** * Returns the amount of milliseconds elapsed since the UNIX epoch. * Works on both windows and linux. diff --git a/library/include/modules/Items.h b/library/include/modules/Items.h index 4deba6cdb..1e889fca1 100644 --- a/library/include/modules/Items.h +++ b/library/include/modules/Items.h @@ -32,6 +32,15 @@ distribution. #include "Virtual.h" #include "modules/Materials.h" #include "MemAccess.h" + +#include "DataDefs.h" +#include "df/item_type.h" + +namespace df +{ + struct itemdef; +} + /** * \defgroup grp_items Items module and its types * @ingroup grp_modules @@ -39,6 +48,42 @@ distribution. namespace DFHack { + struct DFHACK_EXPORT ItemTypeInfo { + df::item_type type; + int16_t subtype; + + df::itemdef *custom; + + public: + ItemTypeInfo(df::item_type type_ = df::enums::item_type::NONE, int16_t subtype_ = -1) { + decode(type_, subtype_); + } + template ItemTypeInfo(T *ptr) { decode(ptr); } + + bool isValid() const { + return (type != df::enums::item_type::NONE) && (subtype == -1 || custom); + } + + bool decode(df::item_type type_, int16_t subtype_ = -1); + bool decode(df::item *ptr); + + template bool decode(T *ptr) { + return ptr ? decode(ptr->item_type, ptr->item_subtype) : decode(df::enums::item_type::NONE); + } + + std::string toString(); + + bool find(const std::string &token); + + bool matches(const df::job_item &item, MaterialInfo *mat = NULL); + }; + + inline bool operator== (const ItemTypeInfo &a, const ItemTypeInfo &b) { + return a.type == b.type && a.subtype == b.subtype; + } + inline bool operator!= (const ItemTypeInfo &a, const ItemTypeInfo &b) { + return a.type != b.type || a.subtype != b.subtype; + } class Context; class DFContextShared; diff --git a/library/modules/Items.cpp b/library/modules/Items.cpp index ddf6c4f29..fb2ae6655 100644 --- a/library/modules/Items.cpp +++ b/library/modules/Items.cpp @@ -42,8 +42,338 @@ using namespace std; #include "ModuleFactory.h" #include "Core.h" #include "Virtual.h" +#include "MiscUtils.h" + +#include "df/world.h" +#include "df/item.h" +#include "df/tool_uses.h" +#include "df/itemdef_weaponst.h" +#include "df/itemdef_trapcompst.h" +#include "df/itemdef_toyst.h" +#include "df/itemdef_toolst.h" +#include "df/itemdef_instrumentst.h" +#include "df/itemdef_armorst.h" +#include "df/itemdef_ammost.h" +#include "df/itemdef_siegeammost.h" +#include "df/itemdef_glovesst.h" +#include "df/itemdef_shoesst.h" +#include "df/itemdef_shieldst.h" +#include "df/itemdef_helmst.h" +#include "df/itemdef_pantsst.h" +#include "df/itemdef_foodst.h" +#include "df/trapcomp_flags.h" +#include "df/job_item.h" using namespace DFHack; +using namespace df::enums; + +#define ITEMDEF_VECTORS \ + ITEM(WEAPON, weapons) \ + ITEM(TRAPCOMP, trapcomps) \ + ITEM(TOY, toys) \ + ITEM(TOOL, tools) \ + ITEM(INSTRUMENT, instruments) \ + ITEM(ARMOR, armor) \ + ITEM(AMMO, ammo) \ + ITEM(SIEGEAMMO, siege_ammo) \ + ITEM(GLOVES, gloves) \ + ITEM(SHOES, shoes) \ + ITEM(SHIELD, shields) \ + ITEM(HELM, helms) \ + ITEM(PANTS, pants) \ + ITEM(FOOD, food) + +bool ItemTypeInfo::decode(df::item_type type_, int16_t subtype_) +{ + using namespace df::enums::item_type; + + type = type_; + subtype = subtype_; + custom = NULL; + + df::world_raws::T_itemdefs &defs = df::global::world->raws.itemdefs; + + switch (type_) { + case NONE: + return false; + +#define ITEM(type,vec) \ + case type: \ + custom = vector_get(defs.vec, subtype); \ + break; +ITEMDEF_VECTORS +#undef ITEM + + default: + break; + } + + return isValid(); +} + +bool ItemTypeInfo::decode(df::item *ptr) +{ + if (!ptr) + return decode(item_type::NONE); + else + return decode(ptr->getType(), ptr->getSubtype()); +} + +std::string ItemTypeInfo::toString() +{ + std::string rv = ENUM_KEY_STR(item_type, type); + if (custom) + rv += ":" + custom->id; + else if (subtype != -1) + rv += stl_sprintf(":%d", subtype); + return rv; +} + +bool ItemTypeInfo::find(const std::string &token) +{ + using namespace df::enums::item_type; + + std::vector items; + split_string(&items, token, ":"); + + type = NONE; + subtype = -1; + custom = NULL; + + if (items.size() < 1 || items.size() > 2) + return false; + + if (items[0] == "NONE") + return true; + + FOR_ENUM_ITEMS(item_type, i) + { + const char *key = ENUM_ATTR(item_type, key, i); + if (key && key == items[0]) + { + type = i; + break; + } + } + + if (type == NONE) + return false; + if (items.size() == 1) + return true; + + df::world_raws::T_itemdefs &defs = df::global::world->raws.itemdefs; + + switch (type) { +#define ITEM(type,vec) \ + case type: \ + for (int i = 0; i < defs.vec.size(); i++) { \ + if (defs.vec[i]->id == items[1]) { \ + subtype = i; custom = defs.vec[i]; return true; \ + } \ + } \ + break; +ITEMDEF_VECTORS +#undef ITEM + + default: + break; + } + + return (subtype >= 0); +} + +bool ItemTypeInfo::matches(const df::job_item &item, MaterialInfo *mat) +{ + using namespace df::enums::item_type; + + if (!isValid()) + return mat ? mat->matches(item) : true; + + df::job_item_flags1 ok1, mask1, item_ok1, item_mask1; + df::job_item_flags2 ok2, mask2, item_ok2, item_mask2; + df::job_item_flags3 ok3, mask3, item_ok3, item_mask3; + + ok1.whole = mask1.whole = item_ok1.whole = item_mask1.whole = 0; + ok2.whole = mask2.whole = item_ok2.whole = item_mask2.whole = 0; + ok3.whole = mask3.whole = item_ok3.whole = item_mask3.whole = 0; + + if (mat) { + mat->getMatchBits(ok1, mask1); + mat->getMatchBits(ok2, mask2); + mat->getMatchBits(ok3, mask3); + } + +#define OK(id,name) item_ok##id.bits.name = true +#define RQ(id,name) item_mask##id.bits.name = true + + // Set up the flag mask + + RQ(1,millable); RQ(1,sharpenable); RQ(1,distillable); RQ(1,processable); RQ(1,bag); + RQ(1,extract_bearing_plant); RQ(1,extract_bearing_fish); RQ(1,extract_bearing_vermin); + RQ(1,processable_to_vial); RQ(1,processable_to_bag); RQ(1,processable_to_barrel); + RQ(1,solid); RQ(1,tameable_vermin); RQ(1,sand_bearing); RQ(1,milk); RQ(1,milkable); + RQ(1,not_bin); RQ(1,lye_bearing); + + RQ(2,dye); RQ(2,dyeable); RQ(2,dyed); RQ(2,glass_making); RQ(2,screw); + RQ(2,building_material); RQ(2,fire_safe); RQ(2,magma_safe); RQ(2,non_economic); + RQ(2,totemable); RQ(2,plaster_containing); RQ(2,body_part); RQ(2,lye_milk_free); + RQ(2,blunt); RQ(2,unengraved); RQ(2,hair_wool); + + RQ(3,any_raw_material); RQ(3,non_pressed); RQ(3,food_storage); + + // Compute the ok mask + + OK(1,solid); + OK(1,not_bin); + + // TODO: furniture, ammo, finished good, craft + + switch (type) { + case PLANT: + OK(1,millable); OK(1,processable); + OK(1,distillable); + OK(1,extract_bearing_plant); + OK(1,processable_to_vial); + OK(1,processable_to_bag); + OK(1,processable_to_barrel); + break; + + case BOULDER: + OK(1,sharpenable); + OK(2,non_economic); + case BAR: + OK(3,any_raw_material); + case BLOCKS: + case WOOD: + OK(2,building_material); + OK(2,fire_safe); OK(2,magma_safe); + break; + + case VERMIN: + OK(1,extract_bearing_fish); + OK(1,extract_bearing_vermin); + OK(1,tameable_vermin); + OK(1,milkable); + break; + + case DRINK: + item_ok1.bits.solid = false; + break; + + case ROUGH: + OK(2,glass_making); + break; + + case ANIMALTRAP: + case CAGE: + OK(1,milk); + OK(1,milkable); + break; + + case BUCKET: + case FLASK: + OK(1,milk); + break; + + case TOOL: + OK(1,lye_bearing); + OK(1,milk); + OK(2,lye_milk_free); + OK(2,blunt); + + if (VIRTUAL_CAST_VAR(def, df::itemdef_toolst, custom)) { + df::enum_field key(tool_uses::FOOD_STORAGE); + if (linear_index(def->tool_use, key) >= 0) + OK(3,food_storage); + } else { + OK(3,food_storage); + } + break; + + case BARREL: + OK(1,lye_bearing); + OK(1,milk); + OK(2,lye_milk_free); + OK(3,food_storage); + break; + + case BOX: + OK(1,bag); OK(1,sand_bearing); OK(1,milk); + OK(2,dye); OK(2,plaster_containing); + break; + + case BIN: + item_ok1.bits.not_bin = false; + break; + + case LIQUID_MISC: + item_ok1.bits.solid = false; + OK(1,milk); + break; + + case POWDER_MISC: + OK(2,dye); + case GLOB: + OK(3,any_raw_material); + OK(3,non_pressed); + break; + + case THREAD: + case CLOTH: + OK(2,dyeable); OK(2,dyed); + break; + + case WEAPON: + case AMMO: + case ROCK: + OK(2,blunt); + break; + + case TRAPCOMP: + if (VIRTUAL_CAST_VAR(def, df::itemdef_trapcompst, custom)) { + if (def->flags.is_set(trapcomp_flags::IS_SCREW)) + OK(2,screw); + } else { + OK(2,screw); + } + OK(2,blunt); + break; + + case CORPSE: + case CORPSEPIECE: + OK(2,totemable); + OK(2,body_part); + OK(2,hair_wool); + break; + + case SLAB: + OK(2,unengraved); + break; + + case ANVIL: + OK(2,fire_safe); OK(2,magma_safe); + break; + + default: + break; + } + + if ((item_ok1.whole & ~item_mask1.whole) || + (item_ok2.whole & ~item_mask2.whole) || + (item_ok3.whole & ~item_mask3.whole)) + Core::getInstance().con.printerr("ItemTypeInfo.matches inconsistent\n"); + +#undef OK +#undef RQ + + return bits_match(item.flags1.whole, ok1.whole, mask1.whole) && + bits_match(item.flags2.whole, ok2.whole, mask2.whole) && + bits_match(item.flags3.whole, ok3.whole, mask3.whole) && + bits_match(item.flags1.whole, item_ok1.whole, item_mask1.whole) && + bits_match(item.flags2.whole, item_ok2.whole, item_mask2.whole) && + bits_match(item.flags3.whole, item_ok3.whole, item_mask3.whole); +} + Module* DFHack::createItems() { diff --git a/library/modules/Job.cpp b/library/modules/Job.cpp index 3e3016e1f..4e8094547 100644 --- a/library/modules/Job.cpp +++ b/library/modules/Job.cpp @@ -37,6 +37,7 @@ using namespace std; #include "modules/Job.h" #include "modules/Materials.h" +#include "modules/Items.h" #include "DataDefs.h" #include @@ -140,9 +141,9 @@ bool DFHack::operator== (const df::job &a, const df::job &b) static void print_job_item_details(Core *c, df::job *job, unsigned idx, df::job_item *item) { - c->con << " Input Item " << (idx+1) << ": " << ENUM_KEY_STR(item_type,item->item_type); - if (item->item_subtype != -1) - c->con << " [" << item->item_subtype << "]"; + ItemTypeInfo info(item); + c->con << " Input Item " << (idx+1) << ": " << info.toString(); + if (item->quantity != 1) c->con << "; quantity=" << item->quantity; if (item->min_dimension >= 0) @@ -179,7 +180,12 @@ void DFHack::printJobDetails(Core *c, df::job *job) c->con << " (" << bitfieldToString(job->flags) << ")"; c->con << endl; + df::item_type itype = ENUM_ATTR(job_type, item, job->job_type); + MaterialInfo mat(job); + if (itype == item_type::FOOD) + mat.decode(-1); + if (mat.isValid() || job->material_category.whole) { c->con << " material: " << mat.toString(); @@ -189,8 +195,12 @@ void DFHack::printJobDetails(Core *c, df::job *job) } if (job->item_subtype >= 0 || job->item_category.whole) - c->con << " item: " << job->item_subtype + { + ItemTypeInfo iinfo(itype, job->item_subtype); + + c->con << " item: " << iinfo.toString() << " (" << bitfieldToString(job->item_category) << ")" << endl; + } if (job->hist_figure_id >= 0) c->con << " figure: " << job->hist_figure_id << endl; diff --git a/library/modules/Materials.cpp b/library/modules/Materials.cpp index 32145cc90..716717230 100644 --- a/library/modules/Materials.cpp +++ b/library/modules/Materials.cpp @@ -161,6 +161,8 @@ bool MaterialInfo::find(const std::string &token) return true; if (findInorganic(items[0])) return true; + if (findPlant(items[0], "")) + return true; } else if (items.size() == 2) { @@ -177,6 +179,12 @@ bool MaterialInfo::findBuiltin(const std::string &token) { if (token.empty()) return decode(-1); + + if (token == "NONE") { + decode(-1); + return true; + } + df::world_raws &raws = df::global::world->raws; for (int i = 1; i < NUM_BUILTIN; i++) if (raws.mat_table.builtin[i]->id == token) @@ -188,6 +196,12 @@ bool MaterialInfo::findInorganic(const std::string &token) { if (token.empty()) return decode(-1); + + if (token == "NONE") { + decode(0, -1); + return true; + } + df::world_raws &raws = df::global::world->raws; for (unsigned i = 0; i < raws.inorganics.size(); i++) { @@ -200,7 +214,7 @@ bool MaterialInfo::findInorganic(const std::string &token) bool MaterialInfo::findPlant(const std::string &token, const std::string &subtoken) { - if (token.empty() || subtoken.empty()) + if (token.empty()) return decode(-1); df::world_raws &raws = df::global::world->raws; for (unsigned i = 0; i < raws.plants.all.size(); i++) @@ -209,6 +223,10 @@ bool MaterialInfo::findPlant(const std::string &token, const std::string &subtok if (p->id != token) continue; + // As a special exception, return the structural material with empty subtoken + if (subtoken.empty()) + return decode(p->material_defs.type_basic_mat, p->material_defs.idx_basic_mat); + for (unsigned j = 0; j < p->material.size(); j++) if (p->material[j]->id == subtoken) return decode(PLANT_BASE+j, i); @@ -317,7 +335,7 @@ bool MaterialInfo::matches(const df::job_material_category &cat) bool MaterialInfo::matches(const df::job_item &item) { - if (!isValid()) return false; + if (!isValid()) return true; df::job_item_flags1 ok1, mask1; getMatchBits(ok1, mask1); @@ -328,9 +346,9 @@ bool MaterialInfo::matches(const df::job_item &item) df::job_item_flags3 ok3, mask3; getMatchBits(ok3, mask3); - return ((item.flags1.whole & mask1.whole) == (item.flags1.whole & ok1.whole)) && - ((item.flags2.whole & mask2.whole) == (item.flags2.whole & ok2.whole)) && - ((item.flags3.whole & mask3.whole) == (item.flags3.whole & ok3.whole)); + return bits_match(item.flags1.whole, ok1.whole, mask1.whole) && + bits_match(item.flags2.whole, ok2.whole, mask2.whole) && + bits_match(item.flags3.whole, ok3.whole, mask3.whole); } void MaterialInfo::getMatchBits(df::job_item_flags1 &ok, df::job_item_flags1 &mask) @@ -349,7 +367,7 @@ void MaterialInfo::getMatchBits(df::job_item_flags1 &ok, df::job_item_flags1 &ma TEST(sharpenable, MAT_FLAG(IS_STONE)); TEST(distillable, structural && FLAG(plant, plant_raw_flags::DRINK)); TEST(processable, structural && FLAG(plant, plant_raw_flags::THREAD)); - TEST(bag, isAnyCloth()); + TEST(bag, isAnyCloth() || MAT_FLAG(LEATHER)); TEST(cookable, MAT_FLAG(EDIBLE_COOKED)); TEST(extract_bearing_plant, structural && FLAG(plant, plant_raw_flags::EXTRACT_STILL_VIAL)); TEST(extract_bearing_fish, false); @@ -363,7 +381,7 @@ void MaterialInfo::getMatchBits(df::job_item_flags1 &ok, df::job_item_flags1 &ma MAT_FLAG(LIQUID_MISC_CREATURE) || MAT_FLAG(LIQUID_MISC_OTHER))); TEST(tameable_vermin, false); - TEST(sharpenable, MAT_FLAG(IS_GLASS)); + TEST(sharpenable, MAT_FLAG(IS_STONE)); TEST(milk, linear_index(material->reaction_product.id, std::string("CHEESE_MAT")) >= 0); //04000000 - "milkable" - vtable[107],1,1 } diff --git a/library/xml b/library/xml index b93b61a98..85dfa3550 160000 --- a/library/xml +++ b/library/xml @@ -1 +1 @@ -Subproject commit b93b61a988020a4aaa0103cefcee0217c37ce7b0 +Subproject commit 85dfa3550fe204c8c75279335cae1457cf03e0ed diff --git a/plugins/jobutils.cpp b/plugins/jobutils.cpp index a908b7607..29d86230c 100644 --- a/plugins/jobutils.cpp +++ b/plugins/jobutils.cpp @@ -5,6 +5,7 @@ #include #include +#include #include #include @@ -60,12 +61,14 @@ DFhackCExport command_result plugin_init (Core *c, std::vector & PluginCommand( "job", "General job query and manipulation.", job_cmd, false, - " job query\n" + " job [query]\n" " Print details of the current job.\n" " job list\n" " Print details of all jobs in the workshop.\n" " job item-material \n" " Replace the exact material id in the job item.\n" + " job item-type \n" + " Replace the exact item type id in the job item.\n" ) ); @@ -154,6 +157,13 @@ static command_result job_material_in_job(Core *c, MaterialInfo &new_mat) 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 @@ -282,14 +292,25 @@ static command_result job_duplicate(Core * c, vector & parameters) /* Main job command implementation */ +static df::job_item *getJobItem(Core *c, df::job *job, std::string idx) +{ + if (!job) + return NULL; + + int v = atoi(idx.c_str()); + if (v < 1 || v > job->job_items.size()) { + c->con.printerr("Invalid item index.\n"); + return NULL; + } + + return job->job_items[v-1]; +} + static command_result job_cmd(Core * c, vector & parameters) { CoreSuspender suspend(c); - if (parameters.empty()) - return CR_WRONG_USAGE; - - std::string cmd = parameters[0]; + std::string cmd = (parameters.empty() ? "query" : parameters[0]); if (cmd == "query" || cmd == "list") { df::job *job = getSelectedWorkshopJob(c); @@ -306,28 +327,23 @@ static command_result job_cmd(Core * c, vector & parameters) } else if (cmd == "item-material") { - if (parameters.size() < 1+1+1) + if (parameters.size() != 3) return CR_WRONG_USAGE; df::job *job = getSelectedWorkshopJob(c); - if (!job) + df::job_item *item = getJobItem(c, job, parameters[1]); + if (!item) return CR_WRONG_USAGE; - int v = atoi(parameters[1].c_str()); - if (v < 1 || v > job->job_items.size()) { - c->con.printerr("Invalid item index.\n"); - return CR_WRONG_USAGE; - } + ItemTypeInfo iinfo(item); + MaterialInfo minfo; - df::job_item *item = job->job_items[v-1]; - - MaterialInfo info; - if (!info.find(parameters[2])) { + if (!minfo.find(parameters[2])) { c->con.printerr("Could not find the specified material.\n"); return CR_FAILURE; } - if (!info.matches(*item)) { + if (!iinfo.matches(*item, &minfo)) { c->con.printerr("Material does not match the requirements.\n"); printJobDetails(c, job); return CR_FAILURE; @@ -337,19 +353,52 @@ static command_result job_cmd(Core * c, vector & parameters) job->mat_type == item->mat_type && job->mat_index == item->mat_index) { - job->mat_type = info.type; - job->mat_index = info.index; + job->mat_type = minfo.type; + job->mat_index = minfo.index; } - item->mat_type = info.type; - item->mat_index = info.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"); - c->con << "Job item " << v << " updated." << endl; printJobDetails(c, job); return CR_OK; } else if (cmd == "item-type") { + if (parameters.size() != 3) + return CR_WRONG_USAGE; + + df::job *job = getSelectedWorkshopJob(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.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; From 3e147fe9024c656ab4929630ba9292b18df86203 Mon Sep 17 00:00:00 2001 From: Alexander Gavrilov Date: Mon, 9 Jan 2012 17:29:28 +0400 Subject: [PATCH 36/82] Modify the workflow plugin to protect all repeat jobs when enabled. --- plugins/workflow.cpp | 341 ++++++++++++++++++------------------------- 1 file changed, 143 insertions(+), 198 deletions(-) diff --git a/plugins/workflow.cpp b/plugins/workflow.cpp index 0a1319d2c..32ca50a82 100644 --- a/plugins/workflow.cpp +++ b/plugins/workflow.cpp @@ -36,7 +36,7 @@ using df::global::job_next_id; /* Plugin registration */ -static command_result protect_job(Core *c, vector & parameters); +static command_result workflow_cmd(Core *c, vector & parameters); static void init_state(Core *c); static void cleanup_state(Core *c); @@ -55,14 +55,17 @@ DFhackCExport command_result plugin_init (Core *c, std::vector & if (ui_workshop_job_cursor && job_next_id) { commands.push_back( PluginCommand( - "protect-job", "Manage protection of workshop jobs from removal.", - protect_job, false, - " protect-job list\n" - " List protected jobs. If a workshop is selected, filters by it.\n" - " protect-job add [all]\n" - " Protect the selected job, or any repeat jobs (possibly in the workshop).\n" - " protect-job remove [all]\n" - " Unprotect the selected job, or any repeat jobs (possibly in the workshop).\n" + "workflow", "Manage control of repeat jobs.", + workflow_cmd, false, + " workflow enable\n" + " workflow disable\n" + " Enable or disable the plugin.\n" + " workflow list-jobs\n" + " List workflow-controlled jobs (if in a workshop, filtered by it).\n" + "Function:\n" + " When the plugin is enabled, it protects all repeat jobs from removal.\n" + " If they do disappear due to any cause, they are immediately re-added\n" + " to their workshop and suspended.\n" ) ); } @@ -130,20 +133,35 @@ struct ProtectedJob { } }; -PersistentDataItem config; -static std::vector protected_cfg; +/*******************************/ + +static bool enabled = false; +static PersistentDataItem config; + +enum ConfigFlags { + CF_ENABLED = 1 +}; typedef std::map TKnownJobs; static TKnownJobs known_jobs; static std::vector pending_recover; +/*******************************/ + static ProtectedJob *get_known(int id) { TKnownJobs::iterator it = known_jobs.find(id); return (it != known_jobs.end()) ? it->second : NULL; } +static bool isSupportedJob(df::job *job) +{ + return job->misc_links.empty() && + !job->job_items.empty() && + getJobHolder(job); +} + static void enumLiveJobs(std::map &rv) { df::job_list_link *p = world->job_list.next; @@ -151,129 +169,74 @@ static void enumLiveJobs(std::map &rv) rv[p->item->id] = p->item; } -static void cleanup_state(Core *) -{ - config = PersistentDataItem(); - protected_cfg.clear(); +/*******************************/ +static void stop_protect(Core *c) +{ pending_recover.clear(); + if (!known_jobs.empty()) + c->con.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 init_state(Core *c) +static void cleanup_state(Core *c) { - config = c->getWorld()->GetPersistentData("workflow/config"); - c->getWorld()->GetPersistentData(&protected_cfg, "workflow/protected-jobs"); - - std::map jobs; - enumLiveJobs(jobs); + config = PersistentDataItem(); - for (unsigned i = 0; i < protected_cfg.size(); i++) - { - PersistentDataItem &item = protected_cfg[i]; - for (int j = 0; j < PersistentDataItem::NumInts; j++) - { - int id = item.ival(j); - if (id <= 0) - continue; + stop_protect(c); +} - if (get_known(id)) // duplicate - { - item.ival(j) = -1; - continue; - } +static bool check_lost_jobs(Core *c); - df::job *job = jobs[id]; - if (!job) - { - c->con.printerr("Protected job lost: %d\n", id); - item.ival(j) = -1; - continue; - } +static void start_protect(Core *c) +{ + check_lost_jobs(c); - if (!job->misc_links.empty() || job->job_items.empty()) - { - c->con.printerr("Protected job unsupported: %d (%s)\n", - id, ENUM_KEY_STR(job_type, job->job_type)); - item.ival(j) = -1; - continue; - } + if (!known_jobs.empty()) + c->con.print("Protecting %d jobs.\n", known_jobs.size()); +} - ProtectedJob *pj = new ProtectedJob(job); - if (!pj->holder) - { - c->con.printerr("Protected job not in building: %d (%s)\n", - id, ENUM_KEY_STR(job_type, job->job_type)); - delete pj; - item.ival(j) = -1; - continue; - } +static void init_state(Core *c) +{ + config = c->getWorld()->GetPersistentData("workflow/config"); - known_jobs[id] = pj; + enabled = config.isValid() && config.ival(0) != -1 && + (config.ival(0) & CF_ENABLED); - if (!job->flags.bits.repeat) { - c->con.printerr("Protected job not repeating: %d\n", id); - job->flags.bits.repeat = true; - } - } - } + if (!enabled) + return; - if (!known_jobs.empty()) - c->con.print("Protecting %d jobs.\n", known_jobs.size()); + start_protect(c); } -static int *find_protected_id_slot(Core *c, int key) +static void enable_plugin(Core *c) { - for (unsigned i = 0; i < protected_cfg.size(); i++) + if (!config.isValid()) { - PersistentDataItem &item = protected_cfg[i]; - for (int j = 0; j < PersistentDataItem::NumInts; j++) - { - if (item.ival(j) == key) - return &item.ival(j); - } + config = c->getWorld()->AddPersistentData("workflow/config"); + config.ival(0) = 0; } - if (key == -1) { - protected_cfg.push_back(c->getWorld()->AddPersistentData("workflow/protected-jobs")); - PersistentDataItem &item = protected_cfg.back(); - return &item.ival(0); - } + config.ival(0) |= CF_ENABLED; + enabled = true; + c->con << "Enabling the plugin." << endl; - return NULL; + start_protect(c); } +/*******************************/ + static void forget_job(Core *c, ProtectedJob *pj) { known_jobs.erase(pj->id); - - if (int *p = find_protected_id_slot(c, pj->id)) - *p = -1; - delete pj; } -static void remember_job(Core *c, df::job *job) -{ - if (get_known(job->id)) - return; - - if (!job->misc_links.empty() || job->job_items.empty()) - { - c->con.printerr("Unsupported job type: %d (%s)\n", - job->id, ENUM_KEY_STR(job_type, job->job_type)); - return; - } - - known_jobs[job->id] = new ProtectedJob(job); - - *find_protected_id_slot(c, -1) = job->id; -} - static bool recover_job(Core *c, ProtectedJob *pj) { // Check that the building exists @@ -305,37 +268,22 @@ static bool recover_job(Core *c, ProtectedJob *pj) return false; } - // Find the position in the job list - df::job_list_link *ins_pos = &world->job_list; - while (ins_pos->next && ins_pos->next->item->id < pj->id) - ins_pos = ins_pos->next; + // Create and link in the actual job structure + df::job *recovered = cloneJobStruct(pj->job_copy); + + recovered->flags.bits.repeat = true; + recovered->flags.bits.suspend = true; - if (ins_pos->next && ins_pos->next->item->id == pj->id) + if (!linkJobIntoWorld(recovered, false)) // reuse same id { + deleteJobStruct(recovered); + c->con.printerr("Inconsistency: job %d (%s) already in list.", pj->id, ENUM_KEY_STR(job_type, pj->job_copy->job_type)); pj->live = true; return true; } - // Create the actual job structure - df::job *recovered = cloneJobStruct(pj->job_copy); - - recovered->flags.bits.repeat = true; - recovered->flags.bits.suspend = true; - - // Link the job into the global list - df::job_list_link *link = new df::job_list_link(); - recovered->list_link = link; - - link->item = recovered; - link->next = ins_pos->next; - if (ins_pos->next) - ins_pos->next->prev = link; - link->prev = ins_pos; - ins_pos->next = link; - - // Add to building jobs pj->holder->jobs.push_back(recovered); // Done @@ -343,7 +291,7 @@ static bool recover_job(Core *c, ProtectedJob *pj) return true; } -static void check_lost_jobs(Core *c) +static bool check_lost_jobs(Core *c) { static int check = 1; check++; @@ -351,15 +299,27 @@ static void check_lost_jobs(Core *c) df::job_list_link *p = world->job_list.next; for (; p; p = p->next) { - ProtectedJob *pj = get_known(p->item->id); - if (!pj) - continue; - pj->check_idx = check; + df::job *job = p->item; - // force repeat - p->item->flags.bits.repeat = true; + ProtectedJob *pj = get_known(job->id); + if (pj) + { + if (!job->flags.bits.repeat) + forget_job(c, pj); + else + pj->check_idx = check; + } + else if (job->flags.bits.repeat && isSupportedJob(job)) + { + pj = new ProtectedJob(job); + assert(pj->holder); + known_jobs[pj->id] = pj; + pj->check_idx = check; + } } + bool any_lost = false; + for (TKnownJobs::const_iterator it = known_jobs.begin(); it != known_jobs.end(); ++it) { if (it->second->check_idx == check || !it->second->live) @@ -367,7 +327,10 @@ static void check_lost_jobs(Core *c) it->second->live = false; pending_recover.push_back(it->second); + any_lost = true; } + + return any_lost; } static void update_job_data(Core *c) @@ -382,21 +345,30 @@ static void update_job_data(Core *c) } } +static void recover_jobs(Core *c) +{ + for (int i = pending_recover.size()-1; i >= 0; i--) + if (recover_job(c, pending_recover[i])) + vector_erase_at(pending_recover, i); +} + DFhackCExport command_result plugin_onupdate(Core* c) { - if (known_jobs.empty()) + if (!enabled) return CR_OK; static unsigned cnt = 0; cnt++; - if ((cnt % 10) == 0) + bool force_recover = false; + if ((cnt % 5) == 0) { - for (int i = pending_recover.size()-1; i >= 0; i--) - if (recover_job(c, pending_recover[i])) - vector_erase_at(pending_recover, i); + force_recover = check_lost_jobs(c); + } - check_lost_jobs(c); + if (force_recover || (cnt % 50) == 0) + { + recover_jobs(c); } if ((cnt % 500) == 0) @@ -405,10 +377,12 @@ DFhackCExport command_result plugin_onupdate(Core* c) return CR_OK; } -static command_result protect_job(Core *c, vector & parameters) +static command_result workflow_cmd(Core *c, vector & parameters) { CoreSuspender suspend(c); + update_job_data(c); + if (parameters.empty()) return CR_WRONG_USAGE; @@ -424,10 +398,38 @@ static command_result protect_job(Core *c, vector & parameters) std::map jobs; enumLiveJobs(jobs); - update_job_data(c); std::string cmd = parameters[0]; - if (cmd == "list") + + if (cmd == "enable") + { + if (enabled) + { + c->con << "The plugin is already enabled." << endl; + return CR_OK; + } + + enable_plugin(c); + return CR_OK; + } + else if (cmd == "disable") + { + if (!enabled) + { + c->con << "The plugin is already disabled." << endl; + return CR_OK; + } + + enabled = false; + config.ival(0) &= ~CF_ENABLED; + stop_protect(c); + return CR_OK; + } + + if (!enabled) + c->con << "Note: the plugin is not enabled." << endl; + + if (cmd == "list-jobs") { if (workshop) { @@ -457,65 +459,8 @@ static command_result protect_job(Core *c, vector & parameters) printJobDetails(c, pending_recover[i]->job_copy); } } - } - else if (cmd == "add" || cmd == "remove") - { - bool add = (cmd == "add"); - bool all = (parameters.size() >= 2 && parameters[1] == "all"); - if (parameters.size() >= 2 && !all) - return CR_WRONG_USAGE; - - if (workshop && all) - { - for (unsigned i = 0; i < workshop->jobs.size(); i++) - { - df::job *job = workshop->jobs[i]; - if (add) - { - if (!job->flags.bits.repeat) - continue; - remember_job(c, job); - } - else - { - if (ProtectedJob *pj = get_known(job->id)) - forget_job(c, pj); - } - } - } - else if (workshop) - { - if (!job) { - c->con.printerr("No job is selected in the current building.\n"); - return CR_FAILURE; - } - - if (add) - remember_job(c, job); - else if (ProtectedJob *pj = get_known(job->id)) - forget_job(c, pj); - } - else - { - if (!all) { - c->con.printerr("Please either select a job, or specify 'all'.\n"); - return CR_WRONG_USAGE; - } - if (add) - { - for (std::map::iterator it = jobs.begin(); it != jobs.end(); it++) - if (it->second->flags.bits.repeat) - remember_job(c, it->second); - } - else - { - pending_recover.clear(); - - while (!known_jobs.empty()) - forget_job(c, known_jobs.begin()->second); - } - } + return CR_OK; } else return CR_WRONG_USAGE; From ba338be350f632d4d3da3c5d76dabdadbec9bdf9 Mon Sep 17 00:00:00 2001 From: Alexander Gavrilov Date: Mon, 9 Jan 2012 19:20:28 +0400 Subject: [PATCH 37/82] Allow specifying constraints on item amounts, and match jobs to them. --- plugins/workflow.cpp | 319 ++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 297 insertions(+), 22 deletions(-) diff --git a/plugins/workflow.cpp b/plugins/workflow.cpp index 32ca50a82..46e1e740b 100644 --- a/plugins/workflow.cpp +++ b/plugins/workflow.cpp @@ -5,6 +5,7 @@ #include #include +#include #include #include #include @@ -60,8 +61,14 @@ DFhackCExport command_result plugin_init (Core *c, std::vector & " workflow enable\n" " workflow disable\n" " Enable or disable the plugin.\n" - " workflow list-jobs\n" + " workflow jobs\n" " List workflow-controlled jobs (if in a workshop, filtered by it).\n" + " workflow list\n" + " List active constraints, and their job counts.\n" + " workflow limit [cnt-gap]\n" + " Set a constraint.\n" + " workflow unlimit \n" + " Delete a constraint.\n" "Function:\n" " When the plugin is enabled, it protects all repeat jobs from removal.\n" " If they do disappear due to any cause, they are immediately re-added\n" @@ -101,6 +108,8 @@ DFhackCExport command_result plugin_onstatechange(Core* c, state_change_event ev /*******************************/ +struct ItemConstraint; + struct ProtectedJob { int id; int building_id; @@ -110,12 +119,17 @@ struct ProtectedJob { df::building *holder; df::job *job_copy; + df::job *actual_job; + + std::vector constraints; + ProtectedJob(df::job *job) : id(job->id), live(true) { check_idx = 0; holder = getJobHolder(job); building_id = holder ? holder->id : -1; job_copy = cloneJobStruct(job); + actual_job = job; } ~ProtectedJob() @@ -125,6 +139,7 @@ struct ProtectedJob { void update(df::job *job) { + actual_job = job; if (*job == *job_copy) return; @@ -133,6 +148,29 @@ struct ProtectedJob { } }; +struct ItemConstraint { + PersistentDataItem config; + + ItemTypeInfo item; + + MaterialInfo material; + df::job_material_category mat_mask; + + int weight; + std::vector jobs; + + std::map, bool> material_cache; + + int goalCount() { return config.ival(0); } + void setGoalCount(int v) { config.ival(0) = v; } + + int goalGap() { + int gcnt = std::max(1, goalCount()/2); + return std::min(gcnt, config.ival(1) <= 0 ? 5 : config.ival(1)); + } + void setGoalGap(int v) { config.ival(1) = v; } +}; + /*******************************/ static bool enabled = false; @@ -146,6 +184,7 @@ typedef std::map TKnownJobs; static TKnownJobs known_jobs; static std::vector pending_recover; +static std::vector constraints; /*******************************/ @@ -189,9 +228,14 @@ static void cleanup_state(Core *c) config = PersistentDataItem(); stop_protect(c); + + for (unsigned i = 0; i < constraints.size(); i++) + delete constraints[i]; + constraints.clear(); } static bool check_lost_jobs(Core *c); +static ItemConstraint *get_constraint(Core *c, const std::string &str, PersistentDataItem *cfg = NULL); static void start_protect(Core *c) { @@ -208,6 +252,18 @@ static void init_state(Core *c) enabled = config.isValid() && config.ival(0) != -1 && (config.ival(0) & CF_ENABLED); + // Parse constraints + std::vector items; + c->getWorld()->GetPersistentData(&items, "workflow/constraints"); + + for (int i = items.size()-1; i >= 0; i--) { + if (get_constraint(c, items[i].val(), &items[i])) + continue; + + c->con.printerr("Lost constraint %s\n", items[i].val().c_str()); + c->getWorld()->DeletePersistentData(items[i]); + } + if (!enabled) return; @@ -287,6 +343,7 @@ static bool recover_job(Core *c, ProtectedJob *pj) pj->holder->jobs.push_back(recovered); // Done + pj->actual_job = recovered; pj->live = true; return true; } @@ -326,6 +383,7 @@ static bool check_lost_jobs(Core *c) continue; it->second->live = false; + it->second->actual_job = NULL; pending_recover.push_back(it->second); any_lost = true; } @@ -358,33 +416,207 @@ DFhackCExport command_result plugin_onupdate(Core* c) return CR_OK; static unsigned cnt = 0; + static unsigned last_rlen = 0; cnt++; - bool force_recover = false; - if ((cnt % 5) == 0) + if ((cnt % 5) == 0) { + check_lost_jobs(c); + + if (pending_recover.size() != last_rlen || (cnt % 50) == 0) + { + recover_jobs(c); + last_rlen = pending_recover.size(); + + if ((cnt % 500) == 0) + update_job_data(c); + } + } + + return CR_OK; +} + +/*******************************/ + +static ItemConstraint *get_constraint(Core *c, const std::string &str, PersistentDataItem *cfg) +{ + std::vector 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; + + MaterialInfo material; + std::string matstr = vector_get(tokens,1); + 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); + + df::job_material_category mat_mask; + std::string maskstr = vector_get(tokens,2); + 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 && 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; + } + + if (mat_mask.whole != 0) + weight += 100; + + for (unsigned i = 0; i < constraints.size(); i++) { - force_recover = check_lost_jobs(c); + ItemConstraint *ct = constraints[i]; + if (ct->item == item && ct->material == material && + ct->mat_mask.whole == mat_mask.whole) + return ct; } - if (force_recover || (cnt % 50) == 0) + ItemConstraint *nct = new ItemConstraint; + nct->item = item; + nct->material = material; + nct->mat_mask = mat_mask; + nct->weight = weight; + + if (cfg) + nct->config = *cfg; + else { - recover_jobs(c); + nct->config = c->getWorld()->AddPersistentData("workflow/constraints"); + nct->config.val() = str; } - if ((cnt % 500) == 0) - update_job_data(c); + constraints.push_back(nct); + return nct; +} - return CR_OK; +static void delete_constraint(Core *c, ItemConstraint *cv) +{ + int idx = linear_index(constraints, cv); + if (idx >= 0) + vector_erase_at(constraints, idx); + + c->getWorld()->DeletePersistentData(cv->config); + delete cv; +} + +static void print_constraint(Core *c, ItemConstraint *cv, bool no_job = false, std::string prefix = "") +{ + c->con << prefix << "Constraint " << cv->config.val() << ": " + << cv->goalCount() << " (gap " << cv->goalGap() << ")" << endl; + + if (no_job) return; + + if (cv->jobs.empty()) + c->con.printerr(" (no jobs)\n"); + + for (int i = 0; i < cv->jobs.size(); i++) + { + ProtectedJob *pj = cv->jobs[i]; + df::job *job = pj->actual_job; + + c->con << prefix << " job " << job->id << ": " + << ENUM_KEY_STR(job_type, job->job_type); + if (job->flags.bits.suspend) + c->con << " (suspended)"; + c->con << endl; + } +} + +static void print_job(Core *c, ProtectedJob *pj) +{ + if (!pj) + return; + + printJobDetails(c, pj->job_copy); + + for (int i = 0; i < pj->constraints.size(); i++) + print_constraint(c, pj->constraints[i], true, " "); +} + +static void map_job_constraints(Core *c) +{ + for (unsigned i = 0; i < constraints.size(); i++) + constraints[i]->jobs.clear(); + + for (TKnownJobs::const_iterator it = known_jobs.begin(); it != known_jobs.end(); ++it) + { + it->second->constraints.clear(); + + if (!it->second->live) + continue; + + df::job *job = it->second->job_copy; + + df::item_type itype = ENUM_ATTR(job_type, item, job->job_type); + if (itype == item_type::NONE) + continue; + + int16_t isubtype = job->item_subtype; + + int16_t mat_type = job->mat_type; + int32_t mat_index = job->mat_index; + + if (itype == item_type::FOOD) + mat_type = -1; + + if (mat_type == -1 && job->job_items.size() == 1) { + mat_type = job->job_items[0]->mat_type; + mat_index = job->job_items[0]->mat_index; + } + + MaterialInfo mat(mat_type, mat_index); + + for (unsigned i = 0; i < constraints.size(); i++) + { + ItemConstraint *ct = constraints[i]; + + if (ct->item.type != itype || + (ct->item.subtype != -1 && ct->item.subtype != isubtype)) + continue; + if (ct->material.isValid() && ct->material != mat) + continue; + if (ct->mat_mask.whole) + { + if (mat.isValid() && !mat.matches(ct->mat_mask)) + continue; + else if (!(job->material_category.whole & ct->mat_mask.whole)) + continue; + } + + ct->jobs.push_back(it->second); + it->second->constraints.push_back(ct); + } + } } static command_result workflow_cmd(Core *c, vector & parameters) { CoreSuspender suspend(c); - update_job_data(c); - - if (parameters.empty()) - return CR_WRONG_USAGE; + if (enabled) { + check_lost_jobs(c); + recover_jobs(c); + update_job_data(c); + map_job_constraints(c); + } df::building *workshop = NULL; df::job *job = NULL; @@ -396,10 +628,7 @@ static command_result workflow_cmd(Core *c, vector & parameters) job = getSelectedWorkshopJob(c, true); } - std::map jobs; - enumLiveJobs(jobs); - - std::string cmd = parameters[0]; + std::string cmd = parameters.empty() ? "list" : parameters[0]; if (cmd == "enable") { @@ -429,19 +658,18 @@ static command_result workflow_cmd(Core *c, vector & parameters) if (!enabled) c->con << "Note: the plugin is not enabled." << endl; - if (cmd == "list-jobs") + if (cmd == "jobs") { if (workshop) { for (unsigned i = 0; i < workshop->jobs.size(); i++) - if (get_known(workshop->jobs[i]->id)) - printJobDetails(c, workshop->jobs[i]); + print_job(c, get_known(workshop->jobs[i]->id)); } else { for (TKnownJobs::iterator it = known_jobs.begin(); it != known_jobs.end(); ++it) - if (df::job *job = jobs[it->first]) - printJobDetails(c, job); + if (it->second->live) + print_job(c, it->second); } bool pending = false; @@ -462,6 +690,53 @@ static command_result workflow_cmd(Core *c, vector & parameters) return CR_OK; } + else if (cmd == "list") + { + for (int i = 0; i < constraints.size(); i++) + print_constraint(c, constraints[i]); + + return CR_OK; + } + else if (cmd == "limit") + { + if (parameters.size() < 3) + return CR_WRONG_USAGE; + + int limit = atoi(parameters[2].c_str()); + if (limit <= 0) { + c->con.printerr("Invalid limit value.\n"); + return CR_FAILURE; + } + + ItemConstraint *icv = get_constraint(c, parameters[1]); + if (!icv) + return CR_FAILURE; + + icv->setGoalCount(limit); + if (parameters.size() >= 4) + icv->setGoalGap(atoi(parameters[3].c_str())); + + map_job_constraints(c); + print_constraint(c, icv); + return CR_OK; + } + else if (cmd == "unlimit") + { + if (parameters.size() != 2) + return CR_WRONG_USAGE; + + for (int i = 0; i < constraints.size(); i++) + { + if (constraints[i]->config.val() != parameters[1]) + continue; + + delete_constraint(c, constraints[i]); + return CR_OK; + } + + c->con.printerr("Constraint not found: %s\n", parameters[1].c_str()); + return CR_FAILURE; + } else return CR_WRONG_USAGE; } From c3d564dc7a1783431703eccd68bff9cd0042416c Mon Sep 17 00:00:00 2001 From: Alexander Gavrilov Date: Mon, 9 Jan 2012 21:25:55 +0400 Subject: [PATCH 38/82] Count items matching constraints, and suspend/resume jobs based on it. --- plugins/workflow.cpp | 207 +++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 199 insertions(+), 8 deletions(-) diff --git a/plugins/workflow.cpp b/plugins/workflow.cpp index 46e1e740b..464cf468d 100644 --- a/plugins/workflow.cpp +++ b/plugins/workflow.cpp @@ -23,6 +23,7 @@ #include #include #include +#include using std::vector; using std::string; @@ -66,13 +67,25 @@ DFhackCExport command_result plugin_init (Core *c, std::vector & " workflow list\n" " List active constraints, and their job counts.\n" " workflow limit [cnt-gap]\n" - " Set a constraint.\n" + " workflow limit-count [cnt-gap]\n" + " Set a constraint. The second form counts each stack as 1 item.\n" " workflow unlimit \n" " Delete a constraint.\n" "Function:\n" - " When the plugin is enabled, it protects all repeat jobs from removal.\n" - " If they do disappear due to any cause, they are immediately re-added\n" - " to their workshop and suspended.\n" + " - When the plugin is enabled, it protects all repeat jobs from removal.\n" + " If they do disappear due to any cause, they are immediately re-added\n" + " to their workshop and suspended.\n" + " - In addition, when any constraints on item amounts are set, repeat jobs\n" + " that produce that kind of item are automatically suspended and resumed\n" + " as the item amount goes above or below the limit. The gap specifies how\n" + " much below the limit the amount has to drop before jobs are resumed.\n" + "Constraint examples:\n" + " workflow limit AMMO:ITEM_AMMO_BOLTS//WOOD,BONE 200 50\n" + " Keep wooden and bone bolts between 150 and 200.\n" + " workflow limit-count DRINK 120 30\n" + " Keep the number of drink barrels between 90 and 120\n" + " workflow limit-count BIN 30\n" + " Make sure there are always 25-30 empty bins.\n" ) ); } @@ -148,6 +161,8 @@ struct ProtectedJob { } }; +typedef std::map, bool> TMaterialCache; + struct ItemConstraint { PersistentDataItem config; @@ -159,7 +174,12 @@ struct ItemConstraint { int weight; std::vector jobs; - std::map, bool> material_cache; + int item_amount, item_count, item_inuse; + bool request_suspend, request_resume; + + TMaterialCache material_cache; + + ItemConstraint() : weight(0), item_amount(0), item_count(0), item_inuse(0) {} int goalCount() { return config.ival(0); } void setGoalCount(int v) { config.ival(0) = v; } @@ -169,6 +189,27 @@ struct ItemConstraint { return std::min(gcnt, config.ival(1) <= 0 ? 5 : config.ival(1)); } void setGoalGap(int v) { config.ival(1) = v; } + + bool goalByCount() { return config.ival(2) & 1; } + void setGoalByCount(bool v) { + if (v) + config.ival(2) |= 1; + else + config.ival(2) &= ~1; + } + + void init(const std::string &str) + { + config.val() = str; + config.ival(2) = 0; + } + + void computeRequest() + { + int size = goalByCount() ? item_count : item_amount; + request_resume = (size <= goalCount()-goalGap()); + request_suspend = (size >= goalCount()); + } }; /*******************************/ @@ -410,6 +451,8 @@ static void recover_jobs(Core *c) vector_erase_at(pending_recover, i); } +static void process_constraints(Core *c); + DFhackCExport command_result plugin_onupdate(Core* c) { if (!enabled) @@ -419,7 +462,8 @@ DFhackCExport command_result plugin_onupdate(Core* c) static unsigned last_rlen = 0; cnt++; - if ((cnt % 5) == 0) { + if ((cnt % 5) == 0) + { check_lost_jobs(c); if (pending_recover.size() != last_rlen || (cnt % 50) == 0) @@ -428,7 +472,10 @@ DFhackCExport command_result plugin_onupdate(Core* c) last_rlen = pending_recover.size(); if ((cnt % 500) == 0) + { update_job_data(c); + process_constraints(c); + } } } @@ -500,7 +547,7 @@ static ItemConstraint *get_constraint(Core *c, const std::string &str, Persisten else { nct->config = c->getWorld()->AddPersistentData("workflow/constraints"); - nct->config.val() = str; + nct->init(str); } constraints.push_back(nct); @@ -520,8 +567,14 @@ static void delete_constraint(Core *c, ItemConstraint *cv) static void print_constraint(Core *c, ItemConstraint *cv, bool no_job = false, std::string prefix = "") { c->con << prefix << "Constraint " << cv->config.val() << ": " + << (cv->goalByCount() ? "count " : "amount ") << cv->goalCount() << " (gap " << cv->goalGap() << ")" << endl; + if (cv->item_count || cv->item_inuse) + c->con << prefix << " items: amount " << cv->item_amount << "; " + << cv->item_count << " stacks available, " + << cv->item_inuse << " in use." << endl; + if (no_job) return; if (cv->jobs.empty()) @@ -607,6 +660,136 @@ static void map_job_constraints(Core *c) } } +static bool itemNotEmpty(df::item *item) +{ + for (unsigned i = 0; i < item->itemrefs.size(); i++) + if (strict_virtual_cast(item->itemrefs[i])) + return true; + + return false; +} + +static void map_job_items(Core *c) +{ + for (unsigned i = 0; i < constraints.size(); i++) + { + constraints[i]->item_amount = 0; + constraints[i]->item_count = 0; + constraints[i]->item_inuse = 0; + } + + // Precompute a bitmask with the bad flags + df::item_flags bad_flags; + bad_flags.whole = 0; + +#define F(x) bad_flags.bits.x = true; + F(dump); F(forbid); F(garbage_colect); + F(hostile); F(on_fire); F(rotten); F(trader); + F(in_building); F(in_job); +#undef F + + std::vector &items = df::item::get_vector(); + for (unsigned i = 0; i < items.size(); i++) + { + df::item *item = items[i]; + + if (item->flags.whole & bad_flags.whole) + continue; + + bool in_use = item->isAssignedToStockpile() || itemNotEmpty(item); + + df::item_type itype = item->getType(); + int16_t isubtype = item->getSubtype(); + int16_t imattype = item->getActualMaterial(); + int32_t imatindex = item->getActualMaterialIndex(); + + TMaterialCache::key_type matkey(imattype, imatindex); + + for (unsigned i = 0; i < constraints.size(); i++) + { + ItemConstraint *cv = constraints[i]; + if (cv->item.type != itype || + (cv->item.subtype != -1 && cv->item.subtype != isubtype)) + continue; + + TMaterialCache::iterator it = cv->material_cache.find(matkey); + + bool ok = true; + if (it != cv->material_cache.end()) + ok = it->second; + else + { + MaterialInfo mat(imattype, imatindex); + bool ok = (!cv->material.isValid() || mat == cv->material) && + (cv->mat_mask.whole == 0 || (mat.isValid() && mat.matches(cv->mat_mask))); + cv->material_cache[matkey] = ok; + } + + if (!ok) + continue; + + if (in_use) + cv->item_inuse++; + else + { + cv->item_count++; + cv->item_amount += item->getStackSize(); + } + } + } + + for (unsigned i = 0; i < constraints.size(); i++) + constraints[i]->computeRequest(); +} + +static void update_jobs_by_constraints(Core *c) +{ + for (TKnownJobs::const_iterator it = known_jobs.begin(); it != known_jobs.end(); ++it) + { + ProtectedJob *pj = it->second; + if (!pj->live || pj->constraints.empty()) + continue; + + int resume_weight = -1; + int suspend_weight = -1; + + for (unsigned 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->actual_job->flags.bits.suspend; + + if (suspend_weight >= 0 && suspend_weight >= resume_weight) + goal = true; + else if (resume_weight >= 0) + goal = false; + + if (goal != pj->actual_job->flags.bits.suspend) + { + pj->actual_job->flags.bits.suspend = goal; + c->con.print("%s job %d: %s\n", + (goal ? "Suspending" : "Resuming"), pj->id, + ENUM_KEY_STR(job_type, pj->actual_job->job_type)); + } + } +} + +static void process_constraints(Core *c) +{ + if (constraints.empty()) + return; + + map_job_constraints(c); + map_job_items(c); + update_jobs_by_constraints(c); +} + +/*******************************/ + static command_result workflow_cmd(Core *c, vector & parameters) { CoreSuspender suspend(c); @@ -616,6 +799,7 @@ static command_result workflow_cmd(Core *c, vector & parameters) recover_jobs(c); update_job_data(c); map_job_constraints(c); + map_job_items(c); } df::building *workshop = NULL; @@ -654,6 +838,11 @@ static command_result workflow_cmd(Core *c, vector & parameters) stop_protect(c); return CR_OK; } + else if (cmd == "limit" || cmd == "limit-count") + { + if (!enabled) + enable_plugin(c); + } if (!enabled) c->con << "Note: the plugin is not enabled." << endl; @@ -697,7 +886,7 @@ static command_result workflow_cmd(Core *c, vector & parameters) return CR_OK; } - else if (cmd == "limit") + else if (cmd == "limit" || cmd == "limit-count") { if (parameters.size() < 3) return CR_WRONG_USAGE; @@ -712,11 +901,13 @@ static command_result workflow_cmd(Core *c, vector & parameters) if (!icv) return CR_FAILURE; + icv->setGoalByCount(cmd == "limit-count"); icv->setGoalCount(limit); if (parameters.size() >= 4) icv->setGoalGap(atoi(parameters[3].c_str())); map_job_constraints(c); + map_job_items(c); print_constraint(c, icv); return CR_OK; } From 571498ea2100ae84b360c1ef54f727404be20986 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Mr=C3=A1zek?= Date: Tue, 10 Jan 2012 00:45:43 +0100 Subject: [PATCH 39/82] Vermin tweaks. --- library/include/modules/Vermin.h | 10 +++------- library/modules/Vermin.cpp | 15 ++++++--------- library/xml | 2 +- plugins/colonies.cpp | 11 ++++++----- 4 files changed, 16 insertions(+), 22 deletions(-) diff --git a/library/include/modules/Vermin.h b/library/include/modules/Vermin.h index bcec96b51..9ca2730d8 100644 --- a/library/include/modules/Vermin.h +++ b/library/include/modules/Vermin.h @@ -13,13 +13,13 @@ namespace DFHack { namespace Simple { namespace Vermin { void * origin; int16_t race; - uint16_t type; + int16_t caste; uint16_t x; uint16_t y; uint16_t z; - bool in_use; - uint8_t unknown; uint32_t countdown; + bool visible:1; + bool is_colony:1; /// Is vermin object a colony? }; static const uint16_t TYPE_WILD_COLONY = 0xFFFF; @@ -35,8 +35,4 @@ namespace DFHack { namespace Simple { namespace Vermin * Write into vermin object */ DFHACK_EXPORT bool Write (const uint32_t index, t_vermin & point); - /** - * Is vermin object a colony? - */ - DFHACK_EXPORT bool isWildColony(t_vermin & point); } } } // end DFHack::Simple::Vermin diff --git a/library/modules/Vermin.cpp b/library/modules/Vermin.cpp index 31e156e22..6b83d76bb 100644 --- a/library/modules/Vermin.cpp +++ b/library/modules/Vermin.cpp @@ -57,12 +57,13 @@ bool Vermin::Read (const uint32_t index, t_vermin & sp) sp.origin = verm; sp.race = verm->race; - sp.type = verm->type; - sp.in_use = verm->in_use; + sp.caste = verm->caste; + sp.visible = verm->visible; sp.countdown = verm->countdown; sp.x = verm->x; sp.y = verm->y; sp.z = verm->z; + sp.is_colony = verm->flags.bits.is_colony; return true; } @@ -72,16 +73,12 @@ bool Vermin::Write (const uint32_t index, t_vermin & sp) if (!verm) return false; verm->race = sp.race; - verm->type = sp.type; - verm->in_use = sp.in_use; + verm->caste = sp.caste; + verm->visible = sp.visible; verm->countdown = sp.countdown; verm->x = sp.x; verm->y = sp.y; verm->z = sp.z; + verm->flags.bits.is_colony = sp.is_colony; return true; } - -bool Vermin::isWildColony(t_vermin & point) -{ - return (point.type == TYPE_WILD_COLONY); -} diff --git a/library/xml b/library/xml index 85dfa3550..f7903623e 160000 --- a/library/xml +++ b/library/xml @@ -1 +1 @@ -Subproject commit 85dfa3550fe204c8c75279335cae1457cf03e0ed +Subproject commit f7903623ec2f69759debd2974b037463cc46efff diff --git a/plugins/colonies.cpp b/plugins/colonies.cpp index 73106b966..3089b7ccd 100644 --- a/plugins/colonies.cpp +++ b/plugins/colonies.cpp @@ -88,6 +88,7 @@ DFhackCExport command_result colonies (Core * c, vector & parameters) return CR_OK; } +//FIXME: this is probably bullshit void destroyColonies() { uint32_t numSpawnPoints = Vermin::getNumVermin(); @@ -96,9 +97,9 @@ void destroyColonies() Vermin::t_vermin sp; Vermin::Read(i, sp); - if (sp.in_use && Vermin::isWildColony(sp)) + if (sp.visible && sp.is_colony) { - sp.in_use = false; + sp.visible = false; Vermin::Write(i, sp); } } @@ -127,7 +128,7 @@ void convertColonies(DFHack::Materials *Materials) Vermin::t_vermin sp; Vermin::Read(i, sp); - if (sp.in_use && Vermin::isWildColony(sp)) + if (sp.visible && sp.is_colony) { sp.race = bee_idx; Vermin::Write(i, sp); @@ -145,14 +146,14 @@ void showColonies(Core *c, DFHack::Materials *Materials) Vermin::Read(i, sp); - if (sp.in_use && Vermin::isWildColony(sp)) + if (sp.visible && sp.is_colony) { numColonies++; string race="(no race)"; if(sp.race != -1) race = Materials->raceEx[sp.race].id; - c->con.print("Spawn point %u: %s at %d:%d:%d\n", i, + c->con.print("Colony %u: %s at %d:%d:%d\n", i, race.c_str(), sp.x, sp.y, sp.z); } } From 7f5aa4de62931d7c5dad2630103803d7ec14e208 Mon Sep 17 00:00:00 2001 From: Alexander Gavrilov Date: Tue, 10 Jan 2012 17:23:37 +0400 Subject: [PATCH 40/82] Support the most important job types in workflow. --- library/include/modules/Materials.h | 10 + library/modules/Items.cpp | 2 +- library/modules/Materials.cpp | 51 +++- library/xml | 2 +- plugins/jobutils.cpp | 9 +- plugins/workflow.cpp | 428 ++++++++++++++++++++++------ 6 files changed, 402 insertions(+), 100 deletions(-) diff --git a/library/include/modules/Materials.h b/library/include/modules/Materials.h index e1455c158..7bc56d1fc 100644 --- a/library/include/modules/Materials.h +++ b/library/include/modules/Materials.h @@ -51,6 +51,7 @@ namespace df struct job_item; union job_material_category; + union dfhack_material_category; union job_item_flags1; union job_item_flags2; union job_item_flags3; @@ -118,11 +119,20 @@ namespace DFHack df::craft_material_class getCraftClass(); + bool matches(const MaterialInfo &mat) + { + if (!mat.isValid()) return true; + return (type == mat.type) && + (mat.index == -1 || index == mat.index); + } + bool matches(const df::job_material_category &cat); + bool matches(const df::dfhack_material_category &cat); bool matches(const df::job_item &item); }; DFHACK_EXPORT bool parseJobMaterialCategory(df::job_material_category *cat, const std::string &token); + DFHACK_EXPORT bool parseJobMaterialCategory(df::dfhack_material_category *cat, const std::string &token); inline bool operator== (const MaterialInfo &a, const MaterialInfo &b) { return a.type == b.type && a.index == b.index; diff --git a/library/modules/Items.cpp b/library/modules/Items.cpp index fb2ae6655..8ec4e2301 100644 --- a/library/modules/Items.cpp +++ b/library/modules/Items.cpp @@ -187,7 +187,7 @@ bool ItemTypeInfo::matches(const df::job_item &item, MaterialInfo *mat) using namespace df::enums::item_type; if (!isValid()) - return mat ? mat->matches(item) : true; + return mat ? mat->matches(item) : false; df::job_item_flags1 ok1, mask1, item_ok1, item_mask1; df::job_item_flags2 ok2, mask2, item_ok2, item_mask2; diff --git a/library/modules/Materials.cpp b/library/modules/Materials.cpp index 716717230..cc9102ae5 100644 --- a/library/modules/Materials.cpp +++ b/library/modules/Materials.cpp @@ -52,6 +52,7 @@ using namespace std; #include "df/job_item.h" #include "df/job_material_category.h" +#include "df/dfhack_material_category.h" #include "df/matter_state.h" #include "df/material_vec_ref.h" @@ -314,8 +315,9 @@ bool MaterialInfo::matches(const df::job_material_category &cat) if (!material) return false; - using namespace df::enums::material_flags; #define TEST(bit,flag) if (cat.bits.bit && material->flags.is_set(flag)) return true; + + using namespace df::enums::material_flags; TEST(plant, STRUCTURAL_PLANT_MAT); TEST(wood, WOOD); TEST(cloth, THREAD_PLANT); @@ -329,13 +331,37 @@ bool MaterialInfo::matches(const df::job_material_category &cat) TEST(horn, HORN); TEST(pearl, PEARL); TEST(yarn, YARN); -#undef TEST return false; } +bool MaterialInfo::matches(const df::dfhack_material_category &cat) +{ + if (!material) + return false; + + df::job_material_category mc; + mc.whole = cat.whole; + if (matches(mc)) + return true; + + using namespace df::enums::material_flags; + using namespace df::enums::inorganic_flags; + TEST(metal, IS_METAL); + TEST(stone, IS_STONE); + if (cat.bits.stone && type == 0 && index == -1) + return true; + if (cat.bits.sand && inorganic && inorganic->flags.is_set(SOIL_SAND)) + return true; + TEST(glass, IS_GLASS); + if (cat.bits.clay && linear_index(material->reaction_product.id, std::string("FIRED_MAT")) >= 0) + return true; +} + +#undef TEST + bool MaterialInfo::matches(const df::job_item &item) { - if (!isValid()) return true; + if (!isValid()) return false; df::job_item_flags1 ok1, mask1; getMatchBits(ok1, mask1); @@ -449,6 +475,25 @@ bool DFHack::parseJobMaterialCategory(df::job_material_category *cat, const std: return true; } +bool DFHack::parseJobMaterialCategory(df::dfhack_material_category *cat, const std::string &token) +{ + cat->whole = 0; + + std::vector items; + split_string(&items, toLower(token), ",", true); + + for (unsigned i = 0; i < items.size(); i++) + { + int id = findBitfieldField(*cat, items[i]); + if (id < 0) + return false; + + cat->whole |= (1 << id); + } + + return true; +} + Module* DFHack::createMaterials() { return new Materials(); diff --git a/library/xml b/library/xml index f7903623e..9bbec980c 160000 --- a/library/xml +++ b/library/xml @@ -1 +1 @@ -Subproject commit f7903623ec2f69759debd2974b037463cc46efff +Subproject commit 9bbec980c28d296ce80813cb1bfc4dd31c19266d diff --git a/plugins/jobutils.cpp b/plugins/jobutils.cpp index 29d86230c..8557f0102 100644 --- a/plugins/jobutils.cpp +++ b/plugins/jobutils.cpp @@ -268,7 +268,10 @@ static command_result job_duplicate(Core * c, vector & parameters) if (!job) return CR_FAILURE; - if (!job->misc_links.empty() || job->job_items.empty()) + if (!job->misc_links.empty() || + (job->job_items.empty() && + job->job_type != job_type::CollectSand && + job->job_type != job_type::CollectClay)) { c->con.printerr("Cannot duplicate job %s\n", ENUM_KEY_STR(job_type,job->job_type)); return CR_FAILURE; @@ -343,7 +346,7 @@ static command_result job_cmd(Core * c, vector & parameters) return CR_FAILURE; } - if (!iinfo.matches(*item, &minfo)) { + if (minfo.isValid() && !iinfo.matches(*item, &minfo)) { c->con.printerr("Material does not match the requirements.\n"); printJobDetails(c, job); return CR_FAILURE; @@ -387,7 +390,7 @@ static command_result job_cmd(Core * c, vector & parameters) return CR_FAILURE; } - if (!iinfo.matches(*item, &minfo)) { + if (iinfo.isValid() && !iinfo.matches(*item, &minfo)) { c->con.printerr("Item type does not match the requirements.\n"); printJobDetails(c, job); return CR_FAILURE; diff --git a/plugins/workflow.cpp b/plugins/workflow.cpp index 464cf468d..a874cd45a 100644 --- a/plugins/workflow.cpp +++ b/plugins/workflow.cpp @@ -18,12 +18,19 @@ #include #include #include +#include #include #include #include #include #include #include +#include +#include +#include +#include +#include +#include using std::vector; using std::string; @@ -78,14 +85,30 @@ DFhackCExport command_result plugin_init (Core *c, std::vector & " - In addition, when any constraints on item amounts are set, repeat jobs\n" " that produce that kind of item are automatically suspended and resumed\n" " as the item amount goes above or below the limit. The gap specifies how\n" - " much below the limit the amount has to drop before jobs are resumed.\n" + " much below the limit the amount has to drop before jobs are resumed;\n" + " this is intended to reduce the frequency of jobs being toggled.\n" "Constraint examples:\n" - " workflow limit AMMO:ITEM_AMMO_BOLTS//WOOD,BONE 200 50\n" - " Keep wooden and bone bolts between 150 and 200.\n" + " workflow limit AMMO:ITEM_AMMO_BOLTS/METAL 1000 100\n" + " workflow limit AMMO:ITEM_AMMO_BOLTS/WOOD,BONE 200 50\n" + " Keep metal bolts within 900-1000, and wood/bone within 150-200.\n" + " workflow limit-count FOOD 120 30\n" " workflow limit-count DRINK 120 30\n" - " Keep the number of drink barrels between 90 and 120\n" - " workflow limit-count BIN 30\n" - " Make sure there are always 25-30 empty bins.\n" + " Keep the number of prepared food & drink stacks between 90 and 120\n" + " workflow limit BIN 30\n" + " workflow limit BARREL 30\n" + " workflow limit BOX/CLOTH,SILK,YARN 30\n" + " Make sure there are always 25-30 empty bins/barrels/bags.\n" + " workflow limit BAR//COAL 20\n" + " workflow limit BAR//COPPER 30\n" + " Make sure there are always 15-20 coal and 25-30 copper bars.\n" + " workflow limit-count POWDER_MISC/SAND 20\n" + " workflow limit-count BOULDER/CLAY 20\n" + " Collect 15-20 sand bags and clay boulders.\n" + " workflow limit POWDER_MISC//MUSHROOM_CUP_DIMPLE:MILL 100 20\n" + " Make sure there are always 80-100 units of dimple dye.\n" + " In order for this to work, you have to set the material of\n" + " the PLANT input on the Mill Plants job to MUSHROOM_CUP_DIMPLE\n" + " using the 'job item-material' command.\n" ) ); } @@ -131,6 +154,7 @@ struct ProtectedJob { bool live; df::building *holder; df::job *job_copy; + int reaction_id; df::job *actual_job; @@ -143,6 +167,7 @@ struct ProtectedJob { building_id = holder ? holder->id : -1; job_copy = cloneJobStruct(job); actual_job = job; + reaction_id = -1; } ~ProtectedJob() @@ -156,6 +181,7 @@ struct ProtectedJob { if (*job == *job_copy) return; + reaction_id = -1; deleteJobStruct(job_copy); job_copy = cloneJobStruct(job); } @@ -169,7 +195,7 @@ struct ItemConstraint { ItemTypeInfo item; MaterialInfo material; - df::job_material_category mat_mask; + df::dfhack_material_category mat_mask; int weight; std::vector jobs; @@ -238,8 +264,10 @@ static ProtectedJob *get_known(int id) static bool isSupportedJob(df::job *job) { return job->misc_links.empty() && - !job->job_items.empty() && - getJobHolder(job); + getJobHolder(job) && + (!job->job_items.empty() || + job->job_type == job_type::CollectClay || + job->job_type == job_type::CollectSand); } static void enumLiveJobs(std::map &rv) @@ -503,8 +531,18 @@ static ItemConstraint *get_constraint(Core *c, const std::string &str, Persisten 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,1); + 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; @@ -513,21 +551,11 @@ static ItemConstraint *get_constraint(Core *c, const std::string &str, Persisten if (material.type >= 0) weight += (material.index >= 0 ? 5000 : 1000); - df::job_material_category mat_mask; - std::string maskstr = vector_get(tokens,2); - 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 && 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; } - if (mat_mask.whole != 0) - weight += 100; - for (unsigned i = 0; i < constraints.size(); i++) { ItemConstraint *ct = constraints[i]; @@ -564,99 +592,241 @@ static void delete_constraint(Core *c, ItemConstraint *cv) delete cv; } -static void print_constraint(Core *c, ItemConstraint *cv, bool no_job = false, std::string prefix = "") +static void link_job_constraint(ProtectedJob *pj, df::item_type itype, int16_t isubtype, + df::dfhack_material_category mat_mask, + int16_t mat_type, int32_t mat_index) { - c->con << prefix << "Constraint " << cv->config.val() << ": " - << (cv->goalByCount() ? "count " : "amount ") - << cv->goalCount() << " (gap " << cv->goalGap() << ")" << endl; - - if (cv->item_count || cv->item_inuse) - c->con << prefix << " items: amount " << cv->item_amount << "; " - << cv->item_count << " stacks available, " - << cv->item_inuse << " in use." << endl; + MaterialInfo mat(mat_type, mat_index); - if (no_job) return; + for (unsigned i = 0; i < constraints.size(); i++) + { + ItemConstraint *ct = constraints[i]; - if (cv->jobs.empty()) - c->con.printerr(" (no jobs)\n"); + if (ct->item.type != itype || + (ct->item.subtype != -1 && ct->item.subtype != isubtype)) + continue; + if (!mat.matches(ct->material)) + continue; + if (ct->mat_mask.whole) + { + if (mat.isValid()) + { + if (!mat.matches(ct->mat_mask)) + continue; + } + else + { + if (!(mat_mask.whole & ct->mat_mask.whole)) + continue; + } + } - for (int i = 0; i < cv->jobs.size(); i++) - { - ProtectedJob *pj = cv->jobs[i]; - df::job *job = pj->actual_job; + if (linear_index(pj->constraints, ct) >= 0) + continue; - c->con << prefix << " job " << job->id << ": " - << ENUM_KEY_STR(job_type, job->job_type); - if (job->flags.bits.suspend) - c->con << " (suspended)"; - c->con << endl; + ct->jobs.push_back(pj); + pj->constraints.push_back(ct); } } -static void print_job(Core *c, ProtectedJob *pj) +static void compute_custom_job(ProtectedJob *pj, df::job *job) { - if (!pj) + 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; - printJobDetails(c, pj->job_copy); + for (unsigned i = 0; i < r->products.size(); i++) + { + using namespace df::enums::reaction_product_item_flags; - for (int i = 0; i < pj->constraints.size(); i++) - print_constraint(c, pj->constraints[i], true, " "); + VIRTUAL_CAST_VAR(prod, df::reaction_product_itemst, r->products[i]); + if (!prod || prod->item_type < 0) + continue; + + MaterialInfo mat(prod); + + 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) + { + if (!mat.isValid()) + continue; + + int idx = linear_index(mat.material->reaction_product.id, + prod->get_material.product_code); + if (idx < 0) + continue; + + mat.decode(mat.material->reaction_product.material, idx); + } + } + + link_job_constraint(pj, prod->item_type, prod->item_subtype, + 0, mat.type, mat.index); + } } -static void map_job_constraints(Core *c) +static void guess_job_material(df::job *job, MaterialInfo &mat, df::dfhack_material_category &mat_mask) { - for (unsigned i = 0; i < constraints.size(); i++) - constraints[i]->jobs.clear(); + using namespace df::enums::job_type; - for (TKnownJobs::const_iterator it = known_jobs.begin(); it != known_jobs.end(); ++it) + 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) { - it->second->constraints.clear(); + MaterialInfo info; + if (info.findBuiltin(job_material)) + mat = info; + else + parseJobMaterialCategory(&mat_mask, job_material); + } - if (!it->second->live) - continue; + // Material from the job reagent + if (!mat.isValid() && job->job_items.size() == 1) + { + 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; + } + } +} - df::job *job = it->second->job_copy; +static void compute_job_outputs(Core *c, ProtectedJob *pj) +{ + using namespace df::enums::job_type; - df::item_type itype = ENUM_ATTR(job_type, item, job->job_type); - if (itype == item_type::NONE) - continue; + // Custom reactions handled in another function + df::job *job = pj->job_copy; - int16_t isubtype = job->item_subtype; + if (job->job_type == CustomReaction) + { + compute_custom_job(pj, job); + return; + } - int16_t mat_type = job->mat_type; - int32_t mat_index = job->mat_index; + // 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) + return; - if (itype == item_type::FOOD) - mat_type = -1; + // Item material & material category + MaterialInfo mat; + df::dfhack_material_category mat_mask; + guess_job_material(job, mat, mat_mask); - if (mat_type == -1 && job->job_items.size() == 1) { - mat_type = job->job_items[0]->mat_type; - mat_index = job->job_items[0]->mat_index; + // Job-specific code + switch (job->job_type) + { + case SmeltOre: + if (mat.inorganic) + { + std::vector &ores = mat.inorganic->metal_ore.mat_index; + for (unsigned i = 0; i < ores.size(); i++) + link_job_constraint(pj, item_type::BAR, -1, 0, 0, ores[i]); } + return; - MaterialInfo mat(mat_type, mat_index); + case ExtractMetalStrands: + if (mat.inorganic) + { + std::vector &threads = mat.inorganic->thread_metal.mat_index; + for (unsigned i = 0; i < threads.size(); i++) + link_job_constraint(pj, item_type::THREAD, -1, 0, 0, threads[i]); + } + return; - for (unsigned i = 0; i < constraints.size(); i++) + case PrepareMeal: + if (job->mat_type != -1) { - ItemConstraint *ct = constraints[i]; + std::vector &food = df::itemdef_foodst::get_vector(); + for (unsigned 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; - if (ct->item.type != itype || - (ct->item.subtype != -1 && ct->item.subtype != isubtype)) - continue; - if (ct->material.isValid() && ct->material != mat) - continue; - if (ct->mat_mask.whole) - { - if (mat.isValid() && !mat.matches(ct->mat_mask)) - continue; - else if (!(job->material_category.whole & ct->mat_mask.whole)) - continue; - } +#define PLANT_PROCESS_MAT(flag, tag) \ + if (!mat.isValid() && !job->job_items.empty()\ + && job->job_items[0]->item_type == item_type::PLANT) \ + mat.decode(job->job_items[0]); \ + 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 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 - ct->jobs.push_back(it->second); - it->second->constraints.push_back(ct); - } + default: + break; + } + + link_job_constraint(pj, itype, isubtype, mat_mask, mat.type, mat.index); +} + +static void map_job_constraints(Core *c) +{ + for (unsigned i = 0; i < constraints.size(); i++) + constraints[i]->jobs.clear(); + + for (TKnownJobs::const_iterator it = known_jobs.begin(); it != known_jobs.end(); ++it) + { + it->second->constraints.clear(); + + if (!it->second->live) + continue; + + compute_job_outputs(c, it->second); } } @@ -669,6 +839,20 @@ static bool itemNotEmpty(df::item *item) return false; } +static bool itemInRealJob(df::item *item) +{ + if (!item->flags.bits.in_job) + return false; + + if (item->jobs.size() != 1 || + item->jobs[0]->unk1 != 2 || + item->jobs[0]->job == NULL) + return true; + + return ENUM_ATTR(job_type, type, item->jobs[0]->job->job_type) + != job_type_class::Hauling; +} + static void map_job_items(Core *c) { for (unsigned i = 0; i < constraints.size(); i++) @@ -685,7 +869,7 @@ static void map_job_items(Core *c) #define F(x) bad_flags.bits.x = true; F(dump); F(forbid); F(garbage_colect); F(hostile); F(on_fire); F(rotten); F(trader); - F(in_building); F(in_job); + F(in_building); F(artifact1); #undef F std::vector &items = df::item::get_vector(); @@ -695,8 +879,8 @@ static void map_job_items(Core *c) if (item->flags.whole & bad_flags.whole) continue; - - bool in_use = item->isAssignedToStockpile() || itemNotEmpty(item); + if (itemInRealJob(item)) + continue; df::item_type itype = item->getType(); int16_t isubtype = item->getSubtype(); @@ -720,16 +904,20 @@ static void map_job_items(Core *c) else { MaterialInfo mat(imattype, imatindex); - bool ok = (!cv->material.isValid() || mat == cv->material) && - (cv->mat_mask.whole == 0 || (mat.isValid() && mat.matches(cv->mat_mask))); + ok = mat.matches(cv->material) && + (cv->mat_mask.whole == 0 || mat.matches(cv->mat_mask)); cv->material_cache[matkey] = ok; } if (!ok) continue; - if (in_use) + if (item->flags.bits.owned || + item->isAssignedToStockpile() || + itemNotEmpty(item)) + { cv->item_inuse++; + } else { cv->item_count++; @@ -763,10 +951,10 @@ static void update_jobs_by_constraints(Core *c) bool goal = pj->actual_job->flags.bits.suspend; - if (suspend_weight >= 0 && suspend_weight >= resume_weight) - goal = true; - else if (resume_weight >= 0) + if (resume_weight >= 0 && resume_weight >= suspend_weight) goal = false; + else if (suspend_weight >= 0 && suspend_weight >= resume_weight) + goal = true; if (goal != pj->actual_job->flags.bits.suspend) { @@ -790,6 +978,60 @@ static void process_constraints(Core *c) /*******************************/ +static void print_constraint(Core *c, ItemConstraint *cv, bool no_job = false, std::string prefix = "") +{ + c->con << prefix << "Constraint " << cv->config.val() << ": " + << (cv->goalByCount() ? "count " : "amount ") + << cv->goalCount() << " (gap " << cv->goalGap() << ")" << endl; + + if (cv->item_count || cv->item_inuse) + c->con << prefix << " items: amount " << cv->item_amount << "; " + << cv->item_count << " stacks available, " + << cv->item_inuse << " in use." << endl; + + if (no_job) return; + + if (cv->jobs.empty()) + c->con.printerr(" (no jobs)\n"); + + for (int i = 0; i < cv->jobs.size(); i++) + { + ProtectedJob *pj = cv->jobs[i]; + df::job *job = pj->actual_job; + + c->con << prefix << " job " << job->id << ": "; + + if (job->job_type != job_type::CustomReaction) + c->con << ENUM_KEY_STR(job_type, job->job_type); + else + c->con << job->reaction_name; + + MaterialInfo mat; + df::dfhack_material_category mat_mask; + guess_job_material(job, mat, mat_mask); + + if (mat.isValid()) + c->con << " [" << mat.toString() << "]"; + else if (mat_mask.whole) + c->con << " [" << bitfieldToString(mat_mask) << "]"; + + if (job->flags.bits.suspend) + c->con << " (suspended)"; + c->con << endl; + } +} + +static void print_job(Core *c, ProtectedJob *pj) +{ + if (!pj) + return; + + printJobDetails(c, pj->job_copy); + + for (int i = 0; i < pj->constraints.size(); i++) + print_constraint(c, pj->constraints[i], true, " "); +} + static command_result workflow_cmd(Core *c, vector & parameters) { CoreSuspender suspend(c); @@ -905,6 +1147,8 @@ static command_result workflow_cmd(Core *c, vector & parameters) icv->setGoalCount(limit); if (parameters.size() >= 4) icv->setGoalGap(atoi(parameters[3].c_str())); + else + icv->setGoalGap(-1); map_job_constraints(c); map_job_items(c); From 1d4b9ac318717d0f20b526388d957a51e996f503 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Mr=C3=A1zek?= Date: Tue, 10 Jan 2012 19:47:48 +0100 Subject: [PATCH 41/82] Track structures --- library/xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/xml b/library/xml index f7903623e..9799fc70b 160000 --- a/library/xml +++ b/library/xml @@ -1 +1 @@ -Subproject commit f7903623ec2f69759debd2974b037463cc46efff +Subproject commit 9799fc70b8389ddc0e73805f528dbd7b223653e5 From 24576ffe19c48651f4c683015ab80b763f73294f Mon Sep 17 00:00:00 2001 From: Quietust Date: Wed, 11 Jan 2012 08:54:54 -0600 Subject: [PATCH 42/82] Silence annoying warning in MSVC --- library/include/PluginManager.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/include/PluginManager.h b/library/include/PluginManager.h index 726734baa..d14f4d99a 100644 --- a/library/include/PluginManager.h +++ b/library/include/PluginManager.h @@ -43,7 +43,7 @@ namespace DFHack { class Core; class PluginManager; - struct virtual_identity; + class virtual_identity; enum command_result { From 1f8a00581817c8003fd4dcba88d57666d8d7c33b Mon Sep 17 00:00:00 2001 From: Quietust Date: Wed, 11 Jan 2012 08:58:26 -0600 Subject: [PATCH 43/82] Update cleaners/drybuckets, Materials module now gone --- plugins/cleaners.cpp | 7 +++---- plugins/drybuckets.cpp | 5 ++--- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/plugins/cleaners.cpp b/plugins/cleaners.cpp index c25a1ed33..f25c5ae87 100644 --- a/plugins/cleaners.cpp +++ b/plugins/cleaners.cpp @@ -12,8 +12,7 @@ #include "df/unit.h" #include "df/matter_state.h" #include "df/cursor.h" - -#include "modules/Materials.h" +#include "df/builtin_mats.h" using std::vector; using std::string; @@ -48,12 +47,12 @@ command_result cleanmap (Core * c, bool snow, bool mud) // filter snow if(!snow - && spatter->mat_type == DFHack::Materials::WATER + && spatter->mat_type == df::builtin_mats::WATER && spatter->mat_state == df::matter_state::Powder) continue; // filter mud if(!mud - && spatter->mat_type == DFHack::Materials::MUD + && spatter->mat_type == df::builtin_mats::MUD && spatter->mat_state == df::matter_state::Solid) continue; diff --git a/plugins/drybuckets.cpp b/plugins/drybuckets.cpp index 09456c01c..c824ddfe9 100644 --- a/plugins/drybuckets.cpp +++ b/plugins/drybuckets.cpp @@ -8,8 +8,7 @@ #include #include "df/world.h" #include "df/item.h" - -#include "modules/Materials.h" +#include "df/builtin_mats.h" using std::string; using std::vector; @@ -28,7 +27,7 @@ DFhackCExport command_result df_drybuckets (Core * c, vector & paramete for (int i = 0; i < world->items.all.size(); i++) { df::item *item = world->items.all[i]; - if ((item->getType() == df::item_type::LIQUID_MISC) && (item->getMaterial() == DFHack::Materials::WATER)) + if ((item->getType() == df::item_type::LIQUID_MISC) && (item->getMaterial() == df::builtin_mats::WATER)) { item->flags.bits.garbage_colect = 1; dried_total++; From 524b53935d0392e7f85f81c18498581cd4fab65e Mon Sep 17 00:00:00 2001 From: Quietust Date: Wed, 11 Jan 2012 09:53:28 -0600 Subject: [PATCH 44/82] block_index is declared correctly now --- plugins/cleaners.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/plugins/cleaners.cpp b/plugins/cleaners.cpp index f25c5ae87..52b92de6f 100644 --- a/plugins/cleaners.cpp +++ b/plugins/cleaners.cpp @@ -120,8 +120,7 @@ df::map_block *getBlock (int32_t x, int32_t y, int32_t z) return NULL; if ((x >= world->map.x_count) || (y >= world->map.y_count) || (z >= world->map.z_count)) return NULL; - // block_index isn't declared correctly - needs one more level of indirection - return ((df::map_block ****)world->map.block_index)[x >> 4][y >> 4][z]; + return world->map.block_index[x >> 4][y >> 4][z]; } DFhackCExport command_result spotclean (Core * c, vector & parameters) From 9cc774fc9da403ae65e2c89667f0dd8eda8ede2f Mon Sep 17 00:00:00 2001 From: Quietust Date: Wed, 11 Jan 2012 09:53:48 -0600 Subject: [PATCH 45/82] Update deramp plugin, no longer relies on modules --- plugins/deramp.cpp | 196 ++++++++++++++++++--------------------------- 1 file changed, 76 insertions(+), 120 deletions(-) diff --git a/plugins/deramp.cpp b/plugins/deramp.cpp index c5b1c8558..72801b77a 100644 --- a/plugins/deramp.cpp +++ b/plugins/deramp.cpp @@ -1,158 +1,114 @@ // De-ramp. All ramps marked for removal are replaced with given tile (presently, normal floor). -#include -#include -#include -#include -#include -#include -using namespace std; #include "Core.h" #include #include #include -#include -#include -using namespace DFHack; -DFhackCExport command_result df_deramp (Core * c, vector & parameters); +#include "DataDefs.h" +#include "df/world.h" +#include "df/map_block.h" +#include "df/tile_dig_designation.h" +#include -DFhackCExport const char * plugin_name ( void ) -{ - return "deramp"; -} +using std::vector; +using std::string; +using namespace DFHack; -DFhackCExport command_result plugin_init ( Core * c, std::vector &commands) -{ - commands.clear(); - commands.push_back(PluginCommand("deramp", - "De-ramp. All ramps marked for removal are replaced with floors.", - df_deramp)); - return CR_OK; -} +using df::global::world; +using namespace DFHack; -DFhackCExport command_result plugin_shutdown ( Core * c ) +// This is slightly different from what's in the Maps module - it takes tile coordinates rather than block coordinates +df::map_block *getBlock (int32_t x, int32_t y, int32_t z) { - return CR_OK; + if ((x < 0) || (y < 0) || (z < 0)) + return NULL; + if ((x >= world->map.x_count) || (y >= world->map.y_count) || (z >= world->map.z_count)) + return NULL; + return world->map.block_index[x >> 4][y >> 4][z]; } DFhackCExport command_result df_deramp (Core * c, vector & parameters) { - uint32_t x_max,y_max,z_max; - uint32_t num_blocks = 0; - uint32_t bytes_read = 0; - DFHack::designations40d designations; - DFHack::tiletypes40d tiles; - DFHack::tiletypes40d tilesAbove; - - //DFHack::TileRow *ptile; - int32_t oldT, newT; - - bool dirty= false; - int count=0; - int countbad=0; for(int i = 0; i < parameters.size();i++) { if(parameters[i] == "help" || parameters[i] == "?") { c->con.print("This command does two things:\n" - "If there are any ramps designated for removal, they will be instantly removed.\n" - "Any ramps that don't have their counterpart will be removed (fixes bugs with caveins)\n" - ); + "If there are any ramps designated for removal, they will be instantly removed.\n" + "Any ramps that don't have their counterpart will be removed (fixes bugs with caveins)\n" + ); return CR_OK; } } - c->Suspend(); - DFHack::Maps *Mapz = c->getMaps(); - - // init the map - if (!Mapz->Start()) - { - c->con.printerr("Can't init map.\n"); - c->Resume(); - return CR_FAILURE; - } - Mapz->getSize(x_max,y_max,z_max); + CoreSuspender suspend(c); - uint8_t zeroes [16][16] = {0}; + int count = 0; + int countbad = 0; - // walk the map - for (uint32_t x = 0; x< x_max;x++) + int num_blocks = 0, blocks_total = world->map.map_blocks.size(); + for (int i = 0; i < blocks_total; i++) { - for (uint32_t y = 0; y< y_max;y++) + df::map_block *block = world->map.map_blocks[i]; + df::map_block *above = getBlock(block->map_x, block->map_y, block->map_z + 1); + + for (int x = 0; x < 16; x++) { - for (uint32_t z = 0; z< z_max;z++) + for (int y = 0; y < 16; y++) { - if (Mapz->getBlock(x,y,z)) + int16_t oldT = block->tiletype[x][y]; + if ((tileShape(oldT) == RAMP) && + (block->designation[x][y].bits.dig == df::tile_dig_designation::Default)) { - dirty= false; - Mapz->ReadDesignations(x,y,z, &designations); - Mapz->ReadTileTypes(x,y,z, &tiles); - if (Mapz->getBlock(x,y,z+1)) - { - Mapz->ReadTileTypes(x,y,z+1, &tilesAbove); - } - else - { - memset(&tilesAbove,0,sizeof(tilesAbove)); - } - - for (uint32_t ty=0;ty<16;++ty) - { - for (uint32_t tx=0;tx<16;++tx) - { - //Only the remove ramp designation (ignore channel designation, etc) - oldT = tiles[tx][ty]; - if ( DFHack::designation_default == designations[tx][ty].bits.dig - && DFHack::RAMP==DFHack::tileShape(oldT)) - { - //Current tile is a ramp. - //Set current tile, as accurately as can be expected - newT = DFHack::findSimilarTileType(oldT,DFHack::FLOOR); + // Current tile is a ramp. + // Set current tile, as accurately as can be expected + int16_t newT = findSimilarTileType(oldT, FLOOR); - //If no change, skip it (couldn't find a good tile type) - if ( oldT == newT) continue; - //Set new tile type, clear designation - tiles[tx][ty] = newT; - designations[tx][ty].bits.dig = DFHack::designation_no; + // If no change, skip it (couldn't find a good tile type) + if (oldT == newT) + continue; + // Set new tile type, clear designation + block->tiletype[x][y] = newT; + block->designation[x][y].bits.dig = df::tile_dig_designation::No; - //Check the tile above this one, in case a downward slope needs to be removed. - if ( DFHack::RAMP_TOP == DFHack::tileShape(tilesAbove[tx][ty]) ) - { - tilesAbove[tx][ty] = 32; - } - dirty= true; - ++count; - } - // ramp fixer - else if(DFHack::RAMP!=DFHack::tileShape(oldT) && DFHack::RAMP_TOP == DFHack::tileShape(tilesAbove[tx][ty])) - { - tilesAbove[tx][ty] = 32; - countbad++; - dirty = true; - } - } - } - //If anything was changed, write it all. - if (dirty) - { - Mapz->WriteDesignations(x,y,z, &designations); - Mapz->WriteTileTypes(x,y,z, &tiles); - if (Mapz->getBlock(x,y,z+1)) - { - Mapz->WriteTileTypes(x,y,z+1, &tilesAbove); - } - dirty = false; - } + // Check the tile above this one, in case a downward slope needs to be removed. + if ((above) && (tileShape(above->tiletype[x][y]) == RAMP_TOP)) + above->tiletype[x][y] = 32; // open space + count++; + } + // ramp fixer + else if ((tileShape(oldT) != RAMP) + && (above) && (tileShape(above->tiletype[x][y]) == RAMP_TOP)) + { + above->tiletype[x][y] = 32; // open space + countbad++; } } } } - c->Resume(); - if(count) - c->con.print("Found and changed %d tiles.\n",count); - if(countbad) - c->con.print("Fixed %d bad down ramps.\n",countbad); + if (count) + c->con.print("Found and changed %d tiles.\n", count); + if (countbad) + c->con.print("Fixed %d bad down ramps.\n", countbad); return CR_OK; } + +DFhackCExport const char * plugin_name ( void ) +{ + return "deramp"; +} + +DFhackCExport command_result plugin_init ( Core * c, std::vector &commands) +{ + commands.clear(); + commands.push_back(PluginCommand("deramp", + "De-ramp. All ramps marked for removal are replaced with floors.", + df_deramp)); + return CR_OK; +} + +DFhackCExport command_result plugin_shutdown ( Core * c ) +{ + return CR_OK; +} \ No newline at end of file From 9a86087db509e85838254c0fd79277364c697672 Mon Sep 17 00:00:00 2001 From: Alexander Gavrilov Date: Wed, 11 Jan 2012 20:04:04 +0400 Subject: [PATCH 46/82] Add timeouts when a job is cancelled, and color the command output. --- library/modules/Job.cpp | 2 + plugins/workflow.cpp | 366 +++++++++++++++++++++++++++++----------- 2 files changed, 273 insertions(+), 95 deletions(-) diff --git a/library/modules/Job.cpp b/library/modules/Job.cpp index 4e8094547..80c332fc8 100644 --- a/library/modules/Job.cpp +++ b/library/modules/Job.cpp @@ -175,10 +175,12 @@ static void print_job_item_details(Core *c, df::job *job, unsigned idx, df::job_ void DFHack::printJobDetails(Core *c, df::job *job) { + c->con.color(job->flags.bits.suspend ? Console::COLOR_DARKGREY : Console::COLOR_GREY); c->con << "Job " << job->id << ": " << ENUM_KEY_STR(job_type,job->job_type); if (job->flags.whole) c->con << " (" << bitfieldToString(job->flags) << ")"; c->con << endl; + c->con.reset_color(); df::item_type itype = ENUM_ATTR(job_type, item, job->job_type); diff --git a/plugins/workflow.cpp b/plugins/workflow.cpp index a874cd45a..369f9947c 100644 --- a/plugins/workflow.cpp +++ b/plugins/workflow.cpp @@ -20,11 +20,13 @@ #include #include #include +#include #include #include #include #include #include +#include #include #include #include @@ -73,9 +75,9 @@ DFhackCExport command_result plugin_init (Core *c, std::vector & " List workflow-controlled jobs (if in a workshop, filtered by it).\n" " workflow list\n" " List active constraints, and their job counts.\n" - " workflow limit [cnt-gap]\n" - " workflow limit-count [cnt-gap]\n" - " Set a constraint. The second form counts each stack as 1 item.\n" + " workflow count [cnt-gap]\n" + " workflow amount [cnt-gap]\n" + " Set a constraint. The first form counts each stack as only 1 item.\n" " workflow unlimit \n" " Delete a constraint.\n" "Function:\n" @@ -88,23 +90,23 @@ DFhackCExport command_result plugin_init (Core *c, std::vector & " much below the limit the amount has to drop before jobs are resumed;\n" " this is intended to reduce the frequency of jobs being toggled.\n" "Constraint examples:\n" - " workflow limit AMMO:ITEM_AMMO_BOLTS/METAL 1000 100\n" - " workflow limit AMMO:ITEM_AMMO_BOLTS/WOOD,BONE 200 50\n" + " workflow amount AMMO:ITEM_AMMO_BOLTS/METAL 1000 100\n" + " workflow amount AMMO:ITEM_AMMO_BOLTS/WOOD,BONE 200 50\n" " Keep metal bolts within 900-1000, and wood/bone within 150-200.\n" - " workflow limit-count FOOD 120 30\n" - " workflow limit-count DRINK 120 30\n" + " workflow count FOOD 120 30\n" + " workflow count DRINK 120 30\n" " Keep the number of prepared food & drink stacks between 90 and 120\n" - " workflow limit BIN 30\n" - " workflow limit BARREL 30\n" - " workflow limit BOX/CLOTH,SILK,YARN 30\n" + " workflow count BIN 30\n" + " workflow count BARREL 30\n" + " workflow count BOX/CLOTH,SILK,YARN 30\n" " Make sure there are always 25-30 empty bins/barrels/bags.\n" - " workflow limit BAR//COAL 20\n" - " workflow limit BAR//COPPER 30\n" + " workflow count BAR//COAL 20\n" + " workflow count BAR//COPPER 30\n" " Make sure there are always 15-20 coal and 25-30 copper bars.\n" - " workflow limit-count POWDER_MISC/SAND 20\n" - " workflow limit-count BOULDER/CLAY 20\n" + " workflow count POWDER_MISC/SAND 20\n" + " workflow count BOULDER/CLAY 20\n" " Collect 15-20 sand bags and clay boulders.\n" - " workflow limit POWDER_MISC//MUSHROOM_CUP_DIMPLE:MILL 100 20\n" + " workflow amount POWDER_MISC//MUSHROOM_CUP_DIMPLE:MILL 100 20\n" " Make sure there are always 80-100 units of dimple dye.\n" " In order for this to work, you have to set the material of\n" " the PLANT input on the Mill Plants job to MUSHROOM_CUP_DIMPLE\n" @@ -142,32 +144,46 @@ DFhackCExport command_result plugin_onstatechange(Core* c, state_change_event ev return CR_OK; } -/*******************************/ +/****************************** + * JOB STATE TRACKING STRUCTS * + ******************************/ + +const int DAY_TICKS = 1200; +const int MONTH_DAYS = 28; +const int YEAR_MONTHS = 12; struct ItemConstraint; struct ProtectedJob { int id; int building_id; - int check_idx; + int tick_idx; + + static int cur_tick_idx; - bool live; df::building *holder; df::job *job_copy; int reaction_id; df::job *actual_job; + bool want_resumed; + int resume_time, resume_delay; + std::vector constraints; - ProtectedJob(df::job *job) : id(job->id), live(true) +public: + ProtectedJob(df::job *job) : id(job->id) { - check_idx = 0; + tick_idx = cur_tick_idx; holder = getJobHolder(job); building_id = holder ? holder->id : -1; job_copy = cloneJobStruct(job); actual_job = job; reaction_id = -1; + + want_resumed = false; + resume_time = 0; resume_delay = DAY_TICKS; } ~ProtectedJob() @@ -175,6 +191,14 @@ struct ProtectedJob { deleteJobStruct(job_copy); } + bool isActuallyResumed() { + return actual_job && !actual_job->flags.bits.suspend; + } + bool isResumed() { + return want_resumed || isActuallyResumed(); + } + bool isLive() { return actual_job != NULL; } + void update(df::job *job) { actual_job = job; @@ -185,8 +209,60 @@ struct ProtectedJob { deleteJobStruct(job_copy); job_copy = cloneJobStruct(job); } + + void tick_job(df::job *job, int ticks) + { + tick_idx = cur_tick_idx; + actual_job = job; + + if (isActuallyResumed()) + { + resume_time = 0; + resume_delay = std::max(DAY_TICKS, resume_delay - ticks); + } + else if (want_resumed) + { + if (!resume_time) + want_resumed = false; + else if (world->frame_counter >= resume_time) + actual_job->flags.bits.suspend = false; + } + } + + void recover(df::job *job) + { + actual_job = job; + job->flags.bits.repeat = true; + job->flags.bits.suspend = true; + + resume_delay = std::min(DAY_TICKS*MONTH_DAYS, 5*resume_delay/3); + resume_time = world->frame_counter + resume_delay; + } + + void set_resumed(bool resume) + { + want_resumed = resume; + + if (resume) + { + if (world->frame_counter >= resume_time) + actual_job->flags.bits.suspend = false; + } + else + { + if (isActuallyResumed()) + { + resume_time = 0; + resume_delay = DAY_TICKS; + } + + actual_job->flags.bits.suspend = true; + } + } }; +int ProtectedJob::cur_tick_idx = 0; + typedef std::map, bool> TMaterialCache; struct ItemConstraint { @@ -205,6 +281,7 @@ struct ItemConstraint { TMaterialCache material_cache; +public: ItemConstraint() : weight(0), item_amount(0), item_count(0), item_inuse(0) {} int goalCount() { return config.ival(0); } @@ -238,11 +315,16 @@ struct ItemConstraint { } }; -/*******************************/ +/****************************** + * GLOBAL VARIABLES * + ******************************/ static bool enabled = false; static PersistentDataItem config; +static int last_tick_frame_count = 0; +static int last_frame_count = 0; + enum ConfigFlags { CF_ENABLED = 1 }; @@ -253,7 +335,9 @@ static TKnownJobs known_jobs; static std::vector pending_recover; static std::vector constraints; -/*******************************/ +/****************************** + * MISC FUNCTIONS * + ******************************/ static ProtectedJob *get_known(int id) { @@ -277,7 +361,9 @@ static void enumLiveJobs(std::map &rv) rv[p->item->id] = p->item; } -/*******************************/ +/****************************** + * STATE INITIALIZATION * + ******************************/ static void stop_protect(Core *c) { @@ -303,12 +389,12 @@ static void cleanup_state(Core *c) constraints.clear(); } -static bool check_lost_jobs(Core *c); +static void check_lost_jobs(Core *c, int ticks); static ItemConstraint *get_constraint(Core *c, const std::string &str, PersistentDataItem *cfg = NULL); static void start_protect(Core *c) { - check_lost_jobs(c); + check_lost_jobs(c, 0); if (!known_jobs.empty()) c->con.print("Protecting %d jobs.\n", known_jobs.size()); @@ -333,6 +419,9 @@ static void init_state(Core *c) c->getWorld()->DeletePersistentData(items[i]); } + last_tick_frame_count = world->frame_counter; + last_frame_count = world->frame_counter; + if (!enabled) return; @@ -354,7 +443,9 @@ static void enable_plugin(Core *c) start_protect(c); } -/*******************************/ +/****************************** + * JOB AUTO-RECOVERY * + ******************************/ static void forget_job(Core *c, ProtectedJob *pj) { @@ -364,6 +455,9 @@ static void forget_job(Core *c, ProtectedJob *pj) static bool recover_job(Core *c, ProtectedJob *pj) { + if (pj->isLive()) + return true; + // Check that the building exists pj->holder = df::building::find(pj->building_id); if (!pj->holder) @@ -396,31 +490,26 @@ static bool recover_job(Core *c, ProtectedJob *pj) // Create and link in the actual job structure df::job *recovered = cloneJobStruct(pj->job_copy); - recovered->flags.bits.repeat = true; - recovered->flags.bits.suspend = true; - if (!linkJobIntoWorld(recovered, false)) // reuse same id { deleteJobStruct(recovered); c->con.printerr("Inconsistency: job %d (%s) already in list.", pj->id, ENUM_KEY_STR(job_type, pj->job_copy->job_type)); - pj->live = true; return true; } pj->holder->jobs.push_back(recovered); // Done - pj->actual_job = recovered; - pj->live = true; + pj->recover(recovered); return true; } -static bool check_lost_jobs(Core *c) +static void check_lost_jobs(Core *c, int ticks) { - static int check = 1; - check++; + ProtectedJob::cur_tick_idx++; + if (ticks < 0) ticks = 0; df::job_list_link *p = world->job_list.next; for (; p; p = p->next) @@ -433,31 +522,25 @@ static bool check_lost_jobs(Core *c) if (!job->flags.bits.repeat) forget_job(c, pj); else - pj->check_idx = check; + 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; - pj->check_idx = check; } } - bool any_lost = false; - for (TKnownJobs::const_iterator it = known_jobs.begin(); it != known_jobs.end(); ++it) { - if (it->second->check_idx == check || !it->second->live) + if (it->second->tick_idx == ProtectedJob::cur_tick_idx || + !it->second->isLive()) continue; - it->second->live = false; it->second->actual_job = NULL; pending_recover.push_back(it->second); - any_lost = true; } - - return any_lost; } static void update_job_data(Core *c) @@ -486,31 +569,39 @@ DFhackCExport command_result plugin_onupdate(Core* c) if (!enabled) return CR_OK; + // Every 5 frames check the jobs for disappearance static unsigned cnt = 0; + if ((++cnt % 5) != 0) + return CR_OK; + + check_lost_jobs(c, world->frame_counter - last_tick_frame_count); + last_tick_frame_count = world->frame_counter; + + // Proceed every in-game half-day, or when jobs to recover changed static unsigned last_rlen = 0; - cnt++; + bool check_time = (world->frame_counter - last_frame_count) >= DAY_TICKS/2; - if ((cnt % 5) == 0) + if (pending_recover.size() != last_rlen || check_time) { - check_lost_jobs(c); + recover_jobs(c); + last_rlen = pending_recover.size(); - if (pending_recover.size() != last_rlen || (cnt % 50) == 0) + // If the half-day passed, proceed to update + if (check_time) { - recover_jobs(c); - last_rlen = pending_recover.size(); + last_frame_count = world->frame_counter; - if ((cnt % 500) == 0) - { - update_job_data(c); - process_constraints(c); - } + update_job_data(c); + process_constraints(c); } } return CR_OK; } -/*******************************/ +/****************************** + * ITEM COUNT CONSTRAINT * + ******************************/ static ItemConstraint *get_constraint(Core *c, const std::string &str, PersistentDataItem *cfg) { @@ -592,6 +683,10 @@ static void delete_constraint(Core *c, ItemConstraint *cv) delete cv; } +/****************************** + * JOB-CONSTRAINT MAPPING * + ******************************/ + static void link_job_constraint(ProtectedJob *pj, df::item_type itype, int16_t isubtype, df::dfhack_material_category mat_mask, int16_t mat_type, int32_t mat_index) @@ -823,18 +918,27 @@ static void map_job_constraints(Core *c) { it->second->constraints.clear(); - if (!it->second->live) + if (!it->second->isLive()) continue; compute_job_outputs(c, it->second); } } +/****************************** + * ITEM-CONSTRAINT MAPPING * + ******************************/ + static bool itemNotEmpty(df::item *item) { for (unsigned i = 0; i < item->itemrefs.size(); i++) - if (strict_virtual_cast(item->itemrefs[i])) + { + df::general_ref *ref = item->itemrefs[i]; + if (strict_virtual_cast(ref)) return true; + if (strict_virtual_cast(ref)) + return true; + } return false; } @@ -869,10 +973,11 @@ static void map_job_items(Core *c) #define F(x) bad_flags.bits.x = true; F(dump); F(forbid); F(garbage_colect); F(hostile); F(on_fire); F(rotten); F(trader); - F(in_building); F(artifact1); + F(in_building); F(construction); F(artifact1); #undef F - std::vector &items = df::item::get_vector(); + std::vector &items = world->items.other[items_other_id::ANY_FREE]; + for (unsigned i = 0; i < items.size(); i++) { df::item *item = items[i]; @@ -930,12 +1035,18 @@ static void map_job_items(Core *c) constraints[i]->computeRequest(); } +/****************************** + * ITEM COUNT CONSTRAINT * + ******************************/ + +static std::string shortJobDescription(df::job *job); + static void update_jobs_by_constraints(Core *c) { for (TKnownJobs::const_iterator it = known_jobs.begin(); it != known_jobs.end(); ++it) { ProtectedJob *pj = it->second; - if (!pj->live || pj->constraints.empty()) + if (!pj->isLive() || pj->constraints.empty()) continue; int resume_weight = -1; @@ -949,19 +1060,22 @@ static void update_jobs_by_constraints(Core *c) suspend_weight = std::max(suspend_weight, pj->constraints[i]->weight); } - bool goal = pj->actual_job->flags.bits.suspend; + bool current = pj->isResumed(); + bool goal = current; if (resume_weight >= 0 && resume_weight >= suspend_weight) - goal = false; - else if (suspend_weight >= 0 && suspend_weight >= resume_weight) goal = true; + else if (suspend_weight >= 0 && suspend_weight >= resume_weight) + goal = false; - if (goal != pj->actual_job->flags.bits.suspend) + pj->set_resumed(goal); + + if (goal != current) { - pj->actual_job->flags.bits.suspend = goal; - c->con.print("%s job %d: %s\n", - (goal ? "Suspending" : "Resuming"), pj->id, - ENUM_KEY_STR(job_type, pj->actual_job->job_type)); + c->con.print("%s %s%s\n", + (goal ? "Resuming" : "Suspending"), + shortJobDescription(pj->actual_job).c_str(), + (!goal || pj->isActuallyResumed() ? "" : " (delayed)")); } } } @@ -976,13 +1090,49 @@ static void process_constraints(Core *c) update_jobs_by_constraints(c); } -/*******************************/ +/****************************** + * PRINTING AND THE COMMAND * + ******************************/ + +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 += " [" + bitfieldToString(mat_mask) + "]"; + + return rv; +} static void print_constraint(Core *c, ItemConstraint *cv, bool no_job = false, std::string prefix = "") { - c->con << prefix << "Constraint " << cv->config.val() << ": " - << (cv->goalByCount() ? "count " : "amount ") + Console::color_value color; + if (cv->request_resume) + color = Console::COLOR_GREEN; + else if (cv->request_suspend) + color = Console::COLOR_CYAN; + else + color = Console::COLOR_DARKGREY; + + c->con.color(color); + c->con << prefix << "Constraint " << flush; + c->con.color(Console::COLOR_GREY); + c->con << cv->config.val() << " " << flush; + c->con.color(color); + c->con << (cv->goalByCount() ? "count " : "amount ") << cv->goalCount() << " (gap " << cv->goalGap() << ")" << endl; + c->con.reset_color(); if (cv->item_count || cv->item_inuse) c->con << prefix << " items: amount " << cv->item_amount << "; " @@ -994,30 +1144,57 @@ static void print_constraint(Core *c, ItemConstraint *cv, bool no_job = false, s if (cv->jobs.empty()) c->con.printerr(" (no jobs)\n"); + std::vector unique_jobs; + std::vector unique_counts; + for (int i = 0; i < cv->jobs.size(); i++) { ProtectedJob *pj = cv->jobs[i]; + for (int j = 0; j < unique_jobs.size(); j++) + { + if (unique_jobs[j]->building_id == pj->building_id && + *unique_jobs[j]->actual_job == *pj->actual_job) + { + unique_counts[j]++; + goto next_job; + } + } + + unique_jobs.push_back(pj); + unique_counts.push_back(1); + next_job:; + } + + for (int i = 0; i < unique_jobs.size(); i++) + { + ProtectedJob *pj = unique_jobs[i]; df::job *job = pj->actual_job; - c->con << prefix << " job " << job->id << ": "; + std::string start = prefix + " " + shortJobDescription(job); - if (job->job_type != job_type::CustomReaction) - c->con << ENUM_KEY_STR(job_type, job->job_type); + if (!pj->isActuallyResumed()) + { + if (pj->want_resumed) + { + c->con.color(Console::COLOR_YELLOW); + c->con << start << " (delayed)" << endl; + } + else + { + c->con.color(Console::COLOR_BLUE); + c->con << start << " (suspended)" << endl; + } + } else - c->con << job->reaction_name; - - MaterialInfo mat; - df::dfhack_material_category mat_mask; - guess_job_material(job, mat, mat_mask); + { + c->con.color(Console::COLOR_GREEN); + c->con << start << endl; + } - if (mat.isValid()) - c->con << " [" << mat.toString() << "]"; - else if (mat_mask.whole) - c->con << " [" << bitfieldToString(mat_mask) << "]"; + c->con.reset_color(); - if (job->flags.bits.suspend) - c->con << " (suspended)"; - c->con << endl; + if (unique_counts[i] > 1) + c->con << prefix << " (" << unique_counts[i] << " copies)" << endl; } } @@ -1026,7 +1203,7 @@ static void print_job(Core *c, ProtectedJob *pj) if (!pj) return; - printJobDetails(c, pj->job_copy); + printJobDetails(c, pj->isLive() ? pj->actual_job : pj->job_copy); for (int i = 0; i < pj->constraints.size(); i++) print_constraint(c, pj->constraints[i], true, " "); @@ -1037,7 +1214,7 @@ static command_result workflow_cmd(Core *c, vector & parameters) CoreSuspender suspend(c); if (enabled) { - check_lost_jobs(c); + check_lost_jobs(c, 0); recover_jobs(c); update_job_data(c); map_job_constraints(c); @@ -1080,7 +1257,7 @@ static command_result workflow_cmd(Core *c, vector & parameters) stop_protect(c); return CR_OK; } - else if (cmd == "limit" || cmd == "limit-count") + else if (cmd == "count" || cmd == "amount") { if (!enabled) enable_plugin(c); @@ -1099,7 +1276,7 @@ static command_result workflow_cmd(Core *c, vector & parameters) else { for (TKnownJobs::iterator it = known_jobs.begin(); it != known_jobs.end(); ++it) - if (it->second->live) + if (it->second->isLive()) print_job(c, it->second); } @@ -1128,7 +1305,7 @@ static command_result workflow_cmd(Core *c, vector & parameters) return CR_OK; } - else if (cmd == "limit" || cmd == "limit-count") + else if (cmd == "count" || cmd == "amount") { if (parameters.size() < 3) return CR_WRONG_USAGE; @@ -1143,15 +1320,14 @@ static command_result workflow_cmd(Core *c, vector & parameters) if (!icv) return CR_FAILURE; - icv->setGoalByCount(cmd == "limit-count"); + icv->setGoalByCount(cmd == "count"); icv->setGoalCount(limit); if (parameters.size() >= 4) icv->setGoalGap(atoi(parameters[3].c_str())); else icv->setGoalGap(-1); - map_job_constraints(c); - map_job_items(c); + process_constraints(c); print_constraint(c, icv); return CR_OK; } From 29b0c4273e5110adc278b4ff0ebdb8379d49e9a1 Mon Sep 17 00:00:00 2001 From: Quietust Date: Wed, 11 Jan 2012 10:17:25 -0600 Subject: [PATCH 47/82] Cleanup fastdwarf plugin, no longer relies on modules --- plugins/fastdwarf.cpp | 53 ++++++++++++++++++++----------------------- 1 file changed, 24 insertions(+), 29 deletions(-) diff --git a/plugins/fastdwarf.cpp b/plugins/fastdwarf.cpp index 38b7f312d..c8265be52 100644 --- a/plugins/fastdwarf.cpp +++ b/plugins/fastdwarf.cpp @@ -1,21 +1,20 @@ -// foo -// vi:expandtab:sw=4 - -#include -#include -#include -#include -#include -#include -using namespace std; #include "Core.h" #include #include #include -#include -#include + +#include +#include "df/ui.h" +#include "df/world.h" +#include "df/unit.h" + +using std::string; +using std::vector; using namespace DFHack; +using df::global::world; +using df::global::ui; + // dfhack interface DFhackCExport const char * plugin_name ( void ) { @@ -33,22 +32,16 @@ DFhackCExport command_result plugin_onupdate ( Core * c ) { if (!enable_fastdwarf) return CR_OK; - df_unit *cre; - DFHack::Units * cr = c->getUnits(); - static vector *v = cr->creatures; - uint32_t race = cr->GetDwarfRaceIndex(); - uint32_t civ = cr->GetDwarfCivId(); - if (!v) - { - c->con.printerr("Unable to locate creature vector. Fastdwarf cancelled.\n"); - } + int32_t race = ui->race_id; + int32_t civ = ui->civ_id; - for (unsigned i=0 ; isize() ; ++i) + for (int i = 0; i < world->units.all.size(); i++) { - cre = v->at(i); - if (cre->race == race && cre->civ == civ && cre->job_counter > 0) - cre->job_counter = 0; - // could also patch the cre->current_job->counter + df::unit *unit = world->units.all[i]; + + if (unit->race == race && unit->civ_id == civ && unit->counters.job_counter > 0) + unit->counters.job_counter = 0; + // could also patch the unit->job.current_job->completion_timer } return CR_OK; } @@ -65,7 +58,9 @@ static command_result fastdwarf (Core * c, vector & parameters) } else { - c->con.print("Makes your minions move at ludicrous speeds.\nActivate with 'fastdwarf 1', deactivate with 'fastdwarf 0'.\nCurrent state: %d.\n", enable_fastdwarf); + c->con.print("Makes your minions move at ludicrous speeds.\n" + "Activate with 'fastdwarf 1', deactivate with 'fastdwarf 0'.\n" + "Current state: %d.\n", enable_fastdwarf); } return CR_OK; @@ -76,8 +71,8 @@ DFhackCExport command_result plugin_init ( Core * c, std::vector commands.clear(); commands.push_back(PluginCommand("fastdwarf", - "enable/disable fastdwarf (parameter=0/1)", - fastdwarf)); + "enable/disable fastdwarf (parameter=0/1)", + fastdwarf)); return CR_OK; } From b0be2f55c6f164df8f137602db216c427cb45413 Mon Sep 17 00:00:00 2001 From: Quietust Date: Wed, 11 Jan 2012 10:29:59 -0600 Subject: [PATCH 48/82] Cleanup plugin 'flows' --- plugins/flows.cpp | 118 ++++++++++++++++++++-------------------------- 1 file changed, 50 insertions(+), 68 deletions(-) diff --git a/plugins/flows.cpp b/plugins/flows.cpp index c5b588903..fd4c0c579 100644 --- a/plugins/flows.cpp +++ b/plugins/flows.cpp @@ -1,19 +1,59 @@ // This tool counts static tiles and active flows of water and magma. -#include -#include -#include -#include -#include -using namespace std; #include "Core.h" #include #include #include -#include + +#include +#include "df/world.h" +#include "df/map_block.h" +#include "df/tile_liquid.h" + +using std::string; +using std::vector; using namespace DFHack; -DFhackCExport command_result df_flows (Core * c, vector & parameters); +using df::global::world; + +DFhackCExport command_result df_flows (Core * c, vector & parameters) +{ + CoreSuspender suspend(c); + + int flow1 = 0, flow2 = 0, flowboth = 0, water = 0, magma = 0; + c->con.print("Counting flows and liquids ...\n"); + + for (int i = 0; i < world->map.map_blocks.size(); i++) + { + df::map_block *cur = world->map.map_blocks[i]; + if (cur->flags.is_set(df::block_flags::UpdateLiquid)) + flow1++; + if (cur->flags.is_set(df::block_flags::UpdateLiquidTwice)) + flow2++; + if (cur->flags.is_set(df::block_flags::UpdateLiquid) && cur->flags.is_set(df::block_flags::UpdateLiquidTwice)) + flowboth++; + for (int x = 0; x < 16; x++) + { + for (int y = 0; y < 16; y++) + { + // only count tiles with actual liquid in them + if (cur->designation[x][y].bits.flow_size == 0) + continue; + if (cur->designation[x][y].bits.liquid_type == df::tile_liquid::Magma) + magma++; + if (cur->designation[x][y].bits.liquid_type == df::tile_liquid::Water) + water++; + } + } + } + + c->con.print("Blocks with liquid_1=true: %d\n", flow1); + c->con.print("Blocks with liquid_2=true: %d\n", flow2); + c->con.print("Blocks with both: %d\n", flowboth); + c->con.print("Water tiles: %d\n", water); + c->con.print("Magma tiles: %d\n", magma); + return CR_OK; +} DFhackCExport const char * plugin_name ( void ) { @@ -24,8 +64,8 @@ DFhackCExport command_result plugin_init ( Core * c, std::vector { commands.clear(); commands.push_back(PluginCommand("flows", - "Counts map blocks with flowing liquids.", - df_flows)); + "Counts map blocks with flowing liquids.", + df_flows)); return CR_OK; } @@ -33,61 +73,3 @@ DFhackCExport command_result plugin_shutdown ( Core * c ) { return CR_OK; } - -DFhackCExport command_result df_flows (Core * c, vector & parameters) -{ - uint32_t x_max,y_max,z_max; - DFHack::designations40d designations; - DFHack::Maps *Maps; - - c->Suspend(); - Maps = c->getMaps(); - // init the map - if(!Maps->Start()) - { - c->con.printerr("Can't init map.\n"); - c->Resume(); - return CR_FAILURE; - } - DFHack::t_blockflags bflags; - Maps->getSize(x_max,y_max,z_max); - // walk the map, count flowing tiles, magma, water - uint32_t flow1=0, flow2=0, flowboth=0, water=0, magma=0; - c->con.print("Counting flows and liquids ...\n"); - for(uint32_t x = 0; x< x_max;x++) - { - for(uint32_t y = 0; y< y_max;y++) - { - for(uint32_t z = 0; z< z_max;z++) - { - if(Maps->getBlock(x,y,z)) - { - Maps->ReadBlockFlags(x, y, z, bflags); - Maps->ReadDesignations(x, y, z, &designations); - if (bflags.bits.liquid_1) - flow1++; - if (bflags.bits.liquid_2) - flow2++; - if (bflags.bits.liquid_1 && bflags.bits.liquid_2) - flowboth++; - for (uint32_t i = 0; i < 16;i++) for (uint32_t j = 0; j < 16;j++) - { - if (designations[i][j].bits.liquid_type == DFHack::liquid_magma) - magma++; - if (designations[i][j].bits.liquid_type == DFHack::liquid_water) - water++; - } - } - } - } - } - c->con.print("Blocks with liquid_1=true: %d\n" - "Blocks with liquid_2=true: %d\n" - "Blocks with both: %d\n" - "Water tiles: %d\n" - "Magma tiles: %d\n" - ,flow1, flow2, flowboth, water, magma - ); - c->Resume(); - return CR_OK; -} From a3d2cf3a85457109d003d8b9dced3709d9c072ec Mon Sep 17 00:00:00 2001 From: Quietust Date: Wed, 11 Jan 2012 10:31:23 -0600 Subject: [PATCH 49/82] Minor cleanup --- plugins/regrass.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/plugins/regrass.cpp b/plugins/regrass.cpp index bd227638e..99af1de7f 100644 --- a/plugins/regrass.cpp +++ b/plugins/regrass.cpp @@ -7,16 +7,15 @@ #include #include +#include "df/world.h" +#include "df/map_block.h" #include -#include -#include using std::string; using std::vector; using namespace DFHack; using df::global::world; -using df::map_block; DFhackCExport command_result df_regrass (Core * c, vector & parameters) { @@ -28,7 +27,7 @@ DFhackCExport command_result df_regrass (Core * c, vector & parameters) int count = 0; for (int i = 0; i < world->map.map_blocks.size(); i++) { - map_block *cur = world->map.map_blocks[i]; + df::map_block *cur = world->map.map_blocks[i]; for (int x = 0; x < 16; x++) { for (int y = 0; y < 16; y++) From 5173be649fec0f878924f5f51efbd6a0bbb531ea Mon Sep 17 00:00:00 2001 From: Quietust Date: Wed, 11 Jan 2012 10:49:42 -0600 Subject: [PATCH 50/82] Silence warning --- plugins/cleaners.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/cleaners.cpp b/plugins/cleaners.cpp index 52b92de6f..1ff121de0 100644 --- a/plugins/cleaners.cpp +++ b/plugins/cleaners.cpp @@ -13,6 +13,7 @@ #include "df/matter_state.h" #include "df/cursor.h" #include "df/builtin_mats.h" +#include "df/contaminant.h" using std::vector; using std::string; From 6d2ce7b8a980a754bca86be92beadb59b0c5a060 Mon Sep 17 00:00:00 2001 From: Quietust Date: Wed, 11 Jan 2012 10:50:38 -0600 Subject: [PATCH 51/82] Add default return value to MaterialInfo::matches --- library/modules/Materials.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/library/modules/Materials.cpp b/library/modules/Materials.cpp index cc9102ae5..2682f57bf 100644 --- a/library/modules/Materials.cpp +++ b/library/modules/Materials.cpp @@ -355,6 +355,7 @@ bool MaterialInfo::matches(const df::dfhack_material_category &cat) TEST(glass, IS_GLASS); if (cat.bits.clay && linear_index(material->reaction_product.id, std::string("FIRED_MAT")) >= 0) return true; + return false; } #undef TEST From 555183cb255870e4c1a2a216214bb8607fd7d0bd Mon Sep 17 00:00:00 2001 From: Quietust Date: Wed, 11 Jan 2012 10:57:05 -0600 Subject: [PATCH 52/82] Remove unreferenced variables --- library/modules/Translation.cpp | 2 -- library/modules/Units.cpp | 2 -- plugins/autodump.cpp | 1 - plugins/probe.cpp | 1 - 4 files changed, 6 deletions(-) diff --git a/library/modules/Translation.cpp b/library/modules/Translation.cpp index 6df7c7f24..a2e73ad66 100644 --- a/library/modules/Translation.cpp +++ b/library/modules/Translation.cpp @@ -190,8 +190,6 @@ bool Translation::readName(t_name & name, df_name * source) bool Translation::copyName(df_name * source, df_name * target) { - uint8_t buf[28]; - if (source == target) return true; Core & c = Core::getInstance(); diff --git a/library/modules/Units.cpp b/library/modules/Units.cpp index 2d68be559..f969e3f90 100644 --- a/library/modules/Units.cpp +++ b/library/modules/Units.cpp @@ -136,7 +136,6 @@ int32_t Units::GetCreatureInBox (int32_t index, df_unit ** furball, return -1; Process *p = d->owner; - uint16_t coords[3]; uint32_t size = creatures->size(); while (uint32_t(index) < size) { @@ -575,7 +574,6 @@ bool Units::ReadOwnedItemsByIdx(const uint32_t index, std::vector & ite bool Units::ReadOwnedItemsByPtr(const df_unit * temp, std::vector & items) { - unsigned int i; if(!d->Started) return false; items = temp->owned_items; return true; diff --git a/plugins/autodump.cpp b/plugins/autodump.cpp index 3963bf2af..0584ca090 100644 --- a/plugins/autodump.cpp +++ b/plugins/autodump.cpp @@ -72,7 +72,6 @@ DFhackCExport command_result df_autodump (Core * c, vector & parameters } } c->Suspend(); - DFHack::occupancies40d * occupancies; DFHack::VersionInfo *mem = c->vinfo; DFHack::Gui * Gui = c->getGui(); DFHack::Items * Items = c->getItems(); diff --git a/plugins/probe.cpp b/plugins/probe.cpp index d70a6dbaf..cf00fe0dd 100644 --- a/plugins/probe.cpp +++ b/plugins/probe.cpp @@ -54,7 +54,6 @@ DFhackCExport command_result plugin_shutdown ( Core * c ) DFhackCExport command_result df_cprobe (Core * c, vector & parameters) { Console & con = c->con; - BEGIN_PROBE: c->Suspend(); DFHack::Gui *Gui = c->getGui(); DFHack::Units * cr = c->getUnits(); From bb0959e4703dcb9271ebc506fde4b5ed87528baa Mon Sep 17 00:00:00 2001 From: Quietust Date: Wed, 11 Jan 2012 10:59:56 -0600 Subject: [PATCH 53/82] Fix confusion between "cout" and "c->con" --- plugins/mode.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/mode.cpp b/plugins/mode.cpp index 2ca741ae2..9c7aefb73 100644 --- a/plugins/mode.cpp +++ b/plugins/mode.cpp @@ -166,7 +166,7 @@ DFhackCExport command_result mode (Core * c, vector & parameters) c->Suspend(); world->WriteGameMode(gm); c->Resume(); - cout << endl; + c->con << endl; } return CR_OK; } \ No newline at end of file From 18f2459b5dc39f5412517bed49b531979edb8873 Mon Sep 17 00:00:00 2001 From: Quietust Date: Wed, 11 Jan 2012 11:04:06 -0600 Subject: [PATCH 54/82] Add missing newline to "clean" usage --- plugins/cleaners.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/cleaners.cpp b/plugins/cleaners.cpp index 1ff121de0..fcfc166ff 100644 --- a/plugins/cleaners.cpp +++ b/plugins/cleaners.cpp @@ -196,7 +196,7 @@ DFhackCExport command_result clean (Core * c, vector & parameters) "snow - also remove snow\n" "mud - also remove mud\n" "Example: clean all mud snow\n" - "This removes all spatter, including mud and snow from map tiles." + "This removes all spatter, including mud and snow from map tiles.\n" ); return CR_OK; } From 59b66a2681c6de703f240df4d1d7fbd3998fb09c Mon Sep 17 00:00:00 2001 From: Quietust Date: Wed, 11 Jan 2012 11:04:20 -0600 Subject: [PATCH 55/82] Fix output formatting --- plugins/cleanowned.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/cleanowned.cpp b/plugins/cleanowned.cpp index c7d931676..1899129c1 100644 --- a/plugins/cleanowned.cpp +++ b/plugins/cleanowned.cpp @@ -120,7 +120,7 @@ DFhackCExport command_result df_cleanowned (Core * c, vector & paramete int32_t owner = Items->getItemOwnerID(item); if (owner >= 0) { - c->con.print("Fixing a misflagged item: "); + c->con.print("Fixing a misflagged item: \t"); confiscate = true; } else From 53e9a1659be03338998d08d23c623c41655bbe18 Mon Sep 17 00:00:00 2001 From: Alexander Gavrilov Date: Thu, 12 Jan 2012 20:07:53 +0400 Subject: [PATCH 56/82] Add automatic drybucket and melting to workflow. --- library/xml | 2 +- plugins/workflow.cpp | 207 +++++++++++++++++++++++++++++++++---------- 2 files changed, 162 insertions(+), 47 deletions(-) diff --git a/library/xml b/library/xml index 9799fc70b..91b6531e1 160000 --- a/library/xml +++ b/library/xml @@ -1 +1 @@ -Subproject commit 9799fc70b8389ddc0e73805f528dbd7b223653e5 +Subproject commit 91b6531e1a66e98f7c0ae7f81b5496ccde584b73 diff --git a/plugins/workflow.cpp b/plugins/workflow.cpp index 369f9947c..e8ac9a4cc 100644 --- a/plugins/workflow.cpp +++ b/plugins/workflow.cpp @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -33,6 +34,7 @@ #include #include #include +#include using std::vector; using std::string; @@ -68,9 +70,12 @@ DFhackCExport command_result plugin_init (Core *c, std::vector & PluginCommand( "workflow", "Manage control of repeat jobs.", workflow_cmd, false, - " workflow enable\n" - " workflow disable\n" - " Enable or disable the plugin.\n" + " workflow enable [option...]\n" + " workflow disable [option...]\n" + " If no options are specified, enables or disables the plugin.\n" + " Otherwise, enables or disables any of the following options:\n" + " - drybuckets: Automatically empty abandoned water buckets.\n" + " - auto-melt: Resume melt jobs when there are objects to melt.\n" " workflow jobs\n" " List workflow-controlled jobs (if in a workshop, filtered by it).\n" " workflow list\n" @@ -241,8 +246,6 @@ public: void set_resumed(bool resume) { - want_resumed = resume; - if (resume) { if (world->frame_counter >= resume_time) @@ -250,14 +253,14 @@ public: } else { + resume_time = 0; if (isActuallyResumed()) - { - resume_time = 0; resume_delay = DAY_TICKS; - } actual_job->flags.bits.suspend = true; } + + want_resumed = resume; } }; @@ -326,7 +329,9 @@ static int last_tick_frame_count = 0; static int last_frame_count = 0; enum ConfigFlags { - CF_ENABLED = 1 + CF_ENABLED = 1, + CF_DRYBUCKETS = 2, + CF_AUTOMELT = 4 }; typedef std::map TKnownJobs; @@ -335,6 +340,8 @@ static TKnownJobs known_jobs; static std::vector pending_recover; static std::vector constraints; +static int meltable_count = 0; + /****************************** * MISC FUNCTIONS * ******************************/ @@ -361,6 +368,22 @@ static void enumLiveJobs(std::map &rv) rv[p->item->id] = p->item; } +static bool isOptionEnabled(unsigned flag) +{ + return config.isValid() && (config.ival(0) & flag) != 0; +} + +static void setOptionEnabled(ConfigFlags flag, bool on) +{ + if (!config.isValid()) + return; + + if (on) + config.ival(0) |= flag; + else + config.ival(0) &= ~flag; +} + /****************************** * STATE INITIALIZATION * ******************************/ @@ -403,9 +426,10 @@ static void start_protect(Core *c) static void init_state(Core *c) { config = c->getWorld()->GetPersistentData("workflow/config"); + if (config.isValid() && config.ival(0) == -1) + config.ival(0) = 0; - enabled = config.isValid() && config.ival(0) != -1 && - (config.ival(0) & CF_ENABLED); + enabled = isOptionEnabled(CF_ENABLED); // Parse constraints std::vector items; @@ -436,7 +460,7 @@ static void enable_plugin(Core *c) config.ival(0) = 0; } - config.ival(0) |= CF_ENABLED; + setOptionEnabled(CF_ENABLED, true); enabled = true; c->con << "Enabling the plugin." << endl; @@ -929,15 +953,45 @@ static void map_job_constraints(Core *c) * ITEM-CONSTRAINT MAPPING * ******************************/ -static bool itemNotEmpty(df::item *item) +static void dryBucket(df::item *item) { for (unsigned i = 0; i < item->itemrefs.size(); i++) { df::general_ref *ref = item->itemrefs[i]; if (strict_virtual_cast(ref)) + { + df::item *obj = ref->getItem(); + + if (obj && + obj->getType() == item_type::LIQUID_MISC && + obj->getMaterial() == builtin_mats::WATER) + { + obj->flags.bits.garbage_colect = true; + obj->flags.bits.hidden = true; + } + } + } +} + +static bool itemBusy(df::item *item) +{ + + for (unsigned i = 0; i < item->itemrefs.size(); i++) + { + df::general_ref *ref = item->itemrefs[i]; + if (strict_virtual_cast(ref)) + { + df::item *obj = ref->getItem(); + if (obj && !obj->flags.bits.garbage_colect) + return true; + } + else if (strict_virtual_cast(ref)) return true; - if (strict_virtual_cast(ref)) - return true; + else if (strict_virtual_cast(ref)) + { + if (!item->flags.bits.in_job) + return true; + } } return false; @@ -966,6 +1020,8 @@ static void map_job_items(Core *c) constraints[i]->item_inuse = 0; } + meltable_count = 0; + // Precompute a bitmask with the bad flags df::item_flags bad_flags; bad_flags.whole = 0; @@ -976,6 +1032,8 @@ static void map_job_items(Core *c) F(in_building); F(construction); F(artifact1); #undef F + bool dry_buckets = isOptionEnabled(CF_DRYBUCKETS); + std::vector &items = world->items.other[items_other_id::ANY_FREE]; for (unsigned i = 0; i < items.size(); i++) @@ -984,14 +1042,20 @@ static void map_job_items(Core *c) if (item->flags.whole & bad_flags.whole) continue; - if (itemInRealJob(item)) - continue; df::item_type itype = item->getType(); int16_t isubtype = item->getSubtype(); int16_t imattype = item->getActualMaterial(); int32_t imatindex = item->getActualMaterialIndex(); + // Special handling + if (dry_buckets && itype == item_type::BUCKET && !item->flags.bits.in_job) + dryBucket(item); + + if (item->flags.bits.melt && !item->flags.bits.owned && !itemBusy(item)) + meltable_count++; + + // Match to constraints TMaterialCache::key_type matkey(imattype, imatindex); for (unsigned i = 0; i < constraints.size(); i++) @@ -1019,7 +1083,8 @@ static void map_job_items(Core *c) if (item->flags.bits.owned || item->isAssignedToStockpile() || - itemNotEmpty(item)) + itemInRealJob(item) || + itemBusy(item)) { cv->item_inuse++; } @@ -1041,12 +1106,37 @@ static void map_job_items(Core *c) static std::string shortJobDescription(df::job *job); +static void setJobResumed(Core *c, ProtectedJob *pj, bool goal) +{ + bool current = pj->isResumed(); + + pj->set_resumed(goal); + + if (goal != current) + { + c->con.print("%s %s%s\n", + (goal ? "Resuming" : "Suspending"), + shortJobDescription(pj->actual_job).c_str(), + (!goal || pj->isActuallyResumed() ? "" : " (delayed)")); + } +} + static void update_jobs_by_constraints(Core *c) { for (TKnownJobs::const_iterator it = known_jobs.begin(); it != known_jobs.end(); ++it) { ProtectedJob *pj = it->second; - if (!pj->isLive() || pj->constraints.empty()) + if (!pj->isLive()) + continue; + + if (pj->actual_job->job_type == job_type::MeltMetalObject && + isOptionEnabled(CF_AUTOMELT)) + { + setJobResumed(c, pj, meltable_count > 0); + continue; + } + + if (pj->constraints.empty()) continue; int resume_weight = -1; @@ -1060,29 +1150,21 @@ static void update_jobs_by_constraints(Core *c) suspend_weight = std::max(suspend_weight, pj->constraints[i]->weight); } - bool current = pj->isResumed(); - bool goal = current; + 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; - pj->set_resumed(goal); - - if (goal != current) - { - c->con.print("%s %s%s\n", - (goal ? "Resuming" : "Suspending"), - shortJobDescription(pj->actual_job).c_str(), - (!goal || pj->isActuallyResumed() ? "" : " (delayed)")); - } + setJobResumed(c, pj, goal); } } static void process_constraints(Core *c) { - if (constraints.empty()) + if (constraints.empty() && + !isOptionEnabled(CF_DRYBUCKETS | CF_AUTOMELT)) return; map_job_constraints(c); @@ -1203,7 +1285,22 @@ static void print_job(Core *c, ProtectedJob *pj) if (!pj) return; - printJobDetails(c, pj->isLive() ? pj->actual_job : pj->job_copy); + df::job *job = pj->isLive() ? pj->actual_job : pj->job_copy; + + printJobDetails(c, job); + + if (job->job_type == job_type::MeltMetalObject && + isOptionEnabled(CF_AUTOMELT)) + { + if (meltable_count <= 0) + c->con.color(Console::COLOR_CYAN); + else if (pj->want_resumed && !pj->isActuallyResumed()) + c->con.color(Console::COLOR_YELLOW); + else + c->con.color(Console::COLOR_GREEN); + c->con << " Meltable: " << meltable_count << " objects." << endl; + c->con.reset_color(); + } for (int i = 0; i < pj->constraints.size(); i++) print_constraint(c, pj->constraints[i], true, " "); @@ -1233,28 +1330,46 @@ static command_result workflow_cmd(Core *c, vector & parameters) std::string cmd = parameters.empty() ? "list" : parameters[0]; - if (cmd == "enable") + if (cmd == "enable" || cmd == "disable") { - if (enabled) + bool enable = (cmd == "enable"); + if (enable && !enabled) + { + enable_plugin(c); + } + else if (!enable && parameters.size() == 1) { - c->con << "The plugin is already enabled." << endl; + if (enabled) + { + enabled = false; + setOptionEnabled(CF_ENABLED, false); + stop_protect(c); + } + + c->con << "The plugin is disabled." << endl; return CR_OK; } - enable_plugin(c); - return CR_OK; - } - else if (cmd == "disable") - { - if (!enabled) + for (unsigned i = 1; i < parameters.size(); i++) { - c->con << "The plugin is already disabled." << endl; - return CR_OK; + if (parameters[i] == "drybuckets") + setOptionEnabled(CF_DRYBUCKETS, enable); + else if (parameters[i] == "auto-melt") + setOptionEnabled(CF_AUTOMELT, enable); + else + return CR_WRONG_USAGE; } - enabled = false; - config.ival(0) &= ~CF_ENABLED; - stop_protect(c); + if (enabled) + c->con << "The plugin is enabled." << endl; + else + c->con << "The plugin is disabled." << endl; + + if (isOptionEnabled(CF_DRYBUCKETS)) + c->con << "Option drybuckets is enabled." << endl; + if (isOptionEnabled(CF_AUTOMELT)) + c->con << "Option auto-melt is enabled." << endl; + return CR_OK; } else if (cmd == "count" || cmd == "amount") From a31542862aa0a3f8a64db9dcf4d7351394c2dfe9 Mon Sep 17 00:00:00 2001 From: Alexander Gavrilov Date: Sat, 14 Jan 2012 19:31:43 +0400 Subject: [PATCH 57/82] Add utility functions to retrieve the selected job/unit/item. Units can be selected via 'u', 'j', 'v' and 'k'; full-screen unit details view not supported. Items can be selected via 't', 'k', 'v'->inventory. Also, when viewing a container item full-screen, the selected contained item or unit is returned; never the container itself. The api is used in rename to allow setting nicknames for arbitrary units, including animals and enemies. --- Memory.xml | 19 +++- library/include/DataDefs.h | 8 +- library/include/modules/Gui.h | 15 +++ library/modules/Gui.cpp | 208 ++++++++++++++++++++++++++++++++++ library/xml | 2 +- plugins/cleaners.cpp | 2 + plugins/rename.cpp | 74 +++++++++--- 7 files changed, 310 insertions(+), 18 deletions(-) diff --git a/Memory.xml b/Memory.xml index 62f20f9ab..811bef3e9 100644 --- a/Memory.xml +++ b/Memory.xml @@ -1095,6 +1095,11 @@
+
+
+
+
+
@@ -2348,6 +2353,12 @@
+ +
+
+
+
+
cmake @@ -3230,11 +3241,17 @@
- +
+ +
+
+
+
+
diff --git a/library/include/DataDefs.h b/library/include/DataDefs.h index 4acf19c35..e998dc386 100644 --- a/library/include/DataDefs.h +++ b/library/include/DataDefs.h @@ -249,10 +249,16 @@ namespace df { SIMPLE_GLOBAL(job_next_id,int) \ SIMPLE_GLOBAL(ui_look_cursor,int) \ SIMPLE_GLOBAL(ui_workshop_job_cursor,int) \ + SIMPLE_GLOBAL(ui_building_item_cursor,int) \ SIMPLE_GLOBAL(ui_workshop_in_add,bool) \ + SIMPLE_GLOBAL(ui_selected_unit,int) \ + SIMPLE_GLOBAL(cur_year,int) \ + SIMPLE_GLOBAL(cur_year_tick,int) \ GLOBAL(ui_sidebar_menus,ui_sidebar_menus) \ GLOBAL(ui_build_selector,ui_build_selector) \ - GLOBAL(ui_look_list,ui_look_list) + GLOBAL(ui_look_list,ui_look_list) \ + GLOBAL(ui_unit_view_mode, ui_unit_view_mode) + #define SIMPLE_GLOBAL(name,tname) \ namespace global { extern DFHACK_EXPORT tname *name; } diff --git a/library/include/modules/Gui.h b/library/include/modules/Gui.h index 7e07cbd4d..ce087d490 100644 --- a/library/include/modules/Gui.h +++ b/library/include/modules/Gui.h @@ -35,6 +35,8 @@ distribution. namespace df { struct viewscreen; struct job; + struct unit; + struct item; }; /** @@ -46,11 +48,24 @@ namespace DFHack { class Core; + DFHACK_EXPORT bool item_details_hotkey(Core *, df::viewscreen *top); + DFHACK_EXPORT bool unitjobs_hotkey(Core *, df::viewscreen *top); + DFHACK_EXPORT bool workshop_job_hotkey(Core *c, df::viewscreen *top); DFHACK_EXPORT bool build_selector_hotkey(Core *c, df::viewscreen *top); + DFHACK_EXPORT bool view_unit_hotkey(Core *c, df::viewscreen *top); + DFHACK_EXPORT bool unit_inventory_hotkey(Core *c, df::viewscreen *top); + + DFHACK_EXPORT bool any_job_hotkey(Core *c, df::viewscreen *top); + DFHACK_EXPORT bool any_unit_hotkey(Core *c, df::viewscreen *top); + DFHACK_EXPORT bool any_item_hotkey(Core *c, df::viewscreen *top); DFHACK_EXPORT df::job *getSelectedWorkshopJob(Core *c, bool quiet = false); + DFHACK_EXPORT df::job *getSelectedJob(Core *c, bool quiet = false); + DFHACK_EXPORT df::unit *getSelectedUnit(Core *c, bool quiet = false); + DFHACK_EXPORT df::item *getSelectedItem(Core *c, bool quiet = false); + class DFContextShared; /** * A GUI screen diff --git a/library/modules/Gui.cpp b/library/modules/Gui.cpp index 04f23ccba..86b73f556 100644 --- a/library/modules/Gui.cpp +++ b/library/modules/Gui.cpp @@ -38,17 +38,25 @@ using namespace std; #include "ModuleFactory.h" #include "Core.h" #include "PluginManager.h" +#include "MiscUtils.h" using namespace DFHack; #include "DataDefs.h" #include "df/world.h" #include "df/cursor.h" #include "df/viewscreen_dwarfmodest.h" +#include "df/viewscreen_unitjobsst.h" +#include "df/viewscreen_itemst.h" #include "df/ui.h" +#include "df/ui_unit_view_mode.h" +#include "df/ui_sidebar_menus.h" +#include "df/ui_look_list.h" #include "df/job.h" #include "df/ui_build_selector.h" #include "df/building_workshopst.h" #include "df/building_furnacest.h" +#include "df/general_ref.h" +#include "df/unit_inventory_item.h" using namespace df::enums; @@ -69,6 +77,18 @@ bool DFHack::dwarfmode_hotkey(Core *, df::viewscreen *top) return !!strict_virtual_cast(top); } +bool DFHack::unitjobs_hotkey(Core *, df::viewscreen *top) +{ + // Require the main dwarf mode screen + return !!strict_virtual_cast(top); +} + +bool DFHack::item_details_hotkey(Core *, df::viewscreen *top) +{ + // Require the main dwarf mode screen + return !!strict_virtual_cast(top); +} + bool DFHack::cursor_hotkey(Core *c, df::viewscreen *top) { if (!dwarfmode_hotkey(c, top)) @@ -147,6 +167,34 @@ bool DFHack::build_selector_hotkey(Core *c, df::viewscreen *top) } } +bool DFHack::view_unit_hotkey(Core *c, df::viewscreen *top) +{ + using df::global::ui; + using df::global::world; + using df::global::ui_selected_unit; + + if (!dwarfmode_hotkey(c,top)) + return false; + if (ui->main.mode != ui_sidebar_mode::ViewUnits) + return false; + if (!ui_selected_unit) // allow missing + return false; + + return vector_get(world->units.other[0], *ui_selected_unit) != NULL; +} + +bool DFHack::unit_inventory_hotkey(Core *c, df::viewscreen *top) +{ + using df::global::ui_unit_view_mode; + + if (!view_unit_hotkey(c,top)) + return false; + if (!ui_unit_view_mode) + return false; + + return ui_unit_view_mode->value == df::ui_unit_view_mode::Inventory; +} + df::job *DFHack::getSelectedWorkshopJob(Core *c, bool quiet) { using df::global::world; @@ -170,6 +218,166 @@ df::job *DFHack::getSelectedWorkshopJob(Core *c, bool quiet) return selected->jobs[idx]; } +bool DFHack::any_job_hotkey(Core *c, df::viewscreen *top) +{ + if (VIRTUAL_CAST_VAR(screen, df::viewscreen_unitjobsst, top)) + return vector_get(screen->jobs, screen->cursor_pos) != NULL; + + return workshop_job_hotkey(c,top); +} + +df::job *DFHack::getSelectedJob(Core *c, bool quiet) +{ + df::viewscreen *top = c->getTopViewscreen(); + + if (VIRTUAL_CAST_VAR(screen, df::viewscreen_unitjobsst, top)) + { + df::job *job = vector_get(screen->jobs, screen->cursor_pos); + + if (!job && !quiet) + c->con.printerr("Selected unit has no job\n"); + + return job; + } + else + return getSelectedWorkshopJob(c, quiet); +} + +static df::unit *getAnyUnit(Core *c, df::viewscreen *top) +{ + using namespace ui_sidebar_mode; + using df::global::ui; + using df::global::world; + using df::global::ui_look_cursor; + using df::global::ui_look_list; + using df::global::ui_selected_unit; + + if (VIRTUAL_CAST_VAR(screen, df::viewscreen_unitjobsst, top)) + return vector_get(screen->units, screen->cursor_pos); + + if (VIRTUAL_CAST_VAR(screen, df::viewscreen_itemst, top)) + { + df::general_ref *ref = vector_get(screen->entry_ref, screen->cursor_pos); + return ref ? ref->getUnit() : NULL; + } + + if (!dwarfmode_hotkey(c,top)) + return NULL; + + switch (ui->main.mode) { + case ViewUnits: + { + if (!ui_selected_unit) + return NULL; + + return vector_get(world->units.other[0], *ui_selected_unit); + } + case LookAround: + { + if (!ui_look_list || !ui_look_cursor) + return NULL; + + auto item = vector_get(ui_look_list->items, *ui_look_cursor); + if (item && item->type == df::ui_look_list::T_items::Unit) + return item->unit; + else + return NULL; + } + default: + return NULL; + } +} + +bool DFHack::any_unit_hotkey(Core *c, df::viewscreen *top) +{ + return getAnyUnit(c, top) != NULL; +} + +df::unit *DFHack::getSelectedUnit(Core *c, bool quiet) +{ + df::unit *unit = getAnyUnit(c, c->getTopViewscreen()); + + if (!unit && !quiet) + c->con.printerr("No unit is selected in the UI.\n"); + + return unit; +} + +static df::item *getAnyItem(Core *c, df::viewscreen *top) +{ + using namespace ui_sidebar_mode; + using df::global::ui; + using df::global::world; + using df::global::ui_look_cursor; + using df::global::ui_look_list; + using df::global::ui_unit_view_mode; + using df::global::ui_building_item_cursor; + using df::global::ui_sidebar_menus; + + if (VIRTUAL_CAST_VAR(screen, df::viewscreen_itemst, top)) + { + df::general_ref *ref = vector_get(screen->entry_ref, screen->cursor_pos); + return ref ? ref->getItem() : NULL; + } + + if (!dwarfmode_hotkey(c,top)) + return NULL; + + switch (ui->main.mode) { + case ViewUnits: + { + if (!ui_unit_view_mode || !ui_look_cursor || !ui_sidebar_menus) + return NULL; + + if (ui_unit_view_mode->value != df::ui_unit_view_mode::Inventory) + return NULL; + + auto inv_item = vector_get(ui_sidebar_menus->unit.inv_items, *ui_look_cursor); + return inv_item ? inv_item->item : NULL; + } + case LookAround: + { + if (!ui_look_list || !ui_look_cursor) + return NULL; + + auto item = vector_get(ui_look_list->items, *ui_look_cursor); + if (item && item->type == df::ui_look_list::T_items::Item) + return item->item; + else + return NULL; + } + case BuildingItems: + { + if (!ui_building_item_cursor) + return NULL; + + VIRTUAL_CAST_VAR(selected, df::building_actual, world->selected_building); + if (!selected) + return NULL; + + auto inv_item = vector_get(selected->contained_items, *ui_building_item_cursor); + return inv_item ? inv_item->item : NULL; + } + default: + return NULL; + } +} + +bool DFHack::any_item_hotkey(Core *c, df::viewscreen *top) +{ + return getAnyItem(c, top) != NULL; +} + +df::item *DFHack::getSelectedItem(Core *c, bool quiet) +{ + df::item *item = getAnyItem(c, c->getTopViewscreen()); + + if (!item && !quiet) + c->con.printerr("No item is selected in the UI.\n"); + + return item; +} + // Module* DFHack::createGui() diff --git a/library/xml b/library/xml index 91b6531e1..f9c6d105a 160000 --- a/library/xml +++ b/library/xml @@ -1 +1 @@ -Subproject commit 91b6531e1a66e98f7c0ae7f81b5496ccde584b73 +Subproject commit f9c6d105af74cd4e307f513a7df674e685dc9ff0 diff --git a/plugins/cleaners.cpp b/plugins/cleaners.cpp index c25a1ed33..d0b780b4f 100644 --- a/plugins/cleaners.cpp +++ b/plugins/cleaners.cpp @@ -12,6 +12,8 @@ #include "df/unit.h" #include "df/matter_state.h" #include "df/cursor.h" +#include "df/contaminant.h" +#include "df/unit_spatter.h" #include "modules/Materials.h" diff --git a/plugins/rename.cpp b/plugins/rename.cpp index 17841c5fa..8ffc3af05 100644 --- a/plugins/rename.cpp +++ b/plugins/rename.cpp @@ -3,10 +3,16 @@ #include #include +#include + #include #include #include #include +#include +#include +#include +#include #include @@ -30,7 +36,13 @@ DFhackCExport command_result plugin_init (Core *c, std::vector & { commands.clear(); if (world && ui) { - commands.push_back(PluginCommand("rename", "Rename various things.", rename)); + commands.push_back(PluginCommand( + "rename", "Rename various things.", rename, false, + " rename squad \"name\"\n" + " rename hotkey \"name\"\n" + " rename unit \"nickname\"\n" + " (a unit must be highlighted in the ui)\n" + )); } return CR_OK; } @@ -40,12 +52,17 @@ DFhackCExport command_result plugin_shutdown ( Core * c ) return CR_OK; } -static command_result usage(Core *c) +static void set_nickname(df::language_name *name, std::string nick) { - c->con << "Usage:" << endl - << " rename squad \"name\"" << endl - << " rename hotkey \"name\"" << endl; - return CR_OK; + if (!name->has_name) + { + *name = df::language_name(); + + name->language = 0; + name->has_name = true; + } + + name->nickname = nick; } static command_result rename(Core * c, vector ¶meters) @@ -56,34 +73,61 @@ static command_result rename(Core * c, vector ¶meters) if (!parameters.empty()) cmd = parameters[0]; - if (cmd == "squad") { + if (cmd == "squad") + { if (parameters.size() != 3) - return usage(c); - + return CR_WRONG_USAGE; + std::vector &squads = world->squads.all; int id = atoi(parameters[1].c_str()); if (id < 1 || id > squads.size()) { c->con.printerr("Invalid squad index\n"); - return usage(c); + return CR_WRONG_USAGE; } squads[id-1]->alias = parameters[2]; - } else if (cmd == "hotkey") { + } + else if (cmd == "hotkey") + { if (parameters.size() != 3) - return usage(c); + return CR_WRONG_USAGE; int id = atoi(parameters[1].c_str()); if (id < 1 || id > 16) { c->con.printerr("Invalid hotkey index\n"); - return usage(c); + return CR_WRONG_USAGE; } ui->main.hotkeys[id-1].name = parameters[2]; - } else { + } + else if (cmd == "unit") + { + if (parameters.size() != 2) + return CR_WRONG_USAGE; + + df::unit *unit = getSelectedUnit(c); + if (!unit) + return CR_WRONG_USAGE; + + // There are 3 copies of the name, and the one + // in the unit is not the authoritative one. + // This is the reason why military units often + // lose nicknames set from Dwarf Therapist. + set_nickname(&unit->name, parameters[1]); + + if (unit->status.current_soul) + set_nickname(&unit->status.current_soul->name, parameters[1]); + + df::historical_figure *figure = df::historical_figure::find(unit->hist_figure_id); + if (figure) + set_nickname(&figure->name, parameters[1]); + } + else + { if (!parameters.empty() && cmd != "?") c->con.printerr("Invalid command: %s\n", cmd.c_str()); - return usage(c); + return CR_WRONG_USAGE; } return CR_OK; From 990a69ce9b4f04b30ee9e2f5ff09caccf3d4d1fa Mon Sep 17 00:00:00 2001 From: Alexander Gavrilov Date: Sat, 14 Jan 2012 21:13:30 +0400 Subject: [PATCH 58/82] Add hotkey commands to destroy items under cursor, and a specific item. --- plugins/autodump.cpp | 139 +++++++++++++++++++++++++++++++++++++++---- 1 file changed, 126 insertions(+), 13 deletions(-) diff --git a/plugins/autodump.cpp b/plugins/autodump.cpp index 3963bf2af..f9367cb23 100644 --- a/plugins/autodump.cpp +++ b/plugins/autodump.cpp @@ -22,11 +22,18 @@ using namespace std; #include #include +#include +#include +#include +#include + using namespace DFHack; using MapExtras::Block; using MapExtras::MapCache; -DFhackCExport command_result df_autodump (Core * c, vector & parameters); +DFhackCExport command_result df_autodump(Core * c, vector & parameters); +DFhackCExport command_result df_autodump_destroy_here(Core * c, vector & parameters); +DFhackCExport command_result df_autodump_destroy_item(Core * c, vector & parameters); DFhackCExport const char * plugin_name ( void ) { @@ -39,6 +46,18 @@ DFhackCExport command_result plugin_init ( Core * c, std::vector commands.push_back(PluginCommand("autodump", "Teleport items marked for dumping to the cursor.", df_autodump)); + commands.push_back(PluginCommand( + "autodump-destroy-here", "Destroy items marked for dumping under cursor.", + df_autodump_destroy_here, cursor_hotkey, + " Identical to autodump destroy-here, but intended for use as keybinding.\n" + )); + commands.push_back(PluginCommand( + "autodump-destroy-item", "Destroy the selected item.", + df_autodump_destroy_item, any_item_hotkey, + " Destroy the selected item. The item may be selected\n" + " in the 'k' list, or inside a container. If called\n" + " again before the game is resumed, cancels destroy.\n" + )); return CR_OK; } @@ -49,15 +68,18 @@ DFhackCExport command_result plugin_shutdown ( Core * c ) typedef std::map coordmap; -DFhackCExport command_result df_autodump (Core * c, vector & parameters) +static command_result autodump_main(Core * c, vector & parameters) { // Command line options bool destroy = false; + bool here = false; if(parameters.size() > 0) { string & p = parameters[0]; if(p == "destroy") destroy = true; + else if (p == "destroy-here") + destroy = here = true; else if(p == "?" || p == "help") { c->con.print( @@ -66,12 +88,13 @@ DFhackCExport command_result df_autodump (Core * c, vector & parameters "and the forbid flag is set, as if it had been dumped normally.\n" "Be aware that any active dump item tasks still point at the item.\n\n" "Options:\n" - "destroy - instead of dumping, destroy the items instantly.\n" + "destroy - instead of dumping, destroy the items instantly.\n" + "destroy-here - only affect the tile under cursor.\n" ); return CR_OK; } } - c->Suspend(); + DFHack::occupancies40d * occupancies; DFHack::VersionInfo *mem = c->vinfo; DFHack::Gui * Gui = c->getGui(); @@ -82,7 +105,6 @@ DFhackCExport command_result df_autodump (Core * c, vector & parameters if(!Items->readItemVector(p_items)) { c->con.printerr("Can't access the item vector.\n"); - c->Resume(); return CR_FAILURE; } std::size_t numItems = p_items.size(); @@ -91,7 +113,6 @@ DFhackCExport command_result df_autodump (Core * c, vector & parameters if(!Maps->Start()) { c->con.printerr("Can't initialize map.\n"); - c->Resume(); return CR_FAILURE; } MapCache MC (Maps); @@ -100,28 +121,28 @@ DFhackCExport command_result df_autodump (Core * c, vector & parameters int cx, cy, cz; DFCoord pos_cursor; - if(!destroy) + if(!destroy || here) { if (!Gui->getCursorCoords(cx,cy,cz)) { c->con.printerr("Cursor position not found. Please enabled the cursor.\n"); - c->Resume(); return CR_FAILURE; } pos_cursor = DFCoord(cx,cy,cz); + } + if (!destroy) + { { Block * b = MC.BlockAt(pos_cursor / 16); if(!b) { c->con.printerr("Cursor is in an invalid/uninitialized area. Place it over a floor.\n"); - c->Resume(); return CR_FAILURE; } uint16_t ttype = MC.tiletypeAt(pos_cursor); if(!DFHack::isFloorTerrain(ttype)) { c->con.printerr("Cursor should be placed over a floor.\n"); - c->Resume(); return CR_FAILURE; } } @@ -154,7 +175,7 @@ DFhackCExport command_result df_autodump (Core * c, vector & parameters || itm->flags.in_building || itm->flags.in_chest || itm->flags.in_inventory - || itm->flags.construction + || itm->flags.artifact1 ) continue; @@ -200,7 +221,14 @@ DFhackCExport command_result df_autodump (Core * c, vector & parameters } else // destroy { + if (here && pos_item != pos_cursor) + continue; + itm->flags.garbage_colect = true; + + // Cosmetic changes: make them disappear from view instantly + itm->flags.forbid = true; + itm->flags.hidden = true; } // keeping track of item pile sizes ;) it->second --; @@ -238,7 +266,92 @@ DFhackCExport command_result df_autodump (Core * c, vector & parameters // Is this necessary? Is "forbid" a dirtyable attribute like "dig" is? Maps->WriteDirtyBit(cx/16, cy/16, cz, true); } - c->Resume(); c->con.print("Done. %d items %s.\n", dumped_total, destroy ? "marked for desctruction" : "quickdumped"); return CR_OK; -} \ No newline at end of file +} + +DFhackCExport command_result df_autodump(Core * c, vector & parameters) +{ + CoreSuspender suspend(c); + + return autodump_main(c, parameters); +} + +DFhackCExport command_result df_autodump_destroy_here(Core * c, vector & parameters) +{ + // HOTKEY COMMAND; CORE ALREADY SUSPENDED + if (!parameters.empty()) + return CR_WRONG_USAGE; + + vector args; + args.push_back("destroy-here"); + + return autodump_main(c, args); +} + +static std::map pending_destroy; +static int last_frame = 0; + +DFhackCExport command_result df_autodump_destroy_item(Core * c, vector & parameters) +{ + // HOTKEY COMMAND; CORE ALREADY SUSPENDED + if (!parameters.empty()) + return CR_WRONG_USAGE; + + df::item *item = getSelectedItem(c); + if (!item) + return CR_FAILURE; + + // Allow undoing the destroy + if (df::global::world->frame_counter != last_frame) + { + last_frame = df::global::world->frame_counter; + pending_destroy.clear(); + } + + if (pending_destroy.count(item->id)) + { + df::item_flags old_flags = pending_destroy[item->id]; + pending_destroy.erase(item->id); + + item->flags.bits.garbage_colect = false; + item->flags.bits.hidden = old_flags.bits.hidden; + item->flags.bits.dump = old_flags.bits.dump; + item->flags.bits.forbid = old_flags.bits.forbid; + return CR_OK; + } + + // Check the item is good to destroy + if (item->flags.bits.garbage_colect) + { + c->con.printerr("Item is already marked for destroy.\n"); + return CR_FAILURE; + } + + if (item->flags.bits.construction || + item->flags.bits.in_building || + item->flags.bits.artifact1) + { + c->con.printerr("Choosing not to destroy buildings, constructions and artifacts.\n"); + return CR_FAILURE; + } + + for (unsigned i = 0; i < item->itemrefs.size(); i++) + { + df::general_ref *ref = item->itemrefs[i]; + if (strict_virtual_cast(ref)) + { + c->con.printerr("Choosing not to destroy items in unit inventory.\n"); + return CR_FAILURE; + } + } + + // Set the flags + pending_destroy[item->id] = item->flags; + + item->flags.bits.garbage_colect = true; + item->flags.bits.hidden = true; + item->flags.bits.dump = true; + item->flags.bits.forbid = true; + return CR_OK; +} From 8135420d87b88917b734ec448cfd4677279fead2 Mon Sep 17 00:00:00 2001 From: Alexander Gavrilov Date: Sun, 15 Jan 2012 12:50:53 +0400 Subject: [PATCH 59/82] Let job-material use any material in the build item selection mode. --- plugins/jobutils.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/plugins/jobutils.cpp b/plugins/jobutils.cpp index 8557f0102..4b89591a4 100644 --- a/plugins/jobutils.cpp +++ b/plugins/jobutils.cpp @@ -123,6 +123,13 @@ static command_result job_material_in_job(Core *c, MaterialInfo &new_mat) 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) @@ -241,8 +248,8 @@ static command_result job_material(Core * c, vector & parameters) MaterialInfo new_mat; if (parameters.size() == 1) { - if (!new_mat.findInorganic(parameters[0])) { - c->con.printerr("Could not find inorganic material: %s\n", parameters[0].c_str()); + if (!new_mat.find(parameters[0])) { + c->con.printerr("Could not find material: %s\n", parameters[0].c_str()); return CR_WRONG_USAGE; } } From 54485d25510c824809982d58dfb9045088f4572a Mon Sep 17 00:00:00 2001 From: Alexander Gavrilov Date: Sun, 15 Jan 2012 12:58:36 +0400 Subject: [PATCH 60/82] Move plant material detection to guess_job_material in workflow. So that the data will be available to shortJobDescription. --- plugins/workflow.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/plugins/workflow.cpp b/plugins/workflow.cpp index e8ac9a4cc..4306c3431 100644 --- a/plugins/workflow.cpp +++ b/plugins/workflow.cpp @@ -829,7 +829,9 @@ static void guess_job_material(df::job *job, MaterialInfo &mat, df::dfhack_mater } // Material from the job reagent - if (!mat.isValid() && job->job_items.size() == 1) + 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]); @@ -899,9 +901,6 @@ static void compute_job_outputs(Core *c, ProtectedJob *pj) break; #define PLANT_PROCESS_MAT(flag, tag) \ - if (!mat.isValid() && !job->job_items.empty()\ - && job->job_items[0]->item_type == item_type::PLANT) \ - mat.decode(job->job_items[0]); \ 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); \ From 0f56611edcfa4bb1be7c82f69b9d838d66332a4a Mon Sep 17 00:00:00 2001 From: Alexander Gavrilov Date: Sun, 15 Jan 2012 15:19:20 +0400 Subject: [PATCH 61/82] Support showing announcements, as suggested by Q. --- library/include/modules/Gui.h | 27 +++++++++++--- library/modules/Gui.cpp | 66 +++++++++++++++++++++++++++++++++++ library/xml | 2 +- 3 files changed, 90 insertions(+), 5 deletions(-) diff --git a/library/include/modules/Gui.h b/library/include/modules/Gui.h index ce087d490..34a62308c 100644 --- a/library/include/modules/Gui.h +++ b/library/include/modules/Gui.h @@ -48,24 +48,43 @@ namespace DFHack { class Core; + // Full-screen item details view DFHACK_EXPORT bool item_details_hotkey(Core *, df::viewscreen *top); + // 'u'nits or 'j'obs full-screen view DFHACK_EXPORT bool unitjobs_hotkey(Core *, df::viewscreen *top); + // A job is selected in a workshop DFHACK_EXPORT bool workshop_job_hotkey(Core *c, df::viewscreen *top); + // Building material selection mode DFHACK_EXPORT bool build_selector_hotkey(Core *c, df::viewscreen *top); + // A unit is selected in the 'v' mode DFHACK_EXPORT bool view_unit_hotkey(Core *c, df::viewscreen *top); + // Above + the inventory page is selected. DFHACK_EXPORT bool unit_inventory_hotkey(Core *c, df::viewscreen *top); - DFHACK_EXPORT bool any_job_hotkey(Core *c, df::viewscreen *top); - DFHACK_EXPORT bool any_unit_hotkey(Core *c, df::viewscreen *top); - DFHACK_EXPORT bool any_item_hotkey(Core *c, df::viewscreen *top); - + // In workshop_job_hotkey, returns the job DFHACK_EXPORT df::job *getSelectedWorkshopJob(Core *c, bool quiet = false); + // A job is selected in a workshop, or unitjobs + DFHACK_EXPORT bool any_job_hotkey(Core *c, df::viewscreen *top); DFHACK_EXPORT df::job *getSelectedJob(Core *c, bool quiet = false); + + // A unit is selected via 'v', 'k', unitjobs, or + // a full-screen item view of a cage or suchlike + DFHACK_EXPORT bool any_unit_hotkey(Core *c, df::viewscreen *top); DFHACK_EXPORT df::unit *getSelectedUnit(Core *c, bool quiet = false); + + // An item is selected via 'v'->inventory, 'k', 't', or + // a full-screen item view of a container. Note that in the + // last case, the highlighted contained item is returned, not + // the container itself. + DFHACK_EXPORT bool any_item_hotkey(Core *c, df::viewscreen *top); DFHACK_EXPORT df::item *getSelectedItem(Core *c, bool quiet = false); + // Show a plain announcement, or a titan-style popup message + DFHACK_EXPORT void showAnnouncement(std::string message, int color = 7, bool bright = true); + DFHACK_EXPORT void showPopupAnnouncement(std::string message, int color = 7, bool bright = true); + class DFContextShared; /** * A GUI screen diff --git a/library/modules/Gui.cpp b/library/modules/Gui.cpp index 86b73f556..adef1acae 100644 --- a/library/modules/Gui.cpp +++ b/library/modules/Gui.cpp @@ -57,6 +57,8 @@ using namespace DFHack; #include "df/building_furnacest.h" #include "df/general_ref.h" #include "df/unit_inventory_item.h" +#include "df/report.h" +#include "df/popup_message.h" using namespace df::enums; @@ -380,6 +382,70 @@ df::item *DFHack::getSelectedItem(Core *c, bool quiet) // +void DFHack::showAnnouncement(std::string message, int color, bool bright) +{ + using df::global::world; + using df::global::cur_year; + using df::global::cur_year_tick; + + int year = 0, year_time = 0; + + if (cur_year && cur_year_tick) + { + year = *cur_year; + year_time = *cur_year_tick; + } + else if (!world->status.reports.empty()) + { + // Fallback: copy from the last report + df::report *last = world->status.reports.back(); + year = last->year; + year_time = last->time; + } + + bool continued = false; + + while (!message.empty()) + { + df::report *new_rep = new df::report(); + + new_rep->color = color; + new_rep->bright = bright; + new_rep->year = year; + new_rep->time = year_time; + + new_rep->flags.bits.continuation = continued; + new_rep->flags.bits.announcement = true; + + int size = std::min(message.size(), 73U); + new_rep->text = message.substr(0, size); + message = message.substr(size); + + continued = true; + + // Add the object to the lists + new_rep->id = world->status.next_report_id++; + + world->status.reports.push_back(new_rep); + world->status.announcements.push_back(new_rep); + world->status.display_timer = 2000; + } + +} + +void DFHack::showPopupAnnouncement(std::string message, int color, bool bright) +{ + using df::global::world; + + df::popup_message *popup = new df::popup_message(); + popup->text = message; + popup->color = color; + popup->bright = bright; + world->status.popups.push_back(popup); +} + +// + Module* DFHack::createGui() { return new Gui(); diff --git a/library/xml b/library/xml index f9c6d105a..30ce6e3d5 160000 --- a/library/xml +++ b/library/xml @@ -1 +1 @@ -Subproject commit f9c6d105af74cd4e307f513a7df674e685dc9ff0 +Subproject commit 30ce6e3d537ccc51e232c129680d53d5d58180fc From bcb51d8ff72f3d030a38cbb05f8b84378ca38352 Mon Sep 17 00:00:00 2001 From: Alexander Gavrilov Date: Sun, 15 Jan 2012 15:39:20 +0400 Subject: [PATCH 62/82] Use the announcement API to report starting and stopping workflow jobs. --- library/include/modules/Items.h | 1 + library/modules/Items.cpp | 53 ++++++++++++++++++--------- plugins/workflow.cpp | 63 ++++++++++++++++++++++++++++++--- 3 files changed, 96 insertions(+), 21 deletions(-) diff --git a/library/include/modules/Items.h b/library/include/modules/Items.h index 1e889fca1..d0424a6f0 100644 --- a/library/include/modules/Items.h +++ b/library/include/modules/Items.h @@ -71,6 +71,7 @@ namespace DFHack return ptr ? decode(ptr->item_type, ptr->item_subtype) : decode(df::enums::item_type::NONE); } + std::string getToken(); std::string toString(); bool find(const std::string &token); diff --git a/library/modules/Items.cpp b/library/modules/Items.cpp index 8ec4e2301..9fffcc03d 100644 --- a/library/modules/Items.cpp +++ b/library/modules/Items.cpp @@ -68,20 +68,20 @@ using namespace DFHack; using namespace df::enums; #define ITEMDEF_VECTORS \ - ITEM(WEAPON, weapons) \ - ITEM(TRAPCOMP, trapcomps) \ - ITEM(TOY, toys) \ - ITEM(TOOL, tools) \ - ITEM(INSTRUMENT, instruments) \ - ITEM(ARMOR, armor) \ - ITEM(AMMO, ammo) \ - ITEM(SIEGEAMMO, siege_ammo) \ - ITEM(GLOVES, gloves) \ - ITEM(SHOES, shoes) \ - ITEM(SHIELD, shields) \ - ITEM(HELM, helms) \ - ITEM(PANTS, pants) \ - ITEM(FOOD, food) + ITEM(WEAPON, weapons, itemdef_weaponst) \ + ITEM(TRAPCOMP, trapcomps, itemdef_trapcompst) \ + ITEM(TOY, toys, itemdef_toyst) \ + ITEM(TOOL, tools, itemdef_toolst) \ + ITEM(INSTRUMENT, instruments, itemdef_instrumentst) \ + ITEM(ARMOR, armor, itemdef_armorst) \ + ITEM(AMMO, ammo, itemdef_ammost) \ + ITEM(SIEGEAMMO, siege_ammo, itemdef_siegeammost) \ + ITEM(GLOVES, gloves, itemdef_glovesst) \ + ITEM(SHOES, shoes, itemdef_shoesst) \ + ITEM(SHIELD, shields, itemdef_shieldst) \ + ITEM(HELM, helms, itemdef_helmst) \ + ITEM(PANTS, pants, itemdef_pantsst) \ + ITEM(FOOD, food, itemdef_foodst) bool ItemTypeInfo::decode(df::item_type type_, int16_t subtype_) { @@ -97,7 +97,7 @@ bool ItemTypeInfo::decode(df::item_type type_, int16_t subtype_) case NONE: return false; -#define ITEM(type,vec) \ +#define ITEM(type,vec,tclass) \ case type: \ custom = vector_get(defs.vec, subtype); \ break; @@ -119,7 +119,7 @@ bool ItemTypeInfo::decode(df::item *ptr) return decode(ptr->getType(), ptr->getSubtype()); } -std::string ItemTypeInfo::toString() +std::string ItemTypeInfo::getToken() { std::string rv = ENUM_KEY_STR(item_type, type); if (custom) @@ -129,6 +129,25 @@ std::string ItemTypeInfo::toString() return rv; } +std::string ItemTypeInfo::toString() +{ + using namespace df::enums::item_type; + + switch (type) { +#define ITEM(type,vec,tclass) \ + case type: \ + if (VIRTUAL_CAST_VAR(cv, df::tclass, custom)) \ + return cv->name; +ITEMDEF_VECTORS +#undef ITEM + + default: + break; + } + + return toLower(ENUM_KEY_STR(item_type, type)); +} + bool ItemTypeInfo::find(const std::string &token) { using namespace df::enums::item_type; @@ -164,7 +183,7 @@ bool ItemTypeInfo::find(const std::string &token) df::world_raws::T_itemdefs &defs = df::global::world->raws.itemdefs; switch (type) { -#define ITEM(type,vec) \ +#define ITEM(type,vec,tclass) \ case type: \ for (int i = 0; i < defs.vec.size(); i++) { \ if (defs.vec[i]->id == items[1]) { \ diff --git a/plugins/workflow.cpp b/plugins/workflow.cpp index 4306c3431..e2fe03fc9 100644 --- a/plugins/workflow.cpp +++ b/plugins/workflow.cpp @@ -282,10 +282,15 @@ struct ItemConstraint { int item_amount, item_count, item_inuse; bool request_suspend, request_resume; + bool is_active, cant_resume_reported; + TMaterialCache material_cache; public: - ItemConstraint() : weight(0), item_amount(0), item_count(0), item_inuse(0) {} + ItemConstraint() + : weight(0), item_amount(0), item_count(0), item_inuse(0) + , is_active(false), cant_resume_reported(false) + {} int goalCount() { return config.ival(0); } void setGoalCount(int v) { config.ival(0) = v; } @@ -341,6 +346,7 @@ static std::vector pending_recover; static std::vector constraints; static int meltable_count = 0; +static bool melt_active = false; /****************************** * MISC FUNCTIONS * @@ -745,6 +751,9 @@ static void link_job_constraint(ProtectedJob *pj, df::item_type itype, int16_t i ct->jobs.push_back(pj); pj->constraints.push_back(ct); + + if (!ct->is_active && pj->isResumed()) + ct->is_active = true; } } @@ -934,17 +943,27 @@ static void compute_job_outputs(Core *c, ProtectedJob *pj) static void map_job_constraints(Core *c) { + melt_active = false; + for (unsigned 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) { - it->second->constraints.clear(); + ProtectedJob *pj = it->second; + + pj->constraints.clear(); - if (!it->second->isLive()) + if (!pj->isLive()) continue; - compute_job_outputs(c, it->second); + if (!melt_active && pj->actual_job->job_type == job_type::MeltMetalObject) + melt_active = pj->isResumed(); + + compute_job_outputs(c, pj); } } @@ -1158,6 +1177,42 @@ static void update_jobs_by_constraints(Core *c) setJobResumed(c, pj, goal); } + + for (unsigned i = 0; i < constraints.size(); i++) + { + ItemConstraint *ct = constraints[i]; + + bool is_running = false; + for (unsigned j = 0; j < ct->jobs.size(); j++) + if (!!(is_running = ct->jobs[j]->isResumed())) + break; + + std::string info = ct->item.toString(); + + if (ct->material.isValid()) + info = ct->material.toString() + " " + info; + else if (ct->mat_mask.whole) + info = bitfieldToString(ct->mat_mask) + " " + info; + + if (is_running != ct->is_active) + { + if (is_running && ct->request_resume) + showAnnouncement("Resuming production: " + info, 2, false); + else if (!is_running && !ct->request_resume) + showAnnouncement("Stopping production: " + info, 3, false); + } + + if (ct->request_resume && !is_running) + { + if (!ct->cant_resume_reported) + showAnnouncement("Cannot produce: " + info, 6, true); + ct->cant_resume_reported = true; + } + else + { + ct->cant_resume_reported = false; + } + } } static void process_constraints(Core *c) From 81587337452dfbc56decf44cdc038ef10ef8bcdc Mon Sep 17 00:00:00 2001 From: Alexander Gavrilov Date: Sun, 15 Jan 2012 15:57:33 +0400 Subject: [PATCH 63/82] Support changing the custom profession via rename. Likewise, it works for any unit, including animals and enemies. --- plugins/rename.cpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/plugins/rename.cpp b/plugins/rename.cpp index 8ffc3af05..9cd864042 100644 --- a/plugins/rename.cpp +++ b/plugins/rename.cpp @@ -40,7 +40,9 @@ DFhackCExport command_result plugin_init (Core *c, std::vector & "rename", "Rename various things.", rename, false, " rename squad \"name\"\n" " rename hotkey \"name\"\n" + " (identified by ordinal index)\n" " rename unit \"nickname\"\n" + " rename unit-profession \"custom profession\"\n" " (a unit must be highlighted in the ui)\n" )); } @@ -123,6 +125,17 @@ static command_result rename(Core * c, vector ¶meters) if (figure) set_nickname(&figure->name, parameters[1]); } + else if (cmd == "unit-profession") + { + if (parameters.size() != 2) + return CR_WRONG_USAGE; + + df::unit *unit = getSelectedUnit(c); + if (!unit) + return CR_WRONG_USAGE; + + unit->custom_profession = parameters[1]; + } else { if (!parameters.empty() && cmd != "?") From f0f354f3c73af85090db609af4b14389591a615a Mon Sep 17 00:00:00 2001 From: Alexander Gavrilov Date: Sun, 15 Jan 2012 20:45:02 +0400 Subject: [PATCH 64/82] Don't count stuff in flasks and backpacks as available in workflow. --- plugins/workflow.cpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/plugins/workflow.cpp b/plugins/workflow.cpp index e2fe03fc9..38e2313cd 100644 --- a/plugins/workflow.cpp +++ b/plugins/workflow.cpp @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -993,6 +994,7 @@ static void dryBucket(df::item *item) static bool itemBusy(df::item *item) { + using namespace df::enums::item_type; for (unsigned i = 0; i < item->itemrefs.size(); i++) { @@ -1010,6 +1012,17 @@ static bool itemBusy(df::item *item) if (!item->flags.bits.in_job) return true; } + else if (strict_virtual_cast(ref)) + { + df::item *obj = ref->getItem(); + if (!obj) + continue; + + // Stuff in flasks and backpacks is busy + df::item_type type = obj->getType(); + if ((type == FLASK && item->getType() == DRINK) || type == BACKPACK) + return true; + } } return false; From f3cbf07a0130a1f41c3e14ce320516425604d01f Mon Sep 17 00:00:00 2001 From: Quietust Date: Sun, 15 Jan 2012 13:59:34 -0600 Subject: [PATCH 65/82] Use general_ref::getType() instead of strict_virtual_cast<> --- plugins/autodump.cpp | 2 +- plugins/workflow.cpp | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/plugins/autodump.cpp b/plugins/autodump.cpp index 109253dc5..5fc9adfc2 100644 --- a/plugins/autodump.cpp +++ b/plugins/autodump.cpp @@ -338,7 +338,7 @@ DFhackCExport command_result df_autodump_destroy_item(Core * c, vector for (unsigned i = 0; i < item->itemrefs.size(); i++) { df::general_ref *ref = item->itemrefs[i]; - if (strict_virtual_cast(ref)) + if (ref->getType() == df::general_ref_type::unit_holder) { c->con.printerr("Choosing not to destroy items in unit inventory.\n"); return CR_FAILURE; diff --git a/plugins/workflow.cpp b/plugins/workflow.cpp index 38e2313cd..104604ce6 100644 --- a/plugins/workflow.cpp +++ b/plugins/workflow.cpp @@ -977,7 +977,7 @@ static void dryBucket(df::item *item) for (unsigned i = 0; i < item->itemrefs.size(); i++) { df::general_ref *ref = item->itemrefs[i]; - if (strict_virtual_cast(ref)) + if (ref->getType() == df::general_ref_type::contains_item) { df::item *obj = ref->getItem(); @@ -999,20 +999,20 @@ static bool itemBusy(df::item *item) for (unsigned i = 0; i < item->itemrefs.size(); i++) { df::general_ref *ref = item->itemrefs[i]; - if (strict_virtual_cast(ref)) + if (ref->getType() == df::general_ref_type::contains_item) { df::item *obj = ref->getItem(); if (obj && !obj->flags.bits.garbage_colect) return true; } - else if (strict_virtual_cast(ref)) + else if (ref->getType() == df::general_ref_type::contains_unit) return true; - else if (strict_virtual_cast(ref)) + else if (ref->getType() == df::general_ref_type::unit_holder) { if (!item->flags.bits.in_job) return true; } - else if (strict_virtual_cast(ref)) + else if (ref->getType() == df::general_ref_type::contained_in_item) { df::item *obj = ref->getItem(); if (!obj) From e82055986e1d0850915095721175a32656c716c5 Mon Sep 17 00:00:00 2001 From: Quietust Date: Sun, 15 Jan 2012 14:54:14 -0600 Subject: [PATCH 66/82] Only use #include <> for system libraries - for everything else, use "" --- library/modules/Job.cpp | 18 +++++----- plugins/autodump.cpp | 32 +++++++++--------- plugins/cleaners.cpp | 8 ++--- plugins/cleanowned.cpp | 16 ++++----- plugins/colonies.cpp | 18 +++++----- plugins/deramp.cpp | 10 +++--- plugins/drybuckets.cpp | 10 +++--- plugins/fastdwarf.cpp | 8 ++--- plugins/filltraffic.cpp | 14 ++++---- plugins/fixwagons.cpp | 10 +++--- plugins/flows.cpp | 8 ++--- plugins/getplants.cpp | 12 +++---- plugins/initflags.cpp | 10 +++--- plugins/jobutils.cpp | 51 ++++++++++++++-------------- plugins/liquids.cpp | 16 ++++----- plugins/mode.cpp | 10 +++--- plugins/plants.cpp | 16 ++++----- plugins/probe.cpp | 21 ++++++------ plugins/prospector.cpp | 8 ++--- plugins/regrass.cpp | 10 +++--- plugins/rename.cpp | 28 ++++++++-------- plugins/reveal.cpp | 16 ++++----- plugins/seedwatch.cpp | 2 +- plugins/stockpiles.cpp | 20 +++++------ plugins/tiletypes.cpp | 16 ++++----- plugins/tubefill.cpp | 14 ++++---- plugins/vdig.cpp | 12 +++---- plugins/versionosd.cpp | 12 +++---- plugins/weather.cpp | 8 ++--- plugins/workflow.cpp | 74 ++++++++++++++++++++--------------------- 30 files changed, 252 insertions(+), 256 deletions(-) diff --git a/library/modules/Job.cpp b/library/modules/Job.cpp index 80c332fc8..be9560890 100644 --- a/library/modules/Job.cpp +++ b/library/modules/Job.cpp @@ -1,4 +1,4 @@ -/* +/* https://github.com/peterix/dfhack Copyright (c) 2009-2011 Petr Mrázek (peterix@gmail.com) @@ -40,14 +40,14 @@ using namespace std; #include "modules/Items.h" #include "DataDefs.h" -#include -#include -#include -#include -#include -#include -#include -#include +#include "df/world.h" +#include "df/ui.h" +#include "df/job.h" +#include "df/job_item.h" +#include "df/job_list_link.h" +#include "df/general_ref.h" +#include "df/general_ref_unit_workerst.h" +#include "df/general_ref_building_holderst.h" using namespace DFHack; using namespace df::enums; diff --git a/plugins/autodump.cpp b/plugins/autodump.cpp index 5fc9adfc2..2e2bb4db4 100644 --- a/plugins/autodump.cpp +++ b/plugins/autodump.cpp @@ -5,27 +5,25 @@ #include #include #include +#include +#include #include using namespace std; #include "Core.h" -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include -#include -#include -#include +#include "Console.h" +#include "Export.h" +#include "PluginManager.h" +#include "modules/Maps.h" +#include "modules/Gui.h" +#include "modules/Items.h" +#include "modules/Materials.h" +#include "modules/MapCache.h" + +#include "DataDefs.h" +#include "df/item.h" +#include "df/world.h" +#include "df/general_ref.h" using namespace DFHack; using MapExtras::Block; diff --git a/plugins/cleaners.cpp b/plugins/cleaners.cpp index fcfc166ff..1ee4b3406 100644 --- a/plugins/cleaners.cpp +++ b/plugins/cleaners.cpp @@ -1,7 +1,7 @@ #include "Core.h" -#include -#include -#include +#include "Console.h" +#include "Export.h" +#include "PluginManager.h" #include "DataDefs.h" #include "df/world.h" @@ -227,4 +227,4 @@ DFhackCExport command_result plugin_init ( Core * c, std::vector DFhackCExport command_result plugin_shutdown ( Core * c ) { return CR_OK; -} \ No newline at end of file +} diff --git a/plugins/cleanowned.cpp b/plugins/cleanowned.cpp index 1899129c1..966d8e335 100644 --- a/plugins/cleanowned.cpp +++ b/plugins/cleanowned.cpp @@ -9,16 +9,16 @@ using namespace std; #include "Core.h" -#include -#include -#include +#include "Console.h" +#include "Export.h" +#include "PluginManager.h" #include #include -#include -#include -#include -#include -#include +#include "modules/Maps.h" +#include "modules/Items.h" +#include "modules/Units.h" +#include "modules/Materials.h" +#include "modules/Translation.h" using namespace DFHack; DFhackCExport command_result df_cleanowned (Core * c, vector & parameters); diff --git a/plugins/colonies.cpp b/plugins/colonies.cpp index 3089b7ccd..ba1e16cc7 100644 --- a/plugins/colonies.cpp +++ b/plugins/colonies.cpp @@ -1,16 +1,16 @@ #include "Core.h" -#include -#include -#include +#include "Console.h" +#include "Export.h" +#include "PluginManager.h" #include #include -#include +#include "modules/Vermin.h" +#include "modules/Materials.h" using std::vector; using std::string; using namespace DFHack; using namespace DFHack::Simple; -#include DFhackCExport command_result colonies (Core * c, vector & parameters); @@ -34,8 +34,8 @@ DFhackCExport command_result plugin_shutdown ( Core * c ) } void destroyColonies(); -void convertColonies(DFHack::Materials *Materials); -void showColonies(Core *c, DFHack::Materials *Materials); +void convertColonies(Materials *Materials); +void showColonies(Core *c, Materials *Materials); DFhackCExport command_result colonies (Core * c, vector & parameters) { @@ -106,7 +106,7 @@ void destroyColonies() } // Convert all colonies to honey bees. -void convertColonies(DFHack::Materials *Materials) +void convertColonies(Materials *Materials) { int bee_idx = -1; for (size_t i = 0; i < Materials->raceEx.size(); i++) @@ -136,7 +136,7 @@ void convertColonies(DFHack::Materials *Materials) } } -void showColonies(Core *c, DFHack::Materials *Materials) +void showColonies(Core *c, Materials *Materials) { uint32_t numSpawnPoints = Vermin::getNumVermin(); int numColonies = 0; diff --git a/plugins/deramp.cpp b/plugins/deramp.cpp index 72801b77a..a86b61e8e 100644 --- a/plugins/deramp.cpp +++ b/plugins/deramp.cpp @@ -1,15 +1,15 @@ // De-ramp. All ramps marked for removal are replaced with given tile (presently, normal floor). #include "Core.h" -#include -#include -#include +#include "Console.h" +#include "Export.h" +#include "PluginManager.h" #include "DataDefs.h" #include "df/world.h" #include "df/map_block.h" #include "df/tile_dig_designation.h" -#include +#include "TileTypes.h" using std::vector; using std::string; @@ -111,4 +111,4 @@ DFhackCExport command_result plugin_init ( Core * c, std::vector DFhackCExport command_result plugin_shutdown ( Core * c ) { return CR_OK; -} \ No newline at end of file +} diff --git a/plugins/drybuckets.cpp b/plugins/drybuckets.cpp index c824ddfe9..abe692c0a 100644 --- a/plugins/drybuckets.cpp +++ b/plugins/drybuckets.cpp @@ -1,11 +1,11 @@ // Dry Buckets : Remove all "water" objects from buckets scattered around the fortress #include "Core.h" -#include -#include -#include +#include "Console.h" +#include "Export.h" +#include "PluginManager.h" -#include +#include "DataDefs.h" #include "df/world.h" #include "df/item.h" #include "df/builtin_mats.h" @@ -53,4 +53,4 @@ DFhackCExport command_result plugin_init ( Core * c, std::vector DFhackCExport command_result plugin_shutdown ( Core * c ) { return CR_OK; -} \ No newline at end of file +} diff --git a/plugins/fastdwarf.cpp b/plugins/fastdwarf.cpp index c8265be52..23310898c 100644 --- a/plugins/fastdwarf.cpp +++ b/plugins/fastdwarf.cpp @@ -1,9 +1,9 @@ #include "Core.h" -#include -#include -#include +#include "Console.h" +#include "Export.h" +#include "PluginManager.h" -#include +#include "DataDefs.h" #include "df/ui.h" #include "df/world.h" #include "df/unit.h" diff --git a/plugins/filltraffic.cpp b/plugins/filltraffic.cpp index a5c2188fe..b011bce2c 100644 --- a/plugins/filltraffic.cpp +++ b/plugins/filltraffic.cpp @@ -6,12 +6,12 @@ #include #include #include "Core.h" -#include -#include -#include -#include -#include -#include +#include "Console.h" +#include "Export.h" +#include "PluginManager.h" +#include "modules/Maps.h" +#include "modules/MapCache.h" +#include "modules/Gui.h" using std::stack; using MapExtras::MapCache; using namespace DFHack; @@ -377,4 +377,4 @@ void allRestricted(DFHack::DFCoord coord, MapExtras::MapCache * map) DFHack::t_designation des = map->designationAt(coord); des.bits.traffic = traffic_restricted; map->setDesignationAt(coord, des); -} \ No newline at end of file +} diff --git a/plugins/fixwagons.cpp b/plugins/fixwagons.cpp index 3d7c5ff9b..9f9a4732f 100644 --- a/plugins/fixwagons.cpp +++ b/plugins/fixwagons.cpp @@ -1,11 +1,11 @@ // I'll fix his little red wagon... #include "Core.h" -#include -#include -#include +#include "Console.h" +#include "Export.h" +#include "PluginManager.h" -#include +#include "DataDefs.h" #include "df/world.h" #include "df/historical_entity.h" #include "df/entity_raw.h" @@ -103,4 +103,4 @@ DFhackCExport command_result plugin_init ( Core * c, std::vector DFhackCExport command_result plugin_shutdown ( Core * c ) { return CR_OK; -} \ No newline at end of file +} diff --git a/plugins/flows.cpp b/plugins/flows.cpp index fd4c0c579..757bf9710 100644 --- a/plugins/flows.cpp +++ b/plugins/flows.cpp @@ -1,11 +1,11 @@ // This tool counts static tiles and active flows of water and magma. #include "Core.h" -#include -#include -#include +#include "Console.h" +#include "Export.h" +#include "PluginManager.h" -#include +#include "DataDefs.h" #include "df/world.h" #include "df/map_block.h" #include "df/tile_liquid.h" diff --git a/plugins/getplants.cpp b/plugins/getplants.cpp index 5643676aa..c2ddc4992 100644 --- a/plugins/getplants.cpp +++ b/plugins/getplants.cpp @@ -1,12 +1,12 @@ // Designate all matching plants for gathering/cutting #include "Core.h" -#include -#include -#include +#include "Console.h" +#include "Export.h" +#include "PluginManager.h" -#include -#include +#include "DataDefs.h" +#include "TileTypes.h" #include "df/world.h" #include "df/map_block.h" #include "df/tile_dig_designation.h" @@ -152,4 +152,4 @@ DFhackCExport command_result plugin_init ( Core * c, vector &com DFhackCExport command_result plugin_shutdown ( Core * c ) { return CR_OK; -} \ No newline at end of file +} diff --git a/plugins/initflags.cpp b/plugins/initflags.cpp index c7a634b78..d6d03811e 100644 --- a/plugins/initflags.cpp +++ b/plugins/initflags.cpp @@ -1,10 +1,10 @@ #include "Core.h" -#include -#include -#include +#include "Console.h" +#include "Export.h" +#include "PluginManager.h" -#include -#include +#include "DataDefs.h" +#include "df/d_init.h" using std::vector; using std::string; diff --git a/plugins/jobutils.cpp b/plugins/jobutils.cpp index 4b89591a4..e7cca6bf0 100644 --- a/plugins/jobutils.cpp +++ b/plugins/jobutils.cpp @@ -1,30 +1,29 @@ #include "Core.h" -#include -#include -#include -#include - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include "Console.h" +#include "Export.h" +#include "PluginManager.h" +#include "MiscUtils.h" + +#include "modules/Materials.h" +#include "modules/Items.h" +#include "modules/Gui.h" +#include "modules/Job.h" + +#include "DataDefs.h" +#include "df/world.h" +#include "df/ui.h" +#include "df/ui_build_selector.h" +#include "df/ui_build_item_req.h" +#include "df/build_req_choice_genst.h" +#include "df/build_req_choice_specst.h" +#include "df/building_workshopst.h" +#include "df/building_furnacest.h" +#include "df/job.h" +#include "df/job_item.h" +#include "df/job_list_link.h" +#include "df/item.h" +#include "df/tool_uses.h" +#include "df/general_ref.h" using std::vector; using std::string; diff --git a/plugins/liquids.cpp b/plugins/liquids.cpp index 17f4e6309..4b6af8735 100644 --- a/plugins/liquids.cpp +++ b/plugins/liquids.cpp @@ -10,14 +10,14 @@ using std::endl; using std::set; #include "Core.h" -#include -#include -#include -#include -#include -#include -#include -#include +#include "Console.h" +#include "Export.h" +#include "PluginManager.h" +#include "modules/Vegetation.h" +#include "modules/Maps.h" +#include "modules/Gui.h" +#include "TileTypes.h" +#include "modules/MapCache.h" using namespace MapExtras; using namespace DFHack; diff --git a/plugins/mode.cpp b/plugins/mode.cpp index 9c7aefb73..89728a341 100644 --- a/plugins/mode.cpp +++ b/plugins/mode.cpp @@ -2,12 +2,12 @@ using namespace std; #include "Core.h" -#include -#include -#include +#include "Console.h" +#include "Export.h" +#include "PluginManager.h" #include #include -#include +#include "modules/World.h" #include using namespace DFHack; @@ -169,4 +169,4 @@ DFhackCExport command_result mode (Core * c, vector & parameters) c->con << endl; } return CR_OK; -} \ No newline at end of file +} diff --git a/plugins/plants.cpp b/plugins/plants.cpp index 4d8960cee..eb95ce483 100644 --- a/plugins/plants.cpp +++ b/plugins/plants.cpp @@ -6,14 +6,14 @@ #include #include "Core.h" -#include -#include -#include -#include -#include -#include -#include -#include +#include "Console.h" +#include "Export.h" +#include "PluginManager.h" +#include "modules/Vegetation.h" +#include "modules/Maps.h" +#include "modules/Gui.h" +#include "TileTypes.h" +#include "modules/MapCache.h" using std::vector; using std::string; diff --git a/plugins/probe.cpp b/plugins/probe.cpp index cf00fe0dd..a56757dc4 100644 --- a/plugins/probe.cpp +++ b/plugins/probe.cpp @@ -4,23 +4,22 @@ #include #include #include +#include #include #include #include using namespace std; #include "Core.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include "Console.h" +#include "Export.h" +#include "PluginManager.h" +#include "modules/Units.h" +#include "modules/Maps.h" +#include "modules/Gui.h" +#include "modules/Materials.h" +#include "modules/MapCache.h" +#include "MiscUtils.h" using std::vector; using std::string; diff --git a/plugins/prospector.cpp b/plugins/prospector.cpp index 6287734c1..6d907a4a4 100644 --- a/plugins/prospector.cpp +++ b/plugins/prospector.cpp @@ -13,11 +13,11 @@ #include using namespace std; -#include -#include #include "Core.h" -#include -#include +#include "Console.h" +#include "Export.h" +#include "PluginManager.h" +#include "modules/MapCache.h" using namespace DFHack; diff --git a/plugins/regrass.cpp b/plugins/regrass.cpp index 99af1de7f..53733fc29 100644 --- a/plugins/regrass.cpp +++ b/plugins/regrass.cpp @@ -2,14 +2,14 @@ // Necessary for worlds generated prior to version 0.31.19 - otherwise, outdoor shrubs and trees no longer grow. #include "Core.h" -#include -#include -#include +#include "Console.h" +#include "Export.h" +#include "PluginManager.h" -#include +#include "DataDefs.h" #include "df/world.h" #include "df/map_block.h" -#include +#include "TileTypes.h" using std::string; using std::vector; diff --git a/plugins/rename.cpp b/plugins/rename.cpp index 9cd864042..379230023 100644 --- a/plugins/rename.cpp +++ b/plugins/rename.cpp @@ -1,18 +1,18 @@ #include "Core.h" -#include -#include -#include - -#include - -#include -#include -#include -#include -#include -#include -#include -#include +#include "Console.h" +#include "Export.h" +#include "PluginManager.h" + +#include "modules/Gui.h" + +#include "DataDefs.h" +#include "df/ui.h" +#include "df/world.h" +#include "df/squad.h" +#include "df/unit.h" +#include "df/unit_soul.h" +#include "df/historical_figure.h" +#include "df/language_name.h" #include diff --git a/plugins/reveal.cpp b/plugins/reveal.cpp index ce37f3f1e..bafb6e40f 100644 --- a/plugins/reveal.cpp +++ b/plugins/reveal.cpp @@ -3,13 +3,13 @@ #include #include #include "Core.h" -#include -#include -#include -#include -#include -#include -#include +#include "Console.h" +#include "Export.h" +#include "PluginManager.h" +#include "modules/Maps.h" +#include "modules/World.h" +#include "modules/MapCache.h" +#include "modules/Gui.h" using MapExtras::MapCache; using namespace DFHack; @@ -504,4 +504,4 @@ DFhackCExport command_result revflood(DFHack::Core * c, std::vector delete MCache; c->Resume(); return CR_OK; -} \ No newline at end of file +} diff --git a/plugins/seedwatch.cpp b/plugins/seedwatch.cpp index 3b83338e2..2d1a23b51 100755 --- a/plugins/seedwatch.cpp +++ b/plugins/seedwatch.cpp @@ -12,7 +12,7 @@ #include "modules/Items.h" #include "modules/World.h" #include "modules/kitchen.h" -#include +#include "VersionInfo.h" using DFHack::t_materialType; using DFHack::t_materialIndex; diff --git a/plugins/stockpiles.cpp b/plugins/stockpiles.cpp index e104ec908..a090b3f58 100644 --- a/plugins/stockpiles.cpp +++ b/plugins/stockpiles.cpp @@ -1,14 +1,14 @@ #include "Core.h" -#include -#include -#include - -#include -#include -#include -#include -#include -#include +#include "Console.h" +#include "Export.h" +#include "PluginManager.h" + +#include "DataDefs.h" +#include "df/world.h" +#include "df/ui.h" +#include "df/building_stockpilest.h" +#include "df/selection_rect.h" +#include "df/viewscreen_dwarfmodest.h" using std::vector; using std::string; diff --git a/plugins/tiletypes.cpp b/plugins/tiletypes.cpp index 57184f013..b20764447 100644 --- a/plugins/tiletypes.cpp +++ b/plugins/tiletypes.cpp @@ -11,14 +11,14 @@ using std::endl; using std::set; #include "Core.h" -#include -#include -#include -#include -#include -#include -#include -#include +#include "Console.h" +#include "Export.h" +#include "PluginManager.h" +#include "modules/Vegetation.h" +#include "modules/Maps.h" +#include "modules/Gui.h" +#include "TileTypes.h" +#include "modules/MapCache.h" using namespace MapExtras; using namespace DFHack; diff --git a/plugins/tubefill.cpp b/plugins/tubefill.cpp index 23e6e992a..b0a371cf1 100644 --- a/plugins/tubefill.cpp +++ b/plugins/tubefill.cpp @@ -5,13 +5,13 @@ #include #include #include "Core.h" -#include -#include -#include -#include -#include -#include -#include +#include "Console.h" +#include "Export.h" +#include "PluginManager.h" +#include "modules/Maps.h" +#include "modules/World.h" +#include "modules/MapCache.h" +#include "modules/Gui.h" using MapExtras::MapCache; using namespace DFHack; diff --git a/plugins/vdig.cpp b/plugins/vdig.cpp index fbbd36e46..2f9daf7d8 100644 --- a/plugins/vdig.cpp +++ b/plugins/vdig.cpp @@ -1,10 +1,10 @@ #include "Core.h" -#include -#include -#include -#include -#include -#include +#include "Console.h" +#include "Export.h" +#include "PluginManager.h" +#include "modules/Maps.h" +#include "modules/Gui.h" +#include "modules/MapCache.h" #include #include #include diff --git a/plugins/versionosd.cpp b/plugins/versionosd.cpp index 5f4ff11a8..f3e63e8c3 100644 --- a/plugins/versionosd.cpp +++ b/plugins/versionosd.cpp @@ -8,11 +8,11 @@ #include using namespace std; #include "Core.h" -#include -#include -#include -#include -#include +#include "Console.h" +#include "Export.h" +#include "PluginManager.h" +#include "modules/Graphic.h" +#include "modules/Gui.h" using namespace DFHack; DFhackCExport command_result df_versionosd (Core * c, vector & parameters); @@ -145,4 +145,4 @@ DFTileSurface* gettile (int x, int y) } return NULL; -} \ No newline at end of file +} diff --git a/plugins/weather.cpp b/plugins/weather.cpp index 0f2325d48..efe4ecaec 100644 --- a/plugins/weather.cpp +++ b/plugins/weather.cpp @@ -1,10 +1,10 @@ #include "Core.h" -#include -#include -#include +#include "Console.h" +#include "Export.h" +#include "PluginManager.h" #include #include -#include +#include "modules/World.h" using std::vector; using std::string; diff --git a/plugins/workflow.cpp b/plugins/workflow.cpp index 104604ce6..4a3564d65 100644 --- a/plugins/workflow.cpp +++ b/plugins/workflow.cpp @@ -1,41 +1,41 @@ #include "Core.h" -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include "Console.h" +#include "Export.h" +#include "PluginManager.h" +#include "MiscUtils.h" + +#include "modules/Materials.h" +#include "modules/Items.h" +#include "modules/Gui.h" +#include "modules/Job.h" +#include "modules/World.h" + +#include "DataDefs.h" +#include "df/world.h" +#include "df/ui.h" +#include "df/building_workshopst.h" +#include "df/building_furnacest.h" +#include "df/job.h" +#include "df/job_item.h" +#include "df/job_list_link.h" +#include "df/dfhack_material_category.h" +#include "df/item.h" +#include "df/items_other_id.h" +#include "df/tool_uses.h" +#include "df/general_ref.h" +#include "df/general_ref_unit_workerst.h" +#include "df/general_ref_unit_holderst.h" +#include "df/general_ref_building_holderst.h" +#include "df/general_ref_contains_itemst.h" +#include "df/general_ref_contained_in_itemst.h" +#include "df/general_ref_contains_unitst.h" +#include "df/itemdef_foodst.h" +#include "df/reaction.h" +#include "df/reaction_reagent_itemst.h" +#include "df/reaction_product_itemst.h" +#include "df/plant_raw.h" +#include "df/inorganic_raw.h" +#include "df/builtin_mats.h" using std::vector; using std::string; From 0e0bca5dbb3474855051f60270b34ae1b78b4fdf Mon Sep 17 00:00:00 2001 From: Quietust Date: Sun, 15 Jan 2012 14:59:47 -0600 Subject: [PATCH 67/82] Fix deadlock in autodump --- plugins/autodump.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/autodump.cpp b/plugins/autodump.cpp index 2e2bb4db4..f84b241c3 100644 --- a/plugins/autodump.cpp +++ b/plugins/autodump.cpp @@ -92,7 +92,7 @@ static command_result autodump_main(Core * c, vector & parameters) return CR_OK; } } - c->Suspend(); + DFHack::VersionInfo *mem = c->vinfo; DFHack::Gui * Gui = c->getGui(); DFHack::Items * Items = c->getItems(); From e84904f5c56827c1d88db74c262c265b347c28a6 Mon Sep 17 00:00:00 2001 From: Quietust Date: Sun, 15 Jan 2012 15:01:40 -0600 Subject: [PATCH 68/82] Typo - "desctruction" -> "destruction" --- plugins/autodump.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/autodump.cpp b/plugins/autodump.cpp index f84b241c3..1ad392ed7 100644 --- a/plugins/autodump.cpp +++ b/plugins/autodump.cpp @@ -263,7 +263,7 @@ static command_result autodump_main(Core * c, vector & parameters) // Is this necessary? Is "forbid" a dirtyable attribute like "dig" is? Maps->WriteDirtyBit(cx/16, cy/16, cz, true); } - c->con.print("Done. %d items %s.\n", dumped_total, destroy ? "marked for desctruction" : "quickdumped"); + c->con.print("Done. %d items %s.\n", dumped_total, destroy ? "marked for destruction" : "quickdumped"); return CR_OK; } From 97bae19c13eb7f1b9ce651a0eae0a29a0e0b492b Mon Sep 17 00:00:00 2001 From: Quietust Date: Sun, 15 Jan 2012 18:08:35 -0600 Subject: [PATCH 69/82] Update BitArray to automatically grow whenever setting/toggling bits beyond the end --- library/include/BitArray.h | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/library/include/BitArray.h b/library/include/BitArray.h index 77e2a3ac1..5aa46baa9 100644 --- a/library/include/BitArray.h +++ b/library/include/BitArray.h @@ -50,6 +50,18 @@ namespace DFHack if(bits) memset(bits, 0, size); } + void extend (T index) + { + uint32_t newsize = (index / 8) + 1; + if (newsize <= size) + return; + uint8_t *newbits = new uint8_t[newsize]; + memset(newbits, 0, newsize); + memcpy(newbits, bits, size); + delete[] bits; + bits = newbits; + size = newsize; + } void set (T index, bool value = true) { if(!value) @@ -58,7 +70,8 @@ namespace DFHack return; } uint32_t byte = index / 8; - if(byte < size) + extend(index); + //if(byte < size) { uint8_t bit = 1 << (index % 8); bits[byte] |= bit; @@ -76,7 +89,8 @@ namespace DFHack void toggle (T index) { uint32_t byte = index / 8; - if(byte < size) + extend(index); + //if(byte < size) { uint8_t bit = 1 << (index % 8); bits[byte] ^= bit; From 4811d2945e31c713144dc556fd54d182b22f8ea4 Mon Sep 17 00:00:00 2001 From: Alexander Gavrilov Date: Mon, 16 Jan 2012 19:45:38 +0400 Subject: [PATCH 70/82] Count hospital supplies as busy, and detect soap-producing reactions. --- plugins/workflow.cpp | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/plugins/workflow.cpp b/plugins/workflow.cpp index 38e2313cd..b6bee9671 100644 --- a/plugins/workflow.cpp +++ b/plugins/workflow.cpp @@ -777,6 +777,7 @@ static void compute_custom_job(ProtectedJob *pj, df::job *job) 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)) @@ -799,20 +800,26 @@ static void compute_custom_job(ProtectedJob *pj, df::job *job) if (get_mat_prod) { - if (!mat.isValid()) - continue; + std::string code = prod->get_material.product_code; - int idx = linear_index(mat.material->reaction_product.id, - prod->get_material.product_code); - if (idx < 0) - continue; + 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); + 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, - 0, mat.type, mat.index); + mat_mask, mat.type, mat.index); } } @@ -1113,6 +1120,7 @@ static void map_job_items(Core *c) continue; if (item->flags.bits.owned || + item->flags.bits.in_chest || item->isAssignedToStockpile() || itemInRealJob(item) || itemBusy(item)) From 64b55acf37519450f6feca5cda7d8fba2ee1e491 Mon Sep 17 00:00:00 2001 From: Quietust Date: Mon, 16 Jan 2012 20:16:16 -0600 Subject: [PATCH 71/82] df_item -> df::item, t_itemflags -> df::item_flags --- library/include/modules/Items.h | 489 +------------------------------- library/include/modules/Units.h | 6 +- library/modules/Items.cpp | 38 +-- library/modules/Units.cpp | 4 +- library/modules/kitchen.cpp | 11 +- plugins/autodump.cpp | 30 +- plugins/cleanowned.cpp | 26 +- plugins/seedwatch.cpp | 31 +- 8 files changed, 87 insertions(+), 548 deletions(-) diff --git a/library/include/modules/Items.h b/library/include/modules/Items.h index d0424a6f0..566ba3447 100644 --- a/library/include/modules/Items.h +++ b/library/include/modules/Items.h @@ -34,6 +34,7 @@ distribution. #include "MemAccess.h" #include "DataDefs.h" +#include "df/item.h" #include "df/item_type.h" namespace df @@ -90,58 +91,6 @@ class Context; class DFContextShared; class Units; -/** - * Item flags. A bit fuzzy. - * Mostly from http://dwarffortresswiki.net/index.php/User:Rick/Memory_research - * \ingroup grp_items - */ -union t_itemflags -{ - uint32_t whole; ///< the whole struct. all 32 bits of it, as an integer - struct - { - unsigned int on_ground : 1; ///< 0000 0001 Item on ground - unsigned int in_job : 1; ///< 0000 0002 Item currently being used in a job - unsigned int hostile : 1; ///< 0000 0004 Item owned by hostile - unsigned int in_inventory : 1; ///< 0000 0008 Item in a creature or workshop inventory - - unsigned int unk1 : 1; ///< 0000 0010 unknown, lost (artifact)?, unusable, unseen - unsigned int in_building : 1; ///< 0000 0020 Part of a building (including mechanisms, bodies in coffins) - unsigned int unk2 : 1; ///< 0000 0040 unknown, unseen - unsigned int dead_dwarf : 1; ///< 0000 0080 Dwarf's dead body or body part - - unsigned int rotten : 1; ///< 0000 0100 Rotten food - unsigned int spider_web : 1; ///< 0000 0200 Thread in spider web - unsigned int construction : 1; ///< 0000 0400 Material used in construction - unsigned int unk3 : 1; ///< 0000 0800 unknown, unseen, unusable - - unsigned int unk4 : 1; ///< 0000 1000 unknown, unseen - unsigned int murder : 1; ///< 0000 2000 Implies murder - used in fell moods - unsigned int foreign : 1; ///< 0000 4000 Item is imported - unsigned int trader : 1; ///< 0000 8000 Item ownwed by trader - - unsigned int owned : 1; ///< 0001 0000 Item is owned by a dwarf - unsigned int garbage_colect : 1; ///< 0002 0000 Marked for deallocation by DF it seems - unsigned int artifact1 : 1; ///< 0004 0000 Artifact ? - unsigned int forbid : 1; ///< 0008 0000 Forbidden item - - unsigned int unk6 : 1; ///< 0010 0000 unknown, unseen - unsigned int dump : 1; ///< 0020 0000 Designated for dumping - unsigned int on_fire: 1; ///< 0040 0000 Indicates if item is on fire, Will Set Item On Fire if Set! - unsigned int melt : 1; ///< 0080 0000 Designated for melting, if applicable - - unsigned int hidden : 1; ///< 0100 0000 Hidden item - unsigned int in_chest : 1; ///< 0200 0000 Stored in chest/part of well? - unsigned int unk7 : 1; ///< 0400 0000 unknown, unseen - unsigned int artifact2 : 1; ///< 0800 0000 Artifact ? - - unsigned int unk8 : 1; ///< 1000 0000 unknown, unseen, common - unsigned int unk9 : 1; ///< 2000 0000 unknown, set when viewing details - unsigned int unk10 : 1; ///< 4000 0000 unknown, unseen - unsigned int unk11 : 1; ///< 8000 0000 unknown, unseen - }; -}; - /** * Describes relationship of an item with other objects * \ingroup grp_items @@ -161,337 +110,17 @@ struct df_contaminant int32_t size; ///< 1-24=spatter, 25-49=smear, 50-* = coating }; -/** - * A partial mirror of a DF base type for items - * \ingroup grp_items - */ -class df_item -{ -public: - // 4 - int16_t x; - int16_t y; - // 8 - int16_t z; - // C - t_itemflags flags; - // 10 - uint32_t age; - // 14 - uint32_t id; - // 18 - std::vector unk1; - // 24 L, 28 W - std::vector itemrefs; - // 30 L, 38 W - these were mostly unset (0xCC with malloc patch) - int16_t mystery_meat[12]; - // 48 L, 50 W - int32_t mystery1; - // 4C L, 54 W - int32_t mystery2; - // 50 L, 58 W - int32_t mystery3; - // 54 L, 5C W - int32_t mystery4; - // 58 L, 60 W - int32_t mystery5; - // 5C L, 64 W - pointer to vector of contaminants - std::vector * contaminants; - // 60 L, 6C W - temperature in Urists - int16_t temperature; - // 62 L, 6E W - temperature fraction (maybe, just a guess) - int16_t temperature_fraction; -public: - // 0x0 - virtual t_itemType getType(); - virtual t_itemSubtype getSubtype(); - virtual t_materialType getMaterial(); - virtual t_materialIndex getMaterialIndex(); - // 0x10 - virtual void setSubType(t_itemSubtype); - virtual void setMaterial(t_materialType mat); - virtual void setMaterialIndex (t_materialIndex submat); - virtual t_materialType getMaterial2(); // weird - // 0x20 - virtual t_materialIndex getMaterialIndex2(); // weird - virtual void fn9(void); - virtual void fn10(void); - virtual void fn11(void); - // 0x30 - virtual void fn12(void); - virtual void fn13(void); - virtual void fn14(void); - virtual void fn15(void); - // 0x40 - virtual void fn16(void); - virtual void fn17(void); - virtual void fn18(void); - virtual void fn19(void); - // 0x50 - virtual void fn20(void); - virtual void fn21(void); - virtual void fn22(void); - virtual void fn23(void); - // 0x60 - virtual void fn24(void); - virtual void fn25(void); - virtual void fn26(void); - virtual void fn27(void); - // 0x70 - virtual void fn28(void); - virtual void fn29(void); - virtual void fn30(void); - virtual void fn31(void); - // 0x80 - virtual void fn32(void); - virtual void fn33(void); - virtual void fn34(void); - virtual void fn35(void); - // 0x90 - virtual void fn36(void); - virtual void fn37(void); - virtual void fn38(void); - virtual void fn39(void); - // 0xA0 - virtual void fn40(void); - virtual void fn41(void); - virtual void fn42(void); - virtual void fn43(void); - // 0xB0 - virtual void fn44(void); - virtual void fn45(void); - virtual void fn46(void); - virtual void fn47(void); - // 0xC0 - virtual void fn48(void); - virtual void fn49(void); - virtual void fn50(void); - virtual int16_t getWear(void); // 0 = normal, 1 = x, 2 = X, 3 = XX - // 0xD0 - virtual void setWear(int16_t wear); // also zeroes wear timer? - virtual void fn53(void); - virtual void fn54(void); - virtual void fn55(void); - // 0xE0 - virtual void fn56(void); - virtual void fn57(void); - virtual void fn58(void); - virtual void fn59(void); - // 0xF0 - virtual void fn60(void); - virtual void fn61(void); - virtual void fn62(void); - virtual void fn63(void); - // 0x100 - virtual void fn64(void); - virtual void fn65(void); - virtual void fn66(void); - virtual void fn67(void); - // 0x110 - virtual void fn68(void); - virtual void fn69(void); - virtual void fn70(void); - virtual void fn71(void); - // 0x120 - virtual void fn72(void); - virtual void fn73(void); - virtual void fn74(void); - virtual void fn75(void); - // 0x130 - virtual void fn76(void); - virtual void fn77(void); - virtual void fn78(void); - virtual void fn79(void); - // 0x140 - virtual void fn80(void); - virtual void fn81(void); - virtual void fn82(void); - virtual void fn83(void); - // 0x150 - virtual void fn84(void); - virtual void fn85(void); - virtual void fn86(void); - virtual void fn87(void); - // 0x160 - virtual void fn88(void); - virtual void fn89(void); - virtual void fn90(void); - virtual void fn91(void); - // 0x170 - virtual void fn92(void); - virtual void fn93(void); - virtual void fn94(void); - virtual void fn95(void); - // 0x180 - virtual void fn96(void); - virtual void fn97(void); - virtual void fn98(void); - virtual void fn99(void); - // 0x190 - virtual void fn100(void); - virtual void fn101(void); - virtual void fn102(void); - virtual void fn103(void); - // 0x1A0 - virtual void fn104(void); - virtual void fn105(void); - virtual void fn106(void); - virtual void fn107(void); - // 0x1B0 - virtual void fn108(void); - virtual void fn109(void); - virtual void fn110(void); - virtual void fn111(void); - // 0x1C0 - virtual void fn112(void); - virtual void fn113(void); - virtual void fn114(void); - virtual void fn115(void); - // 0x1D0 - virtual void fn116(void); - virtual void fn117(void); - virtual void fn118(void); - virtual void fn119(void); - // 0x1E0 - virtual void fn120(void); - virtual void fn121(void); - virtual void fn122(void); - virtual void fn123(void); - // 0x1F0 - virtual void fn124(void); - virtual void fn125(void); - virtual void fn126(void); - virtual void fn127(void); - // 0x200 - virtual void fn128(void); - virtual void fn129(void); - virtual void fn130(void); - virtual void fn131(void); - // 0x210 - virtual void fn132(void); - virtual int32_t getStackSize( void ); - virtual void fn134(void); - virtual void fn135(void); - // 0x220 - virtual void fn136(void); - virtual void fn137(void); - virtual void fn138(void); - virtual void fn139(void); - // 0x230 - virtual void fn140(void); - virtual void fn141(void); - virtual void fn142(void); - virtual void fn143(void); - // 0x240 - virtual void fn144(void); - virtual void fn145(void); - virtual void fn146(void); - virtual void fn147(void); - // 0x250 - virtual void fn148(void); - virtual void fn149(void); - virtual void fn150(void); - virtual int16_t getQuality( void ); - // 0x260 - virtual void fn152(void); - virtual void fn153(void); - virtual void fn154(void); - virtual void fn155(void); - // 0x270 - virtual void fn156(void); - virtual void fn157(void); - virtual void fn158(void); - virtual void fn159(void); - // 0x280 - virtual void fn160(void); - virtual void fn161(void); - virtual void fn162(void); - virtual void fn163(void); - // 0x290 - virtual void fn164(void); - virtual void fn165(void); - virtual void fn166(void); - virtual void fn167(void); - // 0x2A0 - virtual void fn168(void); // value returned (int) = first param to descriprion construction function - virtual void fn169(void); - virtual void fn170(void); - virtual void fn171(void); - // 0x2B0 - virtual void fn172(void); - virtual void fn173(void); - virtual void fn174(void); - virtual void fn175(void); - // 0x2C0 - virtual void fn176(void); - virtual void fn177(void); - //virtual std::string *getItemDescription ( std::string * str, int sizes = 0); // 0 = stacked, 1 = singular, 2 = plural - virtual std::string *getItemDescription ( std::string * str, int sizes = 0); // 0 = stacked, 1 = singular, 2 = plural - virtual void fn179(void); - // 0x2D0 - virtual void fn180(void); - virtual void fn181(void); - virtual void fn182(void); - virtual void fn183(void); - // 0x2E0 - virtual void fn184(void); - virtual void fn185(void); - virtual void fn186(void); - virtual void fn187(void); - // 0x2F0 - virtual void fn188(void); - virtual void fn189(void); - virtual void fn190(void); - virtual void fn191(void); - // 0x300 - virtual void fn192(void); - virtual void fn193(void); - virtual void fn194(void); - virtual void fn195(void); - // 0x310 - virtual void fn196(void); - virtual void fn197(void); - virtual void fn198(void); - virtual void fn199(void); - // 0x320 - virtual void fn200(void); - virtual void fn201(void); - virtual void fn202(void); - virtual void fn203(void); - // 0x330 - virtual void fn204(void); - virtual void fn205(void); - virtual void fn206(void); - virtual void fn207(void); - // 0x340 - virtual void fn208(void); - virtual void fn209(void); - virtual void fn210(void); - virtual void fn211(void); - // 0x350 - virtual void fn212(void); - virtual void fn213(void); - virtual void fn214(void); - virtual void fn215(void); - // 0x360 - virtual void fn216(void); - virtual void fn217(void); - - // and this should be all 218 of them - // fn numbers start with 0 -}; - /** * Type for holding an item read from DF * \ingroup grp_items */ struct dfh_item { - df_item *origin; // where this was read from + df::item *origin; // where this was read from int16_t x; int16_t y; int16_t z; - t_itemflags flags; + df::item_flags flags; uint32_t age; uint32_t id; t_material matdesc; @@ -523,98 +152,6 @@ public: * All the known item types as an enum * From http://df.magmawiki.com/index.php/DF2010:Item_token */ - enum item_types - { - BAR, ///< Bars, such as metal, fuel, or soap. - SMALLGEM, ///< Cut gemstones usable in jeweler's workshop - BLOCKS, ///< Blocks of any kind. - ROUGH, ///< Rough gemstones. - BOULDER, ///< or IT_STONE - raw mined stone. - STONE = BOULDER, - WOOD, ///< Wooden logs. - DOOR, ///< Doors. - FLOODGATE, ///< Floodgates. - BED, ///< Beds. - CHAIR, ///< Chairs and thrones. - CHAIN, ///< Restraints. - FLASK, ///< Flasks. - GOBLET, ///< Goblets. - INSTRUMENT, ///< Musical instruments. Subtypes come from item_instrument.txt - TOY, ///< Toys. Subtypes come from item_toy.txt - WINDOW, ///< Glass windows. - CAGE, ///< Cages. - BARREL, ///< Barrels. - BUCKET, ///< Buckets. - ANIMALTRAP, ///< Animal traps. - TABLE, ///< Tables. - COFFIN, ///< Coffins. - STATUE, ///< Statues. - CORPSE, ///< Corpses. - WEAPON, ///< Weapons. Subtypes come from item_weapon.txt - ARMOR, ///< Armor and clothing worn on the upper body. Subtypes come from item_armor.txt - SHOES, ///< Armor and clothing worn on the feet. Subtypes come from item_shoes.txt - SHIELD, ///< Shields and bucklers. Subtypes come from item_shield.txt - HELM, ///< Armor and clothing worn on the head. Subtypes come from item_helm.txt - GLOVES, ///< Armor and clothing worn on the hands. Subtypes come from item_gloves.txt - BOX, ///< Chests (wood), coffers (stone), boxes (glass), and bags (cloth or leather). - BIN, ///< Bins. - ARMORSTAND, ///< Armor stands. - WEAPONRACK, ///< Weapon racks. - CABINET, ///< Cabinets. - FIGURINE, ///< Figurines. - AMULET, ///< Amulets. - SCEPTER, ///< Scepters. - AMMO, ///< Ammunition for hand-held weapons. Subtypes come from item_ammo.txt - CROWN, ///< Crowns. - RING, ///< Rings. - EARRING, ///< Earrings. - BRACELET, ///< Bracelets. - GEM, ///< Large gems. - ANVIL, ///< Anvils. - CORPSEPIECE,///< Body parts. - REMAINS, ///< Dead vermin bodies. - MEAT, ///< Butchered meat. - FISH, ///< Prepared fish. - FISH_RAW, ///< Unprepared fish. - VERMIN, ///< Live vermin. - PET, ///< Tame vermin. - SEEDS, ///< Seeds from plants. - PLANT, ///< Plants. - SKIN_TANNED,///< Tanned skins. - LEAVES, ///< Leaves, usually from quarry bushes. - THREAD, ///< Thread gathered from webs or made at the farmer's workshop. - CLOTH, ///< Cloth made at the loom. - TOTEM, ///< Skull totems. - PANTS, ///< Armor and clothing worn on the legs. Subtypes come from item_pants.txt - BACKPACK, ///< Backpacks. - QUIVER, ///< Quivers. - CATAPULTPARTS, ///< Catapult parts. - BALLISTAPARTS, ///< Ballista parts. - SIEGEAMMO, ///< Siege engine ammunition. Subtypes come from item_siegeammo.txt - BALLISTAARROWHEAD, ///< Ballista arrow heads. - TRAPPARTS, ///< Mechanisms. - TRAPCOMP, ///< Trap components. Subtypes come from item_trapcomp.txt - DRINK, ///< Alcoholic drinks. - POWDER_MISC,///< Powders such as flour, gypsum plaster, dye, or sand. - CHEESE, ///< Pieces of cheese. - FOOD, ///< Prepared meals. Subtypes come from item_food.txt - LIQUID_MISC,///< Liquids such as water, lye, and extracts. - COIN, ///< Coins. - GLOB, ///< Fat, tallow, pastes/pressed objects, and small bits of molten rock/metal. - ROCK, ///< Small rocks (usually sharpened and/or thrown in adventurer mode) - PIPE_SECTION, ///< Pipe sections. - HATCH_COVER, ///< Hatch covers. - GRATE, ///< Grates. - QUERN, ///< Querns. - MILLSTONE, ///< Millstones. - SPLINT, ///< Splints. - CRUTCH, ///< Crutches. - TRACTION_BENCH, ///< Traction benches. - ORTHOPEDIC_CAST, ///< Casts. - TOOL, ///< Tools. Subtypes come from item_tool.txt - SLAB, ///< Slabs. - EGG, ///< Eggs. - }; public: Items(); @@ -622,30 +159,30 @@ public: bool Start(); bool Finish(); /// Read the item vector from DF into a supplied vector - bool readItemVector(std::vector &items); + bool readItemVector(std::vector &items); /// Look for a particular item by ID - df_item * findItemByID(int32_t id); + df::item * findItemByID(int32_t id); /// Make a partial copy of a DF item - bool copyItem(df_item * source, dfh_item & target); + bool copyItem(df::item * source, dfh_item & target); /// write copied item back to its origin bool writeItem(const dfh_item & item); /// get the class name of an item - std::string getItemClass(const df_item * item); + std::string getItemClass(const df::item * item); /// who owns this item we already read? - int32_t getItemOwnerID(const df_item * item); + int32_t getItemOwnerID(const df::item * item); /// which item is it contained in? - int32_t getItemContainerID(const df_item * item); + int32_t getItemContainerID(const df::item * item); /// which items does it contain? - bool getContainedItems(const df_item * item, /*output*/ std::vector &items); + bool getContainedItems(const df::item * item, /*output*/ std::vector &items); /// wipe out the owner records - bool removeItemOwner(df_item * item, Units *creatures); + bool removeItemOwner(df::item * item, Units *creatures); /// read item references, filtered by class - bool readItemRefs(const df_item * item, const ClassNameCheck &classname, + bool readItemRefs(const df::item * item, const ClassNameCheck &classname, /*output*/ std::vector &values); /// get list of item references that are unknown along with their values - bool unknownRefs(const df_item * item, /*output*/ std::vector >& refs); + bool unknownRefs(const df::item * item, /*output*/ std::vector >& refs); private: class Private; Private* d; diff --git a/library/include/modules/Units.h b/library/include/modules/Units.h index d373b0a16..c7dfe202d 100644 --- a/library/include/modules/Units.h +++ b/library/include/modules/Units.h @@ -557,7 +557,7 @@ namespace DFHack int16_t unk_280; int32_t unk_284; - std::vector inventory; // 288 - vector of item pointers + std::vector inventory; // 288 - vector of item pointers std::vector owned_items; // 298 - vector of item IDs std::vector unk_2a8; std::vector unk_2b8; @@ -777,8 +777,8 @@ namespace DFHack bool ReadJob(const df_unit * unit, std::vector & mat); - bool ReadInventoryByIdx(const uint32_t index, std::vector & item); - bool ReadInventoryByPtr(const df_unit * unit, std::vector & item); + bool ReadInventoryByIdx(const uint32_t index, std::vector & item); + bool ReadInventoryByPtr(const df_unit * unit, std::vector & item); bool ReadOwnedItemsByIdx(const uint32_t index, std::vector & item); bool ReadOwnedItemsByPtr(const df_unit * unit, std::vector & item); diff --git a/library/modules/Items.cpp b/library/modules/Items.cpp index 9fffcc03d..4c695607d 100644 --- a/library/modules/Items.cpp +++ b/library/modules/Items.cpp @@ -403,7 +403,7 @@ class Items::Private { public: Process * owner; - std::map idLookupTable; + std::map idLookupTable; uint32_t refVectorOffset; uint32_t idFieldOffset; void * itemVectorAddress; @@ -498,16 +498,16 @@ bool Items::Finish() return true; } -bool Items::readItemVector(std::vector &items) +bool Items::readItemVector(std::vector &items) { - std::vector *p_items = (std::vector *) d->itemVectorAddress; + std::vector *p_items = (std::vector *) d->itemVectorAddress; d->idLookupTable.clear(); items.resize(p_items->size()); for (unsigned i = 0; i < p_items->size(); i++) { - df_item * ptr = p_items->at(i); + df::item * ptr = p_items->at(i); items[i] = ptr; d->idLookupTable[ptr->id] = ptr; } @@ -515,14 +515,14 @@ bool Items::readItemVector(std::vector &items) return true; } -df_item * Items::findItemByID(int32_t id) +df::item * Items::findItemByID(int32_t id) { if (id < 0) return 0; if (d->idLookupTable.empty()) { - std::vector tmp; + std::vector tmp; readItemVector(tmp); } @@ -535,11 +535,11 @@ Items::~Items() delete d; } -bool Items::copyItem(df_item * itembase, DFHack::dfh_item &item) +bool Items::copyItem(df::item * itembase, DFHack::dfh_item &item) { if(!itembase) return false; - df_item * itreal = (df_item *) itembase; + df::item * itreal = (df::item *) itembase; item.origin = itembase; item.x = itreal->x; item.y = itreal->y; @@ -557,7 +557,7 @@ bool Items::copyItem(df_item * itembase, DFHack::dfh_item &item) return true; } -int32_t Items::getItemOwnerID(const DFHack::df_item * item) +int32_t Items::getItemOwnerID(const df::item * item) { std::vector vals; if (readItemRefs(item, d->isOwnerRefClass, vals)) @@ -566,7 +566,7 @@ int32_t Items::getItemOwnerID(const DFHack::df_item * item) return -1; } -int32_t Items::getItemContainerID(const DFHack::df_item * item) +int32_t Items::getItemContainerID(const df::item * item) { std::vector vals; if (readItemRefs(item, d->isContainerRefClass, vals)) @@ -575,14 +575,14 @@ int32_t Items::getItemContainerID(const DFHack::df_item * item) return -1; } -bool Items::getContainedItems(const DFHack::df_item * item, std::vector &items) +bool Items::getContainedItems(const df::item * item, std::vector &items) { return readItemRefs(item, d->isContainsRefClass, items); } -bool Items::readItemRefs(const df_item * item, const ClassNameCheck &classname, std::vector &values) +bool Items::readItemRefs(const df::item * item, const ClassNameCheck &classname, std::vector &values) { - const std::vector &p_refs = item->itemrefs; + const std::vector &p_refs = (const std::vector &)item->itemrefs; values.clear(); for (uint32_t i=0; i >& refs) +bool Items::unknownRefs(const df::item * item, std::vector >& refs) { refs.clear(); - const std::vector &p_refs = item->itemrefs; + const std::vector &p_refs = (const std::vector &)item->itemrefs; for (uint32_t i=0; i 0); } -bool Items::removeItemOwner(df_item * item, Units *creatures) +bool Items::removeItemOwner(df::item * item, Units *creatures) { - std::vector &p_refs = item->itemrefs; + std::vector &p_refs = (std::vector &)item->itemrefs; for (uint32_t i=0; iisOwnerRefClass(d->owner, p_refs[i]->vptr)) @@ -632,12 +632,12 @@ bool Items::removeItemOwner(df_item * item, Units *creatures) p_refs.erase(p_refs.begin() + i--); } - item->flags.owned = 0; + item->flags.bits.owned = 0; return true; } -std::string Items::getItemClass(const df_item * item) +std::string Items::getItemClass(const df::item * item) { const t_virtual * virt = (t_virtual *) item; return virt->getClassName(); diff --git a/library/modules/Units.cpp b/library/modules/Units.cpp index f969e3f90..f69d74c69 100644 --- a/library/modules/Units.cpp +++ b/library/modules/Units.cpp @@ -549,7 +549,7 @@ bool Creatures::ReadJob(const t_creature * furball, vector & mat) return true; } */ -bool Units::ReadInventoryByIdx(const uint32_t index, std::vector & item) +bool Units::ReadInventoryByIdx(const uint32_t index, std::vector & item) { if(!d->Started) return false; if(index >= creatures->size()) return false; @@ -557,7 +557,7 @@ bool Units::ReadInventoryByIdx(const uint32_t index, std::vector & it return this->ReadInventoryByPtr(temp, item); } -bool Units::ReadInventoryByPtr(const df_unit * temp, std::vector & items) +bool Units::ReadInventoryByPtr(const df_unit * temp, std::vector & items) { if(!d->Started) return false; items = temp->inventory; diff --git a/library/modules/kitchen.cpp b/library/modules/kitchen.cpp index fbf11a079..cd67a9e23 100644 --- a/library/modules/kitchen.cpp +++ b/library/modules/kitchen.cpp @@ -19,6 +19,7 @@ using namespace std; #include "ModuleFactory.h" #include "Core.h" #include "Virtual.h" +#include "df/item_type.h" namespace DFHack { @@ -89,7 +90,7 @@ namespace Kitchen for(std::size_t i = 0; i < size(); ++i) { if(d->materialIndices[i] == materialIndex - && (d->itemTypes[i] == DFHack::Items::SEEDS || d->itemTypes[i] == DFHack::Items::PLANT) + && (d->itemTypes[i] == df::item_type::SEEDS || d->itemTypes[i] == df::item_type::PLANT) && d->exclusionTypes[i] == cookingExclusion ) { @@ -119,15 +120,15 @@ namespace Kitchen if(d->materialIndices[i] == materialIndex && d->exclusionTypes[i] == cookingExclusion) { - if(d->itemTypes[i] == DFHack::Items::SEEDS) + if(d->itemTypes[i] == df::item_type::SEEDS) SeedAlreadyIn = true; - else if (d->itemTypes[i] == DFHack::Items::PLANT) + else if (d->itemTypes[i] == df::item_type::PLANT) PlantAlreadyIn = true; } } if(!SeedAlreadyIn) { - d->itemTypes.push_back(DFHack::Items::SEEDS); + d->itemTypes.push_back(df::item_type::SEEDS); d->itemSubtypes.push_back(organicSubtype); d->materialTypes.push_back(type->material_type_seed); d->materialIndices.push_back(materialIndex); @@ -135,7 +136,7 @@ namespace Kitchen } if(!PlantAlreadyIn) { - d->itemTypes.push_back(DFHack::Items::PLANT); + d->itemTypes.push_back(df::item_type::PLANT); d->itemSubtypes.push_back(organicSubtype); d->materialTypes.push_back(type->material_type_basic_mat); d->materialIndices.push_back(materialIndex); diff --git a/plugins/autodump.cpp b/plugins/autodump.cpp index 1ad392ed7..8c1820f2b 100644 --- a/plugins/autodump.cpp +++ b/plugins/autodump.cpp @@ -98,7 +98,7 @@ static command_result autodump_main(Core * c, vector & parameters) DFHack::Items * Items = c->getItems(); DFHack::Maps *Maps = c->getMaps(); - vector p_items; + vector p_items; if(!Items->readItemVector(p_items)) { c->con.printerr("Can't access the item vector.\n"); @@ -148,7 +148,7 @@ static command_result autodump_main(Core * c, vector & parameters) // proceed with the dumpification operation for(std::size_t i=0; i< numItems; i++) { - df_item * itm = p_items[i]; + df::item * itm = p_items[i]; DFCoord pos_item(itm->x, itm->y, itm->z); // keep track how many items are at places. all items. @@ -165,22 +165,22 @@ static command_result autodump_main(Core * c, vector & parameters) // iterator is valid here, we use it later to decrement the pile counter if the item is moved // only dump the stuff marked for dumping and laying on the ground - if ( !itm->flags.dump - || !itm->flags.on_ground - || itm->flags.construction - || itm->flags.hidden - || itm->flags.in_building - || itm->flags.in_chest - || itm->flags.in_inventory - || itm->flags.artifact1 + if ( !itm->flags.bits.dump + || !itm->flags.bits.on_ground + || itm->flags.bits.construction + || itm->flags.bits.hidden + || itm->flags.bits.in_building + || itm->flags.bits.in_chest + || itm->flags.bits.in_inventory + || itm->flags.bits.artifact1 ) continue; if(!destroy) // move to cursor { // Change flags to indicate the dump was completed, as if by super-dwarfs - itm->flags.dump = false; - itm->flags.forbid = true; + itm->flags.bits.dump = false; + itm->flags.bits.forbid = true; // Don't move items if they're already at the cursor if (pos_cursor == pos_item) @@ -221,11 +221,11 @@ static command_result autodump_main(Core * c, vector & parameters) if (here && pos_item != pos_cursor) continue; - itm->flags.garbage_colect = true; + itm->flags.bits.garbage_colect = true; // Cosmetic changes: make them disappear from view instantly - itm->flags.forbid = true; - itm->flags.hidden = true; + itm->flags.bits.forbid = true; + itm->flags.bits.hidden = true; } // keeping track of item pile sizes ;) it->second --; diff --git a/plugins/cleanowned.cpp b/plugins/cleanowned.cpp index 966d8e335..0935c2eaa 100644 --- a/plugins/cleanowned.cpp +++ b/plugins/cleanowned.cpp @@ -99,7 +99,7 @@ DFhackCExport command_result df_cleanowned (Core * c, vector & paramete ok &= Creatures->Start(num_creatures); ok &= Tran->Start(); - vector p_items; + vector p_items; ok &= Items->readItemVector(p_items); if(!ok) { @@ -111,11 +111,11 @@ DFhackCExport command_result df_cleanowned (Core * c, vector & paramete for (std::size_t i=0; i < p_items.size(); i++) { - df_item * item = p_items[i]; + df::item * item = p_items[i]; bool confiscate = false; bool dump = false; - if (!item->flags.owned) + if (!item->flags.bits.owned) { int32_t owner = Items->getItemOwnerID(item); if (owner >= 0) @@ -131,21 +131,21 @@ DFhackCExport command_result df_cleanowned (Core * c, vector & paramete std::string name = Items->getItemClass(item); - if (item->flags.rotten) + if (item->flags.bits.rotten) { c->con.print("Confiscating a rotten item: \t"); confiscate = true; } - else if (item->flags.on_ground) + else if (item->flags.bits.on_ground) { int32_t type = item->getType(); - if(type == Items::MEAT || - type == Items::FISH || - type == Items::VERMIN || - type == Items::PET || - type == Items::PLANT || - type == Items::CHEESE || - type == Items::FOOD + if(type == df::item_type::MEAT || + type == df::item_type::FISH || + type == df::item_type::VERMIN || + type == df::item_type::PET || + type == df::item_type::PLANT || + type == df::item_type::CHEESE || + type == df::item_type::FOOD ) { confiscate = true; @@ -209,7 +209,7 @@ DFhackCExport command_result df_cleanowned (Core * c, vector & paramete if (!Items->removeItemOwner(item, Creatures)) c->con.print("(unsuccessfully) "); if (dump) - item->flags.dump = 1; + item->flags.bits.dump = 1; } c->con.print("\n"); } diff --git a/plugins/seedwatch.cpp b/plugins/seedwatch.cpp index 2d1a23b51..91da6813c 100755 --- a/plugins/seedwatch.cpp +++ b/plugins/seedwatch.cpp @@ -13,6 +13,7 @@ #include "modules/World.h" #include "modules/kitchen.h" #include "VersionInfo.h" +#include "df/item_flags.h" using DFHack::t_materialType; using DFHack::t_materialIndex; @@ -23,19 +24,19 @@ bool running = false; // whether seedwatch is counting the seeds or not // abbreviations for the standard plants std::map abbreviations; -bool ignoreSeeds(DFHack::t_itemflags& f) // seeds with the following flags should not be counted +bool ignoreSeeds(df::item_flags& f) // seeds with the following flags should not be counted { return - f.dump || - f.forbid || - f.garbage_colect || - f.hidden || - f.hostile || - f.on_fire || - f.rotten || - f.trader || - f.in_building || - f.in_job; + f.bits.dump || + f.bits.forbid || + f.bits.garbage_colect || + f.bits.hidden || + f.bits.hostile || + f.bits.on_fire || + f.bits.rotten || + f.bits.trader || + f.bits.in_building || + f.bits.in_job; }; void printHelp(DFHack::Core& core) // prints help @@ -329,9 +330,9 @@ DFhackCExport DFHack::command_result plugin_onupdate(DFHack::Core* pCore) std::map seedCount; // the number of seeds DFHack::Items& itemsModule = *core.getItems(); itemsModule.Start(); - std::vector items; + std::vector items; itemsModule.readItemVector(items); - DFHack::df_item * item; + df::item * item; // count all seeds and plants by RAW material for(std::size_t i = 0; i < items.size(); ++i) { @@ -339,10 +340,10 @@ DFhackCExport DFHack::command_result plugin_onupdate(DFHack::Core* pCore) t_materialIndex materialIndex = item->getMaterialIndex(); switch(item->getType()) { - case DFHack::Items::SEEDS: + case df::item_type::SEEDS: if(!ignoreSeeds(item->flags)) ++seedCount[materialIndex]; break; - case DFHack::Items::PLANT: + case df::item_type::PLANT: break; } } From c18619520d47ca07d64be22d046917ffcb820dcd Mon Sep 17 00:00:00 2001 From: Quietust Date: Mon, 16 Jan 2012 20:18:40 -0600 Subject: [PATCH 72/82] df_contaminant -> df::contaminant --- library/include/modules/Items.h | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/library/include/modules/Items.h b/library/include/modules/Items.h index 566ba3447..eeea8eb63 100644 --- a/library/include/modules/Items.h +++ b/library/include/modules/Items.h @@ -100,16 +100,6 @@ struct t_itemref : public t_virtual int32_t value; }; -struct df_contaminant -{ - int16_t material; - int32_t mat_index; - int16_t mat_state; // FIXME: enum or document in text - int16_t temperature; - int16_t temperature_fraction; // maybe... - int32_t size; ///< 1-24=spatter, 25-49=smear, 50-* = coating -}; - /** * Type for holding an item read from DF * \ingroup grp_items From 7c5835d318282ee30bfeae0d490ebf73a08b6791 Mon Sep 17 00:00:00 2001 From: Quietust Date: Mon, 16 Jan 2012 20:40:29 -0600 Subject: [PATCH 73/82] t_itemref -> df::general_ref --- library/include/modules/Items.h | 12 ++----- library/modules/Items.cpp | 61 +++++++++++++++++---------------- 2 files changed, 34 insertions(+), 39 deletions(-) diff --git a/library/include/modules/Items.h b/library/include/modules/Items.h index eeea8eb63..1f0a0a5d0 100644 --- a/library/include/modules/Items.h +++ b/library/include/modules/Items.h @@ -36,6 +36,7 @@ distribution. #include "DataDefs.h" #include "df/item.h" #include "df/item_type.h" +#include "df/general_ref.h" namespace df { @@ -91,15 +92,6 @@ class Context; class DFContextShared; class Units; -/** - * Describes relationship of an item with other objects - * \ingroup grp_items - */ -struct t_itemref : public t_virtual -{ - int32_t value; -}; - /** * Type for holding an item read from DF * \ingroup grp_items @@ -169,7 +161,7 @@ public: /// wipe out the owner records bool removeItemOwner(df::item * item, Units *creatures); /// read item references, filtered by class - bool readItemRefs(const df::item * item, const ClassNameCheck &classname, + bool readItemRefs(const df::item * item, const df::general_ref_type type, /*output*/ std::vector &values); /// get list of item references that are unknown along with their values bool unknownRefs(const df::item * item, /*output*/ std::vector >& refs); diff --git a/library/modules/Items.cpp b/library/modules/Items.cpp index 4c695607d..4588b4397 100644 --- a/library/modules/Items.cpp +++ b/library/modules/Items.cpp @@ -63,6 +63,7 @@ using namespace std; #include "df/itemdef_foodst.h" #include "df/trapcomp_flags.h" #include "df/job_item.h" +#include "df/general_ref.h" using namespace DFHack; using namespace df::enums; @@ -559,36 +560,40 @@ bool Items::copyItem(df::item * itembase, DFHack::dfh_item &item) int32_t Items::getItemOwnerID(const df::item * item) { - std::vector vals; - if (readItemRefs(item, d->isOwnerRefClass, vals)) - return vals[0]; - else - return -1; + for (uint32_t i = 0; i < item->itemrefs.size(); i++) + { + df::general_ref *ref = item->itemrefs[i]; + if (ref->getType() == df::general_ref_type::unit_itemowner) + return ref->getID(); + } + return -1; } int32_t Items::getItemContainerID(const df::item * item) { - std::vector vals; - if (readItemRefs(item, d->isContainerRefClass, vals)) - return vals[0]; - else - return -1; + for (uint32_t i = 0; i < item->itemrefs.size(); i++) + { + df::general_ref *ref = item->itemrefs[i]; + if (ref->getType() == df::general_ref_type::contained_in_item) + return ref->getID(); + } + return -1; } bool Items::getContainedItems(const df::item * item, std::vector &items) { - return readItemRefs(item, d->isContainsRefClass, items); + return readItemRefs(item, df::general_ref_type::contains_item, items); } -bool Items::readItemRefs(const df::item * item, const ClassNameCheck &classname, std::vector &values) +bool Items::readItemRefs(const df::item * item, df::general_ref_type type, std::vector &values) { - const std::vector &p_refs = (const std::vector &)item->itemrefs; values.clear(); - for (uint32_t i=0; iitemrefs.size(); i++) { - if (classname(d->owner, p_refs[i]->vptr)) - values.push_back(int32_t(p_refs[i]->value)); + df::general_ref *ref = item->itemrefs[i]; + if (ref->getType() == type) + values.push_back(ref->getID()); } return !values.empty(); @@ -598,15 +603,13 @@ bool Items::unknownRefs(const df::item * item, std::vector &p_refs = (const std::vector &)item->itemrefs; - - for (uint32_t i=0; iitemrefs.size(); i++) { - std::string name = p_refs[i]->getClassName(); + std::string name = ((t_virtual *)(item->itemrefs[i]))->getClassName(); if (d->knownItemRefTypes.find(name) == d->knownItemRefTypes.end()) { - refs.push_back(pair(name, p_refs[i]->value)); + refs.push_back(pair(name, item->itemrefs[i]->getID())); } } @@ -615,21 +618,21 @@ bool Items::unknownRefs(const df::item * item, std::vector &p_refs = (std::vector &)item->itemrefs; - for (uint32_t i=0; iitemrefs.size(); i++) { - if (!d->isOwnerRefClass(d->owner, p_refs[i]->vptr)) + df::general_ref *ref = item->itemrefs[i]; + if (ref->getType() != df::general_ref_type::unit_itemowner) continue; - int32_t & oid = p_refs[i]->value; - int32_t ix = creatures->FindIndexById(oid); + df_unit *unit = (df_unit *)ref->getUnit(); - if (ix < 0 || !creatures->RemoveOwnedItemByIdx(ix, item->id)) + if (unit == NULL || !creatures->RemoveOwnedItemByPtr(unit, item->id)) { - cerr << "RemoveOwnedItemIdx: CREATURE " << ix << " ID " << item->id << " FAILED!" << endl; + cerr << "RemoveOwnedItemIdx: CREATURE " << ref->getID() << " ID " << item->id << " FAILED!" << endl; return false; } - p_refs.erase(p_refs.begin() + i--); + delete ref; + item->itemrefs.erase(item->itemrefs.begin() + i--); } item->flags.bits.owned = 0; From a9eb555b99e7bd83b48ac9c0e057fe35f6cc3ab8 Mon Sep 17 00:00:00 2001 From: Quietust Date: Mon, 16 Jan 2012 20:41:09 -0600 Subject: [PATCH 74/82] Get rid of t_itemimprovement (wasn't even used) --- library/include/modules/Items.h | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/library/include/modules/Items.h b/library/include/modules/Items.h index 1f0a0a5d0..828fb07cf 100644 --- a/library/include/modules/Items.h +++ b/library/include/modules/Items.h @@ -111,17 +111,6 @@ struct dfh_item int16_t wear_level; }; - -/** - * Type for holding item improvements. broken/unused. - * \ingroup grp_items - */ -struct t_improvement -{ - t_material matdesc; - int32_t quality; -}; - /** * The Items module * \ingroup grp_modules From 9d8c67b71038e7d0cacb13f5b026bbdedf21c4ed Mon Sep 17 00:00:00 2001 From: Quietust Date: Mon, 16 Jan 2012 21:22:42 -0600 Subject: [PATCH 75/82] Kill the Kitchen module (which was never really a proper module to begin with) --- library/include/modules/kitchen.h | 56 +++-- library/modules/kitchen.cpp | 333 +++++++++++++----------------- plugins/seedwatch.cpp | 90 ++++---- 3 files changed, 213 insertions(+), 266 deletions(-) diff --git a/library/include/modules/kitchen.h b/library/include/modules/kitchen.h index b169dfb3f..a18011390 100644 --- a/library/include/modules/kitchen.h +++ b/library/include/modules/kitchen.h @@ -30,9 +30,9 @@ distribution. #include "Module.h" #include "Types.h" #include "VersionInfo.h" -#include "modules/Materials.h" -#include "modules/Items.h" #include "Core.h" +#include "modules/Items.h" + /** * \defgroup grp_kitchen Kitchen settings * @ingroup grp_modules @@ -40,6 +40,8 @@ distribution. namespace DFHack { +namespace Simple +{ namespace Kitchen { typedef uint8_t t_exclusionType; @@ -52,45 +54,33 @@ const t_itemSubtype limitSubtype = 0; // used to store limit as an entry in the const t_exclusionType limitExclusion = 4; // used to store limit as an entry in the exclusion list /** - * Kitchen exclusions manipulator class. Currently geared towards plants and seeds. - * @ingroup grp_kitchen + * Kitchen exclusions manipulator. Currently geared towards plants and seeds. + * \ingroup grp_modules + * \ingroup grp_kitchen */ -class DFHACK_EXPORT Exclusions -{ -public: - /// ctor - Exclusions(DFHack::Core& core_); - /// dtor - ~Exclusions(); - - /// print the exclusion list, with the material index also translated into its token (for organics) - for debug really - void debug_print() const; - /// remove this material from the exclusion list if it is in it - void allowPlantSeedCookery(t_materialIndex materialIndex); +// print the exclusion list, with the material index also translated into its token (for organics) - for debug really +DFHACK_EXPORT void debug_print(Core &); - /// add this material to the exclusion list, if it is not already in it - void denyPlantSeedCookery(t_materialIndex materialIndex); +// remove this material from the exclusion list if it is in it +DFHACK_EXPORT void allowPlantSeedCookery(t_materialIndex materialIndex); - /// fills a map with info from the limit info storage entries in the exclusion list - void fillWatchMap(std::map& watchMap) const; +// add this material to the exclusion list, if it is not already in it +DFHACK_EXPORT void denyPlantSeedCookery(t_materialIndex materialIndex); - /// removes a limit info storage entry from the exclusion list if it's present - void removeLimit(t_materialIndex materialIndex); +// fills a map with info from the limit info storage entries in the exclusion list +DFHACK_EXPORT void fillWatchMap(std::map& watchMap); - /// add a limit info storage item to the exclusion list, or alters an existing one - void setLimit(t_materialIndex materialIndex, unsigned int limit); +// removes a limit info storage entry from the exclusion list if it's present +DFHACK_EXPORT void removeLimit(t_materialIndex materialIndex); - /// clears all limit info storage items from the exclusion list - void clearLimits(); +// add a limit info storage item to the exclusion list, or alters an existing one +DFHACK_EXPORT void setLimit(t_materialIndex materialIndex, unsigned int limit); - /// the size of the exclusions vectors (they are all the same size - if not, there is a problem!) - std::size_t size() const; -private: - class Private; - Private* d; - -}; +// clears all limit info storage items from the exclusion list +DFHACK_EXPORT void clearLimits(); +DFHACK_EXPORT std::size_t size(); +} } } diff --git a/library/modules/kitchen.cpp b/library/modules/kitchen.cpp index cd67a9e23..3a85b3926 100644 --- a/library/modules/kitchen.cpp +++ b/library/modules/kitchen.cpp @@ -9,226 +9,191 @@ #include using namespace std; -#include "Types.h" #include "VersionInfo.h" #include "MemAccess.h" -#include "modules/Materials.h" -#include "modules/Items.h" -#include "modules/Units.h" +#include "Types.h" +#include "Error.h" #include "modules/kitchen.h" #include "ModuleFactory.h" #include "Core.h" -#include "Virtual.h" +using namespace DFHack; +using namespace DFHack::Simple; + +#include "DataDefs.h" +#include "df/world.h" +#include "df/ui.h" #include "df/item_type.h" +#include "df/plant_raw.h" + +using namespace df::enums; +using df::global::world; +using df::global::ui; -namespace DFHack +void Kitchen::debug_print(Core &core) { -namespace Kitchen + core.con.print("Kitchen Exclusions\n"); + for(std::size_t i = 0; i < size(); ++i) + { + core.con.print("%2u: IT:%2i IS:%i MT:%3i MI:%2i ET:%i %s\n", + i, + ui->kitchen.item_types[i], + ui->kitchen.item_subtypes[i], + ui->kitchen.mat_types[i], + ui->kitchen.mat_indices[i], + ui->kitchen.exc_types[i], + (ui->kitchen.mat_types[i] >= 419 && ui->kitchen.mat_types[i] <= 618) ? world->raws.plants.all[ui->kitchen.mat_indices[i]]->id.c_str() : "n/a" + ); + } + core.con.print("\n"); +} + +void Kitchen::allowPlantSeedCookery(t_materialIndex materialIndex) { - class Exclusions::Private + bool match = false; + do { - public: - Private (DFHack::Core& core_) - : core(core_) - , itemTypes (*((std::vector*)(addr(core_,0)))) - , itemSubtypes (*((std::vector*)(addr(core_,1)))) - , materialTypes (*((std::vector*)(addr(core_,2)))) - , materialIndices (*((std::vector*)(addr(core_,3)))) - , exclusionTypes (*((std::vector*)(addr(core_,4)))) + match = false; + std::size_t matchIndex = 0; + for(std::size_t i = 0; i < size(); ++i) { - }; - DFHack::Core& core; - std::vector& itemTypes; // the item types vector of the kitchen exclusion list - std::vector& itemSubtypes; // the item subtype vector of the kitchen exclusion list - std::vector& materialTypes; // the material subindex vector of the kitchen exclusion list - std::vector& materialIndices; // the material index vector of the kitchen exclusion list - std::vector& exclusionTypes; // the exclusion type vector of the kitchen excluions list - - static void * addr(const DFHack::Core& core, int index) + if(ui->kitchen.mat_indices[i] == materialIndex + && (ui->kitchen.item_types[i] == df::item_type::SEEDS || ui->kitchen.item_types[i] == df::item_type::PLANT) + && ui->kitchen.exc_types[i] == cookingExclusion + ) + { + match = true; + matchIndex = i; + } + } + if(match) { - static char * start = core.vinfo->getAddress("kitchen_limits"); - return start + sizeof(std::vector) * index; - }; - }; - - Exclusions::Exclusions(Core & c) - { - d = new Private(c); - }; - - Exclusions::~Exclusions() - { - delete d; - }; + ui->kitchen.item_types.erase(ui->kitchen.item_types.begin() + matchIndex); + ui->kitchen.item_subtypes.erase(ui->kitchen.item_subtypes.begin() + matchIndex); + ui->kitchen.mat_indices.erase(ui->kitchen.mat_indices.begin() + matchIndex); + ui->kitchen.mat_types.erase(ui->kitchen.mat_types.begin() + matchIndex); + ui->kitchen.exc_types.erase(ui->kitchen.exc_types.begin() + matchIndex); + } + } while(match); +}; - void Exclusions::debug_print() const +void Kitchen::denyPlantSeedCookery(t_materialIndex materialIndex) +{ + df::plant_raw *type = world->raws.plants.all[materialIndex]; + bool SeedAlreadyIn = false; + bool PlantAlreadyIn = false; + for(std::size_t i = 0; i < size(); ++i) { - d->core.con.print("Kitchen Exclusions\n"); - Materials& materialsModule= *d->core.getMaterials(); - for(std::size_t i = 0; i < size(); ++i) + if(ui->kitchen.mat_indices[i] == materialIndex + && ui->kitchen.exc_types[i] == cookingExclusion) { - d->core.con.print("%2u: IT:%2i IS:%i MT:%3i MI:%2i ET:%i %s\n", - i, - d->itemTypes[i], - d->itemSubtypes[i], - d->materialTypes[i], - d->materialIndices[i], - d->exclusionTypes[i], - materialsModule.df_organic->at(d->materialIndices[i])->ID.c_str() - ); + if(ui->kitchen.item_types[i] == df::item_type::SEEDS) + SeedAlreadyIn = true; + else if (ui->kitchen.item_types[i] == df::item_type::PLANT) + PlantAlreadyIn = true; } - d->core.con.print("\n"); } + if(!SeedAlreadyIn) + { + ui->kitchen.item_types.push_back(df::item_type::SEEDS); + ui->kitchen.item_subtypes.push_back(organicSubtype); + ui->kitchen.mat_types.push_back(type->material_defs.type_seed); + ui->kitchen.mat_indices.push_back(materialIndex); + ui->kitchen.exc_types.push_back(cookingExclusion); + } + if(!PlantAlreadyIn) + { + ui->kitchen.item_types.push_back(df::item_type::PLANT); + ui->kitchen.item_subtypes.push_back(organicSubtype); + ui->kitchen.mat_types.push_back(type->material_defs.type_basic_mat); + ui->kitchen.mat_indices.push_back(materialIndex); + ui->kitchen.exc_types.push_back(cookingExclusion); + } +}; - void Exclusions::allowPlantSeedCookery(t_materialIndex materialIndex) +void Kitchen::fillWatchMap(std::map& watchMap) +{ + watchMap.clear(); + for(std::size_t i = 0; i < size(); ++i) { - bool match = false; - do + if(ui->kitchen.item_subtypes[i] == limitType && ui->kitchen.item_subtypes[i] == limitSubtype && ui->kitchen.exc_types[i] == limitExclusion) { - match = false; - std::size_t matchIndex = 0; - for(std::size_t i = 0; i < size(); ++i) - { - if(d->materialIndices[i] == materialIndex - && (d->itemTypes[i] == df::item_type::SEEDS || d->itemTypes[i] == df::item_type::PLANT) - && d->exclusionTypes[i] == cookingExclusion - ) - { - match = true; - matchIndex = i; - } - } - if(match) - { - d->itemTypes.erase(d->itemTypes.begin() + matchIndex); - d->itemSubtypes.erase(d->itemSubtypes.begin() + matchIndex); - d->materialIndices.erase(d->materialIndices.begin() + matchIndex); - d->materialTypes.erase(d->materialTypes.begin() + matchIndex); - d->exclusionTypes.erase(d->exclusionTypes.begin() + matchIndex); - } - } while(match); - }; + watchMap[ui->kitchen.mat_indices[i]] = (unsigned int) ui->kitchen.mat_types[i]; + } + } +}; - void Exclusions::denyPlantSeedCookery(t_materialIndex materialIndex) +void Kitchen::removeLimit(t_materialIndex materialIndex) +{ + bool match = false; + do { - Materials *mats = d->core.getMaterials(); - df_plant_type *type = mats->df_organic->at(materialIndex); - bool SeedAlreadyIn = false; - bool PlantAlreadyIn = false; + match = false; + std::size_t matchIndex = 0; for(std::size_t i = 0; i < size(); ++i) { - if(d->materialIndices[i] == materialIndex - && d->exclusionTypes[i] == cookingExclusion) + if(ui->kitchen.item_types[i] == limitType + && ui->kitchen.item_subtypes[i] == limitSubtype + && ui->kitchen.mat_indices[i] == materialIndex + && ui->kitchen.exc_types[i] == limitExclusion) { - if(d->itemTypes[i] == df::item_type::SEEDS) - SeedAlreadyIn = true; - else if (d->itemTypes[i] == df::item_type::PLANT) - PlantAlreadyIn = true; + match = true; + matchIndex = i; } } - if(!SeedAlreadyIn) + if(match) { - d->itemTypes.push_back(df::item_type::SEEDS); - d->itemSubtypes.push_back(organicSubtype); - d->materialTypes.push_back(type->material_type_seed); - d->materialIndices.push_back(materialIndex); - d->exclusionTypes.push_back(cookingExclusion); + ui->kitchen.item_types.erase(ui->kitchen.item_types.begin() + matchIndex); + ui->kitchen.item_subtypes.erase(ui->kitchen.item_subtypes.begin() + matchIndex); + ui->kitchen.mat_types.erase(ui->kitchen.mat_types.begin() + matchIndex); + ui->kitchen.mat_indices.erase(ui->kitchen.mat_indices.begin() + matchIndex); + ui->kitchen.exc_types.erase(ui->kitchen.exc_types.begin() + matchIndex); } - if(!PlantAlreadyIn) - { - d->itemTypes.push_back(df::item_type::PLANT); - d->itemSubtypes.push_back(organicSubtype); - d->materialTypes.push_back(type->material_type_basic_mat); - d->materialIndices.push_back(materialIndex); - d->exclusionTypes.push_back(cookingExclusion); - } - }; + } while(match); +}; - void Exclusions::fillWatchMap(std::map& watchMap) const +void Kitchen::setLimit(t_materialIndex materialIndex, unsigned int limit) +{ + removeLimit(materialIndex); + if(limit > seedLimit) { - watchMap.clear(); - for(std::size_t i = 0; i < size(); ++i) - { - if(d->itemTypes[i] == limitType && d->itemSubtypes[i] == limitSubtype && d->exclusionTypes[i] == limitExclusion) - { - watchMap[d->materialIndices[i]] = (unsigned int) d->materialTypes[i]; - } - } - }; + limit = seedLimit; + } + ui->kitchen.item_types.push_back(limitType); + ui->kitchen.item_subtypes.push_back(limitSubtype); + ui->kitchen.mat_indices.push_back(materialIndex); + ui->kitchen.mat_types.push_back((t_materialType) (limit < seedLimit) ? limit : seedLimit); + ui->kitchen.exc_types.push_back(limitExclusion); +}; - void Exclusions::removeLimit(t_materialIndex materialIndex) +void Kitchen::clearLimits() +{ + bool match = false; + do { - bool match = false; - do + match = false; + std::size_t matchIndex; + for(std::size_t i = 0; i < size(); ++i) { - match = false; - std::size_t matchIndex = 0; - for(std::size_t i = 0; i < size(); ++i) + if(ui->kitchen.item_types[i] == limitType + && ui->kitchen.item_subtypes[i] == limitSubtype + && ui->kitchen.exc_types[i] == limitExclusion) { - if(d->itemTypes[i] == limitType - && d->itemSubtypes[i] == limitSubtype - && d->materialIndices[i] == materialIndex - && d->exclusionTypes[i] == limitExclusion) - { - match = true; - matchIndex = i; - } + match = true; + matchIndex = i; } - if(match) - { - d->itemTypes.erase(d->itemTypes.begin() + matchIndex); - d->itemSubtypes.erase(d->itemSubtypes.begin() + matchIndex); - d->materialTypes.erase(d->materialTypes.begin() + matchIndex); - d->materialIndices.erase(d->materialIndices.begin() + matchIndex); - d->exclusionTypes.erase(d->exclusionTypes.begin() + matchIndex); - } - } while(match); - }; - - void Exclusions::setLimit(t_materialIndex materialIndex, unsigned int limit) - { - removeLimit(materialIndex); - if(limit > seedLimit) + } + if(match) { - limit = seedLimit; + ui->kitchen.item_types.erase(ui->kitchen.item_types.begin() + matchIndex); + ui->kitchen.item_subtypes.erase(ui->kitchen.item_subtypes.begin() + matchIndex); + ui->kitchen.mat_indices.erase(ui->kitchen.mat_indices.begin() + matchIndex); + ui->kitchen.mat_types.erase(ui->kitchen.mat_types.begin() + matchIndex); + ui->kitchen.exc_types.erase(ui->kitchen.exc_types.begin() + matchIndex); } - d->itemTypes.push_back(limitType); - d->itemSubtypes.push_back(limitSubtype); - d->materialIndices.push_back(materialIndex); - d->materialTypes.push_back((t_materialType) (limit < seedLimit) ? limit : seedLimit); - d->exclusionTypes.push_back(limitExclusion); - }; + } while(match); +}; - void Exclusions::clearLimits() - { - bool match = false; - do - { - match = false; - std::size_t matchIndex; - for(std::size_t i = 0; i < size(); ++i) - { - if(d->itemTypes[i] == limitType - && d->itemSubtypes[i] == limitSubtype - && d->exclusionTypes[i] == limitExclusion) - { - match = true; - matchIndex = i; - } - } - if(match) - { - d->itemTypes.erase(d->itemTypes.begin() + matchIndex); - d->itemSubtypes.erase(d->itemSubtypes.begin() + matchIndex); - d->materialIndices.erase(d->materialIndices.begin() + matchIndex); - d->materialTypes.erase(d->materialTypes.begin() + matchIndex); - d->exclusionTypes.erase(d->exclusionTypes.begin() + matchIndex); - } - } while(match); - }; - size_t Exclusions::size() const - { - return d->itemTypes.size(); - }; -} -}; \ No newline at end of file +size_t Kitchen::size() +{ + return ui->kitchen.item_types.size(); +}; diff --git a/plugins/seedwatch.cpp b/plugins/seedwatch.cpp index 91da6813c..20d59be36 100755 --- a/plugins/seedwatch.cpp +++ b/plugins/seedwatch.cpp @@ -8,15 +8,14 @@ #include "Core.h" #include "Export.h" #include "PluginManager.h" -#include "modules/Materials.h" #include "modules/Items.h" #include "modules/World.h" #include "modules/kitchen.h" #include "VersionInfo.h" #include "df/item_flags.h" -using DFHack::t_materialType; -using DFHack::t_materialIndex; +using namespace DFHack; +using namespace DFHack::Simple; const int buffer = 20; // seed number buffer - 20 is reasonable bool running = false; // whether seedwatch is counting the seeds or not @@ -39,7 +38,7 @@ bool ignoreSeeds(df::item_flags& f) // seeds with the following flags should not f.bits.in_job; }; -void printHelp(DFHack::Core& core) // prints help +void printHelp(Core& core) // prints help { core.con.print( "Watches the numbers of seeds available and enables/disables seed and plant cooking.\n" @@ -93,17 +92,17 @@ std::string searchAbbreviations(std::string in) } }; -DFhackCExport DFHack::command_result df_seedwatch(DFHack::Core* pCore, std::vector& parameters) +DFhackCExport command_result df_seedwatch(Core* pCore, std::vector& parameters) { - DFHack::Core& core = *pCore; + Core& core = *pCore; if(!core.isValid()) { - return DFHack::CR_FAILURE; + return CR_FAILURE; } core.Suspend(); - DFHack::Materials& materialsModule = *core.getMaterials(); - std::vector organics; + Materials& materialsModule = *core.getMaterials(); + std::vector organics; materialsModule.CopyOrganicMaterials(organics); std::map materialsReverser; @@ -112,17 +111,17 @@ DFhackCExport DFHack::command_result df_seedwatch(DFHack::Core* pCore, std::vect materialsReverser[organics[i].id] = i; } - DFHack::World *w = core.getWorld(); - DFHack::t_gamemodes gm; + World *w = core.getWorld(); + t_gamemodes gm; w->ReadGameMode(gm);// FIXME: check return value // if game mode isn't fortress mode - if(gm.g_mode != DFHack::GAMEMODE_DWARF || gm.g_type != DFHack::GAMETYPE_DWARF_MAIN) + if(gm.g_mode != GAMEMODE_DWARF || gm.g_type != GAMETYPE_DWARF_MAIN) { // just print the help printHelp(core); core.Resume(); - return DFHack::CR_OK; + return CR_OK; } std::string par; @@ -148,8 +147,7 @@ DFhackCExport DFHack::command_result df_seedwatch(DFHack::Core* pCore, std::vect } else if(par == "clear") { - DFHack::Kitchen::Exclusions kitchenExclusions(core); - kitchenExclusions.clearLimits(); + Kitchen::clearLimits(); core.con.print("seedwatch watchlist cleared\n"); } else if(par == "info") @@ -163,9 +161,8 @@ DFhackCExport DFHack::command_result df_seedwatch(DFHack::Core* pCore, std::vect { core.con.print("seedwatch is not supervising. Use 'seedwatch start' to start supervision.\n"); } - DFHack::Kitchen::Exclusions kitchenExclusions(core); std::map watchMap; - kitchenExclusions.fillWatchMap(watchMap); + Kitchen::fillWatchMap(watchMap); if(watchMap.empty()) { core.con.print("The watch list is empty.\n"); @@ -181,10 +178,9 @@ DFhackCExport DFHack::command_result df_seedwatch(DFHack::Core* pCore, std::vect } else if(par == "debug") { - DFHack::Kitchen::Exclusions kitchenExclusions(core); std::map watchMap; - kitchenExclusions.fillWatchMap(watchMap); - kitchenExclusions.debug_print(); + Kitchen::fillWatchMap(watchMap); + Kitchen::debug_print(core); } /* else if(par == "dumpmaps") @@ -209,8 +205,7 @@ DFhackCExport DFHack::command_result df_seedwatch(DFHack::Core* pCore, std::vect std::string token = searchAbbreviations(par); if(materialsReverser.count(token) > 0) { - DFHack::Kitchen::Exclusions kitchenExclusions(core); - kitchenExclusions.removeLimit(materialsReverser[token]); + Kitchen::removeLimit(materialsReverser[token]); core.con.print("%s is not being watched\n", token.c_str()); } else @@ -226,8 +221,7 @@ DFhackCExport DFHack::command_result df_seedwatch(DFHack::Core* pCore, std::vect { for(std::map::const_iterator i = abbreviations.begin(); i != abbreviations.end(); ++i) { - DFHack::Kitchen::Exclusions kitchenExclusions(core); - if(materialsReverser.count(i->second) > 0) kitchenExclusions.setLimit(materialsReverser[i->second], limit); + if(materialsReverser.count(i->second) > 0) Kitchen::setLimit(materialsReverser[i->second], limit); } } else @@ -235,8 +229,7 @@ DFhackCExport DFHack::command_result df_seedwatch(DFHack::Core* pCore, std::vect std::string token = searchAbbreviations(parameters[0]); if(materialsReverser.count(token) > 0) { - DFHack::Kitchen::Exclusions kitchenExclusions(core); - kitchenExclusions.setLimit(materialsReverser[token], limit); + Kitchen::setLimit(materialsReverser[token], limit); core.con.print("%s is being watched.\n", token.c_str()); } else @@ -251,7 +244,7 @@ DFhackCExport DFHack::command_result df_seedwatch(DFHack::Core* pCore, std::vect } core.Resume(); - return DFHack::CR_OK; + return CR_OK; } DFhackCExport const char* plugin_name(void) @@ -259,10 +252,10 @@ DFhackCExport const char* plugin_name(void) return "seedwatch"; } -DFhackCExport DFHack::command_result plugin_init(DFHack::Core* pCore, std::vector& commands) +DFhackCExport command_result plugin_init(Core* pCore, std::vector& commands) { commands.clear(); - commands.push_back(DFHack::PluginCommand("seedwatch", "Switches cookery based on quantity of seeds, to keep reserves", df_seedwatch)); + commands.push_back(PluginCommand("seedwatch", "Switches cookery based on quantity of seeds, to keep reserves", df_seedwatch)); // fill in the abbreviations map, with abbreviations for the standard plants abbreviations["bs"] = "SLIVER_BARB"; abbreviations["bt"] = "TUBER_BLOATED"; @@ -285,14 +278,14 @@ DFhackCExport DFHack::command_result plugin_init(DFHack::Core* pCore, std::vecto abbreviations["vh"] = "HERB_VALLEY"; abbreviations["ws"] = "BERRIES_STRAW_WILD"; abbreviations["wv"] = "VINE_WHIP"; - return DFHack::CR_OK; + return CR_OK; } -DFhackCExport DFHack::command_result plugin_onstatechange(DFHack::Core* pCore, DFHack::state_change_event event) +DFhackCExport command_result plugin_onstatechange(Core* pCore, state_change_event event) { switch (event) { - case DFHack::SC_GAME_LOADED: - case DFHack::SC_GAME_UNLOADED: + case SC_GAME_LOADED: + case SC_GAME_UNLOADED: if (running) pCore->con.printerr("seedwatch deactivated due to game load/unload\n"); running = false; @@ -301,34 +294,34 @@ DFhackCExport DFHack::command_result plugin_onstatechange(DFHack::Core* pCore, D break; } - return DFHack::CR_OK; + return CR_OK; } -DFhackCExport DFHack::command_result plugin_onupdate(DFHack::Core* pCore) +DFhackCExport command_result plugin_onupdate(Core* pCore) { if (running) { // reduce processing rate static int counter = 0; if (++counter < 500) - return DFHack::CR_OK; + return CR_OK; counter = 0; - DFHack::Core& core = *pCore; - DFHack::World *w = core.getWorld(); - DFHack::t_gamemodes gm; + Core& core = *pCore; + World *w = core.getWorld(); + t_gamemodes gm; w->ReadGameMode(gm);// FIXME: check return value // if game mode isn't fortress mode - if(gm.g_mode != DFHack::GAMEMODE_DWARF || gm.g_type != DFHack::GAMETYPE_DWARF_MAIN) + if(gm.g_mode != GAMEMODE_DWARF || gm.g_type != GAMETYPE_DWARF_MAIN) { // stop running. running = false; core.con.printerr("seedwatch deactivated due to game mode switch\n"); - return DFHack::CR_OK; + return CR_OK; } // this is dwarf mode, continue std::map seedCount; // the number of seeds - DFHack::Items& itemsModule = *core.getItems(); + Items& itemsModule = *core.getItems(); itemsModule.Start(); std::vector items; itemsModule.readItemVector(items); @@ -349,25 +342,24 @@ DFhackCExport DFHack::command_result plugin_onupdate(DFHack::Core* pCore) } itemsModule.Finish(); - DFHack::Kitchen::Exclusions kitchenExclusions(core); std::map watchMap; - kitchenExclusions.fillWatchMap(watchMap); + Kitchen::fillWatchMap(watchMap); for(auto i = watchMap.begin(); i != watchMap.end(); ++i) { if(seedCount[i->first] <= i->second) { - kitchenExclusions.denyPlantSeedCookery(i->first); + Kitchen::denyPlantSeedCookery(i->first); } else if(i->second + buffer < seedCount[i->first]) { - kitchenExclusions.allowPlantSeedCookery(i->first); + Kitchen::allowPlantSeedCookery(i->first); } } } - return DFHack::CR_OK; + return CR_OK; } -DFhackCExport DFHack::command_result plugin_shutdown(DFHack::Core* pCore) +DFhackCExport command_result plugin_shutdown(Core* pCore) { - return DFHack::CR_OK; + return CR_OK; } From e75291ee91adb0c76619a7d61814b85ea22402a1 Mon Sep 17 00:00:00 2001 From: Quietust Date: Mon, 16 Jan 2012 21:29:09 -0600 Subject: [PATCH 76/82] Unlink seedwatch plugin from Materials module --- plugins/seedwatch.cpp | 26 ++++++++++---------------- 1 file changed, 10 insertions(+), 16 deletions(-) diff --git a/plugins/seedwatch.cpp b/plugins/seedwatch.cpp index 20d59be36..43de41490 100755 --- a/plugins/seedwatch.cpp +++ b/plugins/seedwatch.cpp @@ -8,15 +8,18 @@ #include "Core.h" #include "Export.h" #include "PluginManager.h" -#include "modules/Items.h" #include "modules/World.h" #include "modules/kitchen.h" #include "VersionInfo.h" +#include "df/world.h" +#include "df/plant_raw.h" #include "df/item_flags.h" using namespace DFHack; using namespace DFHack::Simple; +using df::global::world; + const int buffer = 20; // seed number buffer - 20 is reasonable bool running = false; // whether seedwatch is counting the seeds or not @@ -101,14 +104,10 @@ DFhackCExport command_result df_seedwatch(Core* pCore, std::vector& } core.Suspend(); - Materials& materialsModule = *core.getMaterials(); - std::vector organics; - materialsModule.CopyOrganicMaterials(organics); - std::map materialsReverser; - for(std::size_t i = 0; i < organics.size(); ++i) + for(std::size_t i = 0; i < world->raws.plants.all.size(); ++i) { - materialsReverser[organics[i].id] = i; + materialsReverser[world->raws.plants.all[i]->id] = i; } World *w = core.getWorld(); @@ -172,7 +171,7 @@ DFhackCExport command_result df_seedwatch(Core* pCore, std::vector& core.con.print("The watch list is:\n"); for(std::map::const_iterator i = watchMap.begin(); i != watchMap.end(); ++i) { - core.con.print("%s : %u\n", organics[i->first].id.c_str(), i->second); + core.con.print("%s : %u\n", world->raws.plants.all[i->first]->id.c_str(), i->second); } } } @@ -321,15 +320,11 @@ DFhackCExport command_result plugin_onupdate(Core* pCore) } // this is dwarf mode, continue std::map seedCount; // the number of seeds - Items& itemsModule = *core.getItems(); - itemsModule.Start(); - std::vector items; - itemsModule.readItemVector(items); - df::item * item; + // count all seeds and plants by RAW material - for(std::size_t i = 0; i < items.size(); ++i) + for(std::size_t i = 0; i < world->items.all.size(); ++i) { - item = items[i]; + df::item * item = world->items.all[i]; t_materialIndex materialIndex = item->getMaterialIndex(); switch(item->getType()) { @@ -340,7 +335,6 @@ DFhackCExport command_result plugin_onupdate(Core* pCore) break; } } - itemsModule.Finish(); std::map watchMap; Kitchen::fillWatchMap(watchMap); From fd653a0227f3bca86d8fd4b9e7f515b6c4015524 Mon Sep 17 00:00:00 2001 From: Quietust Date: Mon, 16 Jan 2012 22:12:58 -0600 Subject: [PATCH 77/82] Kill the Items module --- library/Core.cpp | 1 - library/include/Core.h | 4 - library/include/ModuleFactory.h | 1 - library/include/modules/Items.h | 68 ++++++-------- library/include/modules/Units.h | 2 - library/modules/Items.cpp | 156 +------------------------------- plugins/autodump.cpp | 12 +-- plugins/cleanowned.cpp | 28 +++--- 8 files changed, 44 insertions(+), 228 deletions(-) diff --git a/library/Core.cpp b/library/Core.cpp index 9404fdb5b..68af3e15a 100644 --- a/library/Core.cpp +++ b/library/Core.cpp @@ -1094,7 +1094,6 @@ MODULE_GETTER(Maps); MODULE_GETTER(Gui); MODULE_GETTER(World); MODULE_GETTER(Materials); -MODULE_GETTER(Items); MODULE_GETTER(Translation); MODULE_GETTER(Vegetation); MODULE_GETTER(Constructions); diff --git a/library/include/Core.h b/library/include/Core.h index 3366b990b..988595062 100644 --- a/library/include/Core.h +++ b/library/include/Core.h @@ -58,7 +58,6 @@ namespace DFHack class Gui; class World; class Materials; - class Items; class Translation; class Vegetation; class Constructions; @@ -111,8 +110,6 @@ namespace DFHack World * getWorld(); /// get the materials module Materials * getMaterials(); - /// get the items module - Items * getItems(); /// get the translation module Translation * getTranslation(); /// get the vegetation module @@ -173,7 +170,6 @@ namespace DFHack Gui * pGui; World * pWorld; Materials * pMaterials; - Items * pItems; Translation * pTranslation; Vegetation * pVegetation; Constructions * pConstructions; diff --git a/library/include/ModuleFactory.h b/library/include/ModuleFactory.h index 0ee5b178f..78ff9db19 100644 --- a/library/include/ModuleFactory.h +++ b/library/include/ModuleFactory.h @@ -35,7 +35,6 @@ namespace DFHack Module* createGui(); Module* createWorld(); Module* createMaterials(); - Module* createItems(); Module* createTranslation(); Module* createVegetation(); Module* createBuildings(); diff --git a/library/include/modules/Items.h b/library/include/modules/Items.h index 828fb07cf..4cd29766a 100644 --- a/library/include/modules/Items.h +++ b/library/include/modules/Items.h @@ -116,46 +116,32 @@ struct dfh_item * \ingroup grp_modules * \ingroup grp_items */ -class DFHACK_EXPORT Items : public Module +namespace Simple { -public: - /** - * All the known item types as an enum - * From http://df.magmawiki.com/index.php/DF2010:Item_token - */ - -public: - Items(); - ~Items(); - bool Start(); - bool Finish(); - /// Read the item vector from DF into a supplied vector - bool readItemVector(std::vector &items); - /// Look for a particular item by ID - df::item * findItemByID(int32_t id); - - /// Make a partial copy of a DF item - bool copyItem(df::item * source, dfh_item & target); - /// write copied item back to its origin - bool writeItem(const dfh_item & item); - - /// get the class name of an item - std::string getItemClass(const df::item * item); - /// who owns this item we already read? - int32_t getItemOwnerID(const df::item * item); - /// which item is it contained in? - int32_t getItemContainerID(const df::item * item); - /// which items does it contain? - bool getContainedItems(const df::item * item, /*output*/ std::vector &items); - /// wipe out the owner records - bool removeItemOwner(df::item * item, Units *creatures); - /// read item references, filtered by class - bool readItemRefs(const df::item * item, const df::general_ref_type type, - /*output*/ std::vector &values); - /// get list of item references that are unknown along with their values - bool unknownRefs(const df::item * item, /*output*/ std::vector >& refs); -private: - class Private; - Private* d; -}; +namespace Items +{ + +/// Look for a particular item by ID +DFHACK_EXPORT df::item * findItemByID(int32_t id); + +/// Make a partial copy of a DF item +DFHACK_EXPORT bool copyItem(df::item * source, dfh_item & target); +/// write copied item back to its origin +DFHACK_EXPORT bool writeItem(const dfh_item & item); + +/// get the class name of an item +DFHACK_EXPORT std::string getItemClass(const df::item * item); +/// who owns this item we already read? +DFHACK_EXPORT int32_t getItemOwnerID(const df::item * item); +/// which item is it contained in? +DFHACK_EXPORT int32_t getItemContainerID(const df::item * item); +/// which items does it contain? +DFHACK_EXPORT bool getContainedItems(const df::item * item, /*output*/ std::vector &items); +/// wipe out the owner records +DFHACK_EXPORT bool removeItemOwner(df::item * item, Units *creatures); +/// read item references, filtered by class +DFHACK_EXPORT bool readItemRefs(const df::item * item, const df::general_ref_type type, + /*output*/ std::vector &values); +} } +} \ No newline at end of file diff --git a/library/include/modules/Units.h b/library/include/modules/Units.h index c7dfe202d..779fef8cf 100644 --- a/library/include/modules/Units.h +++ b/library/include/modules/Units.h @@ -807,8 +807,6 @@ namespace DFHack void CopyNameTo(df_unit *creature, df_name * target); - protected: - friend class Items; bool RemoveOwnedItemByIdx(const uint32_t index, int32_t id); bool RemoveOwnedItemByPtr(df_unit * unit, int32_t id); diff --git a/library/modules/Items.cpp b/library/modules/Items.cpp index 4588b4397..d54a56f13 100644 --- a/library/modules/Items.cpp +++ b/library/modules/Items.cpp @@ -66,7 +66,9 @@ using namespace std; #include "df/general_ref.h" using namespace DFHack; +using namespace DFHack::Simple; using namespace df::enums; +using df::global::world; #define ITEMDEF_VECTORS \ ITEM(WEAPON, weapons, itemdef_weaponst) \ @@ -394,146 +396,11 @@ bool ItemTypeInfo::matches(const df::job_item &item, MaterialInfo *mat) bits_match(item.flags3.whole, item_ok3.whole, item_mask3.whole); } - -Module* DFHack::createItems() -{ - return new Items(); -} - -class Items::Private -{ - public: - Process * owner; - std::map idLookupTable; - uint32_t refVectorOffset; - uint32_t idFieldOffset; - void * itemVectorAddress; - - ClassNameCheck isOwnerRefClass; - ClassNameCheck isContainerRefClass; - ClassNameCheck isContainsRefClass; - - // Similar to isOwnerRefClass. Value is unique to each creature, but - // different than the creature's id. - ClassNameCheck isUnitHolderRefClass; - - // One of these is present for each creature contained in a cage. - // The value is similar to that for isUnitHolderRefClass, different - // than the creature's ID but unique for each creature. - ClassNameCheck isCagedUnitRefClass; - - // ID of bulding containing/holding the item. - ClassNameCheck isBuildingHolderRefClass; - - // Building ID of lever/etc which triggers bridge/etc holding - // this mechanism. - ClassNameCheck isTriggeredByRefClass; - - // Building ID of bridge/etc which is triggered by lever/etc holding - // this mechanism. - ClassNameCheck isTriggerTargetRefClass; - - // Civilization ID of owner of item, for items not owned by the - // fortress. - ClassNameCheck isEntityOwnerRefClass; - - // Item has been offered to the caravan. The value is the - // civilization ID of - ClassNameCheck isOfferedRefClass; - - // Item is in a depot for trade. Purpose of value is unknown, but is - // different for each item, even in the same depot at the same time. - ClassNameCheck isTradingRefClass; - - // Item is flying or falling through the air. The value seems to - // be the ID for a "projectile information" object. - ClassNameCheck isProjectileRefClass; - - std::set knownItemRefTypes; -}; - -Items::Items() -{ - Core & c = Core::getInstance(); - d = new Private; - d->owner = c.p; - - DFHack::OffsetGroup* itemGroup = c.vinfo->getGroup("Items"); - d->itemVectorAddress = itemGroup->getAddress("items_vector"); - d->idFieldOffset = itemGroup->getOffset("id"); - d->refVectorOffset = itemGroup->getOffset("item_ref_vector"); - - d->isOwnerRefClass = ClassNameCheck("general_ref_unit_itemownerst"); - d->isContainerRefClass = ClassNameCheck("general_ref_contained_in_itemst"); - d->isContainsRefClass = ClassNameCheck("general_ref_contains_itemst"); - d->isUnitHolderRefClass = ClassNameCheck("general_ref_unit_holderst"); - d->isCagedUnitRefClass = ClassNameCheck("general_ref_contains_unitst"); - d->isBuildingHolderRefClass - = ClassNameCheck("general_ref_building_holderst"); - d->isTriggeredByRefClass = ClassNameCheck("general_ref_building_triggerst"); - d->isTriggerTargetRefClass - = ClassNameCheck("general_ref_building_triggertargetst"); - d->isEntityOwnerRefClass = ClassNameCheck("general_ref_entity_itemownerst"); - d->isOfferedRefClass = ClassNameCheck("general_ref_entity_offeredst"); - d->isTradingRefClass = ClassNameCheck("general_ref_unit_tradebringerst"); - d->isProjectileRefClass = ClassNameCheck("general_ref_projectilest"); - - std::vector known_names; - ClassNameCheck::getKnownClassNames(known_names); - - for (size_t i = 0; i < known_names.size(); i++) - { - if (known_names[i].find("general_ref_") == 0) - d->knownItemRefTypes.insert(known_names[i]); - } -} - -bool Items::Start() -{ - d->idLookupTable.clear(); - return true; -} - -bool Items::Finish() -{ - return true; -} - -bool Items::readItemVector(std::vector &items) -{ - std::vector *p_items = (std::vector *) d->itemVectorAddress; - - d->idLookupTable.clear(); - items.resize(p_items->size()); - - for (unsigned i = 0; i < p_items->size(); i++) - { - df::item * ptr = p_items->at(i); - items[i] = ptr; - d->idLookupTable[ptr->id] = ptr; - } - - return true; -} - df::item * Items::findItemByID(int32_t id) { if (id < 0) return 0; - - if (d->idLookupTable.empty()) - { - std::vector tmp; - readItemVector(tmp); - } - - return d->idLookupTable[id]; -} - -Items::~Items() -{ - Finish(); - delete d; + return df::item::find(id); } bool Items::copyItem(df::item * itembase, DFHack::dfh_item &item) @@ -599,23 +466,6 @@ bool Items::readItemRefs(const df::item * item, df::general_ref_type type, std:: return !values.empty(); } -bool Items::unknownRefs(const df::item * item, std::vector >& refs) -{ - refs.clear(); - - for (uint32_t i = 0; i < item->itemrefs.size(); i++) - { - std::string name = ((t_virtual *)(item->itemrefs[i]))->getClassName(); - - if (d->knownItemRefTypes.find(name) == d->knownItemRefTypes.end()) - { - refs.push_back(pair(name, item->itemrefs[i]->getID())); - } - } - - return (refs.size() > 0); -} - bool Items::removeItemOwner(df::item * item, Units *creatures) { for (uint32_t i = 0; i < item->itemrefs.size(); i++) diff --git a/plugins/autodump.cpp b/plugins/autodump.cpp index 8c1820f2b..8c7f9a16b 100644 --- a/plugins/autodump.cpp +++ b/plugins/autodump.cpp @@ -28,6 +28,7 @@ using namespace std; using namespace DFHack; using MapExtras::Block; using MapExtras::MapCache; +using df::global::world; DFhackCExport command_result df_autodump(Core * c, vector & parameters); DFhackCExport command_result df_autodump_destroy_here(Core * c, vector & parameters); @@ -95,16 +96,9 @@ static command_result autodump_main(Core * c, vector & parameters) DFHack::VersionInfo *mem = c->vinfo; DFHack::Gui * Gui = c->getGui(); - DFHack::Items * Items = c->getItems(); DFHack::Maps *Maps = c->getMaps(); - vector p_items; - if(!Items->readItemVector(p_items)) - { - c->con.printerr("Can't access the item vector.\n"); - return CR_FAILURE; - } - std::size_t numItems = p_items.size(); + std::size_t numItems = world->items.all.size(); // init the map if(!Maps->Start()) @@ -148,7 +142,7 @@ static command_result autodump_main(Core * c, vector & parameters) // proceed with the dumpification operation for(std::size_t i=0; i< numItems; i++) { - df::item * itm = p_items[i]; + df::item * itm = world->items.all[i]; DFCoord pos_item(itm->x, itm->y, itm->z); // keep track how many items are at places. all items. diff --git a/plugins/cleanowned.cpp b/plugins/cleanowned.cpp index 0935c2eaa..4e8c254bc 100644 --- a/plugins/cleanowned.cpp +++ b/plugins/cleanowned.cpp @@ -20,6 +20,11 @@ using namespace std; #include "modules/Materials.h" #include "modules/Translation.h" using namespace DFHack; +using namespace DFHack::Simple; +#include "DataDefs.h" +#include "df/world.h" + +using df::global::world; DFhackCExport command_result df_cleanowned (Core * c, vector & parameters); @@ -89,7 +94,6 @@ DFhackCExport command_result df_cleanowned (Core * c, vector & paramete } c->Suspend(); DFHack::Materials *Materials = c->getMaterials(); - DFHack::Items *Items = c->getItems(); DFHack::Units *Creatures = c->getUnits(); DFHack::Translation *Tran = c->getTranslation(); @@ -99,25 +103,17 @@ DFhackCExport command_result df_cleanowned (Core * c, vector & paramete ok &= Creatures->Start(num_creatures); ok &= Tran->Start(); - vector p_items; - ok &= Items->readItemVector(p_items); - if(!ok) - { - c->con.printerr("Can't continue due to offset errors.\n"); - c->Resume(); - return CR_FAILURE; - } - c->con.print("Found total %d items.\n", p_items.size()); + c->con.print("Found total %d items.\n", world->items.all.size()); - for (std::size_t i=0; i < p_items.size(); i++) + for (std::size_t i=0; i < world->items.all.size(); i++) { - df::item * item = p_items[i]; + df::item * item = world->items.all[i]; bool confiscate = false; bool dump = false; if (!item->flags.bits.owned) { - int32_t owner = Items->getItemOwnerID(item); + int32_t owner = Items::getItemOwnerID(item); if (owner >= 0) { c->con.print("Fixing a misflagged item: \t"); @@ -129,8 +125,6 @@ DFhackCExport command_result df_cleanowned (Core * c, vector & paramete } } - std::string name = Items->getItemClass(item); - if (item->flags.bits.rotten) { c->con.print("Confiscating a rotten item: \t"); @@ -189,7 +183,7 @@ DFhackCExport command_result df_cleanowned (Core * c, vector & paramete item->getWear() ); - int32_t owner = Items->getItemOwnerID(item); + int32_t owner = Items::getItemOwnerID(item); int32_t owner_index = Creatures->FindIndexById(owner); std::string info; @@ -206,7 +200,7 @@ DFhackCExport command_result df_cleanowned (Core * c, vector & paramete if (!dry_run) { - if (!Items->removeItemOwner(item, Creatures)) + if (!Items::removeItemOwner(item, Creatures)) c->con.print("(unsuccessfully) "); if (dump) item->flags.bits.dump = 1; From 43476b2ea750daff2badd8cc7dd3abf5ffd601c3 Mon Sep 17 00:00:00 2001 From: Alexander Gavrilov Date: Tue, 17 Jan 2012 19:44:48 +0400 Subject: [PATCH 78/82] Fix Z level computation in prospect, and add levels for flows & aquifer. --- plugins/prospector.cpp | 75 ++++++++++++++++++++++++++++++++++-------- 1 file changed, 61 insertions(+), 14 deletions(-) diff --git a/plugins/prospector.cpp b/plugins/prospector.cpp index 6d907a4a4..c2a936f1c 100644 --- a/plugins/prospector.cpp +++ b/plugins/prospector.cpp @@ -19,6 +19,9 @@ using namespace std; #include "PluginManager.h" #include "modules/MapCache.h" +#include "DataDefs.h" +#include "df/world.h" + using namespace DFHack; struct matdata @@ -85,6 +88,16 @@ struct compare_pair_second } }; +void printMatdata(DFHack::Console & con, const matdata &data) +{ + con << std::setw(9) << data.count; + + if(data.lower_z != data.upper_z) + con <<" Z:" << std::setw(4) << data.lower_z << ".." << data.upper_z << std::endl; + else + con <<" Z:" << std::setw(4) << data.lower_z << std::endl; +} + // printMats() accepts a vector of pointers to t_matgloss so that it can // deal t_matgloss and all subclasses. template @@ -108,12 +121,8 @@ void printMats(DFHack::Console & con, MatMap &mat, std::vector &materials) continue; } T* mat = materials[it->first]; - con << std::setw(25) << mat->ID << " : " - << std::setw(9) << it->second.count; - if(it->second.lower_z != it->second.upper_z) - con <<" Z:" << std::setw(4) << it->second.lower_z << ".." << it->second.upper_z << std::endl; - else - con <<" Z:" << std::setw(4) << it->second.lower_z << std::endl; + con << std::setw(25) << mat->ID << " : "; + printMatdata(con, it->second); total += it->second.count; } @@ -231,6 +240,10 @@ DFhackCExport command_result prospector (DFHack::Core * c, vector & par MatMap plantMats; MatMap treeMats; + matdata liquidWater; + matdata liquidMagma; + matdata aquiferTiles; + if (!(showSlade && maps->ReadGlobalFeatures(globalFeatures))) { con.printerr("Unable to read global features; slade won't be listed!\n"); @@ -282,6 +295,8 @@ DFhackCExport command_result prospector (DFHack::Core * c, vector & par } } + int global_z = df::global::world->map.region_z + z; + // Iterate over all the tiles in the block for(uint32_t y = 0; y < 16; y++) { @@ -301,6 +316,7 @@ DFhackCExport command_result prospector (DFHack::Core * c, vector & par if (des.bits.water_table) { hasAquifer = true; + aquiferTiles.add(global_z); } // Check for lairs @@ -309,6 +325,15 @@ DFhackCExport command_result prospector (DFHack::Core * c, vector & par hasLair = true; } + // Check for liquid + if (des.bits.flow_size) + { + if (des.bits.liquid_type == liquid_magma) + liquidMagma.add(global_z); + else + liquidWater.add(global_z); + } + uint16_t type = b->TileTypeAt(coord); const DFHack::TileRow *info = DFHack::getTileRow(type); @@ -330,17 +355,17 @@ DFhackCExport command_result prospector (DFHack::Core * c, vector & par } // Count the material type - baseMats[info->material].add(z); + baseMats[info->material].add(global_z); // Find the type of the tile switch (info->material) { case DFHack::SOIL: case DFHack::STONE: - layerMats[b->baseMaterialAt(coord)].add(z); + layerMats[b->baseMaterialAt(coord)].add(global_z); break; case DFHack::VEIN: - veinMats[b->veinMaterialAt(coord)].add(z); + veinMats[b->veinMaterialAt(coord)].add(global_z); break; case DFHack::FEATSTONE: if (blockFeatureLocal && des.bits.feature_local) @@ -348,7 +373,7 @@ DFhackCExport command_result prospector (DFHack::Core * c, vector & par if (blockFeatureLocal->type == DFHack::feature_Adamantine_Tube && blockFeatureLocal->main_material == 0) // stone { - veinMats[blockFeatureLocal->sub_material].add(z); + veinMats[blockFeatureLocal->sub_material].add(global_z); } else if (showTemple && blockFeatureLocal->type == DFHack::feature_Hell_Temple) @@ -361,7 +386,7 @@ DFhackCExport command_result prospector (DFHack::Core * c, vector & par && blockFeatureGlobal->type == DFHack::feature_Underworld && blockFeatureGlobal->main_material == 0) // stone { - layerMats[blockFeatureGlobal->sub_material].add(z); + layerMats[blockFeatureGlobal->sub_material].add(global_z); } break; case DFHack::OBSIDIAN: @@ -386,9 +411,9 @@ DFhackCExport command_result prospector (DFHack::Core * c, vector & par if (showHidden || !b->DesignationAt(loc).bits.hidden) { if(plant.is_shrub) - plantMats[plant.material].add(z); + plantMats[plant.material].add(global_z); else - treeMats[plant.material].add(z); + treeMats[plant.material].add(global_z); } } } @@ -409,6 +434,21 @@ DFhackCExport command_result prospector (DFHack::Core * c, vector & par con << std::setw(25) << DFHack::TileMaterialString[it->first] << " : " << it->second.count << std::endl; } + if (liquidWater.count || liquidMagma.count) + { + con << std::endl << "Liquids:" << std::endl; + if (liquidWater.count) + { + con << std::setw(25) << "WATER" << " : "; + printMatdata(con, liquidWater); + } + if (liquidWater.count) + { + con << std::setw(25) << "MAGMA" << " : "; + printMatdata(con, liquidMagma); + } + } + con << std::endl << "Layer materials:" << std::endl; printMats(con, layerMats, *mats->df_inorganic); @@ -424,7 +464,14 @@ DFhackCExport command_result prospector (DFHack::Core * c, vector & par if (hasAquifer) { - con << "Has aquifer" << std::endl; + con << "Has aquifer"; + if (aquiferTiles.count) + { + con << " : "; + printMatdata(con, aquiferTiles); + } + else + con << std::endl; } if (hasDemonTemple) From 1aec9649c5c2657be03211733844c751ee023f3e Mon Sep 17 00:00:00 2001 From: Alexander Gavrilov Date: Tue, 17 Jan 2012 19:56:52 +0400 Subject: [PATCH 79/82] Support including material value in the prospector output. --- plugins/prospector.cpp | 40 +++++++++++++++++++++++++++++----------- 1 file changed, 29 insertions(+), 11 deletions(-) diff --git a/plugins/prospector.cpp b/plugins/prospector.cpp index c2a936f1c..8f76465ea 100644 --- a/plugins/prospector.cpp +++ b/plugins/prospector.cpp @@ -88,7 +88,7 @@ struct compare_pair_second } }; -void printMatdata(DFHack::Console & con, const matdata &data) +static void printMatdata(DFHack::Console & con, const matdata &data) { con << std::setw(9) << data.count; @@ -98,10 +98,20 @@ void printMatdata(DFHack::Console & con, const matdata &data) con <<" Z:" << std::setw(4) << data.lower_z << std::endl; } +static int getValue(const df_inorganic_type &info) +{ + return info.mat.MATERIAL_VALUE; +} + +static int getValue(const df_plant_type &info) +{ + return info.value; +} + // printMats() accepts a vector of pointers to t_matgloss so that it can // deal t_matgloss and all subclasses. template -void printMats(DFHack::Console & con, MatMap &mat, std::vector &materials) +void printMats(DFHack::Console & con, MatMap &mat, std::vector &materials, bool show_value) { unsigned int total = 0; MatSorter sorting_vector; @@ -122,6 +132,8 @@ void printMats(DFHack::Console & con, MatMap &mat, std::vector &materials) } T* mat = materials[it->first]; con << std::setw(25) << mat->ID << " : "; + if (show_value) + con << std::setw(3) << getValue(*mat) << " : "; printMatdata(con, it->second); total += it->second.count; } @@ -130,7 +142,7 @@ void printMats(DFHack::Console & con, MatMap &mat, std::vector &materials) } void printVeins(DFHack::Console & con, MatMap &mat_map, - DFHack::Materials* mats) + DFHack::Materials* mats, bool show_value) { MatMap ores; MatMap gems; @@ -149,13 +161,13 @@ void printVeins(DFHack::Console & con, MatMap &mat_map, } con << "Ores:" << std::endl; - printMats(con, ores, *mats->df_inorganic); + printMats(con, ores, *mats->df_inorganic, show_value); con << "Gems:" << std::endl; - printMats(con, gems, *mats->df_inorganic); + printMats(con, gems, *mats->df_inorganic, show_value); con << "Other vein stone:" << std::endl; - printMats(con, rest, *mats->df_inorganic); + printMats(con, rest, *mats->df_inorganic, show_value); } DFhackCExport command_result prospector (Core * c, vector & parameters); @@ -183,13 +195,18 @@ DFhackCExport command_result prospector (DFHack::Core * c, vector & par bool showPlants = true; bool showSlade = true; bool showTemple = true; + bool showValue = false; Console & con = c->con; for(int i = 0; i < parameters.size();i++) { - if (parameters[0] == "all") + if (parameters[i] == "all") { showHidden = true; } + if (parameters[i] == "value") + { + showValue = true; + } else if(parameters[i] == "help" || parameters[i] == "?") { c->con.print("Prints a big list of all the present minerals.\n" @@ -197,6 +214,7 @@ DFhackCExport command_result prospector (DFHack::Core * c, vector & par "\n" "Options:\n" "all - Scan the whole map, as if it was revealed.\n" + "value - Show material value in the output.\n" ); return CR_OK; } @@ -450,16 +468,16 @@ DFhackCExport command_result prospector (DFHack::Core * c, vector & par } con << std::endl << "Layer materials:" << std::endl; - printMats(con, layerMats, *mats->df_inorganic); + printMats(con, layerMats, *mats->df_inorganic, showValue); - printVeins(con, veinMats, mats); + printVeins(con, veinMats, mats, showValue); if (showPlants) { con << "Shrubs:" << std::endl; - printMats(con, plantMats, *mats->df_organic); + printMats(con, plantMats, *mats->df_organic, showValue); con << "Wood in trees:" << std::endl; - printMats(con, treeMats, *mats->df_organic); + printMats(con, treeMats, *mats->df_organic, showValue); } if (hasAquifer) From 35ad84c58a0a35732d14cc6e31e457e28546e721 Mon Sep 17 00:00:00 2001 From: Quietust Date: Wed, 18 Jan 2012 08:26:08 -0600 Subject: [PATCH 80/82] angavrilov changed general_ref_type to be all uppercase --- library/modules/Items.cpp | 10 +++++----- plugins/autodump.cpp | 2 +- plugins/workflow.cpp | 10 +++++----- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/library/modules/Items.cpp b/library/modules/Items.cpp index d54a56f13..3b731c0d0 100644 --- a/library/modules/Items.cpp +++ b/library/modules/Items.cpp @@ -1,4 +1,4 @@ -/* +/* https://github.com/peterix/dfhack Copyright (c) 2009-2011 Petr Mrázek (peterix@gmail.com) @@ -430,7 +430,7 @@ int32_t Items::getItemOwnerID(const df::item * item) for (uint32_t i = 0; i < item->itemrefs.size(); i++) { df::general_ref *ref = item->itemrefs[i]; - if (ref->getType() == df::general_ref_type::unit_itemowner) + if (ref->getType() == df::general_ref_type::UNIT_ITEMOWNER) return ref->getID(); } return -1; @@ -441,7 +441,7 @@ int32_t Items::getItemContainerID(const df::item * item) for (uint32_t i = 0; i < item->itemrefs.size(); i++) { df::general_ref *ref = item->itemrefs[i]; - if (ref->getType() == df::general_ref_type::contained_in_item) + if (ref->getType() == df::general_ref_type::CONTAINED_IN_ITEM) return ref->getID(); } return -1; @@ -449,7 +449,7 @@ int32_t Items::getItemContainerID(const df::item * item) bool Items::getContainedItems(const df::item * item, std::vector &items) { - return readItemRefs(item, df::general_ref_type::contains_item, items); + return readItemRefs(item, df::general_ref_type::CONTAINS_ITEM, items); } bool Items::readItemRefs(const df::item * item, df::general_ref_type type, std::vector &values) @@ -471,7 +471,7 @@ bool Items::removeItemOwner(df::item * item, Units *creatures) for (uint32_t i = 0; i < item->itemrefs.size(); i++) { df::general_ref *ref = item->itemrefs[i]; - if (ref->getType() != df::general_ref_type::unit_itemowner) + if (ref->getType() != df::general_ref_type::UNIT_ITEMOWNER) continue; df_unit *unit = (df_unit *)ref->getUnit(); diff --git a/plugins/autodump.cpp b/plugins/autodump.cpp index 8c7f9a16b..d36854bbf 100644 --- a/plugins/autodump.cpp +++ b/plugins/autodump.cpp @@ -330,7 +330,7 @@ DFhackCExport command_result df_autodump_destroy_item(Core * c, vector for (unsigned i = 0; i < item->itemrefs.size(); i++) { df::general_ref *ref = item->itemrefs[i]; - if (ref->getType() == df::general_ref_type::unit_holder) + if (ref->getType() == df::general_ref_type::UNIT_HOLDER) { c->con.printerr("Choosing not to destroy items in unit inventory.\n"); return CR_FAILURE; diff --git a/plugins/workflow.cpp b/plugins/workflow.cpp index 4a3564d65..7556ca944 100644 --- a/plugins/workflow.cpp +++ b/plugins/workflow.cpp @@ -977,7 +977,7 @@ static void dryBucket(df::item *item) for (unsigned i = 0; i < item->itemrefs.size(); i++) { df::general_ref *ref = item->itemrefs[i]; - if (ref->getType() == df::general_ref_type::contains_item) + if (ref->getType() == df::general_ref_type::CONTAINS_ITEM) { df::item *obj = ref->getItem(); @@ -999,20 +999,20 @@ static bool itemBusy(df::item *item) for (unsigned i = 0; i < item->itemrefs.size(); i++) { df::general_ref *ref = item->itemrefs[i]; - if (ref->getType() == df::general_ref_type::contains_item) + if (ref->getType() == df::general_ref_type::CONTAINS_ITEM) { df::item *obj = ref->getItem(); if (obj && !obj->flags.bits.garbage_colect) return true; } - else if (ref->getType() == df::general_ref_type::contains_unit) + else if (ref->getType() == df::general_ref_type::CONTAINS_UNIT) return true; - else if (ref->getType() == df::general_ref_type::unit_holder) + else if (ref->getType() == df::general_ref_type::UNIT_HOLDER) { if (!item->flags.bits.in_job) return true; } - else if (ref->getType() == df::general_ref_type::contained_in_item) + else if (ref->getType() == df::general_ref_type::CONTAINED_IN_ITEM) { df::item *obj = ref->getItem(); if (!obj) From 7db467a740509cb60f0ca7a996dc45265694cfc7 Mon Sep 17 00:00:00 2001 From: Alexander Gavrilov Date: Thu, 19 Jan 2012 14:30:22 +0400 Subject: [PATCH 81/82] Update code to accomodate the new coord/coord2d/coord_path structs. Also replicate the methods of DFCoord. --- library/include/DataDefs.h | 4 ++ library/include/df/.gitignore | 2 +- library/include/df/custom/coord.methods.inc | 45 +++++++++++++++++++ library/include/df/custom/coord2d.methods.inc | 32 +++++++++++++ .../include/df/custom/coord_path.methods.inc | 8 ++++ library/modules/Items.cpp | 6 +-- library/modules/Vermin.cpp | 12 ++--- plugins/autodump.cpp | 10 ++--- plugins/cleaners.cpp | 1 + plugins/deramp.cpp | 2 +- 10 files changed, 106 insertions(+), 16 deletions(-) create mode 100644 library/include/df/custom/coord.methods.inc create mode 100644 library/include/df/custom/coord2d.methods.inc create mode 100644 library/include/df/custom/coord_path.methods.inc diff --git a/library/include/DataDefs.h b/library/include/DataDefs.h index e998dc386..41d05ac38 100644 --- a/library/include/DataDefs.h +++ b/library/include/DataDefs.h @@ -268,3 +268,7 @@ DF_KNOWN_GLOBALS #undef GLOBAL #undef SIMPLE_GLOBAL } + +// A couple of headers that have to be included at once +#include "df/coord2d.h" +#include "df/coord.h" diff --git a/library/include/df/.gitignore b/library/include/df/.gitignore index 7cd9ae481..feeeba782 100644 --- a/library/include/df/.gitignore +++ b/library/include/df/.gitignore @@ -1,3 +1,3 @@ *.h -*.inc +static*.inc *.xml diff --git a/library/include/df/custom/coord.methods.inc b/library/include/df/custom/coord.methods.inc new file mode 100644 index 000000000..64d170376 --- /dev/null +++ b/library/include/df/custom/coord.methods.inc @@ -0,0 +1,45 @@ +coord(const coord2d &c, uint16_t _z) : x(c.x), y(c.y), z(_z) {} +coord(uint16_t _x, uint16_t _y, uint16_t _z) : x(_x), y(_y), z(_z) {} + +operator coord2d() const { return coord2d(x,y); } + +bool isValid() const { return x != -30000; } +void clear() { x = y = z = -30000; } + +bool operator==(const coord &other) const +{ + return (x == other.x) && (y == other.y) && (z == other.z); +} +bool operator!=(const coord &other) const +{ + return (x != other.x) || (y != other.y) || (z != other.z); +} + +bool operator<(const coord &other) const +{ + if (x != other.x) return (x < other.x); + if (y != other.y) return (y < other.y); + return z < other.z; +} + +coord operator/(int number) const +{ + return coord(x/number, y/number, z); +} +coord operator*(int number) const +{ + return coord(x*number, y*number, z); +} +coord operator%(int number) const +{ + return coord(x%number, y%number, z); +} + +coord operator-(int number) const +{ + return coord(x,y,z-number); +} +coord operator+(int number) const +{ + return coord(x,y,z+number); +} diff --git a/library/include/df/custom/coord2d.methods.inc b/library/include/df/custom/coord2d.methods.inc new file mode 100644 index 000000000..b6b47bca1 --- /dev/null +++ b/library/include/df/custom/coord2d.methods.inc @@ -0,0 +1,32 @@ +coord2d(uint16_t _x, uint16_t _y) : x(_x), y(_y) {} + +bool isValid() const { return x != -30000; } +void clear() { x = y = -30000; } + +bool operator==(const coord2d &other) const +{ + return (x == other.x) && (y == other.y); +} +bool operator!=(const coord2d &other) const +{ + return (x != other.x) || (y != other.y); +} + +bool operator<(const coord2d &other) const +{ + if (x != other.x) return (x < other.x); + return y < other.y; +} + +coord2d operator/(int number) const +{ + return coord2d(x/number, y/number); +} +coord2d operator*(int number) const +{ + return coord2d(x*number, y*number); +} +coord2d operator%(int number) const +{ + return coord2d(x%number, y%number); +} diff --git a/library/include/df/custom/coord_path.methods.inc b/library/include/df/custom/coord_path.methods.inc new file mode 100644 index 000000000..d3c48de7f --- /dev/null +++ b/library/include/df/custom/coord_path.methods.inc @@ -0,0 +1,8 @@ +unsigned size() const { return x.size(); } + +coord operator[] (unsigned idx) const { + if (idx >= x.size() || idx >= y.size() || idx >= z.size()) + return coord(); + else + return coord(x[idx], y[idx], z[idx]); +} diff --git a/library/modules/Items.cpp b/library/modules/Items.cpp index 3b731c0d0..43c763a59 100644 --- a/library/modules/Items.cpp +++ b/library/modules/Items.cpp @@ -409,9 +409,9 @@ bool Items::copyItem(df::item * itembase, DFHack::dfh_item &item) return false; df::item * itreal = (df::item *) itembase; item.origin = itembase; - item.x = itreal->x; - item.y = itreal->y; - item.z = itreal->z; + item.x = itreal->pos.x; + item.y = itreal->pos.y; + item.z = itreal->pos.z; item.id = itreal->id; item.age = itreal->age; item.flags = itreal->flags; diff --git a/library/modules/Vermin.cpp b/library/modules/Vermin.cpp index 6b83d76bb..689a9edda 100644 --- a/library/modules/Vermin.cpp +++ b/library/modules/Vermin.cpp @@ -60,9 +60,9 @@ bool Vermin::Read (const uint32_t index, t_vermin & sp) sp.caste = verm->caste; sp.visible = verm->visible; sp.countdown = verm->countdown; - sp.x = verm->x; - sp.y = verm->y; - sp.z = verm->z; + sp.x = verm->pos.x; + sp.y = verm->pos.y; + sp.z = verm->pos.z; sp.is_colony = verm->flags.bits.is_colony; return true; } @@ -76,9 +76,9 @@ bool Vermin::Write (const uint32_t index, t_vermin & sp) verm->caste = sp.caste; verm->visible = sp.visible; verm->countdown = sp.countdown; - verm->x = sp.x; - verm->y = sp.y; - verm->z = sp.z; + verm->pos.x = sp.x; + verm->pos.y = sp.y; + verm->pos.z = sp.z; verm->flags.bits.is_colony = sp.is_colony; return true; } diff --git a/plugins/autodump.cpp b/plugins/autodump.cpp index d36854bbf..a7cebf7bb 100644 --- a/plugins/autodump.cpp +++ b/plugins/autodump.cpp @@ -143,7 +143,7 @@ static command_result autodump_main(Core * c, vector & parameters) for(std::size_t i=0; i< numItems; i++) { df::item * itm = world->items.all[i]; - DFCoord pos_item(itm->x, itm->y, itm->z); + DFCoord pos_item(itm->pos.x, itm->pos.y, itm->pos.z); // keep track how many items are at places. all items. coordmap::iterator it = counts.find(pos_item); @@ -185,7 +185,7 @@ static command_result autodump_main(Core * c, vector & parameters) { // yes... cerr << "Moving from block to block!" << endl; - df_block * bl_src = Maps->getBlock(itm->x /16, itm->y/16, itm->z); + df_block * bl_src = Maps->getBlock(itm->pos.x /16, itm->pos.y/16, itm->pos.z); df_block * bl_tgt = Maps->getBlock(cx /16, cy/16, cz); if(bl_src) { @@ -206,9 +206,9 @@ static command_result autodump_main(Core * c, vector & parameters) } // Move the item - itm->x = pos_cursor.x; - itm->y = pos_cursor.y; - itm->z = pos_cursor.z; + itm->pos.x = pos_cursor.x; + itm->pos.y = pos_cursor.y; + itm->pos.z = pos_cursor.z; } else // destroy { diff --git a/plugins/cleaners.cpp b/plugins/cleaners.cpp index 1ee4b3406..9351d15ea 100644 --- a/plugins/cleaners.cpp +++ b/plugins/cleaners.cpp @@ -10,6 +10,7 @@ #include "df/block_square_event_material_spatterst.h" #include "df/item_actual.h" #include "df/unit.h" +#include "df/unit_spatter.h" #include "df/matter_state.h" #include "df/cursor.h" #include "df/builtin_mats.h" diff --git a/plugins/deramp.cpp b/plugins/deramp.cpp index a86b61e8e..2549fb83c 100644 --- a/plugins/deramp.cpp +++ b/plugins/deramp.cpp @@ -51,7 +51,7 @@ DFhackCExport command_result df_deramp (Core * c, vector & parameters) for (int i = 0; i < blocks_total; i++) { df::map_block *block = world->map.map_blocks[i]; - df::map_block *above = getBlock(block->map_x, block->map_y, block->map_z + 1); + df::map_block *above = getBlock(block->map_pos.x, block->map_pos.y, block->map_pos.z + 1); for (int x = 0; x < 16; x++) { From e2d7359bdd51a345ddf900bad0487ce3de29d346 Mon Sep 17 00:00:00 2001 From: Alexander Gavrilov Date: Thu, 19 Jan 2012 17:26:21 +0400 Subject: [PATCH 82/82] Add the gps global to Memory.xml. --- Memory.xml | 5 +++++ library/include/DataDefs.h | 3 ++- library/xml | 2 +- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/Memory.xml b/Memory.xml index 811bef3e9..9ea0239fd 100644 --- a/Memory.xml +++ b/Memory.xml @@ -1100,6 +1100,7 @@
+
@@ -2359,6 +2360,8 @@
+ +
cmake @@ -3252,6 +3255,8 @@
+ +
diff --git a/library/include/DataDefs.h b/library/include/DataDefs.h index 41d05ac38..80f722e05 100644 --- a/library/include/DataDefs.h +++ b/library/include/DataDefs.h @@ -257,7 +257,8 @@ namespace df { GLOBAL(ui_sidebar_menus,ui_sidebar_menus) \ GLOBAL(ui_build_selector,ui_build_selector) \ GLOBAL(ui_look_list,ui_look_list) \ - GLOBAL(ui_unit_view_mode, ui_unit_view_mode) + GLOBAL(ui_unit_view_mode, ui_unit_view_mode) \ + GLOBAL(gps, graphic) \ #define SIMPLE_GLOBAL(name,tname) \ diff --git a/library/xml b/library/xml index 30ce6e3d5..d5abec61f 160000 --- a/library/xml +++ b/library/xml @@ -1 +1 @@ -Subproject commit 30ce6e3d537ccc51e232c129680d53d5d58180fc +Subproject commit d5abec61f72f113e023219fed19c4022363de953