From b54e5714c968b29ed3d87ca13bfa376ba28bc192 Mon Sep 17 00:00:00 2001 From: cc9cii Date: Sun, 26 Apr 2015 14:55:40 +1000 Subject: [PATCH] Revert rebasing the moved refs to the new cell, because the original ref may still be referred by a mod. --- apps/opencs/model/doc/savingstages.cpp | 13 ++---- apps/opencs/model/world/data.cpp | 2 +- apps/opencs/model/world/refcollection.cpp | 55 +++++++++++------------ apps/opencs/model/world/refcollection.hpp | 3 +- 4 files changed, 33 insertions(+), 40 deletions(-) diff --git a/apps/opencs/model/doc/savingstages.cpp b/apps/opencs/model/doc/savingstages.cpp index 5a45691d5..1f6da2580 100644 --- a/apps/opencs/model/doc/savingstages.cpp +++ b/apps/opencs/model/doc/savingstages.cpp @@ -303,13 +303,6 @@ void CSMDoc::WriteCellCollectionStage::perform (int stage, Messages& messages) if (ref.mState==CSMWorld::RecordBase::State_Modified || ref.mState==CSMWorld::RecordBase::State_ModifiedOnly) { - // To get an MVRF tag, the ref's mOriginalCell needs to be non-empty (empty - // is meant to indicate that it is the same as the current cell) and - // different to mCell (its current cell) TODO: the second check seems redundant? - // - // To have mOriginalCell be non-empty, it needs to be loaded as 'base' in - // RefCollection::load() - // // recalculate the ref's cell location std::ostringstream stream; if (!interior) @@ -318,8 +311,10 @@ void CSMDoc::WriteCellCollectionStage::perform (int stage, Messages& messages) stream << "#" << index.first << " " << index.second; } - if (!ref.get().mOriginalCell.empty() && - ref.get().mOriginalCell!=stream.str()) + // An empty mOriginalCell is meant to indicate that it is the same as + // the current cell. It is possible that a moved ref is moved again. + if ((ref.get().mOriginalCell.empty() ? ref.get().mCell : ref.get().mOriginalCell) + != stream.str()) { ESM::MovedCellRef moved; moved.mRefNum = ref.get().mRefNum; diff --git a/apps/opencs/model/world/data.cpp b/apps/opencs/model/world/data.cpp index f4ae78ae7..97b34551d 100644 --- a/apps/opencs/model/world/data.cpp +++ b/apps/opencs/model/world/data.cpp @@ -870,7 +870,7 @@ bool CSMWorld::Data::continueLoading (CSMDoc::Messages& messages) index = mCells.getSize()-1; } std::string cellId = Misc::StringUtils::lowerCase (mCells.getId (index)); - mRefs.load (*mReader, index, mBase, mRefLoadCache, cellId, messages); + mRefs.load (*mReader, index, mBase, mRefLoadCache[cellId], messages); break; } diff --git a/apps/opencs/model/world/refcollection.cpp b/apps/opencs/model/world/refcollection.cpp index c94ec1dc4..8f12b6844 100644 --- a/apps/opencs/model/world/refcollection.cpp +++ b/apps/opencs/model/world/refcollection.cpp @@ -13,10 +13,8 @@ #include "record.hpp" void CSMWorld::RefCollection::load (ESM::ESMReader& reader, int cellIndex, bool base, - std::map >& cache, const std::string& origCellId, - CSMDoc::Messages& messages) + std::map& cache, CSMDoc::Messages& messages) { - std::string cellid = origCellId; Record cell = mCells.getRecord (cellIndex); Cell& cell2 = base ? cell.mBase : cell.mModified; @@ -43,18 +41,13 @@ void CSMWorld::RefCollection::load (ESM::ESMReader& reader, int cellIndex, bool ref.mCell = stream.str(); - // It is not always possibe to ignore moved references sub-record and calculate from - // coordinates. Some mods may place the ref in positions outside normal bounds, - // resulting in non sensical cell id's. - // - // Use the target cell from the MVRF tag but if different output an error message if (!base && // don't try to update base records mref.mRefNum.mIndex != 0) // MVRF tag found { - std::ostringstream stream; - stream << "#" << mref.mTarget[0] << " " << mref.mTarget[1]; - ref.mCell = stream.str(); // overwrite - + // there is a requirement for a placeholder where the original object was + // + // see the forum discussions here for more details: + // https://forum.openmw.org/viewtopic.php?f=6&t=577&start=30 ref.mOriginalCell = cell2.mId; if (deleted) @@ -67,29 +60,35 @@ void CSMWorld::RefCollection::load (ESM::ESMReader& reader, int cellIndex, bool continue; } - else + + // It is not always possibe to ignore moved references sub-record and + // calculate from coordinates. Some mods may place the ref in positions + // outside normal bounds, resulting in non sensical cell id's. This often + // happens if the moved ref was deleted. + // + // Use the target cell from the MVRF tag but if different output an error + // message + if (index.first != mref.mTarget[0] || index.second != mref.mTarget[1]) { - if (index.first != mref.mTarget[0] || index.second != mref.mTarget[1]) - { - std::cerr << "The Position of moved ref " - << ref.mRefID << " does not match the target cell" << std::endl; - std::cerr << "Position: #" << index.first << " " << index.second - <<", Target #"<< mref.mTarget[0] << " " << mref.mTarget[1] << std::endl; - } - - // transfer the ref to the new cell - cellid = ref.mCell; + std::cerr << "The Position of moved ref " + << ref.mRefID << " does not match the target cell" << std::endl; + std::cerr << "Position: #" << index.first << " " << index.second + <<", Target #"<< mref.mTarget[0] << " " << mref.mTarget[1] << std::endl; + + std::ostringstream stream; + stream << "#" << mref.mTarget[0] << " " << mref.mTarget[1]; + ref.mCell = stream.str(); // overwrite } } } else ref.mCell = cell2.mId; - std::map::iterator iter = cache[cellid].find (ref.mRefNum); + std::map::iterator iter = cache.find (ref.mRefNum); if (deleted) { - if (iter==cache[cellid].end()) + if (iter==cache.end()) { CSMWorld::UniversalId id (CSMWorld::UniversalId::Type_Cell, mCells.getId (cellIndex)); @@ -106,7 +105,7 @@ void CSMWorld::RefCollection::load (ESM::ESMReader& reader, int cellIndex, bool if (record.mState==RecordBase::State_BaseOnly) { removeRows (index, 1); - cache[cellid].erase (iter); + cache.erase (iter); } else { @@ -117,7 +116,7 @@ void CSMWorld::RefCollection::load (ESM::ESMReader& reader, int cellIndex, bool continue; } - if (iter==cache[cellid].end()) + if (iter==cache.end()) { // new reference ref.mId = getNewId(); @@ -128,7 +127,7 @@ void CSMWorld::RefCollection::load (ESM::ESMReader& reader, int cellIndex, bool appendRecord (record); - cache[cellid].insert (std::make_pair (ref.mRefNum, ref.mId)); + cache.insert (std::make_pair (ref.mRefNum, ref.mId)); } else { diff --git a/apps/opencs/model/world/refcollection.hpp b/apps/opencs/model/world/refcollection.hpp index 82ec2f390..d031398d3 100644 --- a/apps/opencs/model/world/refcollection.hpp +++ b/apps/opencs/model/world/refcollection.hpp @@ -27,8 +27,7 @@ namespace CSMWorld {} void load (ESM::ESMReader& reader, int cellIndex, bool base, - std::map >& cache, const std::string& cellid, - CSMDoc::Messages& messages); + std::map& cache, CSMDoc::Messages& messages); ///< Load a sequence of references. std::string getNewId();