diff --git a/library/include/modules/EventManager.h b/library/include/modules/EventManager.h index 1c610564e..a06439fcd 100644 --- a/library/include/modules/EventManager.h +++ b/library/include/modules/EventManager.h @@ -37,9 +37,9 @@ namespace DFHack { } }; - DFHACK_EXPORT void registerListener(EventType::EventType e, EventHandler handler, Plugin* plugin); + DFHACK_EXPORT void registerListener(EventType::EventType e, EventHandler handler, int32_t freq, Plugin* plugin); DFHACK_EXPORT void registerTick(EventHandler handler, int32_t when, Plugin* plugin, bool absolute=false); - DFHACK_EXPORT void unregister(EventType::EventType e, EventHandler handler, Plugin* plugin); + DFHACK_EXPORT void unregister(EventType::EventType e, EventHandler handler, int32_t freq, Plugin* plugin); DFHACK_EXPORT void unregisterAll(Plugin* plugin); void manageEvents(color_ostream& out); void onStateChange(color_ostream& out, state_change_event event); diff --git a/library/modules/EventManager.cpp b/library/modules/EventManager.cpp index 24bd6aeec..2725d80a3 100644 --- a/library/modules/EventManager.cpp +++ b/library/modules/EventManager.cpp @@ -34,11 +34,16 @@ multimap tickQueue; //TODO: consider unordered_map of pairs, or unordered_map of unordered_set, or whatever multimap handlers[EventType::EVENT_MAX]; +multimap pluginFrequencies[EventType::EVENT_MAX]; +map eventFrequency[EventType::EVENT_MAX]; +uint32_t eventLastTick[EventType::EVENT_MAX]; const uint32_t ticksPerYear = 403200; -void DFHack::EventManager::registerListener(EventType::EventType e, EventHandler handler, Plugin* plugin) { +void DFHack::EventManager::registerListener(EventType::EventType e, EventHandler handler, int32_t freq, Plugin* plugin) { handlers[e].insert(pair(plugin, handler)); + eventFrequency[e][freq]++; + pluginFrequencies[e].insert(pair(plugin, freq)); } void DFHack::EventManager::registerTick(EventHandler handler, int32_t when, Plugin* plugin, bool absolute) { @@ -59,7 +64,7 @@ void DFHack::EventManager::registerTick(EventHandler handler, int32_t when, Plug return; } -void DFHack::EventManager::unregister(EventType::EventType e, EventHandler handler, Plugin* plugin) { +void DFHack::EventManager::unregister(EventType::EventType e, EventHandler handler, int32_t freq, Plugin* plugin) { for ( multimap::iterator i = handlers[e].find(plugin); i != handlers[e].end(); i++ ) { if ( (*i).first != plugin ) break; @@ -69,6 +74,16 @@ void DFHack::EventManager::unregister(EventType::EventType e, EventHandler handl break; } } + if ( eventFrequency[e].find(freq) == eventFrequency[e].end() ) { + Core::getInstance().getConsole().print("%s, line %d: Error: incorrect frequency on deregister.\n", __FILE__, __LINE__); + return; + } + eventFrequency[e][freq]--; + if ( eventFrequency[e][freq] == 0 ) { + eventFrequency[e].erase(eventFrequency[e].find(freq)); + } else if ( eventFrequency[e][freq] < 0 ) { + Core::getInstance().getConsole().print("%s, line %d: Error: incorrect frequency on deregister.\n", __FILE__, __LINE__); + } return; } @@ -95,6 +110,21 @@ void DFHack::EventManager::unregisterAll(Plugin* plugin) { for ( size_t a = 0; a < (size_t)EventType::EVENT_MAX; a++ ) { handlers[a].erase(plugin); } + + for ( size_t a = 0; a < (size_t)EventType::EVENT_MAX; a++ ) { + for ( auto b = pluginFrequencies[a].begin(); b != pluginFrequencies[a].end(); b++ ) { + if ( (*b).first != plugin ) + continue; + int32_t freq = (*b).second; + eventFrequency[a][freq]--; + if ( eventFrequency[a][freq] < 0 ) { + Core::getInstance().getConsole().print("%s, line %d: Error: incorrect frequency on deregister.\n", __FILE__, __LINE__); + eventFrequency[a].erase(eventFrequency[a].find(freq)); + } else if ( eventFrequency[a][freq] == 0 ) { + eventFrequency[a].erase(eventFrequency[a].find(freq)); + } + } + } return; } @@ -134,7 +164,7 @@ void DFHack::EventManager::onStateChange(color_ostream& out, state_change_event //TODO: put this somewhere else doOnce = true; EventHandler buildingHandler(Buildings::updateBuildings); - DFHack::EventManager::registerListener(EventType::BUILDING, buildingHandler, NULL); + DFHack::EventManager::registerListener(EventType::BUILDING, buildingHandler, 100, NULL); //out.print("Registered listeners.\n %d", __LINE__); } if ( event == DFHack::SC_MAP_UNLOADED ) { @@ -175,17 +205,36 @@ void DFHack::EventManager::manageEvents(color_ostream& out) { } uint32_t tick = DFHack::World::ReadCurrentYear()*ticksPerYear + DFHack::World::ReadCurrentTick(); + if ( tick <= lastTick ) return; lastTick = tick; manageTickEvent(out); - manageJobInitiatedEvent(out); - manageJobCompletedEvent(out); - manageUnitDeathEvent(out); - manageItemCreationEvent(out); - manageBuildingEvent(out); - manageConstructionEvent(out); + if ( tick - eventLastTick[EventType::JOB_INITIATED] >= (*eventFrequency[EventType::JOB_INITIATED].begin()).first ) { + manageJobInitiatedEvent(out); + eventLastTick[EventType::JOB_INITIATED] = tick; + } + if ( tick - eventLastTick[EventType::JOB_COMPLETED] >= (*eventFrequency[EventType::JOB_COMPLETED].begin()).first ) { + manageJobCompletedEvent(out); + eventLastTick[EventType::JOB_COMPLETED] = tick; + } + if ( tick - eventLastTick[EventType::UNIT_DEATH] >= (*eventFrequency[EventType::UNIT_DEATH].begin()).first ) { + manageUnitDeathEvent(out); + eventLastTick[EventType::UNIT_DEATH] = tick; + } + if ( tick - eventLastTick[EventType::ITEM_CREATED] >= (*eventFrequency[EventType::ITEM_CREATED].begin()).first ) { + manageItemCreationEvent(out); + eventLastTick[EventType::ITEM_CREATED] = tick; + } + if ( tick - eventLastTick[EventType::BUILDING] >= (*eventFrequency[EventType::BUILDING].begin()).first ) { + manageBuildingEvent(out); + eventLastTick[EventType::BUILDING] = tick; + } + if ( tick - eventLastTick[EventType::CONSTRUCTION] >= (*eventFrequency[EventType::CONSTRUCTION].begin()).first ) { + manageConstructionEvent(out); + eventLastTick[EventType::CONSTRUCTION] = tick; + } return; } diff --git a/plugins/devel/eventExample.cpp b/plugins/devel/eventExample.cpp index d93396d29..e6a3dd22f 100644 --- a/plugins/devel/eventExample.cpp +++ b/plugins/devel/eventExample.cpp @@ -43,16 +43,16 @@ command_result eventExample(color_ostream& out, vector& parameters) { Plugin* me = Core::getInstance().getPluginManager()->getPluginByName("eventExample"); EventManager::unregisterAll(me); - EventManager::registerListener(EventManager::EventType::JOB_INITIATED, initiateHandler, me); - EventManager::registerListener(EventManager::EventType::JOB_COMPLETED, completeHandler, me); + EventManager::registerListener(EventManager::EventType::JOB_INITIATED, initiateHandler, 10, me); + EventManager::registerListener(EventManager::EventType::JOB_COMPLETED, completeHandler, 5, me); EventManager::registerTick(timeHandler, 1, me); EventManager::registerTick(timeHandler, 2, me); EventManager::registerTick(timeHandler, 4, me); EventManager::registerTick(timeHandler, 8, me); - EventManager::registerListener(EventManager::EventType::UNIT_DEATH, deathHandler, me); - EventManager::registerListener(EventManager::EventType::ITEM_CREATED, itemHandler, me); - EventManager::registerListener(EventManager::EventType::BUILDING, buildingHandler, me); - EventManager::registerListener(EventManager::EventType::CONSTRUCTION, constructionHandler, me); + EventManager::registerListener(EventManager::EventType::UNIT_DEATH, deathHandler, 500, me); + EventManager::registerListener(EventManager::EventType::ITEM_CREATED, itemHandler, 1000, me); + EventManager::registerListener(EventManager::EventType::BUILDING, buildingHandler, 500, me); + EventManager::registerListener(EventManager::EventType::CONSTRUCTION, constructionHandler, 100, me); out.print("Events registered.\n"); return CR_OK; }