From 3594dc2eb89b9fcd24530e96f6df96b4a250de7f Mon Sep 17 00:00:00 2001 From: expwnent Date: Sun, 20 Oct 2013 21:48:28 -0400 Subject: [PATCH] EventManager: fixed the TICK event, and a few tweaks. - redo tick event management to work with world->frame_counter - the freq of a TICK EventHandler is now ignored - unregistering for an individual TICK event is still broken - you would have to know the modified freq to even begin removing it - it is only removed from handleres[TICK], not from tickQueue - redo unregisterAll to be more efficient - use the map loaded/unloaded events instead of world loaded/unloaded for initializing/clearing event monitoring data - get rid of silly unsigned variables --- library/modules/EventManager.cpp | 63 +++++++++++++++----------------- 1 file changed, 29 insertions(+), 34 deletions(-) diff --git a/library/modules/EventManager.cpp b/library/modules/EventManager.cpp index 31ebfecc8..1a91e2c11 100644 --- a/library/modules/EventManager.cpp +++ b/library/modules/EventManager.cpp @@ -37,36 +37,31 @@ using namespace EventManager; * consider a typedef instead of a struct for EventHandler **/ -//map > tickQueue; -static multimap tickQueue; +static multimap tickQueue; //TODO: consider unordered_map of pairs, or unordered_map of unordered_set, or whatever static multimap handlers[EventType::EVENT_MAX]; -static uint32_t eventLastTick[EventType::EVENT_MAX]; +static int32_t eventLastTick[EventType::EVENT_MAX]; -static const uint32_t ticksPerYear = 403200; +static const int32_t ticksPerYear = 403200; void DFHack::EventManager::registerListener(EventType::EventType e, EventHandler handler, Plugin* plugin) { handlers[e].insert(pair(plugin, handler)); } void DFHack::EventManager::registerTick(EventHandler handler, int32_t when, Plugin* plugin, bool absolute) { - uint32_t tick = DFHack::World::ReadCurrentYear()*ticksPerYear - + DFHack::World::ReadCurrentTick(); - if ( !Core::getInstance().isWorldLoaded() ) { - tick = 0; - if ( absolute ) { - Core::getInstance().getConsole().print("Warning: absolute flag will not be honored.\n"); + if ( !absolute ) { + df::world* world = df::global::world; + if ( world ) { + when += world->frame_counter; + } else { + if ( Once::doOnce("EventManager registerTick unhonored absolute=false") ) + Core::getInstance().getConsole().print("EventManager::registerTick: warning! absolute flag=false not honored.\n"); } } - if ( absolute ) { - tick = 0; - } - handler.freq = 1; //to make manageEvents work more nicely - - tickQueue.insert(pair(tick+(uint32_t)when, handler)); + handler.freq = when; + tickQueue.insert(pair(handler.freq, handler)); handlers[EventType::TICK].insert(pair(plugin,handler)); - return; } void DFHack::EventManager::unregister(EventType::EventType e, EventHandler handler, Plugin* plugin) { @@ -92,15 +87,16 @@ void DFHack::EventManager::unregisterAll(Plugin* plugin) { bool didSomething; do { didSomething = false; - for ( auto j = tickQueue.begin(); j != tickQueue.end(); j++ ) { - EventHandler candidate = (*j).second; - if ( getRidOf != candidate ) + for ( auto j = tickQueue.find(getRidOf.freq); j != tickQueue.end(); j++ ) { + if ( (*j).first > getRidOf.freq ) + break; + if ( (*j).second != getRidOf ) continue; tickQueue.erase(j); didSomething = true; break; } - } while(didSomething); + } while (didSomething); //this loop is here in case the same EventHandler was added more than once } for ( size_t a = 0; a < (size_t)EventType::EVENT_MAX; a++ ) { handlers[a].erase(plugin); @@ -165,6 +161,8 @@ static int32_t nextInvasion; void DFHack::EventManager::onStateChange(color_ostream& out, state_change_event event) { static bool doOnce = false; +// const string eventNames[] = {"world loaded", "world unloaded", "map loaded", "map unloaded", "viewscreen changed", "core initialized", "begin unload", "paused", "unpaused"}; +// out.print("%s,%d: onStateChange %d: \"%s\"\n", __FILE__, __LINE__, (int32_t)event, eventNames[event].c_str()); if ( !doOnce ) { //TODO: put this somewhere else doOnce = true; @@ -172,7 +170,7 @@ void DFHack::EventManager::onStateChange(color_ostream& out, state_change_event DFHack::EventManager::registerListener(EventType::BUILDING, buildingHandler, NULL); //out.print("Registered listeners.\n %d", __LINE__); } - if ( event == DFHack::SC_WORLD_UNLOADED ) { + if ( event == DFHack::SC_MAP_UNLOADED ) { lastJobId = -1; for ( auto i = prevJobs.begin(); i != prevJobs.end(); i++ ) { Job::deleteJobStruct((*i).second, true); @@ -186,16 +184,14 @@ void DFHack::EventManager::onStateChange(color_ostream& out, state_change_event Buildings::clearBuildings(out); gameLoaded = false; // equipmentLog.clear(); - } else if ( event == DFHack::SC_WORLD_LOADED ) { - uint32_t tick = DFHack::World::ReadCurrentYear()*ticksPerYear - + DFHack::World::ReadCurrentTick(); - multimap newTickQueue; - for ( auto i = tickQueue.begin(); i != tickQueue.end(); i++ ) { - newTickQueue.insert(pair(tick + (*i).first, (*i).second)); - } + } else if ( event == DFHack::SC_MAP_LOADED ) { + int32_t tick = df::global::world->frame_counter; + multimap newTickQueue; + for ( auto i = tickQueue.begin(); i != tickQueue.end(); i++ ) + newTickQueue.insert(pair(tick+(*i).first, (*i).second)); tickQueue.clear(); - tickQueue.insert(newTickQueue.begin(), newTickQueue.end()); + //out.print("%s,%d: on load, frame_counter = %d\n", __FILE__, __LINE__, tick); nextItem = *df::global::item_next_id; nextBuilding = *df::global::building_next_id; @@ -268,8 +264,7 @@ void DFHack::EventManager::manageEvents(color_ostream& out) { } static void manageTickEvent(color_ostream& out) { - uint32_t tick = DFHack::World::ReadCurrentYear()*ticksPerYear - + DFHack::World::ReadCurrentTick(); + int32_t tick = df::global::world->frame_counter; while ( !tickQueue.empty() ) { if ( tick < (*tickQueue.begin()).first ) break; @@ -318,8 +313,8 @@ static int32_t getWorkerID(df::job* job) { TODO: consider checking item creation / experience gain just in case */ static void manageJobCompletedEvent(color_ostream& out) { - uint32_t tick0 = eventLastTick[EventType::JOB_COMPLETED]; - uint32_t tick1 = df::global::world->frame_counter; + int32_t tick0 = eventLastTick[EventType::JOB_COMPLETED]; + int32_t tick1 = df::global::world->frame_counter; multimap copy(handlers[EventType::JOB_COMPLETED].begin(), handlers[EventType::JOB_COMPLETED].end()); map nowJobs;