Support index RefId as pair of record type and std::uint32_t

depth-refraction
elsid 2 years ago
parent 86293af084
commit e6cf516e12
No known key found for this signature in database
GPG Key ID: 4DE04C198CBA7625

@ -134,7 +134,7 @@ void CSMDoc::Document::addOptionalMagicEffects()
{
ESM::MagicEffect effect;
effect.mIndex = i;
effect.mId = ESM::RefId::stringRefId(ESM::MagicEffect::indexToId(i));
effect.mId = ESM::MagicEffect::indexToRefId(i);
effect.blank();
addOptionalMagicEffect(effect);
@ -207,7 +207,7 @@ void CSMDoc::Document::createBase()
{
ESM::Skill record;
record.mIndex = i;
record.mId = ESM::RefId::stringRefId(ESM::Skill::indexToId(record.mIndex));
record.mId = ESM::Skill::indexToRefId(record.mIndex);
record.blank();
getData().getSkills().add(record);
@ -288,7 +288,7 @@ void CSMDoc::Document::createBase()
ESM::MagicEffect record;
record.mIndex = i;
record.mId = ESM::RefId::stringRefId(ESM::MagicEffect::indexToId(i));
record.mId = ESM::MagicEffect::indexToRefId(i);
record.blank();

@ -71,7 +71,7 @@ void CSMTools::ClassCheckStage::perform(int stage, CSMDoc::Messages& messages)
for (auto& skill : skills)
if (skill.second > 1)
{
messages.add(id, "Skill " + ESM::Skill::indexToId(skill.first) + " is listed more than once", "",
CSMDoc::Message::Severity_Error);
messages.add(id, "Skill " + ESM::Skill::indexToRefId(skill.first).toString() + " is listed more than once",
"", CSMDoc::Message::Severity_Error);
}
}

@ -61,8 +61,8 @@ void CSMTools::FactionCheckStage::perform(int stage, CSMDoc::Messages& messages)
for (auto& skill : skills)
if (skill.second > 1)
{
messages.add(id, "Skill " + ESM::Skill::indexToId(skill.first) + " is listed more than once", "",
CSMDoc::Message::Severity_Error);
messages.add(id, "Skill " + ESM::Skill::indexToRefId(skill.first).toString() + " is listed more than once",
"", CSMDoc::Message::Severity_Error);
}
/// \todo check data members that can't be edited in the table view

@ -404,7 +404,7 @@ namespace CSMWorld
{
int skill = record.get().mData.getSkill(mIndex, mMajor);
return QString::fromUtf8(ESM::Skill::indexToId(skill).c_str());
return QString::fromStdString(ESM::Skill::indexToRefId(skill).toString());
}
void set(Record<ESXRecordT>& record, const QVariant& data) override

@ -213,6 +213,7 @@ namespace ESM
{ RefId::stringRefId(std::string({ 'a', 0, -1, '\n', '\t' })), { 'a', 0, -1, '\n', '\t' } },
{ RefId::formIdRefId(42), "42" },
{ RefId::generated(42), "42" },
{ RefId::index(ESM::REC_ARMO, 42), "ARMO, 42" },
};
INSTANTIATE_TEST_SUITE_P(ESMRefIdToString, ESMRefIdToStringTest, ValuesIn(toStringParams));
@ -243,6 +244,7 @@ namespace ESM
{ RefId::stringRefId(std::string({ 'a', 0, -1, '\n', '\t' })), "String{a\\x0\\xFF\\xA\\x9}" },
{ RefId::formIdRefId(42), "FormId{42}" },
{ RefId::generated(42), "Generated{42}" },
{ RefId::index(ESM::REC_ARMO, 42), "Index{ARMO, 42}" },
};
INSTANTIATE_TEST_SUITE_P(ESMRefIdToDebugString, ESMRefIdToDebugStringTest, ValuesIn(toDebugStringParams));

@ -450,7 +450,7 @@ namespace
const int index = 3;
decltype(RecordType::mId) refId;
if constexpr (hasIndex<RecordType> && !std::is_same_v<RecordType, ESM::LandTexture>)
refId = ESM::RefId::stringRefId(RecordType::indexToId(index));
refId = RecordType::indexToRefId(index);
else
refId = ESM::StringRefId("foobar");

@ -89,7 +89,8 @@ add_component_dir(esm attr common defs esmcommon records util luascripts format
formidrefid
stringrefid
generatedrefid
)
indexrefid
)
add_component_dir(fx pass technique lexer widgets stateupdater)

@ -0,0 +1,26 @@
#include "indexrefid.hpp"
#include <ostream>
#include <sstream>
#include "esmcommon.hpp"
namespace ESM
{
std::string IndexRefId::toString() const
{
return ESM::NAME(mRecordType).toString() + ", " + std::to_string(mValue);
}
std::string IndexRefId::toDebugString() const
{
std::ostringstream stream;
stream << *this;
return stream.str();
}
std::ostream& operator<<(std::ostream& stream, IndexRefId value)
{
return stream << "Index{" << ESM::NAME(value.mRecordType).toStringView() << ", " << value.mValue << '}';
}
}

@ -0,0 +1,61 @@
#ifndef OPENMW_COMPONENTS_ESM_INDEXREFID_HPP
#define OPENMW_COMPONENTS_ESM_INDEXREFID_HPP
#include <functional>
#include <iosfwd>
#include "defs.hpp"
namespace ESM
{
class IndexRefId
{
public:
constexpr explicit IndexRefId(RecNameInts recordType, std::uint32_t value) noexcept
: mRecordType(recordType)
, mValue(value)
{
}
constexpr RecNameInts getRecordType() const { return mRecordType; }
constexpr std::uint32_t getValue() const { return mValue; }
std::string toString() const;
std::string toDebugString() const;
friend inline constexpr auto tie(const IndexRefId& value) noexcept
{
return std::tie(value.mRecordType, value.mValue);
}
constexpr bool operator==(IndexRefId rhs) const noexcept { return tie(*this) == tie(rhs); }
constexpr bool operator<(IndexRefId rhs) const noexcept { return tie(*this) < tie(rhs); }
friend std::ostream& operator<<(std::ostream& stream, IndexRefId value);
friend struct std::hash<IndexRefId>;
private:
RecNameInts mRecordType;
std::uint32_t mValue;
};
static_assert(sizeof(IndexRefId) <= sizeof(std::uint64_t));
}
namespace std
{
template <>
struct hash<ESM::IndexRefId>
{
std::size_t operator()(ESM::IndexRefId value) const noexcept
{
return std::hash<std::uint64_t>{}(static_cast<std::uint64_t>(value.mRecordType) | value.mValue);
}
};
}
#endif

@ -12,6 +12,7 @@
#include "formidrefid.hpp"
#include "generatedrefid.hpp"
#include "indexrefid.hpp"
#include "stringrefid.hpp"
namespace ESM
@ -36,6 +37,7 @@ namespace ESM
UnsizedString = 2,
FormId = 3,
Generated = 4,
Index = 5,
};
// RefId is used to represent an Id that identifies an ESM record. These Ids can then be used in
@ -56,6 +58,10 @@ namespace ESM
// global counter.
static RefId generated(std::uint64_t value) { return RefId(GeneratedRefId{ value }); }
// Constructs RefId from record type and 32bit index storing the value in-place. Should be used for records
// identified by index (i.e. ESM3 SKIL).
static RefId index(RecNameInts recordType, std::uint32_t value) { return RefId(IndexRefId(recordType, value)); }
constexpr RefId() = default;
constexpr RefId(EmptyRefId value) noexcept
@ -78,6 +84,11 @@ namespace ESM
{
}
constexpr RefId(IndexRefId value) noexcept
: mValue(value)
{
}
// Returns a reference to the value of StringRefId if it's the underlying value or throws an exception.
const std::string& getRefIdString() const;
@ -120,7 +131,7 @@ namespace ESM
friend struct std::hash<ESM::RefId>;
private:
std::variant<EmptyRefId, StringRefId, FormIdRefId, GeneratedRefId> mValue{ EmptyRefId{} };
std::variant<EmptyRefId, StringRefId, FormIdRefId, GeneratedRefId, IndexRefId> mValue{ EmptyRefId{} };
};
}

@ -463,6 +463,14 @@ namespace ESM
getExact(&generated, sizeof(std::uint64_t));
return RefId::generated(generated);
}
case RefIdType::Index:
{
RecNameInts recordType{};
getExact(&recordType, sizeof(std::uint32_t));
std::uint32_t index{};
getExact(&index, sizeof(std::uint32_t));
return RefId::index(recordType, index);
}
}
fail("Unsupported RefIdType: " + std::to_string(static_cast<unsigned>(refIdType)));

@ -53,6 +53,13 @@ namespace ESM
mWriter.writeT(RefIdType::Generated);
mWriter.writeT(v.getValue());
}
void operator()(IndexRefId v) const
{
mWriter.writeT(RefIdType::Generated);
mWriter.writeT(v.getRecordType());
mWriter.writeT(v.getValue());
}
};
}

@ -1,7 +1,5 @@
#include "loadmgef.hpp"
#include <sstream>
#include "esmreader.hpp"
#include "esmwriter.hpp"
@ -11,156 +9,6 @@ namespace ESM
{
namespace
{
static const char* sIds[MagicEffect::Length] = {
"WaterBreathing",
"SwiftSwim",
"WaterWalking",
"Shield",
"FireShield",
"LightningShield",
"FrostShield",
"Burden",
"Feather",
"Jump",
"Levitate",
"SlowFall",
"Lock",
"Open",
"FireDamage",
"ShockDamage",
"FrostDamage",
"DrainAttribute",
"DrainHealth",
"DrainMagicka",
"DrainFatigue",
"DrainSkill",
"DamageAttribute",
"DamageHealth",
"DamageMagicka",
"DamageFatigue",
"DamageSkill",
"Poison",
"WeaknessToFire",
"WeaknessToFrost",
"WeaknessToShock",
"WeaknessToMagicka",
"WeaknessToCommonDisease",
"WeaknessToBlightDisease",
"WeaknessToCorprusDisease",
"WeaknessToPoison",
"WeaknessToNormalWeapons",
"DisintegrateWeapon",
"DisintegrateArmor",
"Invisibility",
"Chameleon",
"Light",
"Sanctuary",
"NightEye",
"Charm",
"Paralyze",
"Silence",
"Blind",
"Sound",
"CalmHumanoid",
"CalmCreature",
"FrenzyHumanoid",
"FrenzyCreature",
"DemoralizeHumanoid",
"DemoralizeCreature",
"RallyHumanoid",
"RallyCreature",
"Dispel",
"Soultrap",
"Telekinesis",
"Mark",
"Recall",
"DivineIntervention",
"AlmsiviIntervention",
"DetectAnimal",
"DetectEnchantment",
"DetectKey",
"SpellAbsorption",
"Reflect",
"CureCommonDisease",
"CureBlightDisease",
"CureCorprusDisease",
"CurePoison",
"CureParalyzation",
"RestoreAttribute",
"RestoreHealth",
"RestoreMagicka",
"RestoreFatigue",
"RestoreSkill",
"FortifyAttribute",
"FortifyHealth",
"FortifyMagicka",
"FortifyFatigue",
"FortifySkill",
"FortifyMaximumMagicka",
"AbsorbAttribute",
"AbsorbHealth",
"AbsorbMagicka",
"AbsorbFatigue",
"AbsorbSkill",
"ResistFire",
"ResistFrost",
"ResistShock",
"ResistMagicka",
"ResistCommonDisease",
"ResistBlightDisease",
"ResistCorprusDisease",
"ResistPoison",
"ResistNormalWeapons",
"ResistParalysis",
"RemoveCurse",
"TurnUndead",
"SummonScamp",
"SummonClannfear",
"SummonDaedroth",
"SummonDremora",
"SummonAncestralGhost",
"SummonSkeletalMinion",
"SummonBonewalker",
"SummonGreaterBonewalker",
"SummonBonelord",
"SummonWingedTwilight",
"SummonHunger",
"SummonGoldenSaint",
"SummonFlameAtronach",
"SummonFrostAtronach",
"SummonStormAtronach",
"FortifyAttack",
"CommandCreature",
"CommandHumanoid",
"BoundDagger",
"BoundLongsword",
"BoundMace",
"BoundBattleAxe",
"BoundSpear",
"BoundLongbow",
"ExtraSpell",
"BoundCuirass",
"BoundHelm",
"BoundBoots",
"BoundShield",
"BoundGloves",
"Corprus",
"Vampirism",
"SummonCenturionSphere",
"SunDamage",
"StuntedMagicka",
// Tribunal only
"SummonFabricant",
// Bloodmoon only
"SummonWolf",
"SummonBear",
"SummonBonewolf",
"SummonCreature04",
"SummonCreature05",
};
const int NumberOfHardcodedFlags = 143;
const int HardcodedFlags[NumberOfHardcodedFlags] = { 0x11c8, 0x11c0, 0x11c8, 0x11e0, 0x11e0, 0x11e0, 0x11e0,
0x11d0, 0x11c0, 0x11c0, 0x11e0, 0x11c0, 0x11184, 0x11184, 0x1f0, 0x1f0, 0x1f0, 0x11d2, 0x11f0, 0x11d0,
@ -186,7 +34,7 @@ namespace ESM
esm.getHNT(mIndex, "INDX");
mId = ESM::RefId::stringRefId(indexToId(mIndex));
mId = indexToRefId(mIndex);
esm.getHNTSized<36>(mData, "MEDT");
if (esm.getFormatVersion() == DefaultFormatVersion)
@ -592,28 +440,10 @@ namespace ESM
mDescription.clear();
}
std::string MagicEffect::indexToId(int index)
RefId MagicEffect::indexToRefId(int index)
{
std::ostringstream stream;
if (index != -1)
{
stream << "#";
if (index < 100)
{
stream << "0";
if (index < 10)
stream << "0";
}
stream << index;
if (index >= 0 && index < Length)
stream << sIds[index];
}
return stream.str();
if (index == -1)
return RefId();
return RefId::index(sRecordId, static_cast<std::uint32_t>(index));
}
}

@ -269,7 +269,7 @@ namespace ESM
Length
};
static std::string indexToId(int index);
static RefId indexToRefId(int index);
};
}
#endif

@ -1,7 +1,5 @@
#include "loadskil.hpp"
#include <sstream>
#include "esmreader.hpp"
#include "esmwriter.hpp"
@ -133,7 +131,7 @@ namespace ESM
// create an ID from the index and the name (only used in the editor and likely to change in the
// future)
mId = ESM::RefId::stringRefId(indexToId(mIndex));
mId = indexToRefId(mIndex);
}
void Skill::save(ESMWriter& esm, bool /*isDeleted*/) const
@ -152,23 +150,10 @@ namespace ESM
mDescription.clear();
}
std::string Skill::indexToId(int index)
RefId Skill::indexToRefId(int index)
{
std::ostringstream stream;
if (index != -1)
{
stream << "#";
if (index < 10)
stream << "0";
stream << index;
if (index >= 0 && index < Length)
stream << sSkillNameIds[index].substr(6);
}
return stream.str();
if (index == -1)
return RefId();
return RefId::index(sRecordId, static_cast<std::uint32_t>(index));
}
}

@ -87,7 +87,7 @@ namespace ESM
void blank();
///< Set record to default state (does not touch the ID/index).
static std::string indexToId(int index);
static RefId indexToRefId(int index);
};
}
#endif

Loading…
Cancel
Save