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.
7220-lua-add-a-general-purpose-lexical-parser
florent.teppe 2 years ago
parent cb8cdd8831
commit 5037dcf9bc

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

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

@ -18,9 +18,11 @@ namespace ESM4
namespace MWWorld
{
class CellStore;
struct Cell : public ESM::CellVariant
{
friend MWWorld::CellStore;
struct MoodData
{
uint32_t mAmbiantColor;
@ -39,7 +41,7 @@ namespace MWWorld
bool isQuasiExterior() const { return mFlags.isQuasiExterior; }
bool hasWater() const { return mFlags.hasWater; }
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; }
std::string_view getEditorName() const { return mNameID; }
std::string getDescription() const;

@ -772,79 +772,78 @@ namespace MWWorld
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());
std::map<ESM::RefNum, ESM::RefId> refNumToID; // used to detect refID modifications
if (cell.mContextList.empty())
return; // this is a dynamically generated cell -> skipping.
if (mCellVariant.isEsm4())
// Load references from all plugins that do something with this cell.
for (size_t i = 0; i < cell.mContextList.size(); i++)
{
auto cell4 = mCellVariant.getEsm4();
auto& refs = MWBase::Environment::get().getWorld()->getStore().get<ESM4::Reference>();
auto it = refs.begin();
while (it != refs.end())
try
{
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.
// Reopen the ESM reader and seek to the right position.
const std::size_t index = static_cast<std::size_t>(cell.mContextList[i].index);
const ESM::ReadersCache::BusyItem reader = mReaders.get(index);
cell.restore(*reader, i);
// Load references from all plugins that do something with this cell.
for (size_t i = 0; i < cell3.mContextList.size(); i++)
{
try
ESM::CellRef ref;
// Get each reference in turn
ESM::MovedCellRef cMRef;
bool deleted = false;
bool moved = false;
while (ESM::Cell::getNextRef(
*reader, ref, deleted, cMRef, moved, ESM::Cell::GetNextRefMode::LoadOnlyNotMoved))
{
// 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 ESM::ReadersCache::BusyItem reader = mReaders.get(index);
cell3.restore(*reader, i);
ESM::CellRef ref;
// Get each reference in turn
ESM::MovedCellRef cMRef;
bool deleted = false;
bool moved = false;
while (ESM::Cell::getNextRef(
*reader, ref, deleted, cMRef, moved, ESM::Cell::GetNextRefMode::LoadOnlyNotMoved))
if (moved)
continue;
// Don't load reference if it was moved to a different cell.
ESM::MovedCellRefTracker::const_iterator iter
= std::find(cell.mMovedRefs.begin(), cell.mMovedRefs.end(), ref.mRefNum);
if (iter != cell.mMovedRefs.end())
{
if (moved)
continue;
// Don't load reference if it was moved to a different cell.
ESM::MovedCellRefTracker::const_iterator iter
= std::find(cell3.mMovedRefs.begin(), cell3.mMovedRefs.end(), ref.mRefNum);
if (iter != cell3.mMovedRefs.end())
{
continue;
}
loadRef(ref, deleted, refNumToID);
continue;
}
}
catch (std::exception& e)
{
Log(Debug::Error) << "An error occurred loading references for cell " << getCell()->getDescription()
<< ": " << e.what();
loadRef(ref, deleted, refNumToID);
}
}
// Load moved references, from separately tracked list.
for (const auto& leasedRef : cell3.mLeasedRefs)
catch (std::exception& e)
{
ESM::CellRef& ref = const_cast<ESM::CellRef&>(leasedRef.first);
bool deleted = leasedRef.second;
Log(Debug::Error) << "An error occurred loading references for cell " << getCell()->getDescription()
<< ": " << e.what();
}
}
// Load moved references, from separately tracked list.
for (const auto& leasedRef : cell.mLeasedRefs)
{
ESM::CellRef& ref = const_cast<ESM::CellRef&>(leasedRef.first);
bool deleted = leasedRef.second;
loadRef(ref, deleted, refNumToID);
loadRef(ref, deleted, refNumToID);
}
}
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();
}
@ -1087,18 +1086,21 @@ namespace MWWorld
}
}
bool CellStore::operator==(const CellStore& right) const
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; };
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
template <class L, class R>
bool operator()(L, R) const
{
return false;
}
};
bool CellStore::operator==(const CellStore& right) const
{
return std::visit(Visitor{}, this->mCellVariant.mVariant, right.mCellVariant.mVariant);
}
void CellStore::setFog(std::unique_ptr<ESM::FogState>&& fog)

@ -386,6 +386,9 @@ namespace MWWorld
/// Run through references and store IDs
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 loadRef(const ESM4::Reference& ref, bool deleted);

@ -888,7 +888,7 @@ namespace MWWorld
loadingListener->setProgressRange(cell->count());
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());
// Load cell.

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

Loading…
Cancel
Save