1
0
Fork 0
mirror of https://github.com/OpenMW/openmw.git synced 2025-04-01 10:36:39 +00:00

Fixes a crash on launch and some compile issue

also uses std::visit in cellstore comparison to avoid missing combinasion

split loadrefs in loadref of ESM4 and ESM3.
This commit is contained in:
florent.teppe 2023-01-27 15:29:05 +01:00
parent cb8cdd8831
commit 5037dcf9bc
7 changed files with 92 additions and 85 deletions

View file

@ -104,9 +104,10 @@ namespace MWMechanics
if (mIsGraphConstructed) if (mIsGraphConstructed)
return true; return true;
mCell = cell->getCell()->isEsm4() ? nullptr : &cell->getCell()->getEsm3(); if (cell->getCell()->isEsm4())
if (!mCell)
return false; return false;
mCell = &cell->getCell()->getEsm3();
mPathgrid = MWBase::Environment::get().getWorld()->getStore().get<ESM::Pathgrid>().search(*mCell); mPathgrid = MWBase::Environment::get().getWorld()->getStore().get<ESM::Pathgrid>().search(*mCell);
if (!mPathgrid) if (!mPathgrid)
return false; return false;

View file

@ -37,7 +37,6 @@ namespace MWWorld
Cell::Cell(const ESM::Cell& cell) Cell::Cell(const ESM::Cell& cell)
: ESM::CellVariant(cell) : ESM::CellVariant(cell)
{ {
assert(cell != nullptr);
mNameID = cell.mName; mNameID = cell.mName;
mDisplayname = cell.mName; mDisplayname = cell.mName;
mGridPos.x() = cell.getGridX(); mGridPos.x() = cell.getGridX();

View file

@ -18,9 +18,11 @@ namespace ESM4
namespace MWWorld namespace MWWorld
{ {
class CellStore;
struct Cell : public ESM::CellVariant struct Cell : public ESM::CellVariant
{ {
friend MWWorld::CellStore;
struct MoodData struct MoodData
{ {
uint32_t mAmbiantColor; uint32_t mAmbiantColor;
@ -39,7 +41,7 @@ namespace MWWorld
bool isQuasiExterior() const { return mFlags.isQuasiExterior; } bool isQuasiExterior() const { return mFlags.isQuasiExterior; }
bool hasWater() const { return mFlags.hasWater; } bool hasWater() const { return mFlags.hasWater; }
bool noSleep() const { return mFlags.noSleep; } bool noSleep() const { return mFlags.noSleep; }
const ESM::CellId& getCellId() const { return mCellId; }; const ESM::CellId& getCellId() const { return mCellId; }
const ESM::RefId& getRegion() const { return mRegion; } const ESM::RefId& getRegion() const { return mRegion; }
std::string_view getEditorName() const { return mNameID; } std::string_view getEditorName() const { return mNameID; }
std::string getDescription() const; std::string getDescription() const;

View file

@ -772,41 +772,20 @@ namespace MWWorld
std::sort(mIds.begin(), mIds.end()); std::sort(mIds.begin(), mIds.end());
} }
void CellStore::loadRefs() void CellStore::loadRefs(const ESM::Cell& cell, std::map<ESM::RefNum, ESM::RefId>& refNumToID)
{ {
assert(mCellVariant.isValid()); if (cell.mContextList.empty())
std::map<ESM::RefNum, ESM::RefId> refNumToID; // used to detect refID modifications
if (mCellVariant.isEsm4())
{
auto cell4 = mCellVariant.getEsm4();
auto& refs = MWBase::Environment::get().getWorld()->getStore().get<ESM4::Reference>();
auto it = refs.begin();
while (it != refs.end())
{
if (it->mParent == cell4.mId)
{
loadRef(*it, false);
}
++it;
}
}
else
{
auto cell3 = mCellVariant.getEsm3();
if (cell3.mContextList.empty())
return; // this is a dynamically generated cell -> skipping. return; // this is a dynamically generated cell -> skipping.
// Load references from all plugins that do something with this cell. // Load references from all plugins that do something with this cell.
for (size_t i = 0; i < cell3.mContextList.size(); i++) for (size_t i = 0; i < cell.mContextList.size(); i++)
{ {
try try
{ {
// Reopen the ESM reader and seek to the right position. // Reopen the ESM reader and seek to the right position.
const std::size_t index = static_cast<std::size_t>(cell3.mContextList[i].index); const std::size_t index = static_cast<std::size_t>(cell.mContextList[i].index);
const ESM::ReadersCache::BusyItem reader = mReaders.get(index); const ESM::ReadersCache::BusyItem reader = mReaders.get(index);
cell3.restore(*reader, i); cell.restore(*reader, i);
ESM::CellRef ref; ESM::CellRef ref;
// Get each reference in turn // Get each reference in turn
@ -821,8 +800,8 @@ namespace MWWorld
// Don't load reference if it was moved to a different cell. // Don't load reference if it was moved to a different cell.
ESM::MovedCellRefTracker::const_iterator iter ESM::MovedCellRefTracker::const_iterator iter
= std::find(cell3.mMovedRefs.begin(), cell3.mMovedRefs.end(), ref.mRefNum); = std::find(cell.mMovedRefs.begin(), cell.mMovedRefs.end(), ref.mRefNum);
if (iter != cell3.mMovedRefs.end()) if (iter != cell.mMovedRefs.end())
{ {
continue; continue;
} }
@ -837,7 +816,7 @@ namespace MWWorld
} }
} }
// Load moved references, from separately tracked list. // Load moved references, from separately tracked list.
for (const auto& leasedRef : cell3.mLeasedRefs) for (const auto& leasedRef : cell.mLeasedRefs)
{ {
ESM::CellRef& ref = const_cast<ESM::CellRef&>(leasedRef.first); ESM::CellRef& ref = const_cast<ESM::CellRef&>(leasedRef.first);
bool deleted = leasedRef.second; bool deleted = leasedRef.second;
@ -846,6 +825,26 @@ namespace MWWorld
} }
} }
void CellStore::loadRefs(const ESM4::Cell& cell, std::map<ESM::RefNum, ESM::RefId>& refNumToID)
{
auto& refs = MWBase::Environment::get().getWorld()->getStore().get<ESM4::Reference>();
for (const auto& ref : refs)
{
if (ref.mParent == cell.mId)
{
loadRef(ref, false);
}
}
}
void CellStore::loadRefs()
{
assert(mCellVariant.isValid());
std::map<ESM::RefNum, ESM::RefId> refNumToID; // used to detect refID modifications
std::visit([&refNumToID, this](auto&& cell) { this->loadRefs(*cell, refNumToID); }, mCellVariant.mVariant);
updateMergedRefs(); updateMergedRefs();
} }
@ -1087,18 +1086,21 @@ namespace MWWorld
} }
} }
struct Visitor
{
bool operator()(const ESM::Cell* a, const ESM::Cell* b) const { return a->getCellId() == b->getCellId(); };
bool operator()(const ESM4::Cell* a, const ESM4::Cell* b) const { return a->mId == b->mId; };
template <class L, class R>
bool operator()(L, R) const
{
return false;
}
};
bool CellStore::operator==(const CellStore& right) const bool CellStore::operator==(const CellStore& right) const
{ {
return std::visit(Visitor{}, this->mCellVariant.mVariant, right.mCellVariant.mVariant);
bool bothCell4 = mCellVariant.isEsm4() && right.mCellVariant.isEsm4();
bool bothCell3 = !mCellVariant.isEsm4() && !right.mCellVariant.isEsm4();
if (bothCell3)
return mCellVariant.getEsm3().getCellId() == right.mCellVariant.getEsm3().getCellId();
else if (bothCell4)
return mCellVariant.getEsm4().mId == right.mCellVariant.getEsm4().mId;
else
return false;
} }
void CellStore::setFog(std::unique_ptr<ESM::FogState>&& fog) void CellStore::setFog(std::unique_ptr<ESM::FogState>&& fog)

View file

@ -386,6 +386,9 @@ namespace MWWorld
/// Run through references and store IDs /// Run through references and store IDs
void listRefs(); void listRefs();
void loadRefs(const ESM::Cell& cell, std::map<ESM::RefNum, ESM::RefId>& refNumToID);
void loadRefs(const ESM4::Cell& cell, std::map<ESM::RefNum, ESM::RefId>& refNumToID);
void loadRefs(); void loadRefs();
void loadRef(const ESM4::Reference& ref, bool deleted); void loadRef(const ESM4::Reference& ref, bool deleted);

View file

@ -888,7 +888,7 @@ namespace MWWorld
loadingListener->setProgressRange(cell->count()); loadingListener->setProgressRange(cell->count());
mNavigator.setWorldspace( mNavigator.setWorldspace(
Misc::StringUtils::lowerCase(cell->getCell()->getEditorName()), navigatorUpdateGuard.get()); Misc::StringUtils::lowerCase(cell->getCell()->getCellId().mWorldspace), navigatorUpdateGuard.get());
mNavigator.updateBounds(position.asVec3(), navigatorUpdateGuard.get()); mNavigator.updateBounds(position.asVec3(), navigatorUpdateGuard.get());
// Load cell. // Load cell.

View file

@ -19,7 +19,7 @@ namespace ESM
struct CellVariant struct CellVariant
{ {
private: protected:
std::variant<const ESM4::Cell*, const ESM::Cell*> mVariant; std::variant<const ESM4::Cell*, const ESM::Cell*> mVariant;
public: public: