Don't trigger onNewExterior while loading saves

pull/3236/head
Evil Eye 6 months ago
parent 57adb93075
commit 152073a42e

@ -630,6 +630,12 @@ namespace MWWorld
} }
void Store<ESM::Cell>::clearDynamic() void Store<ESM::Cell>::clearDynamic()
{ {
for (const auto& [_, cell] : mDynamicExt)
mCells.erase(cell->mId);
mDynamicExt.clear();
for (const auto& [_, cell] : mDynamicInt)
mCells.erase(cell->mId);
mDynamicInt.clear();
setUp(); setUp();
} }

@ -473,8 +473,8 @@ namespace MWWorld
mStore.write(writer, progress); // dynamic Store must be written (and read) before Cells, so that mStore.write(writer, progress); // dynamic Store must be written (and read) before Cells, so that
// references to custom made records will be recognized // references to custom made records will be recognized
mWorldModel.write(writer, progress); // the player's cell needs to be loaded before the player
mPlayer->write(writer, progress); mPlayer->write(writer, progress);
mWorldModel.write(writer, progress);
mGlobalVariables.write(writer, progress); mGlobalVariables.write(writer, progress);
mWeatherManager->write(writer, progress); mWeatherManager->write(writer, progress);
mProjectileManager->write(writer, progress); mProjectileManager->write(writer, progress);

@ -101,6 +101,24 @@ namespace MWWorld
return Cell(*cell); return Cell(*cell);
return std::nullopt; return std::nullopt;
} }
CellStore* getOrCreateExterior(const ESM::ExteriorCellLocation& location,
std::map<ESM::ExteriorCellLocation, MWWorld::CellStore*>& exteriors, ESMStore& store,
ESM::ReadersCache& readers, std::unordered_map<ESM::RefId, CellStore>& cells, bool triggerEvent)
{
if (const auto it = exteriors.find(location); it != exteriors.end())
{
assert(it->second != nullptr);
return it->second;
}
auto [cell, created] = createExteriorCell(location, store);
const ESM::RefId id = cell.getId();
CellStore* const cellStore = &emplaceCellStore(id, std::move(cell), store, readers, cells);
exteriors.emplace(location, cellStore);
if (created && triggerEvent)
MWBase::Environment::get().getLuaManager()->exteriorCreated(*cellStore);
return cellStore;
}
} }
} }
@ -178,23 +196,7 @@ namespace MWWorld
{ {
CellStore& WorldModel::getExterior(ESM::ExteriorCellLocation location, bool forceLoad) const CellStore& WorldModel::getExterior(ESM::ExteriorCellLocation location, bool forceLoad) const
{ {
const auto it = mExteriors.find(location); CellStore* cellStore = getOrCreateExterior(location, mExteriors, mStore, mReaders, mCells, true);
CellStore* cellStore = nullptr;
if (it == mExteriors.end())
{
auto [cell, created] = createExteriorCell(location, mStore);
const ESM::RefId id = cell.getId();
cellStore = &emplaceCellStore(id, std::move(cell), mStore, mReaders, mCells);
mExteriors.emplace(location, cellStore);
if (created)
MWBase::Environment::get().getLuaManager()->exteriorCreated(*cellStore);
}
else
{
assert(it->second != nullptr);
cellStore = it->second;
}
if (forceLoad && cellStore->getState() != CellStore::State_Loaded) if (forceLoad && cellStore->getState() != CellStore::State_Loaded)
cellStore->load(); cellStore->load();
@ -447,17 +449,26 @@ void MWWorld::WorldModel::write(ESM::ESMWriter& writer, Loading::Listener& progr
} }
} }
struct GetCellStoreCallback : public MWWorld::CellStore::GetCellStoreCallback struct MWWorld::WorldModel::GetCellStoreCallback : public CellStore::GetCellStoreCallback
{ {
public: public:
GetCellStoreCallback(MWWorld::WorldModel& worldModel) GetCellStoreCallback(WorldModel& worldModel)
: mWorldModel(worldModel) : mWorldModel(worldModel)
{ {
} }
MWWorld::WorldModel& mWorldModel; WorldModel& mWorldModel;
MWWorld::CellStore* getCellStore(const ESM::RefId& cellId) override { return mWorldModel.findCell(cellId); } CellStore* getCellStore(const ESM::RefId& cellId) override
{
if (const auto* exteriorId = cellId.getIf<ESM::ESM3ExteriorCellRefId>())
{
ESM::ExteriorCellLocation location(exteriorId->getX(), exteriorId->getY(), ESM::Cell::sDefaultWorldspaceId);
return getOrCreateExterior(
location, mWorldModel.mExteriors, mWorldModel.mStore, mWorldModel.mReaders, mWorldModel.mCells, false);
}
return mWorldModel.findCell(cellId);
}
}; };
bool MWWorld::WorldModel::readRecord(ESM::ESMReader& reader, uint32_t type) bool MWWorld::WorldModel::readRecord(ESM::ESMReader& reader, uint32_t type)
@ -467,7 +478,10 @@ bool MWWorld::WorldModel::readRecord(ESM::ESMReader& reader, uint32_t type)
ESM::CellState state; ESM::CellState state;
state.mId = reader.getCellId(); state.mId = reader.getCellId();
CellStore* const cellStore = findCell(state.mId); GetCellStoreCallback callback(*this);
CellStore* const cellStore = callback.getCellStore(state.mId);
if (cellStore == nullptr) if (cellStore == nullptr)
{ {
Log(Debug::Warning) << "Dropping state for cell " << state.mId << " (cell no longer exists)"; Log(Debug::Warning) << "Dropping state for cell " << state.mId << " (cell no longer exists)";
@ -484,8 +498,6 @@ bool MWWorld::WorldModel::readRecord(ESM::ESMReader& reader, uint32_t type)
if (cellStore->getState() != CellStore::State_Loaded) if (cellStore->getState() != CellStore::State_Loaded)
cellStore->load(); cellStore->load();
GetCellStoreCallback callback(*this);
cellStore->readReferences(reader, &callback); cellStore->readReferences(reader, &callback);
return true; return true;

@ -104,6 +104,8 @@ namespace MWWorld
bool readRecord(ESM::ESMReader& reader, uint32_t type); bool readRecord(ESM::ESMReader& reader, uint32_t type);
private: private:
struct GetCellStoreCallback;
PtrRegistry mPtrRegistry; // defined before mCells because during destruction it should be the last PtrRegistry mPtrRegistry; // defined before mCells because during destruction it should be the last
MWWorld::ESMStore& mStore; MWWorld::ESMStore& mStore;

Loading…
Cancel
Save