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

ESM3 Cells have an Id.

Store<ESM::Cell> is updated to use it.
This commit is contained in:
florent.teppe 2023-02-18 22:32:27 +01:00
parent b04bcb9a9b
commit 36502eaf75
8 changed files with 71 additions and 36 deletions

View file

@ -20,6 +20,7 @@ namespace MWWorld
.mWorldspace{ Misc::StringUtils::lowerCase(cell.mEditorId) }, .mWorldspace{ Misc::StringUtils::lowerCase(cell.mEditorId) },
.mIndex{ cell.getGridX(), cell.getGridY() }, .mIndex{ cell.getGridX(), cell.getGridY() },
.mPaged = isExterior(),} .mPaged = isExterior(),}
, mId(cell.mId)
,mMood{ ,mMood{
.mAmbiantColor = cell.mLighting.ambient, .mAmbiantColor = cell.mLighting.ambient,
.mDirectionalColor = cell.mLighting.directional, .mDirectionalColor = cell.mLighting.directional,
@ -41,6 +42,7 @@ namespace MWWorld
, mNameID(cell.mName) , mNameID(cell.mName)
, mRegion(cell.mRegion) , mRegion(cell.mRegion)
, mCellId(cell.getCellId()) , mCellId(cell.getCellId())
, mId(cell.mId)
, mMood{ , mMood{
.mAmbiantColor = cell.mAmbi.mAmbient, .mAmbiantColor = cell.mAmbi.mAmbient,
.mDirectionalColor = cell.mAmbi.mSunlight, .mDirectionalColor = cell.mAmbi.mSunlight,

View file

@ -49,6 +49,7 @@ namespace MWWorld
std::string getDescription() const; std::string getDescription() const;
const MoodData& getMood() const { return mMood; } const MoodData& getMood() const { return mMood; }
float getWaterHeight() const { return mWaterHeight; } float getWaterHeight() const { return mWaterHeight; }
const ESM::RefId& getId() const { return mId; };
private: private:
bool mIsExterior; bool mIsExterior;
@ -61,6 +62,7 @@ namespace MWWorld
std::string mNameID; // The name that will be used by the script and console commands std::string mNameID; // The name that will be used by the script and console commands
ESM::RefId mRegion; ESM::RefId mRegion;
ESM::CellId mCellId; ESM::CellId mCellId;
ESM::RefId mId;
MoodData mMood; MoodData mMood;
float mWaterHeight; float mWaterHeight;

View file

@ -468,13 +468,17 @@ namespace MWWorld
// Cell // Cell
//========================================================================= //=========================================================================
const ESM::Cell* Store<ESM::Cell>::search(const ESM::RefId& cellId) const
{
auto foundCellIt = mCells.find(cellId);
if (foundCellIt == mCells.end())
return &foundCellIt->second;
return nullptr;
}
const ESM::Cell* Store<ESM::Cell>::search(const ESM::Cell& cell) const const ESM::Cell* Store<ESM::Cell>::search(const ESM::Cell& cell) const
{ {
if (cell.isExterior()) return search(cell.mId);
{
return search(cell.getGridX(), cell.getGridY());
}
return search(cell.mName);
} }
// this method *must* be called right after esm3.loadCell() // this method *must* be called right after esm3.loadCell()
@ -521,13 +525,13 @@ namespace MWWorld
DynamicInt::const_iterator it = mInt.find(name); DynamicInt::const_iterator it = mInt.find(name);
if (it != mInt.end()) if (it != mInt.end())
{ {
return &(it->second); return it->second;
} }
DynamicInt::const_iterator dit = mDynamicInt.find(name); DynamicInt::const_iterator dit = mDynamicInt.find(name);
if (dit != mDynamicInt.end()) if (dit != mDynamicInt.end())
{ {
return &dit->second; return dit->second;
} }
return nullptr; return nullptr;
@ -537,11 +541,11 @@ namespace MWWorld
std::pair<int, int> key(x, y); std::pair<int, int> key(x, y);
DynamicExt::const_iterator it = mExt.find(key); DynamicExt::const_iterator it = mExt.find(key);
if (it != mExt.end()) if (it != mExt.end())
return &(it->second); return it->second;
DynamicExt::const_iterator dit = mDynamicExt.find(key); DynamicExt::const_iterator dit = mDynamicExt.find(key);
if (dit != mDynamicExt.end()) if (dit != mDynamicExt.end())
return &dit->second; return dit->second;
return nullptr; return nullptr;
} }
@ -549,7 +553,7 @@ namespace MWWorld
{ {
DynamicExt::const_iterator it = mExt.find(std::make_pair(x, y)); DynamicExt::const_iterator it = mExt.find(std::make_pair(x, y));
if (it != mExt.end()) if (it != mExt.end())
return &(it->second); return (it->second);
return nullptr; return nullptr;
} }
const ESM::Cell* Store<ESM::Cell>::searchOrCreate(int x, int y) const ESM::Cell* Store<ESM::Cell>::searchOrCreate(int x, int y)
@ -557,11 +561,11 @@ namespace MWWorld
std::pair<int, int> key(x, y); std::pair<int, int> key(x, y);
DynamicExt::const_iterator it = mExt.find(key); DynamicExt::const_iterator it = mExt.find(key);
if (it != mExt.end()) if (it != mExt.end())
return &(it->second); return (it->second);
DynamicExt::const_iterator dit = mDynamicExt.find(key); DynamicExt::const_iterator dit = mDynamicExt.find(key);
if (dit != mDynamicExt.end()) if (dit != mDynamicExt.end())
return &dit->second; return dit->second;
ESM::Cell newCell; ESM::Cell newCell;
newCell.mData.mX = x; newCell.mData.mX = x;
@ -574,8 +578,11 @@ namespace MWWorld
newCell.mCellId.mPaged = true; newCell.mCellId.mPaged = true;
newCell.mCellId.mIndex.mX = x; newCell.mCellId.mIndex.mX = x;
newCell.mCellId.mIndex.mY = y; newCell.mCellId.mIndex.mY = y;
newCell.updateId();
return &mExt.insert(std::make_pair(key, newCell)).first->second; ESM::Cell* newCellInserted = &mCells.insert(std::make_pair(newCell.mId, newCell)).first->second;
return mExt.insert(std::make_pair(key, newCellInserted)).first->second;
} }
const ESM::Cell* Store<ESM::Cell>::find(std::string_view id) const const ESM::Cell* Store<ESM::Cell>::find(std::string_view id) const
{ {
@ -607,12 +614,12 @@ namespace MWWorld
mSharedInt.clear(); mSharedInt.clear();
mSharedInt.reserve(mInt.size()); mSharedInt.reserve(mInt.size());
for (auto& [_, cell] : mInt) for (auto& [_, cell] : mInt)
mSharedInt.push_back(&cell); mSharedInt.push_back(cell);
mSharedExt.clear(); mSharedExt.clear();
mSharedExt.reserve(mExt.size()); mSharedExt.reserve(mExt.size());
for (auto& [_, cell] : mExt) for (auto& [_, cell] : mExt)
mSharedExt.push_back(&cell); mSharedExt.push_back(cell);
} }
RecordId Store<ESM::Cell>::load(ESM::ESMReader& esm) RecordId Store<ESM::Cell>::load(ESM::ESMReader& esm)
{ {
@ -622,13 +629,17 @@ namespace MWWorld
// are not available until both cells have been loaded at least partially! // are not available until both cells have been loaded at least partially!
// All cells have a name record, even nameless exterior cells. // All cells have a name record, even nameless exterior cells.
ESM::Cell cell; ESM::Cell* emplacedCell = nullptr;
bool isDeleted = false; bool isDeleted = false;
{
ESM::Cell cellToLoad;
cellToLoad.loadNameAndData(esm, isDeleted);
emplacedCell = &mCells.insert(std::make_pair(cellToLoad.mId, cellToLoad)).first->second;
}
ESM::Cell& cell = *emplacedCell;
// Load the (x,y) coordinates of the cell, if it is an exterior cell, // Load the (x,y) coordinates of the cell, if it is an exterior cell,
// so we can find the cell we need to merge with // so we can find the cell we need to merge with
cell.loadNameAndData(esm, isDeleted);
if (cell.mData.mFlags & ESM::Cell::Interior) if (cell.mData.mFlags & ESM::Cell::Interior)
{ {
// Store interior cell by name, try to merge with existing parent data. // Store interior cell by name, try to merge with existing parent data.
@ -647,7 +658,7 @@ namespace MWWorld
// spawn a new cell // spawn a new cell
cell.loadCell(esm, true); cell.loadCell(esm, true);
mInt[cell.mName] = cell; mInt[cell.mName] = &cell;
} }
} }
else else
@ -700,19 +711,19 @@ namespace MWWorld
else else
{ {
// spawn a new cell // spawn a new cell
cell.loadCell(esm, false); emplacedCell->loadCell(esm, false);
// handle moved ref (MVRF) subrecords // handle moved ref (MVRF) subrecords
handleMovedCellRefs(esm, &cell); handleMovedCellRefs(esm, emplacedCell);
// push the new references on the list of references to manage // push the new references on the list of references to manage
cell.postLoad(esm); emplacedCell->postLoad(esm);
mExt[std::make_pair(cell.mData.mX, cell.mData.mY)] = cell; mExt[std::make_pair(cell.mData.mX, cell.mData.mY)] = &cell;
} }
} }
return RecordId(ESM::RefId::stringRefId(cell.mName), isDeleted); return RecordId(cell.mId, isDeleted);
} }
Store<ESM::Cell>::iterator Store<ESM::Cell>::intBegin() const Store<ESM::Cell>::iterator Store<ESM::Cell>::intBegin() const
{ {
@ -785,6 +796,7 @@ namespace MWWorld
} }
ESM::Cell* Store<ESM::Cell>::insert(const ESM::Cell& cell) ESM::Cell* Store<ESM::Cell>::insert(const ESM::Cell& cell)
{ {
ESM::Cell* insertedCell = &mCells.emplace(cell.mId, cell).first->second;
if (search(cell) != nullptr) if (search(cell) != nullptr)
{ {
const std::string cellType = (cell.isExterior()) ? "exterior" : "interior"; const std::string cellType = (cell.isExterior()) ? "exterior" : "interior";
@ -795,16 +807,16 @@ namespace MWWorld
std::pair<int, int> key(cell.getGridX(), cell.getGridY()); std::pair<int, int> key(cell.getGridX(), cell.getGridY());
// duplicate insertions are avoided by search(ESM::Cell &) // duplicate insertions are avoided by search(ESM::Cell &)
DynamicExt::iterator result = mDynamicExt.emplace(key, cell).first; DynamicExt::iterator result = mDynamicExt.emplace(key, insertedCell).first;
mSharedExt.push_back(&result->second); mSharedExt.push_back(result->second);
return &result->second; return result->second;
} }
else else
{ {
// duplicate insertions are avoided by search(ESM::Cell &) // duplicate insertions are avoided by search(ESM::Cell &)
DynamicInt::iterator result = mDynamicInt.emplace(cell.mName, cell).first; DynamicInt::iterator result = mDynamicInt.emplace(cell.mName, insertedCell).first;
mSharedInt.push_back(&result->second); mSharedInt.push_back(result->second);
return &result->second; return result->second;
} }
} }
bool Store<ESM::Cell>::erase(const ESM::Cell& cell) bool Store<ESM::Cell>::erase(const ESM::Cell& cell)
@ -828,7 +840,7 @@ namespace MWWorld
for (it = mDynamicInt.begin(); it != mDynamicInt.end(); ++it) for (it = mDynamicInt.begin(); it != mDynamicInt.end(); ++it)
{ {
mSharedInt.push_back(&it->second); mSharedInt.push_back(it->second);
} }
return true; return true;
@ -847,7 +859,7 @@ namespace MWWorld
for (it = mDynamicExt.begin(); it != mDynamicExt.end(); ++it) for (it = mDynamicExt.begin(); it != mDynamicExt.end(); ++it)
{ {
mSharedExt.push_back(&it->second); mSharedExt.push_back(it->second);
} }
return true; return true;

View file

@ -347,10 +347,12 @@ namespace MWWorld
} }
}; };
typedef std::unordered_map<std::string, ESM::Cell, Misc::StringUtils::CiHash, Misc::StringUtils::CiEqual> typedef std::unordered_map<std::string, ESM::Cell*, Misc::StringUtils::CiHash, Misc::StringUtils::CiEqual>
DynamicInt; DynamicInt;
typedef std::map<std::pair<int, int>, ESM::Cell, DynamicExtCmp> DynamicExt; typedef std::map<std::pair<int, int>, ESM::Cell*, DynamicExtCmp> DynamicExt;
std::unordered_map<ESM::RefId, ESM::Cell> mCells;
DynamicInt mInt; DynamicInt mInt;
DynamicExt mExt; DynamicExt mExt;
@ -367,6 +369,7 @@ namespace MWWorld
public: public:
typedef SharedIterator<ESM::Cell> iterator; typedef SharedIterator<ESM::Cell> iterator;
const ESM::Cell* search(const ESM::RefId& id) const;
const ESM::Cell* search(std::string_view id) const; const ESM::Cell* search(std::string_view id) const;
const ESM::Cell* search(int x, int y) const; const ESM::Cell* search(int x, int y) const;
const ESM::Cell* searchStatic(int x, int y) const; const ESM::Cell* searchStatic(int x, int y) const;

View file

@ -180,6 +180,7 @@ MWWorld::CellStore* MWWorld::WorldModel::getExterior(int x, int y)
record.mData.mY = y; record.mData.mY = y;
record.mWater = 0; record.mWater = 0;
record.mMapColor = 0; record.mMapColor = 0;
record.updateId();
cell = MWBase::Environment::get().getWorld()->createRecord(record); cell = MWBase::Environment::get().getWorld()->createRecord(record);
} }

View file

@ -562,7 +562,7 @@ namespace
REGISTER_TYPED_TEST_SUITE_P(StoreSaveLoadTest, shouldNotChangeRefId); REGISTER_TYPED_TEST_SUITE_P(StoreSaveLoadTest, shouldNotChangeRefId);
static_assert(std::tuple_size_v<RecordTypesWithSave> == 38); static_assert(std::tuple_size_v<RecordTypesWithSave> == 39);
INSTANTIATE_TYPED_TEST_SUITE_P( INSTANTIATE_TYPED_TEST_SUITE_P(
RecordTypesTest, StoreSaveLoadTest, typename AsTestingTypes<RecordTypesWithSave>::Type); RecordTypesTest, StoreSaveLoadTest, typename AsTestingTypes<RecordTypesWithSave>::Type);

View file

@ -57,6 +57,19 @@ namespace ESM
loadCell(esm, saveContext); loadCell(esm, saveContext);
} }
const ESM::RefId& Cell::updateId()
{
if (isExterior())
{
mId = ESM::RefId::stringRefId("#" + std::to_string(mData.mX) + "," + std::to_string(mData.mY));
}
else
{
mId = ESM::RefId::stringRefId(mName);
}
return mId;
}
void Cell::loadNameAndData(ESMReader& esm, bool& isDeleted) void Cell::loadNameAndData(ESMReader& esm, bool& isDeleted)
{ {
isDeleted = false; isDeleted = false;
@ -105,6 +118,7 @@ namespace ESM
mCellId.mIndex.mX = 0; mCellId.mIndex.mX = 0;
mCellId.mIndex.mY = 0; mCellId.mIndex.mY = 0;
} }
updateId();
} }
void Cell::loadCell(ESMReader& esm, bool saveContext) void Cell::loadCell(ESMReader& esm, bool saveContext)

View file

@ -110,7 +110,7 @@ namespace ESM
, mRefNumCounter(0) , mRefNumCounter(0)
{ {
} }
ESM::RefId mId;
// Interior cells are indexed by this (it's the 'id'), for exterior // Interior cells are indexed by this (it's the 'id'), for exterior
// cells it is optional. // cells it is optional.
std::string mName; std::string mName;
@ -192,6 +192,7 @@ namespace ESM
///< Set record to default state (does not touch the ID/index). ///< Set record to default state (does not touch the ID/index).
const CellId& getCellId() const; const CellId& getCellId() const;
const ESM::RefId& updateId();
}; };
} }
#endif #endif