mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-01-18 13:12:50 +00:00
maps with tuple key instead of map of map
instead of using a map with key as exterior and map of <int ,int >, Cell as value we use a single map with a tuple x,y,exterior as key
This commit is contained in:
parent
d8a782425b
commit
1d03b54694
@ -1107,30 +1107,21 @@ namespace MWWorld
|
||||
|
||||
const ESM4::Cell* Store<ESM4::Cell>::searchExterior(int x, int y, ESM::RefId worldSpace) const
|
||||
{
|
||||
const auto foundWorldSpace = mExteriors.find(worldSpace);
|
||||
if (foundWorldSpace == mExteriors.end())
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
const auto foundCell = foundWorldSpace->second.find(std::make_pair(x, y));
|
||||
if (foundCell == foundWorldSpace->second.end())
|
||||
const auto foundCell = mExteriors.find({ x, y, worldSpace });
|
||||
if (foundCell == mExteriors.end())
|
||||
return nullptr;
|
||||
return foundCell->second;
|
||||
}
|
||||
|
||||
bool Store<ESM4::Cell>::exteriorExists(ESM::RefId worldspace) const
|
||||
{
|
||||
const auto foundWorldSpace = mExteriors.find(worldspace);
|
||||
return (foundWorldSpace != mExteriors.end());
|
||||
}
|
||||
|
||||
ESM4::Cell* Store<ESM4::Cell>::insert(const ESM4::Cell& item, bool overrideOnly)
|
||||
{
|
||||
auto cellPtr = TypedDynamicStore<ESM4::Cell>::insert(item, overrideOnly);
|
||||
if (!cellPtr->mEditorId.empty())
|
||||
mCellNameIndex[cellPtr->mEditorId] = cellPtr;
|
||||
if (cellPtr->isExterior())
|
||||
mExteriors[cellPtr->mParent][std::make_pair(cellPtr->getGridX(), cellPtr->getGridY())] = cellPtr;
|
||||
{
|
||||
mExteriors[{ cellPtr->mX, cellPtr->mY, cellPtr->mParent }] = cellPtr;
|
||||
}
|
||||
|
||||
return cellPtr;
|
||||
}
|
||||
@ -1141,7 +1132,7 @@ namespace MWWorld
|
||||
if (!cellPtr->mEditorId.empty())
|
||||
mCellNameIndex[cellPtr->mEditorId] = cellPtr;
|
||||
if (cellPtr->isExterior())
|
||||
mExteriors[cellPtr->mParent][std::make_pair(cellPtr->getGridX(), cellPtr->getGridY())] = cellPtr;
|
||||
mExteriors[{ cellPtr->mX, cellPtr->mY, cellPtr->mParent }] = cellPtr;
|
||||
|
||||
return cellPtr;
|
||||
}
|
||||
@ -1153,7 +1144,7 @@ namespace MWWorld
|
||||
ESM4::Cell& cellToDelete = cellToDeleteIt.second;
|
||||
if (cellToDelete.isExterior())
|
||||
{
|
||||
mExteriors[cellToDelete.mParent].erase(std::make_pair(cellToDelete.mX, cellToDelete.mY));
|
||||
mExteriors.erase({ cellToDelete.mX, cellToDelete.mY, cellToDelete.mParent });
|
||||
}
|
||||
if (!cellToDelete.mEditorId.empty())
|
||||
mCellNameIndex.erase(cellToDelete.mEditorId);
|
||||
|
@ -9,6 +9,7 @@
|
||||
#include <vector>
|
||||
|
||||
#include <components/esm/refid.hpp>
|
||||
#include <components/esm/util.hpp>
|
||||
#include <components/esm3/loadcell.hpp>
|
||||
#include <components/esm3/loaddial.hpp>
|
||||
#include <components/esm3/loadglob.hpp>
|
||||
@ -283,12 +284,12 @@ namespace MWWorld
|
||||
{
|
||||
std::unordered_map<std::string, ESM4::Cell*, Misc::StringUtils::CiHash, Misc::StringUtils::CiEqual>
|
||||
mCellNameIndex;
|
||||
std::unordered_map<ESM::RefId, std::map<std::pair<int, int>, ESM4::Cell*>> mExteriors;
|
||||
|
||||
std::unordered_map<ESM::ExteriorCellIndex, ESM4::Cell*> mExteriors;
|
||||
|
||||
public:
|
||||
const ESM4::Cell* searchCellName(std::string_view) const;
|
||||
const ESM4::Cell* searchExterior(int x, int y, ESM::RefId worldSpace) const;
|
||||
bool exteriorExists(ESM::RefId worldspace) const;
|
||||
ESM4::Cell* insert(const ESM4::Cell& item, bool overrideOnly = false);
|
||||
ESM4::Cell* insertStatic(const ESM4::Cell& item);
|
||||
void clearDynamic() override;
|
||||
|
@ -76,12 +76,11 @@ MWWorld::CellStore& MWWorld::WorldModel::getCellStore(const ESM::Cell* cell)
|
||||
}
|
||||
else
|
||||
{
|
||||
auto& Esm3Exteriors = mExteriors[ESM::Cell::sDefaultWorldspaceId];
|
||||
std::map<std::pair<int, int>, CellStore*>::iterator result
|
||||
= Esm3Exteriors.find(std::make_pair(cell->getGridX(), cell->getGridY()));
|
||||
ESM::ExteriorCellIndex extIndex = { cell->getGridX(), cell->getGridY(), ESM::Cell::sDefaultWorldspaceId };
|
||||
std::map<ESM::ExteriorCellIndex, CellStore*>::iterator result = mExteriors.find(extIndex);
|
||||
|
||||
if (result == Esm3Exteriors.end())
|
||||
result = Esm3Exteriors.emplace(std::make_pair(cell->getGridX(), cell->getGridY()), cellStore).first;
|
||||
if (result == mExteriors.end())
|
||||
result = mExteriors.emplace(extIndex, cellStore).first;
|
||||
|
||||
return *result->second;
|
||||
}
|
||||
@ -163,14 +162,14 @@ MWWorld::WorldModel::WorldModel(const MWWorld::ESMStore& store, ESM::ReadersCach
|
||||
|
||||
MWWorld::CellStore& MWWorld::WorldModel::getExterior(int x, int y, ESM::RefId exteriorWorldspace)
|
||||
{
|
||||
auto foundWorldspace = mExteriors.find(exteriorWorldspace);
|
||||
std::map<std::pair<int, int>, CellStore*>::iterator result;
|
||||
if (exteriorWorldspace == ESM::Cell::sDefaultWorldspaceId)
|
||||
{
|
||||
auto& esm3Exteriors = mExteriors[exteriorWorldspace];
|
||||
result = esm3Exteriors.find(std::make_pair(x, y));
|
||||
std::map<ESM::ExteriorCellIndex, CellStore*>::iterator result;
|
||||
ESM::ExteriorCellIndex extIndex = { x, y, exteriorWorldspace };
|
||||
|
||||
if (result == esm3Exteriors.end())
|
||||
result = mExteriors.find({ x, y, exteriorWorldspace });
|
||||
|
||||
if (result == mExteriors.end())
|
||||
{
|
||||
if (exteriorWorldspace == ESM::Cell::sDefaultWorldspaceId)
|
||||
{
|
||||
const ESM::Cell* cell = mStore.get<ESM::Cell>().search(x, y);
|
||||
|
||||
@ -190,21 +189,15 @@ MWWorld::CellStore& MWWorld::WorldModel::getExterior(int x, int y, ESM::RefId ex
|
||||
|
||||
CellStore* cellStore
|
||||
= &mCells.emplace(cell->mId, CellStore(MWWorld::Cell(*cell), mStore, mReaders)).first->second;
|
||||
result = esm3Exteriors.emplace(std::make_pair(x, y), cellStore).first;
|
||||
result = mExteriors.emplace(extIndex, cellStore).first;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
const Store<ESM4::Cell>& cell4Store = mStore.get<ESM4::Cell>();
|
||||
if (cell4Store.exteriorExists(exteriorWorldspace))
|
||||
else
|
||||
{
|
||||
auto& exteriors = mExteriors[exteriorWorldspace];
|
||||
|
||||
result = exteriors.find(std::make_pair(x, y));
|
||||
|
||||
if (result == exteriors.end())
|
||||
const Store<ESM4::Cell>& cell4Store = mStore.get<ESM4::Cell>();
|
||||
bool exteriorExists = mStore.get<ESM4::World>().search(exteriorWorldspace);
|
||||
const ESM4::Cell* cell = cell4Store.searchExterior(x, y, exteriorWorldspace);
|
||||
if (exteriorExists)
|
||||
{
|
||||
const ESM4::Cell* cell = cell4Store.searchExterior(x, y, exteriorWorldspace);
|
||||
if (!cell)
|
||||
{
|
||||
ESM4::Cell record;
|
||||
@ -216,15 +209,14 @@ MWWorld::CellStore& MWWorld::WorldModel::getExterior(int x, int y, ESM::RefId ex
|
||||
}
|
||||
CellStore* cellStore
|
||||
= &mCells.emplace(cell->mId, CellStore(MWWorld::Cell(*cell), mStore, mReaders)).first->second;
|
||||
result = exteriors.emplace(std::make_pair(x, y), cellStore).first;
|
||||
result = mExteriors.emplace(extIndex, cellStore).first;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw std::runtime_error("exterior not found: '" + exteriorWorldspace.toDebugString() + "'");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
throw std::runtime_error("exterior not found: '" + exteriorWorldspace.toDebugString() + "'");
|
||||
}
|
||||
}
|
||||
|
||||
if (result->second->getState() != CellStore::State_Loaded)
|
||||
{
|
||||
result->second->load();
|
||||
@ -287,7 +279,8 @@ MWWorld::CellStore& MWWorld::WorldModel::getCell(const ESM::RefId& id)
|
||||
{
|
||||
std::pair<int, int> coord
|
||||
= std::make_pair(newCellStore->getCell()->getGridX(), newCellStore->getCell()->getGridY());
|
||||
mExteriors[newCellStore->getCell()->getWorldSpace()].emplace(coord, newCellStore);
|
||||
ESM::ExteriorCellIndex extIndex = { coord.first, coord.second, newCellStore->getCell()->getWorldSpace() };
|
||||
mExteriors.emplace(extIndex, newCellStore);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -382,14 +375,11 @@ MWWorld::Ptr MWWorld::WorldModel::getPtr(const ESM::RefId& name)
|
||||
// Then check cells that are already listed
|
||||
// Search in reverse, this is a workaround for an ambiguous chargen_plank reference in the vanilla game.
|
||||
// there is one at -22,16 and one at -2,-9, the latter should be used.
|
||||
for (auto iterExt = mExteriors.rbegin(); iterExt != mExteriors.rend(); ++iterExt)
|
||||
for (auto iter = mExteriors.rbegin(); iter != mExteriors.rend(); ++iter)
|
||||
{
|
||||
for (auto iter = iterExt->second.rbegin(); iter != iterExt->second.rend(); iter++)
|
||||
{
|
||||
Ptr ptr = getPtrAndCache(name, *iter->second);
|
||||
if (!ptr.isEmpty())
|
||||
return ptr;
|
||||
}
|
||||
Ptr ptr = getPtrAndCache(name, *iter->second);
|
||||
if (!ptr.isEmpty())
|
||||
return ptr;
|
||||
}
|
||||
|
||||
for (auto iter = mInteriors.begin(); iter != mInteriors.end(); ++iter)
|
||||
|
@ -7,6 +7,7 @@
|
||||
#include <unordered_map>
|
||||
#include <variant>
|
||||
|
||||
#include <components/esm/util.hpp>
|
||||
#include <components/misc/algorithm.hpp>
|
||||
|
||||
#include "cellstore.hpp"
|
||||
@ -42,7 +43,8 @@ namespace MWWorld
|
||||
ESM::ReadersCache& mReaders;
|
||||
mutable std::unordered_map<ESM::RefId, CellStore> mCells;
|
||||
mutable std::map<std::string, CellStore*, Misc::StringUtils::CiComp> mInteriors;
|
||||
mutable std::map<ESM::RefId, std::map<std::pair<int, int>, CellStore*>> mExteriors;
|
||||
|
||||
mutable std::map<ESM::ExteriorCellIndex, CellStore*> mExteriors;
|
||||
IdCache mIdCache;
|
||||
std::size_t mIdCacheIndex = 0;
|
||||
std::unordered_map<ESM::RefNum, Ptr> mPtrIndex;
|
||||
|
@ -4,6 +4,8 @@
|
||||
#include <osg/Quat>
|
||||
#include <osg/Vec3f>
|
||||
|
||||
#include <components/esm/refid.hpp>
|
||||
|
||||
namespace ESM
|
||||
{
|
||||
|
||||
@ -42,6 +44,41 @@ namespace ESM
|
||||
operator osg::Vec3f() const { return osg::Vec3f(mValues[0], mValues[1], mValues[2]); }
|
||||
};
|
||||
|
||||
struct ExteriorCellIndex
|
||||
{
|
||||
int mX, mY;
|
||||
ESM::RefId mWorldspace;
|
||||
|
||||
bool operator==(const ExteriorCellIndex& other) const
|
||||
{
|
||||
return mX == other.mX && mY == other.mY && mWorldspace == other.mWorldspace;
|
||||
}
|
||||
|
||||
bool operator<(const ExteriorCellIndex& other) const
|
||||
{
|
||||
return std::make_tuple(mX, mY, mWorldspace) < std::make_tuple(other.mX, other.mY, other.mWorldspace);
|
||||
}
|
||||
|
||||
friend struct std::hash<ExteriorCellIndex>;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
namespace std
|
||||
{
|
||||
template <>
|
||||
struct hash<ESM::ExteriorCellIndex>
|
||||
{
|
||||
std::size_t operator()(const ESM::ExteriorCellIndex& toHash) const
|
||||
{
|
||||
// Compute individual hash values for first,
|
||||
// second and third and combine them using XOR
|
||||
// and bit shifting:
|
||||
|
||||
return ((hash<int>()(toHash.mX) ^ (hash<int>()(toHash.mY) << 1)) >> 1)
|
||||
^ (hash<ESM::RefId>()(toHash.mWorldspace) << 1);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
|
Loading…
x
Reference in New Issue
Block a user