mirror of
https://github.com/PrismLauncher/PrismLauncher.git
synced 2025-09-13 14:06:07 -04:00
Improve mod parsing
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
This commit is contained in:
parent
94f3fd28b9
commit
428f69b387
@ -244,35 +244,23 @@ void World::readFromZip(const QFileInfo& file)
|
|||||||
{
|
{
|
||||||
MMCZip::ArchiveReader r(file.absoluteFilePath());
|
MMCZip::ArchiveReader r(file.absoluteFilePath());
|
||||||
|
|
||||||
if (m_isValid = r.collectFiles(); !m_isValid) {
|
m_isValid = false;
|
||||||
return;
|
r.parse([this](MMCZip::ArchiveReader::File* file, bool& stop) {
|
||||||
}
|
const QString levelDat = "level.dat";
|
||||||
|
auto filePath = file->filename();
|
||||||
QString path;
|
|
||||||
const QString levelDat = "level.dat";
|
|
||||||
for (auto filePath : r.getFiles()) {
|
|
||||||
QFileInfo fi(filePath);
|
QFileInfo fi(filePath);
|
||||||
if (fi.fileName().compare(levelDat, Qt::CaseInsensitive) == 0) {
|
if (fi.fileName().compare(levelDat, Qt::CaseInsensitive) == 0) {
|
||||||
m_containerOffsetPath = filePath.chopped(levelDat.length());
|
m_containerOffsetPath = filePath.chopped(levelDat.length());
|
||||||
path = filePath;
|
if (!m_containerOffsetPath.isEmpty()) {
|
||||||
break;
|
return false;
|
||||||
|
}
|
||||||
|
m_levelDatTime = file->dateTime();
|
||||||
|
loadFromLevelDat(file->readAll());
|
||||||
|
m_isValid = true;
|
||||||
|
stop = true;
|
||||||
}
|
}
|
||||||
}
|
return true;
|
||||||
|
});
|
||||||
if (m_isValid = !m_containerOffsetPath.isEmpty(); !m_isValid) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto zippedFile = r.goToFile(path);
|
|
||||||
if (m_isValid = !!zippedFile; !m_isValid) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// read the install profile
|
|
||||||
m_levelDatTime = zippedFile->dateTime();
|
|
||||||
if (!m_isValid) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
loadFromLevelDat(zippedFile->readAll());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool World::install(const QString& to, const QString& name)
|
bool World::install(const QString& to, const QString& name)
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#include "LocalModParseTask.h"
|
#include "LocalModParseTask.h"
|
||||||
|
|
||||||
#include <qdcss.h>
|
#include <qdcss.h>
|
||||||
|
#include <qstringview.h>
|
||||||
#include <toml++/toml.h>
|
#include <toml++/toml.h>
|
||||||
#include <QJsonArray>
|
#include <QJsonArray>
|
||||||
#include <QJsonDocument>
|
#include <QJsonDocument>
|
||||||
@ -13,6 +14,7 @@
|
|||||||
#include "Json.h"
|
#include "Json.h"
|
||||||
#include "archive/ArchiveReader.h"
|
#include "archive/ArchiveReader.h"
|
||||||
#include "minecraft/mod/ModDetails.h"
|
#include "minecraft/mod/ModDetails.h"
|
||||||
|
#include "modplatform/ModIndex.h"
|
||||||
#include "settings/INIFile.h"
|
#include "settings/INIFile.h"
|
||||||
|
|
||||||
static const QRegularExpression s_newlineRegex("\r\n|\n|\r");
|
static const QRegularExpression s_newlineRegex("\r\n|\n|\r");
|
||||||
@ -470,35 +472,32 @@ bool processZIP(Mod& mod, [[maybe_unused]] ProcessingLevel level)
|
|||||||
ModDetails details;
|
ModDetails details;
|
||||||
|
|
||||||
MMCZip::ArchiveReader zip(mod.fileinfo().filePath());
|
MMCZip::ArchiveReader zip(mod.fileinfo().filePath());
|
||||||
if (!zip.collectFiles())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
auto isForge = zip.exists("META-INF/mods.toml");
|
bool baseForgePopulated = false;
|
||||||
if (isForge || zip.exists("META-INF/neoforge.mods.toml")) {
|
bool isNilMod = false;
|
||||||
{
|
bool isValid = false;
|
||||||
std::unique_ptr<MMCZip::ArchiveReader::File> file;
|
QString manifestVersion = {};
|
||||||
if (isForge) {
|
QByteArray nilData = {};
|
||||||
file = zip.goToFile("META-INF/mods.toml");
|
QString nilFilePath = {};
|
||||||
} else {
|
|
||||||
file = zip.goToFile("META-INF/neoforge.mods.toml");
|
|
||||||
}
|
|
||||||
if (!file) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
details = ReadMCModTOML(file->readAll());
|
if (!zip.parse([&details, &baseForgePopulated, &manifestVersion, &isValid, &nilData, &isNilMod, &nilFilePath](
|
||||||
}
|
MMCZip::ArchiveReader::File* file, bool& stop) {
|
||||||
|
auto filePath = file->filename();
|
||||||
|
|
||||||
// to replace ${file.jarVersion} with the actual version, as needed
|
if (filePath == "META-INF/mods.toml" || filePath == "META-INF/neoforge.mods.toml") {
|
||||||
if (details.version == "${file.jarVersion}") {
|
details = ReadMCModTOML(file->readAll());
|
||||||
if (zip.exists("META-INF/MANIFEST.MF")) {
|
isValid = true;
|
||||||
auto file = zip.goToFile("META-INF/MANIFEST.MF");
|
if (details.version == "${file.jarVersion}" && !manifestVersion.isEmpty()) {
|
||||||
if (!file) {
|
details.version = manifestVersion;
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
stop = details.version != "${file.jarVersion}";
|
||||||
|
baseForgePopulated = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (filePath == "META-INF/MANIFEST.MF") {
|
||||||
// quick and dirty line-by-line parser
|
// quick and dirty line-by-line parser
|
||||||
auto manifestLines = QString(file->readAll()).split(s_newlineRegex);
|
auto manifestLines = QString(file->readAll()).split(s_newlineRegex);
|
||||||
QString manifestVersion = "";
|
manifestVersion = "";
|
||||||
for (auto& line : manifestLines) {
|
for (auto& line : manifestLines) {
|
||||||
if (line.startsWith("Implementation-Version: ", Qt::CaseInsensitive)) {
|
if (line.startsWith("Implementation-Version: ", Qt::CaseInsensitive)) {
|
||||||
manifestVersion = line.remove("Implementation-Version: ", Qt::CaseInsensitive);
|
manifestVersion = line.remove("Implementation-Version: ", Qt::CaseInsensitive);
|
||||||
@ -511,79 +510,64 @@ bool processZIP(Mod& mod, [[maybe_unused]] ProcessingLevel level)
|
|||||||
if (manifestVersion.contains("task ':jar' property 'archiveVersion'") || manifestVersion == "") {
|
if (manifestVersion.contains("task ':jar' property 'archiveVersion'") || manifestVersion == "") {
|
||||||
manifestVersion = "NONE";
|
manifestVersion = "NONE";
|
||||||
}
|
}
|
||||||
|
if (baseForgePopulated) {
|
||||||
details.version = manifestVersion;
|
details.version = manifestVersion;
|
||||||
|
stop = true;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (filePath == "mcmod.info") {
|
||||||
|
details = ReadMCModInfo(file->readAll());
|
||||||
|
isValid = true;
|
||||||
|
stop = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (filePath == "quilt.mod.json") {
|
||||||
|
details = ReadQuiltModInfo(file->readAll());
|
||||||
|
isValid = true;
|
||||||
|
stop = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (filePath == "fabric.mod.json") {
|
||||||
|
details = ReadFabricModInfo(file->readAll());
|
||||||
|
isValid = true;
|
||||||
|
stop = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (filePath == "forgeversion.properties") {
|
||||||
|
details = ReadForgeInfo(file->readAll());
|
||||||
|
isValid = true;
|
||||||
|
stop = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (filePath == "META-INF/nil/mappings.json") {
|
||||||
|
// nilloader uses the filename of the metadata file for the modid, so we can't know the exact filename
|
||||||
|
// thankfully, there is a good file to use as a canary so we don't look for nil meta all the time
|
||||||
|
isNilMod = true;
|
||||||
|
stop = !nilFilePath.isEmpty();
|
||||||
|
file->skip();
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
mod.setDetails(details);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
} else if (zip.exists("mcmod.info")) {
|
|
||||||
auto file = zip.goToFile("mcmod.info");
|
|
||||||
if (!file) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
details = ReadMCModInfo(file->readAll());
|
|
||||||
|
|
||||||
mod.setDetails(details);
|
|
||||||
return true;
|
|
||||||
} else if (zip.exists("quilt.mod.json")) {
|
|
||||||
auto file = zip.goToFile("quilt.mod.json");
|
|
||||||
if (!file) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
details = ReadQuiltModInfo(file->readAll());
|
|
||||||
|
|
||||||
mod.setDetails(details);
|
|
||||||
return true;
|
|
||||||
} else if (zip.exists("fabric.mod.json")) {
|
|
||||||
auto file = zip.goToFile("fabric.mod.json");
|
|
||||||
if (!file) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
details = ReadFabricModInfo(file->readAll());
|
|
||||||
|
|
||||||
mod.setDetails(details);
|
|
||||||
return true;
|
|
||||||
} else if (zip.exists("forgeversion.properties")) {
|
|
||||||
auto file = zip.goToFile("forgeversion.properties");
|
|
||||||
if (!file) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
details = ReadForgeInfo(file->readAll());
|
|
||||||
|
|
||||||
mod.setDetails(details);
|
|
||||||
return true;
|
|
||||||
} else if (zip.exists("META-INF/nil/mappings.json")) {
|
|
||||||
// nilloader uses the filename of the metadata file for the modid, so we can't know the exact filename
|
|
||||||
// thankfully, there is a good file to use as a canary so we don't look for nil meta all the time
|
|
||||||
|
|
||||||
QString foundNilMeta;
|
|
||||||
for (auto& fname : zip.getFiles()) {
|
|
||||||
// nilmods can shade nilloader to be able to run as a standalone agent - which includes nilloader's own meta file
|
// nilmods can shade nilloader to be able to run as a standalone agent - which includes nilloader's own meta file
|
||||||
if (fname.endsWith(".nilmod.css") && fname != "nilloader.nilmod.css") {
|
if (filePath.endsWith(".nilmod.css") && filePath != "nilloader.nilmod.css") {
|
||||||
foundNilMeta = fname;
|
nilData = file->readAll();
|
||||||
break;
|
nilFilePath = filePath;
|
||||||
|
stop = isNilMod;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
file->skip();
|
||||||
|
|
||||||
if (zip.exists(foundNilMeta)) {
|
|
||||||
auto file = zip.goToFile(foundNilMeta);
|
|
||||||
if (!file) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
details = ReadNilModInfo(file->readAll(), foundNilMeta);
|
|
||||||
|
|
||||||
mod.setDetails(details);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
})) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (isNilMod) {
|
||||||
|
details = ReadNilModInfo(nilData, nilFilePath);
|
||||||
|
isValid = true;
|
||||||
|
}
|
||||||
|
if (isValid) {
|
||||||
|
mod.setDetails(details);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false; // no valid mod found in archive
|
return false; // no valid mod found in archive
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -90,35 +90,25 @@ bool processZIP(TexturePack& pack, ProcessingLevel level)
|
|||||||
Q_ASSERT(pack.type() == ResourceType::ZIPFILE);
|
Q_ASSERT(pack.type() == ResourceType::ZIPFILE);
|
||||||
|
|
||||||
MMCZip::ArchiveReader zip(pack.fileinfo().filePath());
|
MMCZip::ArchiveReader zip(pack.fileinfo().filePath());
|
||||||
|
bool packProcessed = false;
|
||||||
|
bool iconProcessed = false;
|
||||||
|
|
||||||
{
|
return zip.parse([&packProcessed, &iconProcessed, &pack, level](MMCZip::ArchiveReader::File* file, bool& stop) {
|
||||||
auto file = zip.goToFile("pack.txt");
|
if (!packProcessed && file->filename() == "pack.txt") {
|
||||||
if (file) {
|
packProcessed = true;
|
||||||
auto data = file->readAll();
|
auto data = file->readAll();
|
||||||
|
stop = packProcessed && (iconProcessed || level == ProcessingLevel::BasicInfoOnly);
|
||||||
bool packTXT_result = TexturePackUtils::processPackTXT(pack, std::move(data));
|
return TexturePackUtils::processPackTXT(pack, std::move(data));
|
||||||
|
|
||||||
if (!packTXT_result) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
if (!iconProcessed && file->filename() == "pack.png") {
|
||||||
|
iconProcessed = true;
|
||||||
if (level == ProcessingLevel::BasicInfoOnly) {
|
auto data = file->readAll();
|
||||||
|
stop = packProcessed && iconProcessed;
|
||||||
|
return TexturePackUtils::processPackPNG(pack, std::move(data));
|
||||||
|
}
|
||||||
|
file->skip();
|
||||||
return true;
|
return true;
|
||||||
}
|
});
|
||||||
|
|
||||||
auto file = zip.goToFile("pack.png");
|
|
||||||
if (file) {
|
|
||||||
auto data = file->readAll();
|
|
||||||
|
|
||||||
bool packPNG_result = TexturePackUtils::processPackPNG(pack, std::move(data));
|
|
||||||
|
|
||||||
if (!packPNG_result) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool processPackTXT(TexturePack& pack, QByteArray&& raw_data)
|
bool processPackTXT(TexturePack& pack, QByteArray&& raw_data)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user