1
0
mirror of https://gitlab.com/OpenMW/openmw.git synced 2025-02-10 03:39:55 +00:00

Move Ptr registry into a separate type

There is no dependency on the rest of the WorldModel state.
This commit is contained in:
elsid 2023-05-28 11:56:02 +02:00
parent 16a580eb21
commit ce91784085
No known key found for this signature in database
GPG Key ID: 4DE04C198CBA7625
18 changed files with 103 additions and 71 deletions

View File

@ -78,7 +78,7 @@ add_openmw_dir (mwworld
actionequip timestamp actionalchemy cellstore actionapply actioneat
store esmstore fallback actionrepair actionsoulgem livecellref actiondoor
contentloader esmloader actiontrap cellreflist cellref weather projectilemanager
cellpreloader datetimemanager groundcoverstore magiceffects cell
cellpreloader datetimemanager groundcoverstore magiceffects cell ptrregistry
)
add_openmw_dir (mwphysics

View File

@ -208,7 +208,7 @@ namespace MWClass
}
newPtr.getCellRef().unsetRefNum();
newPtr.getRefData().setLuaScripts(nullptr);
MWBase::Environment::get().getWorldModel()->registerPtr(newPtr);
MWBase::Environment::get().getWorldModel()->getPtrRegistry().insert(newPtr);
return newPtr;
}
@ -229,7 +229,7 @@ namespace MWClass
newPtr = MWWorld::Ptr(cell.insert(ref), &cell);
}
ptr.getRefData().setLuaScripts(nullptr);
MWBase::Environment::get().getWorldModel()->registerPtr(newPtr);
MWBase::Environment::get().getWorldModel()->getPtrRegistry().insert(newPtr);
return newPtr;
}

View File

@ -83,7 +83,7 @@ namespace MWLua
auto visitor = [&](const MWWorld::Ptr& ptr) {
if (ptr.getRefData().isDeleted())
return true;
MWBase::Environment::get().getWorldModel()->registerPtr(ptr);
MWBase::Environment::get().getWorldModel()->getPtrRegistry().insert(ptr);
if (getLiveCellRefType(ptr.mRef) == ptr.getType())
res->push_back(getId(ptr));
return true;

View File

@ -74,7 +74,7 @@ namespace MWLua
private:
MWWorld::Ptr getPtr(const ESM::RefNum& id) const
{
MWWorld::Ptr res = mWorldModel->getPtr(id);
MWWorld::Ptr res = mWorldModel->getPtrRegistry().getOrDefault(id);
if (res.isEmpty() && Settings::lua().mLuaDebug)
Log(Debug::Verbose) << "Can not find object" << id.toString() << " when calling engine hanglers";
return res;

View File

@ -40,7 +40,7 @@ namespace MWLua
mGlobalEventBatch.clear();
for (const Local& e : mLocalEventBatch)
{
MWWorld::Ptr ptr = MWBase::Environment::get().getWorldModel()->getPtr(e.mDest);
MWWorld::Ptr ptr = MWBase::Environment::get().getWorldModel()->getPtrRegistry().getOrDefault(e.mDest);
LocalScripts* scripts = ptr.isEmpty() ? nullptr : ptr.getRefData().getLuaScripts();
if (scripts)
scripts->receiveEvent(e.mEventName, e.mEventData);

View File

@ -136,7 +136,7 @@ namespace MWLua
if (!mPlayer.isInCell() || !newPlayerPtr.isInCell() || mPlayer.getCell() != newPlayerPtr.getCell())
{
mPlayer = newPlayerPtr; // player was moved to another cell, update ptr in registry
MWBase::Environment::get().getWorldModel()->registerPtr(mPlayer);
MWBase::Environment::get().getWorldModel()->getPtrRegistry().insert(mPlayer);
}
mWorldView.update();
@ -299,7 +299,7 @@ namespace MWLua
if (localScripts)
{
mActiveLocalScripts.erase(localScripts);
if (!MWBase::Environment::get().getWorldModel()->getPtr(getId(ptr)).isEmpty())
if (!MWBase::Environment::get().getWorldModel()->getPtrRegistry().getOrDefault(getId(ptr)).isEmpty())
mEngineEvents.addToQueue(EngineEvents::OnInactive{ getId(ptr) });
}
}
@ -401,7 +401,7 @@ namespace MWLua
return;
}
MWBase::Environment::get().getWorldModel()->registerPtr(ptr);
MWBase::Environment::get().getWorldModel()->getPtrRegistry().insert(ptr);
LocalScripts* scripts = createLocalScripts(ptr);
scripts->setSerializer(mLocalSerializer.get());
@ -409,7 +409,7 @@ namespace MWLua
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);
MWBase::Environment::get().getWorldModel()->getPtrRegistry().remove(ptr);
}
void LuaManager::reloadAllScripts()
@ -430,7 +430,7 @@ namespace MWLua
mGlobalScripts.load(data);
}
for (const auto& [id, ptr] : MWBase::Environment::get().getWorldModel()->getAllPtrs())
for (const auto& [id, ptr] : MWBase::Environment::get().getWorldModel()->getPtrRegistry())
{ // Reload local scripts
LocalScripts* scripts = ptr.getRefData().getLuaScripts();
if (scripts == nullptr)

View File

@ -497,7 +497,7 @@ namespace MWLua
while (it.getType() != -1)
{
const MWWorld::Ptr& item = *(it++);
MWBase::Environment::get().getWorldModel()->registerPtr(item);
MWBase::Environment::get().getWorldModel()->getPtrRegistry().insert(item);
list->push_back(getId(item));
}
return ObjectList<ObjectT>{ list };
@ -516,7 +516,7 @@ namespace MWLua
{
if (item.getCellRef().getRefId() == itemId)
{
MWBase::Environment::get().getWorldModel()->registerPtr(item);
MWBase::Environment::get().getWorldModel()->getPtrRegistry().insert(item);
return ObjectT(getId(item));
}
}
@ -531,7 +531,7 @@ namespace MWLua
{
if (item.getCellRef().getRefId() == itemId)
{
MWBase::Environment::get().getWorldModel()->registerPtr(item);
MWBase::Environment::get().getWorldModel()->getPtrRegistry().insert(item);
list->push_back(getId(item));
}
}

View File

@ -32,7 +32,8 @@ namespace MWLua
MWWorld::Ptr itemPtr;
if (std::holds_alternative<ObjectId>(item))
{
itemPtr = MWBase::Environment::get().getWorldModel()->getPtr(std::get<ObjectId>(item));
itemPtr = MWBase::Environment::get().getWorldModel()->getPtrRegistry().getOrDefault(
std::get<ObjectId>(item));
if (old_it != store.end() && *old_it == itemPtr)
return true; // already equipped
if (itemPtr.isEmpty() || itemPtr.getRefData().getCount() == 0
@ -217,7 +218,7 @@ namespace MWLua
auto it = store.getSlot(slot);
if (it == store.end())
continue;
MWBase::Environment::get().getWorldModel()->registerPtr(*it);
MWBase::Environment::get().getWorldModel()->getPtrRegistry().insert(*it);
if (dynamic_cast<const GObject*>(&o))
equipment[slot] = sol::make_object(lua, GObject(*it));
else
@ -233,7 +234,7 @@ namespace MWLua
auto it = store.getSlot(slot);
if (it == store.end())
return sol::nil;
MWBase::Environment::get().getWorldModel()->registerPtr(*it);
MWBase::Environment::get().getWorldModel()->getPtrRegistry().insert(*it);
if (dynamic_cast<const GObject*>(&o))
return sol::make_object(lua, GObject(*it));
else

View File

@ -58,7 +58,7 @@ namespace MWLua
void WorldView::objectAddedToScene(const MWWorld::Ptr& ptr)
{
MWBase::Environment::get().getWorldModel()->registerPtr(ptr);
MWBase::Environment::get().getWorldModel()->getPtrRegistry().insert(ptr);
ObjectGroup* group = chooseGroup(ptr);
if (group)
addToGroup(*group, ptr);
@ -81,13 +81,13 @@ namespace MWLua
void WorldView::load(ESM::ESMReader& esm)
{
esm.getHNT(mSimulationTime, "LUAW");
MWBase::Environment::get().getWorldModel()->setLastGeneratedRefNum(esm.getFormId(true));
MWBase::Environment::get().getWorldModel()->getPtrRegistry().setLastGenerated(esm.getFormId(true));
}
void WorldView::save(ESM::ESMWriter& esm) const
{
esm.writeHNT("LUAW", mSimulationTime);
esm.writeFormId(MWBase::Environment::get().getWorldModel()->getLastGeneratedRefNum(), true);
esm.writeFormId(MWBase::Environment::get().getWorldModel()->getPtrRegistry().getLastGenerated(), true);
}
void WorldView::ObjectGroup::updateList()

View File

@ -63,7 +63,7 @@ namespace
if (pair.second.empty())
return MWWorld::Ptr();
else if (pair.first.hasContentFile())
return MWBase::Environment::get().getWorldModel()->getPtr(pair.first);
return MWBase::Environment::get().getWorldModel()->getPtrRegistry().getOrDefault(pair.first);
return MWBase::Environment::get().getWorld()->searchPtr(pair.second, false);
}
};

View File

@ -275,7 +275,7 @@ namespace
iter->mData.enable();
MWBase::Environment::get().getWorld()->disable(ptr);
}
MWBase::Environment::get().getWorldModel()->registerPtr(ptr);
MWBase::Environment::get().getWorldModel()->getPtrRegistry().insert(ptr);
return;
}
@ -290,7 +290,7 @@ namespace
collection.mList.push_back(ref);
MWWorld::LiveCellRefBase* base = &collection.mList.back();
MWBase::Environment::get().getWorldModel()->registerPtr(MWWorld::Ptr(base, cellstore));
MWBase::Environment::get().getWorldModel()->getPtrRegistry().insert(MWWorld::Ptr(base, cellstore));
}
// this function allows us to link a CellRefList<T> to the associated recNameInt, and apply a function
@ -443,7 +443,8 @@ namespace MWWorld
throw std::runtime_error(
"moveTo: can't move object from a non-loaded cell (how did you get this object anyway?)");
MWBase::Environment::get().getWorldModel()->registerPtr(MWWorld::Ptr(object.getBase(), cellToMoveTo));
MWBase::Environment::get().getWorldModel()->getPtrRegistry().insert(
MWWorld::Ptr(object.getBase(), cellToMoveTo));
MovedRefTracker::iterator found = mMovedHere.find(object.getBase());
if (found != mMovedHere.end())
@ -1041,7 +1042,7 @@ namespace MWWorld
}
// Search for the reference. It might no longer exist if its content file was removed.
Ptr movedRef = MWBase::Environment::get().getWorldModel()->getPtr(refnum);
Ptr movedRef = MWBase::Environment::get().getWorldModel()->getPtrRegistry().getOrDefault(refnum);
if (movedRef.isEmpty())
{
Log(Debug::Warning) << "Warning: Dropping moved ref tag for " << refnum.mIndex

View File

@ -375,7 +375,7 @@ namespace MWWorld
newPtr.getCellRef().unsetRefNum(); // This RefNum is only valid within the original cell of the reference
newPtr.getRefData().setCount(count);
newPtr.getRefData().setLuaScripts(nullptr);
MWBase::Environment::get().getWorldModel()->registerPtr(newPtr);
MWBase::Environment::get().getWorldModel()->getPtrRegistry().insert(newPtr);
if (hasInventoryStore(newPtr))
getInventoryStore(newPtr).setActor(newPtr);
return newPtr;
@ -385,7 +385,7 @@ namespace MWWorld
{
Ptr newPtr = copyToCellImpl(ptr, cell);
ptr.getRefData().setLuaScripts(nullptr);
MWBase::Environment::get().getWorldModel()->registerPtr(newPtr);
MWBase::Environment::get().getWorldModel()->getPtrRegistry().insert(newPtr);
if (hasInventoryStore(newPtr))
getInventoryStore(newPtr).setActor(newPtr);
return newPtr;

View File

@ -308,7 +308,7 @@ MWWorld::ContainerStoreIterator MWWorld::ContainerStore::add(
// The copy of the original item we just made
MWWorld::Ptr item = *it;
MWBase::Environment::get().getWorldModel()->registerPtr(item);
MWBase::Environment::get().getWorldModel()->getPtrRegistry().insert(item);
// we may have copied an item from the world, so reset a few things first
item.getRefData().setBaseNode(

View File

@ -24,7 +24,7 @@ namespace MWWorld
SafePtr::SafePtr(const Ptr& ptr)
: mId(ptr.getCellRef().getRefNum())
, mPtr(ptr)
, mLastUpdate(MWBase::Environment::get().getWorldModel()->getPtrIndexUpdateCounter())
, mLastUpdate(MWBase::Environment::get().getWorldModel()->getPtrRegistry().getRevision())
{
}
@ -39,11 +39,11 @@ namespace MWWorld
void SafePtr::update() const
{
WorldModel& w = *MWBase::Environment::get().getWorldModel();
if (mLastUpdate < w.getPtrIndexUpdateCounter())
const PtrRegistry& registry = MWBase::Environment::get().getWorldModel()->getPtrRegistry();
if (mLastUpdate < registry.getRevision())
{
mPtr = w.getPtr(mId);
mLastUpdate = w.getPtrIndexUpdateCounter();
mPtr = registry.getOrDefault(mId);
mLastUpdate = registry.getRevision();
}
}
}

View File

@ -0,0 +1,59 @@
#ifndef OPENMW_APPS_OPENMW_MWWORLD_PTRREGISTRY_H
#define OPENMW_APPS_OPENMW_MWWORLD_PTRREGISTRY_H
#include "ptr.hpp"
#include "components/esm3/cellref.hpp"
#include <unordered_map>
namespace MWWorld
{
class PtrRegistry
{
public:
std::size_t getRevision() const { return mRevision; }
ESM::RefNum getLastGenerated() const { return mLastGenerated; }
auto begin() const { return mIndex.cbegin(); }
auto end() const { return mIndex.cend(); }
Ptr getOrDefault(ESM::RefNum refNum) const
{
const auto it = mIndex.find(refNum);
if (it != mIndex.end())
return it->second;
return Ptr();
}
void setLastGenerated(ESM::RefNum v) { mLastGenerated = v; }
void clear()
{
mIndex.clear();
mLastGenerated = ESM::RefNum{};
mRevision = 0;
}
void insert(const Ptr& ptr)
{
mIndex[ptr.getCellRef().getOrAssignRefNum(mLastGenerated)] = ptr;
++mRevision;
}
void remove(const Ptr& ptr)
{
mIndex.erase(ptr.getCellRef().getRefNum());
++mRevision;
}
private:
std::size_t mRevision = 0;
std::unordered_map<ESM::RefNum, Ptr> mIndex;
ESM::RefNum mLastGenerated;
};
}
#endif

View File

@ -1851,7 +1851,8 @@ namespace MWWorld
facedObject = rayToObject.mHitObject;
if (facedObject.isEmpty() && rayToObject.mHitRefnum.isSet())
facedObject = MWBase::Environment::get().getWorldModel()->getPtr(rayToObject.mHitRefnum);
facedObject
= MWBase::Environment::get().getWorldModel()->getPtrRegistry().getOrDefault(rayToObject.mHitRefnum);
if (rayToObject.mHit)
mDistanceToFacedObject = (rayToObject.mRatio * maxDistance) - camDist;
else
@ -1868,7 +1869,8 @@ namespace MWWorld
res.mHitNormal = rayRes.mHitNormalWorld;
res.mHitObject = rayRes.mHitObject;
if (res.mHitObject.isEmpty() && rayRes.mHitRefnum.isSet())
res.mHitObject = MWBase::Environment::get().getWorldModel()->getPtr(rayRes.mHitRefnum);
res.mHitObject
= MWBase::Environment::get().getWorldModel()->getPtrRegistry().getOrDefault(rayRes.mHitRefnum);
return res.mHit;
}

View File

@ -82,9 +82,7 @@ MWWorld::CellStore& MWWorld::WorldModel::insertCellStore(const ESM::Cell& cell)
void MWWorld::WorldModel::clear()
{
mPtrIndex.clear();
mPtrIndexUpdateCounter = 0;
mLastGeneratedRefnum = ESM::RefNum{};
mPtrRegistry.clear();
mInteriors.clear();
mExteriors.clear();
mCells.clear();
@ -92,27 +90,6 @@ void MWWorld::WorldModel::clear()
mIdCacheIndex = 0;
}
void MWWorld::WorldModel::registerPtr(const MWWorld::Ptr& ptr)
{
mPtrIndex[ptr.getCellRef().getOrAssignRefNum(mLastGeneratedRefnum)] = ptr;
mPtrIndexUpdateCounter++;
}
void MWWorld::WorldModel::deregisterPtr(const MWWorld::Ptr& ptr)
{
mPtrIndex.erase(ptr.getCellRef().getRefNum());
mPtrIndexUpdateCounter++;
}
MWWorld::Ptr MWWorld::WorldModel::getPtr(const ESM::RefNum& refNum) const
{
auto it = mPtrIndex.find(refNum);
if (it != mPtrIndex.end())
return it->second;
else
return MWWorld::Ptr();
}
MWWorld::Ptr MWWorld::WorldModel::getPtrAndCache(const ESM::RefId& name, CellStore& cellStore)
{
Ptr ptr = cellStore.getPtr(name);

View File

@ -12,6 +12,7 @@
#include "cellstore.hpp"
#include "ptr.hpp"
#include "ptrregistry.hpp"
namespace ESM
{
@ -51,17 +52,10 @@ namespace MWWorld
CellStore& getCell(std::string_view name, bool forceLoad = true); // interior or named exterior
CellStore& getCell(const ESM::RefId& Id, bool forceLoad = true);
void registerPtr(const MWWorld::Ptr& ptr);
void deregisterPtr(const MWWorld::Ptr& ptr);
ESM::RefNum getLastGeneratedRefNum() const { return mLastGeneratedRefnum; }
void setLastGeneratedRefNum(ESM::RefNum v) { mLastGeneratedRefnum = v; }
size_t getPtrIndexUpdateCounter() const { return mPtrIndexUpdateCounter; }
const std::unordered_map<ESM::RefNum, Ptr>& getAllPtrs() const { return mPtrIndex; }
Ptr getPtr(const ESM::RefNum& refNum) const;
Ptr getPtr(const ESM::RefId& name);
PtrRegistry& getPtrRegistry() { return mPtrRegistry; }
template <typename Fn>
void forEachLoadedCellStore(Fn&& fn)
{
@ -90,9 +84,7 @@ namespace MWWorld
mutable std::map<ESM::ExteriorCellLocation, CellStore*> mExteriors;
std::vector<std::pair<ESM::RefId, CellStore*>> mIdCache;
std::size_t mIdCacheIndex = 0;
std::unordered_map<ESM::RefNum, Ptr> mPtrIndex;
std::size_t mPtrIndexUpdateCounter = 0;
ESM::RefNum mLastGeneratedRefnum;
PtrRegistry mPtrRegistry;
CellStore& getOrInsertCellStore(const ESM::Cell& cell);