diff --git a/apps/launcher/utils/cellnameloader.cpp b/apps/launcher/utils/cellnameloader.cpp index d47e923eb2..8cc1191d76 100644 --- a/apps/launcher/utils/cellnameloader.cpp +++ b/apps/launcher/utils/cellnameloader.cpp @@ -1,7 +1,11 @@ #include "cellnameloader.hpp" +#include + #include +#include #include +#include #include QSet CellNameLoader::getCellNames(const QStringList& contentPaths) @@ -16,7 +20,17 @@ QSet CellNameLoader::getCellNames(const QStringList& contentPaths) continue; try { - esmReader.open(Files::pathFromQString(contentPath)); + std::filesystem::path filepath = Files::pathFromQString(contentPath); + auto stream = Files::openBinaryInputFileStream(filepath); + if (!stream->is_open()) + continue; + + const ESM::Format format = ESM::readFormat(*stream); + if (format != ESM::Format::Tes3) + continue; + + stream->seekg(0); + esmReader.open(std::move(stream), filepath); // Loop through all records while (esmReader.hasMoreRecs()) diff --git a/components/contentselector/model/contentmodel.cpp b/components/contentselector/model/contentmodel.cpp index 970b8aa0fa..08f240d27e 100644 --- a/components/contentselector/model/contentmodel.cpp +++ b/components/contentselector/model/contentmodel.cpp @@ -1,13 +1,17 @@ #include "contentmodel.hpp" #include "esmfile.hpp" +#include #include #include #include #include +#include #include +#include +#include #include ContentSelectorModel::ContentModel::ContentModel(QObject* parent, QIcon warningIcon, bool showOMWScripts) @@ -467,29 +471,59 @@ void ContentSelectorModel::ContentModel::addFiles(const QString& path, bool newf try { - ESM::ESMReader fileReader; - ToUTF8::Utf8Encoder encoder(ToUTF8::calculateEncoding(mEncoding.toStdString())); - fileReader.setEncoder(&encoder); - fileReader.open(Files::pathFromQString(dir.absoluteFilePath(path2))); - EsmFile* file = new EsmFile(path2); - - for (std::vector::const_iterator itemIter = fileReader.getGameFiles().begin(); - itemIter != fileReader.getGameFiles().end(); ++itemIter) - file->addGameFile(QString::fromUtf8(itemIter->name.c_str())); - - file->setAuthor(QString::fromUtf8(fileReader.getAuthor().c_str())); file->setDate(info.lastModified()); - file->setFormat(fileReader.getFormatVersion()); file->setFilePath(info.absoluteFilePath()); - file->setDescription(QString::fromUtf8(fileReader.getDesc().c_str())); + std::filesystem::path filepath = Files::pathFromQString(info.absoluteFilePath()); - // HACK - // Load order constraint of Bloodmoon.esm needing Tribunal.esm is missing - // from the file supplied by Bethesda, so we have to add it ourselves - if (file->fileName().compare("Bloodmoon.esm", Qt::CaseInsensitive) == 0) + auto stream = Files::openBinaryInputFileStream(filepath); + if (!stream->is_open()) + { + qWarning() << "Failed to open addon file " << info.fileName() << ": " + << std::generic_category().message(errno).c_str(); + continue; + } + const ESM::Format format = ESM::readFormat(*stream); + stream->seekg(0); + switch (format) { - file->addGameFile(QString::fromUtf8("Tribunal.esm")); + case ESM::Format::Tes3: + { + ToUTF8::Utf8Encoder encoder(ToUTF8::calculateEncoding(mEncoding.toStdString())); + ESM::ESMReader fileReader; + fileReader.setEncoder(&encoder); + fileReader.open(std::move(stream), filepath); + file->setAuthor(QString::fromUtf8(fileReader.getAuthor().c_str())); + file->setFormat(fileReader.getFormatVersion()); + file->setDescription(QString::fromUtf8(fileReader.getDesc().c_str())); + for (const auto& master : fileReader.getGameFiles()) + file->addGameFile(QString::fromUtf8(master.name.c_str())); + + // HACK + // Load order constraint of Bloodmoon.esm needing Tribunal.esm is missing + // from the file supplied by Bethesda, so we have to add it ourselves + if (file->fileName().compare("Bloodmoon.esm", Qt::CaseInsensitive) == 0) + file->addGameFile(QString::fromUtf8("Tribunal.esm")); + + break; + } + case ESM::Format::Tes4: + { + ToUTF8::StatelessUtf8Encoder encoder(ToUTF8::calculateEncoding(mEncoding.toStdString())); + ESM4::Reader reader(std::move(stream), filepath, nullptr, &encoder, true); + file->setAuthor(QString::fromUtf8(reader.getAuthor().c_str())); + file->setFormat(reader.esmVersion()); + file->setDescription(QString::fromUtf8(reader.getDesc().c_str())); + for (const auto& master : reader.getGameFiles()) + file->addGameFile(QString::fromUtf8(master.name.c_str())); + break; + } + default: + { + qWarning() << "Error reading addon file " << info.fileName() << ": unsupported ESM format " + << ESM::NAME(format).toString().c_str(); + continue; + } } // Put the file in the table