diff options
| author | Alexander Gavrilov | 2012-09-13 17:49:41 +0400 |
|---|---|---|
| committer | Alexander Gavrilov | 2012-09-13 17:49:41 +0400 |
| commit | 5690a26439c275995f48f60a3a7ba18c86e2c083 (patch) | |
| tree | 9aa6f1a883f50d69242ce94edfda9532a6539a49 /plugins/devel | |
| parent | c9d73cb6fb846a7e1b5befcb13d1712c0cce831a (diff) | |
| download | dfhack-5690a26439c275995f48f60a3a7ba18c86e2c083.tar.gz dfhack-5690a26439c275995f48f60a3a7ba18c86e2c083.tar.bz2 dfhack-5690a26439c275995f48f60a3a7ba18c86e2c083.tar.xz | |
On second thought, remove stockpile->engine links; keep only reverse.
Bi-directional links involve the risk of crashes if the plugin
is unloaded, and the engine subsequently deconstructed.
Diffstat (limited to 'plugins/devel')
| -rw-r--r-- | plugins/devel/siege-engine.cpp | 120 |
1 files changed, 34 insertions, 86 deletions
diff --git a/plugins/devel/siege-engine.cpp b/plugins/devel/siege-engine.cpp index b41ac931..3e5777e5 100644 --- a/plugins/devel/siege-engine.cpp +++ b/plugins/devel/siege-engine.cpp @@ -200,8 +200,6 @@ struct EngineInfo { static std::map<df::building*, EngineInfo*> engines; static std::map<df::coord, df::building*> coord_engines; -static std::set<df::building*> recheck_piles; - static EngineInfo *find_engine(df::building *bld, bool create = false) { auto ebld = strict_virtual_cast<df::building_siegeenginest>(bld); @@ -276,7 +274,6 @@ static void clear_engines() delete it->second; engines.clear(); coord_engines.clear(); - recheck_piles.clear(); } static void load_engines() @@ -316,14 +313,8 @@ static void load_engines() pworld->DeletePersistentData(*it); continue;; } - auto plinks = pile->getStockpileLinks(); - if (!plinks) - continue; engine->stockpiles.insert(it->ival(1)); - - insert_into_vector(engine->links.take_from_pile, &df::building::id, pile); - insert_into_vector(plinks->give_to_workshop, &df::building::id, (df::building*)engine->bld); } } @@ -437,21 +428,47 @@ static int setAmmoItem(lua_State *L) return 1; } +static void forgetStockpileLink(EngineInfo *engine, int pile_id) +{ + engine->stockpiles.erase(pile_id); + + auto pworld = Core::getInstance().getWorld(); + auto key = stl_sprintf("siege-engine/stockpiles/%d/%d", engine->id, pile_id); + pworld->DeletePersistentData(pworld->GetPersistentData(key)); +} + +static void update_stockpile_links(EngineInfo *engine) +{ + engine->links.take_from_pile.clear(); + + for (auto it = engine->stockpiles.begin(); it != engine->stockpiles.end(); ) + { + int id = *it; ++it; + auto pile = df::building::find(id); + + if (!pile || pile->getType() != building_type::Stockpile) + forgetStockpileLink(engine, id); + else + // The vector is sorted, but we are iterating through a sorted set + engine->links.take_from_pile.push_back(pile); + } +} + static int getStockpileLinks(lua_State *L) { auto engine = find_engine(L, 1, false, true); if (!engine || engine->stockpiles.empty()) return 0; - int idx = 1; - lua_createtable(L, engine->stockpiles.size(), 0); + update_stockpile_links(engine); + + auto &links = engine->links.take_from_pile; + lua_createtable(L, links.size(), 0); - for (auto it = engine->stockpiles.begin(); it != engine->stockpiles.end(); ++it) + for (size_t i = 0; i < links.size(); i++) { - auto pile = df::building::find(*it); - if (!pile) continue; - Lua::Push(L, pile); - lua_rawseti(L, -2, idx++); + Lua::Push(L, links[i]); + lua_rawseti(L, -2, i+1); } return 1; @@ -472,9 +489,6 @@ static bool addStockpileLink(df::building_siegeenginest *bld, df::building_stock CHECK_NULL_POINTER(bld); CHECK_NULL_POINTER(pile); - auto plinks = pile->getStockpileLinks(); - CHECK_NULL_POINTER(plinks); - if (!enable_plugin()) return false; @@ -490,21 +504,9 @@ static bool addStockpileLink(df::building_siegeenginest *bld, df::building_stock entry.ival(1) = pile->id; engine->stockpiles.insert(pile->id); - - insert_into_vector(engine->links.take_from_pile, &df::building::id, (df::building*)pile); - insert_into_vector(plinks->give_to_workshop, &df::building::id, (df::building*)engine->bld); return true; } -static void forgetStockpileLink(EngineInfo *engine, int pile_id) -{ - engine->stockpiles.erase(pile_id); - - auto pworld = Core::getInstance().getWorld(); - auto key = stl_sprintf("siege-engine/stockpiles/%d/%d", engine->id, pile_id); - pworld->DeletePersistentData(pworld->GetPersistentData(key)); -} - static bool removeStockpileLink(df::building_siegeenginest *bld, df::building_stockpilest *pile) { CHECK_NULL_POINTER(bld); @@ -513,47 +515,12 @@ static bool removeStockpileLink(df::building_siegeenginest *bld, df::building_st if (auto engine = find_engine(bld)) { forgetStockpileLink(engine, pile->id); - - auto plinks = pile->getStockpileLinks(); - erase_from_vector(engine->links.take_from_pile, &df::building::id, pile->id); - erase_from_vector(plinks->give_to_workshop, &df::building::id, bld->id); return true; } return false; } -static void recheck_pile_links(color_ostream &out, EngineInfo *engine) -{ - auto removed = engine->stockpiles; - - out.print("rechecking piles in %d\n", engine->id); - - // Detect and save changes in take links - for (size_t i = 0; i < engine->links.take_from_pile.size(); i++) - { - auto pile = engine->links.take_from_pile[i]; - - removed.erase(pile->id); - - if (!engine->stockpiles.count(pile->id)) - addStockpileLink(engine->bld, (df::building_stockpilest*)pile); - } - - for (auto it = removed.begin(); it != removed.end(); it++) - forgetStockpileLink(engine, *it); - - // Remove give links - for (size_t i = 0; i < engine->links.give_to_pile.size(); i++) - { - auto pile = engine->links.give_to_pile[i]; - auto plinks = pile->getStockpileLinks(); - erase_from_vector(plinks->take_from_workshop, &df::building::id, engine->id); - } - - engine->links.give_to_pile.clear(); -} - static int getOperatorSkill(df::building_siegeenginest *bld, bool force = false) { CHECK_NULL_POINTER(bld); @@ -1396,19 +1363,11 @@ IMPLEMENT_VMETHOD_INTERPOSE(projectile_hook, checkImpact); struct building_hook : df::building_siegeenginest { typedef df::building_siegeenginest interpose_base; - DEFINE_VMETHOD_INTERPOSE(bool, canLinkToStockpile, ()) - { - if (find_engine(this, true)) - return true; - - return INTERPOSE_NEXT(canLinkToStockpile)(); - } - DEFINE_VMETHOD_INTERPOSE(df::stockpile_links*, getStockpileLinks, ()) { if (auto engine = find_engine(this)) { - recheck_piles.insert(this); + update_stockpile_links(engine); return &engine->links; } @@ -1476,7 +1435,6 @@ struct building_hook : df::building_siegeenginest { } }; -IMPLEMENT_VMETHOD_INTERPOSE(building_hook, canLinkToStockpile); IMPLEMENT_VMETHOD_INTERPOSE(building_hook, getStockpileLinks); IMPLEMENT_VMETHOD_INTERPOSE(building_hook, updateAction); @@ -1522,7 +1480,6 @@ static void enable_hooks(bool enable) INTERPOSE_HOOK(projectile_hook, checkMovement).apply(enable); INTERPOSE_HOOK(projectile_hook, checkImpact).apply(enable); - INTERPOSE_HOOK(building_hook, canLinkToStockpile).apply(enable); INTERPOSE_HOOK(building_hook, getStockpileLinks).apply(enable); INTERPOSE_HOOK(building_hook, updateAction).apply(enable); @@ -1555,15 +1512,6 @@ static void clear_caches(color_ostream &out) UnitPath::cache.clear(); } - - if (!recheck_piles.empty()) - { - for (auto it = recheck_piles.begin(); it != recheck_piles.end(); ++it) - if (auto engine = find_engine(*it)) - recheck_pile_links(out, engine); - - recheck_piles.clear(); - } } DFhackCExport command_result plugin_onstatechange(color_ostream &out, state_change_event event) |
