Merge branch 'eventManager' into diggingInvaders-unstable

develop
expwnent 2013-01-03 15:53:06 -05:00
commit 84b8fae326
5 changed files with 387 additions and 23 deletions

@ -25,7 +25,9 @@ distribution.
#pragma once #pragma once
#include "Export.h" #include "Export.h"
#include "DataDefs.h" #include "DataDefs.h"
#include "Types.h"
#include "df/building.h" #include "df/building.h"
#include "df/building_type.h"
#include "df/civzone_type.h" #include "df/civzone_type.h"
#include "df/furnace_type.h" #include "df/furnace_type.h"
#include "df/workshop_type.h" #include "df/workshop_type.h"
@ -181,5 +183,8 @@ DFHACK_EXPORT bool constructWithFilters(df::building *bld, std::vector<df::job_i
*/ */
DFHACK_EXPORT bool deconstruct(df::building *bld); DFHACK_EXPORT bool deconstruct(df::building *bld);
void updateBuildings(color_ostream& out, void* ptr);
void clearBuildings(color_ostream& out);
} }
} }

@ -17,6 +17,10 @@ namespace DFHack {
JOB_COMPLETED, JOB_COMPLETED,
UNIT_DEATH, UNIT_DEATH,
ITEM_CREATED, ITEM_CREATED,
BUILDING,
CONSTRUCTION,
SYNDROME,
INVASION,
EVENT_MAX EVENT_MAX
}; };
} }
@ -34,10 +38,18 @@ namespace DFHack {
return !( *this == handle); return !( *this == handle);
} }
}; };
struct SyndromeData {
int32_t unitId;
int32_t syndromeIndex;
SyndromeData(int32_t unitId_in, int32_t syndromeIndex_in): unitId(unitId_in), syndromeIndex(syndromeIndex_in) {
}
};
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 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); 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);

@ -25,11 +25,16 @@ distribution.
#include "Internal.h" #include "Internal.h"
#include <algorithm>
#include <cstdlib>
#include <iostream>
#include <map>
#include <string> #include <string>
#include <unordered_map>
#include <vector> #include <vector>
#include <map>
using namespace std; using namespace std;
#include "ColorText.h"
#include "VersionInfo.h" #include "VersionInfo.h"
#include "MemAccess.h" #include "MemAccess.h"
#include "Types.h" #include "Types.h"
@ -77,6 +82,14 @@ using df::global::building_next_id;
using df::global::process_jobs; using df::global::process_jobs;
using df::building_def; using df::building_def;
struct CoordHash {
size_t operator()(const df::coord pos) const {
return pos.x*65537 + pos.y*17 + pos.z;
}
};
static unordered_map<df::coord, int32_t, CoordHash> locationToBuilding;
static uint8_t *getExtentTile(df::building_extents &extent, df::coord2d tile) static uint8_t *getExtentTile(df::building_extents &extent, df::coord2d tile)
{ {
if (!extent.extents) if (!extent.extents)
@ -236,6 +249,31 @@ df::building *Buildings::findAtTile(df::coord pos)
if (!occ || !occ->bits.building) if (!occ || !occ->bits.building)
return NULL; return NULL;
auto a = locationToBuilding.find(pos);
if ( a == locationToBuilding.end() ) {
cerr << __FILE__ << ", " << __LINE__ << ": can't find building at " << pos.x << ", " << pos.y << ", " <<pos.z << "." << endl;
exit(1);
}
int32_t id = (*a).second;
int32_t index = df::building::binsearch_index(df::global::world->buildings.all, id);
if ( index == -1 ) {
cerr << __FILE__ << ", " << __LINE__ << ": can't find building at " << pos.x << ", " << pos.y << ", " <<pos.z << "." << endl;
exit(1);
}
df::building* building = df::global::world->buildings.all[index];
if (!building->isSettingOccupancy())
return NULL;
if (building->room.extents && building->isExtentShaped())
{
auto etile = getExtentTile(building->room, pos);
if (!etile || !*etile)
return NULL;
}
return building;
/*
//old method: brute-force
auto &vec = df::building::get_vector(); auto &vec = df::building::get_vector();
for (size_t i = 0; i < vec.size(); i++) for (size_t i = 0; i < vec.size(); i++)
{ {
@ -260,6 +298,7 @@ df::building *Buildings::findAtTile(df::coord pos)
} }
return NULL; return NULL;
*/
} }
bool Buildings::findCivzonesAt(std::vector<df::building_civzonest*> *pvec, df::coord pos) bool Buildings::findCivzonesAt(std::vector<df::building_civzonest*> *pvec, df::coord pos)
@ -1077,3 +1116,52 @@ bool Buildings::deconstruct(df::building *bld)
return true; return true;
} }
static unordered_map<int32_t, df::coord> corner1;
static unordered_map<int32_t, df::coord> corner2;
void Buildings::clearBuildings(color_ostream& out) {
corner1.clear();
corner2.clear();
locationToBuilding.clear();
}
void Buildings::updateBuildings(color_ostream& out, void* ptr) {
//out.print("Updating buildings, %s %d\n", __FILE__, __LINE__);
int32_t id = (int32_t)ptr;
if ( corner1.find(id) == corner1.end() ) {
//new building: mark stuff
int32_t index = df::building::binsearch_index(df::global::world->buildings.all, id);
if ( index == -1 ) {
out.print("%s, line %d: Couldn't find new building id=%d.\n", __FILE__, __LINE__, id);
exit(1);
}
df::building* building = df::global::world->buildings.all[index];
df::coord p1(min(building->x1, building->x2), min(building->y1,building->y2), building->z);
df::coord p2(max(building->x1, building->x2), max(building->y1,building->y2), building->z);
corner1[id] = p1;
corner2[id] = p2;
for ( int32_t x = p1.x; x <= p2.x; x++ ) {
for ( int32_t y = p1.y; y <= p2.y; y++ ) {
df::coord pt(x,y,building->z);
locationToBuilding[pt] = id;
}
}
} else {
//existing building: destroy it
df::coord p1 = corner1[id];
df::coord p2 = corner2[id];
for ( int32_t x = p1.x; x <= p2.x; x++ ) {
for ( int32_t y = p1.y; y <= p2.y; y++ ) {
df::coord pt(x,y,p1.z);
locationToBuilding.erase(pt);
}
}
corner1.erase(id);
corner2.erase(id);
}
}

@ -1,19 +1,26 @@
#include "Core.h" #include "Core.h"
#include "Console.h" #include "Console.h"
#include "modules/Buildings.h"
#include "modules/Constructions.h"
#include "modules/EventManager.h" #include "modules/EventManager.h"
#include "modules/Job.h" #include "modules/Job.h"
#include "modules/World.h" #include "modules/World.h"
#include "df/building.h"
#include "df/construction.h"
#include "df/global_objects.h" #include "df/global_objects.h"
#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/world.h" #include "df/world.h"
//#include <list>
#include <map> #include <map>
//#include <vector> #include <unordered_map>
#include <unordered_set>
using namespace std; using namespace std;
using namespace DFHack; using namespace DFHack;
using namespace EventManager; using namespace EventManager;
@ -21,17 +28,24 @@ using namespace EventManager;
/* /*
* TODO: * TODO:
* error checking * error checking
* consider a typedef instead of a struct for EventHandler
**/ **/
//map<uint32_t, vector<DFHack::EventManager::EventHandler> > tickQueue; //map<uint32_t, vector<DFHack::EventManager::EventHandler> > tickQueue;
multimap<uint32_t, EventHandler> tickQueue; 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*, 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; 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*, 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) {
@ -52,7 +66,7 @@ void DFHack::EventManager::registerTick(EventHandler handler, int32_t when, Plug
return; 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<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;
@ -62,6 +76,16 @@ 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;
} }
@ -88,6 +112,21 @@ 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;
} }
@ -96,14 +135,46 @@ static void manageJobInitiatedEvent(color_ostream& out);
static void manageJobCompletedEvent(color_ostream& out); static void manageJobCompletedEvent(color_ostream& out);
static void manageUnitDeathEvent(color_ostream& out); static void manageUnitDeathEvent(color_ostream& out);
static void manageItemCreationEvent(color_ostream& out); 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; static uint32_t lastTick = 0;
//job initiated
static int32_t lastJobId = -1; static int32_t lastJobId = -1;
static map<int32_t, df::job*> prevJobs;
static set<int32_t> livingUnits; //job completed
static unordered_map<int32_t, df::job*> prevJobs;
//unit death
static unordered_set<int32_t> livingUnits;
//item creation
static int32_t nextItem; static int32_t nextItem;
//building
static int32_t nextBuilding;
static unordered_set<int32_t> buildings;
//construction
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) { 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);
//out.print("Registered listeners.\n %d", __LINE__);
}
if ( event == DFHack::SC_MAP_UNLOADED ) { if ( event == DFHack::SC_MAP_UNLOADED ) {
lastTick = 0; lastTick = 0;
lastJobId = -1; lastJobId = -1;
@ -114,6 +185,13 @@ void DFHack::EventManager::onStateChange(color_ostream& out, state_change_event
tickQueue.clear(); tickQueue.clear();
livingUnits.clear(); livingUnits.clear();
nextItem = -1; nextItem = -1;
nextBuilding = -1;
buildings.clear();
constructions.clear();
Buildings::clearBuildings(out);
gameLoaded = false;
nextInvasion = -1;
} else if ( event == DFHack::SC_MAP_LOADED ) { } else if ( event == DFHack::SC_MAP_LOADED ) {
uint32_t tick = DFHack::World::ReadCurrentYear()*ticksPerYear uint32_t tick = DFHack::World::ReadCurrentYear()*ticksPerYear
+ DFHack::World::ReadCurrentTick(); + DFHack::World::ReadCurrentTick();
@ -125,25 +203,58 @@ void DFHack::EventManager::onStateChange(color_ostream& out, state_change_event
tickQueue.insert(newTickQueue.begin(), newTickQueue.end()); tickQueue.insert(newTickQueue.begin(), newTickQueue.end());
nextItem = *df::global::item_next_id; nextItem = 0;
nextBuilding = 0;
lastTick = 0;
nextInvasion = df::global::ui->invasions.next_id;
gameLoaded = true;
} }
} }
void DFHack::EventManager::manageEvents(color_ostream& out) { void DFHack::EventManager::manageEvents(color_ostream& out) {
if ( !Core::getInstance().isWorldLoaded() ) { if ( !gameLoaded ) {
return; return;
} }
uint32_t tick = DFHack::World::ReadCurrentYear()*ticksPerYear uint32_t tick = DFHack::World::ReadCurrentYear()*ticksPerYear
+ DFHack::World::ReadCurrentTick(); + DFHack::World::ReadCurrentTick();
if ( tick <= lastTick ) if ( tick <= lastTick )
return; return;
lastTick = tick; lastTick = tick;
manageTickEvent(out); manageTickEvent(out);
manageJobInitiatedEvent(out); if ( tick - eventLastTick[EventType::JOB_INITIATED] >= (*eventFrequency[EventType::JOB_INITIATED].begin()).first ) {
manageJobCompletedEvent(out); manageJobInitiatedEvent(out);
manageUnitDeathEvent(out); eventLastTick[EventType::JOB_INITIATED] = tick;
manageItemCreationEvent(out); }
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;
}
if ( tick - eventLastTick[EventType::SYNDROME] >= (*eventFrequency[EventType::SYNDROME].begin()).first ) {
manageSyndromeEvent(out);
eventLastTick[EventType::SYNDROME] = tick;
}
if ( tick - eventLastTick[EventType::INVASION] >= (*eventFrequency[EventType::INVASION].begin()).first ) {
manageInvasionEvent(out);
eventLastTick[EventType::INVASION] = tick;
}
return; return;
} }
@ -201,7 +312,7 @@ static void manageJobCompletedEvent(color_ostream& out) {
nowJobs[link->item->id] = link->item; nowJobs[link->item->id] = link->item;
} }
for ( map<int32_t, df::job*>::iterator i = prevJobs.begin(); i != prevJobs.end(); i++ ) { for ( auto i = prevJobs.begin(); i != prevJobs.end(); i++ ) {
if ( nowJobs.find((*i).first) != nowJobs.end() ) if ( nowJobs.find((*i).first) != nowJobs.end() )
continue; continue;
@ -212,13 +323,13 @@ static void manageJobCompletedEvent(color_ostream& out) {
} }
//erase old jobs, copy over possibly altered jobs //erase old jobs, copy over possibly altered jobs
for ( map<int32_t, df::job*>::iterator i = prevJobs.begin(); i != prevJobs.end(); i++ ) { for ( auto i = prevJobs.begin(); i != prevJobs.end(); i++ ) {
Job::deleteJobStruct((*i).second); Job::deleteJobStruct((*i).second);
} }
prevJobs.clear(); prevJobs.clear();
//create new jobs //create new jobs
for ( map<int32_t, df::job*>::iterator j = nowJobs.begin(); j != nowJobs.end(); j++ ) { for ( auto j = nowJobs.begin(); j != nowJobs.end(); j++ ) {
/*map<int32_t, df::job*>::iterator i = prevJobs.find((*j).first); /*map<int32_t, df::job*>::iterator i = prevJobs.find((*j).first);
if ( i != prevJobs.end() ) { if ( i != prevJobs.end() ) {
continue; continue;
@ -289,3 +400,122 @@ static void manageItemCreationEvent(color_ostream& out) {
nextItem = *df::global::item_next_id; nextItem = *df::global::item_next_id;
} }
static void manageBuildingEvent(color_ostream& out) {
/*
* TODO: could be faster
* consider looking at jobs: building creation / destruction
**/
if ( handlers[EventType::BUILDING].empty() )
return;
multimap<Plugin*,EventHandler> copy(handlers[EventType::BUILDING].begin(), handlers[EventType::BUILDING].end());
//first alert people about new buildings
for ( int32_t a = nextBuilding; a < *df::global::building_next_id; a++ ) {
int32_t index = df::building::binsearch_index(df::global::world->buildings.all, a);
if ( index == -1 ) {
//out.print("%s, line %d: Couldn't find new building with id %d.\n", __FILE__, __LINE__, a);
//the tricky thing is that when the game first starts, it's ok to skip buildings, but otherwise, if you skip buildings, something is probably wrong. TODO: make this smarter
continue;
}
buildings.insert(a);
for ( auto b = copy.begin(); b != copy.end(); b++ ) {
EventHandler bob = (*b).second;
bob.eventHandler(out, (void*)a);
}
}
nextBuilding = *df::global::building_next_id;
//now alert people about destroyed buildings
unordered_set<int32_t> toDelete;
for ( auto a = buildings.begin(); a != buildings.end(); a++ ) {
int32_t id = *a;
int32_t index = df::building::binsearch_index(df::global::world->buildings.all,id);
if ( index != -1 )
continue;
toDelete.insert(id);
for ( auto b = copy.begin(); b != copy.end(); b++ ) {
EventHandler bob = (*b).second;
bob.eventHandler(out, (void*)id);
}
}
for ( auto a = toDelete.begin(); a != toDelete.end(); a++ ) {
int32_t id = *a;
buildings.erase(id);
}
//out.print("Sent building event.\n %d", __LINE__);
}
static void manageConstructionEvent(color_ostream& out) {
if ( handlers[EventType::CONSTRUCTION].empty() )
return;
unordered_set<df::construction*> constructionsNow(df::global::world->constructions.begin(), df::global::world->constructions.end());
multimap<Plugin*,EventHandler> copy(handlers[EventType::CONSTRUCTION].begin(), handlers[EventType::CONSTRUCTION].end());
for ( auto a = constructions.begin(); a != constructions.end(); a++ ) {
df::construction* construction = *a;
if ( constructionsNow.find(construction) != constructionsNow.end() )
continue;
for ( auto b = copy.begin(); b != copy.end(); b++ ) {
EventHandler handle = (*b).second;
handle.eventHandler(out, (void*)construction);
}
}
for ( auto a = constructionsNow.begin(); a != constructionsNow.end(); a++ ) {
df::construction* construction = *a;
if ( constructions.find(construction) != constructions.end() )
continue;
for ( auto b = copy.begin(); b != copy.end(); b++ ) {
EventHandler handle = (*b).second;
handle.eventHandler(out, (void*)construction);
}
}
constructions.clear();
constructions.insert(constructionsNow.begin(), constructionsNow.end());
}
static void manageSyndromeEvent(color_ostream& out) {
if ( handlers[EventType::SYNDROME].empty() )
return;
multimap<Plugin*,EventHandler> copy(handlers[EventType::SYNDROME].begin(), handlers[EventType::SYNDROME].end());
for ( auto a = df::global::world->units.active.begin(); a != df::global::world->units.active.end(); a++ ) {
df::unit* unit = *a;
if ( unit->flags1.bits.dead )
continue;
for ( size_t b = 0; b < unit->syndromes.active.size(); b++ ) {
df::unit_syndrome* syndrome = unit->syndromes.active[b];
uint32_t startTime = syndrome->year*ticksPerYear + syndrome->year_time;
if ( startTime <= eventLastTick[EventType::SYNDROME] )
continue;
SyndromeData data(unit->id, b);
for ( auto c = copy.begin(); c != copy.end(); c++ ) {
EventHandler handle = (*c).second;
handle.eventHandler(out, (void*)&data);
}
}
}
}
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);
}
}

@ -21,10 +21,13 @@ void jobCompleted(color_ostream& out, void* job);
void timePassed(color_ostream& out, void* ptr); void timePassed(color_ostream& out, void* ptr);
void unitDeath(color_ostream& out, void* ptr); void unitDeath(color_ostream& out, void* ptr);
void itemCreate(color_ostream& out, void* ptr); 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); command_result eventExample(color_ostream& out, vector<string>& parameters);
DFhackCExport command_result plugin_init(color_ostream &out, std::vector<PluginCommand> &commands) { DFhackCExport command_result plugin_init(color_ostream &out, std::vector<PluginCommand> &commands) {
commands.push_back(PluginCommand("eventExample", "Sets up a few event triggers.",eventExample)); commands.push_back(PluginCommand("eventExample", "Sets up a few event triggers.",eventExample));
return CR_OK; return CR_OK;
@ -36,16 +39,25 @@ command_result eventExample(color_ostream& out, vector<string>& parameters) {
EventManager::EventHandler timeHandler(timePassed); EventManager::EventHandler timeHandler(timePassed);
EventManager::EventHandler deathHandler(unitDeath); EventManager::EventHandler deathHandler(unitDeath);
EventManager::EventHandler itemHandler(itemCreate); EventManager::EventHandler itemHandler(itemCreate);
EventManager::EventHandler buildingHandler(building);
EventManager::EventHandler constructionHandler(construction);
EventManager::EventHandler syndromeHandler(syndrome);
EventManager::EventHandler invasionHandler(invasion);
Plugin* me = Core::getInstance().getPluginManager()->getPluginByName("eventExample"); Plugin* me = Core::getInstance().getPluginManager()->getPluginByName("eventExample");
EventManager::unregisterAll(me);
EventManager::registerListener(EventManager::EventType::JOB_INITIATED, initiateHandler, me); EventManager::registerListener(EventManager::EventType::JOB_INITIATED, initiateHandler, 10, me);
EventManager::registerListener(EventManager::EventType::JOB_COMPLETED, completeHandler, me); EventManager::registerListener(EventManager::EventType::JOB_COMPLETED, completeHandler, 5, 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, me); EventManager::registerListener(EventManager::EventType::UNIT_DEATH, deathHandler, 500, me);
EventManager::registerListener(EventManager::EventType::ITEM_CREATED, itemHandler, 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::INVASION, invasionHandler, 1, me);
out.print("Events registered.\n"); out.print("Events registered.\n");
return CR_OK; return CR_OK;
} }
@ -77,3 +89,20 @@ void itemCreate(color_ostream& out, void* ptr) {
out.print("Item created: %d, %s, at (%d,%d,%d)\n", (int32_t)(ptr), ENUM_KEY_STR(item_type, type).c_str(), pos.x, pos.y, pos.z); out.print("Item created: %d, %s, at (%d,%d,%d)\n", (int32_t)(ptr), ENUM_KEY_STR(item_type, type).c_str(), pos.x, pos.y, pos.z);
} }
void building(color_ostream& out, void* ptr) {
out.print("Building created/destroyed: %d\n", (int32_t)ptr);
}
void construction(color_ostream& out, void* ptr) {
out.print("Construction created/destroyed: 0x%X\n", ptr);
}
void syndrome(color_ostream& out, void* ptr) {
EventManager::SyndromeData* data = (EventManager::SyndromeData*)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);
}