From bb7588852ba0ef2a5660e71b1a6f8d50727dfcf8 Mon Sep 17 00:00:00 2001 From: Mircea TheHonestCTO Date: Sat, 27 Sep 2025 03:36:51 +0200 Subject: [PATCH] refactor AIMemory replacing `getObj` with `getObjInstance` to avoid unnecessary visibility filtering when just a simple iteration over objs is desired --- AI/Nullkiller2/AIGateway.cpp | 4 ++-- AI/Nullkiller2/Analyzers/DangerHitMapAnalyzer.cpp | 4 ++-- AI/Nullkiller2/Behaviors/ExplorationBehavior.cpp | 2 +- AI/Nullkiller2/Engine/AIMemory.cpp | 14 +++++++------- AI/Nullkiller2/Engine/AIMemory.h | 9 +++++---- AI/Nullkiller2/Pathfinding/ObjectGraph.cpp | 2 +- .../Pathfinding/ObjectGraphCalculator.cpp | 2 +- .../Pathfinding/Rules/AILayerTransitionRule.cpp | 2 +- 8 files changed, 20 insertions(+), 19 deletions(-) diff --git a/AI/Nullkiller2/AIGateway.cpp b/AI/Nullkiller2/AIGateway.cpp index 1041d9d4a..ef6362f93 100644 --- a/AI/Nullkiller2/AIGateway.cpp +++ b/AI/Nullkiller2/AIGateway.cpp @@ -1010,7 +1010,7 @@ std::vector AIGateway::getFlaggedObjects() const std::vector ret; for(const ObjectInstanceID objId : nullkiller->memory->visitableObjs) { - const CGObjectInstance * obj = cc->getObj(objId, false); + const CGObjectInstance * obj = cc->getObjInstance(objId); if(obj && obj->tempOwner == playerID) ret.push_back(obj); } @@ -1631,7 +1631,7 @@ void AIGateway::memorizeRevisitableObjs(const std::unique_ptr & memory { for(const ObjectInstanceID objId : memory->visitableObjs) { - const CGObjectInstance * obj = cc->getObj(objId, false); + const CGObjectInstance * obj = cc->getObjInstance(objId); if(obj && isWeeklyRevisitable(playerID, obj)) memory->markObjectUnvisited(obj); } diff --git a/AI/Nullkiller2/Analyzers/DangerHitMapAnalyzer.cpp b/AI/Nullkiller2/Analyzers/DangerHitMapAnalyzer.cpp index 4b5598b64..8598fa50c 100644 --- a/AI/Nullkiller2/Analyzers/DangerHitMapAnalyzer.cpp +++ b/AI/Nullkiller2/Analyzers/DangerHitMapAnalyzer.cpp @@ -90,7 +90,7 @@ void DangerHitMapAnalyzer::updateHitMap() for(const ObjectInstanceID objId : aiNk->memory->visitableObjs) { - const CGObjectInstance * obj = cc->getObj(objId, false); + const CGObjectInstance * obj = cc->getObjInstance(objId); if(!obj) continue; @@ -242,7 +242,7 @@ void DangerHitMapAnalyzer::calculateTileOwners() for(const ObjectInstanceID objId : aiNk->memory->visitableObjs) { - const CGObjectInstance * obj = cc->getObj(objId, false); + const CGObjectInstance * obj = cc->getObjInstance(objId); if(obj && obj->ID == Obj::TOWN) addTownHero(dynamic_cast(obj)); } diff --git a/AI/Nullkiller2/Behaviors/ExplorationBehavior.cpp b/AI/Nullkiller2/Behaviors/ExplorationBehavior.cpp index b17d13346..d73d75065 100644 --- a/AI/Nullkiller2/Behaviors/ExplorationBehavior.cpp +++ b/AI/Nullkiller2/Behaviors/ExplorationBehavior.cpp @@ -35,7 +35,7 @@ Goals::TGoalVec ExplorationBehavior::decompose(const Nullkiller * aiNk) const for (const ObjectInstanceID objId : aiNk->memory->visitableObjs) { - const CGObjectInstance * obj = aiNk->cc->getObj(objId, false); + const CGObjectInstance * obj = aiNk->cc->getObjInstance(objId); if(!obj) continue; diff --git a/AI/Nullkiller2/Engine/AIMemory.cpp b/AI/Nullkiller2/Engine/AIMemory.cpp index aa99d2763..91632f07c 100644 --- a/AI/Nullkiller2/Engine/AIMemory.cpp +++ b/AI/Nullkiller2/Engine/AIMemory.cpp @@ -54,7 +54,7 @@ void AIMemory::addVisitableObject(const CGObjectInstance * obj) visitableObjs.insert(obj->id); // All teleport objects seen automatically assigned to appropriate channels - if(const auto teleportObj = dynamic_cast(obj)) + if(const auto * const teleportObj = dynamic_cast(obj)) { CGTeleport::addToChannel(knownTeleportChannels, teleportObj); } @@ -91,34 +91,34 @@ bool AIMemory::wasVisited(const CGObjectInstance * obj) const return vstd::contains(alreadyVisited, obj->id); } -void AIMemory::removeInvisibleOrDeletedObjects(const CCallback & cb) +void AIMemory::removeInvisibleOrDeletedObjects(const CCallback & cc) { auto shouldBeErased = [&](const ObjectInstanceID objId) -> bool { - return !cb.getObj(objId, false); + return !cc.getObj(objId, false); }; vstd::erase_if(visitableObjs, shouldBeErased); vstd::erase_if(alreadyVisited, shouldBeErased); } -std::vector AIMemory::visitableIdsToObjsVector(const CCallback & cb) const +std::vector AIMemory::visitableIdsToObjsVector(const CCallback & cc) const { auto objs = std::vector(); for(const ObjectInstanceID objId : visitableObjs) { - if(const auto * obj = cb.getObj(objId, false)) + if(const auto * obj = cc.getObjInstance(objId)) objs.push_back(obj); } return objs; } -std::set AIMemory::visitableIdsToObjsSet(const CCallback & cb) const +std::set AIMemory::visitableIdsToObjsSet(const CCallback & cc) const { auto objs = std::set(); for(const ObjectInstanceID objId : visitableObjs) { - if(const auto * obj = cb.getObj(objId, false)) + if(const auto * obj = cc.getObjInstance(objId)) objs.insert(obj); } return objs; diff --git a/AI/Nullkiller2/Engine/AIMemory.h b/AI/Nullkiller2/Engine/AIMemory.h index e64525035..86ea9d056 100644 --- a/AI/Nullkiller2/Engine/AIMemory.h +++ b/AI/Nullkiller2/Engine/AIMemory.h @@ -30,10 +30,11 @@ public: void markObjectVisited(const CGObjectInstance * obj); void markObjectUnvisited(const CGObjectInstance * obj); bool wasVisited(const CGObjectInstance * obj) const; - void removeInvisibleOrDeletedObjects(const CCallback & cb); - // Utility method to reuse code, use visitableIds directly where possible to a - std::vector visitableIdsToObjsVector(const CCallback & cb) const; - std::set visitableIdsToObjsSet(const CCallback & cb) const; + void removeInvisibleOrDeletedObjects(const CCallback & cc); + // Utility method to reuse code, use visitableIds directly where possible to avoid time-of-check-to-time-of-use (TOCTOU) race condition + std::vector visitableIdsToObjsVector(const CCallback & cc) const; + // Utility method to reuse code, use visitableIds directly where possible to avoid time-of-check-to-time-of-use (TOCTOU) race condition + std::set visitableIdsToObjsSet(const CCallback & cc) const; }; } diff --git a/AI/Nullkiller2/Pathfinding/ObjectGraph.cpp b/AI/Nullkiller2/Pathfinding/ObjectGraph.cpp index a69826c69..353bfebf4 100644 --- a/AI/Nullkiller2/Pathfinding/ObjectGraph.cpp +++ b/AI/Nullkiller2/Pathfinding/ObjectGraph.cpp @@ -96,7 +96,7 @@ void ObjectGraph::connectHeroes(const Nullkiller * aiNk) { for(const ObjectInstanceID objId : aiNk->memory->visitableObjs) { - const CGObjectInstance * obj = aiNk->cc->getObj(objId, false); + const CGObjectInstance * obj = aiNk->cc->getObjInstance(objId); if(obj && obj->ID == Obj::HERO) { addObject(obj); diff --git a/AI/Nullkiller2/Pathfinding/ObjectGraphCalculator.cpp b/AI/Nullkiller2/Pathfinding/ObjectGraphCalculator.cpp index ce80e4e9b..b9ab42008 100644 --- a/AI/Nullkiller2/Pathfinding/ObjectGraphCalculator.cpp +++ b/AI/Nullkiller2/Pathfinding/ObjectGraphCalculator.cpp @@ -29,7 +29,7 @@ void ObjectGraphCalculator::setGraphObjects() { for(const ObjectInstanceID objId : aiNk->memory->visitableObjs) { - const CGObjectInstance * obj = aiNk->cc->getObj(objId, false); + const CGObjectInstance * obj = aiNk->cc->getObjInstance(objId); if(obj && obj->isVisitable() && obj->ID != Obj::HERO && obj->ID != Obj::EVENT) { addObjectActor(obj); diff --git a/AI/Nullkiller2/Pathfinding/Rules/AILayerTransitionRule.cpp b/AI/Nullkiller2/Pathfinding/Rules/AILayerTransitionRule.cpp index 49d788b1a..e2ee1959d 100644 --- a/AI/Nullkiller2/Pathfinding/Rules/AILayerTransitionRule.cpp +++ b/AI/Nullkiller2/Pathfinding/Rules/AILayerTransitionRule.cpp @@ -147,7 +147,7 @@ namespace AIPathfinding for(const ObjectInstanceID objId : aiNk->memory->visitableObjs) { - const CGObjectInstance * obj = aiNk->cc->getObj(objId, false); + const CGObjectInstance * obj = aiNk->cc->getObjInstance(objId); if(obj && obj->ID != Obj::TOWN) //towns were handled in the previous loop { if(const auto * shipyard = dynamic_cast(obj))