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;
}