From 19695b4ee7e8b370c8ce53aa2dcd399e1e9ca94d Mon Sep 17 00:00:00 2001 From: lethosor Date: Fri, 17 Feb 2017 22:53:48 -0500 Subject: [PATCH] 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 --- library/modules/Buildings.cpp | 92 ++++++++++++++++---------------- library/modules/EventManager.cpp | 6 +-- plugins/eventful.cpp | 6 +-- 3 files changed, 52 insertions(+), 52 deletions(-) diff --git a/library/modules/Buildings.cpp b/library/modules/Buildings.cpp index 9d672cd58..55f0869a4 100644 --- a/library/modules/Buildings.cpp +++ b/library/modules/Buildings.cpp @@ -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 *items) diff --git a/library/modules/EventManager.cpp b/library/modules/EventManager.cpp index dfb978022..e2baf9bfb 100644 --- a/library/modules/EventManager.cpp +++ b/library/modules/EventManager.cpp @@ -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); } diff --git a/plugins/eventful.cpp b/plugins/eventful.cpp index 14f1ec26e..365542314 100644 --- a/plugins/eventful.cpp +++ b/plugins/eventful.cpp @@ -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,