mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-01-29 04:45:33 +00:00
Implement saving of deleted records
(cherry picked from commit 8e6a7be6f5
)
Conflicts:
apps/opencs/model/doc/savingstages.cpp
This commit is contained in:
parent
a120bb2b54
commit
0277a4e8c4
5 changed files with 127 additions and 123 deletions
|
@ -99,41 +99,38 @@ int CSMDoc::WriteDialogueCollectionStage::setup()
|
|||
|
||||
void CSMDoc::WriteDialogueCollectionStage::perform (int stage, Messages& messages)
|
||||
{
|
||||
ESM::ESMWriter& writer = mState.getWriter();
|
||||
const CSMWorld::Record<ESM::Dialogue>& topic = mTopics.getRecord (stage);
|
||||
|
||||
CSMWorld::RecordBase::State state = topic.mState;
|
||||
|
||||
if (state==CSMWorld::RecordBase::State_Deleted)
|
||||
if (topic.mState == CSMWorld::RecordBase::State_Deleted)
|
||||
{
|
||||
// if the topic is deleted, we do not need to bother with INFO records.
|
||||
ESM::Dialogue dialogue = topic.get();
|
||||
dialogue.mIsDeleted = true;
|
||||
|
||||
/// \todo wrote record with delete flag
|
||||
|
||||
writer.startRecord(dialogue.sRecordId);
|
||||
dialogue.save(writer);
|
||||
writer.endRecord(dialogue.sRecordId);
|
||||
return;
|
||||
}
|
||||
|
||||
// Test, if we need to save anything associated info records.
|
||||
bool infoModified = false;
|
||||
|
||||
CSMWorld::InfoCollection::Range range = mInfos.getTopicRange (topic.get().mId);
|
||||
|
||||
for (CSMWorld::InfoCollection::RecordConstIterator iter (range.first); iter!=range.second; ++iter)
|
||||
{
|
||||
CSMWorld::RecordBase::State state = iter->mState;
|
||||
|
||||
if (state==CSMWorld::RecordBase::State_Modified ||
|
||||
state==CSMWorld::RecordBase::State_ModifiedOnly ||
|
||||
state==CSMWorld::RecordBase::State_Deleted)
|
||||
if (topic.isModified() || iter->mState == CSMWorld::RecordBase::State_Deleted)
|
||||
{
|
||||
infoModified = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (state==CSMWorld::RecordBase::State_Modified ||
|
||||
state==CSMWorld::RecordBase::State_ModifiedOnly ||
|
||||
infoModified)
|
||||
if (topic.isModified() || infoModified)
|
||||
{
|
||||
ESM::Dialogue dialogue = topic.get();
|
||||
|
||||
if (infoModified && state != CSMWorld::RecordBase::State_Modified
|
||||
&& state != CSMWorld::RecordBase::State_ModifiedOnly)
|
||||
{
|
||||
|
@ -150,44 +147,40 @@ void CSMDoc::WriteDialogueCollectionStage::perform (int stage, Messages& message
|
|||
mState.getWriter().endRecord (topic.mModified.sRecordId);
|
||||
}
|
||||
|
||||
// write modified selected info records
|
||||
for (CSMWorld::InfoCollection::RecordConstIterator iter (range.first); iter!=range.second;
|
||||
++iter)
|
||||
{
|
||||
CSMWorld::RecordBase::State infoState = iter->mState;
|
||||
writer.startRecord (dialogue.sRecordId);
|
||||
dialogue.save (writer);
|
||||
writer.endRecord (dialogue.sRecordId);
|
||||
|
||||
if (infoState==CSMWorld::RecordBase::State_Deleted)
|
||||
{
|
||||
/// \todo wrote record with delete flag
|
||||
}
|
||||
else if (infoState==CSMWorld::RecordBase::State_Modified ||
|
||||
infoState==CSMWorld::RecordBase::State_ModifiedOnly)
|
||||
// write modified selected info records
|
||||
for (CSMWorld::InfoCollection::RecordConstIterator iter (range.first); iter!=range.second; ++iter)
|
||||
{
|
||||
if (iter->isModified() || iter->mState == CSMWorld::RecordBase::State_Deleted)
|
||||
{
|
||||
ESM::DialInfo info = iter->get();
|
||||
info.mId = info.mId.substr (info.mId.find_last_of ('#')+1);
|
||||
info.mIsDeleted = (iter->mState == CSMWorld::RecordBase::State_Deleted);
|
||||
|
||||
info.mPrev = "";
|
||||
if (iter!=range.first)
|
||||
{
|
||||
CSMWorld::InfoCollection::RecordConstIterator prev = iter;
|
||||
--prev;
|
||||
|
||||
info.mPrev =
|
||||
prev->mModified.mId.substr (prev->mModified.mId.find_last_of ('#')+1);
|
||||
info.mPrev = prev->get().mId.substr (prev->get().mId.find_last_of ('#')+1);
|
||||
}
|
||||
|
||||
CSMWorld::InfoCollection::RecordConstIterator next = iter;
|
||||
++next;
|
||||
|
||||
info.mNext = "";
|
||||
if (next!=range.second)
|
||||
{
|
||||
info.mNext =
|
||||
next->mModified.mId.substr (next->mModified.mId.find_last_of ('#')+1);
|
||||
info.mNext = next->get().mId.substr (next->get().mId.find_last_of ('#')+1);
|
||||
}
|
||||
|
||||
mState.getWriter().startRecord (info.sRecordId);
|
||||
mState.getWriter().writeHNCString ("INAM", info.mId);
|
||||
info.save (mState.getWriter());
|
||||
mState.getWriter().endRecord (info.sRecordId);
|
||||
writer.startRecord (info.sRecordId);
|
||||
info.save (writer);
|
||||
writer.endRecord (info.sRecordId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -279,36 +272,35 @@ int CSMDoc::WriteCellCollectionStage::setup()
|
|||
|
||||
void CSMDoc::WriteCellCollectionStage::perform (int stage, Messages& messages)
|
||||
{
|
||||
const CSMWorld::Record<CSMWorld::Cell>& cell =
|
||||
mDocument.getData().getCells().getRecord (stage);
|
||||
ESM::ESMWriter& writer = mState.getWriter();
|
||||
const CSMWorld::Record<CSMWorld::Cell>& cell = mDocument.getData().getCells().getRecord (stage);
|
||||
|
||||
std::map<std::string, std::deque<int> >::const_iterator references =
|
||||
mState.getSubRecords().find (Misc::StringUtils::lowerCase (cell.get().mId));
|
||||
|
||||
if (cell.mState==CSMWorld::RecordBase::State_Modified ||
|
||||
cell.mState==CSMWorld::RecordBase::State_ModifiedOnly ||
|
||||
if (cell.isModified() ||
|
||||
cell.mState == CSMWorld::RecordBase::State_Deleted ||
|
||||
references!=mState.getSubRecords().end())
|
||||
{
|
||||
bool interior = cell.get().mId.substr (0, 1)!="#";
|
||||
CSMWorld::Cell cellRecord = cell.get();
|
||||
bool interior = cellRecord.mId.substr (0, 1)!="#";
|
||||
|
||||
// write cell data
|
||||
mState.getWriter().startRecord (cell.mModified.sRecordId);
|
||||
|
||||
mState.getWriter().writeHNOCString ("NAME", cell.get().mName);
|
||||
|
||||
ESM::Cell cell2 = cell.get();
|
||||
writer.startRecord (cellRecord.sRecordId);
|
||||
|
||||
if (interior)
|
||||
cell2.mData.mFlags |= ESM::Cell::Interior;
|
||||
cellRecord.mData.mFlags |= ESM::Cell::Interior;
|
||||
else
|
||||
{
|
||||
cell2.mData.mFlags &= ~ESM::Cell::Interior;
|
||||
cellRecord.mData.mFlags &= ~ESM::Cell::Interior;
|
||||
|
||||
std::istringstream stream (cell.get().mId.c_str());
|
||||
std::istringstream stream (cellRecord.mId.c_str());
|
||||
char ignore;
|
||||
stream >> ignore >> cell2.mData.mX >> cell2.mData.mY;
|
||||
stream >> ignore >> cellRecord.mData.mX >> cellRecord.mData.mY;
|
||||
}
|
||||
cell2.save (mState.getWriter());
|
||||
|
||||
cellRecord.mIsDeleted = (cell.mState == CSMWorld::RecordBase::State_Deleted);
|
||||
cellRecord.save (writer);
|
||||
|
||||
// write references
|
||||
if (references!=mState.getSubRecords().end())
|
||||
|
@ -319,24 +311,25 @@ void CSMDoc::WriteCellCollectionStage::perform (int stage, Messages& messages)
|
|||
const CSMWorld::Record<CSMWorld::CellRef>& ref =
|
||||
mDocument.getData().getReferences().getRecord (*iter);
|
||||
|
||||
if (ref.mState==CSMWorld::RecordBase::State_Modified ||
|
||||
ref.mState==CSMWorld::RecordBase::State_ModifiedOnly)
|
||||
if (ref.isModified() || ref.mState == CSMWorld::RecordBase::State_Deleted)
|
||||
{
|
||||
CSMWorld::CellRef refRecord = ref.get();
|
||||
|
||||
// recalculate the ref's cell location
|
||||
std::ostringstream stream;
|
||||
if (!interior)
|
||||
{
|
||||
std::pair<int, int> index = ref.get().getCellIndex();
|
||||
std::pair<int, int> index = refRecord.getCellIndex();
|
||||
stream << "#" << index.first << " " << index.second;
|
||||
}
|
||||
|
||||
// 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)
|
||||
if ((refRecord.mOriginalCell.empty() ? refRecord.mCell : refRecord.mOriginalCell)
|
||||
!= stream.str() && !interior)
|
||||
{
|
||||
ESM::MovedCellRef moved;
|
||||
moved.mRefNum = ref.get().mRefNum;
|
||||
moved.mRefNum = refRecord.mRefNum;
|
||||
|
||||
// Need to fill mTarget with the ref's new position.
|
||||
std::istringstream istream (stream.str().c_str());
|
||||
|
@ -344,24 +337,17 @@ void CSMDoc::WriteCellCollectionStage::perform (int stage, Messages& messages)
|
|||
char ignore;
|
||||
istream >> ignore >> moved.mTarget[0] >> moved.mTarget[1];
|
||||
|
||||
ref.get().mRefNum.save (mState.getWriter(), false, "MVRF");
|
||||
mState.getWriter().writeHNT ("CNDT", moved.mTarget, 8);
|
||||
refRecord.mRefNum.save (writer, false, "MVRF");
|
||||
writer.writeHNT ("CNDT", moved.mTarget, 8);
|
||||
}
|
||||
|
||||
ref.get().save (mState.getWriter());
|
||||
}
|
||||
else if (ref.mState==CSMWorld::RecordBase::State_Deleted)
|
||||
{
|
||||
/// \todo write record with delete flag
|
||||
refRecord.mIsDeleted = (ref.mState == CSMWorld::RecordBase::State_Deleted);
|
||||
refRecord.save (writer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mState.getWriter().endRecord (cell.mModified.sRecordId);
|
||||
}
|
||||
else if (cell.mState==CSMWorld::RecordBase::State_Deleted)
|
||||
{
|
||||
/// \todo write record with delete flag
|
||||
writer.endRecord (cellRecord.sRecordId);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -378,11 +364,11 @@ int CSMDoc::WritePathgridCollectionStage::setup()
|
|||
|
||||
void CSMDoc::WritePathgridCollectionStage::perform (int stage, Messages& messages)
|
||||
{
|
||||
const CSMWorld::Record<CSMWorld::Pathgrid>& pathgrid =
|
||||
ESM::ESMWriter& writer = mState.getWriter();
|
||||
const CSMWorld::Record<CSMWorld::Pathgrid>& pathgrid =
|
||||
mDocument.getData().getPathgrids().getRecord (stage);
|
||||
|
||||
if (pathgrid.mState==CSMWorld::RecordBase::State_Modified ||
|
||||
pathgrid.mState==CSMWorld::RecordBase::State_ModifiedOnly)
|
||||
if (pathgrid.isModified() || pathgrid.mState == CSMWorld::RecordBase::State_Deleted)
|
||||
{
|
||||
CSMWorld::Pathgrid record = pathgrid.get();
|
||||
|
||||
|
@ -395,15 +381,10 @@ void CSMDoc::WritePathgridCollectionStage::perform (int stage, Messages& message
|
|||
else
|
||||
record.mCell = record.mId;
|
||||
|
||||
mState.getWriter().startRecord (record.sRecordId);
|
||||
|
||||
record.save (mState.getWriter());
|
||||
|
||||
mState.getWriter().endRecord (record.sRecordId);
|
||||
}
|
||||
else if (pathgrid.mState==CSMWorld::RecordBase::State_Deleted)
|
||||
{
|
||||
/// \todo write record with delete flag
|
||||
record.mIsDeleted = (pathgrid.mState == CSMWorld::RecordBase::State_Deleted);
|
||||
writer.startRecord (record.sRecordId);
|
||||
record.save (writer);
|
||||
writer.endRecord (record.sRecordId);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -420,26 +401,18 @@ int CSMDoc::WriteLandCollectionStage::setup()
|
|||
|
||||
void CSMDoc::WriteLandCollectionStage::perform (int stage, Messages& messages)
|
||||
{
|
||||
const CSMWorld::Record<CSMWorld::Land>& land =
|
||||
ESM::ESMWriter& writer = mState.getWriter();
|
||||
const CSMWorld::Record<CSMWorld::Land>& land =
|
||||
mDocument.getData().getLand().getRecord (stage);
|
||||
|
||||
if (land.mState==CSMWorld::RecordBase::State_Modified ||
|
||||
land.mState==CSMWorld::RecordBase::State_ModifiedOnly)
|
||||
if (land.isModified() || land.mState == CSMWorld::RecordBase::State_Deleted)
|
||||
{
|
||||
const CSMWorld::Land& record = land.get();
|
||||
|
||||
mState.getWriter().startRecord (record.sRecordId);
|
||||
|
||||
record.save (mState.getWriter());
|
||||
|
||||
if (const ESM::Land::LandData *data = record.getLandData (record.mDataTypes))
|
||||
data->save (mState.getWriter());
|
||||
|
||||
mState.getWriter().endRecord (record.sRecordId);
|
||||
}
|
||||
else if (land.mState==CSMWorld::RecordBase::State_Deleted)
|
||||
{
|
||||
/// \todo write record with delete flag
|
||||
record.mLand->mIsDeleted = (land.mState == CSMWorld::RecordBase::State_Deleted);
|
||||
writer.startRecord (record.mLand->sRecordId);
|
||||
record.mLand->save (writer);
|
||||
writer.endRecord (record.mLand->sRecordId);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -456,25 +429,18 @@ int CSMDoc::WriteLandTextureCollectionStage::setup()
|
|||
|
||||
void CSMDoc::WriteLandTextureCollectionStage::perform (int stage, Messages& messages)
|
||||
{
|
||||
const CSMWorld::Record<CSMWorld::LandTexture>& landTexture =
|
||||
ESM::ESMWriter& writer = mState.getWriter();
|
||||
const CSMWorld::Record<CSMWorld::LandTexture>& landTexture =
|
||||
mDocument.getData().getLandTextures().getRecord (stage);
|
||||
|
||||
if (landTexture.mState==CSMWorld::RecordBase::State_Modified ||
|
||||
landTexture.mState==CSMWorld::RecordBase::State_ModifiedOnly)
|
||||
if (landTexture.isModified() || landTexture.mState == CSMWorld::RecordBase::State_Deleted)
|
||||
{
|
||||
CSMWorld::LandTexture record = landTexture.get();
|
||||
record.mIsDeleted = (landTexture.mState == CSMWorld::RecordBase::State_Deleted);
|
||||
|
||||
mState.getWriter().startRecord (record.sRecordId);
|
||||
|
||||
mState.getWriter().writeHNString("NAME", record.mId);
|
||||
|
||||
record.save (mState.getWriter());
|
||||
|
||||
mState.getWriter().endRecord (record.sRecordId);
|
||||
}
|
||||
else if (landTexture.mState==CSMWorld::RecordBase::State_Deleted)
|
||||
{
|
||||
/// \todo write record with delete flag
|
||||
writer.startRecord (record.sRecordId);
|
||||
record.save (writer);
|
||||
writer.endRecord (record.sRecordId);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -100,26 +100,18 @@ namespace CSMDoc
|
|||
if (CSMWorld::getScopeFromId (mCollection.getRecord (stage).get().mId)!=mScope)
|
||||
return;
|
||||
|
||||
ESM::ESMWriter& writer = mState.getWriter();
|
||||
CSMWorld::RecordBase::State state = mCollection.getRecord (stage).mState;
|
||||
CollectionT::ESXRecord record = mCollection.getRecord (stage).get();
|
||||
|
||||
if (state==CSMWorld::RecordBase::State_Modified ||
|
||||
state==CSMWorld::RecordBase::State_ModifiedOnly)
|
||||
if (state == CSMWorld::RecordBase::State_Modified ||
|
||||
state == CSMWorld::RecordBase::State_ModifiedOnly ||
|
||||
state == CSMWorld::RecordBase::State_Deleted)
|
||||
{
|
||||
// FIXME: A quick Workaround to support records which should not write
|
||||
// NAME, including SKIL, MGEF and SCPT. If there are many more
|
||||
// idcollection records that doesn't use NAME then a more generic
|
||||
// solution may be required.
|
||||
uint32_t name = mCollection.getRecord (stage).mModified.sRecordId;
|
||||
mState.getWriter().startRecord (name);
|
||||
|
||||
if(name != ESM::REC_SKIL && name != ESM::REC_MGEF && name != ESM::REC_SCPT)
|
||||
mState.getWriter().writeHNCString ("NAME", mCollection.getId (stage));
|
||||
mCollection.getRecord (stage).mModified.save (mState.getWriter());
|
||||
mState.getWriter().endRecord (mCollection.getRecord (stage).mModified.sRecordId);
|
||||
}
|
||||
else if (state==CSMWorld::RecordBase::State_Deleted)
|
||||
{
|
||||
/// \todo write record with delete flag
|
||||
CSMWorld::setRecordDeleted (record, state == CSMWorld::RecordBase::State_Deleted);
|
||||
writer.startRecord (record.sRecordId);
|
||||
record.save (writer);
|
||||
writer.endRecord (record.sRecordId);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -43,6 +43,12 @@ namespace CSMWorld
|
|||
template<typename ESXRecordT, typename IdAccessorT = IdAccessor<ESXRecordT> >
|
||||
class Collection : public CollectionBase
|
||||
{
|
||||
public:
|
||||
|
||||
typedef ESXRecordT ESXRecord;
|
||||
|
||||
private:
|
||||
|
||||
std::vector<Record<ESXRecordT> > mRecords;
|
||||
std::map<std::string, int> mIndex;
|
||||
std::vector<Column<ESXRecordT> *> mColumns;
|
||||
|
|
|
@ -42,3 +42,27 @@ bool CSMWorld::isRecordDeleted(const ESM::Skill &skill)
|
|||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
template<>
|
||||
void CSMWorld::setRecordDeleted(CSMWorld::Land &land, bool isDeleted)
|
||||
{
|
||||
land.mLand->mIsDeleted = isDeleted;
|
||||
}
|
||||
|
||||
template<>
|
||||
void CSMWorld::setRecordDeleted(ESM::GameSetting &setting, bool isDeleted)
|
||||
{
|
||||
// GameSetting doesn't have a Deleted flag
|
||||
}
|
||||
|
||||
template<>
|
||||
void CSMWorld::setRecordDeleted(ESM::MagicEffect &effect, bool isDeleted)
|
||||
{
|
||||
// MagicEffect doesn't have a Deleted flag
|
||||
}
|
||||
|
||||
template<>
|
||||
void CSMWorld::setRecordDeleted(ESM::Skill &skill, bool isDeleted)
|
||||
{
|
||||
// Skill doesn't have a Deleted flag
|
||||
}
|
||||
|
|
|
@ -177,6 +177,22 @@ namespace CSMWorld
|
|||
bool isRecordDeleted(const ESM::MagicEffect &effect);
|
||||
template<>
|
||||
bool isRecordDeleted(const ESM::Skill &skill);
|
||||
|
||||
// ... and also a separate method for setting the deleted flag of a record
|
||||
template<typename ESXRecordT>
|
||||
void setRecordDeleted(ESXRecordT &record, bool isDeleted = false)
|
||||
{
|
||||
record.mIsDeleted = isDeleted;
|
||||
}
|
||||
|
||||
template<>
|
||||
void setRecordDeleted(Land &land, bool isDeleted);
|
||||
template<>
|
||||
void setRecordDeleted(ESM::GameSetting &setting, bool isDeleted);
|
||||
template<>
|
||||
void setRecordDeleted(ESM::MagicEffect &effect, bool isDeleted);
|
||||
template<>
|
||||
void setRecordDeleted(ESM::Skill &skill, bool isDeleted);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in a new issue