mirror of
https://github.com/OpenMW/openmw.git
synced 2025-03-31 00:36:40 +00:00
ESM3 Cells have an Id.
Store<ESM::Cell> is updated to use it.
This commit is contained in:
parent
b04bcb9a9b
commit
36502eaf75
8 changed files with 71 additions and 36 deletions
|
@ -20,6 +20,7 @@ namespace MWWorld
|
|||
.mWorldspace{ Misc::StringUtils::lowerCase(cell.mEditorId) },
|
||||
.mIndex{ cell.getGridX(), cell.getGridY() },
|
||||
.mPaged = isExterior(),}
|
||||
, mId(cell.mId)
|
||||
,mMood{
|
||||
.mAmbiantColor = cell.mLighting.ambient,
|
||||
.mDirectionalColor = cell.mLighting.directional,
|
||||
|
@ -41,6 +42,7 @@ namespace MWWorld
|
|||
, mNameID(cell.mName)
|
||||
, mRegion(cell.mRegion)
|
||||
, mCellId(cell.getCellId())
|
||||
, mId(cell.mId)
|
||||
, mMood{
|
||||
.mAmbiantColor = cell.mAmbi.mAmbient,
|
||||
.mDirectionalColor = cell.mAmbi.mSunlight,
|
||||
|
|
|
@ -49,6 +49,7 @@ namespace MWWorld
|
|||
std::string getDescription() const;
|
||||
const MoodData& getMood() const { return mMood; }
|
||||
float getWaterHeight() const { return mWaterHeight; }
|
||||
const ESM::RefId& getId() const { return mId; };
|
||||
|
||||
private:
|
||||
bool mIsExterior;
|
||||
|
@ -61,6 +62,7 @@ namespace MWWorld
|
|||
std::string mNameID; // The name that will be used by the script and console commands
|
||||
ESM::RefId mRegion;
|
||||
ESM::CellId mCellId;
|
||||
ESM::RefId mId;
|
||||
MoodData mMood;
|
||||
|
||||
float mWaterHeight;
|
||||
|
|
|
@ -468,13 +468,17 @@ namespace MWWorld
|
|||
// 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
|
||||
{
|
||||
if (cell.isExterior())
|
||||
{
|
||||
return search(cell.getGridX(), cell.getGridY());
|
||||
}
|
||||
return search(cell.mName);
|
||||
return search(cell.mId);
|
||||
}
|
||||
|
||||
// this method *must* be called right after esm3.loadCell()
|
||||
|
@ -521,13 +525,13 @@ namespace MWWorld
|
|||
DynamicInt::const_iterator it = mInt.find(name);
|
||||
if (it != mInt.end())
|
||||
{
|
||||
return &(it->second);
|
||||
return it->second;
|
||||
}
|
||||
|
||||
DynamicInt::const_iterator dit = mDynamicInt.find(name);
|
||||
if (dit != mDynamicInt.end())
|
||||
{
|
||||
return &dit->second;
|
||||
return dit->second;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
|
@ -537,11 +541,11 @@ namespace MWWorld
|
|||
std::pair<int, int> key(x, y);
|
||||
DynamicExt::const_iterator it = mExt.find(key);
|
||||
if (it != mExt.end())
|
||||
return &(it->second);
|
||||
return it->second;
|
||||
|
||||
DynamicExt::const_iterator dit = mDynamicExt.find(key);
|
||||
if (dit != mDynamicExt.end())
|
||||
return &dit->second;
|
||||
return dit->second;
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -549,7 +553,7 @@ namespace MWWorld
|
|||
{
|
||||
DynamicExt::const_iterator it = mExt.find(std::make_pair(x, y));
|
||||
if (it != mExt.end())
|
||||
return &(it->second);
|
||||
return (it->second);
|
||||
return nullptr;
|
||||
}
|
||||
const ESM::Cell* Store<ESM::Cell>::searchOrCreate(int x, int y)
|
||||
|
@ -557,11 +561,11 @@ namespace MWWorld
|
|||
std::pair<int, int> key(x, y);
|
||||
DynamicExt::const_iterator it = mExt.find(key);
|
||||
if (it != mExt.end())
|
||||
return &(it->second);
|
||||
return (it->second);
|
||||
|
||||
DynamicExt::const_iterator dit = mDynamicExt.find(key);
|
||||
if (dit != mDynamicExt.end())
|
||||
return &dit->second;
|
||||
return dit->second;
|
||||
|
||||
ESM::Cell newCell;
|
||||
newCell.mData.mX = x;
|
||||
|
@ -574,8 +578,11 @@ namespace MWWorld
|
|||
newCell.mCellId.mPaged = true;
|
||||
newCell.mCellId.mIndex.mX = x;
|
||||
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
|
||||
{
|
||||
|
@ -607,12 +614,12 @@ namespace MWWorld
|
|||
mSharedInt.clear();
|
||||
mSharedInt.reserve(mInt.size());
|
||||
for (auto& [_, cell] : mInt)
|
||||
mSharedInt.push_back(&cell);
|
||||
mSharedInt.push_back(cell);
|
||||
|
||||
mSharedExt.clear();
|
||||
mSharedExt.reserve(mExt.size());
|
||||
for (auto& [_, cell] : mExt)
|
||||
mSharedExt.push_back(&cell);
|
||||
mSharedExt.push_back(cell);
|
||||
}
|
||||
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!
|
||||
|
||||
// All cells have a name record, even nameless exterior cells.
|
||||
ESM::Cell cell;
|
||||
ESM::Cell* emplacedCell = nullptr;
|
||||
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,
|
||||
// so we can find the cell we need to merge with
|
||||
cell.loadNameAndData(esm, isDeleted);
|
||||
|
||||
if (cell.mData.mFlags & ESM::Cell::Interior)
|
||||
{
|
||||
// Store interior cell by name, try to merge with existing parent data.
|
||||
|
@ -647,7 +658,7 @@ namespace MWWorld
|
|||
// spawn a new cell
|
||||
cell.loadCell(esm, true);
|
||||
|
||||
mInt[cell.mName] = cell;
|
||||
mInt[cell.mName] = &cell;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -700,19 +711,19 @@ namespace MWWorld
|
|||
else
|
||||
{
|
||||
// spawn a new cell
|
||||
cell.loadCell(esm, false);
|
||||
emplacedCell->loadCell(esm, false);
|
||||
|
||||
// handle moved ref (MVRF) subrecords
|
||||
handleMovedCellRefs(esm, &cell);
|
||||
handleMovedCellRefs(esm, emplacedCell);
|
||||
|
||||
// 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
|
||||
{
|
||||
|
@ -785,6 +796,7 @@ namespace MWWorld
|
|||
}
|
||||
ESM::Cell* Store<ESM::Cell>::insert(const ESM::Cell& cell)
|
||||
{
|
||||
ESM::Cell* insertedCell = &mCells.emplace(cell.mId, cell).first->second;
|
||||
if (search(cell) != nullptr)
|
||||
{
|
||||
const std::string cellType = (cell.isExterior()) ? "exterior" : "interior";
|
||||
|
@ -795,16 +807,16 @@ namespace MWWorld
|
|||
std::pair<int, int> key(cell.getGridX(), cell.getGridY());
|
||||
|
||||
// duplicate insertions are avoided by search(ESM::Cell &)
|
||||
DynamicExt::iterator result = mDynamicExt.emplace(key, cell).first;
|
||||
mSharedExt.push_back(&result->second);
|
||||
return &result->second;
|
||||
DynamicExt::iterator result = mDynamicExt.emplace(key, insertedCell).first;
|
||||
mSharedExt.push_back(result->second);
|
||||
return result->second;
|
||||
}
|
||||
else
|
||||
{
|
||||
// duplicate insertions are avoided by search(ESM::Cell &)
|
||||
DynamicInt::iterator result = mDynamicInt.emplace(cell.mName, cell).first;
|
||||
mSharedInt.push_back(&result->second);
|
||||
return &result->second;
|
||||
DynamicInt::iterator result = mDynamicInt.emplace(cell.mName, insertedCell).first;
|
||||
mSharedInt.push_back(result->second);
|
||||
return result->second;
|
||||
}
|
||||
}
|
||||
bool Store<ESM::Cell>::erase(const ESM::Cell& cell)
|
||||
|
@ -828,7 +840,7 @@ namespace MWWorld
|
|||
|
||||
for (it = mDynamicInt.begin(); it != mDynamicInt.end(); ++it)
|
||||
{
|
||||
mSharedInt.push_back(&it->second);
|
||||
mSharedInt.push_back(it->second);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -847,7 +859,7 @@ namespace MWWorld
|
|||
|
||||
for (it = mDynamicExt.begin(); it != mDynamicExt.end(); ++it)
|
||||
{
|
||||
mSharedExt.push_back(&it->second);
|
||||
mSharedExt.push_back(it->second);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
|
@ -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;
|
||||
|
||||
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;
|
||||
DynamicExt mExt;
|
||||
|
@ -367,6 +369,7 @@ namespace MWWorld
|
|||
public:
|
||||
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(int x, int y) const;
|
||||
const ESM::Cell* searchStatic(int x, int y) const;
|
||||
|
|
|
@ -180,6 +180,7 @@ MWWorld::CellStore* MWWorld::WorldModel::getExterior(int x, int y)
|
|||
record.mData.mY = y;
|
||||
record.mWater = 0;
|
||||
record.mMapColor = 0;
|
||||
record.updateId();
|
||||
|
||||
cell = MWBase::Environment::get().getWorld()->createRecord(record);
|
||||
}
|
||||
|
|
|
@ -562,7 +562,7 @@ namespace
|
|||
|
||||
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(
|
||||
RecordTypesTest, StoreSaveLoadTest, typename AsTestingTypes<RecordTypesWithSave>::Type);
|
||||
|
|
|
@ -57,6 +57,19 @@ namespace ESM
|
|||
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)
|
||||
{
|
||||
isDeleted = false;
|
||||
|
@ -105,6 +118,7 @@ namespace ESM
|
|||
mCellId.mIndex.mX = 0;
|
||||
mCellId.mIndex.mY = 0;
|
||||
}
|
||||
updateId();
|
||||
}
|
||||
|
||||
void Cell::loadCell(ESMReader& esm, bool saveContext)
|
||||
|
|
|
@ -110,7 +110,7 @@ namespace ESM
|
|||
, mRefNumCounter(0)
|
||||
{
|
||||
}
|
||||
|
||||
ESM::RefId mId;
|
||||
// Interior cells are indexed by this (it's the 'id'), for exterior
|
||||
// cells it is optional.
|
||||
std::string mName;
|
||||
|
@ -192,6 +192,7 @@ namespace ESM
|
|||
///< Set record to default state (does not touch the ID/index).
|
||||
|
||||
const CellId& getCellId() const;
|
||||
const ESM::RefId& updateId();
|
||||
};
|
||||
}
|
||||
#endif
|
||||
|
|
Loading…
Reference in a new issue