From b621bfcef0b64511d01282fbf8dcc33134d9b48d Mon Sep 17 00:00:00 2001 From: elsid Date: Sun, 28 May 2023 17:04:44 +0200 Subject: [PATCH 1/2] Define SharedIterator as proper random access iterator Drop Container template argument as it's always std::vector. --- apps/openmw/mwworld/store.hpp | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/apps/openmw/mwworld/store.hpp b/apps/openmw/mwworld/store.hpp index 238c5cbd5f..25cac68c55 100644 --- a/apps/openmw/mwworld/store.hpp +++ b/apps/openmw/mwworld/store.hpp @@ -115,20 +115,20 @@ namespace MWWorld const T* find(int index) const; }; - template > + template class SharedIterator { - typedef typename Container::const_iterator Iter; - - Iter mIter; - public: - SharedIterator() {} + using Iter = typename std::vector::const_iterator; + using iterator_category = std::random_access_iterator_tag; + using value_type = T; + using difference_type = std::ptrdiff_t; + using pointer = T*; + using reference = T&; - SharedIterator(const SharedIterator& orig) - : mIter(orig.mIter) - { - } + SharedIterator() = default; + + SharedIterator(const SharedIterator& other) = default; SharedIterator(const Iter& iter) : mIter(iter) @@ -151,7 +151,7 @@ namespace MWWorld return iter; } - SharedIterator& operator+=(int advance) + SharedIterator& operator+=(difference_type advance) { mIter += advance; return *this; @@ -178,6 +178,14 @@ namespace MWWorld const T& operator*() const { return **mIter; } const T* operator->() const { return &(**mIter); } + + private: + Iter mIter; + + friend inline difference_type operator-(const SharedIterator& lhs, const SharedIterator& rhs) + { + return lhs.mIter - rhs.mIter; + } }; class ESMStore; From a91f3768920e4d621c9a77abe253b5957286c05d Mon Sep 17 00:00:00 2001 From: elsid Date: Sat, 27 May 2023 01:17:20 +0200 Subject: [PATCH 2/2] Do not rely on exceptions to handle absent cell --- .../mwscript/transformationextensions.cpp | 105 +++--- apps/openmw/mwstate/statemanagerimp.cpp | 2 +- apps/openmw/mwworld/player.cpp | 13 +- apps/openmw/mwworld/worldimp.cpp | 15 +- apps/openmw/mwworld/worldmodel.cpp | 329 +++++++++--------- apps/openmw/mwworld/worldmodel.hpp | 21 +- 6 files changed, 232 insertions(+), 253 deletions(-) diff --git a/apps/openmw/mwscript/transformationextensions.cpp b/apps/openmw/mwscript/transformationextensions.cpp index 0de596c9d7..5f142856bd 100644 --- a/apps/openmw/mwscript/transformationextensions.cpp +++ b/apps/openmw/mwscript/transformationextensions.cpp @@ -396,49 +396,46 @@ namespace MWScript if (isPlayer) world->getPlayer().setTeleported(true); - MWWorld::CellStore* store = nullptr; - try - { - store = &worldModel->getCell(cellID); - if (store->isExterior()) - { - const ESM::ExteriorCellLocation cellIndex - = ESM::positionToExteriorCellLocation(x, y, store->getCell()->getWorldSpace()); - store = &worldModel->getExterior(cellIndex); - } - } - catch (std::exception&) + MWWorld::CellStore* store = worldModel->findCell(cellID); + + if (store != nullptr && store->isExterior()) + store = &worldModel->getExterior( + ESM::positionToExteriorCellLocation(x, y, store->getCell()->getWorldSpace())); + + if (store == nullptr) { // cell not found, move to exterior instead if moving the player (vanilla PositionCell // compatibility) - std::string error = "Warning: PositionCell: unknown interior cell (" + std::string(cellID) + ")"; + std::string error = "PositionCell: unknown interior cell (" + std::string(cellID) + ")"; if (isPlayer) error += ", moving to exterior instead"; runtime.getContext().report(error); - Log(Debug::Warning) << error; if (!isPlayer) + { + Log(Debug::Error) << error; return; - store = &worldModel->getExterior( - ESM::positionToExteriorCellLocation(x, y, ESM::Cell::sDefaultWorldspaceId)); + } + Log(Debug::Warning) << error; + const ESM::ExteriorCellLocation cellIndex + = ESM::positionToExteriorCellLocation(x, y, ESM::Cell::sDefaultWorldspaceId); + store = &worldModel->getExterior(cellIndex); } - if (store) - { - MWWorld::Ptr base = ptr; - ptr = world->moveObject(ptr, store, osg::Vec3f(x, y, z)); - dynamic_cast(runtime.getContext()).updatePtr(base, ptr); - auto rot = ptr.getRefData().getPosition().asRotationVec3(); - // Note that you must specify ZRot in minutes (1 degree = 60 minutes; north = 0, east = 5400, south - // = 10800, west = 16200) except for when you position the player, then degrees must be used. See - // "Morrowind Scripting for Dummies (9th Edition)" pages 50 and 54 for reference. - if (!isPlayer) - zRot = zRot / 60.0f; - rot.z() = osg::DegreesToRadians(zRot); - world->rotateObject(ptr, rot); + MWWorld::Ptr base = ptr; + ptr = world->moveObject(ptr, store, osg::Vec3f(x, y, z)); + dynamic_cast(runtime.getContext()).updatePtr(base, ptr); - bool cellActive = MWBase::Environment::get().getWorldScene()->isCellActive(*ptr.getCell()); - ptr.getClass().adjustPosition(ptr, isPlayer || !cellActive); - } + auto rot = ptr.getRefData().getPosition().asRotationVec3(); + // Note that you must specify ZRot in minutes (1 degree = 60 minutes; north = 0, east = 5400, south + // = 10800, west = 16200) except for when you position the player, then degrees must be used. See + // "Morrowind Scripting for Dummies (9th Edition)" pages 50 and 54 for reference. + if (!isPlayer) + zRot = zRot / 60.0f; + rot.z() = osg::DegreesToRadians(zRot); + world->rotateObject(ptr, rot); + + bool cellActive = MWBase::Environment::get().getWorldScene()->isCellActive(*ptr.getCell()); + ptr.getClass().adjustPosition(ptr, isPlayer || !cellActive); } }; @@ -468,7 +465,7 @@ namespace MWScript ptr.getClass().getCreatureStats(ptr).setTeleported(true); if (isPlayer) world->getPlayer().setTeleported(true); - const ESM::ExteriorCellLocation cellIndex + const ESM::ExteriorCellLocation location = ESM::positionToExteriorCellLocation(x, y, ESM::Cell::sDefaultWorldspaceId); // another morrowind oddity: player will be moved to the exterior cell at this location, @@ -476,7 +473,7 @@ namespace MWScript MWWorld::Ptr base = ptr; if (isPlayer) { - MWWorld::CellStore* cell = &MWBase::Environment::get().getWorldModel()->getExterior(cellIndex); + MWWorld::CellStore* cell = &MWBase::Environment::get().getWorldModel()->getExterior(location); ptr = world->moveObject(ptr, cell, osg::Vec3(x, y, z)); } else @@ -517,30 +514,26 @@ namespace MWScript Interpreter::Type_Float zRotDegrees = runtime[0].mFloat; runtime.pop(); - MWWorld::CellStore* store = nullptr; - try + MWWorld::CellStore* const store = MWBase::Environment::get().getWorldModel()->findCell(cellName); + if (store == nullptr) { - store = &MWBase::Environment::get().getWorldModel()->getCell(cellName); - } - catch (std::exception&) - { - runtime.getContext().report("unknown cell (" + std::string(cellName) + ")"); - Log(Debug::Error) << "Error: unknown cell (" << cellName << ")"; - } - if (store) - { - ESM::Position pos; - pos.pos[0] = x; - pos.pos[1] = y; - pos.pos[2] = z; - pos.rot[0] = pos.rot[1] = 0; - pos.rot[2] = osg::DegreesToRadians(zRotDegrees); - MWWorld::ManualRef ref(*MWBase::Environment::get().getESMStore(), itemID); - ref.getPtr().mRef->mData.mPhysicsPostponed = !ref.getPtr().getClass().isActor(); - ref.getPtr().getCellRef().setPosition(pos); - MWWorld::Ptr placed = MWBase::Environment::get().getWorld()->placeObject(ref.getPtr(), store, pos); - placed.getClass().adjustPosition(placed, true); + const std::string message = "unknown cell (" + std::string(cellName) + ")"; + runtime.getContext().report(message); + Log(Debug::Error) << message; + return; } + + ESM::Position pos; + pos.pos[0] = x; + pos.pos[1] = y; + pos.pos[2] = z; + pos.rot[0] = pos.rot[1] = 0; + pos.rot[2] = osg::DegreesToRadians(zRotDegrees); + MWWorld::ManualRef ref(*MWBase::Environment::get().getESMStore(), itemID); + ref.getPtr().mRef->mData.mPhysicsPostponed = !ref.getPtr().getClass().isActor(); + ref.getPtr().getCellRef().setPosition(pos); + MWWorld::Ptr placed = MWBase::Environment::get().getWorld()->placeObject(ref.getPtr(), store, pos); + placed.getClass().adjustPosition(placed, true); } }; diff --git a/apps/openmw/mwstate/statemanagerimp.cpp b/apps/openmw/mwstate/statemanagerimp.cpp index 5ceebacf7b..1e12c98582 100644 --- a/apps/openmw/mwstate/statemanagerimp.cpp +++ b/apps/openmw/mwstate/statemanagerimp.cpp @@ -564,7 +564,7 @@ void MWState::StateManager::loadGame(const Character* character, const std::file else { // Cell no longer exists (i.e. changed game files), choose a default cell - Log(Debug::Warning) << "Warning: Player character's cell no longer exists, changing to the default cell"; + Log(Debug::Warning) << "Player character's cell no longer exists, changing to the default cell"; ESM::ExteriorCellLocation cellIndex(0, 0, ESM::Cell::sDefaultWorldspaceId); MWWorld::CellStore& cell = MWBase::Environment::get().getWorldModel()->getExterior(cellIndex); osg::Vec2 posFromIndex = ESM::indexToPosition(cellIndex, false); diff --git a/apps/openmw/mwworld/player.cpp b/apps/openmw/mwworld/player.cpp index 0b8c49cf4d..d6fcc945ea 100644 --- a/apps/openmw/mwworld/player.cpp +++ b/apps/openmw/mwworld/player.cpp @@ -360,16 +360,9 @@ namespace MWWorld MWBase::World& world = *MWBase::Environment::get().getWorld(); - try - { - mCellStore = &MWBase::Environment::get().getWorldModel()->getCell(player.mCellId); - } - catch (...) - { - Log(Debug::Warning) << "Warning: Player cell '" << player.mCellId << "' no longer exists"; - // Cell no longer exists. The loader will have to choose a default cell. - mCellStore = nullptr; - } + mCellStore = MWBase::Environment::get().getWorldModel()->findCell(player.mCellId); + if (mCellStore == nullptr) + Log(Debug::Warning) << "Player cell " << player.mCellId << " no longer exists"; if (!player.mBirthsign.empty()) { diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 5338980299..8853181c14 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -2744,16 +2744,11 @@ namespace MWWorld { pos.rot[0] = pos.rot[1] = pos.rot[2] = 0; - const MWWorld::CellStore* cellStore = nullptr; - try - { - cellStore = &mWorldModel.getCell(nameId); - if (!cellStore->isExterior()) - return ESM::RefId(); - } - catch (std::exception&) - { - } + const MWWorld::CellStore* cellStore = mWorldModel.findCell(nameId); + + if (cellStore != nullptr && !cellStore->isExterior()) + return ESM::RefId(); + if (!cellStore) { size_t comma = nameId.find(','); diff --git a/apps/openmw/mwworld/worldmodel.cpp b/apps/openmw/mwworld/worldmodel.cpp index 26402c5855..22860a175c 100644 --- a/apps/openmw/mwworld/worldmodel.cpp +++ b/apps/openmw/mwworld/worldmodel.cpp @@ -1,6 +1,8 @@ #include "worldmodel.hpp" #include +#include +#include #include #include @@ -30,6 +32,58 @@ namespace MWWorld std::forward_as_tuple(Cell(cell), store, readers)) .first->second; } + + const ESM::Cell* createEsmCell(ESM::ExteriorCellLocation location, ESMStore& store) + { + ESM::Cell record; + record.mData.mFlags = ESM::Cell::HasWater; + record.mData.mX = location.mX; + record.mData.mY = location.mY; + record.mWater = 0; + record.mMapColor = 0; + record.updateId(); + return store.insert(record); + } + + const ESM4::Cell* createEsm4Cell(ESM::ExteriorCellLocation location, ESMStore& store) + { + ESM4::Cell record; + record.mParent = location.mWorldspace; + record.mX = location.mX; + record.mY = location.mY; + record.mCellFlags = 0; + return store.insert(record); + } + + Cell createExteriorCell(ESM::ExteriorCellLocation location, ESMStore& store) + { + if (ESM::isEsm4Ext(location.mWorldspace)) + { + if (store.get().search(location.mWorldspace) == nullptr) + throw std::runtime_error( + "Exterior ESM4 world is not found: " + location.mWorldspace.toDebugString()); + const ESM4::Cell* cell = store.get().searchExterior(location); + if (cell == nullptr) + cell = createEsm4Cell(location, store); + assert(cell != nullptr); + return MWWorld::Cell(*cell); + } + + const ESM::Cell* cell = store.get().search(location.mX, location.mY); + if (cell == nullptr) + cell = createEsmCell(location, store); + assert(cell != nullptr); + return Cell(*cell); + } + + std::optional createCell(ESM::RefId id, const ESMStore& store) + { + if (const ESM4::Cell* cell = store.get().search(id)) + return Cell(*cell); + if (const ESM::Cell* cell = store.get().search(id)) + return Cell(*cell); + return std::nullopt; + } } } @@ -102,167 +156,120 @@ MWWorld::WorldModel::WorldModel(MWWorld::ESMStore& store, ESM::ReadersCache& rea { } -MWWorld::CellStore& MWWorld::WorldModel::getExterior(ESM::ExteriorCellLocation cellIndex, bool forceLoad) +namespace MWWorld { - std::map::iterator result; - - result = mExteriors.find(cellIndex); - - if (result == mExteriors.end()) + CellStore& WorldModel::getExterior(ESM::ExteriorCellLocation location, bool forceLoad) const { - if (!ESM::isEsm4Ext(cellIndex.mWorldspace)) - { - const ESM::Cell* cell = mStore.get().search(cellIndex.mX, cellIndex.mY); + auto it = mExteriors.find(location); + if (it != mExteriors.end()) + return *it->second; + Cell cell = createExteriorCell(location, mStore); + const ESM::RefId id = cell.getId(); + CellStore& cellStore = emplaceCellStore(id, std::move(cell), mStore, mReaders, mCells); + mExteriors.emplace(location, &cellStore); + if (forceLoad && cellStore.getState() != CellStore::State_Loaded) + cellStore.load(); + return cellStore; + } - if (cell == nullptr) - { - // Cell isn't predefined. Make one on the fly. - ESM::Cell record; - record.mData.mFlags = ESM::Cell::HasWater; - record.mData.mX = cellIndex.mX; - record.mData.mY = cellIndex.mY; - record.mWater = 0; - record.mMapColor = 0; - record.updateId(); + CellStore* WorldModel::findInterior(std::string_view name, bool forceLoad) const + { + const auto it = mInteriors.find(name); + if (it == mInteriors.end()) + return nullptr; + assert(it->second != nullptr); + if (forceLoad && it->second->getState() != CellStore::State_Loaded) + it->second->load(); + return it->second; + } - cell = mStore.insert(record); - } + CellStore& WorldModel::getInterior(std::string_view name, bool forceLoad) const + { + CellStore* const cellStore = findInterior(name, forceLoad); + if (cellStore == nullptr) + throw std::runtime_error("Interior cell is not found: '" + std::string(name) + "'"); + return *cellStore; + } - CellStore* cellStore = &emplaceCellStore(cell->mId, *cell, mStore, mReaders, mCells); - result = mExteriors.emplace(cellIndex, cellStore).first; - } + CellStore* WorldModel::findCell(ESM::RefId id, bool forceLoad) const + { + auto it = mCells.find(id); + if (it != mCells.end()) + return &it->second; + + if (const auto* exteriorId = id.getIf()) + return &getExterior( + ESM::ExteriorCellLocation(exteriorId->getX(), exteriorId->getY(), ESM::Cell::sDefaultWorldspaceId), + forceLoad); + + std::optional cell = createCell(id, mStore); + if (!cell.has_value()) + return nullptr; + + CellStore& cellStore = emplaceCellStore(id, std::move(*cell), mStore, mReaders, mCells); + + if (cellStore.isExterior()) + mExteriors.emplace(ESM::ExteriorCellLocation(cellStore.getCell()->getGridX(), + cellStore.getCell()->getGridY(), cellStore.getCell()->getWorldSpace()), + &cellStore); else + mInteriors.emplace(cellStore.getCell()->getNameId(), &cellStore); + + if (forceLoad && cellStore.getState() != CellStore::State_Loaded) + cellStore.load(); + + return &cellStore; + } + + CellStore& WorldModel::getCell(ESM::RefId id, bool forceLoad) const + { + CellStore* const result = findCell(id, forceLoad); + if (result == nullptr) + throw std::runtime_error("Cell does not exist: " + id.toDebugString()); + return *result; + } + + CellStore* WorldModel::findCell(std::string_view name, bool forceLoad) const + { + if (CellStore* const cellStore = findInterior(name, forceLoad)) + return cellStore; + + // try named exteriors + const ESM::Cell* cell = mStore.get().searchExtByName(name); + + if (cell == nullptr) { - const Store& cell4Store = mStore.get(); - bool exteriorExists = mStore.get().search(cellIndex.mWorldspace) != nullptr; - const ESM4::Cell* cell = cell4Store.searchExterior(cellIndex); - if (!exteriorExists) - throw std::runtime_error("Exterior ESM4 world is not found: " + cellIndex.mWorldspace.toDebugString()); - if (cell == nullptr) - { - ESM4::Cell record; - record.mParent = cellIndex.mWorldspace; - record.mX = cellIndex.mX; - record.mY = cellIndex.mY; - // Other ESM4::Cell members use default values from class definition. - cell = mStore.insert(record); - } - CellStore* cellStore = &emplaceCellStore(cell->mId, *cell, mStore, mReaders, mCells); - result = mExteriors.emplace(cellIndex, cellStore).first; + // treat "Wilderness" like an empty string + static const std::string& defaultName + = mStore.get().find("sDefaultCellname")->mValue.getString(); + if (Misc::StringUtils::ciEqual(name, defaultName)) + cell = mStore.get().searchExtByName({}); } - } - if (forceLoad && result->second->getState() != CellStore::State_Loaded) - { - result->second->load(); - } - return *result->second; -} - -MWWorld::CellStore* MWWorld::WorldModel::getInteriorOrNull(std::string_view name) -{ - auto result = mInteriors.find(name); - if (result == mInteriors.end()) - { - CellStore* newCellStore = nullptr; - if (const ESM::Cell* cell = mStore.get().search(name)) - newCellStore = &emplaceCellStore(cell->mId, *cell, mStore, mReaders, mCells); - else if (const ESM4::Cell* cell4 = mStore.get().searchCellName(name)) - newCellStore = &emplaceCellStore(cell4->mId, *cell4, mStore, mReaders, mCells); - if (!newCellStore) - return nullptr; // Cell not found - result = mInteriors.emplace(name, newCellStore).first; - } - return result->second; -} - -MWWorld::CellStore& MWWorld::WorldModel::getInterior(std::string_view name, bool forceLoad) -{ - CellStore* res = getInteriorOrNull(name); - if (res == nullptr) - throw std::runtime_error("Interior not found: '" + std::string(name) + "'"); - if (forceLoad && res->getState() != CellStore::State_Loaded) - res->load(); - return *res; -} - -MWWorld::CellStore& MWWorld::WorldModel::getCell(const ESM::RefId& id, bool forceLoad) -{ - auto result = mCells.find(id); - if (result != mCells.end()) - return result->second; - - if (const auto* exteriorId = id.getIf()) - return getExterior( - ESM::ExteriorCellLocation(exteriorId->getX(), exteriorId->getY(), ESM::Cell::sDefaultWorldspaceId), - forceLoad); - - const ESM4::Cell* cell4 = mStore.get().search(id); - CellStore* newCellStore = nullptr; - if (!cell4) - { - const ESM::Cell* cell = mStore.get().find(id); - newCellStore = &emplaceCellStore(cell->mId, *cell, mStore, mReaders, mCells); - } - else - { - newCellStore = &emplaceCellStore(cell4->mId, *cell4, mStore, mReaders, mCells); - } - if (newCellStore->getCell()->isExterior()) - { - std::pair coord - = std::make_pair(newCellStore->getCell()->getGridX(), newCellStore->getCell()->getGridY()); - ESM::ExteriorCellLocation extIndex = { coord.first, coord.second, newCellStore->getCell()->getWorldSpace() }; - mExteriors.emplace(extIndex, newCellStore); - } - else - { - mInteriors.emplace(newCellStore->getCell()->getNameId(), newCellStore); - } - if (forceLoad && newCellStore->getState() != CellStore::State_Loaded) - { - newCellStore->load(); - } - return *newCellStore; -} - -MWWorld::CellStore& MWWorld::WorldModel::getCell(std::string_view name, bool forceLoad) -{ - if (CellStore* res = getInteriorOrNull(name)) // first try interiors - { - if (forceLoad && res->getState() != CellStore::State_Loaded) - res->load(); - return *res; - } - - // try named exteriors - const ESM::Cell* cell = mStore.get().searchExtByName(name); - - if (!cell) - { - // treat "Wilderness" like an empty string - static const std::string& defaultName - = mStore.get().find("sDefaultCellname")->mValue.getString(); - if (Misc::StringUtils::ciEqual(name, defaultName)) - cell = mStore.get().searchExtByName({}); - } - if (!cell) - { - // now check for regions - for (const ESM::Region& region : mStore.get()) + if (cell == nullptr) { - if (Misc::StringUtils::ciEqual(name, region.mName)) - { - cell = mStore.get().searchExtByRegion(region.mId); - break; - } + // now check for regions + const Store& regions = mStore.get(); + const auto region = std::find_if(regions.begin(), regions.end(), + [&](const ESM::Region& v) { return Misc::StringUtils::ciEqual(name, v.mName); }); + if (region != regions.end()) + cell = mStore.get().searchExtByRegion(region->mId); } - } - if (!cell) - throw std::runtime_error(std::string("Can't find cell with name ") + std::string(name)); - return getExterior( - ESM::ExteriorCellLocation(cell->getGridX(), cell->getGridY(), ESM::Cell::sDefaultWorldspaceId), forceLoad); + if (cell == nullptr) + return nullptr; + + return &getExterior( + ESM::ExteriorCellLocation(cell->getGridX(), cell->getGridY(), ESM::Cell::sDefaultWorldspaceId), forceLoad); + } + + CellStore& WorldModel::getCell(std::string_view name, bool forceLoad) const + { + CellStore* const result = findCell(name, forceLoad); + if (result == nullptr) + throw std::runtime_error(std::string("Can't find cell with name ") + std::string(name)); + return *result; + } } MWWorld::Ptr MWWorld::WorldModel::getPtr(const ESM::RefId& name) @@ -383,17 +390,7 @@ public: MWWorld::WorldModel& mWorldModel; - MWWorld::CellStore* getCellStore(const ESM::RefId& cellId) override - { - try - { - return &mWorldModel.getCell(cellId); - } - catch (...) - { - return nullptr; - } - } + MWWorld::CellStore* getCellStore(const ESM::RefId& cellId) override { return mWorldModel.findCell(cellId); } }; bool MWWorld::WorldModel::readRecord(ESM::ESMReader& reader, uint32_t type, const std::map& contentFileMap) @@ -403,16 +400,10 @@ bool MWWorld::WorldModel::readRecord(ESM::ESMReader& reader, uint32_t type, cons ESM::CellState state; state.mId = reader.getCellId(); - CellStore* cellStore = nullptr; - - try + CellStore* const cellStore = findCell(state.mId); + if (cellStore == nullptr) { - cellStore = &getCell(state.mId); - } - catch (...) - { - // silently drop cells that don't exist anymore - Log(Debug::Warning) << "Warning: Dropping state for cell " << state.mId << " (cell no longer exists)"; + Log(Debug::Warning) << "Dropping state for cell " << state.mId << " (cell no longer exists)"; reader.skipRecord(); return true; } diff --git a/apps/openmw/mwworld/worldmodel.hpp b/apps/openmw/mwworld/worldmodel.hpp index cdbc458022..41025ce820 100644 --- a/apps/openmw/mwworld/worldmodel.hpp +++ b/apps/openmw/mwworld/worldmodel.hpp @@ -4,8 +4,8 @@ #include #include #include +#include #include -#include #include #include @@ -47,10 +47,19 @@ namespace MWWorld void clear(); - CellStore& getExterior(ESM::ExteriorCellLocation cellIndex, bool forceLoad = true); - CellStore& getInterior(std::string_view name, bool forceLoad = true); - CellStore& getCell(std::string_view name, bool forceLoad = true); // interior or named exterior - CellStore& getCell(const ESM::RefId& Id, bool forceLoad = true); + CellStore& getExterior(ESM::ExteriorCellLocation location, bool forceLoad = true) const; + + CellStore* findCell(ESM::RefId Id, bool forceLoad = true) const; + + CellStore& getCell(ESM::RefId Id, bool forceLoad = true) const; + + CellStore* findInterior(std::string_view name, bool forceLoad = true) const; + + CellStore& getInterior(std::string_view name, bool forceLoad = true) const; + + CellStore* findCell(std::string_view name, bool forceLoad = true) const; + + CellStore& getCell(std::string_view name, bool forceLoad = true) const; Ptr getPtr(const ESM::RefId& name); @@ -102,8 +111,6 @@ namespace MWWorld CellStore& insertCellStore(const ESM::Cell& cell); - CellStore* getInteriorOrNull(std::string_view name); - Ptr getPtrAndCache(const ESM::RefId& name, CellStore& cellStore); void writeCell(ESM::ESMWriter& writer, CellStore& cell) const;