Skip to content

Commit

Permalink
feat: RecordCollection
Browse files Browse the repository at this point in the history
  • Loading branch information
RobbeBryssinck committed Jan 20, 2022
1 parent 3018ad7 commit 98c0825
Show file tree
Hide file tree
Showing 9 changed files with 107 additions and 66 deletions.
38 changes: 11 additions & 27 deletions Code/components/es_loader/ESLoader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,13 @@

ESLoader::ESLoader(String aDirectory)
: m_directory(std::move(aDirectory))
{
}

RecordCollection ESLoader::BuildRecordCollection() noexcept
{
FindFiles();
LoadFiles();
return LoadFiles();
}

void ESLoader::FindFiles()
Expand Down Expand Up @@ -46,7 +50,7 @@ bool ESLoader::LoadLoadOrder()
if (line[0] == '#' || line.empty())
continue;

Plugin plugin;
PluginData plugin;
plugin.m_filename = line;

char extensionType = line.back();
Expand Down Expand Up @@ -74,12 +78,11 @@ bool ESLoader::LoadLoadOrder()
return true;
}

void ESLoader::LoadFiles()
RecordCollection ESLoader::LoadFiles()
{
Map<uint32_t, CLMT> climates{};
Map<uint32_t, NPC> npcs{};
RecordCollection recordCollection;

for (Plugin& plugin : m_loadOrder)
for (PluginData& plugin : m_loadOrder)
{
fs::path pluginPath = GetPath(plugin.m_filename);
if (pluginPath.empty())
Expand All @@ -99,29 +102,10 @@ void ESLoader::LoadFiles()
if (!loadResult)
continue;

pluginFile.IndexRecords();

const Map<uint32_t, CLMT>& pluginClimates = pluginFile.GetClimates();
climates.insert(pluginClimates.begin(), pluginClimates.end());
//spdlog::info("Climate count in {}: {}", plugin.m_filename, pluginClimates.size());

const Map<uint32_t, NPC>& pluginNpcs = pluginFile.GetNPCs();
auto npc = pluginNpcs.find(0x13480);
if (npc != std::end(pluginNpcs))
spdlog::info("Found Faendal! {}", npc->second.m_baseStats.IsRespawn());
for (auto& [formId, npc] : pluginNpcs)
{
npcs[formId] = npc;
}
npcs.insert(pluginNpcs.begin(), pluginNpcs.end());
pluginFile.IndexRecords(recordCollection);
}

spdlog::info("All NPCs:");
for (auto& [formId, npc] : npcs)
{
if (formId == 0x13480)
spdlog::info("\tIsRespawn? {} ({:X})", npc.m_baseStats.IsRespawn(), formId);
}
return recordCollection;
}

// TODO: std::optional
Expand Down
14 changes: 9 additions & 5 deletions Code/components/es_loader/ESLoader.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@

namespace fs = std::filesystem;

class RecordCollection;

class ESLoader
{
public:
struct Plugin
struct PluginData
{
[[nodiscard]] bool IsLite() const noexcept
{
Expand All @@ -23,20 +25,22 @@ class ESLoader
bool m_isLite;
};

static String ReadZString(Buffer::Reader& aReader) noexcept;
static String ReadWString(Buffer::Reader& aReader) noexcept;

ESLoader() = delete;
ESLoader(String aDirectory);

static String ReadZString(Buffer::Reader& aReader) noexcept;
static String ReadWString(Buffer::Reader& aReader) noexcept;
RecordCollection BuildRecordCollection() noexcept;

private:
void FindFiles();
bool LoadLoadOrder();
void LoadFiles();
RecordCollection LoadFiles();

fs::path GetPath(String& aFilename);

String m_directory = "";
Vector<Plugin> m_loadOrder{};
Vector<PluginData> m_loadOrder{};
Map<String, uint8_t> m_masterFiles{};
};
2 changes: 2 additions & 0 deletions Code/components/es_loader/RecordCollection.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
#include "RecordCollection.h"

48 changes: 48 additions & 0 deletions Code/components/es_loader/RecordCollection.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
#pragma once

#include "Records/CLMT.h"
#include "Records/CONT.h"
#include "Records/NPC.h"
#include "Records/REFR.h"

class RecordCollection
{
friend class TESFile;

public:
FormEnum GetFormType(uint32_t aFormId) const noexcept
{
auto record = m_allRecords.find(aFormId);
if (record == std::end(m_allRecords))
{
spdlog::error("Record not found for form id {:X}", aFormId);
return FormEnum::EMPTY_ID;
}

return record->second.GetType();
}

REFR& GetObjectRefById(uint32_t aFormId) noexcept
{
return m_objectReferences[aFormId];
}
CLMT& GetClimateById(uint32_t aFormId) noexcept
{
return m_climates[aFormId];
}
NPC& GetNpcById(uint32_t aFormId) noexcept
{
return m_npcs[aFormId];
}
CONT& GetContainerById(uint32_t aFormId) noexcept
{
return m_containers[aFormId];
}

private:
Map<uint32_t, Record> m_allRecords{};
Map<uint32_t, REFR> m_objectReferences{};
Map<uint32_t, CLMT> m_climates{};
Map<uint32_t, NPC> m_npcs{};
Map<uint32_t, CONT> m_containers{};
};
1 change: 1 addition & 0 deletions Code/components/es_loader/Records/TESFileRecordTypes.inl
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

enum class FormEnum : uint32_t
{
EMPTY_ID = 0,
TES4 = 0x34534554,
GRUP = 0x50555247,
REFR = 0x52464552,
Expand Down
26 changes: 19 additions & 7 deletions Code/components/es_loader/TESFile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,11 @@ bool TESFile::LoadFile(const std::filesystem::path& acPath) noexcept
}

file.read(reinterpret_cast<char*>(m_buffer.GetWriteData()), fileSize);

return true;
}

bool TESFile::IndexRecords() noexcept
bool TESFile::IndexRecords(RecordCollection& aRecordCollection) noexcept
{
if (m_filename.size() == 0)
return false;
Expand All @@ -49,14 +50,14 @@ bool TESFile::IndexRecords() noexcept

while (true)
{
if (!ReadGroupOrRecord(reader))
if (!ReadGroupOrRecord(reader, aRecordCollection))
break;
}

return true;
}

bool TESFile::ReadGroupOrRecord(Buffer::Reader& aReader) noexcept
bool TESFile::ReadGroupOrRecord(Buffer::Reader& aReader, RecordCollection& aRecordCollection) noexcept
{
if (aReader.Eof())
return false;
Expand All @@ -74,7 +75,7 @@ bool TESFile::ReadGroupOrRecord(Buffer::Reader& aReader) noexcept

while (aReader.GetBytePosition() < endOfGroup)
{
ReadGroupOrRecord(aReader);
ReadGroupOrRecord(aReader, aRecordCollection);
}
}
else // Records
Expand All @@ -98,23 +99,34 @@ bool TESFile::ReadGroupOrRecord(Buffer::Reader& aReader) noexcept
//case FormEnum::ACHR:
case FormEnum::REFR: {
REFR parsedRecord = CopyAndParseRecord<REFR>(pRecord);
m_objectReferences[parsedRecord.GetFormId()] = parsedRecord;
aRecordCollection.m_objectReferences[parsedRecord.GetFormId()] = parsedRecord;
break;
}
case FormEnum::CELL:
break;
case FormEnum::CLMT: {
CLMT parsedRecord = CopyAndParseRecord<CLMT>(pRecord);
m_climates[parsedRecord.GetFormId()] = parsedRecord;
aRecordCollection.m_climates[parsedRecord.GetFormId()] = parsedRecord;
break;
}
case FormEnum::NPC_: {
NPC parsedRecord = CopyAndParseRecord<NPC>(pRecord);
m_npcs[parsedRecord.GetFormId()] = parsedRecord;
aRecordCollection.m_npcs[parsedRecord.GetFormId()] = parsedRecord;
break;
}
case FormEnum::CONT: {
CONT parsedRecord = CopyAndParseRecord<CONT>(pRecord);
aRecordCollection.m_containers[parsedRecord.GetFormId()] = parsedRecord;
break;
}
}

Record record;
record.CopyRecordData(*pRecord);
uint8_t baseId = (uint8_t)(pRecord->GetFormId() >> 24);
record.SetBaseId(GetFormIdPrefix(baseId));
aRecordCollection.m_allRecords[pRecord->GetFormId()] = *pRecord;

aReader.Advance(sizeof(Record) + size);
}

Expand Down
28 changes: 4 additions & 24 deletions Code/components/es_loader/TESFile.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#pragma once

#include <RecordCollection.h>

#include <Records/Group.h>
#include <Records/REFR.h>
#include <Records/CLMT.h>
Expand All @@ -15,7 +17,7 @@ class TESFile
void Setup(uint8_t aStandardId);
void Setup(uint16_t aLiteId);
bool LoadFile(const std::filesystem::path& acPath) noexcept;
bool IndexRecords() noexcept;
bool IndexRecords(RecordCollection& aRecordCollection) noexcept;

[[nodiscard]] bool IsLite() const noexcept
{
Expand All @@ -30,28 +32,10 @@ class TESFile
return m_filename;
}

const Map<uint32_t, REFR>& GetObjectReferences() const noexcept
{
return m_objectReferences;
}
const Map<uint32_t, CLMT>& GetClimates() const noexcept
{
return m_climates;
}
const Map<uint32_t, NPC>& GetNPCs() const noexcept
{
return m_npcs;
}

NPC& GetNpcById(uint32_t aFormId) noexcept
{
return m_npcs[aFormId];
}

[[nodiscard]] uint32_t GetFormIdPrefix(uint8_t aCurrentPrefix) const noexcept;

private:
bool ReadGroupOrRecord(Buffer::Reader& aReader) noexcept;
bool ReadGroupOrRecord(Buffer::Reader& aReader, RecordCollection& aRecordCollection) noexcept;

template <class T>
T CopyAndParseRecord(Record* pRecordHeader);
Expand All @@ -69,8 +53,4 @@ class TESFile

Map<String, uint8_t> m_masterFiles{};
Map<uint8_t, uint8_t> m_parentToMaster{};

Map<uint32_t, REFR> m_objectReferences{};
Map<uint32_t, CLMT> m_climates{};
Map<uint32_t, NPC> m_npcs{};
};
14 changes: 11 additions & 3 deletions Code/components/es_loader/TESFileTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,33 +10,41 @@ class TESFileTest : public ::testing::Test
public:
void SetUp() override;
TESFile& GetFile();
RecordCollection& GetCollection();

private:
TESFile m_file;
RecordCollection m_collection;
};

void TESFileTest::SetUp()
{
m_file.LoadFile("Data\\Skyrim.esm");
m_file.IndexRecords();
m_file.IndexRecords(m_collection);
}

TESFile& TESFileTest::GetFile()
{
return m_file;
}

RecordCollection& TESFileTest::GetCollection()
{
return m_collection;
}

TEST(TESFileTests, IndexRecords)
{
TESFile skyrimEsm;
skyrimEsm.LoadFile("Skyrim.esm");
bool result = skyrimEsm.IndexRecords();
RecordCollection collection;
bool result = skyrimEsm.IndexRecords(collection);
EXPECT_TRUE(result);
}

TEST_F(TESFileTest, LoadNPCCompressedFaendal)
{
NPC& npc = GetFile().GetNpcById(0x13480);
NPC& npc = GetCollection().GetNpcById(0x13480);
npc.ParseChunks();

EXPECT_FALSE(npc.m_baseStats.IsFemale());
Expand Down
2 changes: 2 additions & 0 deletions Code/components/es_loader/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ int main(int argc, char** argv)
{
ESLoader loader("Data\\");

RecordCollection collection = loader.BuildRecordCollection();

spdlog::info("Build file list succeeded.");

return 0;
Expand Down

0 comments on commit 98c0825

Please sign in to comment.