mirror of
https://github.com/OpenMW/openmw.git
synced 2025-03-28 23:06:41 +00:00
Merge branch 'dialoguestuff' into 'master'
Improve TESCS dialogue compatibility Closes #8181 See merge request OpenMW/openmw!4396
This commit is contained in:
commit
3e3ff00c72
6 changed files with 86 additions and 14 deletions
|
@ -78,6 +78,7 @@ file(GLOB UNITTEST_SRC_FILES
|
||||||
esm3/testsaveload.cpp
|
esm3/testsaveload.cpp
|
||||||
esm3/testesmwriter.cpp
|
esm3/testesmwriter.cpp
|
||||||
esm3/testinfoorder.cpp
|
esm3/testinfoorder.cpp
|
||||||
|
esm3/testcstringids.cpp
|
||||||
|
|
||||||
nifosg/testnifloader.cpp
|
nifosg/testnifloader.cpp
|
||||||
|
|
||||||
|
|
57
apps/components_tests/esm3/testcstringids.cpp
Normal file
57
apps/components_tests/esm3/testcstringids.cpp
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
#include <components/esm3/esmreader.hpp>
|
||||||
|
#include <components/esm3/esmwriter.hpp>
|
||||||
|
#include <components/esm3/loaddial.hpp>
|
||||||
|
|
||||||
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
|
namespace ESM
|
||||||
|
{
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
TEST(Esm3CStringIdTest, dialNameShouldBeNullTerminated)
|
||||||
|
{
|
||||||
|
std::unique_ptr<std::istream> stream;
|
||||||
|
|
||||||
|
{
|
||||||
|
auto ostream = std::make_unique<std::stringstream>();
|
||||||
|
|
||||||
|
ESMWriter writer;
|
||||||
|
writer.setFormatVersion(DefaultFormatVersion);
|
||||||
|
writer.save(*ostream);
|
||||||
|
|
||||||
|
Dialogue record;
|
||||||
|
record.blank();
|
||||||
|
record.mStringId = "topic name";
|
||||||
|
record.mId = RefId::stringRefId(record.mStringId);
|
||||||
|
record.mType = Dialogue::Topic;
|
||||||
|
writer.startRecord(Dialogue::sRecordId);
|
||||||
|
record.save(writer);
|
||||||
|
writer.endRecord(Dialogue::sRecordId);
|
||||||
|
|
||||||
|
stream = std::move(ostream);
|
||||||
|
}
|
||||||
|
|
||||||
|
ESMReader reader;
|
||||||
|
reader.open(std::move(stream), "stream");
|
||||||
|
ASSERT_TRUE(reader.hasMoreRecs());
|
||||||
|
ASSERT_EQ(reader.getRecName(), Dialogue::sRecordId);
|
||||||
|
reader.getRecHeader();
|
||||||
|
while (reader.hasMoreSubs())
|
||||||
|
{
|
||||||
|
reader.getSubName();
|
||||||
|
if (reader.retSubName().toInt() == SREC_NAME)
|
||||||
|
{
|
||||||
|
reader.getSubHeader();
|
||||||
|
auto size = reader.getSubSize();
|
||||||
|
std::string buffer(size, '1');
|
||||||
|
reader.getExact(buffer.data(), size);
|
||||||
|
ASSERT_EQ(buffer[size - 1], '\0');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
reader.skipHSub();
|
||||||
|
}
|
||||||
|
ASSERT_FALSE(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -57,7 +57,7 @@ namespace ESM
|
||||||
|
|
||||||
// If this test failed probably there is a change in RefId format and CurrentSaveGameFormatVersion should be
|
// If this test failed probably there is a change in RefId format and CurrentSaveGameFormatVersion should be
|
||||||
// incremented, current version should be handled.
|
// incremented, current version should be handled.
|
||||||
TEST_P(Esm3EsmWriterRefIdSizeTest, writeHRefIdShouldProduceCertainNubmerOfBytes)
|
TEST_P(Esm3EsmWriterRefIdSizeTest, writeHRefIdShouldProduceCertainNumberOfBytes)
|
||||||
{
|
{
|
||||||
const auto [refId, size] = GetParam();
|
const auto [refId, size] = GetParam();
|
||||||
|
|
||||||
|
|
|
@ -1430,7 +1430,8 @@ int CSMWorld::Data::count(RecordBase::State state) const
|
||||||
+ count(state, mRegions) + count(state, mBirthsigns) + count(state, mSpells) + count(state, mCells)
|
+ count(state, mRegions) + count(state, mBirthsigns) + count(state, mSpells) + count(state, mCells)
|
||||||
+ count(state, mEnchantments) + count(state, mBodyParts) + count(state, mLand) + count(state, mLandTextures)
|
+ count(state, mEnchantments) + count(state, mBodyParts) + count(state, mLand) + count(state, mLandTextures)
|
||||||
+ count(state, mSoundGens) + count(state, mMagicEffects) + count(state, mReferenceables)
|
+ count(state, mSoundGens) + count(state, mMagicEffects) + count(state, mReferenceables)
|
||||||
+ count(state, mPathgrids);
|
+ count(state, mPathgrids) + count(state, mTopics) + count(state, mTopicInfos) + count(state, mJournals)
|
||||||
|
+ count(state, mJournalInfos);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<ESM::RefId> CSMWorld::Data::getIds(bool listDeleted) const
|
std::vector<ESM::RefId> CSMWorld::Data::getIds(bool listDeleted) const
|
||||||
|
|
|
@ -1,11 +1,12 @@
|
||||||
#include "infocreator.hpp"
|
#include "infocreator.hpp"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <charconv>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
#include <QLabel>
|
#include <QLabel>
|
||||||
|
#include <QRandomGenerator>
|
||||||
#include <QString>
|
#include <QString>
|
||||||
#include <QUuid>
|
|
||||||
|
|
||||||
#include <apps/opencs/model/world/columnbase.hpp>
|
#include <apps/opencs/model/world/columnbase.hpp>
|
||||||
#include <apps/opencs/model/world/idcollection.hpp>
|
#include <apps/opencs/model/world/idcollection.hpp>
|
||||||
|
@ -27,15 +28,27 @@ class QUndoStack;
|
||||||
|
|
||||||
std::string CSVWorld::InfoCreator::getId() const
|
std::string CSVWorld::InfoCreator::getId() const
|
||||||
{
|
{
|
||||||
const std::string topic = mTopic->text().toStdString();
|
std::string id = mTopic->text().toStdString();
|
||||||
|
size_t length = id.size();
|
||||||
std::string unique = QUuid::createUuid().toByteArray().data();
|
// We want generated ids to be at most 31 + \0 characters
|
||||||
|
id.resize(length + 32);
|
||||||
unique.erase(std::remove(unique.begin(), unique.end(), '-'), unique.end());
|
id[length] = '#';
|
||||||
|
// Combine a random 32bit number with a random 64bit number for a max 30 character string
|
||||||
unique = unique.substr(1, unique.size() - 2);
|
quint32 gen32 = QRandomGenerator::global()->generate();
|
||||||
|
char* start = id.data() + length + 1;
|
||||||
return topic + '#' + unique;
|
char* end = start + 10; // 2^32 is a 10 digit number
|
||||||
|
auto result = std::to_chars(start, end, gen32);
|
||||||
|
quint64 gen64 = QRandomGenerator::global()->generate64();
|
||||||
|
if (gen64)
|
||||||
|
{
|
||||||
|
// 0-pad the first number so 10 + 11 isn't the same as 101 + 1
|
||||||
|
std::fill(result.ptr, end, '0');
|
||||||
|
start = end;
|
||||||
|
end = start + 20; // 2^64 is a 20 digit number
|
||||||
|
result = std::to_chars(start, end, gen64);
|
||||||
|
}
|
||||||
|
id.resize(result.ptr - id.data());
|
||||||
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSVWorld::InfoCreator::configureCreateCommand(CSMWorld::CreateCommand& command) const
|
void CSVWorld::InfoCreator::configureCreateCommand(CSMWorld::CreateCommand& command) const
|
||||||
|
|
|
@ -82,10 +82,10 @@ namespace ESM
|
||||||
if (mId != mStringId)
|
if (mId != mStringId)
|
||||||
throw std::runtime_error("Trying to save Dialogue record with name \"" + mStringId
|
throw std::runtime_error("Trying to save Dialogue record with name \"" + mStringId
|
||||||
+ "\" not maching id " + mId.toDebugString());
|
+ "\" not maching id " + mId.toDebugString());
|
||||||
esm.writeHNString("NAME", mStringId);
|
esm.writeHNCString("NAME", mStringId);
|
||||||
}
|
}
|
||||||
else if (esm.getFormatVersion() <= MaxNameIsRefIdOnlyFormatVersion)
|
else if (esm.getFormatVersion() <= MaxNameIsRefIdOnlyFormatVersion)
|
||||||
esm.writeHNRefId("NAME", mId);
|
esm.writeHNCRefId("NAME", mId);
|
||||||
else
|
else
|
||||||
esm.writeHNRefId("ID__", mId);
|
esm.writeHNRefId("ID__", mId);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue