EventManager/eventful: Pass building ID pointers to event handlers

Previously, there was some disagreement over whether event handlers such as
Buildings::updateBuildings() took building pointers or building IDs shoved
into pointers. It turned out to be the latter, which, unfortunately, did not
compile on x64. Passing building IDs isn't possible in all cases, because
building event handlers can be called for recently-deleted buildings too.
Pointers to building IDs do work reliably, though.

Fixes #1003
develop
lethosor 2017-02-17 22:53:48 -05:00
parent 33060c7d0e
commit 19695b4ee7
3 changed files with 52 additions and 52 deletions

@ -1182,52 +1182,52 @@ void Buildings::clearBuildings(color_ostream& out) {
void Buildings::updateBuildings(color_ostream& out, void* ptr)
{
// int32_t id = (int32_t)ptr;
// auto building = df::building::find(id);
// if (building)
// {
// // Already cached -> weird, so bail out
// if (corner1.count(id))
// return;
// // Civzones cannot be cached because they can
// // overlap each other and normal buildings.
// if (!building->isSettingOccupancy())
// return;
// 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);
// if (containsTile(building, pt, false))
// locationToBuilding[pt] = id;
// }
// }
// }
// else if (corner1.count(id))
// {
// //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);
// auto cur = locationToBuilding.find(pt);
// if (cur != locationToBuilding.end() && cur->second == id)
// locationToBuilding.erase(cur);
// }
// }
// corner1.erase(id);
// corner2.erase(id);
// }
int32_t id = *((int32_t*)ptr);
auto building = df::building::find(id);
if (building)
{
// Already cached -> weird, so bail out
if (corner1.count(id))
return;
// Civzones cannot be cached because they can
// overlap each other and normal buildings.
if (!building->isSettingOccupancy())
return;
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);
if (containsTile(building, pt, false))
locationToBuilding[pt] = id;
}
}
}
else if (corner1.count(id))
{
//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);
auto cur = locationToBuilding.find(pt);
if (cur != locationToBuilding.end() && cur->second == id)
locationToBuilding.erase(cur);
}
}
corner1.erase(id);
corner2.erase(id);
}
}
void Buildings::getStockpileContents(df::building_stockpilest *stockpile, std::vector<df::item*> *items)

@ -273,7 +273,7 @@ void DFHack::EventManager::onStateChange(color_ostream& out, state_change_event
}
for ( size_t a = 0; a < df::global::world->buildings.all.size(); a++ ) {
df::building* b = df::global::world->buildings.all[a];
Buildings::updateBuildings(out, (void*)b);
Buildings::updateBuildings(out, (void*)&(b->id));
buildings.insert(b->id);
}
lastSyndromeTime = -1;
@ -609,7 +609,7 @@ static void manageBuildingEvent(color_ostream& out) {
buildings.insert(a);
for ( auto b = copy.begin(); b != copy.end(); b++ ) {
EventHandler bob = (*b).second;
bob.eventHandler(out, (void*)intptr_t(a));
bob.eventHandler(out, (void*)&a);
}
}
nextBuilding = *df::global::building_next_id;
@ -625,7 +625,7 @@ static void manageBuildingEvent(color_ostream& out) {
for ( auto b = copy.begin(); b != copy.end(); b++ ) {
EventHandler bob = (*b).second;
bob.eventHandler(out, (void*)intptr_t(id));
bob.eventHandler(out, (void*)&id);
}
a = buildings.erase(a);
}

@ -183,8 +183,8 @@ void ev_mng_invasion(color_ostream& out, void* ptr)
}
static void ev_mng_building(color_ostream& out, void* ptr)
{
int32_t myId=*(int32_t*)&ptr;
onBuildingCreatedDestroyed(out,myId);
int32_t id = *((int32_t*)ptr);
onBuildingCreatedDestroyed(out, id);
}
static void ev_mng_inventory(color_ostream& out, void* ptr)
{
@ -289,7 +289,7 @@ IMPLEMENT_VMETHOD_INTERPOSE(furnace_hook, fillSidebarMenu);
struct product_hook : item_product {
typedef item_product interpose_base;
DEFINE_VMETHOD_INTERPOSE(
void, produce,
(df::unit *unit,