From d998faec1b5c14dbd3f2652a551c631d635f045c Mon Sep 17 00:00:00 2001 From: elsid Date: Sat, 15 Jun 2024 00:30:14 +0200 Subject: [PATCH] Deregister only registered LiveCellRefBase --- apps/openmw/mwworld/livecellref.cpp | 20 +++++++++++++++++++- apps/openmw/mwworld/livecellref.hpp | 12 ++++++++++++ apps/openmw/mwworld/worldmodel.cpp | 15 +++++++++++++++ apps/openmw/mwworld/worldmodel.hpp | 4 ++-- 4 files changed, 48 insertions(+), 3 deletions(-) diff --git a/apps/openmw/mwworld/livecellref.cpp b/apps/openmw/mwworld/livecellref.cpp index 5623083de7..aaa74f5ef3 100644 --- a/apps/openmw/mwworld/livecellref.cpp +++ b/apps/openmw/mwworld/livecellref.cpp @@ -38,9 +38,27 @@ namespace MWWorld { } + LiveCellRefBase::LiveCellRefBase(LiveCellRefBase&& other) noexcept + : mClass(other.mClass) + , mRef(std::move(other.mRef)) + , mData(std::move(other.mData)) + , mWorldModel(std::exchange(other.mWorldModel, nullptr)) + { + } + LiveCellRefBase::~LiveCellRefBase() { - MWBase::Environment::get().getWorldModel()->deregisterLiveCellRef(*this); + if (mWorldModel != nullptr) + mWorldModel->deregisterLiveCellRef(*this); + } + + LiveCellRefBase& LiveCellRefBase::operator=(LiveCellRefBase&& other) noexcept + { + mClass = other.mClass; + mRef = std::move(other.mRef); + mData = std::move(other.mData); + mWorldModel = std::exchange(other.mWorldModel, nullptr); + return *this; } void LiveCellRefBase::loadImp(const ESM::ObjectState& state) diff --git a/apps/openmw/mwworld/livecellref.hpp b/apps/openmw/mwworld/livecellref.hpp index 5694e33642..f3b48c0ff1 100644 --- a/apps/openmw/mwworld/livecellref.hpp +++ b/apps/openmw/mwworld/livecellref.hpp @@ -17,6 +17,7 @@ namespace MWWorld class Ptr; class ESMStore; class Class; + class WorldModel; template struct LiveCellRef; @@ -34,12 +35,23 @@ namespace MWWorld /** runtime-data */ RefData mData; + WorldModel* mWorldModel = nullptr; + LiveCellRefBase(unsigned int type, const ESM::CellRef& cref = ESM::CellRef()); LiveCellRefBase(unsigned int type, const ESM4::Reference& cref); LiveCellRefBase(unsigned int type, const ESM4::ActorCharacter& cref); + + LiveCellRefBase(const LiveCellRefBase& other) = default; + + LiveCellRefBase(LiveCellRefBase&& other) noexcept; + /* Need this for the class to be recognized as polymorphic */ virtual ~LiveCellRefBase(); + LiveCellRefBase& operator=(const LiveCellRefBase& other) = default; + + LiveCellRefBase& operator=(LiveCellRefBase&& other) noexcept; + virtual void load(const ESM::ObjectState& state) = 0; ///< Load state into a LiveCellRef, that has already been initialised with base and class. /// diff --git a/apps/openmw/mwworld/worldmodel.cpp b/apps/openmw/mwworld/worldmodel.cpp index 3a1c486f0e..39ed27e96b 100644 --- a/apps/openmw/mwworld/worldmodel.cpp +++ b/apps/openmw/mwworld/worldmodel.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include #include @@ -339,6 +340,20 @@ namespace MWWorld throw std::runtime_error(std::string("Can't find cell with name ") + std::string(name)); return *result; } + + void WorldModel::registerPtr(const Ptr& ptr) + { + if (ptr.mRef == nullptr) + throw std::logic_error("Ptr with nullptr mRef is not allowed to be registered"); + mPtrRegistry.insert(ptr); + ptr.mRef->mWorldModel = this; + } + + void WorldModel::deregisterLiveCellRef(LiveCellRefBase& ref) noexcept + { + mPtrRegistry.remove(ref); + ref.mWorldModel = nullptr; + } } MWWorld::Ptr MWWorld::WorldModel::getPtrByRefId(const ESM::RefId& name) diff --git a/apps/openmw/mwworld/worldmodel.hpp b/apps/openmw/mwworld/worldmodel.hpp index 4c39d866de..e4b161d16e 100644 --- a/apps/openmw/mwworld/worldmodel.hpp +++ b/apps/openmw/mwworld/worldmodel.hpp @@ -77,9 +77,9 @@ namespace MWWorld std::size_t getPtrRegistryRevision() const { return mPtrRegistry.getRevision(); } - void registerPtr(const Ptr& ptr) { mPtrRegistry.insert(ptr); } + void registerPtr(const Ptr& ptr); - void deregisterLiveCellRef(const LiveCellRefBase& ref) noexcept { mPtrRegistry.remove(ref); } + void deregisterLiveCellRef(LiveCellRefBase& ref) noexcept; void assignSaveFileRefNum(ESM::CellRef& ref) { mPtrRegistry.assign(ref); }