1
0
mirror of https://gitlab.com/OpenMW/openmw.git synced 2025-03-14 01:19:59 +00:00

The esm4 reader logic is mutualised

to avoid copy pasting code, readerutils gives functions that take visitors as params to decide how a record must be handled

Check encoder exists, and get value of stateless encoder.

fixes code formatting conventions

Fixed output of record with RefId

also fixed readTypedRecord and readRecord to have the proper return types

Check if the type has a sRecordId
This commit is contained in:
florent.teppe 2022-12-30 11:28:19 +01:00
parent c721a6cafa
commit 077cf97bc4
12 changed files with 440 additions and 340 deletions

View File

@ -8,6 +8,7 @@
#include <components/esm/esmcommon.hpp>
#include <components/esm4/reader.hpp>
#include <components/esm4/readerutils.hpp>
#include <components/esm4/records.hpp>
#include <components/to_utf8/to_utf8.hpp>
@ -69,6 +70,19 @@ namespace EsmTool
template <class T>
constexpr bool hasFormId = HasFormId<T>::value;
template <class T, class = std::void_t<>>
struct HasRefId : std::false_type
{
};
template <class T>
struct HasRefId<T, std::void_t<decltype(T::mId)>> : std::true_type
{
};
template <class T>
constexpr bool hasRefId = HasRefId<T>::value;
template <class T, class = std::void_t<>>
struct HasFlags : std::false_type
{
@ -169,6 +183,8 @@ namespace EsmTool
std::cout << "\n Record: " << ESM::NAME(reader.hdr().record.typeId).toStringView();
if constexpr (hasFormId<T>)
std::cout << "\n FormId: " << value.mFormId;
if constexpr (hasRefId<T>)
std::cout << "\n RefId: " << value.mId;
if constexpr (hasFlags<T>)
std::cout << "\n Record flags: " << recordFlags(value.mFlags);
if constexpr (hasEditorId<T>)
@ -180,62 +196,80 @@ namespace EsmTool
if constexpr (hasKf<T>)
std::cout << "\n Kf:" << WriteArray("\n - ", value.mKf);
std::cout << '\n';
return;
}
void readRecord(const Params& params, ESM4::Reader& reader)
bool readRecord(const Params& params, ESM4::Reader& reader)
{
switch (static_cast<ESM4::RecordTypes>(reader.hdr().record.typeId))
{
case ESM4::REC_AACT:
break;
case ESM4::REC_ACHR:
return readTypedRecord<ESM4::ActorCharacter>(params, reader);
readTypedRecord<ESM4::ActorCharacter>(params, reader);
return true;
case ESM4::REC_ACRE:
return readTypedRecord<ESM4::ActorCreature>(params, reader);
readTypedRecord<ESM4::ActorCreature>(params, reader);
return true;
case ESM4::REC_ACTI:
return readTypedRecord<ESM4::Activator>(params, reader);
readTypedRecord<ESM4::Activator>(params, reader);
return true;
case ESM4::REC_ADDN:
break;
case ESM4::REC_ALCH:
return readTypedRecord<ESM4::Potion>(params, reader);
readTypedRecord<ESM4::Potion>(params, reader);
return true;
case ESM4::REC_ALOC:
return readTypedRecord<ESM4::MediaLocationController>(params, reader);
readTypedRecord<ESM4::MediaLocationController>(params, reader);
return true;
case ESM4::REC_AMMO:
return readTypedRecord<ESM4::Ammunition>(params, reader);
readTypedRecord<ESM4::Ammunition>(params, reader);
return true;
case ESM4::REC_ANIO:
return readTypedRecord<ESM4::AnimObject>(params, reader);
readTypedRecord<ESM4::AnimObject>(params, reader);
return true;
case ESM4::REC_APPA:
return readTypedRecord<ESM4::Apparatus>(params, reader);
readTypedRecord<ESM4::Apparatus>(params, reader);
return true;
case ESM4::REC_ARMA:
return readTypedRecord<ESM4::ArmorAddon>(params, reader);
readTypedRecord<ESM4::ArmorAddon>(params, reader);
return true;
case ESM4::REC_ARMO:
return readTypedRecord<ESM4::Armor>(params, reader);
readTypedRecord<ESM4::Armor>(params, reader);
return true;
case ESM4::REC_ARTO:
break;
case ESM4::REC_ASPC:
return readTypedRecord<ESM4::AcousticSpace>(params, reader);
readTypedRecord<ESM4::AcousticSpace>(params, reader);
return true;
case ESM4::REC_ASTP:
break;
case ESM4::REC_AVIF:
break;
case ESM4::REC_BOOK:
return readTypedRecord<ESM4::Book>(params, reader);
readTypedRecord<ESM4::Book>(params, reader);
return true;
case ESM4::REC_BPTD:
return readTypedRecord<ESM4::BodyPartData>(params, reader);
readTypedRecord<ESM4::BodyPartData>(params, reader);
return true;
case ESM4::REC_CAMS:
break;
case ESM4::REC_CCRD:
break;
case ESM4::REC_CELL:
return readTypedRecord<ESM4::Cell>(params, reader);
readTypedRecord<ESM4::Cell>(params, reader);
return true;
case ESM4::REC_CLAS:
return readTypedRecord<ESM4::Class>(params, reader);
readTypedRecord<ESM4::Class>(params, reader);
return true;
case ESM4::REC_CLFM:
return readTypedRecord<ESM4::Colour>(params, reader);
readTypedRecord<ESM4::Colour>(params, reader);
return true;
case ESM4::REC_CLMT:
break;
case ESM4::REC_CLOT:
return readTypedRecord<ESM4::Clothing>(params, reader);
readTypedRecord<ESM4::Clothing>(params, reader);
return true;
case ESM4::REC_CMNY:
break;
case ESM4::REC_COBJ:
@ -243,25 +277,30 @@ namespace EsmTool
case ESM4::REC_COLL:
break;
case ESM4::REC_CONT:
return readTypedRecord<ESM4::Container>(params, reader);
readTypedRecord<ESM4::Container>(params, reader);
return true;
case ESM4::REC_CPTH:
break;
case ESM4::REC_CREA:
return readTypedRecord<ESM4::Creature>(params, reader);
readTypedRecord<ESM4::Creature>(params, reader);
return true;
case ESM4::REC_CSTY:
break;
case ESM4::REC_DEBR:
break;
case ESM4::REC_DIAL:
return readTypedRecord<ESM4::Dialogue>(params, reader);
readTypedRecord<ESM4::Dialogue>(params, reader);
return true;
case ESM4::REC_DLBR:
break;
case ESM4::REC_DLVW:
break;
case ESM4::REC_DOBJ:
return readTypedRecord<ESM4::DefaultObj>(params, reader);
readTypedRecord<ESM4::DefaultObj>(params, reader);
return true;
case ESM4::REC_DOOR:
return readTypedRecord<ESM4::Door>(params, reader);
readTypedRecord<ESM4::Door>(params, reader);
return true;
case ESM4::REC_DUAL:
break;
case ESM4::REC_ECZN:
@ -275,81 +314,103 @@ namespace EsmTool
case ESM4::REC_EXPL:
break;
case ESM4::REC_EYES:
return readTypedRecord<ESM4::Eyes>(params, reader);
readTypedRecord<ESM4::Eyes>(params, reader);
return true;
case ESM4::REC_FACT:
break;
case ESM4::REC_FLOR:
return readTypedRecord<ESM4::Flora>(params, reader);
readTypedRecord<ESM4::Flora>(params, reader);
return true;
case ESM4::REC_FLST:
return readTypedRecord<ESM4::FormIdList>(params, reader);
readTypedRecord<ESM4::FormIdList>(params, reader);
return true;
case ESM4::REC_FSTP:
break;
case ESM4::REC_FSTS:
break;
case ESM4::REC_FURN:
return readTypedRecord<ESM4::Furniture>(params, reader);
readTypedRecord<ESM4::Furniture>(params, reader);
return true;
case ESM4::REC_GLOB:
return readTypedRecord<ESM4::GlobalVariable>(params, reader);
readTypedRecord<ESM4::GlobalVariable>(params, reader);
return true;
case ESM4::REC_GMST:
break;
case ESM4::REC_GRAS:
return readTypedRecord<ESM4::Grass>(params, reader);
readTypedRecord<ESM4::Grass>(params, reader);
return true;
case ESM4::REC_GRUP:
break;
case ESM4::REC_HAIR:
return readTypedRecord<ESM4::Hair>(params, reader);
readTypedRecord<ESM4::Hair>(params, reader);
return true;
case ESM4::REC_HAZD:
break;
case ESM4::REC_HDPT:
return readTypedRecord<ESM4::HeadPart>(params, reader);
readTypedRecord<ESM4::HeadPart>(params, reader);
return true;
case ESM4::REC_IDLE:
// FIXME: ESM4::IdleAnimation::load does not work with Oblivion.esm
// return readTypedRecord<ESM4::IdleAnimation>(params, reader);
// readTypedRecord<ESM4::IdleAnimation>(params, reader);
return true;
break;
case ESM4::REC_IDLM:
return readTypedRecord<ESM4::IdleMarker>(params, reader);
readTypedRecord<ESM4::IdleMarker>(params, reader);
return true;
case ESM4::REC_IMAD:
break;
case ESM4::REC_IMGS:
break;
case ESM4::REC_IMOD:
return readTypedRecord<ESM4::ItemMod>(params, reader);
readTypedRecord<ESM4::ItemMod>(params, reader);
return true;
case ESM4::REC_INFO:
return readTypedRecord<ESM4::DialogInfo>(params, reader);
readTypedRecord<ESM4::DialogInfo>(params, reader);
return true;
case ESM4::REC_INGR:
return readTypedRecord<ESM4::Ingredient>(params, reader);
readTypedRecord<ESM4::Ingredient>(params, reader);
return true;
case ESM4::REC_IPCT:
break;
case ESM4::REC_IPDS:
break;
case ESM4::REC_KEYM:
return readTypedRecord<ESM4::Key>(params, reader);
readTypedRecord<ESM4::Key>(params, reader);
return true;
case ESM4::REC_KYWD:
break;
case ESM4::REC_LAND:
return readTypedRecord<ESM4::Land>(params, reader);
readTypedRecord<ESM4::Land>(params, reader);
return true;
case ESM4::REC_LCRT:
break;
case ESM4::REC_LCTN:
break;
case ESM4::REC_LGTM:
return readTypedRecord<ESM4::LightingTemplate>(params, reader);
readTypedRecord<ESM4::LightingTemplate>(params, reader);
return true;
case ESM4::REC_LIGH:
return readTypedRecord<ESM4::Light>(params, reader);
readTypedRecord<ESM4::Light>(params, reader);
return true;
case ESM4::REC_LSCR:
break;
case ESM4::REC_LTEX:
return readTypedRecord<ESM4::LandTexture>(params, reader);
readTypedRecord<ESM4::LandTexture>(params, reader);
return true;
case ESM4::REC_LVLC:
return readTypedRecord<ESM4::LevelledCreature>(params, reader);
readTypedRecord<ESM4::LevelledCreature>(params, reader);
return true;
case ESM4::REC_LVLI:
return readTypedRecord<ESM4::LevelledItem>(params, reader);
readTypedRecord<ESM4::LevelledItem>(params, reader);
return true;
case ESM4::REC_LVLN:
return readTypedRecord<ESM4::LevelledNpc>(params, reader);
readTypedRecord<ESM4::LevelledNpc>(params, reader);
return true;
case ESM4::REC_LVSP:
break;
case ESM4::REC_MATO:
return readTypedRecord<ESM4::Material>(params, reader);
readTypedRecord<ESM4::Material>(params, reader);
return true;
case ESM4::REC_MATT:
break;
case ESM4::REC_MESG:
@ -357,49 +418,66 @@ namespace EsmTool
case ESM4::REC_MGEF:
break;
case ESM4::REC_MISC:
return readTypedRecord<ESM4::MiscItem>(params, reader);
readTypedRecord<ESM4::MiscItem>(params, reader);
return true;
case ESM4::REC_MOVT:
break;
case ESM4::REC_MSET:
return readTypedRecord<ESM4::MediaSet>(params, reader);
readTypedRecord<ESM4::MediaSet>(params, reader);
return true;
case ESM4::REC_MSTT:
return readTypedRecord<ESM4::MovableStatic>(params, reader);
readTypedRecord<ESM4::MovableStatic>(params, reader);
return true;
case ESM4::REC_MUSC:
return readTypedRecord<ESM4::Music>(params, reader);
readTypedRecord<ESM4::Music>(params, reader);
return true;
case ESM4::REC_MUST:
break;
case ESM4::REC_NAVI:
return readTypedRecord<ESM4::Navigation>(params, reader);
readTypedRecord<ESM4::Navigation>(params, reader);
return true;
case ESM4::REC_NAVM:
return readTypedRecord<ESM4::NavMesh>(params, reader);
readTypedRecord<ESM4::NavMesh>(params, reader);
return true;
case ESM4::REC_NOTE:
return readTypedRecord<ESM4::Note>(params, reader);
readTypedRecord<ESM4::Note>(params, reader);
return true;
case ESM4::REC_NPC_:
return readTypedRecord<ESM4::Npc>(params, reader);
readTypedRecord<ESM4::Npc>(params, reader);
return true;
case ESM4::REC_OTFT:
return readTypedRecord<ESM4::Outfit>(params, reader);
readTypedRecord<ESM4::Outfit>(params, reader);
return true;
case ESM4::REC_PACK:
return readTypedRecord<ESM4::AIPackage>(params, reader);
readTypedRecord<ESM4::AIPackage>(params, reader);
return true;
case ESM4::REC_PERK:
break;
case ESM4::REC_PGRD:
return readTypedRecord<ESM4::Pathgrid>(params, reader);
readTypedRecord<ESM4::Pathgrid>(params, reader);
return true;
case ESM4::REC_PGRE:
return readTypedRecord<ESM4::PlacedGrenade>(params, reader);
readTypedRecord<ESM4::PlacedGrenade>(params, reader);
return true;
case ESM4::REC_PHZD:
break;
case ESM4::REC_PROJ:
break;
case ESM4::REC_PWAT:
return readTypedRecord<ESM4::PlaceableWater>(params, reader);
readTypedRecord<ESM4::PlaceableWater>(params, reader);
return true;
case ESM4::REC_QUST:
return readTypedRecord<ESM4::Quest>(params, reader);
readTypedRecord<ESM4::Quest>(params, reader);
return true;
case ESM4::REC_RACE:
return readTypedRecord<ESM4::Race>(params, reader);
readTypedRecord<ESM4::Race>(params, reader);
return true;
case ESM4::REC_REFR:
return readTypedRecord<ESM4::Reference>(params, reader);
readTypedRecord<ESM4::Reference>(params, reader);
return true;
case ESM4::REC_REGN:
return readTypedRecord<ESM4::Region>(params, reader);
readTypedRecord<ESM4::Region>(params, reader);
return true;
case ESM4::REC_RELA:
break;
case ESM4::REC_REVB:
@ -407,23 +485,30 @@ namespace EsmTool
case ESM4::REC_RFCT:
break;
case ESM4::REC_ROAD:
return readTypedRecord<ESM4::Road>(params, reader);
readTypedRecord<ESM4::Road>(params, reader);
return true;
case ESM4::REC_SBSP:
return readTypedRecord<ESM4::SubSpace>(params, reader);
readTypedRecord<ESM4::SubSpace>(params, reader);
return true;
case ESM4::REC_SCEN:
break;
case ESM4::REC_SCOL:
return readTypedRecord<ESM4::StaticCollection>(params, reader);
readTypedRecord<ESM4::StaticCollection>(params, reader);
return true;
case ESM4::REC_SCPT:
return readTypedRecord<ESM4::Script>(params, reader);
readTypedRecord<ESM4::Script>(params, reader);
return true;
case ESM4::REC_SCRL:
return readTypedRecord<ESM4::Scroll>(params, reader);
readTypedRecord<ESM4::Scroll>(params, reader);
return true;
case ESM4::REC_SGST:
return readTypedRecord<ESM4::SigilStone>(params, reader);
readTypedRecord<ESM4::SigilStone>(params, reader);
return true;
case ESM4::REC_SHOU:
break;
case ESM4::REC_SLGM:
return readTypedRecord<ESM4::SoulGem>(params, reader);
readTypedRecord<ESM4::SoulGem>(params, reader);
return true;
case ESM4::REC_SMBN:
break;
case ESM4::REC_SMEN:
@ -433,97 +518,56 @@ namespace EsmTool
case ESM4::REC_SNCT:
break;
case ESM4::REC_SNDR:
return readTypedRecord<ESM4::SoundReference>(params, reader);
readTypedRecord<ESM4::SoundReference>(params, reader);
return true;
case ESM4::REC_SOPM:
break;
case ESM4::REC_SOUN:
return readTypedRecord<ESM4::Sound>(params, reader);
readTypedRecord<ESM4::Sound>(params, reader);
return true;
case ESM4::REC_SPEL:
break;
case ESM4::REC_SPGD:
break;
case ESM4::REC_STAT:
return readTypedRecord<ESM4::Static>(params, reader);
readTypedRecord<ESM4::Static>(params, reader);
return true;
case ESM4::REC_TACT:
return readTypedRecord<ESM4::TalkingActivator>(params, reader);
readTypedRecord<ESM4::TalkingActivator>(params, reader);
return true;
case ESM4::REC_TERM:
return readTypedRecord<ESM4::Terminal>(params, reader);
readTypedRecord<ESM4::Terminal>(params, reader);
return true;
case ESM4::REC_TES4:
return readTypedRecord<ESM4::Header>(params, reader);
readTypedRecord<ESM4::Header>(params, reader);
return true;
case ESM4::REC_TREE:
return readTypedRecord<ESM4::Tree>(params, reader);
readTypedRecord<ESM4::Tree>(params, reader);
return true;
case ESM4::REC_TXST:
return readTypedRecord<ESM4::TextureSet>(params, reader);
readTypedRecord<ESM4::TextureSet>(params, reader);
return true;
case ESM4::REC_VTYP:
break;
case ESM4::REC_WATR:
break;
case ESM4::REC_WEAP:
return readTypedRecord<ESM4::Weapon>(params, reader);
readTypedRecord<ESM4::Weapon>(params, reader);
return true;
case ESM4::REC_WOOP:
break;
case ESM4::REC_WRLD:
return readTypedRecord<ESM4::World>(params, reader);
readTypedRecord<ESM4::World>(params, reader);
return true;
case ESM4::REC_WTHR:
break;
}
if (!params.mQuite)
std::cout << "\n Unsupported record: " << ESM::NAME(reader.hdr().record.typeId).toStringView() << '\n';
reader.skipRecordData();
return false;
}
bool readItem(const Params& params, ESM4::Reader& reader);
bool readGroup(const Params& params, ESM4::Reader& reader)
{
const ESM4::RecordHeader& header = reader.hdr();
if (!params.mQuite)
std::cout << "\nGroup: " << toString(static_cast<ESM4::GroupType>(header.group.type)) << " "
<< ESM::NAME(header.group.typeId).toStringView() << '\n';
switch (static_cast<ESM4::GroupType>(header.group.type))
{
case ESM4::Grp_RecordType:
case ESM4::Grp_InteriorCell:
case ESM4::Grp_InteriorSubCell:
case ESM4::Grp_ExteriorCell:
case ESM4::Grp_ExteriorSubCell:
reader.enterGroup();
return readItem(params, reader);
case ESM4::Grp_WorldChild:
case ESM4::Grp_CellChild:
case ESM4::Grp_TopicChild:
case ESM4::Grp_CellPersistentChild:
case ESM4::Grp_CellTemporaryChild:
case ESM4::Grp_CellVisibleDistChild:
reader.adjustGRUPFormId();
reader.enterGroup();
if (!reader.hasMoreRecs())
return false;
return readItem(params, reader);
}
reader.skipGroup();
return true;
}
bool readItem(const Params& params, ESM4::Reader& reader)
{
if (!reader.getRecordHeader() || !reader.hasMoreRecs())
return false;
const ESM4::RecordHeader& header = reader.hdr();
if (header.record.typeId == ESM4::REC_GRUP)
return readGroup(params, reader);
readRecord(params, reader);
return true;
}
}
int loadTes4(const Arguments& info, std::unique_ptr<std::ifstream>&& stream)
@ -551,12 +595,15 @@ namespace EsmTool
}
}
while (reader.hasMoreRecs())
{
reader.exitGroupCheck();
if (!readItem(params, reader))
break;
}
auto visitorRec = [&params](ESM4::Reader& reader) { return readRecord(params, reader); };
auto visistorGroup = [&params](ESM4::Reader& reader) {
if (params.mQuite)
return;
auto groupType = static_cast<ESM4::GroupType>(reader.hdr().group.type);
std::cout << "\nGroup: " << toString(groupType) << " "
<< ESM::NAME(reader.hdr().group.typeId).toStringView() << '\n';
};
ESM4::ReaderUtils::readAll(reader, visitorRec, visistorGroup);
}
catch (const std::exception& e)
{

View File

@ -1,13 +1,14 @@
#include "esmloader.hpp"
#include "esmstore.hpp"
#include <fstream>
#include <components/esm/format.hpp>
#include <components/esm3/esmreader.hpp>
#include <components/esm3/readerscache.hpp>
#include <components/esm4/reader.hpp>
#include <components/files/conversion.hpp>
#include <components/files/openfile.hpp>
#include <fstream>
namespace MWWorld
{
@ -30,7 +31,6 @@ namespace MWWorld
if (!stream->is_open())
{
throw std::runtime_error(std::string("File Failed to open file: ") + std::strerror(errno) + "\n");
return;
}
const ESM::Format format = ESM::readFormat(*stream);
stream->seekg(0);
@ -64,9 +64,13 @@ namespace MWWorld
}
case ESM::Format::Tes4:
{
ESM4::Reader readerESM4(std::move(stream), filepath);
readerESM4.setEncoder(mEncoder->getStatelessEncoder());
mStore.loadESM4(readerESM4, listener, mDialogue);
if (mEncoder)
{
ESM4::Reader readerESM4(std::move(stream), filepath);
auto statelessEncoder = mEncoder->getStatelessEncoder();
readerESM4.setEncoder(&statelessEncoder);
mStore.loadESM4(readerESM4, listener, mDialogue);
}
}
}
}

View File

@ -13,12 +13,12 @@
#include <components/lua/configuration.hpp>
#include <components/misc/algorithm.hpp>
#include <components/esm4/common.hpp>
#include <components/esm4/loadcell.hpp>
#include <components/esm4/loadrefr.hpp>
#include <components/esm4/loadstat.hpp>
#include <components/esm4/reader.hpp>
#include <components/esm4/common.hpp>
#include <components/esm4/readerutils.hpp>
#include <components/esmloader/load.hpp>
#include "../mwmechanics/spelllist.hpp"
@ -186,13 +186,23 @@ namespace MWWorld
}
}
template <class T, class = std::void_t<>>
struct HasRecordId : std::false_type
{
};
template <class T>
struct HasRecordId<T, std::void_t<decltype(T::sRecordId)>> : std::true_type
{
};
template <typename T>
static void typedReadRecordESM4(ESM4::Reader& reader, ESMStore& stores, Store<T>& store, int& found)
{
auto recordType = static_cast<ESM4::RecordTypes>(reader.hdr().record.typeId);
ESM::RecNameInts esm4RecName = static_cast<ESM::RecNameInts>(ESM::esm4Recname(recordType));
if constexpr (std::is_convertible_v<Store<T>*, DynamicStore*>)
if constexpr (std::is_convertible_v<Store<T>*, DynamicStore*> && HasRecordId<T>::value)
{
if constexpr (ESM::isESM4Rec(T::sRecordId))
{
@ -208,60 +218,14 @@ namespace MWWorld
}
}
static void readRecord(ESM4::Reader& reader, ESMStore& store)
static bool readRecord(ESM4::Reader& reader, ESMStore& store)
{
int found = 0;
std::apply([&reader, &store, &found](
auto&... x) { (ESMStoreImp::typedReadRecordESM4(reader, store, x, found), ...); },
store.mStoreImp->mStores);
assert(found <= 1);
if (found == 0) // unhandled record
reader.skipRecordData();
}
static bool readItem(ESM4::Reader& reader, ESMStore& store)
{
if (!reader.getRecordHeader() || !reader.hasMoreRecs())
return false;
const ESM4::RecordHeader& header = reader.hdr();
if (header.record.typeId == ESM4::REC_GRUP)
return readGroup(reader, store);
readRecord(reader, store);
return true;
}
static bool readGroup(ESM4::Reader& reader, ESMStore& store)
{
const ESM4::RecordHeader& header = reader.hdr();
switch (static_cast<ESM4::GroupType>(header.group.type))
{
case ESM4::Grp_RecordType:
case ESM4::Grp_InteriorCell:
case ESM4::Grp_InteriorSubCell:
case ESM4::Grp_ExteriorCell:
case ESM4::Grp_ExteriorSubCell:
reader.enterGroup();
return readItem(reader, store);
case ESM4::Grp_WorldChild:
case ESM4::Grp_CellChild:
case ESM4::Grp_TopicChild:
case ESM4::Grp_CellPersistentChild:
case ESM4::Grp_CellTemporaryChild:
case ESM4::Grp_CellVisibleDistChild:
reader.adjustGRUPFormId();
reader.enterGroup();
if (!reader.hasMoreRecs())
return false;
return readItem(reader, store);
}
reader.skipGroup();
return true;
return found;
}
};
@ -423,12 +387,8 @@ namespace MWWorld
void ESMStore::loadESM4(ESM4::Reader& reader, Loading::Listener* listener, ESM::Dialogue*& dialogue)
{
while (reader.hasMoreRecs())
{
reader.exitGroupCheck();
if (!ESMStoreImp::readItem(reader, *this))
break;
}
auto visitorRec = [this](ESM4::Reader& reader) { return ESMStoreImp::readRecord(reader, *this); };
ESM4::ReaderUtils::readAll(reader, visitorRec, [](ESM4::Reader&) {});
}
void ESMStore::setIdType(const ESM::RefId& id, ESM::RecNameInts type)

View File

@ -1,21 +1,18 @@
#include "store.hpp"
#include <components/debug/debuglog.hpp>
#include <components/esm/records.hpp>
#include <components/esm3/esmreader.hpp>
#include <components/esm3/esmwriter.hpp>
#include <components/loadinglistener/loadinglistener.hpp>
#include <components/misc/rng.hpp>
#include <iterator>
#include <sstream>
#include <stdexcept>
#include <components/debug/debuglog.hpp>
#include <components/esm/records.hpp>
#include <components/esm3/esmreader.hpp>
#include <components/esm3/esmwriter.hpp>
#include <components/esm4/loadcell.hpp>
#include <components/esm4/loadrefr.hpp>
#include <components/esm4/loadstat.hpp>
#include <components/loadinglistener/loadinglistener.hpp>
#include <components/misc/rng.hpp>
namespace
{

View File

@ -1,84 +1,84 @@
project (Components)
project(Components)
# Version file
set (VERSION_IN_FILE "${OpenMW_SOURCE_DIR}/files/version.in")
set (VERSION_FILE_PATH_BASE "${OpenMW_BINARY_DIR}")
set (VERSION_FILE_PATH_RELATIVE resources/version)
if (GIT_CHECKOUT)
set(VERSION_IN_FILE "${OpenMW_SOURCE_DIR}/files/version.in")
set(VERSION_FILE_PATH_BASE "${OpenMW_BINARY_DIR}")
set(VERSION_FILE_PATH_RELATIVE resources/version)
if(GIT_CHECKOUT)
get_generator_is_multi_config(multi_config)
add_custom_target (git-version
COMMAND ${CMAKE_COMMAND}
-DGIT_EXECUTABLE=${GIT_EXECUTABLE}
-DPROJECT_SOURCE_DIR=${PROJECT_SOURCE_DIR}
-DVERSION_IN_FILE=${VERSION_IN_FILE}
-DVERSION_FILE_PATH_BASE=${VERSION_FILE_PATH_BASE}
-DVERSION_FILE_PATH_RELATIVE=${VERSION_FILE_PATH_RELATIVE}
-DOPENMW_VERSION_MAJOR=${OPENMW_VERSION_MAJOR}
-DOPENMW_VERSION_MINOR=${OPENMW_VERSION_MINOR}
-DOPENMW_VERSION_RELEASE=${OPENMW_VERSION_RELEASE}
-DOPENMW_VERSION=${OPENMW_VERSION}
-DMACROSFILE=${CMAKE_SOURCE_DIR}/cmake/OpenMWMacros.cmake
"-DCMAKE_CONFIGURATION_TYPES=${CMAKE_CONFIGURATION_TYPES}"
-Dgenerator_is_multi_config_var=${multi_config}
-P ${CMAKE_CURRENT_SOURCE_DIR}/../cmake/GitVersion.cmake
VERBATIM)
else (GIT_CHECKOUT)
add_custom_target(git-version
COMMAND ${CMAKE_COMMAND}
-DGIT_EXECUTABLE=${GIT_EXECUTABLE}
-DPROJECT_SOURCE_DIR=${PROJECT_SOURCE_DIR}
-DVERSION_IN_FILE=${VERSION_IN_FILE}
-DVERSION_FILE_PATH_BASE=${VERSION_FILE_PATH_BASE}
-DVERSION_FILE_PATH_RELATIVE=${VERSION_FILE_PATH_RELATIVE}
-DOPENMW_VERSION_MAJOR=${OPENMW_VERSION_MAJOR}
-DOPENMW_VERSION_MINOR=${OPENMW_VERSION_MINOR}
-DOPENMW_VERSION_RELEASE=${OPENMW_VERSION_RELEASE}
-DOPENMW_VERSION=${OPENMW_VERSION}
-DMACROSFILE=${CMAKE_SOURCE_DIR}/cmake/OpenMWMacros.cmake
"-DCMAKE_CONFIGURATION_TYPES=${CMAKE_CONFIGURATION_TYPES}"
-Dgenerator_is_multi_config_var=${multi_config}
-P ${CMAKE_CURRENT_SOURCE_DIR}/../cmake/GitVersion.cmake
VERBATIM)
else(GIT_CHECKOUT)
configure_resource_file(${VERSION_IN_FILE} ${VERSION_FILE_PATH_BASE} ${VERSION_FILE_PATH_RELATIVE})
endif (GIT_CHECKOUT)
endif(GIT_CHECKOUT)
# source files
add_component_dir (lua
add_component_dir(lua
luastate scriptscontainer utilpackage serialization configuration l10n storage
)
)
add_component_dir (l10n
add_component_dir(l10n
messagebundles manager
)
)
add_component_dir (settings
add_component_dir(settings
settings parser
)
)
add_component_dir (bsa
add_component_dir(bsa
bsa_file compressedbsafile
)
)
add_component_dir (vfs
add_component_dir(vfs
manager archive bsaarchive filesystemarchive registerarchives
)
)
add_component_dir (resource
add_component_dir(resource
scenemanager keyframemanager imagemanager bulletshapemanager bulletshape niffilemanager objectcache multiobjectcache resourcesystem
resourcemanager stats animation foreachbulletobject errormarker
)
)
add_component_dir (shader
add_component_dir(shader
shadermanager shadervisitor removedalphafunc
)
)
add_component_dir (sceneutil
add_component_dir(sceneutil
clone attach visitor util statesetupdater controller skeleton riggeometry morphgeometry lightcontroller
lightmanager lightutil positionattitudetransform workqueue pathgridutil waterutil writescene serialize optimizer
actorutil detourdebugdraw navmesh agentpath shadow mwshadowtechnique recastmesh shadowsbin osgacontroller rtt
screencapture depth color riggeometryosgaextension extradata unrefqueue
)
)
add_component_dir (nif
add_component_dir(nif
controlled effect niftypes record controller extra node record_ptr data niffile property nifkey base nifstream physics
)
)
add_component_dir (nifosg
add_component_dir(nifosg
nifloader controller particle matrixtransform
)
)
add_component_dir (nifbullet
add_component_dir(nifbullet
bulletnifloader
)
)
add_component_dir (to_utf8
add_component_dir(to_utf8
to_utf8
)
)
add_component_dir(esm attr common defs esmcommon records util luascripts format refid)
@ -86,7 +86,7 @@ add_component_dir(fx pass technique lexer widgets stateupdater)
add_component_dir(std140 ubo)
add_component_dir (esm3
add_component_dir(esm3
esmreader esmwriter loadacti loadalch loadappa loadarmo loadbody loadbook loadbsgn loadcell
loadclas loadclot loadcont loadcrea loaddial loaddoor loadench loadfact loadglob loadgmst
loadinfo loadingr loadland loadlevlist loadligh loadlock loadprob loadrepa loadltex loadmgef loadmisc
@ -96,13 +96,13 @@ add_component_dir (esm3
inventorystate containerstate npcstate creaturestate dialoguestate statstate npcstats creaturestats
weatherstate quickkeys fogstate spellstate activespells creaturelevliststate doorstate projectilestate debugprofile
aisequence magiceffects custommarkerstate stolenitems transport animationstate controlsstate mappings readerscache
)
)
add_component_dir (esm3terrain
add_component_dir(esm3terrain
storage
)
)
add_component_dir (esm4
add_component_dir(esm4
acti
actor
common
@ -191,96 +191,97 @@ add_component_dir (esm4
loadweap
loadwrld
reader
readerutils
reference
script
)
add_component_dir (misc
add_component_dir(misc
constants utf8stream resourcehelpers rng messageformatparser weakcache thread
compression osguservalues color tuplemeta tuplehelpers
)
)
add_component_dir (stereo
add_component_dir(stereo
frustum multiview stereomanager types
)
)
add_component_dir (debug
add_component_dir(debug
debugging debuglog gldebug debugdraw
)
)
IF(NOT WIN32 AND NOT APPLE)
add_definitions(-DGLOBAL_DATA_PATH="${GLOBAL_DATA_PATH}")
add_definitions(-DGLOBAL_CONFIG_PATH="${GLOBAL_CONFIG_PATH}")
ENDIF()
add_component_dir (files
add_component_dir(files
linuxpath androidpath windowspath macospath fixedpath multidircollection collections configurationmanager
constrainedfilestream memorystream hash configfileparser openfile constrainedfilestreambuf conversion
)
)
add_component_dir (compiler
add_component_dir(compiler
context controlparser errorhandler exception exprparser extensions fileparser generator
lineparser literals locals output parser scanner scriptparser skipparser streamerrorhandler
stringparser tokenloc nullerrorhandler opcodes extensions0 declarationparser
quickfileparser discardparser junkparser
)
)
add_component_dir (interpreter
add_component_dir(interpreter
context controlopcodes genericopcodes installopcodes interpreter localopcodes mathopcodes
miscopcodes opcodes runtime types defines
)
)
add_component_dir (translation
add_component_dir(translation
translation
)
)
add_component_dir (terrain
add_component_dir(terrain
storage world buffercache defs terraingrid material terraindrawable texturemanager chunkmanager compositemaprenderer
quadtreeworld quadtreenode viewdata cellborder view heightcull
)
)
add_component_dir (loadinglistener
add_component_dir(loadinglistener
loadinglistener
)
)
add_component_dir (myguiplatform
add_component_dir(myguiplatform
myguirendermanager myguidatamanager myguiplatform myguitexture myguiloglistener additivelayer scalinglayer
)
)
add_component_dir (widgets
add_component_dir(widgets
box fontwrapper imagebutton tags list numericeditbox sharedstatebutton windowcaption widgets
)
)
add_component_dir (fontloader
add_component_dir(fontloader
fontloader
)
)
add_component_dir (sdlutil
add_component_dir(sdlutil
gl4es_init sdlgraphicswindow imagetosurface sdlinputwrapper sdlvideowrapper events sdlcursormanager sdlmappings
)
)
add_component_dir (version
add_component_dir(version
version
)
)
add_component_dir (fallback
add_component_dir(fallback
fallback validate
)
)
add_component_dir (lua_ui
add_component_dir(lua_ui
registerscriptsettings scriptsettings
properties widget element util layers content alignment resources
adapter text textedit window image container flex
)
)
if(WIN32)
add_component_dir (crashcatcher
add_component_dir(crashcatcher
windows_crashcatcher
windows_crashmonitor
windows_crashshm
)
elseif(NOT ANDROID)
add_component_dir (crashcatcher
add_component_dir(crashcatcher
crashcatcher
)
endif()
@ -316,11 +317,11 @@ add_component_dir(detournavigator
stats
commulativeaabb
recastcontext
)
)
add_component_dir(loadinglistener
reporter
)
)
add_component_dir(sqlite3
db
@ -335,63 +336,63 @@ add_component_dir(esmloader
add_component_dir(navmeshtool
protocol
)
)
add_component_dir(platform
platform
file
)
)
if (WIN32)
if(WIN32)
add_component_dir(platform
file.win32
)
elseif (UNIX)
)
elseif(UNIX)
add_component_dir(platform
file.posix
)
else ()
)
else()
add_component_dir(platform
file.stdio
)
)
endif()
set (ESM_UI ${CMAKE_SOURCE_DIR}/files/ui/contentselector.ui
)
set(ESM_UI ${CMAKE_SOURCE_DIR}/files/ui/contentselector.ui
)
if (USE_QT)
add_component_qt_dir (contentselector
if(USE_QT)
add_component_qt_dir(contentselector
model/modelitem model/esmfile
model/naturalsort model/contentmodel
model/loadordererror
view/combobox view/contentselector
)
add_component_qt_dir (config
)
add_component_qt_dir(config
gamesettings
launchersettings
settingsbase
)
)
add_component_qt_dir (process
add_component_qt_dir(process
processinvoker
)
)
add_component_qt_dir (misc
add_component_qt_dir(misc
helpviewer
)
)
add_component_qt_dir (files
add_component_qt_dir(files
qtconversion
)
)
QT5_WRAP_UI(ESM_UI_HDR ${ESM_UI})
endif()
if (CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
if("${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "x86_64" AND NOT APPLE)
add_definitions(-fPIC)
endif()
endif ()
endif()
include_directories(${BULLET_INCLUDE_DIRS} ${CMAKE_CURRENT_BINARY_DIR})
@ -436,7 +437,7 @@ target_link_libraries(components
smhasher
${ICU_LIBRARIES}
yaml-cpp
)
)
if(Boost_VERSION_STRING VERSION_GREATER_EQUAL 1.77.0)
target_link_libraries(components ${Boost_ATOMIC_LIBRARY})
@ -444,46 +445,46 @@ endif()
target_link_libraries(components ${BULLET_LIBRARIES})
if (WIN32)
if(WIN32)
target_link_libraries(components
${Boost_LOCALE_LIBRARY}
${Boost_ZLIB_LIBRARY})
${Boost_LOCALE_LIBRARY}
${Boost_ZLIB_LIBRARY})
endif()
if (USE_QT)
if(USE_QT)
add_library(components_qt STATIC ${COMPONENT_QT_FILES} ${ESM_UI_HDR})
target_link_libraries(components_qt components Qt5::Widgets Qt5::Core)
target_compile_definitions(components_qt PRIVATE OPENMW_DOC_BASEURL="${OPENMW_DOC_BASEURL}")
endif()
if (GIT_CHECKOUT)
add_dependencies (components git-version)
endif (GIT_CHECKOUT)
if(GIT_CHECKOUT)
add_dependencies(components git-version)
endif(GIT_CHECKOUT)
if (OSG_STATIC AND CMAKE_SYSTEM_NAME MATCHES "Linux")
if(OSG_STATIC AND CMAKE_SYSTEM_NAME MATCHES "Linux")
find_package(X11 REQUIRED COMPONENTS Xinerama Xrandr)
target_link_libraries(components ${CMAKE_DL_LIBS} X11::X11 X11::Xinerama X11::Xrandr)
find_package(Fontconfig MODULE)
if(Fontconfig_FOUND)
target_link_libraries(components Fontconfig::Fontconfig)
endif()
endif()
if (WIN32)
if(WIN32)
target_link_libraries(components shlwapi)
endif()
# Fix for not visible pthreads functions for linker with glibc 2.15
if (UNIX AND NOT APPLE)
target_link_libraries(components ${CMAKE_THREAD_LIBS_INIT})
if(UNIX AND NOT APPLE)
target_link_libraries(components ${CMAKE_THREAD_LIBS_INIT})
endif()
if (BUILD_WITH_CODE_COVERAGE)
if(BUILD_WITH_CODE_COVERAGE)
add_definitions(--coverage)
target_link_libraries(components gcov)
endif()
# Make the variable accessible for other subdirectories
set(COMPONENT_FILES ${COMPONENT_FILES} PARENT_SCOPE)
@ -492,8 +493,10 @@ target_compile_definitions(components PUBLIC BT_USE_DOUBLE_PRECISION)
if(OSG_STATIC)
unset(_osg_plugins_static_files)
add_library(components_osg_plugins INTERFACE)
foreach(_plugin ${USED_OSG_PLUGINS})
string(TOUPPER ${_plugin} _plugin_uc)
if(OPENMW_USE_SYSTEM_OSG)
list(APPEND _osg_plugins_static_files ${${_plugin_uc}_LIBRARY})
else()
@ -502,6 +505,7 @@ if(OSG_STATIC)
add_dependencies(components_osg_plugins ${${_plugin_uc}_LIBRARY})
endif()
endforeach()
# We use --whole-archive because OSG plugins use registration.
get_whole_archive_options(_opts ${_osg_plugins_static_files})
target_link_options(components_osg_plugins INTERFACE ${_opts})
@ -521,7 +525,7 @@ if(USE_QT)
set_property(TARGET components_qt PROPERTY AUTOMOC ON)
endif(USE_QT)
if (CMAKE_VERSION VERSION_GREATER_EQUAL 3.16 AND MSVC)
if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.16 AND MSVC)
target_precompile_headers(components PUBLIC
<sol/sol.hpp>

View File

@ -1,12 +1,13 @@
#ifndef OPENMW_COMPONENTS_ESM_REFID_HPP
#define OPENMW_COMPONENTS_ESM_REFID_HPP
#include <compare>
#include <components/esm4/formid.hpp>
#include <functional>
#include <iosfwd>
#include <string>
#include <string_view>
#include <components/esm4/formid.hpp>
namespace ESM
{
struct RefId

View File

@ -32,11 +32,11 @@
#include <cassert>
#include <cfloat> // FLT_MAX for gcc
#include <iostream> // FIXME: debug only
#include <stdexcept>
#include <iostream> // FIXME: debug only
#include "reader.hpp"
#include <components/esm/refid.hpp>
// #include "writer.hpp"

View File

@ -33,6 +33,7 @@
#include "formid.hpp"
#include "lighting.hpp"
#include <components/esm/defs.hpp>
#include <components/esm/refid.hpp>

View File

@ -30,6 +30,7 @@
#include <cstdint>
#include "reference.hpp" // FormId, Placement, EnableParent
#include <components/esm/defs.hpp>
#include <components/esm/refid.hpp>

View File

@ -32,6 +32,7 @@
#include <vector>
#include "formid.hpp"
#include <components/esm/defs.hpp>
#include <components/esm/refid.hpp>

View File

@ -0,0 +1,84 @@
#ifndef OPENMW_COMPONENTS_ESM4_READERUTILS
#define OPENMW_COMPONENTS_ESM4_READERUTILS
#include <components/esm4/reader.hpp>
namespace ESM4
{
struct ReaderUtils
{
/* RecordInvocable must be an invocable, takes an ESM4::Reader& as input, and outputs a boolean that indicates
if the record was read or ignored. Will be invoked for every record
GroupInvocable's invocable must take a ESM4::Reader& as input, doesn't need to output anything. Will be invoked
for every group*/
template <typename RecordInvocable, typename GroupInvocable>
static void readAll(ESM4::Reader& reader, RecordInvocable&& recordInvocable, GroupInvocable&& groupInvocable)
{
while (reader.hasMoreRecs())
{
reader.exitGroupCheck();
if (!readItem(reader, recordInvocable, groupInvocable))
break;
}
}
template <typename RecordInvocable>
static void readRecord(ESM4::Reader& reader, RecordInvocable&& recordInvocable)
{
if (!recordInvocable(reader))
reader.skipRecordData();
}
template <typename RecordInvocable, typename GroupInvocable>
static bool readGroup(ESM4::Reader& reader, RecordInvocable&& recordInvocable, GroupInvocable&& groupInvocable)
{
const ESM4::RecordHeader& header = reader.hdr();
groupInvocable(reader);
switch (static_cast<ESM4::GroupType>(header.group.type))
{
case ESM4::Grp_RecordType:
case ESM4::Grp_InteriorCell:
case ESM4::Grp_InteriorSubCell:
case ESM4::Grp_ExteriorCell:
case ESM4::Grp_ExteriorSubCell:
reader.enterGroup();
return readItem(reader, recordInvocable, groupInvocable);
case ESM4::Grp_WorldChild:
case ESM4::Grp_CellChild:
case ESM4::Grp_TopicChild:
case ESM4::Grp_CellPersistentChild:
case ESM4::Grp_CellTemporaryChild:
case ESM4::Grp_CellVisibleDistChild:
reader.adjustGRUPFormId();
reader.enterGroup();
if (!reader.hasMoreRecs())
return false;
return readItem(reader, recordInvocable, groupInvocable);
}
reader.skipGroup();
return true;
}
template <typename RecordInvocable, typename GroupInvocable>
static bool readItem(ESM4::Reader& reader, RecordInvocable&& recordInvocable, GroupInvocable&& groupInvocable)
{
if (!reader.getRecordHeader() || !reader.hasMoreRecs())
return false;
const ESM4::RecordHeader& header = reader.hdr();
if (header.record.typeId == ESM4::REC_GRUP)
return readGroup(reader, recordInvocable, groupInvocable);
readRecord(reader, recordInvocable);
return true;
}
};
}
#endif // !OPENMW_COMPONENTS_ESM4_READERUTILS

View File

@ -68,7 +68,7 @@ namespace ToUTF8
/// ASCII-only string. Otherwise returns a view to the input.
std::string_view getLegacyEnc(std::string_view input);
const StatelessUtf8Encoder* getStatelessEncoder() const { return &mImpl; }
const StatelessUtf8Encoder getStatelessEncoder() const { return mImpl; }
private:
std::string mBuffer;