diff --git a/LUA_API.rst b/LUA_API.rst index 3b2847a58..d9488d60f 100644 --- a/LUA_API.rst +++ b/LUA_API.rst @@ -738,6 +738,14 @@ Items module Returns true *x,y,z* of the item; may be not equal to item.pos if in inventory. +* ``dfhack.items.getGeneralRef(item, type)`` + + Searches for a general_ref with the given type. + +* ``dfhack.items.getSpecificRef(item, type)`` + + Searches for a specific_ref with the given type. + * ``dfhack.items.getOwner(item)`` Returns the owner unit or *nil*. diff --git a/Lua API.html b/Lua API.html index c7c2041db..40706d14f 100644 --- a/Lua API.html +++ b/Lua API.html @@ -972,6 +972,12 @@ or raws. The ignore_noble boolean disables the
  • dfhack.items.getPosition(item)

    Returns true x,y,z of the item; may be not equal to item.pos if in inventory.

  • +
  • dfhack.items.getGeneralRef(item, type)

    +

    Searches for a general_ref with the given type.

    +
  • +
  • dfhack.items.getSpecificRef(item, type)

    +

    Searches for a specific_ref with the given type.

    +
  • dfhack.items.getOwner(item)

    Returns the owner unit or nil.

  • diff --git a/library/LuaApi.cpp b/library/LuaApi.cpp index 05a71d610..828e54cbc 100644 --- a/library/LuaApi.cpp +++ b/library/LuaApi.cpp @@ -682,6 +682,8 @@ static bool items_moveToContainer(df::item *item, df::item *container) } static const LuaWrapper::FunctionReg dfhack_items_module[] = { + WRAPM(Items, getGeneralRef), + WRAPM(Items, getSpecificRef), WRAPM(Items, getOwner), WRAPM(Items, setOwner), WRAPM(Items, getContainer), diff --git a/library/LuaTypes.cpp b/library/LuaTypes.cpp index 02a89f9e2..c58c25d11 100644 --- a/library/LuaTypes.cpp +++ b/library/LuaTypes.cpp @@ -1103,26 +1103,39 @@ static void IndexFields(lua_State *state, int base, struct_identity *pstruct, bo name = pstruct->getName() + ("." + name); lua_pop(state, 1); + bool add_to_enum = true; + // Handle the field switch (fields[i].mode) { case struct_field_info::OBJ_METHOD: AddMethodWrapper(state, base+1, base+2, name.c_str(), (function_identity_base*)fields[i].type); - break; + continue; case struct_field_info::CLASS_METHOD: + continue; + + case struct_field_info::POINTER: + // Skip class-typed pointers within unions + if ((fields[i].count & 2) != 0 && fields[i].type && + fields[i].type->type() == IDTYPE_CLASS) + add_to_enum = false; break; default: - // Do not add invalid globals to the enumeration order - if (!globals || *(void**)fields[i].offset) - AssociateId(state, base+3, ++cnt, name.c_str()); - - lua_pushlightuserdata(state, (void*)&fields[i]); - lua_setfield(state, base+2, name.c_str()); break; } + + // Do not add invalid globals to the enumeration order + if (globals && !*(void**)fields[i].offset) + add_to_enum = false; + + if (add_to_enum) + AssociateId(state, base+3, ++cnt, name.c_str()); + + lua_pushlightuserdata(state, (void*)&fields[i]); + lua_setfield(state, base+2, name.c_str()); } } diff --git a/library/MiscUtils.cpp b/library/MiscUtils.cpp index 8658788bb..c0674686b 100644 --- a/library/MiscUtils.cpp +++ b/library/MiscUtils.cpp @@ -26,6 +26,7 @@ distribution. #include "Export.h" #include "MiscUtils.h" #include "Error.h" +#include "Types.h" #ifndef LINUX_BUILD #include @@ -124,6 +125,62 @@ std::string toLower(const std::string &str) return rv; } +df::general_ref *DFHack::findRef(std::vector &vec, df::general_ref_type type) +{ + for (int i = vec.size()-1; i >= 0; i--) + { + df::general_ref *ref = vec[i]; + if (ref->getType() == type) + return ref; + } + + return NULL; +} + +bool DFHack::removeRef(std::vector &vec, df::general_ref_type type, int id) +{ + for (int i = vec.size()-1; i >= 0; i--) + { + df::general_ref *ref = vec[i]; + if (ref->getType() != type || ref->getID() != id) + continue; + + vector_erase_at(vec, i); + delete ref; + return true; + } + + return false; +} + +df::specific_ref *DFHack::findRef(std::vector &vec, df::specific_ref_type type) +{ + for (int i = vec.size()-1; i >= 0; i--) + { + df::specific_ref *ref = vec[i]; + if (ref->type == type) + return ref; + } + + return NULL; +} + +bool DFHack::removeRef(std::vector &vec, df::specific_ref_type type, void *ptr) +{ + for (int i = vec.size()-1; i >= 0; i--) + { + df::specific_ref *ref = vec[i]; + if (ref->type != type || ref->object != ptr) + continue; + + vector_erase_at(vec, i); + delete ref; + return true; + } + + return false; +} + #ifdef LINUX_BUILD // Linux uint64_t GetTimeMs64() { diff --git a/library/include/Types.h b/library/include/Types.h index a8b4516cf..018e7ccfd 100644 --- a/library/include/Types.h +++ b/library/include/Types.h @@ -28,6 +28,10 @@ distribution. #include "Pragma.h" #include "Export.h" +#include "DataDefs.h" +#include "df/general_ref.h" +#include "df/specific_ref.h" + namespace DFHack { struct t_matglossPair @@ -69,4 +73,10 @@ namespace DFHack std::string name; uint32_t xpNxtLvl; }; + + DFHACK_EXPORT df::general_ref *findRef(std::vector &vec, df::general_ref_type type); + DFHACK_EXPORT bool removeRef(std::vector &vec, df::general_ref_type type, int id); + + DFHACK_EXPORT df::specific_ref *findRef(std::vector &vec, df::specific_ref_type type); + DFHACK_EXPORT bool removeRef(std::vector &vec, df::specific_ref_type type, void *ptr); }// namespace DFHack \ No newline at end of file diff --git a/library/include/modules/Items.h b/library/include/modules/Items.h index e7720fa91..8353d24c3 100644 --- a/library/include/modules/Items.h +++ b/library/include/modules/Items.h @@ -36,6 +36,7 @@ distribution. #include "df/item.h" #include "df/item_type.h" #include "df/general_ref.h" +#include "df/specific_ref.h" namespace df { @@ -126,6 +127,10 @@ 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); +/// Retrieve refs +DFHACK_EXPORT df::general_ref *getGeneralRef(df::item *item, df::general_ref_type type); +DFHACK_EXPORT df::specific_ref *getSpecificRef(df::item *item, df::specific_ref_type type); + /// Retrieve the owner of the item. DFHACK_EXPORT df::unit *getOwner(df::item *item); /// Set the owner of the item. Pass NULL as unit to remove the owner. diff --git a/library/modules/Items.cpp b/library/modules/Items.cpp index 96fcc19ce..f1d495bf1 100644 --- a/library/modules/Items.cpp +++ b/library/modules/Items.cpp @@ -421,18 +421,25 @@ bool Items::copyItem(df::item * itembase, DFHack::dfh_item &item) return true; } -df::unit *Items::getOwner(df::item * item) +df::general_ref *Items::getGeneralRef(df::item *item, df::general_ref_type type) { CHECK_NULL_POINTER(item); - for (size_t i = 0; i < item->itemrefs.size(); i++) - { - df::general_ref *ref = item->itemrefs[i]; - if (strict_virtual_cast(ref)) - return ref->getUnit(); - } + return findRef(item->itemrefs, type); +} + +df::specific_ref *Items::getSpecificRef(df::item *item, df::specific_ref_type type) +{ + CHECK_NULL_POINTER(item); + + return findRef(item->specific_refs, type); +} + +df::unit *Items::getOwner(df::item * item) +{ + auto ref = getGeneralRef(item, general_ref_type::UNIT_ITEMOWNER); - return NULL; + return ref ? ref->getUnit() : NULL; } bool Items::setOwner(df::item *item, df::unit *unit) @@ -478,16 +485,9 @@ bool Items::setOwner(df::item *item, df::unit *unit) df::item *Items::getContainer(df::item * item) { - CHECK_NULL_POINTER(item); + auto ref = getGeneralRef(item, general_ref_type::CONTAINED_IN_ITEM); - for (size_t i = 0; i < item->itemrefs.size(); i++) - { - df::general_ref *ref = item->itemrefs[i]; - if (ref->getType() == general_ref_type::CONTAINED_IN_ITEM) - return ref->getItem(); - } - - return NULL; + return ref ? ref->getItem() : NULL; } void Items::getContainedItems(df::item *item, std::vector *items) @@ -546,19 +546,6 @@ df::coord Items::getPosition(df::item *item) return item->pos; } -static void removeRef(std::vector &vec, df::general_ref_type type, int id) -{ - for (int i = vec.size()-1; i >= 0; i--) - { - df::general_ref *ref = vec[i]; - if (ref->getType() != type || ref->getID() != id) - continue; - - vector_erase_at(vec, i); - delete ref; - } -} - static bool detachItem(MapExtras::MapCache &mc, df::item *item) { if (item->flags.bits.on_ground) diff --git a/library/modules/Job.cpp b/library/modules/Job.cpp index 8e8e025d4..149707c6e 100644 --- a/library/modules/Job.cpp +++ b/library/modules/Job.cpp @@ -46,6 +46,7 @@ using namespace std; #include "df/job.h" #include "df/job_item.h" #include "df/job_list_link.h" +#include "df/specific_ref.h" #include "df/general_ref.h" #include "df/general_ref_unit_workerst.h" #include "df/general_ref_building_holderst.h" @@ -67,7 +68,7 @@ df::job *DFHack::Job::cloneJobStruct(df::job *job) pnew->list_link = NULL; pnew->completion_timer = -1; pnew->items.clear(); - pnew->misc_links.clear(); + pnew->specific_refs.clear(); // Clone refs for (int i = pnew->references.size()-1; i >= 0; i--) @@ -93,7 +94,7 @@ void DFHack::Job::deleteJobStruct(df::job *job) return; // Only allow free-floating job structs - assert(!job->list_link && job->items.empty() && job->misc_links.empty()); + assert(!job->list_link && job->items.empty() && job->specific_refs.empty()); for (int i = job->references.size()-1; i >= 0; i--) delete job->references[i]; @@ -331,10 +332,10 @@ bool DFHack::Job::attachJobItem(df::job *job, df::item *item, item->flags.bits.in_job = true; } - auto item_link = new df::item::T_jobs(); - item_link->type = 2; + auto item_link = new df::specific_ref(); + item_link->type = specific_ref_type::JOB; item_link->job = job; - item->jobs.push_back(item_link); + item->specific_refs.push_back(item_link); auto job_link = new df::job_item_ref(); job_link->item = item; diff --git a/library/xml b/library/xml index 6ce2b7120..5707a6aa0 160000 --- a/library/xml +++ b/library/xml @@ -1 +1 @@ -Subproject commit 6ce2b7120e5a246093116b48cb2ac64c35a8270d +Subproject commit 5707a6aa0c035348c8769058ed77b320f9b1436c diff --git a/plugins/autolabor.cpp b/plugins/autolabor.cpp index cfd9419db..797bd7465 100644 --- a/plugins/autolabor.cpp +++ b/plugins/autolabor.cpp @@ -832,7 +832,7 @@ DFhackCExport command_result plugin_onupdate ( color_ostream &out ) { if (is_on_break) dwarf_info[dwarf].state = OTHER; - else if (dwarfs[dwarf]->meetings.size() > 0) + else if (dwarfs[dwarf]->specific_refs.size() > 0) dwarf_info[dwarf].state = OTHER; else dwarf_info[dwarf].state = IDLE; diff --git a/plugins/jobutils.cpp b/plugins/jobutils.cpp index de7f81366..24ad4170e 100644 --- a/plugins/jobutils.cpp +++ b/plugins/jobutils.cpp @@ -272,7 +272,7 @@ static command_result job_duplicate(color_ostream &out, vector & parame if (!job) return CR_FAILURE; - if (!job->misc_links.empty() || + if (!job->specific_refs.empty() || (job->job_items.empty() && job->job_type != job_type::CollectSand && job->job_type != job_type::CollectClay)) diff --git a/plugins/workflow.cpp b/plugins/workflow.cpp index 0d6caa472..1092c86ae 100644 --- a/plugins/workflow.cpp +++ b/plugins/workflow.cpp @@ -364,7 +364,7 @@ static ProtectedJob *get_known(int id) static bool isSupportedJob(df::job *job) { - return job->misc_links.empty() && + return job->specific_refs.empty() && Job::getHolder(job) && (!job->job_items.empty() || job->job_type == job_type::CollectClay || @@ -1083,12 +1083,11 @@ static bool itemInRealJob(df::item *item) if (!item->flags.bits.in_job) return false; - if (item->jobs.size() != 1 || - item->jobs[0]->type != 2 || - item->jobs[0]->job == NULL) + auto ref = Items::getSpecificRef(item, specific_ref_type::JOB); + if (!ref || !ref->job) return true; - return ENUM_ATTR(job_type, type, item->jobs[0]->job->job_type) + return ENUM_ATTR(job_type, type, ref->job->job_type) != job_type_class::Hauling; }