From 339428872ec63e2d572a370e7d997f10a9e17369 Mon Sep 17 00:00:00 2001 From: David Cernat Date: Mon, 23 Sep 2019 21:18:38 +0300 Subject: [PATCH] [Client] Fix infinite loop in CellController MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Previously, using CellController::getCellStore() to get an unloaded CellStore would make its references get loaded in the process, with the CellStore's loadRefs() then running updateMergedRefs(), which in turn – before getting as far as setting the CellStore's state to State_Loaded – would call CellController::hasLocalAuthority() on its accompanying ESM::Cell, which would then run CellController::isActiveWorldCell(), which would then run CellController::getCellStore() to get the CellStore again, which – still being marked as unloaded – would run the whole loop again... and again. --- apps/openmw/mwbase/world.hpp | 2 +- apps/openmw/mwmp/CellController.cpp | 8 ++------ apps/openmw/mwworld/worldimp.cpp | 15 +++++++++++++-- apps/openmw/mwworld/worldimp.hpp | 2 +- 4 files changed, 17 insertions(+), 10 deletions(-) diff --git a/apps/openmw/mwbase/world.hpp b/apps/openmw/mwbase/world.hpp index fff2926f4..488b642a7 100644 --- a/apps/openmw/mwbase/world.hpp +++ b/apps/openmw/mwbase/world.hpp @@ -589,7 +589,7 @@ namespace MWBase Make it possible to check whether a cell is active */ - virtual bool isCellActive(MWWorld::CellStore* cell) = 0; + virtual bool isCellActive(const ESM::Cell& cell) = 0; /* End of tes3mp addition */ diff --git a/apps/openmw/mwmp/CellController.cpp b/apps/openmw/mwmp/CellController.cpp index 9c066ad20..af2aab6b2 100644 --- a/apps/openmw/mwmp/CellController.cpp +++ b/apps/openmw/mwmp/CellController.cpp @@ -35,7 +35,7 @@ void CellController::updateLocal(bool forceUpdate) { mwmp::Cell *mpCell = it->second; - if (!MWBase::Environment::get().getWorld()->isCellActive(mpCell->getCellStore())) + if (!MWBase::Environment::get().getWorld()->isCellActive(*mpCell->getCellStore()->getCell())) { mpCell->uninitializeLocalActors(); mpCell->uninitializeDedicatedActors(); @@ -323,11 +323,7 @@ bool CellController::isInitializedCell(const ESM::Cell& cell) bool CellController::isActiveWorldCell(const ESM::Cell& cell) { - MWWorld::CellStore *cellStore = getCellStore(cell); - - if (!cellStore) return false; - - return MWBase::Environment::get().getWorld()->isCellActive(cellStore); + return MWBase::Environment::get().getWorld()->isCellActive(cell); } Cell *CellController::getCell(const ESM::Cell& cell) diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 28293581f..360048aa9 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -2905,9 +2905,20 @@ namespace MWWorld Make it possible to check whether a cell is active */ - bool World::isCellActive(MWWorld::CellStore* cell) + bool World::isCellActive(const ESM::Cell& cell) { - return mWorldScene->isCellActive(*cell); + const Scene::CellStoreCollection& activeCells = mWorldScene->getActiveCells(); + mwmp::CellController *cellController = mwmp::Main::get().getCellController(); + + for (auto it = activeCells.begin(); it != activeCells.end(); ++it) + { + if (cellController->isSameCell(cell, *(*it)->getCell())) + { + return true; + } + } + + return false; } /* End of tes3mp addition diff --git a/apps/openmw/mwworld/worldimp.hpp b/apps/openmw/mwworld/worldimp.hpp index 33588d2e3..6ec292f4e 100644 --- a/apps/openmw/mwworld/worldimp.hpp +++ b/apps/openmw/mwworld/worldimp.hpp @@ -697,7 +697,7 @@ namespace MWWorld Make it possible to check whether a cell is active */ - bool isCellActive(MWWorld::CellStore* cell) override; + bool isCellActive(const ESM::Cell& cell) override; /* End of tes3mp addition */