Merge branch 'eventManager' into trueTransformation

develop
expwnent 2013-01-05 12:51:14 -05:00
commit 7a33e5bdbe
3 changed files with 79 additions and 61 deletions

@ -20,18 +20,20 @@ namespace DFHack {
BUILDING, BUILDING,
CONSTRUCTION, CONSTRUCTION,
SYNDROME, SYNDROME,
INVASION,
EVENT_MAX EVENT_MAX
}; };
} }
struct EventHandler { struct EventHandler {
void (*eventHandler)(color_ostream&, void*); //called when the event happens void (*eventHandler)(color_ostream&, void*); //called when the event happens
int32_t freq;
EventHandler(void (*eventHandlerIn)(color_ostream&, void*)): eventHandler(eventHandlerIn) { EventHandler(void (*eventHandlerIn)(color_ostream&, void*), int32_t freqIn): eventHandler(eventHandlerIn), freq(freqIn) {
} }
bool operator==(EventHandler& handle) const { bool operator==(EventHandler& handle) const {
return eventHandler == handle.eventHandler; return eventHandler == handle.eventHandler && freq == handle.freq;
} }
bool operator!=(EventHandler& handle) const { bool operator!=(EventHandler& handle) const {
return !( *this == handle); return !( *this == handle);
@ -46,9 +48,9 @@ namespace DFHack {
} }
}; };
DFHACK_EXPORT void registerListener(EventType::EventType e, EventHandler handler, int32_t freq, Plugin* plugin); DFHACK_EXPORT void registerListener(EventType::EventType e, EventHandler handler, Plugin* plugin);
DFHACK_EXPORT void registerTick(EventHandler handler, int32_t when, Plugin* plugin, bool absolute=false); DFHACK_EXPORT void registerTick(EventHandler handler, int32_t when, Plugin* plugin, bool absolute=false);
DFHACK_EXPORT void unregister(EventType::EventType e, EventHandler handler, int32_t freq, Plugin* plugin); DFHACK_EXPORT void unregister(EventType::EventType e, EventHandler handler, Plugin* plugin);
DFHACK_EXPORT void unregisterAll(Plugin* plugin); DFHACK_EXPORT void unregisterAll(Plugin* plugin);
void manageEvents(color_ostream& out); void manageEvents(color_ostream& out);
void onStateChange(color_ostream& out, state_change_event event); void onStateChange(color_ostream& out, state_change_event event);

@ -12,6 +12,7 @@
#include "df/item.h" #include "df/item.h"
#include "df/job.h" #include "df/job.h"
#include "df/job_list_link.h" #include "df/job_list_link.h"
#include "df/ui.h"
#include "df/unit.h" #include "df/unit.h"
#include "df/unit_syndrome.h" #include "df/unit_syndrome.h"
#include "df/world.h" #include "df/world.h"
@ -35,16 +36,12 @@ multimap<uint32_t, EventHandler> tickQueue;
//TODO: consider unordered_map of pairs, or unordered_map of unordered_set, or whatever //TODO: consider unordered_map of pairs, or unordered_map of unordered_set, or whatever
multimap<Plugin*, EventHandler> handlers[EventType::EVENT_MAX]; multimap<Plugin*, EventHandler> handlers[EventType::EVENT_MAX];
multimap<Plugin*, int32_t> pluginFrequencies[EventType::EVENT_MAX];
map<int32_t, int32_t> eventFrequency[EventType::EVENT_MAX];
uint32_t eventLastTick[EventType::EVENT_MAX]; uint32_t eventLastTick[EventType::EVENT_MAX];
const uint32_t ticksPerYear = 403200; const uint32_t ticksPerYear = 403200;
void DFHack::EventManager::registerListener(EventType::EventType e, EventHandler handler, int32_t freq, Plugin* plugin) { void DFHack::EventManager::registerListener(EventType::EventType e, EventHandler handler, Plugin* plugin) {
handlers[e].insert(pair<Plugin*, EventHandler>(plugin, handler)); handlers[e].insert(pair<Plugin*, EventHandler>(plugin, handler));
eventFrequency[e][freq]++;
pluginFrequencies[e].insert(pair<Plugin*,int32_t>(plugin, freq));
} }
void DFHack::EventManager::registerTick(EventHandler handler, int32_t when, Plugin* plugin, bool absolute) { void DFHack::EventManager::registerTick(EventHandler handler, int32_t when, Plugin* plugin, bool absolute) {
@ -65,7 +62,7 @@ void DFHack::EventManager::registerTick(EventHandler handler, int32_t when, Plug
return; return;
} }
void DFHack::EventManager::unregister(EventType::EventType e, EventHandler handler, int32_t freq, Plugin* plugin) { void DFHack::EventManager::unregister(EventType::EventType e, EventHandler handler, Plugin* plugin) {
for ( multimap<Plugin*, EventHandler>::iterator i = handlers[e].find(plugin); i != handlers[e].end(); i++ ) { for ( multimap<Plugin*, EventHandler>::iterator i = handlers[e].find(plugin); i != handlers[e].end(); i++ ) {
if ( (*i).first != plugin ) if ( (*i).first != plugin )
break; break;
@ -75,16 +72,6 @@ void DFHack::EventManager::unregister(EventType::EventType e, EventHandler handl
break; 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; return;
} }
@ -111,21 +98,6 @@ void DFHack::EventManager::unregisterAll(Plugin* plugin) {
for ( size_t a = 0; a < (size_t)EventType::EVENT_MAX; a++ ) { for ( size_t a = 0; a < (size_t)EventType::EVENT_MAX; a++ ) {
handlers[a].erase(plugin); 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; return;
} }
@ -137,6 +109,7 @@ static void manageItemCreationEvent(color_ostream& out);
static void manageBuildingEvent(color_ostream& out); static void manageBuildingEvent(color_ostream& out);
static void manageConstructionEvent(color_ostream& out); static void manageConstructionEvent(color_ostream& out);
static void manageSyndromeEvent(color_ostream& out); static void manageSyndromeEvent(color_ostream& out);
static void manageInvasionEvent(color_ostream& out);
//tick event //tick event
static uint32_t lastTick = 0; static uint32_t lastTick = 0;
@ -161,16 +134,19 @@ static unordered_set<int32_t> buildings;
static unordered_set<df::construction*> constructions; static unordered_set<df::construction*> constructions;
static bool gameLoaded; static bool gameLoaded;
//invasion
static int32_t nextInvasion;
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;
if ( !doOnce ) { if ( !doOnce ) {
//TODO: put this somewhere else //TODO: put this somewhere else
doOnce = true; doOnce = true;
EventHandler buildingHandler(Buildings::updateBuildings); EventHandler buildingHandler(Buildings::updateBuildings, 100);
DFHack::EventManager::registerListener(EventType::BUILDING, buildingHandler, 100, NULL); DFHack::EventManager::registerListener(EventType::BUILDING, buildingHandler, NULL);
//out.print("Registered listeners.\n %d", __LINE__); //out.print("Registered listeners.\n %d", __LINE__);
} }
if ( event == DFHack::SC_MAP_UNLOADED ) { if ( event == DFHack::SC_WORLD_UNLOADED ) {
lastTick = 0; lastTick = 0;
lastJobId = -1; lastJobId = -1;
for ( auto i = prevJobs.begin(); i != prevJobs.end(); i++ ) { for ( auto i = prevJobs.begin(); i != prevJobs.end(); i++ ) {
@ -186,7 +162,8 @@ void DFHack::EventManager::onStateChange(color_ostream& out, state_change_event
Buildings::clearBuildings(out); Buildings::clearBuildings(out);
gameLoaded = false; gameLoaded = false;
} else if ( event == DFHack::SC_MAP_LOADED ) { nextInvasion = -1;
} else if ( event == DFHack::SC_WORLD_LOADED ) {
uint32_t tick = DFHack::World::ReadCurrentYear()*ticksPerYear uint32_t tick = DFHack::World::ReadCurrentYear()*ticksPerYear
+ DFHack::World::ReadCurrentTick(); + DFHack::World::ReadCurrentTick();
multimap<uint32_t,EventHandler> newTickQueue; multimap<uint32_t,EventHandler> newTickQueue;
@ -200,6 +177,7 @@ void DFHack::EventManager::onStateChange(color_ostream& out, state_change_event
nextItem = 0; nextItem = 0;
nextBuilding = 0; nextBuilding = 0;
lastTick = 0; lastTick = 0;
nextInvasion = df::global::ui->invasions.next_id;
gameLoaded = true; gameLoaded = true;
} }
} }
@ -214,36 +192,51 @@ void DFHack::EventManager::manageEvents(color_ostream& out) {
if ( tick <= lastTick ) if ( tick <= lastTick )
return; return;
lastTick = tick; lastTick = tick;
int32_t eventFrequency[EventType::EVENT_MAX];
for ( size_t a = 0; a < EventType::EVENT_MAX; a++ ) {
int32_t min = 1000000000;
for ( auto b = handlers[a].begin(); b != handlers[a].end(); b++ ) {
EventHandler bob = (*b).second;
if ( bob.freq < min )
min = bob.freq;
}
eventFrequency[a] = min;
}
manageTickEvent(out); manageTickEvent(out);
if ( tick - eventLastTick[EventType::JOB_INITIATED] >= (*eventFrequency[EventType::JOB_INITIATED].begin()).first ) { if ( tick - eventLastTick[EventType::JOB_INITIATED] >= eventFrequency[EventType::JOB_INITIATED] ) {
manageJobInitiatedEvent(out); manageJobInitiatedEvent(out);
eventLastTick[EventType::JOB_INITIATED] = tick; eventLastTick[EventType::JOB_INITIATED] = tick;
} }
if ( tick - eventLastTick[EventType::JOB_COMPLETED] >= (*eventFrequency[EventType::JOB_COMPLETED].begin()).first ) { if ( tick - eventLastTick[EventType::JOB_COMPLETED] >= eventFrequency[EventType::JOB_COMPLETED] ) {
manageJobCompletedEvent(out); manageJobCompletedEvent(out);
eventLastTick[EventType::JOB_COMPLETED] = tick; eventLastTick[EventType::JOB_COMPLETED] = tick;
} }
if ( tick - eventLastTick[EventType::UNIT_DEATH] >= (*eventFrequency[EventType::UNIT_DEATH].begin()).first ) { if ( tick - eventLastTick[EventType::UNIT_DEATH] >= eventFrequency[EventType::UNIT_DEATH] ) {
manageUnitDeathEvent(out); manageUnitDeathEvent(out);
eventLastTick[EventType::UNIT_DEATH] = tick; eventLastTick[EventType::UNIT_DEATH] = tick;
} }
if ( tick - eventLastTick[EventType::ITEM_CREATED] >= (*eventFrequency[EventType::ITEM_CREATED].begin()).first ) { if ( tick - eventLastTick[EventType::ITEM_CREATED] >= eventFrequency[EventType::ITEM_CREATED] ) {
manageItemCreationEvent(out); manageItemCreationEvent(out);
eventLastTick[EventType::ITEM_CREATED] = tick; eventLastTick[EventType::ITEM_CREATED] = tick;
} }
if ( tick - eventLastTick[EventType::BUILDING] >= (*eventFrequency[EventType::BUILDING].begin()).first ) { if ( tick - eventLastTick[EventType::BUILDING] >= eventFrequency[EventType::BUILDING] ) {
manageBuildingEvent(out); manageBuildingEvent(out);
eventLastTick[EventType::BUILDING] = tick; eventLastTick[EventType::BUILDING] = tick;
} }
if ( tick - eventLastTick[EventType::CONSTRUCTION] >= (*eventFrequency[EventType::CONSTRUCTION].begin()).first ) { if ( tick - eventLastTick[EventType::CONSTRUCTION] >= eventFrequency[EventType::CONSTRUCTION] ) {
manageConstructionEvent(out); manageConstructionEvent(out);
eventLastTick[EventType::CONSTRUCTION] = tick; eventLastTick[EventType::CONSTRUCTION] = tick;
} }
if ( tick - eventLastTick[EventType::SYNDROME] >= (*eventFrequency[EventType::SYNDROME].begin()).first ) { if ( tick - eventLastTick[EventType::SYNDROME] >= eventFrequency[EventType::SYNDROME] ) {
manageSyndromeEvent(out); manageSyndromeEvent(out);
eventLastTick[EventType::SYNDROME] = tick; eventLastTick[EventType::SYNDROME] = tick;
} }
if ( tick - eventLastTick[EventType::INVASION] >= eventFrequency[EventType::INVASION] ) {
manageInvasionEvent(out);
eventLastTick[EventType::INVASION] = tick;
}
return; return;
} }
@ -492,3 +485,19 @@ static void manageSyndromeEvent(color_ostream& out) {
} }
} }
static void manageInvasionEvent(color_ostream& out) {
if ( handlers[EventType::INVASION].empty() )
return;
multimap<Plugin*,EventHandler> copy(handlers[EventType::INVASION].begin(), handlers[EventType::INVASION].end());
if ( df::global::ui->invasions.next_id <= nextInvasion )
return;
nextInvasion = df::global::ui->invasions.next_id;
for ( auto a = copy.begin(); a != copy.end(); a++ ) {
EventHandler handle = (*a).second;
handle.eventHandler(out, (void*)nextInvasion);
}
}

@ -24,6 +24,7 @@ void itemCreate(color_ostream& out, void* ptr);
void building(color_ostream& out, void* ptr); void building(color_ostream& out, void* ptr);
void construction(color_ostream& out, void* ptr); void construction(color_ostream& out, void* ptr);
void syndrome(color_ostream& out, void* ptr); void syndrome(color_ostream& out, void* ptr);
void invasion(color_ostream& out, void* ptr);
command_result eventExample(color_ostream& out, vector<string>& parameters); command_result eventExample(color_ostream& out, vector<string>& parameters);
@ -33,28 +34,30 @@ DFhackCExport command_result plugin_init(color_ostream &out, std::vector<PluginC
} }
command_result eventExample(color_ostream& out, vector<string>& parameters) { command_result eventExample(color_ostream& out, vector<string>& parameters) {
EventManager::EventHandler initiateHandler(jobInitiated); EventManager::EventHandler initiateHandler(jobInitiated, 10);
EventManager::EventHandler completeHandler(jobCompleted); EventManager::EventHandler completeHandler(jobCompleted, 5);
EventManager::EventHandler timeHandler(timePassed); EventManager::EventHandler timeHandler(timePassed, 1);
EventManager::EventHandler deathHandler(unitDeath); EventManager::EventHandler deathHandler(unitDeath, 500);
EventManager::EventHandler itemHandler(itemCreate); EventManager::EventHandler itemHandler(itemCreate, 1000);
EventManager::EventHandler buildingHandler(building); EventManager::EventHandler buildingHandler(building, 500);
EventManager::EventHandler constructionHandler(construction); EventManager::EventHandler constructionHandler(construction, 100);
EventManager::EventHandler syndromeHandler(syndrome); EventManager::EventHandler syndromeHandler(syndrome, 1);
EventManager::EventHandler invasionHandler(invasion, 1000);
Plugin* me = Core::getInstance().getPluginManager()->getPluginByName("eventExample"); Plugin* me = Core::getInstance().getPluginManager()->getPluginByName("eventExample");
EventManager::unregisterAll(me); EventManager::unregisterAll(me);
EventManager::registerListener(EventManager::EventType::JOB_INITIATED, initiateHandler, 10, me); EventManager::registerListener(EventManager::EventType::JOB_INITIATED, initiateHandler, me);
EventManager::registerListener(EventManager::EventType::JOB_COMPLETED, completeHandler, 5, me); EventManager::registerListener(EventManager::EventType::JOB_COMPLETED, completeHandler, me);
EventManager::registerTick(timeHandler, 1, me); EventManager::registerTick(timeHandler, 1, me);
EventManager::registerTick(timeHandler, 2, me); EventManager::registerTick(timeHandler, 2, me);
EventManager::registerTick(timeHandler, 4, me); EventManager::registerTick(timeHandler, 4, me);
EventManager::registerTick(timeHandler, 8, me); EventManager::registerTick(timeHandler, 8, me);
EventManager::registerListener(EventManager::EventType::UNIT_DEATH, deathHandler, 500, me); EventManager::registerListener(EventManager::EventType::UNIT_DEATH, deathHandler, me);
EventManager::registerListener(EventManager::EventType::ITEM_CREATED, itemHandler, 1000, me); EventManager::registerListener(EventManager::EventType::ITEM_CREATED, itemHandler, me);
EventManager::registerListener(EventManager::EventType::BUILDING, buildingHandler, 500, me); EventManager::registerListener(EventManager::EventType::BUILDING, buildingHandler, me);
EventManager::registerListener(EventManager::EventType::CONSTRUCTION, constructionHandler, 100, me); EventManager::registerListener(EventManager::EventType::CONSTRUCTION, constructionHandler, me);
EventManager::registerListener(EventManager::EventType::SYNDROME, syndromeHandler, 1, me); EventManager::registerListener(EventManager::EventType::SYNDROME, syndromeHandler, me);
EventManager::registerListener(EventManager::EventType::INVASION, invasionHandler, me);
out.print("Events registered.\n"); out.print("Events registered.\n");
return CR_OK; return CR_OK;
} }
@ -99,3 +102,7 @@ void syndrome(color_ostream& out, void* ptr) {
out.print("Syndrome started: unit %d, syndrome %d.\n", data->unitId, data->syndromeIndex); out.print("Syndrome started: unit %d, syndrome %d.\n", data->unitId, data->syndromeIndex);
} }
void invasion(color_ostream& out, void* ptr) {
out.print("New invasion! %d\n", (int32_t)ptr);
}