From 7136329a946932b142945a9fa9ef45749aacfbd0 Mon Sep 17 00:00:00 2001 From: David Cernat Date: Fri, 27 Jul 2018 21:42:08 +0300 Subject: [PATCH] [Client] Add World::updatePtrsWithRefId() method This makes it possible to "reload" the Ptrs in active cells when changes happen to the ESM record that they are based on. In practice, the old Ptrs are deleted, their RefNums and MpNums are blanked out, and new Ptrs are created that use the same RefNum and MpNum as before. The above has required me to also add a method called setRefNum() to CellRef to allow setting a RefNum on the fly. There may be a more elegant implementation available for updatePtrsWithRefIds(), but it requires additional research. --- apps/openmw/mwbase/world.hpp | 10 +++++++ apps/openmw/mwworld/cellref.cpp | 17 +++++++++++- apps/openmw/mwworld/cellref.hpp | 12 ++++++++ apps/openmw/mwworld/worldimp.cpp | 47 ++++++++++++++++++++++++++++++++ apps/openmw/mwworld/worldimp.hpp | 10 +++++++ 5 files changed, 95 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwbase/world.hpp b/apps/openmw/mwbase/world.hpp index fc99aa91a..dc8c716d9 100644 --- a/apps/openmw/mwbase/world.hpp +++ b/apps/openmw/mwbase/world.hpp @@ -204,6 +204,16 @@ namespace MWBase End of tes3mp addition */ + /* + Start of tes3mp addition + + Make it possible to update all Ptrs in active cells that have a certain refId + */ + virtual void updatePtrsWithRefId(std::string refId) = 0; + /* + End of tes3mp addition + */ + virtual MWWorld::Ptr findContainer (const MWWorld::ConstPtr& ptr) = 0; ///< Return a pointer to a liveCellRef which contains \a ptr. /// \note Search is limited to the active cells. diff --git a/apps/openmw/mwworld/cellref.cpp b/apps/openmw/mwworld/cellref.cpp index 70f97a612..3ade46a2c 100644 --- a/apps/openmw/mwworld/cellref.cpp +++ b/apps/openmw/mwworld/cellref.cpp @@ -23,7 +23,22 @@ namespace MWWorld /* Start of tes3mp addition - Get the mMpNum (unique multiplayer reference number) of a CellRef + Set the unique reference number index of a CellRef, needed to + make objects retain their uniqueIndex when they are updated + after their records are modified on the fly by the server + */ + void CellRef::setRefNum(unsigned int index) + { + mCellRef.mRefNum.mIndex = index; + } + /* + End of tes3mp addition + */ + + /* + Start of tes3mp addition + + Get the mMpNum (unique multiplayer number) of a CellRef */ unsigned int CellRef::getMpNum() const { diff --git a/apps/openmw/mwworld/cellref.hpp b/apps/openmw/mwworld/cellref.hpp index b811e3ac9..af4c12bff 100644 --- a/apps/openmw/mwworld/cellref.hpp +++ b/apps/openmw/mwworld/cellref.hpp @@ -28,6 +28,18 @@ namespace MWWorld // Set RefNum to its default state. void unsetRefNum(); + /* + Start of tes3mp addition + + Set the unique reference number index of a CellRef, needed to + make objects retain their uniqueIndex when they are updated + after their records are modified on the fly by the server + */ + void CellRef::setRefNum(unsigned int index); + /* + End of tes3mp addition + */ + /* Start of tes3mp addition diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 3d7143a60..2a6e5dda2 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -766,6 +766,53 @@ namespace MWWorld End of tes3mp addition */ + /* + Start of tes3mp addition + + Make it possible to update all Ptrs in active cells that have a certain refId + */ + void World::updatePtrsWithRefId(std::string refId) + { + for (Scene::CellStoreCollection::const_iterator iter(mWorldScene->getActiveCells().begin()); + iter != mWorldScene->getActiveCells().end(); ++iter) + { + CellStore* cellStore = *iter; + + for (auto &mergedRef : cellStore->getMergedRefs()) + { + if (Misc::StringUtils::ciEqual(refId, mergedRef->mRef.getRefId())) + { + MWWorld::Ptr ptr(mergedRef, cellStore); + + const ESM::Position* position = &ptr.getRefData().getPosition(); + const unsigned int refNum = ptr.getCellRef().getRefNum().mIndex; + const unsigned int mpNum = ptr.getCellRef().getMpNum(); + + deleteObject(ptr); + ptr.getCellRef().unsetRefNum(); + ptr.getCellRef().setMpNum(0); + + MWWorld::ManualRef* reference = new MWWorld::ManualRef(getStore(), refId, 1); + MWWorld::Ptr newPtr = placeObject(reference->getPtr(), cellStore, *position); + newPtr.getCellRef().setRefNum(refNum); + newPtr.getCellRef().setMpNum(mpNum); + + // Update Ptrs for LocalActors and DedicatedActors + if (newPtr.getClass().isActor()) + { + if (mwmp::Main::get().getCellController()->isLocalActor(refNum, mpNum)) + mwmp::Main::get().getCellController()->getLocalActor(refNum, mpNum)->setPtr(newPtr); + else if (mwmp::Main::get().getCellController()->isDedicatedActor(refNum, mpNum)) + mwmp::Main::get().getCellController()->getDedicatedActor(refNum, mpNum)->setPtr(newPtr); + } + } + } + } + } + /* + End of tes3mp addition + */ + struct FindContainerVisitor { ConstPtr mContainedPtr; diff --git a/apps/openmw/mwworld/worldimp.hpp b/apps/openmw/mwworld/worldimp.hpp index 7af5ff33a..6a455d049 100644 --- a/apps/openmw/mwworld/worldimp.hpp +++ b/apps/openmw/mwworld/worldimp.hpp @@ -311,6 +311,16 @@ namespace MWWorld End of tes3mp addition */ + /* + Start of tes3mp addition + + Make it possible to update all Ptrs in active cells that have a certain refId + */ + void updatePtrsWithRefId(std::string refId) override; + /* + End of tes3mp addition + */ + MWWorld::Ptr findContainer (const MWWorld::ConstPtr& ptr) override; ///< Return a pointer to a liveCellRef which contains \a ptr. /// \note Search is limited to the active cells.