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,
CONSTRUCTION,
SYNDROME,
INVASION,
EVENT_MAX
};
}
struct EventHandler {
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 {
return eventHandler == handle.eventHandler;
return eventHandler == handle.eventHandler && freq == handle.freq;
}
bool operator!=(EventHandler& handle) const {
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 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);
void manageEvents(color_ostream& out);
void onStateChange(color_ostream& out, state_change_event event);

@ -12,6 +12,7 @@
#include "df/item.h"
#include "df/job.h"
#include "df/job_list_link.h"
#include "df/ui.h"
#include "df/unit.h"
#include "df/unit_syndrome.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
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];
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));
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) {
@ -65,7 +62,7 @@ void DFHack::EventManager::registerTick(EventHandler handler, int32_t when, Plug
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++ ) {
if ( (*i).first != plugin )
break;
@ -75,16 +72,6 @@ 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;
}
@ -111,21 +98,6 @@ 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;
}
@ -137,6 +109,7 @@ static void manageItemCreationEvent(color_ostream& out);
static void manageBuildingEvent(color_ostream& out);
static void manageConstructionEvent(color_ostream& out);
static void manageSyndromeEvent(color_ostream& out);
static void manageInvasionEvent(color_ostream& out);
//tick event
static uint32_t lastTick = 0;
@ -161,16 +134,19 @@ static unordered_set<int32_t> buildings;
static unordered_set<df::construction*> constructions;
static bool gameLoaded;
//invasion
static int32_t nextInvasion;
void DFHack::EventManager::onStateChange(color_ostream& out, state_change_event event) {
static bool doOnce = false;
if ( !doOnce ) {
//TODO: put this somewhere else
doOnce = true;
EventHandler buildingHandler(Buildings::updateBuildings);
DFHack::EventManager::registerListener(EventType::BUILDING, buildingHandler, 100, NULL);
EventHandler buildingHandler(Buildings::updateBuildings, 100);
DFHack::EventManager::registerListener(EventType::BUILDING, buildingHandler, NULL);
//out.print("Registered listeners.\n %d", __LINE__);
}
if ( event == DFHack::SC_MAP_UNLOADED ) {
if ( event == DFHack::SC_WORLD_UNLOADED ) {
lastTick = 0;
lastJobId = -1;
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);
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
+ DFHack::World::ReadCurrentTick();
multimap<uint32_t,EventHandler> newTickQueue;
@ -200,6 +177,7 @@ void DFHack::EventManager::onStateChange(color_ostream& out, state_change_event
nextItem = 0;
nextBuilding = 0;
lastTick = 0;
nextInvasion = df::global::ui->invasions.next_id;
gameLoaded = true;
}
}
@ -215,35 +193,50 @@ void DFHack::EventManager::manageEvents(color_ostream& out) {
return;
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);
if ( tick - eventLastTick[EventType::JOB_INITIATED] >= (*eventFrequency[EventType::JOB_INITIATED].begin()).first ) {
if ( tick - eventLastTick[EventType::JOB_INITIATED] >= eventFrequency[EventType::JOB_INITIATED] ) {
manageJobInitiatedEvent(out);
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);
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);
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);
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);
eventLastTick[EventType::BUILDING] = tick;
}
if ( tick - eventLastTick[EventType::CONSTRUCTION] >= (*eventFrequency[EventType::CONSTRUCTION].begin()).first ) {
if ( tick - eventLastTick[EventType::CONSTRUCTION] >= eventFrequency[EventType::CONSTRUCTION] ) {
manageConstructionEvent(out);
eventLastTick[EventType::CONSTRUCTION] = tick;
}
if ( tick - eventLastTick[EventType::SYNDROME] >= (*eventFrequency[EventType::SYNDROME].begin()).first ) {
if ( tick - eventLastTick[EventType::SYNDROME] >= eventFrequency[EventType::SYNDROME] ) {
manageSyndromeEvent(out);
eventLastTick[EventType::SYNDROME] = tick;
}
if ( tick - eventLastTick[EventType::INVASION] >= eventFrequency[EventType::INVASION] ) {
manageInvasionEvent(out);
eventLastTick[EventType::INVASION] = tick;
}
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 construction(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);
@ -33,28 +34,30 @@ DFhackCExport command_result plugin_init(color_ostream &out, std::vector<PluginC
}
command_result eventExample(color_ostream& out, vector<string>& parameters) {
EventManager::EventHandler initiateHandler(jobInitiated);
EventManager::EventHandler completeHandler(jobCompleted);
EventManager::EventHandler timeHandler(timePassed);
EventManager::EventHandler deathHandler(unitDeath);
EventManager::EventHandler itemHandler(itemCreate);
EventManager::EventHandler buildingHandler(building);
EventManager::EventHandler constructionHandler(construction);
EventManager::EventHandler syndromeHandler(syndrome);
EventManager::EventHandler initiateHandler(jobInitiated, 10);
EventManager::EventHandler completeHandler(jobCompleted, 5);
EventManager::EventHandler timeHandler(timePassed, 1);
EventManager::EventHandler deathHandler(unitDeath, 500);
EventManager::EventHandler itemHandler(itemCreate, 1000);
EventManager::EventHandler buildingHandler(building, 500);
EventManager::EventHandler constructionHandler(construction, 100);
EventManager::EventHandler syndromeHandler(syndrome, 1);
EventManager::EventHandler invasionHandler(invasion, 1000);
Plugin* me = Core::getInstance().getPluginManager()->getPluginByName("eventExample");
EventManager::unregisterAll(me);
EventManager::registerListener(EventManager::EventType::JOB_INITIATED, initiateHandler, 10, me);
EventManager::registerListener(EventManager::EventType::JOB_COMPLETED, completeHandler, 5, me);
EventManager::registerListener(EventManager::EventType::JOB_INITIATED, initiateHandler, me);
EventManager::registerListener(EventManager::EventType::JOB_COMPLETED, completeHandler, 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, 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);
EventManager::registerListener(EventManager::EventType::SYNDROME, syndromeHandler, 1, 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::SYNDROME, syndromeHandler, me);
EventManager::registerListener(EventManager::EventType::INVASION, invasionHandler, me);
out.print("Events registered.\n");
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);
}
void invasion(color_ostream& out, void* ptr) {
out.print("New invasion! %d\n", (int32_t)ptr);
}