1
0
Fork 0
mirror of https://github.com/OpenMW/openmw.git synced 2025-03-01 05:09:41 +00:00

Merge branch 'moved_cell_ref' into 'master'

Skip only a single cell ref after MVRF subrecord

See merge request OpenMW/openmw!1014
This commit is contained in:
psi29a 2021-07-14 08:19:33 +00:00
commit f403b464f0
7 changed files with 66 additions and 51 deletions

View file

@ -236,7 +236,9 @@ void loadCell(ESM::Cell &cell, ESM::ESMReader &esm, Arguments& info)
if(!quiet) std::cout << " References:\n"; if(!quiet) std::cout << " References:\n";
bool deleted = false; bool deleted = false;
while(cell.getNextRef(esm, ref, deleted)) ESM::MovedCellRef movedCellRef;
bool moved = false;
while(cell.getNextRef(esm, ref, deleted, movedCellRef, moved))
{ {
if (save) { if (save) {
info.data.mCellRefs[&cell].push_back(std::make_pair(ref, deleted)); info.data.mCellRefs[&cell].push_back(std::make_pair(ref, deleted));
@ -244,7 +246,7 @@ void loadCell(ESM::Cell &cell, ESM::ESMReader &esm, Arguments& info)
if(quiet) continue; if(quiet) continue;
std::cout << " Refnum: " << ref.mRefNum.mIndex << '\n'; std::cout << " - Refnum: " << ref.mRefNum.mIndex << '\n';
std::cout << " ID: " << ref.mRefID << '\n'; std::cout << " ID: " << ref.mRefID << '\n';
std::cout << " Position: (" << ref.mPos.pos[0] << ", " << ref.mPos.pos[1] << ", " << ref.mPos.pos[2] << ")\n"; std::cout << " Position: (" << ref.mPos.pos[0] << ", " << ref.mPos.pos[1] << ", " << ref.mPos.pos[2] << ")\n";
if (ref.mScale != 1.f) if (ref.mScale != 1.f)
@ -276,6 +278,13 @@ void loadCell(ESM::Cell &cell, ESM::ESMReader &esm, Arguments& info)
if (!ref.mDestCell.empty()) if (!ref.mDestCell.empty())
std::cout << " Destination cell: " << ref.mDestCell << '\n'; std::cout << " Destination cell: " << ref.mDestCell << '\n';
} }
std::cout << " Moved: " << std::boolalpha << moved << '\n';
if (moved)
{
std::cout << " Moved refnum: " << movedCellRef.mRefNum.mIndex << '\n';
std::cout << " Moved content file: " << movedCellRef.mRefNum.mContentFile << '\n';
std::cout << " Target: " << movedCellRef.mTarget[0] << ", " << movedCellRef.mTarget[1] << '\n';
}
} }
} }

View file

@ -19,8 +19,9 @@ void CSMWorld::RefCollection::load (ESM::ESMReader& reader, int cellIndex, bool
ESM::MovedCellRef mref; ESM::MovedCellRef mref;
mref.mRefNum.mIndex = 0; mref.mRefNum.mIndex = 0;
bool isDeleted = false; bool isDeleted = false;
bool isMoved = false;
while (ESM::Cell::getNextRef(reader, ref, isDeleted, true, &mref)) while (ESM::Cell::getNextRef(reader, ref, isDeleted, mref, isMoved))
{ {
// Keep mOriginalCell empty when in modified (as an indicator that the // Keep mOriginalCell empty when in modified (as an indicator that the
// original cell will always be equal the current cell). // original cell will always be equal the current cell).
@ -34,7 +35,7 @@ void CSMWorld::RefCollection::load (ESM::ESMReader& reader, int cellIndex, bool
ref.mCell = "#" + std::to_string(index.first) + " " + std::to_string(index.second); ref.mCell = "#" + std::to_string(index.first) + " " + std::to_string(index.second);
// Handle non-base moved references // Handle non-base moved references
if (!base && mref.mRefNum.mIndex != 0) if (!base && !isMoved)
{ {
// Moved references must have a link back to their original cell // Moved references must have a link back to their original cell
// See discussion: https://forum.openmw.org/viewtopic.php?f=6&t=577&start=30 // See discussion: https://forum.openmw.org/viewtopic.php?f=6&t=577&start=30
@ -59,8 +60,6 @@ void CSMWorld::RefCollection::load (ESM::ESMReader& reader, int cellIndex, bool
else else
ref.mCell = cell2.mId; ref.mCell = cell2.mId;
mref.mRefNum.mIndex = 0;
// ignore content file number // ignore content file number
std::map<ESM::RefNum, std::string>::iterator iter = cache.begin(); std::map<ESM::RefNum, std::string>::iterator iter = cache.begin();
unsigned int thisIndex = ref.mRefNum.mIndex & 0x00ffffff; unsigned int thisIndex = ref.mRefNum.mIndex & 0x00ffffff;

View file

@ -427,13 +427,11 @@ namespace MWRender
ESM::MovedCellRef cMRef; ESM::MovedCellRef cMRef;
cMRef.mRefNum.mIndex = 0; cMRef.mRefNum.mIndex = 0;
bool deleted = false; bool deleted = false;
while(cell->getNextRef(esm[index], ref, deleted, /*ignoreMoves*/true, &cMRef)) bool moved = false;
while(cell->getNextRef(esm[index], ref, deleted, cMRef, moved))
{ {
if (cMRef.mRefNum.mIndex) if (moved)
{ continue;
cMRef.mRefNum.mIndex = 0;
continue; // ignore refs that are moved
}
if (std::find(cell->mMovedRefs.begin(), cell->mMovedRefs.end(), ref.mRefNum) != cell->mMovedRefs.end()) continue; if (std::find(cell->mMovedRefs.begin(), cell->mMovedRefs.end(), ref.mRefNum) != cell->mMovedRefs.end()) continue;
Misc::StringUtils::lowerCaseInPlace(ref.mRefID); Misc::StringUtils::lowerCaseInPlace(ref.mRefID);

View file

@ -553,17 +553,12 @@ namespace MWWorld
ESM::MovedCellRef cMRef; ESM::MovedCellRef cMRef;
cMRef.mRefNum.mIndex = 0; cMRef.mRefNum.mIndex = 0;
bool deleted = false; bool deleted = false;
while(mCell->getNextRef(esm[index], ref, deleted, /*ignoreMoves*/true, &cMRef)) bool moved = false;
while(mCell->getNextRef(esm[index], ref, deleted, cMRef, moved))
{ {
if (deleted) if (deleted || moved)
continue; continue;
if (cMRef.mRefNum.mIndex)
{
cMRef.mRefNum.mIndex = 0;
continue; // ignore refs that are moved
}
// Don't list reference if it was moved to a different cell. // Don't list reference if it was moved to a different cell.
ESM::MovedCellRefTracker::const_iterator iter = ESM::MovedCellRefTracker::const_iterator iter =
std::find(mCell->mMovedRefs.begin(), mCell->mMovedRefs.end(), ref.mRefNum); std::find(mCell->mMovedRefs.begin(), mCell->mMovedRefs.end(), ref.mRefNum);
@ -618,13 +613,11 @@ namespace MWWorld
ESM::MovedCellRef cMRef; ESM::MovedCellRef cMRef;
cMRef.mRefNum.mIndex = 0; cMRef.mRefNum.mIndex = 0;
bool deleted = false; bool deleted = false;
while(mCell->getNextRef(esm[index], ref, deleted, /*ignoreMoves*/true, &cMRef)) bool moved = false;
while(mCell->getNextRef(esm[index], ref, deleted, cMRef, moved))
{ {
if (cMRef.mRefNum.mIndex) if (moved)
{ continue;
cMRef.mRefNum.mIndex = 0;
continue; // ignore refs that are moved
}
// Don't load reference if it was moved to a different cell. // Don't load reference if it was moved to a different cell.
ESM::MovedCellRefTracker::const_iterator iter = ESM::MovedCellRefTracker::const_iterator iter =

View file

@ -502,8 +502,8 @@ namespace MWWorld
{ {
ESM::CellRef ref; ESM::CellRef ref;
ESM::MovedCellRef cMRef; ESM::MovedCellRef cMRef;
cMRef.mRefNum.mIndex = 0;
bool deleted = false; bool deleted = false;
bool moved = false;
ESM::ESM_Context ctx = esm.getContext(); ESM::ESM_Context ctx = esm.getContext();
@ -512,10 +512,10 @@ namespace MWWorld
// //
// Get regular moved reference data. Adapted from CellStore::loadRefs. Maybe we can optimize the following // Get regular moved reference data. Adapted from CellStore::loadRefs. Maybe we can optimize the following
// implementation when the oher implementation works as well. // implementation when the oher implementation works as well.
while (cell->getNextRef(esm, ref, deleted, /*ignoreMoves*/true, &cMRef)) while (cell->getNextRef(esm, ref, deleted, cMRef, moved))
{ {
if (!cMRef.mRefNum.mIndex) if (!moved)
continue; // ignore refs that are not moved continue;
ESM::Cell *cellAlt = const_cast<ESM::Cell*>(searchOrCreate(cMRef.mTarget[0], cMRef.mTarget[1])); ESM::Cell *cellAlt = const_cast<ESM::Cell*>(searchOrCreate(cMRef.mTarget[0], cMRef.mTarget[1]));

View file

@ -224,7 +224,7 @@ namespace ESM
return region + ' ' + cellGrid; return region + ' ' + cellGrid;
} }
bool Cell::getNextRef(ESMReader &esm, CellRef &ref, bool &isDeleted, bool ignoreMoves, MovedCellRef *mref) bool Cell::getNextRef(ESMReader& esm, CellRef& ref, bool& isDeleted)
{ {
isDeleted = false; isDeleted = false;
@ -232,22 +232,18 @@ namespace ESM
if (!esm.hasMoreSubs()) if (!esm.hasMoreSubs())
return false; return false;
// NOTE: We should not need this check. It is a safety check until we have checked // MVRF are FRMR are present in pairs. MVRF indicates that following FRMR describes moved CellRef.
// more plugins, and how they treat these moved references. // This function has to skip all moved CellRefs therefore read all such pairs to ignored values.
if (esm.isNextSub("MVRF")) while (esm.isNextSub("MVRF"))
{ {
if (ignoreMoves) MovedCellRef movedCellRef;
{ esm.getHT(movedCellRef.mRefNum.mIndex);
esm.getHT (mref->mRefNum.mIndex); esm.getHNOT(movedCellRef.mTarget, "CNDT");
esm.getHNOT (mref->mTarget, "CNDT"); CellRef skippedCellRef;
adjustRefNum (mref->mRefNum, esm); if (!esm.peekNextSub("FRMR"))
}
else
{
// skip rest of cell record (moved references), they are handled elsewhere
esm.skipRecord(); // skip MVRF, CNDT
return false; return false;
} bool skippedDeleted;
skippedCellRef.load(esm, skippedDeleted);
} }
if (esm.peekNextSub("FRMR")) if (esm.peekNextSub("FRMR"))
@ -263,6 +259,29 @@ namespace ESM
return false; return false;
} }
bool Cell::getNextRef(ESMReader& esm, CellRef& cellRef, bool& deleted, MovedCellRef& movedCellRef, bool& moved)
{
deleted = false;
moved = false;
if (!esm.hasMoreSubs())
return false;
if (esm.isNextSub("MVRF"))
{
moved = true;
getNextMVRF(esm, movedCellRef);
}
if (!esm.peekNextSub("FRMR"))
return false;
cellRef.load(esm, deleted);
adjustRefNum(cellRef.mRefNum, esm);
return true;
}
bool Cell::getNextMVRF(ESMReader &esm, MovedCellRef &mref) bool Cell::getNextMVRF(ESMReader &esm, MovedCellRef &mref)
{ {
esm.getHT(mref.mRefNum.mIndex); esm.getHT(mref.mRefNum.mIndex);

View file

@ -181,12 +181,9 @@ struct Cell
All fields of the CellRef struct are overwritten. You can safely All fields of the CellRef struct are overwritten. You can safely
reuse one memory location without blanking it between calls. reuse one memory location without blanking it between calls.
*/ */
/// \param ignoreMoves ignore MVRF record and read reference like a regular CellRef. static bool getNextRef(ESMReader& esm, CellRef& ref, bool& deleted);
static bool getNextRef(ESMReader &esm,
CellRef &ref, static bool getNextRef(ESMReader& esm, CellRef& cellRef, bool& deleted, MovedCellRef& movedCellRef, bool& moved);
bool &isDeleted,
bool ignoreMoves = false,
MovedCellRef *mref = nullptr);
/* This fetches an MVRF record, which is used to track moved references. /* This fetches an MVRF record, which is used to track moved references.
* Since they are comparably rare, we use a separate method for this. * Since they are comparably rare, we use a separate method for this.