EventManager: added construction and building events.

develop
expwnent 2012-12-18 18:34:38 -05:00
parent 78aab90f3a
commit 555c754636
3 changed files with 127 additions and 7 deletions

@ -17,6 +17,8 @@ namespace DFHack {
JOB_COMPLETED, JOB_COMPLETED,
UNIT_DEATH, UNIT_DEATH,
ITEM_CREATED, ITEM_CREATED,
BUILDING,
CONSTRUCTION,
EVENT_MAX EVENT_MAX
}; };
} }

@ -4,6 +4,8 @@
#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"
@ -11,9 +13,10 @@
#include "df/unit.h" #include "df/unit.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,11 +24,13 @@ 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];
const uint32_t ticksPerYear = 403200; const uint32_t ticksPerYear = 403200;
@ -96,13 +101,31 @@ 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);
//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;
void DFHack::EventManager::onStateChange(color_ostream& out, state_change_event event) { void DFHack::EventManager::onStateChange(color_ostream& out, state_change_event event) {
if ( event == DFHack::SC_MAP_UNLOADED ) { if ( event == DFHack::SC_MAP_UNLOADED ) {
lastTick = 0; lastTick = 0;
@ -114,6 +137,9 @@ 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();
} 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();
@ -126,6 +152,8 @@ 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 = *df::global::item_next_id;
nextBuilding = *df::global::building_next_id;
constructions.insert(df::global::world->constructions.begin(), df::global::world->constructions.end());
} }
} }
@ -144,6 +172,8 @@ void DFHack::EventManager::manageEvents(color_ostream& out) {
manageJobCompletedEvent(out); manageJobCompletedEvent(out);
manageUnitDeathEvent(out); manageUnitDeathEvent(out);
manageItemCreationEvent(out); manageItemCreationEvent(out);
manageBuildingEvent(out);
manageConstructionEvent(out);
return; return;
} }
@ -201,7 +231,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 +242,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 +319,77 @@ 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::ITEM_CREATED].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);
}
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);
}
}
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());
}

@ -21,6 +21,8 @@ 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);
command_result eventExample(color_ostream& out, vector<string>& parameters); command_result eventExample(color_ostream& out, vector<string>& parameters);
@ -36,7 +38,10 @@ 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);
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, me);
EventManager::registerListener(EventManager::EventType::JOB_COMPLETED, completeHandler, me); EventManager::registerListener(EventManager::EventType::JOB_COMPLETED, completeHandler, me);
@ -46,6 +51,8 @@ command_result eventExample(color_ostream& out, vector<string>& parameters) {
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, me);
EventManager::registerListener(EventManager::EventType::ITEM_CREATED, itemHandler, me); EventManager::registerListener(EventManager::EventType::ITEM_CREATED, itemHandler, me);
EventManager::registerListener(EventManager::EventType::BUILDING, buildingHandler, me);
EventManager::registerListener(EventManager::EventType::CONSTRUCTION, constructionHandler, me);
out.print("Events registered.\n"); out.print("Events registered.\n");
return CR_OK; return CR_OK;
} }
@ -77,3 +84,10 @@ 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);
}