2013-09-29 09:11:57 +02:00
|
|
|
#include "esmloader.hpp"
|
|
|
|
#include "esmstore.hpp"
|
|
|
|
|
2022-12-30 11:28:19 +01:00
|
|
|
#include <fstream>
|
|
|
|
|
2022-12-28 20:48:25 +01:00
|
|
|
#include <components/esm/format.hpp>
|
2022-01-22 15:58:41 +01:00
|
|
|
#include <components/esm3/esmreader.hpp>
|
2022-06-01 22:53:18 +02:00
|
|
|
#include <components/esm3/readerscache.hpp>
|
2022-12-28 20:48:25 +01:00
|
|
|
#include <components/esm4/reader.hpp>
|
2022-07-03 00:02:29 +02:00
|
|
|
#include <components/files/conversion.hpp>
|
2022-12-28 20:48:25 +01:00
|
|
|
#include <components/files/openfile.hpp>
|
2023-04-07 02:14:32 +02:00
|
|
|
#include <components/misc/strings/lower.hpp>
|
2023-02-19 21:22:07 +01:00
|
|
|
#include <components/resource/resourcesystem.hpp>
|
|
|
|
|
|
|
|
#include "../mwbase/environment.hpp"
|
2013-09-29 09:11:57 +02:00
|
|
|
|
|
|
|
namespace MWWorld
|
|
|
|
{
|
|
|
|
|
2022-09-03 18:50:38 +02:00
|
|
|
EsmLoader::EsmLoader(MWWorld::ESMStore& store, ESM::ReadersCache& readers, ToUTF8::Utf8Encoder* encoder,
|
|
|
|
std::vector<int>& esmVersions)
|
2022-06-01 22:53:18 +02:00
|
|
|
: mReaders(readers)
|
2021-11-23 15:15:22 +01:00
|
|
|
, mStore(store)
|
|
|
|
, mEncoder(encoder)
|
2022-04-16 16:28:39 +02:00
|
|
|
, mDialogue(nullptr) // A content file containing INFO records without a DIAL record appends them to the
|
|
|
|
// previous file's dialogue
|
2022-09-03 18:50:38 +02:00
|
|
|
, mESMVersions(esmVersions)
|
2013-09-29 09:11:57 +02:00
|
|
|
{
|
|
|
|
}
|
2022-09-22 21:26:05 +03:00
|
|
|
|
2022-06-08 23:25:50 +02:00
|
|
|
void EsmLoader::load(const std::filesystem::path& filepath, int& index, Loading::Listener* listener)
|
2013-09-29 09:11:57 +02:00
|
|
|
{
|
2022-09-22 21:26:05 +03:00
|
|
|
|
2022-12-28 20:48:25 +01:00
|
|
|
auto stream = Files::openBinaryInputFileStream(filepath);
|
|
|
|
const ESM::Format format = ESM::readFormat(*stream);
|
|
|
|
stream->seekg(0);
|
2022-09-22 21:26:05 +03:00
|
|
|
|
2022-12-28 20:48:25 +01:00
|
|
|
switch (format)
|
|
|
|
{
|
|
|
|
case ESM::Format::Tes3:
|
|
|
|
{
|
|
|
|
const ESM::ReadersCache::BusyItem reader = mReaders.get(static_cast<std::size_t>(index));
|
|
|
|
reader->setEncoder(mEncoder);
|
|
|
|
reader->setIndex(index);
|
|
|
|
reader->open(filepath);
|
|
|
|
reader->resolveParentFileIndices(mReaders);
|
|
|
|
|
|
|
|
assert(reader->getGameFiles().size() == reader->getParentFileIndices().size());
|
|
|
|
for (std::size_t i = 0, n = reader->getParentFileIndices().size(); i < n; ++i)
|
|
|
|
if (i == static_cast<std::size_t>(reader->getIndex()))
|
|
|
|
throw std::runtime_error("File " + Files::pathToUnicodeString(reader->getName()) + " asks for parent file "
|
2022-06-01 22:53:18 +02:00
|
|
|
+ reader->getGameFiles()[i].name
|
|
|
|
+ ", but it is not available or has been loaded in the wrong order. "
|
|
|
|
"Please run the launcher to fix this issue.");
|
|
|
|
|
2022-12-28 20:48:25 +01:00
|
|
|
mESMVersions[index] = reader->getVer();
|
|
|
|
mStore.load(*reader, listener, mDialogue);
|
2022-06-01 22:53:18 +02:00
|
|
|
|
2022-12-28 20:48:25 +01:00
|
|
|
if (!mMasterFileFormat.has_value()
|
|
|
|
&& (Misc::StringUtils::ciEndsWith(reader->getName().u8string(), u8".esm")
|
|
|
|
|| Misc::StringUtils::ciEndsWith(reader->getName().u8string(), u8".omwgame")))
|
2023-02-10 13:16:52 +01:00
|
|
|
mMasterFileFormat = reader->getFormatVersion();
|
2022-12-28 20:48:25 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case ESM::Format::Tes4:
|
|
|
|
{
|
2023-05-22 18:31:08 +02:00
|
|
|
ESM4::Reader readerESM4(std::move(stream), filepath,
|
|
|
|
MWBase::Environment::get().getResourceSystem()->getVFS(), mReaders.getStatelessEncoder());
|
2023-04-07 02:14:32 +02:00
|
|
|
readerESM4.setModIndex(index);
|
|
|
|
readerESM4.updateModIndices(mNameToIndex);
|
2023-01-04 12:20:02 +01:00
|
|
|
mStore.loadESM4(readerESM4);
|
2023-01-02 19:20:03 +01:00
|
|
|
break;
|
2022-12-28 20:48:25 +01:00
|
|
|
}
|
|
|
|
}
|
2023-04-07 02:14:32 +02:00
|
|
|
mNameToIndex[Misc::StringUtils::lowerCase(Files::pathToUnicodeString(filepath.filename()))] = index;
|
2013-09-29 09:11:57 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
} /* namespace MWWorld */
|