mirror of
https://github.com/OpenMW/openmw.git
synced 2025-01-21 09:53:52 +00:00
Merge branch 'ptrindex' into 'master'
Fix crash: PtrRegistry can contain pointers to already removed temporary ManualRefs See merge request OpenMW/openmw!3411
This commit is contained in:
commit
9d186ee2cd
13 changed files with 49 additions and 40 deletions
|
@ -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,11 +43,18 @@ 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();
|
||||||
|
if (!refNum.isSet())
|
||||||
|
return;
|
||||||
|
auto it = mIndex.find(refNum);
|
||||||
|
if (it != mIndex.end() && it->second.getBase() == &ref)
|
||||||
|
{
|
||||||
|
mIndex.erase(it);
|
||||||
++mRevision;
|
++mRevision;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::size_t mRevision = 0;
|
std::size_t mRevision = 0;
|
||||||
|
|
|
@ -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…
Reference in a new issue