From 83654a193e8856e00bcdbe4f87d209e52c380a62 Mon Sep 17 00:00:00 2001 From: flow Date: Thu, 13 Oct 2022 13:27:52 -0300 Subject: [PATCH 1/4] refactor+fix: Make FTB install task similar to other install tasks In particular, this changes the order so that the instance gets created before downloading the mods (like other install tasks), and the mod download directly puts the files in the staging folder (like the others), instead of that weird makeCached and copy stuff. This fixes some issues with modpack downloads from FTB, like creating an instance with no mods in it. Signed-off-by: flow --- .../modpacksch/FTBPackInstallTask.cpp | 144 ++++++++---------- .../modpacksch/FTBPackInstallTask.h | 7 +- 2 files changed, 64 insertions(+), 87 deletions(-) diff --git a/launcher/modplatform/modpacksch/FTBPackInstallTask.cpp b/launcher/modplatform/modpacksch/FTBPackInstallTask.cpp index 97ce1dc6c..cc926d454 100644 --- a/launcher/modplatform/modpacksch/FTBPackInstallTask.cpp +++ b/launcher/modplatform/modpacksch/FTBPackInstallTask.cpp @@ -58,6 +58,9 @@ PackInstallTask::PackInstallTask(Modpack pack, QString version, QWidget* parent) bool PackInstallTask::abort() { + if (!canAbort()) + return false; + bool aborted = true; if (m_net_job) @@ -65,14 +68,12 @@ bool PackInstallTask::abort() if (m_mod_id_resolver_task) aborted &= m_mod_id_resolver_task->abort(); - if (aborted) - emitAborted(); - - return aborted; + return aborted ? InstanceTask::abort() : false; } void PackInstallTask::executeTask() { + setAbortable(true); setStatus(tr("Getting the manifest...")); // Find pack version @@ -129,6 +130,7 @@ void PackInstallTask::onManifestDownloadSucceeded() void PackInstallTask::resolveMods() { + setAbortable(true); setStatus(tr("Resolving mods...")); setProgress(0, 100); @@ -169,8 +171,6 @@ void PackInstallTask::resolveMods() void PackInstallTask::onResolveModsSucceeded() { - m_abortable = false; - QString text; QList urls; auto anyBlocked = false; @@ -209,94 +209,23 @@ void PackInstallTask::onResolveModsSucceeded() urls); if (message_dialog->exec() == QDialog::Accepted) - downloadPack(); + createInstance(); else abort(); } else { - downloadPack(); + createInstance(); } } -void PackInstallTask::downloadPack() +void PackInstallTask::createInstance() { - setStatus(tr("Downloading mods...")); + setAbortable(false); - auto* jobPtr = new NetJob(tr("Mod download"), APPLICATION->network()); - for (auto const& file : m_version.files) { - if (file.serverOnly || file.url.isEmpty()) - continue; - - QFileInfo file_info(file.name); - auto cacheName = file_info.completeBaseName() + "-" + file.sha1 + "." + file_info.suffix(); - - auto entry = APPLICATION->metacache()->resolveEntry("ModpacksCHPacks", cacheName); - entry->setStale(true); - - auto relpath = FS::PathCombine("minecraft", file.path, file.name); - auto path = FS::PathCombine(m_stagingPath, relpath); - - if (m_files_to_copy.contains(path)) { - qWarning() << "Ignoring" << file.url << "as a file of that path is already downloading."; - continue; - } - - qDebug() << "Will download" << file.url << "to" << path; - m_files_to_copy[path] = entry->getFullPath(); - - auto dl = Net::Download::makeCached(file.url, entry); - if (!file.sha1.isEmpty()) { - auto rawSha1 = QByteArray::fromHex(file.sha1.toLatin1()); - dl->addValidator(new Net::ChecksumValidator(QCryptographicHash::Sha1, rawSha1)); - } - - jobPtr->addNetAction(dl); - } - - connect(jobPtr, &NetJob::succeeded, this, &PackInstallTask::onModDownloadSucceeded); - connect(jobPtr, &NetJob::failed, this, &PackInstallTask::onModDownloadFailed); - connect(jobPtr, &NetJob::progress, this, &PackInstallTask::setProgress); - - m_net_job = jobPtr; - jobPtr->start(); - - m_abortable = true; -} - -void PackInstallTask::onModDownloadSucceeded() -{ - m_net_job.reset(); - install(); -} - -void PackInstallTask::install() -{ - setStatus(tr("Copying modpack files...")); - setProgress(0, m_files_to_copy.size()); - QCoreApplication::processEvents(); - - m_abortable = false; - - int i = 0; - for (auto iter = m_files_to_copy.constBegin(); iter != m_files_to_copy.constEnd(); iter++) { - auto& to = iter.key(); - auto& from = iter.value(); - FS::copy fileCopyOperation(from, to); - if (!fileCopyOperation()) { - qWarning() << "Failed to copy" << from << "to" << to; - emitFailed(tr("Failed to copy files")); - return; - } - - setProgress(i++, m_files_to_copy.size()); - QCoreApplication::processEvents(); - } - - setStatus(tr("Installing modpack...")); + setStatus(tr("Creating the instance...")); QCoreApplication::processEvents(); auto instanceConfigPath = FS::PathCombine(m_stagingPath, "instance.cfg"); auto instanceSettings = std::make_shared(instanceConfigPath); - instanceSettings->suspendSave(); MinecraftInstance instance(m_globalSettings, instanceSettings, m_stagingPath); auto components = instance.getPackProfile(); @@ -337,8 +266,53 @@ void PackInstallTask::install() instance.setName(name()); instance.setIconKey(m_instIcon); instance.setManagedPack("modpacksch", QString::number(m_pack.id), m_pack.name, QString::number(m_version.id), m_version.name); - instanceSettings->resumeSave(); + instance.saveNow(); + + onCreateInstanceSucceeded(); +} + +void PackInstallTask::onCreateInstanceSucceeded() +{ + downloadPack(); +} + +void PackInstallTask::downloadPack() +{ + setAbortable(true); + + setStatus(tr("Downloading mods...")); + + auto* jobPtr = new NetJob(tr("Mod download"), APPLICATION->network()); + for (auto const& file : m_version.files) { + if (file.serverOnly || file.url.isEmpty()) + continue; + + auto path = FS::PathCombine(m_stagingPath, ".minecraft", file.path, file.name); + qDebug() << "Will try to download" << file.url << "to" << path; + + QFileInfo file_info(file.name); + + auto dl = Net::Download::makeFile(file.url, path); + if (!file.sha1.isEmpty()) { + auto rawSha1 = QByteArray::fromHex(file.sha1.toLatin1()); + dl->addValidator(new Net::ChecksumValidator(QCryptographicHash::Sha1, rawSha1)); + } + + jobPtr->addNetAction(dl); + } + + connect(jobPtr, &NetJob::succeeded, this, &PackInstallTask::onModDownloadSucceeded); + connect(jobPtr, &NetJob::failed, this, &PackInstallTask::onModDownloadFailed); + connect(jobPtr, &NetJob::progress, this, &PackInstallTask::setProgress); + + m_net_job = jobPtr; + jobPtr->start(); +} + +void PackInstallTask::onModDownloadSucceeded() +{ + m_net_job.reset(); emitSucceeded(); } @@ -352,6 +326,10 @@ void PackInstallTask::onResolveModsFailed(QString reason) m_net_job.reset(); emitFailed(reason); } +void PackInstallTask::onCreateInstanceFailed(QString reason) +{ + emitFailed(reason); +} void PackInstallTask::onModDownloadFailed(QString reason) { m_net_job.reset(); diff --git a/launcher/modplatform/modpacksch/FTBPackInstallTask.h b/launcher/modplatform/modpacksch/FTBPackInstallTask.h index e63ca0dff..7c6fbeb93 100644 --- a/launcher/modplatform/modpacksch/FTBPackInstallTask.h +++ b/launcher/modplatform/modpacksch/FTBPackInstallTask.h @@ -56,7 +56,6 @@ public: explicit PackInstallTask(Modpack pack, QString version, QWidget* parent = nullptr); ~PackInstallTask() override = default; - bool canAbort() const override { return m_abortable; } bool abort() override; protected: @@ -65,20 +64,20 @@ protected: private slots: void onManifestDownloadSucceeded(); void onResolveModsSucceeded(); + void onCreateInstanceSucceeded(); void onModDownloadSucceeded(); void onManifestDownloadFailed(QString reason); void onResolveModsFailed(QString reason); + void onCreateInstanceFailed(QString reason); void onModDownloadFailed(QString reason); private: void resolveMods(); + void createInstance(); void downloadPack(); - void install(); private: - bool m_abortable = true; - NetJob::Ptr m_net_job = nullptr; shared_qobject_ptr m_mod_id_resolver_task = nullptr; From f26be005716818b643a0c8b1373dbe83e4cdcfbf Mon Sep 17 00:00:00 2001 From: flow Date: Thu, 13 Oct 2022 13:49:06 -0300 Subject: [PATCH 2/4] fix: abort search if we're already trying to download a pack Meaning we don't have to wait for the searches to finish in the background to finally start the modpack download, when we have already selected it -_- Signed-off-by: flow --- launcher/ui/dialogs/NewInstanceDialog.cpp | 8 ++++++++ launcher/ui/pages/modplatform/ftb/FtbListModel.cpp | 11 +++++++++++ launcher/ui/pages/modplatform/ftb/FtbListModel.h | 5 +++++ launcher/ui/pages/modplatform/ftb/FtbPage.cpp | 6 ++++++ launcher/ui/pages/modplatform/ftb/FtbPage.h | 1 + 5 files changed, 31 insertions(+) diff --git a/launcher/ui/dialogs/NewInstanceDialog.cpp b/launcher/ui/dialogs/NewInstanceDialog.cpp index d203795ae..df182f096 100644 --- a/launcher/ui/dialogs/NewInstanceDialog.cpp +++ b/launcher/ui/dialogs/NewInstanceDialog.cpp @@ -139,6 +139,10 @@ NewInstanceDialog::NewInstanceDialog(const QString & initialGroup, const QString void NewInstanceDialog::reject() { APPLICATION->settings()->set("NewInstanceGeometry", saveGeometry().toBase64()); + + // This is just so that the pages get the close() call and can react to it, if needed. + m_container->prepareToClose(); + QDialog::reject(); } @@ -146,6 +150,10 @@ void NewInstanceDialog::accept() { APPLICATION->settings()->set("NewInstanceGeometry", saveGeometry().toBase64()); importIconNow(); + + // This is just so that the pages get the close() call and can react to it, if needed. + m_container->prepareToClose(); + QDialog::accept(); } diff --git a/launcher/ui/pages/modplatform/ftb/FtbListModel.cpp b/launcher/ui/pages/modplatform/ftb/FtbListModel.cpp index ad15b6e62..3a1499448 100644 --- a/launcher/ui/pages/modplatform/ftb/FtbListModel.cpp +++ b/launcher/ui/pages/modplatform/ftb/FtbListModel.cpp @@ -103,6 +103,8 @@ void ListModel::getLogo(const QString &logo, const QString &logoUrl, LogoCallbac void ListModel::request() { + m_aborted = false; + beginResetModel(); modpacks.clear(); endResetModel(); @@ -117,6 +119,12 @@ void ListModel::request() QObject::connect(netJob, &NetJob::failed, this, &ListModel::requestFailed); } +void ListModel::abortRequest() +{ + m_aborted = jobPtr->abort(); + jobPtr.reset(); +} + void ListModel::requestFinished() { jobPtr.reset(); @@ -162,6 +170,9 @@ void ListModel::requestPack() void ListModel::packRequestFinished() { + if (!jobPtr || m_aborted) + return; + jobPtr.reset(); remainingPacks.removeOne(currentPack); diff --git a/launcher/ui/pages/modplatform/ftb/FtbListModel.h b/launcher/ui/pages/modplatform/ftb/FtbListModel.h index 314cb7891..cbf215c4a 100644 --- a/launcher/ui/pages/modplatform/ftb/FtbListModel.h +++ b/launcher/ui/pages/modplatform/ftb/FtbListModel.h @@ -47,9 +47,12 @@ public: QVariant data(const QModelIndex &index, int role) const override; void request(); + void abortRequest(); void getLogo(const QString &logo, const QString &logoUrl, LogoCallback callback); + [[nodiscard]] bool isMakingRequest() const { return jobPtr.get(); } + private slots: void requestFinished(); void requestFailed(QString reason); @@ -65,6 +68,8 @@ private: void requestLogo(QString file, QString url); private: + bool m_aborted = false; + QList modpacks; LogoMap m_logoMap; diff --git a/launcher/ui/pages/modplatform/ftb/FtbPage.cpp b/launcher/ui/pages/modplatform/ftb/FtbPage.cpp index 8975d74ef..1fe28124c 100644 --- a/launcher/ui/pages/modplatform/ftb/FtbPage.cpp +++ b/launcher/ui/pages/modplatform/ftb/FtbPage.cpp @@ -114,6 +114,12 @@ void FtbPage::openedImpl() suggestCurrent(); } +void FtbPage::closedImpl() +{ + if (listModel->isMakingRequest()) + listModel->abortRequest(); +} + void FtbPage::suggestCurrent() { if(!isOpened) diff --git a/launcher/ui/pages/modplatform/ftb/FtbPage.h b/launcher/ui/pages/modplatform/ftb/FtbPage.h index 90c8e7fd4..631ae7f56 100644 --- a/launcher/ui/pages/modplatform/ftb/FtbPage.h +++ b/launcher/ui/pages/modplatform/ftb/FtbPage.h @@ -78,6 +78,7 @@ public: void retranslate() override; void openedImpl() override; + void closedImpl() override; bool eventFilter(QObject * watched, QEvent * event) override; From dfa220ef02f23ff734dec6247f4a124a7a144c7a Mon Sep 17 00:00:00 2001 From: flow Date: Thu, 13 Oct 2022 15:10:35 -0300 Subject: [PATCH 3/4] fix: issues with aborts (again) i hate it Signed-off-by: flow --- launcher/modplatform/flame/FileResolvingTask.cpp | 5 +++-- .../modplatform/modpacksch/FTBPackInstallTask.cpp | 15 +++++++++++---- launcher/ui/dialogs/ProgressDialog.cpp | 5 +++-- launcher/ui/pages/modplatform/ftb/FtbListModel.h | 1 + launcher/ui/pages/modplatform/ftb/FtbPage.cpp | 2 +- 5 files changed, 19 insertions(+), 9 deletions(-) diff --git a/launcher/modplatform/flame/FileResolvingTask.cpp b/launcher/modplatform/flame/FileResolvingTask.cpp index 058d24712..1e7f55590 100644 --- a/launcher/modplatform/flame/FileResolvingTask.cpp +++ b/launcher/modplatform/flame/FileResolvingTask.cpp @@ -9,9 +9,10 @@ Flame::FileResolvingTask::FileResolvingTask(const shared_qobject_ptrabort(); - return true; + aborted &= m_dljob->abort(); + return aborted ? Task::abort() : false; } void Flame::FileResolvingTask::executeTask() diff --git a/launcher/modplatform/modpacksch/FTBPackInstallTask.cpp b/launcher/modplatform/modpacksch/FTBPackInstallTask.cpp index cc926d454..7b112d8f9 100644 --- a/launcher/modplatform/modpacksch/FTBPackInstallTask.cpp +++ b/launcher/modplatform/modpacksch/FTBPackInstallTask.cpp @@ -73,8 +73,8 @@ bool PackInstallTask::abort() void PackInstallTask::executeTask() { - setAbortable(true); setStatus(tr("Getting the manifest...")); + setAbortable(false); // Find pack version auto version_it = std::find_if(m_pack.versions.constBegin(), m_pack.versions.constEnd(), @@ -94,10 +94,12 @@ void PackInstallTask::executeTask() QObject::connect(netJob, &NetJob::succeeded, this, &PackInstallTask::onManifestDownloadSucceeded); QObject::connect(netJob, &NetJob::failed, this, &PackInstallTask::onManifestDownloadFailed); + QObject::connect(netJob, &NetJob::aborted, this, &PackInstallTask::abort); QObject::connect(netJob, &NetJob::progress, this, &PackInstallTask::setProgress); m_net_job = netJob; + setAbortable(true); netJob->start(); } @@ -130,8 +132,8 @@ void PackInstallTask::onManifestDownloadSucceeded() void PackInstallTask::resolveMods() { - setAbortable(true); setStatus(tr("Resolving mods...")); + setAbortable(false); setProgress(0, 100); m_file_id_map.clear(); @@ -164,8 +166,11 @@ void PackInstallTask::resolveMods() connect(m_mod_id_resolver_task.get(), &Flame::FileResolvingTask::succeeded, this, &PackInstallTask::onResolveModsSucceeded); connect(m_mod_id_resolver_task.get(), &Flame::FileResolvingTask::failed, this, &PackInstallTask::onResolveModsFailed); + connect(m_mod_id_resolver_task.get(), &Flame::FileResolvingTask::aborted, this, &PackInstallTask::abort); connect(m_mod_id_resolver_task.get(), &Flame::FileResolvingTask::progress, this, &PackInstallTask::setProgress); + setAbortable(true); + m_mod_id_resolver_task->start(); } @@ -279,9 +284,8 @@ void PackInstallTask::onCreateInstanceSucceeded() void PackInstallTask::downloadPack() { - setAbortable(true); - setStatus(tr("Downloading mods...")); + setAbortable(false); auto* jobPtr = new NetJob(tr("Mod download"), APPLICATION->network()); for (auto const& file : m_version.files) { @@ -304,9 +308,12 @@ void PackInstallTask::downloadPack() connect(jobPtr, &NetJob::succeeded, this, &PackInstallTask::onModDownloadSucceeded); connect(jobPtr, &NetJob::failed, this, &PackInstallTask::onModDownloadFailed); + connect(jobPtr, &NetJob::aborted, this, &PackInstallTask::abort); connect(jobPtr, &NetJob::progress, this, &PackInstallTask::setProgress); m_net_job = jobPtr; + + setAbortable(true); jobPtr->start(); } diff --git a/launcher/ui/dialogs/ProgressDialog.cpp b/launcher/ui/dialogs/ProgressDialog.cpp index 258a32e48..68dd4d17e 100644 --- a/launcher/ui/dialogs/ProgressDialog.cpp +++ b/launcher/ui/dialogs/ProgressDialog.cpp @@ -25,6 +25,7 @@ ProgressDialog::ProgressDialog(QWidget* parent) : QDialog(parent), ui(new Ui::Pr { ui->setupUi(this); this->setWindowFlags(this->windowFlags() & ~Qt::WindowContextHelpButtonHint); + setAttribute(Qt::WidgetAttribute::WA_QuitOnClose, true); setSkipButton(false); changeProgress(0, 100); } @@ -67,7 +68,7 @@ int ProgressDialog::execWithTask(Task* task) return QDialog::DialogCode::Accepted; } - QDialog::DialogCode result; + QDialog::DialogCode result {}; if (handleImmediateResult(result)) { return result; } @@ -80,7 +81,7 @@ int ProgressDialog::execWithTask(Task* task) connect(task, &Task::stepStatus, this, &ProgressDialog::changeStatus); connect(task, &Task::progress, this, &ProgressDialog::changeProgress); - connect(task, &Task::aborted, [this] { QDialog::reject(); }); + connect(task, &Task::aborted, this, &ProgressDialog::hide); connect(task, &Task::abortStatusChanged, ui->skipButton, &QPushButton::setEnabled); m_is_multi_step = task->isMultiStep(); diff --git a/launcher/ui/pages/modplatform/ftb/FtbListModel.h b/launcher/ui/pages/modplatform/ftb/FtbListModel.h index cbf215c4a..d7a120f06 100644 --- a/launcher/ui/pages/modplatform/ftb/FtbListModel.h +++ b/launcher/ui/pages/modplatform/ftb/FtbListModel.h @@ -52,6 +52,7 @@ public: void getLogo(const QString &logo, const QString &logoUrl, LogoCallback callback); [[nodiscard]] bool isMakingRequest() const { return jobPtr.get(); } + [[nodiscard]] bool wasAborted() const { return m_aborted; } private slots: void requestFinished(); diff --git a/launcher/ui/pages/modplatform/ftb/FtbPage.cpp b/launcher/ui/pages/modplatform/ftb/FtbPage.cpp index 1fe28124c..34a3d1c02 100644 --- a/launcher/ui/pages/modplatform/ftb/FtbPage.cpp +++ b/launcher/ui/pages/modplatform/ftb/FtbPage.cpp @@ -105,7 +105,7 @@ void FtbPage::retranslate() void FtbPage::openedImpl() { - if(!initialised) + if(!initialised || listModel->wasAborted()) { listModel->request(); initialised = true; From c90a88b6b6cf1b7d0fe2b6784de880762201f4a9 Mon Sep 17 00:00:00 2001 From: flow Date: Fri, 14 Oct 2022 12:18:06 -0300 Subject: [PATCH 4/4] fix: correct ftb legacy too Signed-off-by: flow --- .../legacy_ftb/PackInstallTask.cpp | 41 +++++++++---------- 1 file changed, 19 insertions(+), 22 deletions(-) diff --git a/launcher/modplatform/legacy_ftb/PackInstallTask.cpp b/launcher/modplatform/legacy_ftb/PackInstallTask.cpp index 209ad884a..06b3788b7 100644 --- a/launcher/modplatform/legacy_ftb/PackInstallTask.cpp +++ b/launcher/modplatform/legacy_ftb/PackInstallTask.cpp @@ -65,48 +65,42 @@ void PackInstallTask::executeTask() void PackInstallTask::downloadPack() { setStatus(tr("Downloading zip for %1").arg(m_pack.name)); + setAbortable(false); + + archivePath = QString("%1/%2/%3").arg(m_pack.dir, m_version.replace(".", "_"), m_pack.file); - auto packoffset = QString("%1/%2/%3").arg(m_pack.dir, m_version.replace(".", "_"), m_pack.file); - auto entry = APPLICATION->metacache()->resolveEntry("FTBPacks", packoffset); netJobContainer = new NetJob("Download FTB Pack", m_network); - - entry->setStale(true); QString url; - if(m_pack.type == PackType::Private) - { - url = QString(BuildConfig.LEGACY_FTB_CDN_BASE_URL + "privatepacks/%1").arg(packoffset); + if (m_pack.type == PackType::Private) { + url = QString(BuildConfig.LEGACY_FTB_CDN_BASE_URL + "privatepacks/%1").arg(archivePath); + } else { + url = QString(BuildConfig.LEGACY_FTB_CDN_BASE_URL + "modpacks/%1").arg(archivePath); } - else - { - url = QString(BuildConfig.LEGACY_FTB_CDN_BASE_URL + "modpacks/%1").arg(packoffset); - } - netJobContainer->addNetAction(Net::Download::makeCached(url, entry)); - archivePath = entry->getFullPath(); + netJobContainer->addNetAction(Net::Download::makeFile(url, archivePath)); connect(netJobContainer.get(), &NetJob::succeeded, this, &PackInstallTask::onDownloadSucceeded); connect(netJobContainer.get(), &NetJob::failed, this, &PackInstallTask::onDownloadFailed); connect(netJobContainer.get(), &NetJob::progress, this, &PackInstallTask::onDownloadProgress); connect(netJobContainer.get(), &NetJob::aborted, this, &PackInstallTask::onDownloadAborted); + netJobContainer->start(); + setAbortable(true); progress(1, 4); } void PackInstallTask::onDownloadSucceeded() { - abortable = false; unzip(); } void PackInstallTask::onDownloadFailed(QString reason) { - abortable = false; emitFailed(reason); } void PackInstallTask::onDownloadProgress(qint64 current, qint64 total) { - abortable = true; progress(current, total * 4); setStatus(tr("Downloading zip for %1 (%2%)").arg(m_pack.name).arg(current / 10)); } @@ -118,8 +112,10 @@ void PackInstallTask::onDownloadAborted() void PackInstallTask::unzip() { - progress(2, 4); setStatus(tr("Extracting modpack")); + setAbortable(false); + progress(2, 4); + QDir extractDir(m_stagingPath); m_packZip.reset(new QuaZip(archivePath)); @@ -151,8 +147,8 @@ void PackInstallTask::onUnzipCanceled() void PackInstallTask::install() { - progress(3, 4); setStatus(tr("Installing modpack")); + progress(3, 4); QDir unzipMcDir(m_stagingPath + "/unzip/minecraft"); if(unzipMcDir.exists()) { @@ -247,11 +243,12 @@ void PackInstallTask::install() bool PackInstallTask::abort() { - if(abortable) - { - return netJobContainer->abort(); + if (!canAbort()) { + return false; } - return false; + + netJobContainer->abort(); + return InstanceTask::abort(); } }