diff --git a/Memory.xml b/Memory.xml
index 5360d6481..9ea0239fd 100644
--- a/Memory.xml
+++ b/Memory.xml
@@ -1093,6 +1093,14 @@
+
+
+
+
+
+
+
+
@@ -2343,6 +2351,17 @@
+
+
+
+
+
+
+
+
+
+
+
cmake
@@ -3225,8 +3244,19 @@
-
+
+
+
+
+
+
+
+
+
+
+
+
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/CMakeLists.txt b/library/CMakeLists.txt
index f24e21fd3..e940264b7 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
@@ -49,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
@@ -89,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/Core.cpp b/library/Core.cpp
index 4a3dacd25..68af3e15a 100644
--- a/library/Core.cpp
+++ b/library/Core.cpp
@@ -1094,11 +1094,8 @@ MODULE_GETTER(Maps);
MODULE_GETTER(Gui);
MODULE_GETTER(World);
MODULE_GETTER(Materials);
-MODULE_GETTER(Items);
MODULE_GETTER(Translation);
MODULE_GETTER(Vegetation);
-MODULE_GETTER(Buildings);
MODULE_GETTER(Constructions);
-MODULE_GETTER(Vermin);
MODULE_GETTER(Notes);
MODULE_GETTER(Graphic);
diff --git a/library/DataDefs.cpp b/library/DataDefs.cpp
index bcdb388b5..cd8a8ed7c 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
@@ -154,12 +156,57 @@ 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;
}
}
+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;
+}
+
+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)
@@ -169,7 +216,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/MiscUtils.cpp b/library/MiscUtils.cpp
index 47deea04c..aa141313b 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,71 @@ distribution.
#include
#endif
+#include
+#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);
+ }
+}
+
+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/Process-linux.cpp b/library/Process-linux.cpp
index ee64c2740..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!!!!!
- int typeinfo = Process::readDWord((uint32_t)vptr - 0x4);
- int typestring = Process::readDWord(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();
@@ -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/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 0f0764d60..6bda6d669 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 nullableBytePtr;
+ typedef map ::iterator byteptr_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] = nullableBytePtr(NOT_SET, (char*) 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);
+ byteptr_Iter it = OGd->addresses.find(key);
if(it != OGd->addresses.end())
{
- uint32_t address = 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;
@@ -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);
+ byteptr_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)
+char * OffsetGroup::getAddress (const string & key)
{
- uint32_Iter iter = OGd->addresses.find(key);
+ byteptr_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);
+ byteptr_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(byteptr_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)
{
+ byteptr_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;
+ byteptr_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(byteptr_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 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/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;
diff --git a/library/include/Core.h b/library/include/Core.h
index a368e360d..988595062 100644
--- a/library/include/Core.h
+++ b/library/include/Core.h
@@ -58,12 +58,9 @@ namespace DFHack
class Gui;
class World;
class Materials;
- class Items;
class Translation;
class Vegetation;
- class Buildings;
class Constructions;
- class Vermin;
class Notes;
class VersionInfo;
class VersionInfoFactory;
@@ -113,18 +110,12 @@ 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
Vegetation * getVegetation();
- /// get the buildings module
- Buildings * getBuildings();
/// get the constructions module
Constructions * getConstructions();
- /// get the vermin module
- Vermin * getVermin();
/// get the notes module
Notes * getNotes();
/// get the graphic module
@@ -179,12 +170,9 @@ namespace DFHack
Gui * pGui;
World * pWorld;
Materials * pMaterials;
- Items * pItems;
Translation * pTranslation;
Vegetation * pVegetation;
- Buildings * pBuildings;
Constructions * pConstructions;
- Vermin * pVermin;
Notes * pNotes;
Graphic * pGraphic;
} s_mods;
diff --git a/library/include/DataDefs.h b/library/include/DataDefs.h
index 75b2ab2e5..80f722e05 100644
--- a/library/include/DataDefs.h
+++ b/library/include/DataDefs.h
@@ -111,15 +111,66 @@ 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
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;
+ }
+
+ 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);
+
+ 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) {
+ return bitfieldToString(&val.whole, sizeof(val.whole), val.get_items());
+ }
+}
+
+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
@@ -127,6 +178,8 @@ namespace df
using DFHack::virtual_ptr;
using DFHack::virtual_identity;
using DFHack::virtual_class;
+ using DFHack::bitfield_item_info;
+ using DFHack::enum_list_attr;
using DFHack::BitArray;
template
@@ -158,6 +211,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 {}
}
@@ -167,6 +232,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) \
@@ -176,11 +246,20 @@ 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_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) \
+ GLOBAL(gps, graphic) \
+
#define SIMPLE_GLOBAL(name,tname) \
namespace global { extern DFHACK_EXPORT tname *name; }
@@ -190,3 +269,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/MemAccess.h b/library/include/MemAccess.h
index 7da132c8a..531b83353 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
+ char * readPtr(const void * address)
+ {
+ return *(char **)address;
+ }
+ /// read a pointer
+ void readPtr(const void * address, char * & value)
+ {
+ value = *(char **)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/MiscUtils.h b/library/include/MiscUtils.h
index 833e74104..b3d70f6b9 100644
--- a/library/include/MiscUtils.h
+++ b/library/include/MiscUtils.h
@@ -66,39 +66,208 @@ 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 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)
+{
+ // Returns the index of the value >= the key
int min = -1, max = (int)vec.size();
- CT **p = vec.data();
- FT key = (FT)value;
+ const FT *p = vec.data();
for (;;)
{
int mid = (min + max)>>1;
if (mid == min)
- {
- return NULL;
- }
+ return exact ? -1 : max;
+ FT midv = p[mid];
+ if (midv == key)
+ return mid;
+ else if (midv < key)
+ min = mid;
+ else
+ max = mid;
+ }
+}
+
+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)
+{
+ // Returns the index of the value >= the key
+ int min = -1, max = (int)vec.size();
+ CT *const *p = vec.data();
+ for (;;)
+ {
+ int mid = (min + max)>>1;
+ if (mid == min)
+ 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
+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)
+{
+ 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)
+ vector_insert_at(vec, 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)
+ vector_insert_at(vec, 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];
+}
+
+/*
+ * List
+ */
+
+template
+Link *linked_list_append(Link *head, Link *tail)
+{
+ while (head->next)
+ head = head->next;
+ head->next = tail;
+ tail->prev = head;
+ 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);
+
+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.
* 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/library/include/ModuleFactory.h b/library/include/ModuleFactory.h
index 3677d3554..78ff9db19 100644
--- a/library/include/ModuleFactory.h
+++ b/library/include/ModuleFactory.h
@@ -35,13 +35,11 @@ namespace DFHack
Module* createGui();
Module* createWorld();
Module* createMaterials();
- Module* createItems();
Module* createTranslation();
Module* createVegetation();
Module* createBuildings();
Module* createConstructions();
Module* createMaps();
- Module* createVermin();
Module* createNotes();
Module* createGraphic();
}
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
{
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..02d526730 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);
+ 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 );
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 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/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/include/modules/Buildings.h b/library/include/modules/Buildings.h
index 330c151dc..7da2ad9dc 100644
--- a/library/include/modules/Buildings.h
+++ b/library/include/modules/Buildings.h
@@ -23,63 +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 origin;
- uint32_t vtable;
- uint32_t x1;
- uint32_t y1;
- uint32_t x2;
- uint32_t y2;
- 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)
- };
+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 a vector of names
- bool ReadCustomWorkshopTypes(std::map & btypes);
- // returns -1 on error, >= 0 for real value
- int32_t GetCustomWorkshopType(t_building & building);
+/**
+ * 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/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/Gui.h b/library/include/modules/Gui.h
index 3d3fe81c7..34a62308c 100644
--- a/library/include/modules/Gui.h
+++ b/library/include/modules/Gui.h
@@ -32,6 +32,13 @@ distribution.
#include "BitArray.h"
#include
+namespace df {
+ struct viewscreen;
+ struct job;
+ struct unit;
+ struct item;
+};
+
/**
* \defgroup grp_gui query DF's GUI state
* @ingroup grp_modules
@@ -39,6 +46,45 @@ distribution.
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);
+
+ // 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/include/modules/Items.h b/library/include/modules/Items.h
index 4deba6cdb..4cd29766a 100644
--- a/library/include/modules/Items.h
+++ b/library/include/modules/Items.h
@@ -32,6 +32,17 @@ distribution.
#include "Virtual.h"
#include "modules/Materials.h"
#include "MemAccess.h"
+
+#include "DataDefs.h"
+#include "df/item.h"
+#include "df/item_type.h"
+#include "df/general_ref.h"
+
+namespace df
+{
+ struct itemdef;
+}
+
/**
* \defgroup grp_items Items module and its types
* @ingroup grp_modules
@@ -39,401 +50,47 @@ distribution.
namespace DFHack
{
+ struct DFHACK_EXPORT ItemTypeInfo {
+ df::item_type type;
+ int16_t subtype;
-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
+ df::itemdef *custom;
- 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
+ public:
+ ItemTypeInfo(df::item_type type_ = df::enums::item_type::NONE, int16_t subtype_ = -1) {
+ decode(type_, subtype_);
+ }
+ template ItemTypeInfo(T *ptr) { decode(ptr); }
- 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
+ bool isValid() const {
+ return (type != df::enums::item_type::NONE) && (subtype == -1 || custom);
+ }
- 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
+ bool decode(df::item_type type_, int16_t subtype_ = -1);
+ bool decode(df::item *ptr);
- 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
+ template bool decode(T *ptr) {
+ return ptr ? decode(ptr->item_type, ptr->item_subtype) : decode(df::enums::item_type::NONE);
+ }
- 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
+ std::string getToken();
+ std::string toString();
- 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 ?
+ bool find(const std::string &token);
- 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
+ bool matches(const df::job_item &item, MaterialInfo *mat = NULL);
};
-};
-/**
- * Describes relationship of an item with other objects
- * \ingroup grp_items
- */
-struct t_itemref : public t_virtual
-{
- int32_t value;
-};
+ 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;
+ }
-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
-};
-
-/**
- * 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
-};
+class Context;
+class DFContextShared;
+class Units;
/**
* Type for holding an item read from DF
@@ -441,11 +98,11 @@ public:
*/
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;
@@ -454,154 +111,37 @@ 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
* \ingroup grp_items
*/
-class DFHACK_EXPORT Items : public Module
+namespace Simple
+{
+namespace Items
{
-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();
- ~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 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);
-private:
- class Private;
- Private* d;
-};
+/// 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/Job.h b/library/include/modules/Job.h
new file mode 100644
index 000000000..5534a9d4f
--- /dev/null
+++ b/library/include/modules/Job.h
@@ -0,0 +1,59 @@
+/*
+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;
+ struct building;
+}
+
+namespace DFHack
+{
+ // Duplicate the job structure. It is not linked into any DF lists.
+ DFHACK_EXPORT df::job *cloneJobStruct(df::job *job);
+
+ // Delete a cloned structure.
+ DFHACK_EXPORT void deleteJobStruct(df::job *job);
+
+ 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);
+
+ 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/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/Materials.h b/library/include/modules/Materials.h
index 8c3ce6846..7bc56d1fc 100644
--- a/library/include/modules/Materials.h
+++ b/library/include/modules/Materials.h
@@ -34,11 +34,113 @@ 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;
+ struct material_vec_ref;
+ struct job_item;
+
+ union job_material_category;
+ union dfhack_material_category;
+ union job_item_flags1;
+ union job_item_flags2;
+ union job_item_flags3;
+}
+
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); }
+ 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);
+
+ 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);
+
+ 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 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;
+ }
+ 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/include/modules/Units.h b/library/include/modules/Units.h
index d373b0a16..779fef8cf 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);
@@ -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/include/modules/Vermin.h b/library/include/modules/Vermin.h
index 01ef3d4ae..9ca2730d8 100644
--- a/library/include/modules/Vermin.h
+++ b/library/include/modules/Vermin.h
@@ -1,86 +1,38 @@
#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
{
- uint32_t origin;
+ 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?
};
-#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);
+} } } // end DFHack::Simple::Vermin
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/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/Buildings.cpp b/library/modules/Buildings.cpp
index fbef81315..2213abd35 100644
--- a/library/modules/Buildings.cpp
+++ b/library/modules/Buildings.cpp
@@ -32,180 +32,65 @@ using namespace std;
#include "VersionInfo.h"
#include "MemAccess.h"
-#include "Vector.h"
#include "Types.h"
#include "Error.h"
#include "modules/Buildings.h"
#include "ModuleFactory.h"
#include "Core.h"
using namespace DFHack;
+using namespace DFHack::Simple;
-//raw
-struct t_building_df40d
-{
- 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
-{
- uint32_t buildings_vector;
- uint32_t 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;
- Process * owner;
- bool Inited;
- bool hasCustomWorkshops;
- bool Started;
-};
-
-Module* DFHack::createBuildings()
-{
- return new Buildings();
-}
+#include "DataDefs.h"
+#include "df/world.h"
+#include "df/building_def.h"
+#include "df/building.h"
+#include "df/building_workshopst.h"
-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->owner = c.p;
- OffsetGroup * OG_build = mem->getGroup("Buildings");
- d->Inited = true;
- try
- {
- d->buildings_vector = 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 = 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;
- }
- }
-}
+using namespace df::enums;
+using df::global::world;
+using df::building_def;
-Buildings::~Buildings()
+uint32_t Buildings::getNumBuildings()
{
- if(d->Started)
- Finish();
- delete d;
-}
-
-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;
+ return world->buildings.all.size();
}
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);
+ Core & c = Core::getInstance();
+ df::building *bld_40d = world->buildings.all[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;
+ c.vinfo->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.index = bld_40d->mat_index;
+ building.material.type = bld_40d->mat_type;
building.type = type;
- return true;
-}
-
-bool Buildings::Finish()
-{
- if(d->p_bld)
- {
- delete d->p_bld;
- d->p_bld = NULL;
- }
- d->Started = false;
+ building.custom_type = bld_40d->getCustomType();
+ building.origin = (void *) &bld_40d;
return true;
}
bool Buildings::ReadCustomWorkshopTypes(map & btypes)
{
- if(!d->Inited)
- return false;
- if(!d->hasCustomWorkshops)
- return false;
-
- Process * p = d->owner;
- DfVector p_matgloss (d->custom_workshop_vector);
- uint32_t size = p_matgloss.size();
+ Core & c = Core::getInstance();
+
+ 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++)
{
- string out = p->readSTLString (p_matgloss[i] + d->custom_workshop_name);
- uint32_t type = p->readDWord (p_matgloss[i] + 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;
}
-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);
- }
- return ret;
-}
-
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..adef1acae 100644
--- a/library/modules/Gui.cpp
+++ b/library/modules/Gui.cpp
@@ -38,11 +38,29 @@ 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"
+#include "df/report.h"
+#include "df/popup_message.h"
+
+using namespace df::enums;
// Predefined common guard functions
@@ -61,6 +79,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))
@@ -73,6 +103,347 @@ 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;
+ }
+}
+
+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;
+ 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];
+}
+
+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;
+}
+
+//
+
+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()
@@ -91,16 +462,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 +535,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 +691,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;
-
- 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;
+ using namespace df::enums::item_type;
- // Building ID of lever/etc which triggers bridge/etc holding
- // this mechanism.
- ClassNameCheck isTriggeredByRefClass;
+ type = type_;
+ subtype = subtype_;
+ custom = NULL;
- // Building ID of bridge/etc which is triggered by lever/etc holding
- // this mechanism.
- ClassNameCheck isTriggerTargetRefClass;
+ df::world_raws::T_itemdefs &defs = df::global::world->raws.itemdefs;
- // 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;
+ switch (type_) {
+ case NONE:
+ return false;
- // 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;
+#define ITEM(type,vec,tclass) \
+ case type: \
+ custom = vector_get(defs.vec, subtype); \
+ break;
+ITEMDEF_VECTORS
+#undef ITEM
- // Item is flying or falling through the air. The value seems to
- // be the ID for a "projectile information" object.
- ClassNameCheck isProjectileRefClass;
+ default:
+ break;
+ }
- std::set knownItemRefTypes;
-};
+ return isValid();
+}
-Items::Items()
+bool ItemTypeInfo::decode(df::item *ptr)
{
- 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]);
- }
+ if (!ptr)
+ return decode(item_type::NONE);
+ else
+ return decode(ptr->getType(), ptr->getSubtype());
}
-bool Items::Start()
+std::string ItemTypeInfo::getToken()
{
- d->idLookupTable.clear();
- return true;
+ 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 Items::Finish()
+std::string ItemTypeInfo::toString()
{
- return true;
+ 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 Items::readItemVector(std::vector &items)
+bool ItemTypeInfo::find(const std::string &token)
{
- std::vector *p_items = (std::vector *) d->itemVectorAddress;
+ 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;
- d->idLookupTable.clear();
- items.resize(p_items->size());
+ if (items[0] == "NONE")
+ return true;
- for (unsigned i = 0; i < p_items->size(); i++)
+ FOR_ENUM_ITEMS(item_type, i)
{
- df_item * ptr = p_items->at(i);
- items[i] = ptr;
- d->idLookupTable[ptr->id] = ptr;
+ const char *key = ENUM_ATTR(item_type, key, i);
+ if (key && key == items[0])
+ {
+ type = i;
+ break;
+ }
}
- return true;
+ 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,tclass) \
+ 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);
}
-df_item * Items::findItemByID(int32_t id)
+bool ItemTypeInfo::matches(const df::job_item &item, MaterialInfo *mat)
{
- if (id < 0)
- return 0;
+ using namespace df::enums::item_type;
- if (d->idLookupTable.empty())
- {
- std::vector tmp;
- readItemVector(tmp);
+ if (!isValid())
+ 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;
+ 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);
}
- return d->idLookupTable[id];
+#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);
}
-Items::~Items()
+df::item * Items::findItemByID(int32_t id)
{
- Finish();
- delete d;
+ if (id < 0)
+ return 0;
+ return df::item::find(id);
}
-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;
- 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;
@@ -209,87 +425,72 @@ 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))
- 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 DFHack::df_item * item)
+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 DFHack::df_item * item, std::vector &items)
+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 = 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();
}
-bool Items::unknownRefs(const df_item * item, std::vector >& refs)
-{
- refs.clear();
-
- const std::vector &p_refs = item->itemrefs;
-
- for (uint32_t i=0; igetClassName();
-
- if (d->knownItemRefTypes.find(name) == d->knownItemRefTypes.end())
- {
- refs.push_back(pair(name, p_refs[i]->value));
- }
- }
-
- return (refs.size() > 0);
-}
-
-bool Items::removeItemOwner(df_item * item, Units *creatures)
+bool Items::removeItemOwner(df::item * item, Units *creatures)
{
- std::vector &p_refs = 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.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/Job.cpp b/library/modules/Job.cpp
new file mode 100644
index 000000000..be9560890
--- /dev/null
+++ b/library/modules/Job.cpp
@@ -0,0 +1,256 @@
+/*
+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