diff --git a/launcher/modplatform/atlauncher/ATLPackInstallTask.cpp b/launcher/modplatform/atlauncher/ATLPackInstallTask.cpp index e5771b7cd..8ae8145de 100644 --- a/launcher/modplatform/atlauncher/ATLPackInstallTask.cpp +++ b/launcher/modplatform/atlauncher/ATLPackInstallTask.cpp @@ -37,6 +37,7 @@ #include "ATLPackInstallTask.h" #include +#include #include @@ -50,6 +51,7 @@ #include "minecraft/MinecraftInstance.h" #include "minecraft/OneSixVersionFormat.h" #include "minecraft/PackProfile.h" +#include "modplatform/atlauncher/ATLPackManifest.h" #include "net/ChecksumValidator.h" #include "settings/INISettingsObject.h" @@ -57,6 +59,7 @@ #include "Application.h" #include "BuildConfig.h" +#include "ui/dialogs/BlockedModsDialog.h" namespace ATLauncher { @@ -717,6 +720,8 @@ void PackInstallTask::downloadMods() jarmods.clear(); jobPtr.reset(new NetJob(tr("Mod download"), APPLICATION->network())); + + QList blocked_mods; for (const auto& mod : m_version.mods) { // skip non-client mods if (!mod.client) @@ -731,9 +736,10 @@ void PackInstallTask::downloadMods() case DownloadType::Server: url = BuildConfig.ATL_DOWNLOAD_SERVER_URL + mod.url; break; - case DownloadType::Browser: - emitFailed(tr("Unsupported download type: %1").arg(mod.download_raw)); - return; + case DownloadType::Browser: { + blocked_mods.append(mod); + continue; + } case DownloadType::Direct: url = mod.url; break; @@ -805,24 +811,86 @@ void PackInstallTask::downloadMods() modsToCopy[entry->getFullPath()] = path; } } + if (!blocked_mods.isEmpty()) { + QList mods; + + for (auto mod : blocked_mods) { + BlockedMod blocked_mod; + blocked_mod.name = mod.file; + blocked_mod.websiteUrl = mod.url; + blocked_mod.hash = mod.md5; + blocked_mod.matched = false; + blocked_mod.localPath = ""; + + mods.append(blocked_mod); + } + + qWarning() << "Blocked mods found, displaying mod list"; + + BlockedModsDialog message_dialog(nullptr, tr("Blocked mods found"), + tr("The following files are not available for download in third party launchers.
" + "You will need to manually download them and add them to the instance."), + mods, "md5"); + + message_dialog.setModal(true); + + if (message_dialog.exec()) { + qDebug() << "Post dialog blocked mods list: " << mods; + for (auto blocked : mods) { + if (!blocked.matched) { + qDebug() << blocked.name << "was not matched to a local file, skipping copy"; + continue; + } + auto modIter = std::find_if(blocked_mods.begin(), blocked_mods.end(), + [blocked](const VersionMod& mod) { return mod.url == blocked.websiteUrl; }); + if (modIter == blocked_mods.end()) + continue; + auto mod = *modIter; + if (mod.type == ModType::Extract || mod.type == ModType::TexturePackExtract || mod.type == ModType::ResourcePackExtract) { + modsToExtract.insert(blocked.localPath, mod); + } else if (mod.type == ModType::Decomp) { + modsToDecomp.insert(blocked.localPath, mod); + } else { + auto relpath = getDirForModType(mod.type, mod.type_raw); + if (relpath == Q_NULLPTR) + continue; + + auto path = FS::PathCombine(m_stagingPath, "minecraft", relpath, mod.file); + + if (mod.type == ModType::Forge) { + auto ver = getComponentVersion("net.minecraftforge", mod.version); + if (ver) { + componentsToInstall.insert("net.minecraftforge", ver); + continue; + } + + qDebug() << "Jarmod: " + path; + jarmods.push_back(path); + } + + if (mod.type == ModType::Jar) { + qDebug() << "Jarmod: " + path; + jarmods.push_back(path); + } + + modsToCopy[blocked.localPath] = path; + } + } + } else { + emitFailed(tr("Unknown download type: %1").arg("browser")); + return; + } + } connect(jobPtr.get(), &NetJob::succeeded, this, &PackInstallTask::onModsDownloaded); - connect(jobPtr.get(), &NetJob::failed, [&](QString reason) { - abortable = false; - jobPtr.reset(); - emitFailed(reason); - }); - connect(jobPtr.get(), &NetJob::progress, [&](qint64 current, qint64 total) { + connect(jobPtr.get(), &NetJob::progress, [this](qint64 current, qint64 total) { setDetails(tr("%1 out of %2 complete").arg(current).arg(total)); abortable = true; setProgress(current, total); }); connect(jobPtr.get(), &NetJob::stepProgress, this, &PackInstallTask::propagateStepProgress); - connect(jobPtr.get(), &NetJob::aborted, [&] { - abortable = false; - jobPtr.reset(); - emitAborted(); - }); + connect(jobPtr.get(), &NetJob::aborted, &PackInstallTask::emitAborted); + connect(jobPtr.get(), &NetJob::failed, &PackInstallTask::emitFailed); jobPtr->start(); } @@ -843,7 +911,7 @@ void PackInstallTask::onModsDownloaded() QtConcurrent::run(QThreadPool::globalInstance(), this, &PackInstallTask::extractMods, modsToExtract, modsToDecomp, modsToCopy); #endif connect(&m_modExtractFutureWatcher, &QFutureWatcher::finished, this, &PackInstallTask::onModsExtracted); - connect(&m_modExtractFutureWatcher, &QFutureWatcher::canceled, this, [&]() { emitAborted(); }); + connect(&m_modExtractFutureWatcher, &QFutureWatcher::canceled, this, &PackInstallTask::emitAborted); m_modExtractFutureWatcher.setFuture(m_modExtractFuture); } else { install(); diff --git a/launcher/ui/dialogs/BlockedModsDialog.cpp b/launcher/ui/dialogs/BlockedModsDialog.cpp index 5a1a2f80e..7a5a16818 100644 --- a/launcher/ui/dialogs/BlockedModsDialog.cpp +++ b/launcher/ui/dialogs/BlockedModsDialog.cpp @@ -41,8 +41,8 @@ #include #include -BlockedModsDialog::BlockedModsDialog(QWidget* parent, const QString& title, const QString& text, QList& mods) - : QDialog(parent), ui(new Ui::BlockedModsDialog), m_mods(mods) +BlockedModsDialog::BlockedModsDialog(QWidget* parent, const QString& title, const QString& text, QList& mods, QString hash_type) + : QDialog(parent), ui(new Ui::BlockedModsDialog), m_mods(mods), m_hash_type(hash_type) { m_hashing_task = shared_qobject_ptr( new ConcurrentTask(this, "MakeHashesTask", APPLICATION->settings()->get("NumberOfConcurrentTasks").toInt())); @@ -255,7 +255,7 @@ void BlockedModsDialog::addHashTask(QString path) /// @param path the path to the local file being hashed void BlockedModsDialog::buildHashTask(QString path) { - auto hash_task = Hashing::createBlockedModHasher(path, ModPlatform::ResourceProvider::FLAME, "sha1"); + auto hash_task = Hashing::createBlockedModHasher(path, ModPlatform::ResourceProvider::FLAME, m_hash_type); qDebug() << "[Blocked Mods Dialog] Creating Hash task for path: " << path; @@ -335,6 +335,13 @@ bool BlockedModsDialog::checkValidPath(QString path) for (auto& mod : m_mods) { if (compare(filename, mod.name)) { + // if the mod is not yet matched and doesn't have a hash then + // just match it with the file that has the exact same name + if (!mod.matched && mod.hash.isEmpty()) { + mod.matched = true; + mod.localPath = path; + return false; + } qDebug() << "[Blocked Mods Dialog] Name match found:" << mod.name << "| From path:" << path; return true; } diff --git a/launcher/ui/dialogs/BlockedModsDialog.h b/launcher/ui/dialogs/BlockedModsDialog.h index e3b7c9756..09722bce9 100644 --- a/launcher/ui/dialogs/BlockedModsDialog.h +++ b/launcher/ui/dialogs/BlockedModsDialog.h @@ -54,7 +54,7 @@ class BlockedModsDialog : public QDialog { Q_OBJECT public: - BlockedModsDialog(QWidget* parent, const QString& title, const QString& text, QList& mods); + BlockedModsDialog(QWidget* parent, const QString& title, const QString& text, QList& mods, QString hash_type = "sha1"); ~BlockedModsDialog() override; @@ -73,6 +73,7 @@ class BlockedModsDialog : public QDialog { QSet m_pending_hash_paths; bool m_rehash_pending; QPushButton* m_openMissingButton; + QString m_hash_type; void openAll(bool missingOnly); void addDownloadFolder();