|  |  |  | @ -1,5 +1,6 @@ | 
		
	
		
			
				|  |  |  |  | #include "Core.h" | 
		
	
		
			
				|  |  |  |  | #include "Console.h" | 
		
	
		
			
				|  |  |  |  | #include "Debug.h" | 
		
	
		
			
				|  |  |  |  | #include "VTableInterpose.h" | 
		
	
		
			
				|  |  |  |  | #include "modules/Buildings.h" | 
		
	
		
			
				|  |  |  |  | #include "modules/Constructions.h" | 
		
	
	
		
			
				
					|  |  |  | @ -43,6 +44,10 @@ | 
		
	
		
			
				|  |  |  |  | #include <unordered_set> | 
		
	
		
			
				|  |  |  |  | #include <array> | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | namespace DFHack { | 
		
	
		
			
				|  |  |  |  |     DBG_DECLARE(eventmanager, log, DebugCategory::LINFO); | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | using namespace std; | 
		
	
		
			
				|  |  |  |  | using namespace DFHack; | 
		
	
		
			
				|  |  |  |  | using namespace EventManager; | 
		
	
	
		
			
				
					|  |  |  | @ -268,6 +273,7 @@ void DFHack::EventManager::onStateChange(color_ostream& out, state_change_event | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |         multimap<Plugin*,EventHandler> copy(handlers[EventType::UNLOAD].begin(), handlers[EventType::UNLOAD].end()); | 
		
	
		
			
				|  |  |  |  |         for (auto &key_value : copy) { | 
		
	
		
			
				|  |  |  |  |             DEBUG(log,out).print("calling handler for map unloaded state change event\n"); | 
		
	
		
			
				|  |  |  |  |             key_value.second.eventHandler(out, nullptr); | 
		
	
		
			
				|  |  |  |  |         } | 
		
	
		
			
				|  |  |  |  |     } else if ( event == DFHack::SC_MAP_LOADED ) { | 
		
	
	
		
			
				
					|  |  |  | @ -358,6 +364,7 @@ void DFHack::EventManager::manageEvents(color_ostream& out) { | 
		
	
		
			
				|  |  |  |  |     CoreSuspender suspender; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |     int32_t tick = df::global::world->frame_counter; | 
		
	
		
			
				|  |  |  |  |     TRACE(log,out).print("processing events at tick %d\n", tick); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |     for ( size_t a = 0; a < EventType::EVENT_MAX; a++ ) { | 
		
	
		
			
				|  |  |  |  |         if ( handlers[a].empty() ) | 
		
	
	
		
			
				
					|  |  |  | @ -389,6 +396,7 @@ static void manageTickEvent(color_ostream& out) { | 
		
	
		
			
				|  |  |  |  |             break; | 
		
	
		
			
				|  |  |  |  |         EventHandler &handle = (*tickQueue.begin()).second; | 
		
	
		
			
				|  |  |  |  |         tickQueue.erase(tickQueue.begin()); | 
		
	
		
			
				|  |  |  |  |         DEBUG(log,out).print("calling handler for tick event\n"); | 
		
	
		
			
				|  |  |  |  |         handle.eventHandler(out, (void*)intptr_t(tick)); | 
		
	
		
			
				|  |  |  |  |         toRemove.insert(handle); | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
	
		
			
				
					|  |  |  | @ -429,6 +437,7 @@ static void manageJobInitiatedEvent(color_ostream& out) { | 
		
	
		
			
				|  |  |  |  |             continue; | 
		
	
		
			
				|  |  |  |  |         for (auto &key_value : copy) { | 
		
	
		
			
				|  |  |  |  |             EventHandler &handle = key_value.second; | 
		
	
		
			
				|  |  |  |  |             DEBUG(log,out).print("calling handler for job initiated event\n"); | 
		
	
		
			
				|  |  |  |  |             handle.eventHandler(out, (void*)link->item); | 
		
	
		
			
				|  |  |  |  |         } | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
	
		
			
				
					|  |  |  | @ -451,6 +460,7 @@ static void manageJobStartedEvent(color_ostream& out) { | 
		
	
		
			
				|  |  |  |  |             for (auto &key_value : copy) { | 
		
	
		
			
				|  |  |  |  |                 auto &handler = key_value.second; | 
		
	
		
			
				|  |  |  |  |                 // the jobs must have a worker to start
 | 
		
	
		
			
				|  |  |  |  |                 DEBUG(log,out).print("calling handler for job started event\n"); | 
		
	
		
			
				|  |  |  |  |                 handler.eventHandler(out, job); | 
		
	
		
			
				|  |  |  |  |             } | 
		
	
		
			
				|  |  |  |  |         } | 
		
	
	
		
			
				
					|  |  |  | @ -561,6 +571,7 @@ static void manageJobCompletedEvent(color_ostream& out) { | 
		
	
		
			
				|  |  |  |  |             //still false positive if cancelled at EXACTLY the right time, but experiments show this doesn't happen
 | 
		
	
		
			
				|  |  |  |  |             for (auto &key_value : copy) { | 
		
	
		
			
				|  |  |  |  |                 EventHandler &handle = key_value.second; | 
		
	
		
			
				|  |  |  |  |                 DEBUG(log,out).print("calling handler for repeated job completed event\n"); | 
		
	
		
			
				|  |  |  |  |                 handle.eventHandler(out, (void*)&job0); | 
		
	
		
			
				|  |  |  |  |             } | 
		
	
		
			
				|  |  |  |  |             continue; | 
		
	
	
		
			
				
					|  |  |  | @ -573,6 +584,7 @@ static void manageJobCompletedEvent(color_ostream& out) { | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |         for (auto &key_value : copy) { | 
		
	
		
			
				|  |  |  |  |             EventHandler &handle = key_value.second; | 
		
	
		
			
				|  |  |  |  |             DEBUG(log,out).print("calling handler for job completed event\n"); | 
		
	
		
			
				|  |  |  |  |             handle.eventHandler(out, (void*)&job0); | 
		
	
		
			
				|  |  |  |  |         } | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
	
		
			
				
					|  |  |  | @ -607,6 +619,7 @@ static void manageNewUnitActiveEvent(color_ostream& out) { | 
		
	
		
			
				|  |  |  |  |             int32_t id = unit->id; | 
		
	
		
			
				|  |  |  |  |             if (!activeUnits.count(id)) { | 
		
	
		
			
				|  |  |  |  |                 activeUnits.emplace(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
 | 
		
	
		
			
				|  |  |  |  |             } | 
		
	
		
			
				|  |  |  |  |         } | 
		
	
	
		
			
				
					|  |  |  | @ -630,6 +643,7 @@ static void manageUnitDeathEvent(color_ostream& out) { | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |         for (auto &key_value : copy) { | 
		
	
		
			
				|  |  |  |  |             EventHandler &handle = key_value.second; | 
		
	
		
			
				|  |  |  |  |             DEBUG(log,out).print("calling handler for unit death event\n"); | 
		
	
		
			
				|  |  |  |  |             handle.eventHandler(out, (void*)intptr_t(unit->id)); | 
		
	
		
			
				|  |  |  |  |         } | 
		
	
		
			
				|  |  |  |  |         livingUnits.erase(unit->id); | 
		
	
	
		
			
				
					|  |  |  | @ -667,6 +681,7 @@ static void manageItemCreationEvent(color_ostream& out) { | 
		
	
		
			
				|  |  |  |  |             continue; | 
		
	
		
			
				|  |  |  |  |         for (auto &key_value : copy) { | 
		
	
		
			
				|  |  |  |  |             EventHandler &handle = key_value.second; | 
		
	
		
			
				|  |  |  |  |             DEBUG(log,out).print("calling handler for item created event\n"); | 
		
	
		
			
				|  |  |  |  |             handle.eventHandler(out, (void*)intptr_t(item->id)); | 
		
	
		
			
				|  |  |  |  |         } | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
	
		
			
				
					|  |  |  | @ -694,6 +709,7 @@ static void manageBuildingEvent(color_ostream& out) { | 
		
	
		
			
				|  |  |  |  |         buildings.insert(a); | 
		
	
		
			
				|  |  |  |  |         for (auto &key_value : copy) { | 
		
	
		
			
				|  |  |  |  |             EventHandler &handle = key_value.second; | 
		
	
		
			
				|  |  |  |  |             DEBUG(log,out).print("calling handler for created building event\n"); | 
		
	
		
			
				|  |  |  |  |             handle.eventHandler(out, (void*)intptr_t(a)); | 
		
	
		
			
				|  |  |  |  |         } | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
	
		
			
				
					|  |  |  | @ -710,6 +726,7 @@ static void manageBuildingEvent(color_ostream& out) { | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |         for (auto &key_value : copy) { | 
		
	
		
			
				|  |  |  |  |             EventHandler &handle = key_value.second; | 
		
	
		
			
				|  |  |  |  |             DEBUG(log,out).print("calling handler for destroyed building event\n"); | 
		
	
		
			
				|  |  |  |  |             handle.eventHandler(out, (void*)intptr_t(id)); | 
		
	
		
			
				|  |  |  |  |         } | 
		
	
		
			
				|  |  |  |  |         a = buildings.erase(a); | 
		
	
	
		
			
				
					|  |  |  | @ -733,6 +750,7 @@ static void manageConstructionEvent(color_ostream& out) { | 
		
	
		
			
				|  |  |  |  |         // send construction to handlers, because it was removed
 | 
		
	
		
			
				|  |  |  |  |         for (const auto &key_value: copy) { | 
		
	
		
			
				|  |  |  |  |             EventHandler handle = key_value.second; | 
		
	
		
			
				|  |  |  |  |             DEBUG(log,out).print("calling handler for destroyed construction event\n"); | 
		
	
		
			
				|  |  |  |  |             handle.eventHandler(out, (void*) &construction); | 
		
	
		
			
				|  |  |  |  |         } | 
		
	
		
			
				|  |  |  |  |         // erase from existent constructions
 | 
		
	
	
		
			
				
					|  |  |  | @ -747,6 +765,7 @@ static void manageConstructionEvent(color_ostream& out) { | 
		
	
		
			
				|  |  |  |  |             // 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"); | 
		
	
		
			
				|  |  |  |  |                 handle.eventHandler(out, (void*) &construction); | 
		
	
		
			
				|  |  |  |  |             } | 
		
	
		
			
				|  |  |  |  |         } | 
		
	
	
		
			
				
					|  |  |  | @ -775,6 +794,7 @@ static void manageSyndromeEvent(color_ostream& out) { | 
		
	
		
			
				|  |  |  |  |             SyndromeData data(unit->id, b); | 
		
	
		
			
				|  |  |  |  |             for (auto &key_value : copy) { | 
		
	
		
			
				|  |  |  |  |                 EventHandler &handle = key_value.second; | 
		
	
		
			
				|  |  |  |  |                 DEBUG(log,out).print("calling handler for syndrome event\n"); | 
		
	
		
			
				|  |  |  |  |                 handle.eventHandler(out, (void*)&data); | 
		
	
		
			
				|  |  |  |  |             } | 
		
	
		
			
				|  |  |  |  |         } | 
		
	
	
		
			
				
					|  |  |  | @ -793,6 +813,7 @@ static void manageInvasionEvent(color_ostream& out) { | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |     for (auto &key_value : copy) { | 
		
	
		
			
				|  |  |  |  |         EventHandler &handle = key_value.second; | 
		
	
		
			
				|  |  |  |  |         DEBUG(log,out).print("calling handler for invasion event\n"); | 
		
	
		
			
				|  |  |  |  |         handle.eventHandler(out, (void*)intptr_t(nextInvasion-1)); | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  | } | 
		
	
	
		
			
				
					|  |  |  | @ -834,6 +855,7 @@ static void manageEquipmentEvent(color_ostream& out) { | 
		
	
		
			
				|  |  |  |  |                 InventoryChangeData data(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; | 
		
	
	
		
			
				
					|  |  |  | @ -849,6 +871,7 @@ static void manageEquipmentEvent(color_ostream& out) { | 
		
	
		
			
				|  |  |  |  |             InventoryChangeData data(unit->id, &item_old, &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); | 
		
	
		
			
				|  |  |  |  |             } | 
		
	
		
			
				|  |  |  |  |         } | 
		
	
	
		
			
				
					|  |  |  | @ -860,6 +883,7 @@ static void manageEquipmentEvent(color_ostream& out) { | 
		
	
		
			
				|  |  |  |  |             InventoryChangeData data(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); | 
		
	
		
			
				|  |  |  |  |             } | 
		
	
		
			
				|  |  |  |  |         } | 
		
	
	
		
			
				
					|  |  |  | @ -913,6 +937,7 @@ static void manageReportEvent(color_ostream& out) { | 
		
	
		
			
				|  |  |  |  |         df::report* report = reports[idx]; | 
		
	
		
			
				|  |  |  |  |         for (auto &key_value : copy) { | 
		
	
		
			
				|  |  |  |  |             EventHandler &handle = key_value.second; | 
		
	
		
			
				|  |  |  |  |             DEBUG(log,out).print("calling handler for report event\n"); | 
		
	
		
			
				|  |  |  |  |             handle.eventHandler(out, (void*)intptr_t(report->id)); | 
		
	
		
			
				|  |  |  |  |         } | 
		
	
		
			
				|  |  |  |  |         lastReport = report->id; | 
		
	
	
		
			
				
					|  |  |  | @ -990,6 +1015,7 @@ static void manageUnitAttackEvent(color_ostream& out) { | 
		
	
		
			
				|  |  |  |  |             alreadyDone[data.attacker][data.defender] = 1; | 
		
	
		
			
				|  |  |  |  |             for (auto &key_value : copy) { | 
		
	
		
			
				|  |  |  |  |                 EventHandler &handle = key_value.second; | 
		
	
		
			
				|  |  |  |  |                 DEBUG(log,out).print("calling handler for unit1 attack unit attack event\n"); | 
		
	
		
			
				|  |  |  |  |                 handle.eventHandler(out, (void*)&data); | 
		
	
		
			
				|  |  |  |  |             } | 
		
	
		
			
				|  |  |  |  |         } | 
		
	
	
		
			
				
					|  |  |  | @ -1002,6 +1028,7 @@ static void manageUnitAttackEvent(color_ostream& out) { | 
		
	
		
			
				|  |  |  |  |             alreadyDone[data.attacker][data.defender] = 1; | 
		
	
		
			
				|  |  |  |  |             for (auto &key_value : copy) { | 
		
	
		
			
				|  |  |  |  |                 EventHandler &handle = key_value.second; | 
		
	
		
			
				|  |  |  |  |                 DEBUG(log,out).print("calling handler for unit2 attack unit attack event\n"); | 
		
	
		
			
				|  |  |  |  |                 handle.eventHandler(out, (void*)&data); | 
		
	
		
			
				|  |  |  |  |             } | 
		
	
		
			
				|  |  |  |  |         } | 
		
	
	
		
			
				
					|  |  |  | @ -1013,6 +1040,7 @@ static void manageUnitAttackEvent(color_ostream& out) { | 
		
	
		
			
				|  |  |  |  |             alreadyDone[data.attacker][data.defender] = 1; | 
		
	
		
			
				|  |  |  |  |             for (auto &key_value : copy) { | 
		
	
		
			
				|  |  |  |  |                 EventHandler &handle = key_value.second; | 
		
	
		
			
				|  |  |  |  |                 DEBUG(log,out).print("calling handler for unit1 killed unit attack event\n"); | 
		
	
		
			
				|  |  |  |  |                 handle.eventHandler(out, (void*)&data); | 
		
	
		
			
				|  |  |  |  |             } | 
		
	
		
			
				|  |  |  |  |         } | 
		
	
	
		
			
				
					|  |  |  | @ -1024,6 +1052,7 @@ static void manageUnitAttackEvent(color_ostream& out) { | 
		
	
		
			
				|  |  |  |  |             alreadyDone[data.attacker][data.defender] = 1; | 
		
	
		
			
				|  |  |  |  |             for (auto &key_value : copy) { | 
		
	
		
			
				|  |  |  |  |                 EventHandler &handle = key_value.second; | 
		
	
		
			
				|  |  |  |  |                 DEBUG(log,out).print("calling handler for unit2 killed unit attack event\n"); | 
		
	
		
			
				|  |  |  |  |                 handle.eventHandler(out, (void*)&data); | 
		
	
		
			
				|  |  |  |  |             } | 
		
	
		
			
				|  |  |  |  |         } | 
		
	
	
		
			
				
					|  |  |  | @ -1282,6 +1311,7 @@ static void manageInteractionEvent(color_ostream& out) { | 
		
	
		
			
				|  |  |  |  |         //fire event
 | 
		
	
		
			
				|  |  |  |  |         for (auto &key_value : copy) { | 
		
	
		
			
				|  |  |  |  |             EventHandler &handle = key_value.second; | 
		
	
		
			
				|  |  |  |  |             DEBUG(log,out).print("calling handler for interaction event\n"); | 
		
	
		
			
				|  |  |  |  |             handle.eventHandler(out, (void*)&data); | 
		
	
		
			
				|  |  |  |  |         } | 
		
	
		
			
				|  |  |  |  |         //TODO: deduce attacker from latest defend event first
 | 
		
	
	
		
			
				
					|  |  |  | 
 |