diff --git a/apps/openmw/mwbase/world.hpp b/apps/openmw/mwbase/world.hpp index 5caacbdb4d..bd43d689d3 100644 --- a/apps/openmw/mwbase/world.hpp +++ b/apps/openmw/mwbase/world.hpp @@ -512,15 +512,15 @@ namespace MWBase virtual bool screenshot360(osg::Image* image) = 0; /// Find default position inside exterior cell specified by name - /// \return invalid RefId if exterior with given name not exists, the cell's RefId otherwise + /// \return empty RefId if exterior with given name not exists, the cell's RefId otherwise virtual ESM::RefId findExteriorPosition(std::string_view name, ESM::Position& pos) = 0; /// Find default position inside interior cell specified by name - /// \return invalid RefId if interior with given name not exists, the cell's RefId otherwise + /// \return empty RefId if interior with given name not exists, the cell's RefId otherwise virtual ESM::RefId findInteriorPosition(std::string_view name, ESM::Position& pos) = 0; /// Find default position inside interior or exterior cell specified by name - /// \return invalid RefId if interior with given name not exists, the cell's RefId otherwise + /// \return empty RefId if interior with given name not exists, the cell's RefId otherwise virtual ESM::RefId findCellPosition(std::string_view cellName, ESM::Position& pos) = 0; /// Enables or disables use of teleport spell effects (recall, intervention, etc). virtual void enableTeleporting(bool enable) = 0; diff --git a/apps/openmw/mwmechanics/aifollow.cpp b/apps/openmw/mwmechanics/aifollow.cpp index 66acec8770..68162119d2 100644 --- a/apps/openmw/mwmechanics/aifollow.cpp +++ b/apps/openmw/mwmechanics/aifollow.cpp @@ -174,8 +174,7 @@ namespace MWMechanics return true; } } - else if (Misc::StringUtils::ciEqual(mCellId, - actor.getCell()->getCell()->getWorldSpace().toString())) // Cell to travel to + else if (mCellId == actor.getCell()->getCell()->getWorldSpace()) // Cell to travel to { mRemainingDuration = mDuration; return true; diff --git a/apps/openmw/mwmechanics/aipackage.cpp b/apps/openmw/mwmechanics/aipackage.cpp index d4365a478f..6a7dcb6c7c 100644 --- a/apps/openmw/mwmechanics/aipackage.cpp +++ b/apps/openmw/mwmechanics/aipackage.cpp @@ -330,7 +330,7 @@ void MWMechanics::AiPackage::openDoors(const MWWorld::Ptr& actor) const MWMechanics::PathgridGraph& MWMechanics::AiPackage::getPathGridGraph(const MWWorld::CellStore* cell) { - const ESM::RefId& id = cell->getCell()->getId(); + const ESM::RefId id = cell->getCell()->getId(); // static cache is OK for now, pathgrids can never change during runtime typedef std::map> CacheMap; static CacheMap cache; diff --git a/apps/openmw/mwstate/statemanagerimp.cpp b/apps/openmw/mwstate/statemanagerimp.cpp index a2a6171f06..b51ab11a11 100644 --- a/apps/openmw/mwstate/statemanagerimp.cpp +++ b/apps/openmw/mwstate/statemanagerimp.cpp @@ -554,7 +554,7 @@ void MWState::StateManager::loadGame(const Character* character, const std::file if (ptr.isInCell()) { - const ESM::RefId& cellId = ptr.getCell()->getCell()->getId(); + 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); diff --git a/apps/openmw/mwworld/actionteleport.cpp b/apps/openmw/mwworld/actionteleport.cpp index f1b6934ae2..2db14338d6 100644 --- a/apps/openmw/mwworld/actionteleport.cpp +++ b/apps/openmw/mwworld/actionteleport.cpp @@ -54,8 +54,7 @@ namespace MWWorld if (actor == world->getPlayerPtr()) { world->getPlayer().setTeleported(true); - if (!mCellId.empty()) - world->changeToCell(mCellId, mPosition, true); + world->changeToCell(mCellId, mPosition, true); teleported = world->getPlayerPtr(); } else diff --git a/apps/openmw/mwworld/scene.cpp b/apps/openmw/mwworld/scene.cpp index db692957f2..313b0ed8f9 100644 --- a/apps/openmw/mwworld/scene.cpp +++ b/apps/openmw/mwworld/scene.cpp @@ -752,7 +752,7 @@ namespace MWWorld { assert(!(*iter)->getCell()->isExterior()); - if (it->mName == (*iter)->getCell()->getWorldSpace().toString()) + if (it->mName == (*iter)->getCell()->getNameId()) { unloadCell(*iter, navigatorUpdateGuard.get()); break; diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 8d0bc5782e..b7c30327aa 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -2801,7 +2801,7 @@ namespace MWWorld // and use its destination to position inside cell. for (const MWWorld::LiveCellRef& destDoor : source->getReadOnlyDoors().mList) { - if (ESM::RefId::stringRefId(name) == destDoor.mRef.getDestCell()) + if (name == destDoor.mRef.getDestCell()) { /// \note Using _any_ door pointed to the interior, /// not the one pointed to current door. @@ -2869,7 +2869,7 @@ namespace MWWorld { ext = mWorldModel.getCell(nameId)->getCell(); if (!ext->isExterior()) - return ESM::RefId::sEmpty; + return ESM::RefId(); } catch (std::exception&) { diff --git a/apps/openmw_test_suite/mwworld/test_store.cpp b/apps/openmw_test_suite/mwworld/test_store.cpp index 6a38b1cd5b..aea74fab71 100644 --- a/apps/openmw_test_suite/mwworld/test_store.cpp +++ b/apps/openmw_test_suite/mwworld/test_store.cpp @@ -285,7 +285,7 @@ namespace ESM::MaxOldSkillsAndAttributesFormatVersion, ESM::MaxOldCreatureStatsFormatVersion, ESM::MaxStringRefIdFormatVersion, - ESM::MaxUseEsmCellId, + ESM::MaxUseEsmCellIdFormatVersion, }); for (ESM::FormatVersion v = result.back() + 1; v <= ESM::CurrentSaveGameFormatVersion; ++v) result.push_back(v); diff --git a/components/CMakeLists.txt b/components/CMakeLists.txt index 55fb7a76d4..b8463c8af0 100644 --- a/components/CMakeLists.txt +++ b/components/CMakeLists.txt @@ -392,7 +392,7 @@ if (USE_QT) ) add_component_qt_dir (misc - helpviewer utf8qtextstream + helpviewer utf8qtextstream hash ) add_component_qt_dir (files diff --git a/components/esm/esm3exteriorcellrefid.hpp b/components/esm/esm3exteriorcellrefid.hpp index 00dd3ae26a..9bb9bf17d8 100644 --- a/components/esm/esm3exteriorcellrefid.hpp +++ b/components/esm/esm3exteriorcellrefid.hpp @@ -6,6 +6,8 @@ #include +#include + namespace ESM { class ESM3ExteriorCellRefId @@ -47,7 +49,7 @@ namespace std { std::size_t operator()(ESM::ESM3ExteriorCellRefId value) const noexcept { - return (53 + std::hash{}(value.mX)) * 53 + std::hash{}(value.mY); + return Misc::hash2dCoord(value.mX, value.mY); } }; } diff --git a/components/esm3/esmreader.cpp b/components/esm3/esmreader.cpp index 6c7c6cc5a7..42a2b2898a 100644 --- a/components/esm3/esmreader.cpp +++ b/components/esm3/esmreader.cpp @@ -90,7 +90,7 @@ namespace ESM ESM::RefId ESMReader::getCellId() { - if (mHeader.mFormatVersion <= ESM::MaxUseEsmCellId) + if (mHeader.mFormatVersion <= ESM::MaxUseEsmCellIdFormatVersion) { ESM::CellId cellId; cellId.load(*this); diff --git a/components/esm3/esmwriter.cpp b/components/esm3/esmwriter.cpp index a536169970..59a3711b2d 100644 --- a/components/esm3/esmwriter.cpp +++ b/components/esm3/esmwriter.cpp @@ -246,7 +246,7 @@ namespace ESM void ESMWriter::writeCellId(const ESM::RefId& cellId) { - if (mHeader.mFormatVersion <= ESM::MaxUseEsmCellId) + if (mHeader.mFormatVersion <= ESM::MaxUseEsmCellIdFormatVersion) { ESM::CellId generatedCellid = ESM::CellId::extractFromRefId(cellId); generatedCellid.save(*this); diff --git a/components/esm3/formatversion.hpp b/components/esm3/formatversion.hpp index bb34d2eb7c..aa0de9b0b7 100644 --- a/components/esm3/formatversion.hpp +++ b/components/esm3/formatversion.hpp @@ -23,7 +23,7 @@ namespace ESM inline constexpr FormatVersion MaxStringRefIdFormatVersion = 23; inline constexpr FormatVersion MaxSavedGameCellNameAsRefIdFormatVersion = 24; inline constexpr FormatVersion MaxNameIsRefIdOnlyFormatVersion = 25; - inline constexpr FormatVersion MaxUseEsmCellId = 26; + inline constexpr FormatVersion MaxUseEsmCellIdFormatVersion = 26; inline constexpr FormatVersion CurrentSaveGameFormatVersion = 27; } diff --git a/components/misc/hash.hpp b/components/misc/hash.hpp index 461acee303..f87f0daeda 100644 --- a/components/misc/hash.hpp +++ b/components/misc/hash.hpp @@ -15,6 +15,13 @@ namespace Misc std::hash hasher; seed ^= static_cast(hasher(v) + 0x9e3779b9 + (seed << 6) + (seed >> 2)); } + + // Comes from https://stackoverflow.com/questions/2634690/good-hash-function-for-a-2d-index + // Effective Java (2nd edition) is cited as the source + inline std::size_t hash2dCoord(int32_t x, int32_t y) + { + return (53 + std::hash{}(x)) * 53 + std::hash{}(y); + } } #endif