1
0
Fork 0
mirror of https://github.com/OpenMW/openmw.git synced 2025-10-17 18:16:39 +00:00

Merge branch 'dont-take-away-my-individuality' into 'master'

FIX: Track the highest local refNum during plugin loading and increment it for each cloned/created reference

Closes #8620

See merge request OpenMW/openmw!4781
This commit is contained in:
Alexei Kotov 2025-08-06 09:53:06 +03:00
commit 5ad9010e07
6 changed files with 22 additions and 31 deletions

View file

@ -291,8 +291,7 @@ int CSMDoc::WriteCellCollectionStage::setup()
return mDocument.getData().getCells().getSize();
}
void CSMDoc::WriteCellCollectionStage::writeReferences(
const std::deque<int>& references, bool interior, unsigned int& newRefNum)
void CSMDoc::WriteCellCollectionStage::writeReferences(const std::deque<int>& references, bool interior)
{
ESM::ESMWriter& writer = mState.getWriter();
@ -304,6 +303,8 @@ void CSMDoc::WriteCellCollectionStage::writeReferences(
{
CSMWorld::CellRef refRecord = ref.get();
const bool isLocal = refRecord.mRefNum.mContentFile == -1;
// -1 is the current file, saved indices are 1-based
refRecord.mRefNum.mContentFile++;
@ -316,12 +317,7 @@ void CSMDoc::WriteCellCollectionStage::writeReferences(
}
ESM::RefId streamId = ESM::RefId::stringRefId(stream.str());
if (refRecord.mNew || refRecord.mRefNum.mIndex == 0
|| (!interior && ref.mState == CSMWorld::RecordBase::State_ModifiedOnly && refRecord.mCell != streamId))
{
refRecord.mRefNum.mIndex = newRefNum++;
}
else if ((refRecord.mOriginalCell.empty() ? refRecord.mCell : refRecord.mOriginalCell) != streamId
if (!isLocal && (refRecord.mOriginalCell.empty() ? refRecord.mCell : refRecord.mOriginalCell) != streamId
&& !interior)
{
// An empty mOriginalCell is meant to indicate that it is the same as
@ -362,9 +358,6 @@ void CSMDoc::WriteCellCollectionStage::perform(int stage, Messages& messages)
CSMWorld::Cell cellRecord = cell.get();
const bool interior = !cellRecord.mId.startsWith("#");
// count new references and adjust RefNumCount accordingsly
unsigned int newRefNum = cellRecord.mRefNumCounter;
if (references != nullptr)
{
for (std::deque<int>::const_iterator iter(references->begin()); iter != references->end(); ++iter)
@ -390,9 +383,6 @@ void CSMDoc::WriteCellCollectionStage::perform(int stage, Messages& messages)
ESM::RefId::stringRefId(CSMWorld::CellCoordinates(refRecord.getCellIndex()).getId(""))
!= refRecord.mCell))
++cellRecord.mRefNumCounter;
if (refRecord.mRefNum.mIndex >= newRefNum)
newRefNum = refRecord.mRefNum.mIndex + 1;
}
}
@ -415,9 +405,9 @@ void CSMDoc::WriteCellCollectionStage::perform(int stage, Messages& messages)
// write references
if (references != nullptr)
{
writeReferences(persistentRefs, interior, newRefNum);
writeReferences(persistentRefs, interior);
cellRecord.saveTempMarker(writer, static_cast<int>(references->size()) - persistentRefs.size());
writeReferences(tempRefs, interior, newRefNum);
writeReferences(tempRefs, interior);
}
writer.endRecord(cellRecord.sRecordId);

View file

@ -167,7 +167,7 @@ namespace CSMDoc
Document& mDocument;
SavingState& mState;
void writeReferences(const std::deque<int>& references, bool interior, unsigned int& newRefNum);
void writeReferences(const std::deque<int>& references, bool interior);
public:
WriteCellCollectionStage(Document& document, SavingState& state);

View file

@ -273,15 +273,6 @@ namespace CSMWorld
copy->mState = RecordBase::State_ModifiedOnly;
setRecordId(destination, copy->get());
if constexpr (std::is_same_v<ESXRecordT, CSMWorld::CellRef>)
{
if (type == UniversalId::Type_Reference)
{
CSMWorld::CellRef* ptr = (CSMWorld::CellRef*)&copy->mModified;
ptr->mRefNum.mIndex = 0;
}
}
if constexpr (std::is_same_v<ESXRecordT, ESM::Dialogue>)
{
copy->mModified.mStringId = copy->mModified.mId.getRefIdString();

View file

@ -175,6 +175,9 @@ void CSMWorld::RefCollection::load(ESM::ESMReader& reader, int cellIndex, bool b
ref.mIdNum = mNextId; // FIXME: fragile
ref.mId = ESM::RefId::stringRefId(getNewId());
if (!base && ref.mRefNum.mIndex > mHighestUsedRefNum)
mHighestUsedRefNum = ref.mRefNum.mIndex;
cache.emplace(ref.mRefNum, ref.mIdNum);
auto record = std::make_unique<Record<CellRef>>();
@ -222,6 +225,11 @@ std::string CSMWorld::RefCollection::getNewId()
return "ref#" + std::to_string(mNextId++);
}
uint32_t CSMWorld::RefCollection::getNextRefNum()
{
return ++mHighestUsedRefNum;
}
unsigned int CSMWorld::RefCollection::extractIdNum(std::string_view id) const
{
std::string::size_type separator = id.find_last_of('#');
@ -283,6 +291,7 @@ void CSMWorld::RefCollection::appendBlankRecord(const ESM::RefId& id, UniversalI
record->get().mId = id;
record->get().mIdNum = extractIdNum(id.getRefIdString());
record->get().mRefNum.mIndex = getNextRefNum();
Collection<CellRef>::appendRecord(std::move(record));
}
@ -298,15 +307,13 @@ void CSMWorld::RefCollection::cloneRecord(
copy->get().mId = destination;
copy->get().mIdNum = extractIdNum(destination.getRefIdString());
copy->get().mRefNum.mIndex = getNextRefNum();
if (copy->get().mRefNum.hasContentFile())
{
mRefIndex.insert(std::make_pair(static_cast<Record<CellRef>*>(copy.get())->get().mIdNum, index));
copy->get().mRefNum.mContentFile = -1;
copy->get().mRefNum.mIndex = index;
}
else
copy->get().mRefNum.mIndex = copy->get().mIdNum;
insertRecord(std::move(copy), getAppendIndex(destination, type)); // call RefCollection::insertRecord()
}

View file

@ -1,6 +1,7 @@
#ifndef CSM_WOLRD_REFCOLLECTION_H
#define CSM_WOLRD_REFCOLLECTION_H
#include <cstdint>
#include <map>
#include <memory>
#include <string>
@ -40,9 +41,12 @@ namespace CSMWorld
std::map<unsigned int, int> mRefIndex; // CellRef index keyed by CSMWorld::CellRef::mIdNum
int mNextId;
uint32_t mHighestUsedRefNum = 0;
unsigned int extractIdNum(std::string_view id) const;
uint32_t getNextRefNum();
int getIntIndex(unsigned int id) const;
int searchId(unsigned int id) const;

View file

@ -1277,9 +1277,8 @@ void CSVRender::InstanceMode::cloneSelectedInstances()
if (CSVRender::ObjectTag* objectTag = dynamic_cast<CSVRender::ObjectTag*>(tag.get()))
{
macro.push(new CSMWorld::CloneCommand(referencesTable, objectTag->mObject->getReferenceId(),
"ref#" + std::to_string(referencesTable.rowCount()), CSMWorld::UniversalId::Type_Reference));
document.getData().getReferences().getNewId(), CSMWorld::UniversalId::Type_Reference));
}
// getWorldspaceWidget().clearSelection(Mask_Reference);
}
void CSVRender::InstanceMode::dropInstance(CSVRender::Object* object, float dropHeight)