diff options
Diffstat (limited to 'api/logic/modplatform/atlauncher')
4 files changed, 101 insertions, 6 deletions
diff --git a/api/logic/modplatform/atlauncher/ATLPackInstallTask.cpp b/api/logic/modplatform/atlauncher/ATLPackInstallTask.cpp index 89c4dfd3..55087a27 100644 --- a/api/logic/modplatform/atlauncher/ATLPackInstallTask.cpp +++ b/api/logic/modplatform/atlauncher/ATLPackInstallTask.cpp @@ -4,6 +4,7 @@ #include <MMCZip.h> #include <minecraft/OneSixVersionFormat.h> #include <Version.h> +#include <net/ChecksumValidator.h> #include "ATLPackInstallTask.h" #include "BuildConfig.h" @@ -27,7 +28,11 @@ PackInstallTask::PackInstallTask(UserInteractionSupport *support, QString pack, bool PackInstallTask::abort() { - return true; + if(abortable) + { + return jobPtr->abort(); + } + return false; } void PackInstallTask::executeTask() @@ -407,21 +412,29 @@ void PackInstallTask::installConfigs() auto entry = ENV.metacache()->resolveEntry("ATLauncherPacks", path); entry->setStale(true); - jobPtr->addNetAction(Net::Download::makeCached(url, entry)); + auto dl = Net::Download::makeCached(url, entry); + if (!m_version.configs.sha1.isEmpty()) { + auto rawSha1 = QByteArray::fromHex(m_version.configs.sha1.toLatin1()); + dl->addValidator(new Net::ChecksumValidator(QCryptographicHash::Sha1, rawSha1)); + } + jobPtr->addNetAction(dl); archivePath = entry->getFullPath(); connect(jobPtr.get(), &NetJob::succeeded, this, [&]() { + abortable = false; jobPtr.reset(); extractConfigs(); }); connect(jobPtr.get(), &NetJob::failed, [&](QString reason) { + abortable = false; jobPtr.reset(); emitFailed(reason); }); connect(jobPtr.get(), &NetJob::progress, [&](qint64 current, qint64 total) { + abortable = true; setProgress(current, total); }); @@ -457,16 +470,31 @@ void PackInstallTask::extractConfigs() void PackInstallTask::downloadMods() { qDebug() << "PackInstallTask::installMods: " << QThread::currentThreadId(); + + QVector<ATLauncher::VersionMod> optionalMods; + for (const auto& mod : m_version.mods) { + if (mod.optional) { + optionalMods.push_back(mod); + } + } + + // Select optional mods, if pack contains any + QVector<QString> selectedMods; + if (!optionalMods.isEmpty()) { + setStatus(tr("Selecting optional mods...")); + selectedMods = m_support->chooseOptionalMods(optionalMods); + } + setStatus(tr("Downloading mods...")); jarmods.clear(); jobPtr.reset(new NetJob(tr("Mod download"))); for(const auto& mod : m_version.mods) { // skip non-client mods - if (!mod.client) continue; + if(!mod.client) continue; - // skip optional mods for now - if(mod.optional) continue; + // skip optional mods that were not selected + if(mod.optional && !selectedMods.contains(mod.name)) continue; QString url; switch(mod.download) { @@ -493,6 +521,10 @@ void PackInstallTask::downloadMods() modsToExtract.insert(entry->getFullPath(), mod); auto dl = Net::Download::makeCached(url, entry); + if (!mod.md5.isEmpty()) { + auto rawMd5 = QByteArray::fromHex(mod.md5.toLatin1()); + dl->addValidator(new Net::ChecksumValidator(QCryptographicHash::Md5, rawMd5)); + } jobPtr->addNetAction(dl); } else if(mod.type == ModType::Decomp) { @@ -501,6 +533,10 @@ void PackInstallTask::downloadMods() modsToDecomp.insert(entry->getFullPath(), mod); auto dl = Net::Download::makeCached(url, entry); + if (!mod.md5.isEmpty()) { + auto rawMd5 = QByteArray::fromHex(mod.md5.toLatin1()); + dl->addValidator(new Net::ChecksumValidator(QCryptographicHash::Md5, rawMd5)); + } jobPtr->addNetAction(dl); } else { @@ -511,6 +547,10 @@ void PackInstallTask::downloadMods() entry->setStale(true); auto dl = Net::Download::makeCached(url, entry); + if (!mod.md5.isEmpty()) { + auto rawMd5 = QByteArray::fromHex(mod.md5.toLatin1()); + dl->addValidator(new Net::ChecksumValidator(QCryptographicHash::Md5, rawMd5)); + } jobPtr->addNetAction(dl); auto path = FS::PathCombine(m_stagingPath, "minecraft", relpath, mod.file); @@ -543,11 +583,13 @@ void PackInstallTask::downloadMods() 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) { + abortable = true; setProgress(current, total); }); @@ -555,6 +597,8 @@ void PackInstallTask::downloadMods() } void PackInstallTask::onModsDownloaded() { + abortable = false; + qDebug() << "PackInstallTask::onModsDownloaded: " << QThread::currentThreadId(); jobPtr.reset(); diff --git a/api/logic/modplatform/atlauncher/ATLPackInstallTask.h b/api/logic/modplatform/atlauncher/ATLPackInstallTask.h index 3647e471..15fd9b32 100644 --- a/api/logic/modplatform/atlauncher/ATLPackInstallTask.h +++ b/api/logic/modplatform/atlauncher/ATLPackInstallTask.h @@ -19,6 +19,11 @@ class MULTIMC_LOGIC_EXPORT UserInteractionSupport { public: /** + * Requests a user interaction to select which optional mods should be installed. + */ + virtual QVector<QString> chooseOptionalMods(QVector<ATLauncher::VersionMod> mods) = 0; + + /** * Requests a user interaction to select a component version from a given version list * and constrained to a given Minecraft version. */ @@ -34,6 +39,7 @@ public: explicit PackInstallTask(UserInteractionSupport *support, QString pack, QString version); virtual ~PackInstallTask(){} + bool canAbort() const override { return true; } bool abort() override; protected: @@ -67,6 +73,8 @@ private: private: UserInteractionSupport *m_support; + bool abortable = false; + NetJobPtr jobPtr; QByteArray response; diff --git a/api/logic/modplatform/atlauncher/ATLPackManifest.cpp b/api/logic/modplatform/atlauncher/ATLPackManifest.cpp index 57cc52b6..e25d8346 100644 --- a/api/logic/modplatform/atlauncher/ATLPackManifest.cpp +++ b/api/logic/modplatform/atlauncher/ATLPackManifest.cpp @@ -109,6 +109,11 @@ static void loadVersionLibrary(ATLauncher::VersionLibrary & p, QJsonObject & obj p.server = Json::ensureString(obj, "server", ""); } +static void loadVersionConfigs(ATLauncher::VersionConfigs & p, QJsonObject & obj) { + p.filesize = Json::requireInteger(obj, "filesize"); + p.sha1 = Json::requireString(obj, "sha1"); +} + static void loadVersionMod(ATLauncher::VersionMod & p, QJsonObject & obj) { p.name = Json::requireString(obj, "name"); p.version = Json::requireString(obj, "version"); @@ -143,8 +148,24 @@ static void loadVersionMod(ATLauncher::VersionMod & p, QJsonObject & obj) { p.decompFile = Json::requireString(obj, "decompFile"); } + p.description = Json::ensureString(obj, QString("description"), ""); p.optional = Json::ensureBoolean(obj, QString("optional"), false); + p.recommended = Json::ensureBoolean(obj, QString("recommended"), false); + p.selected = Json::ensureBoolean(obj, QString("selected"), false); + p.hidden = Json::ensureBoolean(obj, QString("hidden"), false); + p.library = Json::ensureBoolean(obj, QString("library"), false); + p.group = Json::ensureString(obj, QString("group"), ""); + if(obj.contains("depends")) { + auto dependsArr = Json::requireArray(obj, "depends"); + for (const auto depends : dependsArr) { + p.depends.append(Json::requireString(depends)); + } + } + p.client = Json::ensureBoolean(obj, QString("client"), false); + + // computed + p.effectively_hidden = p.hidden || p.library; } void ATLauncher::loadVersion(PackVersion & v, QJsonObject & obj) @@ -179,7 +200,6 @@ void ATLauncher::loadVersion(PackVersion & v, QJsonObject & obj) } } - if(obj.contains("mods")) { auto mods = Json::requireArray(obj, "mods"); for (const auto modRaw : mods) @@ -190,4 +210,9 @@ void ATLauncher::loadVersion(PackVersion & v, QJsonObject & obj) v.mods.append(mod); } } + + if(obj.contains("configs")) { + auto configsObj = Json::requireObject(obj, "configs"); + loadVersionConfigs(v.configs, configsObj); + } } diff --git a/api/logic/modplatform/atlauncher/ATLPackManifest.h b/api/logic/modplatform/atlauncher/ATLPackManifest.h index 937106a5..17821e4c 100644 --- a/api/logic/modplatform/atlauncher/ATLPackManifest.h +++ b/api/logic/modplatform/atlauncher/ATLPackManifest.h @@ -86,8 +86,25 @@ struct VersionMod QString decompType_raw; QString decompFile; + QString description; bool optional; + bool recommended; + bool selected; + bool hidden; + bool library; + QString group; + QVector<QString> depends; + bool client; + + // computed + bool effectively_hidden; +}; + +struct VersionConfigs +{ + int filesize; + QString sha1; }; struct PackVersion @@ -101,6 +118,7 @@ struct PackVersion VersionLoader loader; QVector<VersionLibrary> libraries; QVector<VersionMod> mods; + VersionConfigs configs; }; MULTIMC_LOGIC_EXPORT void loadVersion(PackVersion & v, QJsonObject & obj); |