Skip to content

Commit e21f878

Browse files
authored
Merge pull request #5649 from ab9rf/clean-sort-filter-function
`sort`: make removal of our filter functions more reliable
2 parents 027a8a3 + 6ca9bab commit e21f878

File tree

2 files changed

+28
-40
lines changed

2 files changed

+28
-40
lines changed

docs/changelog.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ Template for new versions:
5959
## New Features
6060

6161
## Fixes
62+
- `sort`: Using the squad unit selector will no longer cause Dwarf Fortress to crash on exit
6263

6364
## Misc Improvements
6465

plugins/sort.cpp

Lines changed: 27 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#include <variant>
2+
#include <functional>
23

34
#include "Debug.h"
45
#include "LuaTools.h"
@@ -13,6 +14,7 @@
1314
#include "df/widget_unit_list.h"
1415
#include "df/world.h"
1516

17+
1618
using std::vector;
1719
using std::string;
1820

@@ -28,7 +30,8 @@ namespace DFHack {
2830
}
2931

3032
using item_or_unit = std::variant<df::unit*, df::item*>;
31-
using filter_vec_type = std::vector<std::function<bool(item_or_unit)>>;
33+
using filter_func = bool(item_or_unit);
34+
using filter_vec_type = std::vector<std::function<filter_func>>;
3235

3336
// recreated here since our autogenerated df::sort_entry lacks template params
3437
struct sort_entry {
@@ -42,19 +45,10 @@ static const string DFHACK_SORT_IDENT = "dfhack_sort";
4245
// filter logic
4346
//
4447

45-
static bool probing = false;
46-
static bool probe_result = false;
47-
4848
static bool do_filter(const char *module_name, const char *fn_name, const item_or_unit &elem) {
4949
if (std::holds_alternative<df::item*>(elem)) return true;
5050
auto unit = std::get<df::unit*>(elem);
5151

52-
if (probing) {
53-
TRACE(log).print("probe successful\n");
54-
probe_result = true;
55-
return false;
56-
}
57-
5852
bool ret = true;
5953
color_ostream &out = Core::getInstance().getConsole();
6054
Lua::CallLuaModuleFunction(out, module_name, fn_name, std::make_tuple(unit),
@@ -78,35 +72,28 @@ static bool do_work_animal_assignment_filter(item_or_unit elem) {
7872
return do_filter("plugins.sort.info", "do_work_animal_assignment_filter", elem);
7973
}
8074

81-
static int32_t our_filter_idx(df::widget_unit_list *unitlist) {
82-
if (world->units.active.empty())
83-
return -1;
84-
85-
df::unit *u = world->units.active[0]; // any unit will do; we just need a sentinel
86-
if (!u)
87-
return -1;
88-
89-
probing = true;
90-
probe_result = false;
75+
static int32_t our_filter_idx(filter_func* filter, df::widget_unit_list* unitlist)
76+
{
9177
int32_t idx = 0;
9278

93-
filter_vec_type *filter_vec = reinterpret_cast<filter_vec_type *>(&unitlist->filter_func);
79+
filter_vec_type* filter_vec = reinterpret_cast<filter_vec_type*>(&unitlist->filter_func);
9480

9581
TRACE(log).print("probing for our filter function\n");
96-
for (auto& fn : *filter_vec) {
97-
fn(item_or_unit(u));
98-
if (probe_result) {
82+
83+
for (auto& fn : *filter_vec)
84+
{
85+
auto t = fn.target<decltype(filter)>();
86+
if (t && *t == filter)
87+
{
9988
TRACE(log).print("found our filter function at idx %d\n", idx);
100-
break;
89+
return idx;
10190
}
10291
++idx;
10392
}
104-
105-
probing = false;
106-
return probe_result ? idx : -1;
93+
return -1;
10794
}
10895

109-
static df::widget_unit_list * get_squad_unit_list() {
96+
static df::widget_unit_list* get_squad_unit_list() {
11097
return virtual_cast<df::widget_unit_list>(
11198
Gui::getWidget(&game->main_interface.unit_selector, "Unit selector"));
11299
}
@@ -182,8 +169,8 @@ DFhackCExport command_result plugin_init(color_ostream &out, vector<PluginComman
182169
return CR_OK;
183170
}
184171

185-
static void remove_filter_function(color_ostream &out, const char *which, df::widget_unit_list *unitlist) {
186-
int32_t idx = our_filter_idx(unitlist);
172+
static void remove_filter_function(color_ostream &out, filter_func* filter, const char *which, df::widget_unit_list *unitlist) {
173+
int32_t idx = our_filter_idx(filter, unitlist);
187174
if (idx >= 0) {
188175
DEBUG(log,out).print("removing %s filter function\n", which);
189176
filter_vec_type *filter_vec = reinterpret_cast<filter_vec_type *>(&unitlist->filter_func);
@@ -202,22 +189,22 @@ static void remove_sort_function(color_ostream &out, const char *which, df::widg
202189

203190
DFhackCExport command_result plugin_shutdown(color_ostream &out) {
204191
if (auto unitlist = get_squad_unit_list()) {
205-
remove_filter_function(out, "squad", unitlist);
192+
remove_filter_function(out, do_squad_filter, "squad", unitlist);
206193
remove_sort_function(out, "squad", unitlist);
207194
}
208195

209196
if (auto unitlist = get_interrogate_unit_list("Open cases"))
210-
remove_filter_function(out, "open cases interrogate", unitlist);
197+
remove_filter_function(out, do_justice_filter, "open cases interrogate", unitlist);
211198
if (auto unitlist = get_interrogate_unit_list("Cold cases"))
212-
remove_filter_function(out, "cold cases interrogate", unitlist);
199+
remove_filter_function(out, do_justice_filter, "cold cases interrogate", unitlist);
213200

214201
if (auto unitlist = get_convict_unit_list("Open cases"))
215-
remove_filter_function(out, "open cases convict", unitlist);
202+
remove_filter_function(out, do_justice_filter, "open cases convict", unitlist);
216203
if (auto unitlist = get_convict_unit_list("Cold cases"))
217-
remove_filter_function(out, "cold cases convict", unitlist);
204+
remove_filter_function(out, do_justice_filter, "cold cases convict", unitlist);
218205

219206
if (auto unitlist = get_work_animal_assignment_unit_list())
220-
remove_filter_function(out, "work animal assignment", unitlist);
207+
remove_filter_function(out, do_work_animal_assignment_filter, "work animal assignment", unitlist);
221208

222209
return CR_OK;
223210
}
@@ -228,7 +215,7 @@ DFhackCExport command_result plugin_shutdown(color_ostream &out) {
228215

229216
static void sort_set_squad_filter_fn(color_ostream &out) {
230217
auto unitlist = get_squad_unit_list();
231-
if (unitlist && our_filter_idx(unitlist) == -1) {
218+
if (unitlist && our_filter_idx(do_squad_filter, unitlist) == -1) {
232219
DEBUG(log).print("adding squad filter function\n");
233220
auto filter_vec = reinterpret_cast<filter_vec_type *>(&unitlist->filter_func);
234221
filter_vec->emplace_back(do_squad_filter);
@@ -240,7 +227,7 @@ static void sort_set_squad_filter_fn(color_ostream &out) {
240227
}
241228

242229
static void sort_set_justice_filter_fn(color_ostream &out, df::widget_unit_list *unitlist) {
243-
if (unitlist && our_filter_idx(unitlist) == -1) {
230+
if (unitlist && our_filter_idx(do_justice_filter, unitlist) == -1) {
244231
DEBUG(log).print("adding justice filter function\n");
245232
auto filter_vec = reinterpret_cast<filter_vec_type *>(&unitlist->filter_func);
246233
filter_vec->emplace_back(do_justice_filter);
@@ -249,7 +236,7 @@ static void sort_set_justice_filter_fn(color_ostream &out, df::widget_unit_list
249236
}
250237

251238
static void sort_set_work_animal_assignment_filter_fn(color_ostream &out, df::widget_unit_list *unitlist) {
252-
if (unitlist && our_filter_idx(unitlist) == -1) {
239+
if (unitlist && our_filter_idx(do_work_animal_assignment_filter, unitlist) == -1) {
253240
DEBUG(log).print("adding work animal assignment filter function\n");
254241
auto filter_vec = reinterpret_cast<filter_vec_type *>(&unitlist->filter_func);
255242
filter_vec->emplace_back(do_work_animal_assignment_filter);

0 commit comments

Comments
 (0)