F4MP/tiltedcode/Code/components/es_loader/ESLoader.cpp

151 lines
3.6 KiB
C++
Raw Normal View History

#include "ESLoader.h"
#include <filesystem>
#include <fstream>
#include <Records/CLMT.h>
#include <Records/NPC.h>
#include <Records/REFR.h>
namespace ESLoader
{
String ReadZString(Buffer::Reader& aReader) noexcept
{
String zstring = String(reinterpret_cast<const char*>(aReader.GetDataAtPosition()));
aReader.Advance(zstring.size() + 1);
return zstring;
}
String ReadWString(Buffer::Reader& aReader) noexcept
{
uint16_t stringLength = 0;
aReader.ReadBytes(reinterpret_cast<uint8_t*>(&stringLength), 2);
String wstring = String(reinterpret_cast<const char*>(aReader.GetDataAtPosition()), stringLength);
aReader.Advance(stringLength);
return wstring;
}
ESLoader::ESLoader()
{
m_directory = fs::current_path() / "Data"; //< Keep upper case to match Skyrim's file system
}
UniquePtr<RecordCollection> ESLoader::BuildRecordCollection() noexcept
{
if (!fs::is_directory(m_directory))
{
// spdlog::warn("Data directory not found.");
return nullptr;
}
if (!LoadLoadOrder())
{
return nullptr;
}
return MakeUnique<RecordCollection>();
/*
auto recordCollection = LoadFiles();
recordCollection->BuildReferences();
return std::move(recordCollection);
*/
}
bool ESLoader::LoadLoadOrder()
{
std::ifstream loadOrderFile;
auto loadOrderPath = m_directory / "loadorder.txt";
loadOrderFile.open(loadOrderPath.c_str());
if (loadOrderFile.fail())
{
spdlog::warn("Failed to open loadorder.txt");
return false;
}
uint8_t standardId = 0x0;
uint16_t liteId = 0x0;
while (!loadOrderFile.eof())
{
String line;
std::getline(loadOrderFile, line);
if (line[0] == '#' || line.empty())
continue;
PluginData plugin;
plugin.m_filename = line;
// On Linux, the carriage return won't be taken into account
line.erase(std::remove(line.begin(), line.end(), '\r'), line.end());
char extensionType = line.back();
switch (extensionType)
{
case 'm': m_masterFiles[line] = standardId;
case 'p':
plugin.m_standardId = standardId;
standardId += 0x01;
plugin.m_isLite = false;
m_loadOrder.push_back(plugin);
break;
case 'l':
plugin.m_liteId = liteId;
liteId += 0x0001;
plugin.m_isLite = true;
m_loadOrder.push_back(plugin);
break;
default: spdlog::error("Extension in loadorder.txt not recognized: {}", line);
}
}
return true;
}
UniquePtr<RecordCollection> ESLoader::LoadFiles()
{
auto recordCollection = MakeUnique<RecordCollection>();
for (PluginData& plugin : m_loadOrder)
{
fs::path pluginPath = GetPath(plugin.m_filename);
if (pluginPath.empty())
{
spdlog::warn("Path to plugin file not found: {}", plugin.m_filename);
continue;
}
TESFile pluginFile(m_masterFiles);
if (plugin.IsLite())
pluginFile.Setup(plugin.m_liteId);
else
pluginFile.Setup(plugin.m_standardId);
bool loadResult = pluginFile.LoadFile(pluginPath);
if (!loadResult)
continue;
pluginFile.IndexRecords(*recordCollection);
}
return recordCollection;
}
fs::path ESLoader::GetPath(String& aFilename)
{
for (const auto& entry : fs::directory_iterator(m_directory))
{
String filename = entry.path().filename().string().c_str();
if (filename == aFilename)
return entry.path();
}
return fs::path();
}
} // namespace ESLoader