diff --git a/library/include/modules/EventManager.h b/library/include/modules/EventManager.h index bd7a91259..b83300c89 100644 --- a/library/include/modules/EventManager.h +++ b/library/include/modules/EventManager.h @@ -7,6 +7,9 @@ #include "ColorText.h" #include "PluginManager.h" #include "Console.h" +#include "DataDefs.h" + +#include namespace DFHack { namespace EventManager { @@ -63,4 +66,18 @@ namespace DFHack { } } +namespace std { + template <> + struct hash { + std::size_t operator()(const df::coord& c) const { + size_t r = 17; + const size_t m = 65537; + r = m*(r+c.x); + r = m*(r+c.y); + r = m*(r+c.z); + return r; + } + }; +} + #endif diff --git a/library/modules/EventManager.cpp b/library/modules/EventManager.cpp index 556cccc65..4ad3d89c0 100644 --- a/library/modules/EventManager.cpp +++ b/library/modules/EventManager.cpp @@ -151,7 +151,7 @@ static int32_t nextBuilding; static unordered_set buildings; //construction -static unordered_set constructions; +static unordered_map constructions; static bool gameLoaded; //invasion @@ -510,28 +510,35 @@ static void manageConstructionEvent(color_ostream& out) { unordered_set constructionsNow(df::global::world->constructions.begin(), df::global::world->constructions.end()); multimap copy(handlers[EventType::CONSTRUCTION].begin(), handlers[EventType::CONSTRUCTION].end()); + unordered_set toDelete; for ( auto a = constructions.begin(); a != constructions.end(); a++ ) { - df::construction* construction = *a; - if ( constructionsNow.find(construction) != constructionsNow.end() ) + df::construction& construction = (*a).second; + if ( df::construction::find(construction.pos) != NULL ) continue; + //construction removed + toDelete.insert((*a).first); for ( auto b = copy.begin(); b != copy.end(); b++ ) { EventHandler handle = (*b).second; - handle.eventHandler(out, (void*)construction); + handle.eventHandler(out, (void*)&construction); } } - + + for ( auto a = toDelete.begin(); a != toDelete.end(); a++ ) { + constructions.erase(*a); + } + for ( auto a = constructionsNow.begin(); a != constructionsNow.end(); a++ ) { df::construction* construction = *a; - if ( constructions.find(construction) != constructions.end() ) + bool b = constructions.find(construction->pos) != constructions.end(); + constructions[construction->pos] = *construction; + if ( b ) continue; + //construction created for ( auto b = copy.begin(); b != copy.end(); b++ ) { EventHandler handle = (*b).second; handle.eventHandler(out, (void*)construction); } } - - constructions.clear(); - constructions.insert(constructionsNow.begin(), constructionsNow.end()); } static void manageSyndromeEvent(color_ostream& out) { diff --git a/plugins/devel/eventExample.cpp b/plugins/devel/eventExample.cpp index 49cdac4f9..f6fa649b8 100644 --- a/plugins/devel/eventExample.cpp +++ b/plugins/devel/eventExample.cpp @@ -6,6 +6,8 @@ #include "modules/EventManager.h" #include "DataDefs.h" +#include "df/construction.h" +#include "df/coord.h" #include "df/item.h" #include "df/job.h" #include "df/world.h" @@ -105,6 +107,14 @@ void building(color_ostream& out, void* ptr) { void construction(color_ostream& out, void* ptr) { out.print("Construction created/destroyed: 0x%X\n", ptr); + df::construction* constr = (df::construction*)ptr; + df::coord pos = constr->pos; + out.print(" (%d,%d,%d)\n", pos.x, pos.y, pos.z); + if ( df::construction::find(pos) == NULL ) + out.print(" construction destroyed\n"); + else + out.print(" construction created\n"); + } void syndrome(color_ostream& out, void* ptr) {