From 270ead937b5f774c2587f6332b77c86ecc401075 Mon Sep 17 00:00:00 2001 From: Petr Mikheev Date: Tue, 9 May 2023 23:57:32 +0200 Subject: [PATCH 1/3] Remove check in cellstore.cpp that causes Lua teleport command to fail. --- apps/openmw/mwworld/cellstore.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/apps/openmw/mwworld/cellstore.cpp b/apps/openmw/mwworld/cellstore.cpp index cb2063a45e..ff3845e9a2 100644 --- a/apps/openmw/mwworld/cellstore.cpp +++ b/apps/openmw/mwworld/cellstore.cpp @@ -443,10 +443,6 @@ namespace MWWorld throw std::runtime_error( "moveTo: can't move object from a non-loaded cell (how did you get this object anyway?)"); - // Ensure that the object actually exists in the cell - if (searchViaRefNum(object.getCellRef().getRefNum()).isEmpty()) - throw std::runtime_error("moveTo: object is not in this cell"); - MWBase::Environment::get().getWorldModel()->registerPtr(MWWorld::Ptr(object.getBase(), cellToMoveTo)); MovedRefTracker::iterator found = mMovedHere.find(object.getBase()); From 93342af1f9a426d02ee24c54b8850fc1cd1a2e2c Mon Sep 17 00:00:00 2001 From: Petr Mikheev Date: Thu, 11 May 2023 00:16:29 +0200 Subject: [PATCH 2/3] Remove CellStore::searchViaRefNum (replaced with WorldModel::getPtr) --- apps/openmw/mwworld/cellstore.cpp | 9 +-------- apps/openmw/mwworld/cellstore.hpp | 5 ----- apps/openmw/mwworld/worldimp.cpp | 18 ++---------------- 3 files changed, 3 insertions(+), 29 deletions(-) diff --git a/apps/openmw/mwworld/cellstore.cpp b/apps/openmw/mwworld/cellstore.cpp index ff3845e9a2..00be811137 100644 --- a/apps/openmw/mwworld/cellstore.cpp +++ b/apps/openmw/mwworld/cellstore.cpp @@ -655,13 +655,6 @@ namespace MWWorld } }; - Ptr CellStore::searchViaRefNum(const ESM::RefNum& refNum) - { - RefNumSearchVisitor searchVisitor(refNum); - forEach(searchVisitor); - return searchVisitor.mFound; - } - float CellStore::getWaterLevel() const { if (isExterior()) @@ -1046,7 +1039,7 @@ namespace MWWorld } // Search for the reference. It might no longer exist if its content file was removed. - Ptr movedRef = searchViaRefNum(refnum); + Ptr movedRef = MWBase::Environment::get().getWorldModel()->getPtr(refnum); if (movedRef.isEmpty()) { Log(Debug::Warning) << "Warning: Dropping moved ref tag for " << refnum.mIndex diff --git a/apps/openmw/mwworld/cellstore.hpp b/apps/openmw/mwworld/cellstore.hpp index 0cc06f4d2f..47c15edfee 100644 --- a/apps/openmw/mwworld/cellstore.hpp +++ b/apps/openmw/mwworld/cellstore.hpp @@ -166,11 +166,6 @@ namespace MWWorld Ptr searchViaActorId(int id); ///< Will return an empty Ptr if cell is not loaded. - Ptr searchViaRefNum(const ESM::RefNum& refNum); - ///< Will return an empty Ptr if cell is not loaded. Does not check references in - /// containers. - /// @note Triggers CellStore hasState flag. - float getWaterLevel() const; bool movedHere(const MWWorld::Ptr& ptr) const; diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 21ed7a6ee4..8c13a9a4c0 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -1880,14 +1880,7 @@ namespace MWWorld facedObject = rayToObject.mHitObject; if (facedObject.isEmpty() && rayToObject.mHitRefnum.isSet()) - { - for (CellStore* cellstore : mWorldScene->getActiveCells()) - { - facedObject = cellstore->searchViaRefNum(rayToObject.mHitRefnum); - if (!facedObject.isEmpty()) - break; - } - } + facedObject = MWBase::Environment::get().getWorldModel()->getPtr(rayToObject.mHitRefnum); if (rayToObject.mHit) mDistanceToFacedObject = (rayToObject.mRatio * maxDistance) - camDist; else @@ -1904,14 +1897,7 @@ namespace MWWorld res.mHitNormal = rayRes.mHitNormalWorld; res.mHitObject = rayRes.mHitObject; if (res.mHitObject.isEmpty() && rayRes.mHitRefnum.isSet()) - { - for (CellStore* cellstore : mWorldScene->getActiveCells()) - { - res.mHitObject = cellstore->searchViaRefNum(rayRes.mHitRefnum); - if (!res.mHitObject.isEmpty()) - break; - } - } + res.mHitObject = MWBase::Environment::get().getWorldModel()->getPtr(rayRes.mHitRefnum); return res.mHit; } From f3adcab9c54a71a4e5f91d0db9b46fa504796210 Mon Sep 17 00:00:00 2001 From: Petr Mikheev Date: Thu, 11 May 2023 01:00:50 +0200 Subject: [PATCH 3/3] Update CellStore::mMergedRefs lazily. --- apps/openmw/mwworld/cellstore.cpp | 26 +++++++++++++++----------- apps/openmw/mwworld/cellstore.hpp | 15 ++++++++++++--- 2 files changed, 27 insertions(+), 14 deletions(-) diff --git a/apps/openmw/mwworld/cellstore.cpp b/apps/openmw/mwworld/cellstore.cpp index 00be811137..2c5ab8d3ea 100644 --- a/apps/openmw/mwworld/cellstore.cpp +++ b/apps/openmw/mwworld/cellstore.cpp @@ -430,7 +430,7 @@ namespace MWWorld { mMovedHere.insert(std::make_pair(object.getBase(), from)); } - updateMergedRefs(); + requestMergedRefsUpdate(); } MWWorld::Ptr CellStore::moveTo(const Ptr& object, CellStore* cellToMoveTo) @@ -462,14 +462,14 @@ namespace MWWorld originalCell->moveTo(object, cellToMoveTo); } - updateMergedRefs(); + requestMergedRefsUpdate(); return MWWorld::Ptr(object.getBase(), cellToMoveTo); } cellToMoveTo->moveFrom(object, this); mMovedToAnotherCell.insert(std::make_pair(object.getBase(), cellToMoveTo)); - updateMergedRefs(); + requestMergedRefsUpdate(); MWWorld::Ptr ptr(object.getBase(), cellToMoveTo); const Class& cls = ptr.getClass(); if (cls.hasInventoryStore(ptr)) @@ -509,13 +509,19 @@ namespace MWWorld const std::map& mMovedToAnotherCell; }; - void CellStore::updateMergedRefs() + void CellStore::requestMergedRefsUpdate() { - mMergedRefs.clear(); mRechargingItemsUpToDate = false; + mMergedRefsNeedsUpdate = true; + } + + void CellStore::updateMergedRefs() const + { + mMergedRefs.clear(); MergeVisitor visitor(mMergedRefs, mMovedHere, mMovedToAnotherCell); - CellStoreImp::forEachInternal(visitor, *this); + CellStoreImp::forEachInternal(visitor, const_cast(*this)); visitor.merge(); + mMergedRefsNeedsUpdate = false; } bool CellStore::movedHere(const MWWorld::Ptr& ptr) const @@ -670,6 +676,8 @@ namespace MWWorld std::size_t CellStore::count() const { + if (mMergedRefsNeedsUpdate) + updateMergedRefs(); return mMergedRefs.size(); } @@ -836,7 +844,7 @@ namespace MWWorld ESM::visit([&](auto&& cell) { loadRefs(cell, refNumToID); }, mCellVariant); - updateMergedRefs(); + requestMergedRefsUpdate(); } bool CellStore::isExterior() const @@ -1022,10 +1030,6 @@ namespace MWWorld } } - // Do another update here to make sure objects referred to by MVRF tags can be found - // This update is only needed for old saves that used the old copy&delete way of moving objects - updateMergedRefs(); - while (reader.isNextSub("MVRF")) { reader.cacheSubName(); diff --git a/apps/openmw/mwworld/cellstore.hpp b/apps/openmw/mwworld/cellstore.hpp index 47c15edfee..7bbdf0c4cd 100644 --- a/apps/openmw/mwworld/cellstore.hpp +++ b/apps/openmw/mwworld/cellstore.hpp @@ -128,7 +128,7 @@ namespace MWWorld mHasState = true; CellRefList& list = get(); LiveCellRefBase* ret = &list.insert(*ref); - updateMergedRefs(); + requestMergedRefsUpdate(); return ret; } @@ -198,6 +198,8 @@ namespace MWWorld if (mState != State_Loaded) return false; + if (mMergedRefsNeedsUpdate) + updateMergedRefs(); if (mMergedRefs.empty()) return true; @@ -225,6 +227,9 @@ namespace MWWorld if (mState != State_Loaded) return false; + if (mMergedRefsNeedsUpdate) + updateMergedRefs(); + for (unsigned int i = 0; i < mMergedRefs.size(); ++i) { if (!isAccessible(mMergedRefs[i]->mData, mMergedRefs[i]->mRef)) @@ -247,6 +252,8 @@ namespace MWWorld if (mState != State_Loaded) return false; + if (mMergedRefsNeedsUpdate) + updateMergedRefs(); if (mMergedRefs.empty()) return true; @@ -368,7 +375,8 @@ namespace MWWorld // Merged list of ref's currently in this cell - i.e. with added refs from mMovedHere, removed refs from // mMovedToAnotherCell - std::vector mMergedRefs; + mutable std::vector mMergedRefs; + mutable bool mMergedRefsNeedsUpdate = false; // Get the Ptr for the given ref which originated from this cell (possibly moved to another cell at this point). Ptr getCurrentPtr(MWWorld::LiveCellRefBase* ref); @@ -377,7 +385,8 @@ namespace MWWorld void moveFrom(const MWWorld::Ptr& object, MWWorld::CellStore* from); /// Repopulate mMergedRefs. - void updateMergedRefs(); + void requestMergedRefsUpdate(); + void updateMergedRefs() const; // (item, max charge) typedef std::vector> TRechargingItems;