From 6a6fe60a5beddd29de48939d5726ca5671d3d01f Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Mon, 28 Oct 2024 10:29:49 +0000 Subject: [PATCH] Revert "Use non-mod metadata in ModrinthPackExportTask" Out-of-scope Signed-off-by: TheKodeToad --- launcher/minecraft/MinecraftInstance.cpp | 14 +- launcher/minecraft/MinecraftInstance.h | 1 - .../modplatform/flame/FlamePackExportTask.cpp | 40 ++-- .../modplatform/flame/FlamePackExportTask.h | 13 +- launcher/modplatform/helpers/HashUtils.cpp | 2 +- .../modrinth/ModrinthPackExportTask.cpp | 188 +++++++----------- .../modrinth/ModrinthPackExportTask.h | 14 +- launcher/ui/MainWindow.cpp | 27 +-- launcher/ui/dialogs/ExportPackDialog.cpp | 11 +- launcher/ui/dialogs/ExportPackDialog.h | 5 +- 10 files changed, 141 insertions(+), 174 deletions(-) diff --git a/launcher/minecraft/MinecraftInstance.cpp b/launcher/minecraft/MinecraftInstance.cpp index 87bd1b703..2b24ec090 100644 --- a/launcher/minecraft/MinecraftInstance.cpp +++ b/launcher/minecraft/MinecraftInstance.cpp @@ -522,8 +522,7 @@ QStringList MinecraftInstance::javaArguments() if (javaVersion.isModular() && shouldApplyOnlineFixes()) // allow reflective access to java.net - required by the skin fix - args << "--add-opens" - << "java.base/java.net=ALL-UNNAMED"; + args << "--add-opens" << "java.base/java.net=ALL-UNNAMED"; return args; } @@ -797,10 +796,8 @@ QString MinecraftInstance::createLaunchScript(AuthSessionPtr session, MinecraftT QStringList MinecraftInstance::verboseDescription(AuthSessionPtr session, MinecraftTarget::Ptr targetToJoin) { QStringList out; - out << "Main Class:" - << " " + getMainClass() << ""; - out << "Native path:" - << " " + getNativePath() << ""; + out << "Main Class:" << " " + getMainClass() << ""; + out << "Native path:" << " " + getNativePath() << ""; auto profile = m_components->getProfile(); @@ -1230,11 +1227,6 @@ std::shared_ptr MinecraftInstance::shaderPackList() return m_shader_pack_list; } -QList> MinecraftInstance::resourceLists() -{ - return { loaderModList(), coreModList(), nilModList(), resourcePackList(), texturePackList(), shaderPackList() }; -} - std::shared_ptr MinecraftInstance::worldList() { if (!m_world_list) { diff --git a/launcher/minecraft/MinecraftInstance.h b/launcher/minecraft/MinecraftInstance.h index 5d9bb45ef..75e97ae45 100644 --- a/launcher/minecraft/MinecraftInstance.h +++ b/launcher/minecraft/MinecraftInstance.h @@ -116,7 +116,6 @@ class MinecraftInstance : public BaseInstance { std::shared_ptr resourcePackList(); std::shared_ptr texturePackList(); std::shared_ptr shaderPackList(); - QList> resourceLists(); std::shared_ptr worldList(); std::shared_ptr gameOptionsModel(); diff --git a/launcher/modplatform/flame/FlamePackExportTask.cpp b/launcher/modplatform/flame/FlamePackExportTask.cpp index 61eaa826d..d661f1f05 100644 --- a/launcher/modplatform/flame/FlamePackExportTask.cpp +++ b/launcher/modplatform/flame/FlamePackExportTask.cpp @@ -28,7 +28,6 @@ #include #include #include -#include #include "Application.h" #include "Json.h" #include "MMCZip.h" @@ -40,23 +39,24 @@ #include "tasks/Task.h" const QString FlamePackExportTask::TEMPLATE = "
  • {name}{authors}
  • \n"; -const QStringList FlamePackExportTask::FILE_EXTENSIONS({ "jar", "litemod", "zip" }); +const QStringList FlamePackExportTask::FILE_EXTENSIONS({ "jar", "zip" }); -FlamePackExportTask::FlamePackExportTask(QString name, - QString version, - QString author, +FlamePackExportTask::FlamePackExportTask(const QString& name, + const QString& version, + const QString& author, bool optionalFiles, - MinecraftInstancePtr instance, - QString output, + InstancePtr instance, + const QString& output, MMCZip::FilterFunction filter) - : name(std::move(name)) - , version(std::move(version)) - , author(std::move(author)) + : name(name) + , version(version) + , author(author) , optionalFiles(optionalFiles) - , instance(std::move(instance)) - , gameRoot(this->instance->gameRoot()) - , output(std::move(output)) - , filter(std::move(filter)) + , instance(instance) + , mcInstance(dynamic_cast(instance.get())) + , gameRoot(instance->gameRoot()) + , output(output) + , filter(filter) {} void FlamePackExportTask::executeTask() @@ -90,7 +90,11 @@ void FlamePackExportTask::collectFiles() pendingHashes.clear(); resolvedFiles.clear(); - collectHashes(); + if (mcInstance != nullptr) { + mcInstance->loaderModList()->update(); + connect(mcInstance->loaderModList().get(), &ModFolderModel::updateFinished, this, &FlamePackExportTask::collectHashes); + } else + collectHashes(); } void FlamePackExportTask::collectHashes() @@ -98,7 +102,7 @@ void FlamePackExportTask::collectHashes() setAbortable(true); setStatus(tr("Finding file hashes...")); setProgress(1, 5); - auto allMods = instance->loaderModList()->allMods(); + auto allMods = mcInstance->loaderModList()->allMods(); ConcurrentTask::Ptr hashingTask( new ConcurrentTask(this, "MakeHashesTask", APPLICATION->settings()->get("NumberOfConcurrentTasks").toInt())); task.reset(hashingTask); @@ -375,9 +379,9 @@ QByteArray FlamePackExportTask::generateIndex() obj["version"] = version; obj["author"] = author; obj["overrides"] = "overrides"; - if (instance) { + if (mcInstance) { QJsonObject version; - auto profile = instance->getPackProfile(); + auto profile = mcInstance->getPackProfile(); // collect all supported components const ComponentPtr minecraft = profile->getComponent("net.minecraft"); const ComponentPtr quilt = profile->getComponent("org.quiltmc.quilt-loader"); diff --git a/launcher/modplatform/flame/FlamePackExportTask.h b/launcher/modplatform/flame/FlamePackExportTask.h index 83d870b09..b11eb17fa 100644 --- a/launcher/modplatform/flame/FlamePackExportTask.h +++ b/launcher/modplatform/flame/FlamePackExportTask.h @@ -28,12 +28,12 @@ class FlamePackExportTask : public Task { Q_OBJECT public: - FlamePackExportTask(QString name, - QString version, - QString author, + FlamePackExportTask(const QString& name, + const QString& version, + const QString& author, bool optionalFiles, - MinecraftInstancePtr instance, - QString output, + InstancePtr instance, + const QString& output, MMCZip::FilterFunction filter); protected: @@ -47,7 +47,8 @@ class FlamePackExportTask : public Task { // inputs const QString name, version, author; const bool optionalFiles; - const MinecraftInstancePtr instance; + const InstancePtr instance; + MinecraftInstance* mcInstance; const QDir gameRoot; const QString output; const MMCZip::FilterFunction filter; diff --git a/launcher/modplatform/helpers/HashUtils.cpp b/launcher/modplatform/helpers/HashUtils.cpp index 1db7ca453..a3b8d904c 100644 --- a/launcher/modplatform/helpers/HashUtils.cpp +++ b/launcher/modplatform/helpers/HashUtils.cpp @@ -115,7 +115,7 @@ QString hash(QIODevice* device, Algorithm type) QCryptographicHash hash(alg); if (!hash.addData(device)) - qCritical() << "Failed to read file to create hash!"; + qCritical() << "Failed to read JAR to create hash!"; Q_ASSERT(hash.result().length() == hash.hashLength(alg)); auto result = hash.result().toHex(); diff --git a/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp b/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp index c1333963e..d103170af 100644 --- a/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp +++ b/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp @@ -31,23 +31,25 @@ #include "modplatform/helpers/HashUtils.h" #include "tasks/Task.h" +const QStringList ModrinthPackExportTask::PREFIXES({ "mods/", "coremods/", "resourcepacks/", "texturepacks/", "shaderpacks/" }); const QStringList ModrinthPackExportTask::FILE_EXTENSIONS({ "jar", "litemod", "zip" }); -ModrinthPackExportTask::ModrinthPackExportTask(QString name, - QString version, - QString summary, +ModrinthPackExportTask::ModrinthPackExportTask(const QString& name, + const QString& version, + const QString& summary, bool optionalFiles, - MinecraftInstancePtr instance, - QString output, + InstancePtr instance, + const QString& output, MMCZip::FilterFunction filter) - : name(std::move(name)) - , version(std::move(version)) - , summary(std::move(summary)) + : name(name) + , version(version) + , summary(summary) , optionalFiles(optionalFiles) - , instance(std::move(instance)) - , gameRoot(this->instance->gameRoot()) - , output(std::move(output)) - , filter(std::move(filter)) + , instance(instance) + , mcInstance(dynamic_cast(instance.get())) + , gameRoot(instance->gameRoot()) + , output(output) + , filter(filter) {} void ModrinthPackExportTask::executeTask() @@ -81,102 +83,64 @@ void ModrinthPackExportTask::collectFiles() pendingHashes.clear(); resolvedFiles.clear(); - collectHashes(); + if (mcInstance) { + mcInstance->loaderModList()->update(); + connect(mcInstance->loaderModList().get(), &ModFolderModel::updateFinished, this, &ModrinthPackExportTask::collectHashes); + } else + collectHashes(); } void ModrinthPackExportTask::collectHashes() { - // TODO make this just use EnsureMetadataTask - setStatus(tr("Finding file hashes...")); - - QStringList prefixes; - - for (const auto& model : instance->resourceLists()) { - QCoreApplication::processEvents(); - - QEventLoop loop; - connect(model.get(), &ModFolderModel::updateFinished, &loop, &QEventLoop::quit); - model->update(); - loop.exec(); - - prefixes.append(gameRoot.relativeFilePath(model->dir().absolutePath()) + '/'); - - for (const Resource* resource : model->allResources()) { - QCoreApplication::processEvents(); - - if (resource->metadata() == nullptr) - continue; - - const QUrl& url = resource->metadata()->url; - - if (url.isEmpty() || !BuildConfig.MODRINTH_MRPACK_HOSTS.contains(url.host())) - continue; - - const QFileInfo& fileInfo = resource->fileinfo(); - const QString relativePath = gameRoot.relativeFilePath(fileInfo.absoluteFilePath()); - - if (filter(relativePath)) - continue; - - qDebug() << "Resolving" << relativePath << "from index"; - - QString sha1; - QString sha512; - qint64 size; - - if (resource->metadata()->hash_format == "sha1") - sha1 = resource->metadata()->hash; - else if (resource->metadata()->hash_format == "sha512") - sha512 = resource->metadata()->hash; - - { - QFile file(fileInfo.absoluteFilePath()); - - if (!file.open(QFile::ReadOnly)) { - qWarning() << "Could not open" << relativePath << "for hashing"; - continue; - } - - const QByteArray data = file.readAll(); - - if (file.error() != QFileDevice::NoError) { - qWarning() << "Could not read" << relativePath; - continue; - } - - if (sha1.isEmpty()) - sha1 = Hashing::hash(data, Hashing::Algorithm::Sha1); - - if (sha512.isEmpty()) - sha512 = Hashing::hash(data, Hashing::Algorithm::Sha512); - - size = file.size(); - } - - ResolvedFile resolvedFile{ sha1, sha512, url.toEncoded(), size, resource->metadata()->side }; - resolvedFiles[relativePath] = resolvedFile; - } - } - for (const QFileInfo& file : files) { QCoreApplication::processEvents(); const QString relative = gameRoot.relativeFilePath(file.absoluteFilePath()); - - if (resolvedFiles.contains(relative)) - continue; - // require sensible file types - if (!std::any_of(prefixes.begin(), prefixes.end(), [&relative](const QString& prefix) { return relative.startsWith(prefix); })) + if (!std::any_of(PREFIXES.begin(), PREFIXES.end(), [&relative](const QString& prefix) { return relative.startsWith(prefix); })) continue; if (!std::any_of(FILE_EXTENSIONS.begin(), FILE_EXTENSIONS.end(), [&relative](const QString& extension) { return relative.endsWith('.' + extension) || relative.endsWith('.' + extension + ".disabled"); })) continue; + QFile openFile(file.absoluteFilePath()); + if (!openFile.open(QFile::ReadOnly)) { + qWarning() << "Could not open" << file << "for hashing"; + continue; + } + + const QByteArray data = openFile.readAll(); + if (openFile.error() != QFileDevice::NoError) { + qWarning() << "Could not read" << file; + continue; + } + auto sha512 = Hashing::hash(data, Hashing::Algorithm::Sha512); + + auto allMods = mcInstance->loaderModList()->allMods(); + if (auto modIter = std::find_if(allMods.begin(), allMods.end(), [&file](Mod* mod) { return mod->fileinfo() == file; }); + modIter != allMods.end()) { + const Mod* mod = *modIter; + if (mod->metadata() != nullptr) { + const QUrl& url = mod->metadata()->url; + // ensure the url is permitted on modrinth.com + if (!url.isEmpty() && BuildConfig.MODRINTH_MRPACK_HOSTS.contains(url.host())) { + qDebug() << "Resolving" << relative << "from index"; + + auto sha1 = Hashing::hash(data, Hashing::Algorithm::Sha1); + + ResolvedFile resolvedFile{ sha1, sha512, url.toEncoded(), openFile.size(), mod->metadata()->side }; + resolvedFiles[relative] = resolvedFile; + + // nice! we've managed to resolve based on local metadata! + // no need to enqueue it + continue; + } + } + } + qDebug() << "Enqueueing" << relative << "for Modrinth query"; - auto sha512 = Hashing::hash(file.absoluteFilePath(), Hashing::Algorithm::Sha512); pendingHashes[relative] = sha512; } @@ -277,28 +241,30 @@ QByteArray ModrinthPackExportTask::generateIndex() if (!summary.isEmpty()) out["summary"] = summary; - auto profile = instance->getPackProfile(); - // collect all supported components - const ComponentPtr minecraft = profile->getComponent("net.minecraft"); - const ComponentPtr quilt = profile->getComponent("org.quiltmc.quilt-loader"); - const ComponentPtr fabric = profile->getComponent("net.fabricmc.fabric-loader"); - const ComponentPtr forge = profile->getComponent("net.minecraftforge"); - const ComponentPtr neoForge = profile->getComponent("net.neoforged"); + if (mcInstance) { + auto profile = mcInstance->getPackProfile(); + // collect all supported components + const ComponentPtr minecraft = profile->getComponent("net.minecraft"); + const ComponentPtr quilt = profile->getComponent("org.quiltmc.quilt-loader"); + const ComponentPtr fabric = profile->getComponent("net.fabricmc.fabric-loader"); + const ComponentPtr forge = profile->getComponent("net.minecraftforge"); + const ComponentPtr neoForge = profile->getComponent("net.neoforged"); - // convert all available components to mrpack dependencies - QJsonObject dependencies; - if (minecraft != nullptr) - dependencies["minecraft"] = minecraft->m_version; - if (quilt != nullptr) - dependencies["quilt-loader"] = quilt->m_version; - if (fabric != nullptr) - dependencies["fabric-loader"] = fabric->m_version; - if (forge != nullptr) - dependencies["forge"] = forge->m_version; - if (neoForge != nullptr) - dependencies["neoforge"] = neoForge->m_version; + // convert all available components to mrpack dependencies + QJsonObject dependencies; + if (minecraft != nullptr) + dependencies["minecraft"] = minecraft->m_version; + if (quilt != nullptr) + dependencies["quilt-loader"] = quilt->m_version; + if (fabric != nullptr) + dependencies["fabric-loader"] = fabric->m_version; + if (forge != nullptr) + dependencies["forge"] = forge->m_version; + if (neoForge != nullptr) + dependencies["neoforge"] = neoForge->m_version; - out["dependencies"] = dependencies; + out["dependencies"] = dependencies; + } QJsonArray filesOut; for (auto iterator = resolvedFiles.constBegin(); iterator != resolvedFiles.constEnd(); iterator++) { diff --git a/launcher/modplatform/modrinth/ModrinthPackExportTask.h b/launcher/modplatform/modrinth/ModrinthPackExportTask.h index d5dc08678..ee740a456 100644 --- a/launcher/modplatform/modrinth/ModrinthPackExportTask.h +++ b/launcher/modplatform/modrinth/ModrinthPackExportTask.h @@ -29,12 +29,12 @@ class ModrinthPackExportTask : public Task { Q_OBJECT public: - ModrinthPackExportTask(QString name, - QString version, - QString summary, + ModrinthPackExportTask(const QString& name, + const QString& version, + const QString& summary, bool optionalFiles, - MinecraftInstancePtr instance, - QString output, + InstancePtr instance, + const QString& output, MMCZip::FilterFunction filter); protected: @@ -48,12 +48,14 @@ class ModrinthPackExportTask : public Task { Metadata::ModSide side; }; + static const QStringList PREFIXES; static const QStringList FILE_EXTENSIONS; // inputs const QString name, version, summary; const bool optionalFiles; - const MinecraftInstancePtr instance; + const InstancePtr instance; + MinecraftInstance* mcInstance; const QDir gameRoot; const QString output; const MMCZip::FilterFunction filter; diff --git a/launcher/ui/MainWindow.cpp b/launcher/ui/MainWindow.cpp index 6134d9d31..96f1348d2 100644 --- a/launcher/ui/MainWindow.cpp +++ b/launcher/ui/MainWindow.cpp @@ -1403,26 +1403,27 @@ void MainWindow::on_actionExportInstanceZip_triggered() void MainWindow::on_actionExportInstanceMrPack_triggered() { - auto instance = std::dynamic_pointer_cast(m_selectedInstance); - if (instance) { - ExportPackDialog dlg(std::move(instance), this); + if (m_selectedInstance) { + ExportPackDialog dlg(m_selectedInstance, this); dlg.exec(); } } void MainWindow::on_actionExportInstanceFlamePack_triggered() { - auto instance = std::dynamic_pointer_cast(m_selectedInstance); - if (instance) { - if (auto cmp = instance->getPackProfile()->getComponent("net.minecraft"); - cmp && cmp->getVersionFile() && cmp->getVersionFile()->type == "snapshot") { - QMessageBox msgBox(this); - msgBox.setText("Snapshots are currently not supported by CurseForge modpacks."); - msgBox.exec(); - return; + if (m_selectedInstance) { + auto instance = dynamic_cast(m_selectedInstance.get()); + if (instance) { + if (auto cmp = instance->getPackProfile()->getComponent("net.minecraft"); + cmp && cmp->getVersionFile() && cmp->getVersionFile()->type == "snapshot") { + QMessageBox msgBox(this); + msgBox.setText("Snapshots are currently not supported by CurseForge modpacks."); + msgBox.exec(); + return; + } + ExportPackDialog dlg(m_selectedInstance, this, ModPlatform::ResourceProvider::FLAME); + dlg.exec(); } - ExportPackDialog dlg(std::move(instance), this, ModPlatform::ResourceProvider::FLAME); - dlg.exec(); } } diff --git a/launcher/ui/dialogs/ExportPackDialog.cpp b/launcher/ui/dialogs/ExportPackDialog.cpp index c01b83f5c..0278c6cb0 100644 --- a/launcher/ui/dialogs/ExportPackDialog.cpp +++ b/launcher/ui/dialogs/ExportPackDialog.cpp @@ -34,7 +34,7 @@ #include "MMCZip.h" #include "modplatform/modrinth/ModrinthPackExportTask.h" -ExportPackDialog::ExportPackDialog(const MinecraftInstancePtr& instance, QWidget* parent, ModPlatform::ResourceProvider provider) +ExportPackDialog::ExportPackDialog(InstancePtr instance, QWidget* parent, ModPlatform::ResourceProvider provider) : QDialog(parent), instance(instance), ui(new Ui::ExportPackDialog), m_provider(provider) { Q_ASSERT(m_provider == ModPlatform::ResourceProvider::MODRINTH || m_provider == ModPlatform::ResourceProvider::FLAME); @@ -86,9 +86,12 @@ ExportPackDialog::ExportPackDialog(const MinecraftInstancePtr& instance, QWidget proxy->blockedPaths().insert(file); } - for (auto& resourceModel : instance->resourceLists()) - if (resourceModel->indexDir().exists()) - proxy->ignoreFilesWithPath().insert(root.relativeFilePath(resourceModel->indexDir().absolutePath())); + MinecraftInstance* mcInstance = dynamic_cast(instance.get()); + if (mcInstance) { + const QDir index = mcInstance->loaderModList()->indexDir(); + if (index.exists()) + proxy->ignoreFilesWithPath().insert(root.relativeFilePath(index.absolutePath())); + } ui->files->setModel(proxy); ui->files->setRootIndex(proxy->mapFromSource(model->index(instance->gameRoot()))); diff --git a/launcher/ui/dialogs/ExportPackDialog.h b/launcher/ui/dialogs/ExportPackDialog.h index ab20f44bd..830c24d25 100644 --- a/launcher/ui/dialogs/ExportPackDialog.h +++ b/launcher/ui/dialogs/ExportPackDialog.h @@ -18,7 +18,6 @@ #pragma once -#include #include #include "BaseInstance.h" #include "FastFileIconProvider.h" @@ -33,7 +32,7 @@ class ExportPackDialog : public QDialog { Q_OBJECT public: - explicit ExportPackDialog(const MinecraftInstancePtr& instance, + explicit ExportPackDialog(InstancePtr instance, QWidget* parent = nullptr, ModPlatform::ResourceProvider provider = ModPlatform::ResourceProvider::MODRINTH); ~ExportPackDialog(); @@ -42,7 +41,7 @@ class ExportPackDialog : public QDialog { void validate(); private: - const MinecraftInstancePtr instance; + const InstancePtr instance; Ui::ExportPackDialog* ui; FileIgnoreProxy* proxy; FastFileIconProvider icons;