Skip to content

Commit a3b78ac

Browse files
committed
Merge branch 'develop' of https://github.com/DFHack/dfhack into orders-search
2 parents 59c900e + 20240e1 commit a3b78ac

26 files changed

Lines changed: 635 additions & 61 deletions

.github/workflows/build-windows.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,9 +68,14 @@ jobs:
6868
name: Build win64
6969
runs-on: windows-2022
7070
steps:
71+
- name: Set up Python
72+
uses: actions/setup-python@v6
73+
with:
74+
python-version: '3.x'
7175
- name: Install build dependencies
7276
run: |
7377
choco install sccache
78+
pip install Jinja2
7479
- name: Install doc dependencies
7580
if: inputs.docs
7681
run: |

.pre-commit-config.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,11 @@ repos:
2020
args: ['--fix=lf']
2121
- id: trailing-whitespace
2222
- repo: https://github.com/python-jsonschema/check-jsonschema
23-
rev: 0.35.0
23+
rev: 0.36.1
2424
hooks:
2525
- id: check-github-workflows
2626
- repo: https://github.com/Lucas-C/pre-commit-hooks
27-
rev: v1.5.5
27+
rev: v1.5.6
2828
hooks:
2929
- id: forbid-tabs
3030
exclude_types:

CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ cmake_policy(SET CMP0048 NEW)
66
cmake_policy(SET CMP0074 NEW)
77

88
# set up versioning.
9-
set(DF_VERSION "53.08")
9+
set(DF_VERSION "53.10")
1010
set(DFHACK_RELEASE "r1")
1111
set(DFHACK_PRERELEASE FALSE)
1212

docs/changelog.txt

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,9 +58,59 @@ Template for new versions:
5858

5959
## New Features
6060
- `orders`: added search overlay to find and navigate to matching manager orders with arrow indicators
61+
- `sort`: Add death cause button to dead/missing tab in the creatures screen
6162

6263
## Fixes
6364

65+
## Misc Improvements
66+
- Core: DFHack now validates vtable pointers in objects read from memory and will throw an exception instead of crashing when an invalid vtable pointer is encountered. This makes it easier to identify which DF data structure contains corrupted data when this manifests in the form of a bad vtable pointer, and shifts blame for such crashes from DFHack to DF.
67+
68+
## Documentation
69+
70+
## API
71+
- Added ``Maps::addMaterialSpatter``: add a spatter of the specified material + state to the indicated tile, returning whatever amount wouldn't fit in the tile.
72+
- Added ``Maps::addItemSpatter``: add a spatter of the specified item + material + growth print to the indicated tile, returning whatever amount wouldn't fit in the tile.
73+
- Added ``Items::pickGrowthPrint``: given a plant material and a growth index, returns the print variant corresponding to the current in-game time.
74+
- Added ``Items::useStandardMaterial``: given an item type, returns true if the item is made of a specific material and false if it has a race and caste instead.
75+
76+
## Lua
77+
- Added ``Maps::addMaterialSpatter`` as ``dfhack.maps.addMaterialSpatter``.
78+
- Added ``Maps::addItemSpatter`` as ``dfhack.maps.addItemSpatter``.
79+
80+
## Removed
81+
82+
# 53.10-r1
83+
84+
## New Tools
85+
86+
## New Features
87+
88+
## Fixes
89+
- `autochop`: the report will no longer throw a C++ exception when burrows are defined.
90+
- `suspendmanager`: Fix the overlay appearing where it should not when following a unit
91+
92+
## Misc Improvements
93+
94+
## Documentation
95+
96+
## API
97+
- Added ``Burrows::getName``: obtains the name of a burrow, or the same placeholder name that DF would show if the burrow is unnamed.
98+
99+
## Lua
100+
- Added ``Burrows::getName`` as ``dfhack.burrows.getName``.
101+
102+
## Removed
103+
104+
# 53.09-r1
105+
106+
## New Tools
107+
108+
## New Features
109+
- `tweak`: ``drawbridge-tiles``: Make it so raised bridges render with different tiles in ASCII mode to make it more obvious that they ARE raised (and to indicate their direction)
110+
111+
## Fixes
112+
- ``Filesystem::as_string`` now always uses UTF-8 encoding rather than using the system locale encoding
113+
64114
## Misc Improvements
65115

66116
## Documentation

docs/dev/Lua API.rst

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2490,9 +2490,30 @@ Maps module
24902490
Removes an aquifer from the given tile position.
24912491
Returns *true* or *false* depending on success.
24922492

2493+
* ``dfhack.maps.addMaterialSpatter(pos, mat, matg, state, amount)``
2494+
2495+
Adds a material spatter to the specified map tile. If the tile is already
2496+
full of that spatter, returns the amount left over.
2497+
2498+
Specifying a state of -1 (None) will automatically choose either Solid,
2499+
Liquid, or Gas based on the material properties and the tile temperature.
2500+
2501+
* ``dfhack.maps.addItemSpatter(pos, i_type, i_subtype, subcat1, subcat2, print_variant, amount)``
2502+
2503+
Adds an item spatter to the specified map tile. If the tile is already
2504+
full of that spatter, returns the amount left over.
2505+
2506+
For plant growths, specifying a print_variant of -1 will automatically
2507+
choose an appropriate value. For other item types, this field is ignored.
2508+
24932509
Burrows module
24942510
--------------
24952511

2512+
* ``dfhack.burrows.getName(burrow)``
2513+
2514+
Returns the name of the burrow.
2515+
If the burrow has no set name, returns the same placeholder name that DF would show in the UI.
2516+
24962517
* ``dfhack.burrows.findByName(name[, ignore_final_plus])``
24972518

24982519
Returns the burrow pointer or *nil*. if ``ignore_final_plus`` is ``true``,

docs/plugins/tweak.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,9 @@ Commands
4545
Fixes crafted items not wearing out over time (:bug:`6003`). With this
4646
tweak, items made from cloth and leather will gain a level of wear every 20
4747
in-game years.
48+
``drawbridge-tiles``
49+
Makes raising bridges in ASCII mode render with different tiles when they
50+
are raised.
4851
``eggs-fertile``
4952
Displays an indicator on fertile eggs.
5053
``fast-heat``

library/DataDefs.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -370,7 +370,7 @@ const virtual_identity *virtual_identity::find(void *vtable)
370370

371371
// If using a reader/writer lock, re-grab as write here, and recheck
372372
Core &core = Core::getInstance();
373-
std::string name = core.p->doReadClassName(vtable);
373+
std::string name = core.p->readClassName(vtable);
374374

375375
auto name_it = (*name_lookup).find(name);
376376
if (name_it != (*name_lookup).end()) {

library/LuaApi.cpp

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2783,6 +2783,40 @@ static int maps_removeTileAquifer(lua_State* L)
27832783
return 1;
27842784
}
27852785

2786+
static int maps_addMaterialSpatter(lua_State *L)
2787+
{
2788+
int32_t rv;
2789+
df::coord pos;
2790+
2791+
Lua::CheckDFAssign(L, &pos, 1);
2792+
int16_t mat = lua_tointeger(L, 2);
2793+
int32_t matg = lua_tointeger(L, 3);
2794+
df::matter_state state = (df::matter_state)lua_tointeger(L, 4);
2795+
int32_t amount = lua_tointeger(L, 5);
2796+
rv = Maps::addMaterialSpatter(pos, mat, matg, state, amount);
2797+
2798+
lua_pushinteger(L, rv);
2799+
return 1;
2800+
}
2801+
2802+
static int maps_addItemSpatter(lua_State *L)
2803+
{
2804+
int32_t rv;
2805+
df::coord pos;
2806+
2807+
Lua::CheckDFAssign(L, &pos, 1);
2808+
df::item_type i_type = (df::item_type)lua_tointeger(L, 2);
2809+
int16_t i_subtype = lua_tointeger(L, 3);
2810+
int16_t i_subcat1 = lua_tointeger(L, 4);
2811+
int32_t i_subcat2 = lua_tointeger(L, 5);
2812+
int32_t print_variant = lua_tointeger(L, 6);
2813+
int32_t amount = lua_tointeger(L, 7);
2814+
rv = Maps::addItemSpatter(pos, i_type, i_subtype, i_subcat1, i_subcat2, print_variant, amount);
2815+
2816+
lua_pushinteger(L, rv);
2817+
return 1;
2818+
}
2819+
27862820
static const luaL_Reg dfhack_maps_funcs[] = {
27872821
{ "isValidTilePos", maps_isValidTilePos },
27882822
{ "isTileVisible", maps_isTileVisible },
@@ -2798,6 +2832,8 @@ static const luaL_Reg dfhack_maps_funcs[] = {
27982832
{ "isTileHeavyAquifer", maps_isTileHeavyAquifer },
27992833
{ "setTileAquifer", maps_setTileAquifer },
28002834
{ "removeTileAquifer", maps_removeTileAquifer },
2835+
{ "addMaterialSpatter", maps_addMaterialSpatter },
2836+
{ "addItemSpatter", maps_addItemSpatter },
28012837
{ NULL, NULL }
28022838
};
28032839

library/Process.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,9 @@ Process::~Process()
236236

237237
string Process::doReadClassName (void * vptr)
238238
{
239+
if (!checkValidAddress(vptr))
240+
throw std::runtime_error(fmt::format("invalid vtable ptr {}", vptr));
241+
239242
char* rtti = Process::readPtr(((char*)vptr - sizeof(void*)));
240243
#ifndef WIN32
241244
char* typestring = Process::readPtr(rtti + sizeof(void*));
@@ -591,6 +594,20 @@ void Process::getMemRanges(vector<t_memrange>& ranges)
591594
}
592595
#endif
593596

597+
bool Process::checkValidAddress(void* ptr)
598+
{
599+
uintptr_t addr = reinterpret_cast<uintptr_t>(ptr);
600+
auto validate = [&] (t_memrange& r) {
601+
uintptr_t lo = reinterpret_cast<uintptr_t>(r.start);
602+
uintptr_t hi = reinterpret_cast<uintptr_t>(r.end);
603+
return addr >= lo && addr < hi;
604+
};
605+
std::vector<t_memrange> mr;
606+
getMemRanges(mr);
607+
bool valid = std::any_of(mr.begin(), mr.end(), validate);
608+
return valid;
609+
}
610+
594611
uintptr_t Process::getBase()
595612
{
596613
#if WIN32

library/include/MemAccess.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -221,7 +221,7 @@ namespace DFHack
221221

222222
std::string readClassName(void* vptr)
223223
{
224-
std::map<void*, std::string>::iterator it = classNameCache.find(vptr);
224+
auto it = classNameCache.find(vptr);
225225
if (it != classNameCache.end())
226226
return it->second;
227227
return classNameCache[vptr] = doReadClassName(vptr);
@@ -247,6 +247,9 @@ namespace DFHack
247247
/// get virtual memory ranges of the process (what is mapped where)
248248
static void getMemRanges(std::vector<t_memrange>& ranges);
249249

250+
/// check if an address has a mapping
251+
bool checkValidAddress(void* ptr);
252+
250253
/// get the symbol table extension of this process
251254
std::shared_ptr<DFHack::VersionInfo> getDescriptor()
252255
{

0 commit comments

Comments
 (0)