diff --git a/apps/openmw/mwmechanics/aiescort.cpp b/apps/openmw/mwmechanics/aiescort.cpp index 7bf593b6da..41cb5a59cb 100644 --- a/apps/openmw/mwmechanics/aiescort.cpp +++ b/apps/openmw/mwmechanics/aiescort.cpp @@ -2,6 +2,7 @@ #include #include +#include #include "../mwbase/environment.hpp" #include "../mwbase/mechanicsmanager.hpp" @@ -78,7 +79,7 @@ namespace MWMechanics } } - if (!mCellId.empty() && mCellId != actor.getCell()->getCell()->getCellId().mWorldspace) + if (!mCellId.empty() && !Misc::StringUtils::ciEqual(mCellId, actor.getCell()->getCell()->getNameId())) return false; // Not in the correct cell, pause and rely on the player to go back through a teleport door actor.getClass().getCreatureStats(actor).setDrawState(DrawState::Nothing); diff --git a/apps/openmw/mwmechanics/aipackage.cpp b/apps/openmw/mwmechanics/aipackage.cpp index dec0661dd6..d4365a478f 100644 --- a/apps/openmw/mwmechanics/aipackage.cpp +++ b/apps/openmw/mwmechanics/aipackage.cpp @@ -330,9 +330,9 @@ void MWMechanics::AiPackage::openDoors(const MWWorld::Ptr& actor) const MWMechanics::PathgridGraph& MWMechanics::AiPackage::getPathGridGraph(const MWWorld::CellStore* cell) { - const ESM::CellId& id = cell->getCell()->getCellId(); + const ESM::RefId& id = cell->getCell()->getId(); // static cache is OK for now, pathgrids can never change during runtime - typedef std::map> CacheMap; + typedef std::map> CacheMap; static CacheMap cache; CacheMap::iterator found = cache.find(id); if (found == cache.end()) diff --git a/apps/openmw/mwscript/transformationextensions.cpp b/apps/openmw/mwscript/transformationextensions.cpp index 7385d3a2a5..fc994c8754 100644 --- a/apps/openmw/mwscript/transformationextensions.cpp +++ b/apps/openmw/mwscript/transformationextensions.cpp @@ -87,8 +87,8 @@ namespace MWScript float distance; // If the objects are in different worldspaces, return a large value (just like vanilla) if (!to.isInCell() || !from.isInCell() - || to.getCell()->getCell()->getCellId().mWorldspace - != from.getCell()->getCell()->getCellId().mWorldspace) + || !Misc::StringUtils::ciEqual( + to.getCell()->getCell()->getNameId(), from.getCell()->getCell()->getNameId())) distance = std::numeric_limits::max(); else { diff --git a/apps/openmw/mwstate/statemanagerimp.cpp b/apps/openmw/mwstate/statemanagerimp.cpp index e35410b484..c4f96b3724 100644 --- a/apps/openmw/mwstate/statemanagerimp.cpp +++ b/apps/openmw/mwstate/statemanagerimp.cpp @@ -555,7 +555,7 @@ void MWState::StateManager::loadGame(const Character* character, const std::file if (ptr.isInCell()) { - const ESM::CellId& cellId = ptr.getCell()->getCell()->getCellId(); + const ESM::RefId& cellId = ptr.getCell()->getCell()->getId(); // Use detectWorldSpaceChange=false, otherwise some of the data we just loaded would be cleared again MWBase::Environment::get().getWorld()->changeToCell(cellId, ptr.getRefData().getPosition(), false, false); @@ -574,7 +574,7 @@ void MWState::StateManager::loadGame(const Character* character, const std::file pos.rot[0] = 0; pos.rot[1] = 0; pos.rot[2] = 0; - MWBase::Environment::get().getWorld()->changeToCell(cell->getCell()->getCellId(), pos, true, false); + MWBase::Environment::get().getWorld()->changeToCell(cell->getCell()->getId(), pos, true, false); } MWBase::Environment::get().getWorld()->updateProjectilesCasters(); diff --git a/apps/openmw/mwworld/cell.cpp b/apps/openmw/mwworld/cell.cpp index fa35af41a3..b8a352df71 100644 --- a/apps/openmw/mwworld/cell.cpp +++ b/apps/openmw/mwworld/cell.cpp @@ -16,10 +16,6 @@ namespace MWWorld , mDisplayname(cell.mFullName) , mNameID(cell.mEditorId) , mRegion(ESM::RefId()) // Unimplemented for now - , mCellId{ - .mWorldspace{ Misc::StringUtils::lowerCase(cell.mEditorId) }, - .mIndex{ cell.getGridX(), cell.getGridY() }, - .mPaged = isExterior(),} , mId(cell.mId) ,mMood{ .mAmbiantColor = cell.mLighting.ambient, @@ -41,7 +37,6 @@ namespace MWWorld , mDisplayname(cell.mName) , mNameID(cell.mName) , mRegion(cell.mRegion) - , mCellId(cell.getCellId()) , mId(cell.mId) , mMood{ .mAmbiantColor = cell.mAmbi.mAmbient, diff --git a/apps/openmw/mwworld/cell.hpp b/apps/openmw/mwworld/cell.hpp index fd391e870b..60751e8797 100644 --- a/apps/openmw/mwworld/cell.hpp +++ b/apps/openmw/mwworld/cell.hpp @@ -42,7 +42,6 @@ namespace MWWorld bool isQuasiExterior() const { return mIsQuasiExterior; } bool hasWater() const { return mHasWater; } bool noSleep() const { return mNoSleep; } - const ESM::CellId& getCellId() const { return mCellId; } const ESM::RefId& getRegion() const { return mRegion; } std::string_view getNameId() const { return mNameID; } std::string_view getDisplayName() const { return mDisplayname; } @@ -61,7 +60,6 @@ namespace MWWorld std::string mDisplayname; // How the game displays it 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; diff --git a/apps/openmw/mwworld/cellstore.cpp b/apps/openmw/mwworld/cellstore.cpp index cc9f9bfe92..cf438ede74 100644 --- a/apps/openmw/mwworld/cellstore.cpp +++ b/apps/openmw/mwworld/cellstore.cpp @@ -988,7 +988,7 @@ namespace MWWorld void CellStore::saveState(ESM::CellState& state) const { - state.mId = mCellVariant.getCellId(); + state.mId = ESM::CellId::extractFromRefId(mCellVariant.getId()); if (!mCellVariant.isExterior() && mCellVariant.hasWater()) state.mWaterLevel = mWaterLevel; @@ -1019,7 +1019,7 @@ namespace MWWorld for (const auto& [base, store] : mMovedToAnotherCell) { ESM::RefNum refNum = base->mRef.getRefNum(); - ESM::CellId movedTo = store->getCell()->getCellId(); + ESM::CellId movedTo = ESM::CellId::extractFromRefId(store->getCell()->getId()); refNum.save(writer, true, "MVRF"); movedTo.save(writer); diff --git a/apps/openmw/mwworld/player.cpp b/apps/openmw/mwworld/player.cpp index e2000785c8..f0a3f548a5 100644 --- a/apps/openmw/mwworld/player.cpp +++ b/apps/openmw/mwworld/player.cpp @@ -283,7 +283,7 @@ namespace MWWorld ESM::Player player; mPlayer.save(player.mObject); - player.mCellId = mCellStore->getCell()->getCellId(); + player.mCellId = ESM::CellId::extractFromRefId(mCellStore->getCell()->getId()); player.mCurrentCrimeId = mCurrentCrimeId; player.mPaidCrimeId = mPaidCrimeId; @@ -298,7 +298,7 @@ namespace MWWorld { player.mHasMark = true; player.mMarkedPosition = mMarkedPosition; - player.mMarkedCell = mMarkedCell->getCell()->getCellId(); + player.mMarkedCell = ESM::CellId::extractFromRefId(mMarkedCell->getCell()->getId()); } else player.mHasMark = false; diff --git a/apps/openmw/mwworld/scene.cpp b/apps/openmw/mwworld/scene.cpp index c255618dba..b3a077d23d 100644 --- a/apps/openmw/mwworld/scene.cpp +++ b/apps/openmw/mwworld/scene.cpp @@ -554,7 +554,7 @@ namespace MWWorld mNavigator.setWorldspace( Misc::StringUtils::lowerCase( - mWorld.getWorldModel().getExterior(playerCellX, playerCellY)->getCell()->getCellId().mWorldspace), + mWorld.getWorldModel().getExterior(playerCellX, playerCellY)->getCell()->getNameId()), navigatorUpdateGuard.get()); mNavigator.updateBounds(pos, navigatorUpdateGuard.get()); @@ -676,7 +676,7 @@ namespace MWWorld CellStore* cell = mWorld.getWorldModel().getExterior(it->mData.mX, it->mData.mY); mNavigator.setWorldspace( - Misc::StringUtils::lowerCase(cell->getCell()->getCellId().mWorldspace), navigatorUpdateGuard.get()); + Misc::StringUtils::lowerCase(cell->getCell()->getNameId()), navigatorUpdateGuard.get()); const osg::Vec3f position = osg::Vec3f(it->mData.mX + 0.5f, it->mData.mY + 0.5f, 0) * Constants::CellSizeInUnits; mNavigator.updateBounds(position, navigatorUpdateGuard.get()); @@ -734,7 +734,7 @@ namespace MWWorld CellStore* cell = mWorld.getWorldModel().getInterior(it->mName); mNavigator.setWorldspace( - Misc::StringUtils::lowerCase(cell->getCell()->getCellId().mWorldspace), navigatorUpdateGuard.get()); + Misc::StringUtils::lowerCase(cell->getCell()->getNameId()), navigatorUpdateGuard.get()); ESM::Position position; mWorld.findInteriorPosition(it->mName, position); mNavigator.updateBounds(position.asVec3(), navigatorUpdateGuard.get()); @@ -890,7 +890,7 @@ namespace MWWorld loadingListener->setProgressRange(cell->count()); mNavigator.setWorldspace( - Misc::StringUtils::lowerCase(cell->getCell()->getCellId().mWorldspace), navigatorUpdateGuard.get()); + Misc::StringUtils::lowerCase(cell->getCell()->getNameId()), navigatorUpdateGuard.get()); mNavigator.updateBounds(position.asVec3(), navigatorUpdateGuard.get()); // Load cell. diff --git a/apps/openmw/mwworld/worldmodel.cpp b/apps/openmw/mwworld/worldmodel.cpp index 3e22ad02a6..357d5915f4 100644 --- a/apps/openmw/mwworld/worldmodel.cpp +++ b/apps/openmw/mwworld/worldmodel.cpp @@ -240,16 +240,12 @@ MWWorld::CellStore* MWWorld::WorldModel::getCell(const ESM::RefId& id) if (result != mCells.end()) return &result->second; - // TODO: in the future replace that with elsid's refId variant that can be a osg::Vec2i - const std::string& idString = id.getRefIdString(); - if (idString[0] == '#' && idString.find(',')) // That is an exterior cell Id + // TODO tetramir: in the future replace that with elsid's refId variant that can be a osg::Vec2i + ESM::CellId cellId = ESM::CellId::extractFromRefId(id); + if (cellId.mPaged) // That is an exterior cell Id { - int x, y; - std::stringstream stringStream = std::stringstream(idString); - char sharp = '#'; - char comma = ','; - stringStream >> sharp >> x >> comma >> y; - return getExterior(x, y); + + return getExterior(cellId.mIndex.mX, cellId.mIndex.mY); } const ESM4::Cell* cell4 = mStore.get().search(id); diff --git a/apps/openmw_test_suite/mwworld/test_store.cpp b/apps/openmw_test_suite/mwworld/test_store.cpp index 4539478e17..8f2623522a 100644 --- a/apps/openmw_test_suite/mwworld/test_store.cpp +++ b/apps/openmw_test_suite/mwworld/test_store.cpp @@ -445,6 +445,13 @@ namespace decltype(RecordType::mId) refId; if constexpr (ESM::hasIndex && !std::is_same_v) refId = RecordType::indexToRefId(index); + else if constexpr (std::is_same_v) + { + ESM::CellId cellId; + cellId.mPaged = true; + cellId.mIndex = { 0, 0 }; + refId = cellId.getCellRefId(); + } else refId = ESM::StringRefId(stringId); @@ -484,6 +491,9 @@ namespace else result = esmStore.get().search(refId); + if (result == nullptr || result->mId != refId) + int debug = 0; + ASSERT_NE(result, nullptr); EXPECT_EQ(result->mId, refId); } diff --git a/components/esm3/cellid.cpp b/components/esm3/cellid.cpp index 08b81fcd81..c295084a91 100644 --- a/components/esm3/cellid.cpp +++ b/components/esm3/cellid.cpp @@ -2,6 +2,7 @@ #include "esmreader.hpp" #include "esmwriter.hpp" +#include namespace ESM { @@ -45,6 +46,30 @@ namespace ESM } } + CellId CellId::extractFromRefId(const ESM::RefId& id) + { + // This is bad and that code should not be merged. + const std::string& idString = id.getRefIdString(); + CellId out; + if (idString[0] == '#' && idString.find(',')) // That is an exterior cell Id + { + int x, y; + std::stringstream stringStream = std::stringstream(idString); + char sharp = '#'; + char comma = ','; + stringStream >> sharp >> x >> comma >> y; + out.mPaged = true; + out.mIndex = { x, y }; + } + else + { + out.mPaged = false; + out.mWorldspace = Misc::StringUtils::lowerCase(idString); + } + + return out; + } + bool operator==(const CellId& left, const CellId& right) { return left.mWorldspace == right.mWorldspace && left.mPaged == right.mPaged diff --git a/components/esm3/cellid.hpp b/components/esm3/cellid.hpp index 65cca87bb8..0b27425e35 100644 --- a/components/esm3/cellid.hpp +++ b/components/esm3/cellid.hpp @@ -26,6 +26,9 @@ namespace ESM void load(ESMReader& esm); void save(ESMWriter& esm) const; ESM::RefId getCellRefId() const; + + // TODO tetramir: this probably shouldn't exist, needs it because some CellIds are saved on disk + static CellId extractFromRefId(const ESM::RefId& id); }; bool operator==(const CellId& left, const CellId& right);