Skip to content

Commit

Permalink
feat: load world data on the server
Browse files Browse the repository at this point in the history
  • Loading branch information
Yamashi committed Feb 3, 2022
1 parent 5ccf173 commit e6d8d28
Show file tree
Hide file tree
Showing 8 changed files with 126 additions and 12 deletions.
9 changes: 9 additions & 0 deletions Code/components/es_loader/ESLoaderTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -111,4 +111,13 @@ TEST_F(ESLoaderTest, GetGameSettingFloatBribeScale)
EXPECT_EQ(bribeSetting.m_value.m_float, 0.5f);
}

TEST_F(ESLoaderTest, GetWorldTamriel)
{
const auto& pCollection = GetCollection();

const WRLD& tamrielWorld = pCollection->GetWorldById(60);

EXPECT_EQ(tamrielWorld.m_editorId, "Tamriel");
}

} // namespace
6 changes: 6 additions & 0 deletions Code/components/es_loader/RecordCollection.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include "Records/NPC.h"
#include "Records/REFR.h"
#include "Records/GMST.h"
#include "Records/WRLD.h"

class RecordCollection
{
Expand Down Expand Up @@ -43,6 +44,10 @@ class RecordCollection
{
return m_gameSettings[aFormId];
}
WRLD& GetWorldById(uint32_t aFormId) noexcept
{
return m_worlds[aFormId];
}

private:
Map<uint32_t, Record> m_allRecords{};
Expand All @@ -51,4 +56,5 @@ class RecordCollection
Map<uint32_t, NPC> m_npcs{};
Map<uint32_t, CONT> m_containers{};
Map<uint32_t, GMST> m_gameSettings{};
Map<uint32_t, WRLD> m_worlds{};
};
12 changes: 12 additions & 0 deletions Code/components/es_loader/Records/Chunks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -166,4 +166,16 @@ MAST::MAST(Buffer::Reader& aReader)
m_masterName = ESLoader::ReadZString(aReader);
}

WCTR::WCTR(Buffer::Reader& aReader)
{
aReader.ReadBytes(reinterpret_cast<uint8_t*>(&m_x), 2);
aReader.ReadBytes(reinterpret_cast<uint8_t*>(&m_y), 2);
}

DNAM::DNAM(Buffer::Reader& aReader)
{
aReader.ReadBytes(reinterpret_cast<uint8_t*>(&m_landLevel), 4);
aReader.ReadBytes(reinterpret_cast<uint8_t*>(&m_waterLevel), 4);
}

} // namespace
22 changes: 22 additions & 0 deletions Code/components/es_loader/Records/Chunks.h
Original file line number Diff line number Diff line change
Expand Up @@ -310,4 +310,26 @@ struct TypedValue
};
};

struct WCTR
{
WCTR()
{
}
WCTR(Buffer::Reader& aReader);

int16_t m_x;
int16_t m_y;
};

struct DNAM
{
DNAM()
{
}
DNAM(Buffer::Reader& aReader);

float m_landLevel;
float m_waterLevel;
};

} // namespace
22 changes: 13 additions & 9 deletions Code/components/es_loader/Records/TESFileRecordTypes.inl
Original file line number Diff line number Diff line change
@@ -1,17 +1,21 @@
#pragma once

#define EXPAND_TO_INTEGER(name) ((#name)[0]) | ((#name)[1]) << 8 | ((#name)[2]) << 16 | ((#name)[3]) << 24
#define DECLARE_FORM_TYPE(name) name = EXPAND_TO_INTEGER(name)

enum class FormEnum : uint32_t
{
EMPTY_ID = 0,
TES4 = 0x34534554,
GRUP = 0x50555247,
REFR = 0x52464552,
ACHR = 0x52484341,
CELL = 0x4C4C4543,
CLMT = 0x544D4C43,
CONT = 0x544E4F43,
NPC_ = 0x5F43504E,
GMST = 0x54534D47,
DECLARE_FORM_TYPE(TES4),
DECLARE_FORM_TYPE(GRUP),
DECLARE_FORM_TYPE(REFR),
DECLARE_FORM_TYPE(ACHR),
DECLARE_FORM_TYPE(CELL),
DECLARE_FORM_TYPE(CLMT),
DECLARE_FORM_TYPE(CONT),
DECLARE_FORM_TYPE(NPC_),
DECLARE_FORM_TYPE(GMST),
DECLARE_FORM_TYPE(WRLD)
};

enum class ChunkId : uint32_t
Expand Down
36 changes: 36 additions & 0 deletions Code/components/es_loader/Records/WRLD.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
#include "WRLD.h"

#include <ESLoader.h>

void WRLD::ParseChunks(WRLD& aSourceRecord, Map<uint8_t, uint32_t>& aParentToFormIdPrefix) noexcept
{
aSourceRecord.IterateChunks([&](ChunkId aChunkId, Buffer::Reader& aReader) {
switch (aChunkId)
{
case ChunkId::EDID_ID:
m_editorId = ESLoader::ReadZString(aReader);
break;
case ChunkId::WCTR_ID:
m_centerCell = Chunks::WCTR(aReader);
break;
case ChunkId::CNAM_ID:
aReader.ReadBytes(reinterpret_cast<uint8_t*>(&m_climateId), sizeof(m_climateId));
break;
case ChunkId::DNAM_ID:
m_landData = Chunks::DNAM(aReader);
break;
case ChunkId::WNAM_ID: {
uint32_t id = 0;
aReader.ReadBytes(reinterpret_cast<uint8_t*>(&id), sizeof(id));
m_parentId = id;
}
break;

This comment has been minimized.

Copy link
@Dragonisser

Dragonisser Feb 3, 2022

Collaborator

Is this "break;" supposed to be outside the brackets?

This comment has been minimized.

Copy link
@maximegmd

maximegmd Feb 3, 2022

Member

yup, brackets are here so that id doesn't spill to other cases

case ChunkId::ZNAM_ID:
aReader.ReadBytes(reinterpret_cast<uint8_t*>(&m_musicId), sizeof(m_musicId));
break;
case ChunkId::NAMA_ID:
aReader.ReadBytes(reinterpret_cast<uint8_t*>(&m_lodMultiplier), sizeof(m_lodMultiplier));
break;
}
});
}
21 changes: 21 additions & 0 deletions Code/components/es_loader/Records/WRLD.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#pragma once

#include "Record.h"
#include "Chunks.h"

// https://en.uesp.net/wiki/Skyrim_Mod:Mod_File_Format/WRLD
class WRLD : public Record
{
public:
static constexpr FormEnum kType = FormEnum::WRLD;

String m_editorId = "";
std::optional<Chunks::WCTR> m_centerCell;
std::optional<uint32_t> m_climateId;
std::optional<Chunks::DNAM> m_landData;
std::optional<uint32_t> m_parentId;
uint32_t m_musicId;
float m_lodMultiplier;

void ParseChunks(WRLD& aSourceRecord, Map<uint8_t, uint32_t>& aParentToFormIdPrefix) noexcept;
};
10 changes: 7 additions & 3 deletions Code/components/es_loader/TESFile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,10 @@ bool TESFile::ReadGroupOrRecord(Buffer::Reader& aReader, RecordCollection& aReco
aRecordCollection.m_gameSettings[parsedRecord.GetFormId()] = parsedRecord;
break;
}
case FormEnum::WRLD: {
WRLD parsedRecord = CopyAndParseRecord<WRLD>(pRecord);
aRecordCollection.m_worlds[parsedRecord.GetFormId()] = parsedRecord;
}
}

//pRecord->DiscoverChunks();
Expand All @@ -136,7 +140,7 @@ bool TESFile::ReadGroupOrRecord(Buffer::Reader& aReader, RecordCollection& aReco
{
Record record;
record.CopyRecordData(*pRecord);
record.SetBaseId(TESFile::GetFormIdPrefix(pRecord->GetFormId(), m_parentToFormIdPrefix));
record.SetBaseId(GetFormIdPrefix(pRecord->GetFormId(), m_parentToFormIdPrefix));
aRecordCollection.m_allRecords[pRecord->GetFormId()] = *pRecord;
}

Expand All @@ -163,8 +167,8 @@ T TESFile::CopyAndParseRecord(Record* pRecordHeader)

uint32_t TESFile::GetFormIdPrefix(uint32_t aFormId, Map<uint8_t, uint32_t>& aParentToFormIdPrefix) noexcept
{
uint8_t baseId = (uint8_t)(aFormId >> 24);
auto masterId = aParentToFormIdPrefix.find(baseId);
auto baseId = (uint8_t)(aFormId >> 24);
const auto masterId = aParentToFormIdPrefix.find(baseId);

if (masterId == std::end(aParentToFormIdPrefix))
{
Expand Down

0 comments on commit e6d8d28

Please sign in to comment.