#include "ESLoader.h" #include #include #include #include #include namespace ESLoader { String ReadZString(Buffer::Reader& aReader) noexcept { String zstring = String(reinterpret_cast(aReader.GetDataAtPosition())); aReader.Advance(zstring.size() + 1); return zstring; } String ReadWString(Buffer::Reader& aReader) noexcept { uint16_t stringLength = 0; aReader.ReadBytes(reinterpret_cast(&stringLength), 2); String wstring = String(reinterpret_cast(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 ESLoader::BuildRecordCollection() noexcept { if (!fs::is_directory(m_directory)) { // spdlog::warn("Data directory not found."); return nullptr; } if (!LoadLoadOrder()) { return nullptr; } return MakeUnique(); /* 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 ESLoader::LoadFiles() { auto recordCollection = MakeUnique(); 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