Merge branch 'ptrindex' into 'master'

Fix crash: PtrRegistry can contain pointers to already removed temporary ManualRefs

See merge request OpenMW/openmw!3411
macos_ci_fix
psi29a 1 year ago
commit 9d186ee2cd
No known key found for this signature in database

@ -740,6 +740,9 @@ void OMW::Engine::prepareEngine()
// Create the world // Create the world
mWorld = std::make_unique<MWWorld::World>( mWorld = std::make_unique<MWWorld::World>(
mResourceSystem.get(), mActivationDistanceOverride, mCellName, mCfgMgr.getUserDataPath()); mResourceSystem.get(), mActivationDistanceOverride, mCellName, mCfgMgr.getUserDataPath());
mEnvironment.setWorld(*mWorld);
mEnvironment.setWorldModel(mWorld->getWorldModel());
mEnvironment.setESMStore(mWorld->getStore());
Loading::Listener* listener = MWBase::Environment::get().getWindowManager()->getLoadingScreen(); Loading::Listener* listener = MWBase::Environment::get().getWindowManager()->getLoadingScreen();
Loading::AsyncListener asyncListener(*listener); Loading::AsyncListener asyncListener(*listener);
@ -763,12 +766,9 @@ void OMW::Engine::prepareEngine()
listener->loadingOff(); listener->loadingOff();
mWorld->init(mViewer, rootNode, mWorkQueue.get(), *mUnrefQueue); mWorld->init(mViewer, rootNode, mWorkQueue.get(), *mUnrefQueue);
mEnvironment.setWorldScene(mWorld->getWorldScene());
mWorld->setupPlayer(); mWorld->setupPlayer();
mWorld->setRandomSeed(mRandomSeed); mWorld->setRandomSeed(mRandomSeed);
mEnvironment.setWorld(*mWorld);
mEnvironment.setWorldModel(mWorld->getWorldModel());
mEnvironment.setWorldScene(mWorld->getWorldScene());
mEnvironment.setESMStore(mWorld->getStore());
const MWWorld::Store<ESM::GameSetting>* gmst = &mWorld->getStore().get<ESM::GameSetting>(); const MWWorld::Store<ESM::GameSetting>* gmst = &mWorld->getStore().get<ESM::GameSetting>();
mL10nManager->setGmstLoader( mL10nManager->setGmstLoader(

@ -302,8 +302,13 @@ namespace MWClass
MWWorld::Ptr Container::copyToCellImpl(const MWWorld::ConstPtr& ptr, MWWorld::CellStore& cell) const MWWorld::Ptr Container::copyToCellImpl(const MWWorld::ConstPtr& ptr, MWWorld::CellStore& cell) const
{ {
const MWWorld::LiveCellRef<ESM::Container>* ref = ptr.get<ESM::Container>(); const MWWorld::LiveCellRef<ESM::Container>* ref = ptr.get<ESM::Container>();
MWWorld::Ptr newPtr(cell.insert(ref), &cell);
return MWWorld::Ptr(cell.insert(ref), &cell); if (newPtr.getRefData().getCustomData())
{
MWBase::Environment::get().getWorldModel()->registerPtr(newPtr);
newPtr.getContainerStore()->setPtr(newPtr);
}
return newPtr;
} }
void Container::readAdditionalState(const MWWorld::Ptr& ptr, const ESM::ObjectState& state) const void Container::readAdditionalState(const MWWorld::Ptr& ptr, const ESM::ObjectState& state) const

@ -694,8 +694,13 @@ namespace MWClass
MWWorld::Ptr Creature::copyToCellImpl(const MWWorld::ConstPtr& ptr, MWWorld::CellStore& cell) const MWWorld::Ptr Creature::copyToCellImpl(const MWWorld::ConstPtr& ptr, MWWorld::CellStore& cell) const
{ {
const MWWorld::LiveCellRef<ESM::Creature>* ref = ptr.get<ESM::Creature>(); const MWWorld::LiveCellRef<ESM::Creature>* ref = ptr.get<ESM::Creature>();
MWWorld::Ptr newPtr(cell.insert(ref), &cell);
return MWWorld::Ptr(cell.insert(ref), &cell); if (newPtr.getRefData().getCustomData())
{
MWBase::Environment::get().getWorldModel()->registerPtr(newPtr);
newPtr.getContainerStore()->setPtr(newPtr);
}
return newPtr;
} }
bool Creature::isBipedal(const MWWorld::ConstPtr& ptr) const bool Creature::isBipedal(const MWWorld::ConstPtr& ptr) const

@ -1334,8 +1334,13 @@ namespace MWClass
MWWorld::Ptr Npc::copyToCellImpl(const MWWorld::ConstPtr& ptr, MWWorld::CellStore& cell) const MWWorld::Ptr Npc::copyToCellImpl(const MWWorld::ConstPtr& ptr, MWWorld::CellStore& cell) const
{ {
const MWWorld::LiveCellRef<ESM::NPC>* ref = ptr.get<ESM::NPC>(); const MWWorld::LiveCellRef<ESM::NPC>* ref = ptr.get<ESM::NPC>();
MWWorld::Ptr newPtr(cell.insert(ref), &cell);
return MWWorld::Ptr(cell.insert(ref), &cell); if (newPtr.getRefData().getCustomData())
{
MWBase::Environment::get().getWorldModel()->registerPtr(newPtr);
newPtr.getContainerStore()->setPtr(newPtr);
}
return newPtr;
} }
float Npc::getSkill(const MWWorld::Ptr& ptr, ESM::RefId id) const float Npc::getSkill(const MWWorld::Ptr& ptr, ESM::RefId id) const

@ -475,9 +475,6 @@ namespace MWLua
scripts->setSerializer(mLocalSerializer.get()); scripts->setSerializer(mLocalSerializer.get());
scripts->setSavedDataDeserializer(mLocalLoader.get()); scripts->setSavedDataDeserializer(mLocalLoader.get());
scripts->load(data); scripts->load(data);
// LiveCellRef is usually copied after loading, so this Ptr will become invalid and should be deregistered.
MWBase::Environment::get().getWorldModel()->deregisterPtr(ptr);
} }
void LuaManager::reloadAllScripts() void LuaManager::reloadAllScripts()

@ -90,17 +90,15 @@ namespace MWMechanics
{ {
auto world = MWBase::Environment::get().getWorld(); auto world = MWBase::Environment::get().getWorld();
MWWorld::ManualRef ref(world->getStore(), creatureID, 1); MWWorld::ManualRef ref(world->getStore(), creatureID, 1);
MWWorld::Ptr placed = world->safePlaceObject(ref.getPtr(), summoner, summoner.getCell(), 0, 120.f);
MWMechanics::CreatureStats& summonedCreatureStats MWMechanics::CreatureStats& summonedCreatureStats = placed.getClass().getCreatureStats(placed);
= ref.getPtr().getClass().getCreatureStats(ref.getPtr());
// Make the summoned creature follow its master and help in fights // Make the summoned creature follow its master and help in fights
AiFollow package(summoner); AiFollow package(summoner);
summonedCreatureStats.getAiSequence().stack(package, ref.getPtr()); summonedCreatureStats.getAiSequence().stack(package, placed);
creatureActorId = summonedCreatureStats.getActorId(); creatureActorId = summonedCreatureStats.getActorId();
MWWorld::Ptr placed = world->safePlaceObject(ref.getPtr(), summoner, summoner.getCell(), 0, 120.f);
MWRender::Animation* anim = world->getAnimation(placed); MWRender::Animation* anim = world->getAnimation(placed);
if (anim) if (anim)
{ {

@ -157,20 +157,6 @@ MWWorld::ContainerStore::ContainerStore()
{ {
} }
MWWorld::ContainerStore::~ContainerStore()
{
try
{
MWWorld::WorldModel* worldModel = MWBase::Environment::get().getWorldModel();
for (MWWorld::ContainerStoreIterator iter(begin()); iter != end(); ++iter)
worldModel->deregisterPtr(*iter);
}
catch (const std::exception& e)
{
Log(Debug::Error) << "Failed to deregister container store: " << e.what();
}
}
MWWorld::ConstContainerStoreIterator MWWorld::ContainerStore::cbegin(int mask) const MWWorld::ConstContainerStoreIterator MWWorld::ContainerStore::cbegin(int mask) const
{ {
return ConstContainerStoreIterator(mask, this); return ConstContainerStoreIterator(mask, this);

@ -175,7 +175,7 @@ namespace MWWorld
public: public:
ContainerStore(); ContainerStore();
virtual ~ContainerStore(); virtual ~ContainerStore() = default;
virtual std::unique_ptr<ContainerStore> clone() virtual std::unique_ptr<ContainerStore> clone()
{ {

@ -13,6 +13,7 @@
#include "class.hpp" #include "class.hpp"
#include "esmstore.hpp" #include "esmstore.hpp"
#include "ptr.hpp" #include "ptr.hpp"
#include "worldmodel.hpp"
MWWorld::LiveCellRefBase::LiveCellRefBase(unsigned int type, const ESM::CellRef& cref) MWWorld::LiveCellRefBase::LiveCellRefBase(unsigned int type, const ESM::CellRef& cref)
: mClass(&Class::get(type)) : mClass(&Class::get(type))
@ -35,6 +36,11 @@ MWWorld::LiveCellRefBase::LiveCellRefBase(unsigned int type, const ESM4::ActorCh
{ {
} }
MWWorld::LiveCellRefBase::~LiveCellRefBase()
{
MWBase::Environment::get().getWorldModel()->deregisterLiveCellRef(*this);
}
void MWWorld::LiveCellRefBase::loadImp(const ESM::ObjectState& state) void MWWorld::LiveCellRefBase::loadImp(const ESM::ObjectState& state)
{ {
mRef = MWWorld::CellRef(state.mRef); mRef = MWWorld::CellRef(state.mRef);

@ -38,7 +38,7 @@ namespace MWWorld
LiveCellRefBase(unsigned int type, const ESM4::Reference& cref); LiveCellRefBase(unsigned int type, const ESM4::Reference& cref);
LiveCellRefBase(unsigned int type, const ESM4::ActorCharacter& cref); LiveCellRefBase(unsigned int type, const ESM4::ActorCharacter& cref);
/* Need this for the class to be recognized as polymorphic */ /* Need this for the class to be recognized as polymorphic */
virtual ~LiveCellRefBase() {} virtual ~LiveCellRefBase();
virtual void load(const ESM::ObjectState& state) = 0; virtual void load(const ESM::ObjectState& state) = 0;
///< Load state into a LiveCellRef, that has already been initialised with base and class. ///< Load state into a LiveCellRef, that has already been initialised with base and class.

@ -43,10 +43,17 @@ namespace MWWorld
++mRevision; ++mRevision;
} }
void remove(const Ptr& ptr) void remove(const LiveCellRefBase& ref) noexcept
{ {
mIndex.erase(ptr.getCellRef().getRefNum()); const ESM::RefNum& refNum = ref.mRef.getRefNum();
++mRevision; if (!refNum.isSet())
return;
auto it = mIndex.find(refNum);
if (it != mIndex.end() && it->second.getBase() == &ref)
{
mIndex.erase(it);
++mRevision;
}
} }
private: private:

@ -136,8 +136,8 @@ namespace MWWorld
uint32_t mRandomSeed{}; uint32_t mRandomSeed{};
// not implemented // not implemented
World(const World&); World(const World&) = delete;
World& operator=(const World&); World& operator=(const World&) = delete;
void updateWeather(float duration, bool paused = false); void updateWeather(float duration, bool paused = false);

@ -79,7 +79,7 @@ namespace MWWorld
void registerPtr(const Ptr& ptr) { mPtrRegistry.insert(ptr); } void registerPtr(const Ptr& ptr) { mPtrRegistry.insert(ptr); }
void deregisterPtr(const Ptr& ptr) { mPtrRegistry.remove(ptr); } void deregisterLiveCellRef(const LiveCellRefBase& ref) noexcept { mPtrRegistry.remove(ref); }
template <typename Fn> template <typename Fn>
void forEachLoadedCellStore(Fn&& fn) void forEachLoadedCellStore(Fn&& fn)

Loading…
Cancel
Save