From 6db2450c90c7de74004c1d89b771080a1eaae99f Mon Sep 17 00:00:00 2001 From: Petr Mikheev Date: Fri, 22 Jan 2021 15:48:37 +0100 Subject: [PATCH] Initial support of generated RefNums with negative mContentFile. --- apps/openmw/mwrender/groundcover.cpp | 2 +- apps/openmw/mwrender/objectpaging.cpp | 2 +- apps/openmw/mwworld/cellref.cpp | 22 ++++++++++++++++++++++ apps/openmw/mwworld/cellref.hpp | 4 ++++ apps/openmw/mwworld/cellstore.cpp | 2 +- apps/openmw/mwworld/esmstore.cpp | 2 +- apps/openmw/mwworld/worldimp.cpp | 2 +- components/esm/cellref.cpp | 3 ++- components/esm/cellref.hpp | 7 ++++--- components/esm/globalscript.cpp | 2 +- 10 files changed, 38 insertions(+), 10 deletions(-) diff --git a/apps/openmw/mwrender/groundcover.cpp b/apps/openmw/mwrender/groundcover.cpp index 9416a48ec8..dd64c851f1 100644 --- a/apps/openmw/mwrender/groundcover.cpp +++ b/apps/openmw/mwrender/groundcover.cpp @@ -225,7 +225,7 @@ namespace MWRender esm.resize(index+1); cell->restore(esm[index], i); ESM::CellRef ref; - ref.mRefNum.mContentFile = ESM::RefNum::RefNum_NoContentFile; + ref.mRefNum.unset(); bool deleted = false; while(cell->getNextRef(esm[index], ref, deleted)) { diff --git a/apps/openmw/mwrender/objectpaging.cpp b/apps/openmw/mwrender/objectpaging.cpp index a5792d56b9..6b5f9a6e34 100644 --- a/apps/openmw/mwrender/objectpaging.cpp +++ b/apps/openmw/mwrender/objectpaging.cpp @@ -422,7 +422,7 @@ namespace MWRender esm.resize(index+1); cell->restore(esm[index], i); ESM::CellRef ref; - ref.mRefNum.mContentFile = ESM::RefNum::RefNum_NoContentFile; + ref.mRefNum.unset(); ESM::MovedCellRef cMRef; cMRef.mRefNum.mIndex = 0; bool deleted = false; diff --git a/apps/openmw/mwworld/cellref.cpp b/apps/openmw/mwworld/cellref.cpp index 188a80ae14..88c38736e8 100644 --- a/apps/openmw/mwworld/cellref.cpp +++ b/apps/openmw/mwworld/cellref.cpp @@ -1,5 +1,8 @@ #include "cellref.hpp" +#include + +#include #include namespace MWWorld @@ -10,6 +13,25 @@ namespace MWWorld return mCellRef.mRefNum; } + const ESM::RefNum& CellRef::getOrAssignRefNum(ESM::RefNum& lastAssignedRefNum) + { + if (!mCellRef.mRefNum.isSet()) + { + // Generated RefNums have negative mContentFile + assert(lastAssignedRefNum.mContentFile < 0); + lastAssignedRefNum.mIndex++; + if (lastAssignedRefNum.mIndex == 0) // mIndex overflow, so mContentFile should be changed + { + lastAssignedRefNum.mContentFile--; + if (lastAssignedRefNum.mContentFile > 0) + Log(Debug::Error) << "RefNum counter overflow in CellRef::getOrAssignRefNum"; + } + mCellRef.mRefNum = lastAssignedRefNum; + mChanged = true; + } + return mCellRef.mRefNum; + } + bool CellRef::hasContentFile() const { return mCellRef.mRefNum.hasContentFile(); diff --git a/apps/openmw/mwworld/cellref.hpp b/apps/openmw/mwworld/cellref.hpp index f9f6dbdda2..6a6ac69c57 100644 --- a/apps/openmw/mwworld/cellref.hpp +++ b/apps/openmw/mwworld/cellref.hpp @@ -25,6 +25,10 @@ namespace MWWorld // Note: Currently unused for items in containers const ESM::RefNum& getRefNum() const; + // Returns RefNum. + // If RefNum is not set, assigns a generated one and changes the "lastAssignedRefNum" counter. + const ESM::RefNum& getOrAssignRefNum(ESM::RefNum& lastAssignedRefNum); + // Set RefNum to its default state. void unsetRefNum(); diff --git a/apps/openmw/mwworld/cellstore.cpp b/apps/openmw/mwworld/cellstore.cpp index 3aaf6061e3..0d2ee85deb 100644 --- a/apps/openmw/mwworld/cellstore.cpp +++ b/apps/openmw/mwworld/cellstore.cpp @@ -615,7 +615,7 @@ namespace MWWorld mCell->restore (esm[index], i); ESM::CellRef ref; - ref.mRefNum.mContentFile = ESM::RefNum::RefNum_NoContentFile; + ref.mRefNum.unset(); // Get each reference in turn ESM::MovedCellRef cMRef; diff --git a/apps/openmw/mwworld/esmstore.cpp b/apps/openmw/mwworld/esmstore.cpp index 864cb0d9d1..4b9bdf7426 100644 --- a/apps/openmw/mwworld/esmstore.cpp +++ b/apps/openmw/mwworld/esmstore.cpp @@ -34,7 +34,7 @@ namespace readers.resize(index + 1); cell.restore(readers[index], i); ESM::CellRef ref; - ref.mRefNum.mContentFile = ESM::RefNum::RefNum_NoContentFile; + ref.mRefNum.unset(); bool deleted = false; while(cell.getNextRef(readers[index], ref, deleted)) { diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 14c7716f2e..69167e5ccb 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -2020,7 +2020,7 @@ namespace MWWorld rayToObject = mRendering->castCameraToViewportRay(0.5f, 0.5f, maxDistance, ignorePlayer); facedObject = rayToObject.mHitObject; - if (facedObject.isEmpty() && rayToObject.mHitRefnum.hasContentFile()) + if (facedObject.isEmpty() && rayToObject.mHitRefnum.isSet()) { for (CellStore* cellstore : mWorldScene->getActiveCells()) { diff --git a/components/esm/cellref.cpp b/components/esm/cellref.cpp index 7ec7e00f1a..81e0b9f557 100644 --- a/components/esm/cellref.cpp +++ b/components/esm/cellref.cpp @@ -24,8 +24,9 @@ void ESM::RefNum::save (ESMWriter &esm, bool wide, const std::string& tag) const esm.writeHNT (tag, *this, 8); else { + if (isSet() && !hasContentFile()) + Log(Debug::Error) << "Generated RefNum can not be saved in 32bit format"; int refNum = (mIndex & 0xffffff) | ((hasContentFile() ? mContentFile : 0xff)<<24); - esm.writeHNT (tag, refNum, 4); } } diff --git a/components/esm/cellref.hpp b/components/esm/cellref.hpp index c2f7ff6de5..f6eff24cbf 100644 --- a/components/esm/cellref.hpp +++ b/components/esm/cellref.hpp @@ -23,9 +23,10 @@ namespace ESM void save (ESMWriter &esm, bool wide = false, const std::string& tag = "FRMR") const; - enum { RefNum_NoContentFile = -1 }; - inline bool hasContentFile() const { return mContentFile != RefNum_NoContentFile; } - inline void unset() { mIndex = 0; mContentFile = RefNum_NoContentFile; } + inline bool hasContentFile() const { return mContentFile >= 0; } + + inline bool isSet() const { return mIndex != 0 || mContentFile != -1; } + inline void unset() { *this = {0, -1}; } // Note: this method should not be used for objects with invalid RefNum // (for example, for objects from disabled plugins in savegames). diff --git a/components/esm/globalscript.cpp b/components/esm/globalscript.cpp index 016ea4f0cf..a8a8e79cf5 100644 --- a/components/esm/globalscript.cpp +++ b/components/esm/globalscript.cpp @@ -30,7 +30,7 @@ void ESM::GlobalScript::save (ESMWriter &esm) const if (!mTargetId.empty()) { esm.writeHNOString ("TARG", mTargetId); - if (mTargetRef.hasContentFile()) + if (mTargetRef.isSet()) mTargetRef.save (esm, true, "FRMR"); } }