From 1d925154f256c09276b1e0b9247f3d385b713c73 Mon Sep 17 00:00:00 2001 From: cc9cii Date: Tue, 10 Aug 2021 18:00:49 +1000 Subject: [PATCH 1/5] Do not store (or worse, overwrite) empty PGRD records. Should resolve Issue #6209. --- apps/openmw/mwworld/store.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/apps/openmw/mwworld/store.cpp b/apps/openmw/mwworld/store.cpp index 125239e9a3..5b223544b0 100644 --- a/apps/openmw/mwworld/store.cpp +++ b/apps/openmw/mwworld/store.cpp @@ -866,6 +866,10 @@ namespace MWWorld pathgrid.load(esm, isDeleted); + // deal with MODs that have empty pathgrid records (Issue #6209) + if (pathgrid.mPoints.empty() || pathgrid.mEdges.empty()) + return RecordId("", isDeleted); + // Unfortunately the Pathgrid record model does not specify whether the pathgrid belongs to an interior or exterior cell. // For interior cells, mCell is the cell name, but for exterior cells it is either the cell name or if that doesn't exist, the cell's region name. // mX and mY will be (0,0) for interior cells, but there is also an exterior cell with the coordinates of (0,0), so that doesn't help. From 8244ba8957403c6a6b0e0981b97547f9a8fbadc8 Mon Sep 17 00:00:00 2001 From: cc9cii Date: Tue, 10 Aug 2021 19:39:46 +1000 Subject: [PATCH 2/5] Erase old record instead (i.e. assume an empty Pathgrid record was placed in purpose) --- apps/openmw/mwworld/store.cpp | 38 +++++++++++++++++++++++++++++++---- 1 file changed, 34 insertions(+), 4 deletions(-) diff --git a/apps/openmw/mwworld/store.cpp b/apps/openmw/mwworld/store.cpp index 5b223544b0..957a01faf6 100644 --- a/apps/openmw/mwworld/store.cpp +++ b/apps/openmw/mwworld/store.cpp @@ -866,10 +866,6 @@ namespace MWWorld pathgrid.load(esm, isDeleted); - // deal with MODs that have empty pathgrid records (Issue #6209) - if (pathgrid.mPoints.empty() || pathgrid.mEdges.empty()) - return RecordId("", isDeleted); - // Unfortunately the Pathgrid record model does not specify whether the pathgrid belongs to an interior or exterior cell. // For interior cells, mCell is the cell name, but for exterior cells it is either the cell name or if that doesn't exist, the cell's region name. // mX and mY will be (0,0) for interior cells, but there is also an exterior cell with the coordinates of (0,0), so that doesn't help. @@ -877,6 +873,40 @@ namespace MWWorld // A proper fix should be made for future versions of the file format. bool interior = pathgrid.mData.mX == 0 && pathgrid.mData.mY == 0 && mCells->search(pathgrid.mCell) != nullptr; + // deal with MODs that have empty pathgrid records (Issue #6209) + // we assume that these records are empty on purpose (i.e. to remove old pathgrid on an updated cell) + if (pathgrid.mPoints.empty() || pathgrid.mEdges.empty()) + { + std::string contentfile = esm.getContext().filename; + size_t pos = contentfile.find_last_of("/\\"); + if (pos != std::string::npos) + contentfile = contentfile.substr(pos+1); + + if (interior) + { + Interior::iterator it = mInt.find(pathgrid.mCell); + if (it != mInt.end()) + { + mInt.erase(it); + + Log(Debug::Warning) << "Warning: Empty pathgrid overwriting cell '" + << pathgrid.mCell << "' : " << contentfile; + } + } + else + { + Exterior::iterator it = mExt.find(std::make_pair(pathgrid.mData.mX, pathgrid.mData.mY)); + if (it != mExt.end()) + { + mExt.erase(it); + Log(Debug::Warning) << "Warning: Empty pathgrid overwriting cell (" + << pathgrid.mData.mX << ", " << pathgrid.mData.mY << ") : " << contentfile; + } + } + + return RecordId("", isDeleted); + } + // Try to overwrite existing record if (interior) { From 802a202455487d878156dbc89a7cb9df34a19676 Mon Sep 17 00:00:00 2001 From: cc9cii Date: Thu, 19 Aug 2021 12:45:09 +1000 Subject: [PATCH 3/5] Remove warning log messages as they are more suitable for OpenCS. --- apps/openmw/mwworld/store.cpp | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/apps/openmw/mwworld/store.cpp b/apps/openmw/mwworld/store.cpp index 957a01faf6..8faa86597f 100644 --- a/apps/openmw/mwworld/store.cpp +++ b/apps/openmw/mwworld/store.cpp @@ -873,35 +873,21 @@ namespace MWWorld // A proper fix should be made for future versions of the file format. bool interior = pathgrid.mData.mX == 0 && pathgrid.mData.mY == 0 && mCells->search(pathgrid.mCell) != nullptr; - // deal with MODs that have empty pathgrid records (Issue #6209) + // deal with mods that have empty pathgrid records (Issue #6209) // we assume that these records are empty on purpose (i.e. to remove old pathgrid on an updated cell) if (pathgrid.mPoints.empty() || pathgrid.mEdges.empty()) { - std::string contentfile = esm.getContext().filename; - size_t pos = contentfile.find_last_of("/\\"); - if (pos != std::string::npos) - contentfile = contentfile.substr(pos+1); - if (interior) { Interior::iterator it = mInt.find(pathgrid.mCell); if (it != mInt.end()) - { mInt.erase(it); - - Log(Debug::Warning) << "Warning: Empty pathgrid overwriting cell '" - << pathgrid.mCell << "' : " << contentfile; - } } else { Exterior::iterator it = mExt.find(std::make_pair(pathgrid.mData.mX, pathgrid.mData.mY)); if (it != mExt.end()) - { mExt.erase(it); - Log(Debug::Warning) << "Warning: Empty pathgrid overwriting cell (" - << pathgrid.mData.mX << ", " << pathgrid.mData.mY << ") : " << contentfile; - } } return RecordId("", isDeleted); From bd3ef506cd65f34c9a75024c92b2b205377473c6 Mon Sep 17 00:00:00 2001 From: cc9cii Date: Thu, 19 Aug 2021 19:30:01 +1000 Subject: [PATCH 4/5] Empty Pathgrid record is considered as the modder's intention to delete any existing record. --- apps/opencs/CMakeLists.txt | 2 +- apps/opencs/model/world/idcollection.cpp | 43 ++++++++++++++++++++++++ apps/opencs/model/world/idcollection.hpp | 4 +++ apps/opencs/model/world/pathgrid.hpp | 2 +- 4 files changed, 49 insertions(+), 2 deletions(-) create mode 100644 apps/opencs/model/world/idcollection.cpp diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt index 88c4233c9c..4265490afb 100644 --- a/apps/opencs/CMakeLists.txt +++ b/apps/opencs/CMakeLists.txt @@ -19,7 +19,7 @@ opencs_hdrs_noqt (model/doc opencs_units (model/world idtable idtableproxymodel regionmap data commanddispatcher idtablebase resourcetable nestedtableproxymodel idtree infotableproxymodel landtexturetableproxymodel - actoradapter + actoradapter idcollection ) diff --git a/apps/opencs/model/world/idcollection.cpp b/apps/opencs/model/world/idcollection.cpp new file mode 100644 index 0000000000..d06a47e32b --- /dev/null +++ b/apps/opencs/model/world/idcollection.cpp @@ -0,0 +1,43 @@ +#include "idcollection.hpp" + +namespace CSMWorld +{ + template<> + int IdCollection >::load (ESM::ESMReader& reader, bool base) + { + Pathgrid record; + bool isDeleted = false; + + loadRecord (record, reader, isDeleted); + + std::string id = IdAccessor().getId (record); + int index = this->searchId (id); + + if (record.mPoints.empty() || record.mEdges.empty()) + isDeleted = true; + + if (isDeleted) + { + if (index==-1) + { + // deleting a record that does not exist + // ignore it for now + /// \todo report the problem to the user + return -1; + } + + if (base) + { + this->removeRows (index, 1); + return -1; + } + + std::unique_ptr > baseRecord(new Record(this->getRecord(index))); + baseRecord->mState = RecordBase::State_Deleted; + this->setRecord(index, std::move(baseRecord)); + return index; + } + + return load (record, base, index); + } +} diff --git a/apps/opencs/model/world/idcollection.hpp b/apps/opencs/model/world/idcollection.hpp index 9f834d8fae..bbc49f18c1 100644 --- a/apps/opencs/model/world/idcollection.hpp +++ b/apps/opencs/model/world/idcollection.hpp @@ -5,6 +5,7 @@ #include "collection.hpp" #include "land.hpp" +#include "pathgrid.hpp" namespace CSMWorld { @@ -153,6 +154,9 @@ namespace CSMWorld return true; } + + template<> + int IdCollection >::load(ESM::ESMReader& reader, bool base); } #endif diff --git a/apps/opencs/model/world/pathgrid.hpp b/apps/opencs/model/world/pathgrid.hpp index 22d01b0710..ce74d419e4 100644 --- a/apps/opencs/model/world/pathgrid.hpp +++ b/apps/opencs/model/world/pathgrid.hpp @@ -20,7 +20,7 @@ namespace CSMWorld { std::string mId; - void load (ESM::ESMReader &esm, bool &isDeleted, const IdCollection& cells); + void load (ESM::ESMReader &esm, bool &isDeleted, const IdCollection >& cells); void load (ESM::ESMReader &esm, bool &isDeleted); }; } From 28ad139464b5d08c5d213e6fda128a2906d74345 Mon Sep 17 00:00:00 2001 From: cc9cii Date: Sat, 21 Aug 2021 07:20:10 +1000 Subject: [PATCH 5/5] Check if deleted, just in case. --- apps/openmw/mwworld/store.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/openmw/mwworld/store.cpp b/apps/openmw/mwworld/store.cpp index 8faa86597f..f6de1d485b 100644 --- a/apps/openmw/mwworld/store.cpp +++ b/apps/openmw/mwworld/store.cpp @@ -875,7 +875,7 @@ namespace MWWorld // deal with mods that have empty pathgrid records (Issue #6209) // we assume that these records are empty on purpose (i.e. to remove old pathgrid on an updated cell) - if (pathgrid.mPoints.empty() || pathgrid.mEdges.empty()) + if (isDeleted || pathgrid.mPoints.empty() || pathgrid.mEdges.empty()) { if (interior) {