|
|
@ -43,6 +43,7 @@
|
|
|
|
#include <unordered_map>
|
|
|
|
#include <unordered_map>
|
|
|
|
#include <unordered_set>
|
|
|
|
#include <unordered_set>
|
|
|
|
#include <array>
|
|
|
|
#include <array>
|
|
|
|
|
|
|
|
#include <utility>
|
|
|
|
|
|
|
|
|
|
|
|
namespace DFHack {
|
|
|
|
namespace DFHack {
|
|
|
|
DBG_DECLARE(eventmanager, log, DebugCategory::LINFO);
|
|
|
|
DBG_DECLARE(eventmanager, log, DebugCategory::LINFO);
|
|
|
@ -246,6 +247,15 @@ static int32_t reportToRelevantUnitsTime = -1;
|
|
|
|
//interaction
|
|
|
|
//interaction
|
|
|
|
static int32_t lastReportInteraction;
|
|
|
|
static int32_t lastReportInteraction;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
struct hash_pair {
|
|
|
|
|
|
|
|
template<typename A, typename B>
|
|
|
|
|
|
|
|
size_t operator()(const std::pair<A,B>& p) const {
|
|
|
|
|
|
|
|
auto h1 = std::hash<A>{}(p.first);
|
|
|
|
|
|
|
|
auto h2 = std::hash<B>{}(p.second);
|
|
|
|
|
|
|
|
return h1 ^ (h2 << 1);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
void DFHack::EventManager::onStateChange(color_ostream& out, state_change_event event) {
|
|
|
|
void DFHack::EventManager::onStateChange(color_ostream& out, state_change_event event) {
|
|
|
|
static bool doOnce = false;
|
|
|
|
static bool doOnce = false;
|
|
|
|
// const string eventNames[] = {"world loaded", "world unloaded", "map loaded", "map unloaded", "viewscreen changed", "core initialized", "begin unload", "paused", "unpaused"};
|
|
|
|
// const string eventNames[] = {"world loaded", "world unloaded", "map loaded", "map unloaded", "viewscreen changed", "core initialized", "begin unload", "paused", "unpaused"};
|
|
|
@ -276,9 +286,9 @@ void DFHack::EventManager::onStateChange(color_ostream& out, state_change_event
|
|
|
|
gameLoaded = false;
|
|
|
|
gameLoaded = false;
|
|
|
|
|
|
|
|
|
|
|
|
multimap<Plugin*,EventHandler> copy(handlers[EventType::UNLOAD].begin(), handlers[EventType::UNLOAD].end());
|
|
|
|
multimap<Plugin*,EventHandler> copy(handlers[EventType::UNLOAD].begin(), handlers[EventType::UNLOAD].end());
|
|
|
|
for (auto &key_value : copy) {
|
|
|
|
for (auto &[_,handle] : copy) {
|
|
|
|
DEBUG(log,out).print("calling handler for map unloaded state change event\n");
|
|
|
|
DEBUG(log,out).print("calling handler for map unloaded state change event\n");
|
|
|
|
key_value.second.eventHandler(out, nullptr);
|
|
|
|
handle.eventHandler(out, nullptr);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else if ( event == DFHack::SC_MAP_LOADED ) {
|
|
|
|
} else if ( event == DFHack::SC_MAP_LOADED ) {
|
|
|
|
/*
|
|
|
|
/*
|
|
|
@ -375,8 +385,7 @@ void DFHack::EventManager::manageEvents(color_ostream& out) {
|
|
|
|
continue;
|
|
|
|
continue;
|
|
|
|
int32_t eventFrequency = -100;
|
|
|
|
int32_t eventFrequency = -100;
|
|
|
|
if ( a != EventType::TICK )
|
|
|
|
if ( a != EventType::TICK )
|
|
|
|
for (auto &key_value : handlers[a]) {
|
|
|
|
for (auto &[_,handle] : handlers[a]) {
|
|
|
|
EventHandler &handle = key_value.second;
|
|
|
|
|
|
|
|
if (handle.freq < eventFrequency || eventFrequency == -100 )
|
|
|
|
if (handle.freq < eventFrequency || eventFrequency == -100 )
|
|
|
|
eventFrequency = handle.freq;
|
|
|
|
eventFrequency = handle.freq;
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -439,8 +448,7 @@ static void manageJobInitiatedEvent(color_ostream& out) {
|
|
|
|
continue;
|
|
|
|
continue;
|
|
|
|
if ( link->item->id <= lastJobId )
|
|
|
|
if ( link->item->id <= lastJobId )
|
|
|
|
continue;
|
|
|
|
continue;
|
|
|
|
for (auto &key_value : copy) {
|
|
|
|
for (auto &[_,handle] : copy) {
|
|
|
|
EventHandler &handle = key_value.second;
|
|
|
|
|
|
|
|
DEBUG(log,out).print("calling handler for job initiated event\n");
|
|
|
|
DEBUG(log,out).print("calling handler for job initiated event\n");
|
|
|
|
handle.eventHandler(out, (void*)link->item);
|
|
|
|
handle.eventHandler(out, (void*)link->item);
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -455,18 +463,21 @@ static void manageJobStartedEvent(color_ostream& out) {
|
|
|
|
|
|
|
|
|
|
|
|
static unordered_set<int32_t> startedJobs;
|
|
|
|
static unordered_set<int32_t> startedJobs;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
vector<df::job*> new_started_jobs;
|
|
|
|
// iterate event handler callbacks
|
|
|
|
// iterate event handler callbacks
|
|
|
|
multimap<Plugin*, EventHandler> copy(handlers[EventType::JOB_STARTED].begin(), handlers[EventType::JOB_STARTED].end());
|
|
|
|
multimap<Plugin*, EventHandler> copy(handlers[EventType::JOB_STARTED].begin(), handlers[EventType::JOB_STARTED].end());
|
|
|
|
for (df::job_list_link* link = df::global::world->jobs.list.next; link != nullptr; link = link->next) {
|
|
|
|
for (df::job_list_link* link = df::global::world->jobs.list.next; link != nullptr; link = link->next) {
|
|
|
|
df::job* job = link->item;
|
|
|
|
df::job* job = link->item;
|
|
|
|
if (job && Job::getWorker(job) && !startedJobs.count(job->id)) {
|
|
|
|
if (job && Job::getWorker(job) && !startedJobs.count(job->id)) {
|
|
|
|
startedJobs.emplace(job->id);
|
|
|
|
startedJobs.emplace(job->id);
|
|
|
|
for (auto &key_value : copy) {
|
|
|
|
new_started_jobs.emplace_back(job);
|
|
|
|
auto &handler = key_value.second;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
for (df::job* job : new_started_jobs) {
|
|
|
|
|
|
|
|
for (auto &[_,handle] : copy) {
|
|
|
|
// the jobs must have a worker to start
|
|
|
|
// the jobs must have a worker to start
|
|
|
|
DEBUG(log,out).print("calling handler for job started event\n");
|
|
|
|
DEBUG(log,out).print("calling handler for job started event\n");
|
|
|
|
handler.eventHandler(out, job);
|
|
|
|
handle.eventHandler(out, job);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -556,6 +567,8 @@ static void manageJobCompletedEvent(color_ostream& out) {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
vector<df::job*> new_jobs_completed;
|
|
|
|
|
|
|
|
vector<df::job*> new_jobs_completed_repeats;
|
|
|
|
for (auto &prevJob : prevJobs) {
|
|
|
|
for (auto &prevJob : prevJobs) {
|
|
|
|
//if it happened within a tick, must have been cancelled by the user or a plugin: not completed
|
|
|
|
//if it happened within a tick, must have been cancelled by the user or a plugin: not completed
|
|
|
|
if ( tick1 <= tick0 )
|
|
|
|
if ( tick1 <= tick0 )
|
|
|
@ -573,11 +586,7 @@ static void manageJobCompletedEvent(color_ostream& out) {
|
|
|
|
continue;
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
|
|
//still false positive if cancelled at EXACTLY the right time, but experiments show this doesn't happen
|
|
|
|
//still false positive if cancelled at EXACTLY the right time, but experiments show this doesn't happen
|
|
|
|
for (auto &key_value : copy) {
|
|
|
|
new_jobs_completed_repeats.emplace_back(&job0);
|
|
|
|
EventHandler &handle = key_value.second;
|
|
|
|
|
|
|
|
DEBUG(log,out).print("calling handler for repeated job completed event\n");
|
|
|
|
|
|
|
|
handle.eventHandler(out, (void*)&job0);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
continue;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -586,10 +595,19 @@ static void manageJobCompletedEvent(color_ostream& out) {
|
|
|
|
if ( job0.flags.bits.repeat || job0.completion_timer != 0 )
|
|
|
|
if ( job0.flags.bits.repeat || job0.completion_timer != 0 )
|
|
|
|
continue;
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
|
|
for (auto &key_value : copy) {
|
|
|
|
new_jobs_completed.emplace_back(&job0);
|
|
|
|
EventHandler &handle = key_value.second;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (df::job* job : new_jobs_completed_repeats) {
|
|
|
|
|
|
|
|
for (auto &[_,handle] : copy) {
|
|
|
|
|
|
|
|
DEBUG(log,out).print("calling handler for repeated job completed event\n");
|
|
|
|
|
|
|
|
handle.eventHandler(out, (void*) job);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
for (df::job* job : new_jobs_completed) {
|
|
|
|
|
|
|
|
for (auto &[_,handle] : copy) {
|
|
|
|
DEBUG(log,out).print("calling handler for job completed event\n");
|
|
|
|
DEBUG(log,out).print("calling handler for job completed event\n");
|
|
|
|
handle.eventHandler(out, (void*)&job0);
|
|
|
|
handle.eventHandler(out, (void*) job);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -617,16 +635,18 @@ static void manageNewUnitActiveEvent(color_ostream& out) {
|
|
|
|
|
|
|
|
|
|
|
|
multimap<Plugin*,EventHandler> copy(handlers[EventType::UNIT_NEW_ACTIVE].begin(), handlers[EventType::UNIT_NEW_ACTIVE].end());
|
|
|
|
multimap<Plugin*,EventHandler> copy(handlers[EventType::UNIT_NEW_ACTIVE].begin(), handlers[EventType::UNIT_NEW_ACTIVE].end());
|
|
|
|
// iterate event handler callbacks
|
|
|
|
// iterate event handler callbacks
|
|
|
|
for (auto &key_value : copy) {
|
|
|
|
vector<int32_t> new_active_unit_ids;
|
|
|
|
auto &handler = key_value.second;
|
|
|
|
|
|
|
|
for (df::unit* unit : df::global::world->units.active) {
|
|
|
|
for (df::unit* unit : df::global::world->units.active) {
|
|
|
|
int32_t id = unit->id;
|
|
|
|
if (!activeUnits.count(unit->id)) {
|
|
|
|
if (!activeUnits.count(id)) {
|
|
|
|
activeUnits.emplace(unit->id);
|
|
|
|
activeUnits.emplace(id);
|
|
|
|
new_active_unit_ids.emplace_back(unit->id);
|
|
|
|
DEBUG(log,out).print("calling handler for new unit event\n");
|
|
|
|
|
|
|
|
handler.eventHandler(out, (void*) intptr_t(id)); // intptr_t() avoids cast from smaller type warning
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (int32_t unit_id : new_active_unit_ids) {
|
|
|
|
|
|
|
|
for (auto &[_,handle] : copy) {
|
|
|
|
|
|
|
|
DEBUG(log,out).print("calling handler for new unit event\n");
|
|
|
|
|
|
|
|
handle.eventHandler(out, (void*) intptr_t(unit_id)); // intptr_t() avoids cast from smaller type warning
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -635,6 +655,7 @@ static void manageUnitDeathEvent(color_ostream& out) {
|
|
|
|
if (!df::global::world)
|
|
|
|
if (!df::global::world)
|
|
|
|
return;
|
|
|
|
return;
|
|
|
|
multimap<Plugin*,EventHandler> copy(handlers[EventType::UNIT_DEATH].begin(), handlers[EventType::UNIT_DEATH].end());
|
|
|
|
multimap<Plugin*,EventHandler> copy(handlers[EventType::UNIT_DEATH].begin(), handlers[EventType::UNIT_DEATH].end());
|
|
|
|
|
|
|
|
vector<int32_t> dead_unit_ids;
|
|
|
|
for (auto unit : df::global::world->units.all) {
|
|
|
|
for (auto unit : df::global::world->units.all) {
|
|
|
|
//if ( unit->counters.death_id == -1 ) {
|
|
|
|
//if ( unit->counters.death_id == -1 ) {
|
|
|
|
if ( Units::isActive(unit) ) {
|
|
|
|
if ( Units::isActive(unit) ) {
|
|
|
@ -644,13 +665,15 @@ static void manageUnitDeathEvent(color_ostream& out) {
|
|
|
|
//dead: if dead since last check, trigger events
|
|
|
|
//dead: if dead since last check, trigger events
|
|
|
|
if ( livingUnits.find(unit->id) == livingUnits.end() )
|
|
|
|
if ( livingUnits.find(unit->id) == livingUnits.end() )
|
|
|
|
continue;
|
|
|
|
continue;
|
|
|
|
|
|
|
|
livingUnits.erase(unit->id);
|
|
|
|
|
|
|
|
dead_unit_ids.emplace_back(unit->id);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
for (auto &key_value : copy) {
|
|
|
|
for (int32_t unit_id : dead_unit_ids) {
|
|
|
|
EventHandler &handle = key_value.second;
|
|
|
|
for (auto &[_,handle] : copy) {
|
|
|
|
DEBUG(log,out).print("calling handler for unit death event\n");
|
|
|
|
DEBUG(log,out).print("calling handler for unit death event\n");
|
|
|
|
handle.eventHandler(out, (void*)intptr_t(unit->id));
|
|
|
|
handle.eventHandler(out, (void*)intptr_t(unit_id));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
livingUnits.erase(unit->id);
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -666,6 +689,8 @@ static void manageItemCreationEvent(color_ostream& out) {
|
|
|
|
multimap<Plugin*,EventHandler> copy(handlers[EventType::ITEM_CREATED].begin(), handlers[EventType::ITEM_CREATED].end());
|
|
|
|
multimap<Plugin*,EventHandler> copy(handlers[EventType::ITEM_CREATED].begin(), handlers[EventType::ITEM_CREATED].end());
|
|
|
|
size_t index = df::item::binsearch_index(df::global::world->items.all, nextItem, false);
|
|
|
|
size_t index = df::item::binsearch_index(df::global::world->items.all, nextItem, false);
|
|
|
|
if ( index != 0 ) index--;
|
|
|
|
if ( index != 0 ) index--;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
std::vector<int32_t> created_items;
|
|
|
|
for ( size_t a = index; a < df::global::world->items.all.size(); a++ ) {
|
|
|
|
for ( size_t a = index; a < df::global::world->items.all.size(); a++ ) {
|
|
|
|
df::item* item = df::global::world->items.all[a];
|
|
|
|
df::item* item = df::global::world->items.all[a];
|
|
|
|
//already processed
|
|
|
|
//already processed
|
|
|
@ -683,12 +708,17 @@ static void manageItemCreationEvent(color_ostream& out) {
|
|
|
|
//spider webs don't count
|
|
|
|
//spider webs don't count
|
|
|
|
if ( item->flags.bits.spider_web )
|
|
|
|
if ( item->flags.bits.spider_web )
|
|
|
|
continue;
|
|
|
|
continue;
|
|
|
|
for (auto &key_value : copy) {
|
|
|
|
created_items.push_back(item->id);
|
|
|
|
EventHandler &handle = key_value.second;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// handle all created items
|
|
|
|
|
|
|
|
for (int32_t item_id : created_items) {
|
|
|
|
|
|
|
|
for (auto &[_,handle] : copy) {
|
|
|
|
DEBUG(log,out).print("calling handler for item created event\n");
|
|
|
|
DEBUG(log,out).print("calling handler for item created event\n");
|
|
|
|
handle.eventHandler(out, (void*)intptr_t(item->id));
|
|
|
|
handle.eventHandler(out, (void*)intptr_t(item_id));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
nextItem = *df::global::item_next_id;
|
|
|
|
nextItem = *df::global::item_next_id;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -703,6 +733,7 @@ static void manageBuildingEvent(color_ostream& out) {
|
|
|
|
**/
|
|
|
|
**/
|
|
|
|
multimap<Plugin*,EventHandler> copy(handlers[EventType::BUILDING].begin(), handlers[EventType::BUILDING].end());
|
|
|
|
multimap<Plugin*,EventHandler> copy(handlers[EventType::BUILDING].begin(), handlers[EventType::BUILDING].end());
|
|
|
|
//first alert people about new buildings
|
|
|
|
//first alert people about new buildings
|
|
|
|
|
|
|
|
vector<int32_t> new_buildings;
|
|
|
|
for ( int32_t a = nextBuilding; a < *df::global::building_next_id; a++ ) {
|
|
|
|
for ( int32_t a = nextBuilding; a < *df::global::building_next_id; a++ ) {
|
|
|
|
int32_t index = df::building::binsearch_index(df::global::world->buildings.all, a);
|
|
|
|
int32_t index = df::building::binsearch_index(df::global::world->buildings.all, a);
|
|
|
|
if ( index == -1 ) {
|
|
|
|
if ( index == -1 ) {
|
|
|
@ -711,29 +742,32 @@ static void manageBuildingEvent(color_ostream& out) {
|
|
|
|
continue;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
buildings.insert(a);
|
|
|
|
buildings.insert(a);
|
|
|
|
for (auto &key_value : copy) {
|
|
|
|
new_buildings.emplace_back(a);
|
|
|
|
EventHandler &handle = key_value.second;
|
|
|
|
|
|
|
|
DEBUG(log,out).print("calling handler for created building event\n");
|
|
|
|
|
|
|
|
handle.eventHandler(out, (void*)intptr_t(a));
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
nextBuilding = *df::global::building_next_id;
|
|
|
|
nextBuilding = *df::global::building_next_id;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
std::for_each(new_buildings.begin(), new_buildings.end(), [&](int32_t building){
|
|
|
|
|
|
|
|
for (auto &[_,handle] : copy) {
|
|
|
|
|
|
|
|
DEBUG(log,out).print("calling handler for created building event\n");
|
|
|
|
|
|
|
|
handle.eventHandler(out, (void*)intptr_t(building));
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
//now alert people about destroyed buildings
|
|
|
|
//now alert people about destroyed buildings
|
|
|
|
for ( auto a = buildings.begin(); a != buildings.end(); ) {
|
|
|
|
for ( auto it = buildings.begin(); it != buildings.end(); ) {
|
|
|
|
int32_t id = *a;
|
|
|
|
int32_t id = *it;
|
|
|
|
int32_t index = df::building::binsearch_index(df::global::world->buildings.all,id);
|
|
|
|
int32_t index = df::building::binsearch_index(df::global::world->buildings.all,id);
|
|
|
|
if ( index != -1 ) {
|
|
|
|
if ( index != -1 ) {
|
|
|
|
a++;
|
|
|
|
++it;
|
|
|
|
continue;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
for (auto &key_value : copy) {
|
|
|
|
for (auto &[_,handle] : copy) {
|
|
|
|
EventHandler &handle = key_value.second;
|
|
|
|
|
|
|
|
DEBUG(log,out).print("calling handler for destroyed building event\n");
|
|
|
|
DEBUG(log,out).print("calling handler for destroyed building event\n");
|
|
|
|
handle.eventHandler(out, (void*)intptr_t(id));
|
|
|
|
handle.eventHandler(out, (void*)intptr_t(id));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
a = buildings.erase(a);
|
|
|
|
it = buildings.erase(it);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -743,44 +777,52 @@ static void manageConstructionEvent(color_ostream& out) {
|
|
|
|
//unordered_set<df::construction*> constructionsNow(df::global::world->constructions.begin(), df::global::world->constructions.end());
|
|
|
|
//unordered_set<df::construction*> constructionsNow(df::global::world->constructions.begin(), df::global::world->constructions.end());
|
|
|
|
|
|
|
|
|
|
|
|
multimap<Plugin*, EventHandler> copy(handlers[EventType::CONSTRUCTION].begin(), handlers[EventType::CONSTRUCTION].end());
|
|
|
|
multimap<Plugin*, EventHandler> copy(handlers[EventType::CONSTRUCTION].begin(), handlers[EventType::CONSTRUCTION].end());
|
|
|
|
// find & send construction removals
|
|
|
|
|
|
|
|
for (auto iter = constructions.begin(); iter != constructions.end();) {
|
|
|
|
unordered_set<df::construction> next_construction_set; // will be swapped with constructions
|
|
|
|
auto &construction = *iter;
|
|
|
|
next_construction_set.reserve(constructions.bucket_count());
|
|
|
|
// if we can't find it, it was removed
|
|
|
|
vector<df::construction> new_constructions;
|
|
|
|
if (df::construction::find(construction.pos) != nullptr) {
|
|
|
|
|
|
|
|
++iter;
|
|
|
|
// find new constructions - swapping found constructions over from constructions to next_construction_set
|
|
|
|
continue;
|
|
|
|
for (auto c : df::global::world->constructions) {
|
|
|
|
|
|
|
|
auto &construction = *c;
|
|
|
|
|
|
|
|
auto it = constructions.find(construction);
|
|
|
|
|
|
|
|
if (it == constructions.end()) {
|
|
|
|
|
|
|
|
// handle new construction event later
|
|
|
|
|
|
|
|
new_constructions.emplace_back(construction);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// send construction to handlers, because it was removed
|
|
|
|
else {
|
|
|
|
for (const auto &key_value: copy) {
|
|
|
|
constructions.erase(it);
|
|
|
|
EventHandler handle = key_value.second;
|
|
|
|
}
|
|
|
|
|
|
|
|
next_construction_set.emplace(construction);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
constructions.swap(next_construction_set);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// now next_construction_set contains all the constructions that were removed (not found in df::global::world->constructions)
|
|
|
|
|
|
|
|
for (auto& construction : next_construction_set) {
|
|
|
|
|
|
|
|
// handle construction removed event
|
|
|
|
|
|
|
|
for (const auto &[_,handle]: copy) {
|
|
|
|
DEBUG(log,out).print("calling handler for destroyed construction event\n");
|
|
|
|
DEBUG(log,out).print("calling handler for destroyed construction event\n");
|
|
|
|
handle.eventHandler(out, (void*) &construction);
|
|
|
|
handle.eventHandler(out, (void*) &construction);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// erase from existent constructions
|
|
|
|
|
|
|
|
iter = constructions.erase(iter);
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// find & send construction additions
|
|
|
|
// now handle all the new constructions
|
|
|
|
for (auto c: df::global::world->constructions) {
|
|
|
|
for (auto& construction : new_constructions) {
|
|
|
|
auto &construction = *c;
|
|
|
|
for (const auto &[_,handle]: copy) {
|
|
|
|
// add construction to constructions, if it isn't already present
|
|
|
|
|
|
|
|
if (constructions.emplace(construction).second) {
|
|
|
|
|
|
|
|
// send construction to handlers, because it is new
|
|
|
|
|
|
|
|
for (const auto &key_value: copy) {
|
|
|
|
|
|
|
|
EventHandler handle = key_value.second;
|
|
|
|
|
|
|
|
DEBUG(log,out).print("calling handler for created construction event\n");
|
|
|
|
DEBUG(log,out).print("calling handler for created construction event\n");
|
|
|
|
handle.eventHandler(out, (void*) &construction);
|
|
|
|
handle.eventHandler(out, (void*) &construction);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void manageSyndromeEvent(color_ostream& out) {
|
|
|
|
static void manageSyndromeEvent(color_ostream& out) {
|
|
|
|
if (!df::global::world)
|
|
|
|
if (!df::global::world)
|
|
|
|
return;
|
|
|
|
return;
|
|
|
|
multimap<Plugin*,EventHandler> copy(handlers[EventType::SYNDROME].begin(), handlers[EventType::SYNDROME].end());
|
|
|
|
multimap<Plugin*,EventHandler> copy(handlers[EventType::SYNDROME].begin(), handlers[EventType::SYNDROME].end());
|
|
|
|
int32_t highestTime = -1;
|
|
|
|
int32_t highestTime = -1;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
std::vector<SyndromeData> new_syndrome_data;
|
|
|
|
for (auto unit : df::global::world->units.all) {
|
|
|
|
for (auto unit : df::global::world->units.all) {
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
/*
|
|
|
@ -795,14 +837,16 @@ static void manageSyndromeEvent(color_ostream& out) {
|
|
|
|
if ( startTime <= lastSyndromeTime )
|
|
|
|
if ( startTime <= lastSyndromeTime )
|
|
|
|
continue;
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
|
|
SyndromeData data(unit->id, b);
|
|
|
|
new_syndrome_data.emplace_back(unit->id, b);
|
|
|
|
for (auto &key_value : copy) {
|
|
|
|
}
|
|
|
|
EventHandler &handle = key_value.second;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (auto& data : new_syndrome_data) {
|
|
|
|
|
|
|
|
for (auto &[_,handle] : copy) {
|
|
|
|
DEBUG(log,out).print("calling handler for syndrome event\n");
|
|
|
|
DEBUG(log,out).print("calling handler for syndrome event\n");
|
|
|
|
handle.eventHandler(out, (void*)&data);
|
|
|
|
handle.eventHandler(out, (void*)&data);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
lastSyndromeTime = highestTime;
|
|
|
|
lastSyndromeTime = highestTime;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -815,8 +859,7 @@ static void manageInvasionEvent(color_ostream& out) {
|
|
|
|
return;
|
|
|
|
return;
|
|
|
|
nextInvasion = df::global::plotinfo->invasions.next_id;
|
|
|
|
nextInvasion = df::global::plotinfo->invasions.next_id;
|
|
|
|
|
|
|
|
|
|
|
|
for (auto &key_value : copy) {
|
|
|
|
for (auto &[_,handle] : copy) {
|
|
|
|
EventHandler &handle = key_value.second;
|
|
|
|
|
|
|
|
DEBUG(log,out).print("calling handler for invasion event\n");
|
|
|
|
DEBUG(log,out).print("calling handler for invasion event\n");
|
|
|
|
handle.eventHandler(out, (void*)intptr_t(nextInvasion-1));
|
|
|
|
handle.eventHandler(out, (void*)intptr_t(nextInvasion-1));
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -829,6 +872,11 @@ static void manageEquipmentEvent(color_ostream& out) {
|
|
|
|
|
|
|
|
|
|
|
|
unordered_map<int32_t, InventoryItem> itemIdToInventoryItem;
|
|
|
|
unordered_map<int32_t, InventoryItem> itemIdToInventoryItem;
|
|
|
|
unordered_set<int32_t> currentlyEquipped;
|
|
|
|
unordered_set<int32_t> currentlyEquipped;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
vector<InventoryChangeData> equipment_pickups;
|
|
|
|
|
|
|
|
vector<InventoryChangeData> equipment_drops;
|
|
|
|
|
|
|
|
vector<InventoryChangeData> equipment_changes;
|
|
|
|
|
|
|
|
|
|
|
|
for (auto unit : df::global::world->units.all) {
|
|
|
|
for (auto unit : df::global::world->units.all) {
|
|
|
|
itemIdToInventoryItem.clear();
|
|
|
|
itemIdToInventoryItem.clear();
|
|
|
|
currentlyEquipped.clear();
|
|
|
|
currentlyEquipped.clear();
|
|
|
@ -856,12 +904,7 @@ static void manageEquipmentEvent(color_ostream& out) {
|
|
|
|
auto c = itemIdToInventoryItem.find(dfitem_new->item->id);
|
|
|
|
auto c = itemIdToInventoryItem.find(dfitem_new->item->id);
|
|
|
|
if ( c == itemIdToInventoryItem.end() ) {
|
|
|
|
if ( c == itemIdToInventoryItem.end() ) {
|
|
|
|
//new item equipped (probably just picked up)
|
|
|
|
//new item equipped (probably just picked up)
|
|
|
|
InventoryChangeData data(unit->id, nullptr, &item_new);
|
|
|
|
equipment_pickups.emplace_back(unit->id, nullptr, &item_new);
|
|
|
|
for (auto &key_value : copy) {
|
|
|
|
|
|
|
|
EventHandler &handle = key_value.second;
|
|
|
|
|
|
|
|
DEBUG(log,out).print("calling handler for new item equipped inventory change event\n");
|
|
|
|
|
|
|
|
handle.eventHandler(out, (void*)&data);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
continue;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
InventoryItem item_old = (*c).second;
|
|
|
|
InventoryItem item_old = (*c).second;
|
|
|
@ -872,24 +915,14 @@ static void manageEquipmentEvent(color_ostream& out) {
|
|
|
|
continue;
|
|
|
|
continue;
|
|
|
|
//some sort of change in how it's equipped
|
|
|
|
//some sort of change in how it's equipped
|
|
|
|
|
|
|
|
|
|
|
|
InventoryChangeData data(unit->id, &item_old, &item_new);
|
|
|
|
equipment_changes.emplace_back(unit->id, nullptr, &item_new);
|
|
|
|
for (auto &key_value : copy) {
|
|
|
|
|
|
|
|
EventHandler &handle = key_value.second;
|
|
|
|
|
|
|
|
DEBUG(log,out).print("calling handler for inventory change event\n");
|
|
|
|
|
|
|
|
handle.eventHandler(out, (void*)&data);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
//check for dropped items
|
|
|
|
//check for dropped items
|
|
|
|
for (auto i : v) {
|
|
|
|
for (auto i : v) {
|
|
|
|
if ( currentlyEquipped.find(i.itemId) != currentlyEquipped.end() )
|
|
|
|
if ( currentlyEquipped.find(i.itemId) != currentlyEquipped.end() )
|
|
|
|
continue;
|
|
|
|
continue;
|
|
|
|
//TODO: delete ptr if invalid
|
|
|
|
//TODO: delete ptr if invalid
|
|
|
|
InventoryChangeData data(unit->id, &i, nullptr);
|
|
|
|
equipment_drops.emplace_back(unit->id, &i, nullptr);
|
|
|
|
for (auto &key_value : copy) {
|
|
|
|
|
|
|
|
EventHandler &handle = key_value.second;
|
|
|
|
|
|
|
|
DEBUG(log,out).print("calling handler for dropped item inventory change event\n");
|
|
|
|
|
|
|
|
handle.eventHandler(out, (void*)&data);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if ( !hadEquipment )
|
|
|
|
if ( !hadEquipment )
|
|
|
|
delete temp;
|
|
|
|
delete temp;
|
|
|
@ -902,6 +935,26 @@ static void manageEquipmentEvent(color_ostream& out) {
|
|
|
|
equipment.push_back(item);
|
|
|
|
equipment.push_back(item);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// now handle events
|
|
|
|
|
|
|
|
std::for_each(equipment_pickups.begin(), equipment_drops.end(), [&](InventoryChangeData& data) {
|
|
|
|
|
|
|
|
for (auto &[_, handle] : copy) {
|
|
|
|
|
|
|
|
DEBUG(log,out).print("calling handler for new item equipped inventory change event\n");
|
|
|
|
|
|
|
|
handle.eventHandler(out, (void*) &data);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
std::for_each(equipment_drops.begin(), equipment_drops.end(), [&](InventoryChangeData& data) {
|
|
|
|
|
|
|
|
for (auto &[_, handle] : copy) {
|
|
|
|
|
|
|
|
DEBUG(log,out).print("calling handler for dropped item inventory change event\n");
|
|
|
|
|
|
|
|
handle.eventHandler(out, (void*) &data);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
std::for_each(equipment_changes.begin(), equipment_changes.end(), [&](InventoryChangeData& data) {
|
|
|
|
|
|
|
|
for (auto &[_, handle] : copy) {
|
|
|
|
|
|
|
|
DEBUG(log,out).print("calling handler for inventory change event\n");
|
|
|
|
|
|
|
|
handle.eventHandler(out, (void*) &data);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void updateReportToRelevantUnits() {
|
|
|
|
static void updateReportToRelevantUnits() {
|
|
|
@ -939,8 +992,7 @@ static void manageReportEvent(color_ostream& out) {
|
|
|
|
|
|
|
|
|
|
|
|
for ( ; idx < reports.size(); idx++ ) {
|
|
|
|
for ( ; idx < reports.size(); idx++ ) {
|
|
|
|
df::report* report = reports[idx];
|
|
|
|
df::report* report = reports[idx];
|
|
|
|
for (auto &key_value : copy) {
|
|
|
|
for (auto &[_,handle] : copy) {
|
|
|
|
EventHandler &handle = key_value.second;
|
|
|
|
|
|
|
|
DEBUG(log,out).print("calling handler for report event\n");
|
|
|
|
DEBUG(log,out).print("calling handler for report event\n");
|
|
|
|
handle.eventHandler(out, (void*)intptr_t(report->id));
|
|
|
|
handle.eventHandler(out, (void*)intptr_t(report->id));
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -981,7 +1033,7 @@ static void manageUnitAttackEvent(color_ostream& out) {
|
|
|
|
if ( strikeReports.empty() )
|
|
|
|
if ( strikeReports.empty() )
|
|
|
|
return;
|
|
|
|
return;
|
|
|
|
updateReportToRelevantUnits();
|
|
|
|
updateReportToRelevantUnits();
|
|
|
|
map<int32_t, map<int32_t, int32_t> > alreadyDone;
|
|
|
|
unordered_set<std::pair<int32_t, int32_t>, hash_pair> already_done;
|
|
|
|
for (int reportId : strikeReports) {
|
|
|
|
for (int reportId : strikeReports) {
|
|
|
|
df::report* report = df::report::find(reportId);
|
|
|
|
df::report* report = df::report::find(reportId);
|
|
|
|
if ( !report )
|
|
|
|
if ( !report )
|
|
|
@ -1011,27 +1063,25 @@ static void manageUnitAttackEvent(color_ostream& out) {
|
|
|
|
|
|
|
|
|
|
|
|
UnitAttackData data{};
|
|
|
|
UnitAttackData data{};
|
|
|
|
data.report_id = report->id;
|
|
|
|
data.report_id = report->id;
|
|
|
|
if ( wound1 && !alreadyDone[unit1->id][unit2->id] ) {
|
|
|
|
if ( wound1 && already_done.find(std::make_pair(unit1->id,unit2->id)) == already_done.end() ) {
|
|
|
|
data.attacker = unit1->id;
|
|
|
|
data.attacker = unit1->id;
|
|
|
|
data.defender = unit2->id;
|
|
|
|
data.defender = unit2->id;
|
|
|
|
data.wound = wound1->id;
|
|
|
|
data.wound = wound1->id;
|
|
|
|
|
|
|
|
|
|
|
|
alreadyDone[data.attacker][data.defender] = 1;
|
|
|
|
already_done.emplace(unit1->id, unit2->id);
|
|
|
|
for (auto &key_value : copy) {
|
|
|
|
for (auto &[_,handle] : copy) {
|
|
|
|
EventHandler &handle = key_value.second;
|
|
|
|
|
|
|
|
DEBUG(log,out).print("calling handler for unit1 attack unit attack event\n");
|
|
|
|
DEBUG(log,out).print("calling handler for unit1 attack unit attack event\n");
|
|
|
|
handle.eventHandler(out, (void*)&data);
|
|
|
|
handle.eventHandler(out, (void*)&data);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if ( wound2 && !alreadyDone[unit1->id][unit2->id] ) {
|
|
|
|
if ( wound2 && already_done.find(std::make_pair(unit1->id,unit2->id)) == already_done.end() ) {
|
|
|
|
data.attacker = unit2->id;
|
|
|
|
data.attacker = unit2->id;
|
|
|
|
data.defender = unit1->id;
|
|
|
|
data.defender = unit1->id;
|
|
|
|
data.wound = wound2->id;
|
|
|
|
data.wound = wound2->id;
|
|
|
|
|
|
|
|
|
|
|
|
alreadyDone[data.attacker][data.defender] = 1;
|
|
|
|
already_done.emplace(unit1->id, unit2->id);
|
|
|
|
for (auto &key_value : copy) {
|
|
|
|
for (auto &[_,handle] : copy) {
|
|
|
|
EventHandler &handle = key_value.second;
|
|
|
|
|
|
|
|
DEBUG(log,out).print("calling handler for unit2 attack unit attack event\n");
|
|
|
|
DEBUG(log,out).print("calling handler for unit2 attack unit attack event\n");
|
|
|
|
handle.eventHandler(out, (void*)&data);
|
|
|
|
handle.eventHandler(out, (void*)&data);
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -1041,9 +1091,9 @@ static void manageUnitAttackEvent(color_ostream& out) {
|
|
|
|
data.attacker = unit2->id;
|
|
|
|
data.attacker = unit2->id;
|
|
|
|
data.defender = unit1->id;
|
|
|
|
data.defender = unit1->id;
|
|
|
|
data.wound = -1;
|
|
|
|
data.wound = -1;
|
|
|
|
alreadyDone[data.attacker][data.defender] = 1;
|
|
|
|
|
|
|
|
for (auto &key_value : copy) {
|
|
|
|
already_done.emplace(unit1->id, unit2->id);
|
|
|
|
EventHandler &handle = key_value.second;
|
|
|
|
for (auto &[_,handle] : copy) {
|
|
|
|
DEBUG(log,out).print("calling handler for unit1 killed unit attack event\n");
|
|
|
|
DEBUG(log,out).print("calling handler for unit1 killed unit attack event\n");
|
|
|
|
handle.eventHandler(out, (void*)&data);
|
|
|
|
handle.eventHandler(out, (void*)&data);
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -1053,9 +1103,9 @@ static void manageUnitAttackEvent(color_ostream& out) {
|
|
|
|
data.attacker = unit1->id;
|
|
|
|
data.attacker = unit1->id;
|
|
|
|
data.defender = unit2->id;
|
|
|
|
data.defender = unit2->id;
|
|
|
|
data.wound = -1;
|
|
|
|
data.wound = -1;
|
|
|
|
alreadyDone[data.attacker][data.defender] = 1;
|
|
|
|
|
|
|
|
for (auto &key_value : copy) {
|
|
|
|
already_done.emplace(unit1->id, unit2->id);
|
|
|
|
EventHandler &handle = key_value.second;
|
|
|
|
for (auto &[_,handle] : copy) {
|
|
|
|
DEBUG(log,out).print("calling handler for unit2 killed unit attack event\n");
|
|
|
|
DEBUG(log,out).print("calling handler for unit2 killed unit attack event\n");
|
|
|
|
handle.eventHandler(out, (void*)&data);
|
|
|
|
handle.eventHandler(out, (void*)&data);
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -1313,8 +1363,7 @@ static void manageInteractionEvent(color_ostream& out) {
|
|
|
|
lastAttacker = df::unit::find(data.attacker);
|
|
|
|
lastAttacker = df::unit::find(data.attacker);
|
|
|
|
//lastDefender = df::unit::find(data.defender);
|
|
|
|
//lastDefender = df::unit::find(data.defender);
|
|
|
|
//fire event
|
|
|
|
//fire event
|
|
|
|
for (auto &key_value : copy) {
|
|
|
|
for (auto &[_,handle] : copy) {
|
|
|
|
EventHandler &handle = key_value.second;
|
|
|
|
|
|
|
|
DEBUG(log,out).print("calling handler for interaction event\n");
|
|
|
|
DEBUG(log,out).print("calling handler for interaction event\n");
|
|
|
|
handle.eventHandler(out, (void*)&data);
|
|
|
|
handle.eventHandler(out, (void*)&data);
|
|
|
|
}
|
|
|
|
}
|
|
|
|