summaryrefslogtreecommitdiffstats
path: root/api/logic/modplatform/ftb
diff options
context:
space:
mode:
authorPetr Mrázek <peterix@gmail.com>2018-03-16 23:33:58 +0100
committerPetr Mrázek <peterix@gmail.com>2018-03-16 23:33:58 +0100
commit106155dd627d8e333260e2460d4c9c558b49b21f (patch)
treed0678445ccb0881bb10e4bd1b13a3e03eda13d7b /api/logic/modplatform/ftb
parent303842a19e4893e4ac6784d60aca990b4276d0ec (diff)
downloadMultiMC-106155dd627d8e333260e2460d4c9c558b49b21f.tar
MultiMC-106155dd627d8e333260e2460d4c9c558b49b21f.tar.gz
MultiMC-106155dd627d8e333260e2460d4c9c558b49b21f.tar.lz
MultiMC-106155dd627d8e333260e2460d4c9c558b49b21f.tar.xz
MultiMC-106155dd627d8e333260e2460d4c9c558b49b21f.zip
NOISSUE move modpack platform related files to 'modplatform' subfolders
Diffstat (limited to 'api/logic/modplatform/ftb')
-rw-r--r--api/logic/modplatform/ftb/FtbPackDownloader.cpp109
-rw-r--r--api/logic/modplatform/ftb/FtbPackDownloader.h64
-rw-r--r--api/logic/modplatform/ftb/FtbPackFetchTask.cpp96
-rw-r--r--api/logic/modplatform/ftb/FtbPackFetchTask.h33
-rw-r--r--api/logic/modplatform/ftb/FtbPackInstallTask.cpp173
-rw-r--r--api/logic/modplatform/ftb/FtbPackInstallTask.h55
-rw-r--r--api/logic/modplatform/ftb/PackHelpers.h26
7 files changed, 556 insertions, 0 deletions
diff --git a/api/logic/modplatform/ftb/FtbPackDownloader.cpp b/api/logic/modplatform/ftb/FtbPackDownloader.cpp
new file mode 100644
index 00000000..caadd4ae
--- /dev/null
+++ b/api/logic/modplatform/ftb/FtbPackDownloader.cpp
@@ -0,0 +1,109 @@
+#include "FtbPackDownloader.h"
+#include "PackHelpers.h"
+#include "FtbPackFetchTask.h"
+#include "Env.h"
+
+FtbPackDownloader::FtbPackDownloader() {
+ done = false;
+ fetching = false;
+}
+
+FtbPackDownloader::~FtbPackDownloader(){
+}
+
+bool FtbPackDownloader::isValidPackSelected(){
+ FtbModpack dummy;
+ dummy.name = "__INVALID__";
+
+ FtbModpack other = fetchedPacks.value(selected.name, dummy);
+ if(other.name == "__INVALID__") {
+ return false;
+ }
+
+ return other.oldVersions.contains(selectedVersion) && !other.broken;
+}
+
+QString FtbPackDownloader::getSuggestedInstanceName() {
+ return selected.name;
+}
+
+FtbModpackList FtbPackDownloader::getModpacks() {
+ return static_cast<FtbModpackList>(fetchedPacks.values());
+}
+
+void FtbPackDownloader::fetchModpacks(bool force = false){
+ if(fetching || (!force && done)) {
+ qDebug() << "Skipping modpack refetch because done or already fetching [done =>" << done << "| fetching =>" << fetching << "]";
+ return;
+ }
+
+ fetching = true;
+
+ fetchTask = new FtbPackFetchTask();
+ connect(fetchTask, &FtbPackFetchTask::finished, this, &FtbPackDownloader::fetchSuccess);
+ connect(fetchTask, &FtbPackFetchTask::failed, this, &FtbPackDownloader::fetchFailed);
+ fetchTask->fetch();
+}
+
+
+void FtbPackDownloader::fetchSuccess(FtbModpackList modpacks) {
+ for(int i = 0; i < modpacks.size(); i++) {
+ fetchedPacks.insert(modpacks.at(i).name, modpacks.at(i));
+ }
+
+ fetching = false;
+ done = true;
+ emit ready();
+ fetchTask->deleteLater();
+}
+
+void FtbPackDownloader::fetchFailed(QString reason) {
+ qWarning() << "Failed to fetch FtbData" << reason;
+ fetching = false;
+ emit packFetchFailed();
+ fetchTask->deleteLater();
+}
+
+void FtbPackDownloader::selectPack(FtbModpack modpack, QString version) {
+ selected = modpack;
+ selectedVersion = version;
+}
+
+FtbModpack FtbPackDownloader::getSelectedPack() {
+ return selected;
+}
+
+void FtbPackDownloader::downloadSelected(MetaEntryPtr cache) {
+ NetJob *job = new NetJob("Downlad FTB Pack");
+
+ cache->setStale(true);
+ QString url = QString("http://ftb.cursecdn.com/FTB2/modpacks/%1/%2/%3").arg(selected.dir, selectedVersion.replace(".", "_"), selected.file);
+ job->addNetAction(Net::Download::makeCached(url, cache));
+ downloadPath = cache->getFullPath();
+
+ netJobContainer.reset(job);
+
+ connect(job, &NetJob::succeeded, this, &FtbPackDownloader::_downloadSucceeded);
+ connect(job, &NetJob::failed, this, &FtbPackDownloader::_downloadFailed);
+ connect(job, &NetJob::progress, this, &FtbPackDownloader::_downloadProgress);
+ job->start();
+}
+
+void FtbPackDownloader::_downloadSucceeded() {
+ netJobContainer.reset();
+ emit downloadSucceded(downloadPath);
+}
+
+void FtbPackDownloader::_downloadProgress(qint64 current, qint64 total) {
+ emit downloadProgress(current, total);
+}
+
+void FtbPackDownloader::_downloadFailed(QString reason) {
+ netJobContainer.reset();
+ emit downloadFailed(reason);
+}
+
+NetJobPtr FtbPackDownloader::getNetJob()
+{
+ return netJobContainer;
+}
diff --git a/api/logic/modplatform/ftb/FtbPackDownloader.h b/api/logic/modplatform/ftb/FtbPackDownloader.h
new file mode 100644
index 00000000..c5cc9bd2
--- /dev/null
+++ b/api/logic/modplatform/ftb/FtbPackDownloader.h
@@ -0,0 +1,64 @@
+#include <QString>
+#include <QUrl>
+#include <QList>
+#include <QObject>
+#include "FtbPackFetchTask.h"
+#include "tasks/Task.h"
+#include "net/NetJob.h"
+
+#include "PackHelpers.h"
+#include "Env.h"
+
+#pragma once
+
+class FtbPackDownloader;
+class MULTIMC_LOGIC_EXPORT FtbPackDownloader : public QObject {
+
+ Q_OBJECT
+
+private:
+ QMap<QString, FtbModpack> fetchedPacks;
+ bool fetching = false;
+ bool done = false;
+
+ FtbModpack selected;
+ QString selectedVersion;
+ QString downloadPath;
+
+ FtbPackFetchTask *fetchTask = 0;
+ NetJobPtr netJobContainer;
+
+ void _downloadSucceeded();
+ void _downloadFailed(QString reason);
+ void _downloadProgress(qint64 current, qint64 total);
+
+private slots:
+ void fetchSuccess(FtbModpackList modlist);
+ void fetchFailed(QString reason);
+
+public:
+ FtbPackDownloader();
+ ~FtbPackDownloader();
+
+ bool isValidPackSelected();
+ void selectPack(FtbModpack modpack, QString version);
+
+ FtbModpack getSelectedPack();
+
+ void fetchModpacks(bool force);
+ void downloadSelected(MetaEntryPtr cache);
+
+ QString getSuggestedInstanceName();
+
+ FtbModpackList getModpacks();
+ NetJobPtr getNetJob();
+
+signals:
+ void ready();
+ void packFetchFailed();
+
+ void downloadSucceded(QString archivePath);
+ void downloadFailed(QString reason);
+ void downloadProgress(qint64 current, qint64 total);
+
+};
diff --git a/api/logic/modplatform/ftb/FtbPackFetchTask.cpp b/api/logic/modplatform/ftb/FtbPackFetchTask.cpp
new file mode 100644
index 00000000..9e151186
--- /dev/null
+++ b/api/logic/modplatform/ftb/FtbPackFetchTask.cpp
@@ -0,0 +1,96 @@
+#include "FtbPackFetchTask.h"
+#include <QDomDocument>
+
+FtbPackFetchTask::FtbPackFetchTask() {
+
+}
+
+FtbPackFetchTask::~FtbPackFetchTask() {
+
+}
+
+void FtbPackFetchTask::fetch() {
+ NetJob *netJob = new NetJob("FtbModpackFetch");
+
+ QUrl url = QUrl("https://ftb.cursecdn.com/FTB2/static/modpacks.xml");
+ qDebug() << "Downloading version info from " << url.toString();
+
+ netJob->addNetAction(downloadPtr = Net::Download::makeByteArray(url, &modpacksXmlFileData));
+
+ QObject::connect(netJob, &NetJob::succeeded, this, &FtbPackFetchTask::fileDownloadFinished);
+ QObject::connect(netJob, &NetJob::failed, this, &FtbPackFetchTask::fileDownloadFailed);
+
+ jobPtr.reset(netJob);
+ netJob->start();
+}
+
+void FtbPackFetchTask::fileDownloadFinished(){
+
+ jobPtr.reset();
+
+ QDomDocument doc;
+
+ QString errorMsg = "Unknown error.";
+ int errorLine = -1;
+ int errorCol = -1;
+
+ if(!doc.setContent(modpacksXmlFileData, false, &errorMsg, &errorLine, &errorCol)){
+ auto fullErrMsg = QString("Failed to fetch modpack data: %s %d:%d!").arg(errorMsg, errorLine, errorCol);
+ qWarning() << fullErrMsg;
+ emit failed(fullErrMsg);
+ modpacksXmlFileData.clear();
+ return;
+ }
+
+ modpacksXmlFileData.clear();
+
+ FtbModpackList modpackList;
+
+ QDomNodeList nodes = doc.elementsByTagName("modpack");
+ for(int i = 0; i < nodes.length(); i++) {
+ QDomElement element = nodes.at(i).toElement();
+
+ FtbModpack modpack;
+ modpack.name = element.attribute("name");
+ modpack.currentVersion = element.attribute("version");
+ modpack.mcVersion = element.attribute("mcVersion");
+ modpack.description = element.attribute("description");
+ modpack.mods = element.attribute("mods");
+ modpack.image = element.attribute("image");
+ modpack.oldVersions = element.attribute("oldVersions").split(";");
+
+ //remove empty if the xml is bugged
+ for(QString curr : modpack.oldVersions) {
+ if(curr.isNull() || curr.isEmpty()) {
+ modpack.oldVersions.removeAll(curr);
+ modpack.bugged = true;
+ qWarning() << "Removed some empty versions from" << modpack.name;
+ }
+ }
+
+ if(modpack.oldVersions.size() < 1) {
+ if(!modpack.currentVersion.isNull() && !modpack.currentVersion.isEmpty()) {
+ modpack.oldVersions.append(modpack.currentVersion);
+ qWarning() << "Added current version to oldVersions because oldVersions was empty! (" + modpack.name + ")";
+ } else {
+ modpack.broken = true;
+ qWarning() << "Broken pack:" << modpack.name << " => No valid version!";
+ }
+ }
+
+ modpack.author = element.attribute("author");
+
+ modpack.dir = element.attribute("dir");
+ modpack.file = element.attribute("url");
+
+ modpackList.append(modpack);
+ }
+
+
+ emit finished(modpackList);
+}
+
+void FtbPackFetchTask::fileDownloadFailed(QString reason){
+ qWarning() << "Fetching FtbPacks failed: " << reason;
+ emit failed(reason);
+}
diff --git a/api/logic/modplatform/ftb/FtbPackFetchTask.h b/api/logic/modplatform/ftb/FtbPackFetchTask.h
new file mode 100644
index 00000000..3cfac4ed
--- /dev/null
+++ b/api/logic/modplatform/ftb/FtbPackFetchTask.h
@@ -0,0 +1,33 @@
+#pragma once
+
+#include "net/NetJob.h"
+#include <QTemporaryDir>
+#include <QByteArray>
+#include <QObject>
+#include "PackHelpers.h"
+
+class MULTIMC_LOGIC_EXPORT FtbPackFetchTask : public QObject {
+
+ Q_OBJECT
+
+public:
+ FtbPackFetchTask();
+ ~FtbPackFetchTask();
+
+ void fetch();
+
+private:
+ NetJobPtr jobPtr;
+ Net::Download::Ptr downloadPtr;
+
+ QByteArray modpacksXmlFileData;
+
+protected slots:
+ void fileDownloadFinished();
+ void fileDownloadFailed(QString reason);
+
+signals:
+ void finished(FtbModpackList list);
+ void failed(QString reason);
+
+};
diff --git a/api/logic/modplatform/ftb/FtbPackInstallTask.cpp b/api/logic/modplatform/ftb/FtbPackInstallTask.cpp
new file mode 100644
index 00000000..530f72ca
--- /dev/null
+++ b/api/logic/modplatform/ftb/FtbPackInstallTask.cpp
@@ -0,0 +1,173 @@
+#include "FtbPackInstallTask.h"
+#include "Env.h"
+#include "MMCZip.h"
+#include "QtConcurrent"
+#include "BaseInstance.h"
+#include "FileSystem.h"
+#include "settings/INISettingsObject.h"
+#include "minecraft/MinecraftInstance.h"
+#include "minecraft/ComponentList.h"
+#include "minecraft/GradleSpecifier.h"
+
+FtbPackInstallTask::FtbPackInstallTask(FtbPackDownloader *downloader, SettingsObjectPtr settings,
+ const QString &stagingPath, const QString &instName, const QString &instIcon, const QString &instGroup) :
+ m_globalSettings(settings), m_stagingPath(stagingPath), m_instName(instName), m_instIcon(instIcon), m_instGroup(instGroup)
+{
+ m_downloader = downloader;
+}
+
+void FtbPackInstallTask::executeTask() {
+ downloadPack();
+}
+
+void FtbPackInstallTask::downloadPack(){
+ FtbModpack toInstall = m_downloader->getSelectedPack();
+ setStatus(tr("Downloading zip for %1").arg(toInstall.name));
+
+ auto entry = ENV.metacache()->resolveEntry("general", "FTBPacks/" + toInstall.name);
+ m_downloader->downloadSelected(entry);
+
+ connect(m_downloader, &FtbPackDownloader::downloadSucceded, this, &FtbPackInstallTask::onDownloadSucceeded);
+ connect(m_downloader, &FtbPackDownloader::downloadProgress, this, &FtbPackInstallTask::onDownloadProgress);
+ connect(m_downloader, &FtbPackDownloader::downloadFailed, this,&FtbPackInstallTask::onDownloadFailed);
+ progress(1, 4);
+}
+
+void FtbPackInstallTask::onDownloadSucceeded(QString archivePath){
+ abortable = false;
+ unzip(archivePath);
+}
+
+void FtbPackInstallTask::onDownloadFailed(QString reason) {
+ emitFailed(reason);
+}
+
+void FtbPackInstallTask::onDownloadProgress(qint64 current, qint64 total){
+ abortable = true;
+ progress(current, total * 4);
+ setStatus(tr("Downloading zip for %1 (%2\%)").arg(m_downloader->getSelectedPack().name).arg(current / 10));
+}
+
+void FtbPackInstallTask::unzip(QString archivePath) {
+ progress(2, 4);
+ setStatus(tr("Extracting modpack"));
+ QDir extractDir(m_stagingPath);
+
+ m_packZip.reset(new QuaZip(archivePath));
+ if(!m_packZip->open(QuaZip::mdUnzip)) {
+ emitFailed(tr("Failed to open modpack file %1!").arg(archivePath));
+ return;
+ }
+
+ m_extractFuture = QtConcurrent::run(QThreadPool::globalInstance(), MMCZip::extractDir, archivePath, extractDir.absolutePath() + "/unzip");
+ connect(&m_extractFutureWatcher, &QFutureWatcher<QStringList>::finished, this, &FtbPackInstallTask::onUnzipFinished);
+ connect(&m_extractFutureWatcher, &QFutureWatcher<QStringList>::canceled, this, &FtbPackInstallTask::onUnzipCanceled);
+ m_extractFutureWatcher.setFuture(m_extractFuture);
+}
+
+void FtbPackInstallTask::onUnzipFinished() {
+ install();
+}
+
+void FtbPackInstallTask::onUnzipCanceled() {
+ emitAborted();
+}
+
+void FtbPackInstallTask::install() {
+ progress(3, 4);
+ FtbModpack toInstall = m_downloader->getSelectedPack();
+ setStatus(tr("Installing modpack"));
+ QDir unzipMcDir(m_stagingPath + "/unzip/minecraft");
+ if(unzipMcDir.exists()) {
+ //ok, found minecraft dir, move contents to instance dir
+ if(!QDir().rename(m_stagingPath + "/unzip/minecraft", m_stagingPath + "/.minecraft")) {
+ emitFailed(tr("Failed to move unzipped minecraft!"));
+ return;
+ }
+ }
+
+ QString instanceConfigPath = FS::PathCombine(m_stagingPath, "instance.cfg");
+ auto instanceSettings = std::make_shared<INISettingsObject>(instanceConfigPath);
+ instanceSettings->registerSetting("InstanceType", "Legacy");
+ instanceSettings->set("InstanceType", "OneSix");
+
+ MinecraftInstance instance(m_globalSettings, instanceSettings, m_stagingPath);
+ auto components = instance.getComponentList();
+ components->buildingFromScratch();
+ components->setComponentVersion("net.minecraft", toInstall.mcVersion, true);
+
+ bool fallback = true;
+
+ //handle different versions
+ QFile packJson(m_stagingPath + "/.minecraft/pack.json");
+ QDir jarmodDir = QDir(m_stagingPath + "/unzip/instMods");
+ if(packJson.exists()) {
+ packJson.open(QIODevice::ReadOnly | QIODevice::Text);
+ QJsonDocument doc = QJsonDocument::fromJson(packJson.readAll());
+ packJson.close();
+
+ //we only care about the libs
+ QJsonArray libs = doc.object().value("libraries").toArray();
+
+ foreach (const QJsonValue &value, libs) {
+ QString nameValue = value.toObject().value("name").toString();
+ if(!nameValue.startsWith("net.minecraftforge")) {
+ continue;
+ }
+
+ GradleSpecifier forgeVersion(nameValue);
+
+ components->setComponentVersion("net.minecraftforge", forgeVersion.version().replace(toInstall.mcVersion, "").replace("-", ""));
+ packJson.remove();
+ fallback = false;
+ break;
+ }
+
+ }
+
+ if(jarmodDir.exists()) {
+ qDebug() << "Found jarmods, installing...";
+
+ QStringList jarmods;
+ for (auto info: jarmodDir.entryInfoList(QDir::NoDotAndDotDot | QDir::Files))
+ {
+ qDebug() << "Jarmod:" << info.fileName();
+ jarmods.push_back(info.absoluteFilePath());
+ }
+
+ components->installJarMods(jarmods);
+ fallback = false;
+ }
+
+ //just nuke unzip directory, it s not needed anymore
+ FS::deletePath(m_stagingPath + "/unzip");
+
+ if(fallback) {
+ //TODO: Some fallback mechanism... or just keep failing!
+ emitFailed(tr("No installation method found!"));
+ return;
+ }
+
+ components->saveNow();
+
+ progress(4, 4);
+
+ instance.init();
+ instance.setName(m_instName);
+ if(m_instIcon == "default") {
+ m_instIcon = "ftb_logo";
+ }
+ instance.setIconKey(m_instIcon);
+ instance.setGroupInitial(m_instGroup);
+ instanceSettings->resumeSave();
+
+ emitSucceeded();
+}
+
+bool FtbPackInstallTask::abort()
+{
+ if(abortable) {
+ return m_downloader->getNetJob()->abort();
+ }
+ return false;
+}
diff --git a/api/logic/modplatform/ftb/FtbPackInstallTask.h b/api/logic/modplatform/ftb/FtbPackInstallTask.h
new file mode 100644
index 00000000..7d6e5276
--- /dev/null
+++ b/api/logic/modplatform/ftb/FtbPackInstallTask.h
@@ -0,0 +1,55 @@
+#pragma once
+#include "tasks/Task.h"
+#include "modplatform/ftb/FtbPackDownloader.h"
+#include "BaseInstanceProvider.h"
+#include "net/NetJob.h"
+#include "quazip.h"
+#include "quazipdir.h"
+#include "meta/Index.h"
+#include "meta/Version.h"
+#include "meta/VersionList.h"
+
+class MULTIMC_LOGIC_EXPORT FtbPackInstallTask : public Task {
+
+ Q_OBJECT
+
+public:
+ explicit FtbPackInstallTask(FtbPackDownloader *downloader, SettingsObjectPtr settings, const QString &stagingPath, const QString &instName,
+ const QString &instIcon, const QString &instGroup);
+ bool abort() override;
+
+protected:
+ //! Entry point for tasks.
+ virtual void executeTask() override;
+
+private: /* data */
+ SettingsObjectPtr m_globalSettings;
+ QString m_stagingPath;
+ QString m_instName;
+ QString m_instIcon;
+ QString m_instGroup;
+ NetJobPtr m_netJobPtr;
+
+ FtbPackDownloader *m_downloader;
+
+ std::unique_ptr<QuaZip> m_packZip;
+ QFuture<QStringList> m_extractFuture;
+ QFutureWatcher<QStringList> m_extractFutureWatcher;
+
+ void downloadPack();
+ void unzip(QString archivePath);
+ void install();
+
+ bool moveRecursively(QString source, QString dest);
+
+ bool abortable = false;
+
+private slots:
+ void onDownloadSucceeded(QString archivePath);
+ void onDownloadFailed(QString reason);
+ void onDownloadProgress(qint64 current, qint64 total);
+
+ void onUnzipFinished();
+ void onUnzipCanceled();
+
+};
diff --git a/api/logic/modplatform/ftb/PackHelpers.h b/api/logic/modplatform/ftb/PackHelpers.h
new file mode 100644
index 00000000..f761ed6b
--- /dev/null
+++ b/api/logic/modplatform/ftb/PackHelpers.h
@@ -0,0 +1,26 @@
+#pragma once
+#include <QList>
+#include "qmetatype.h"
+
+//Header for structs etc...
+struct FtbModpack {
+ QString name;
+ QString description;
+ QString author;
+ QStringList oldVersions;
+ QString currentVersion;
+ QString mcVersion;
+ QString mods;
+ QString image;
+
+ //Technical data
+ QString dir;
+ QString file; //<- Url in the xml, but doesn't make much sense
+
+ bool bugged = false;
+ bool broken = false;
+};
+//We need it for the proxy model
+Q_DECLARE_METATYPE(FtbModpack)
+
+typedef QList<FtbModpack> FtbModpackList;