From b8ca36372be11b9ddddb3daa3d32583d286f19e2 Mon Sep 17 00:00:00 2001 From: Janrupf Date: Sat, 3 Mar 2018 21:22:00 +0100 Subject: GH-2124 First complete implementation, installing is working now! GH-2172 Added sorting --- api/logic/modplatform/FtbPackInstallTask.cpp | 159 +++++++++++++++++++++++++-- 1 file changed, 151 insertions(+), 8 deletions(-) (limited to 'api/logic/modplatform/FtbPackInstallTask.cpp') diff --git a/api/logic/modplatform/FtbPackInstallTask.cpp b/api/logic/modplatform/FtbPackInstallTask.cpp index bedf3942..8c0bc70c 100644 --- a/api/logic/modplatform/FtbPackInstallTask.cpp +++ b/api/logic/modplatform/FtbPackInstallTask.cpp @@ -2,6 +2,11 @@ #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" FtbPackInstallTask::FtbPackInstallTask(FtbPackDownloader *downloader, SettingsObjectPtr settings, const QString &stagingPath, const QString &instName, const QString &instIcon, const QString &instGroup) : @@ -16,18 +21,19 @@ void FtbPackInstallTask::executeTask() { void FtbPackInstallTask::downloadPack(){ FtbModpack toInstall = m_downloader->getSelectedPack(); - setStatus(tr("Installing new FTB Pack %1").arg(toInstall.name)); + setStatus(tr("Downloading zip for %1").arg(toInstall.name)); - auto entry = ENV.metacache()->resolveEntry("general", "FTBPack/" + 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){ - qDebug() << "Download succeeded!"; + abortable = false; unzip(archivePath); } @@ -36,11 +42,14 @@ void FtbPackInstallTask::onDownloadFailed(QString reason) { } void FtbPackInstallTask::onDownloadProgress(qint64 current, qint64 total){ - progress(current, 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) { - setStatus(QString("Extracting modpack from %1").arg(archivePath)); + progress(2, 4); + setStatus(tr("Extracting modpack")); QDir extractDir(m_stagingPath); m_packZip.reset(new QuaZip(archivePath)); @@ -49,17 +58,151 @@ void FtbPackInstallTask::unzip(QString archivePath) { return; } - m_extractFuture = QtConcurrent::run(QThreadPool::globalInstance(), MMCZip::extractSubDir, m_packZip.get(), QString("/"), extractDir.absolutePath()); + m_extractFuture = QtConcurrent::run(QThreadPool::globalInstance(), MMCZip::extractDir, archivePath, extractDir.absolutePath() + "/unzip"); connect(&m_extractFutureWatcher, &QFutureWatcher::finished, this, &FtbPackInstallTask::onUnzipFinished); connect(&m_extractFutureWatcher, &QFutureWatcher::canceled, this, &FtbPackInstallTask::onUnzipCanceled); m_extractFutureWatcher.setFuture(m_extractFuture); } void FtbPackInstallTask::onUnzipFinished() { - qDebug() << "Unzipped:" << m_stagingPath; - emitSucceeded(); + 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 + moveRecursively(m_stagingPath + "/unzip/minecraft", m_stagingPath + "/.minecraft"); + } + + QString instanceConfigPath = FS::PathCombine(m_stagingPath, "instance.cfg"); + auto instanceSettings = std::make_shared(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; + } + + //It is always maven like + //net.minecraftforge:forge:1.7.10-10.13.4.1448-1.7.10:universal => 1.7.10-10.13.4.1448-1.7.10 + QString forgeVersion = nameValue.split(":").at(2); + + //1.7.10-10.13.4.1448-1.7.10 => 10.13.4.1448 + forgeVersion = forgeVersion.replace(toInstall.mcVersion, "").replace("-", ""); + components->setComponentVersion("net.minecraftforge", forgeVersion); + 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::moveRecursively(QString sourceFolder, QString destFolder) +{ + bool success = false; + QDir sourceDir(sourceFolder); + + if(!sourceDir.exists()) + return false; + + QDir destDir(destFolder); + if(!destDir.exists()) + destDir.mkdir(destFolder); + + QStringList files = sourceDir.entryList(QDir::Files); + for(int i = 0; i< files.count(); i++) { + QString srcName = sourceFolder + QDir::separator() + files[i]; + QString destName = destFolder + QDir::separator() + files[i]; + success = QFile::copy(srcName, destName); + if(!success) + return false; + QFile::remove(srcName); + } + + files.clear(); + files = sourceDir.entryList(QDir::AllDirs | QDir::NoDotAndDotDot); + for(int i = 0; i< files.count(); i++) + { + QString srcName = sourceFolder + QDir::separator() + files[i]; + QString destName = destFolder + QDir::separator() + files[i]; + success = moveRecursively(srcName, destName); + if(!success) + return false; + } + + return QDir(sourceFolder).rmdir(sourceFolder); +} + +bool FtbPackInstallTask::abort() { + if(abortable) { + return m_downloader->getNetJob()->abort(); + } + return false; +} -- cgit v1.2.3