@ -17,23 +17,23 @@
|
||||
|
||||
#include <QtConcurrent>
|
||||
|
||||
#include "FileSystem.h"
|
||||
#include "MMCZip.h"
|
||||
#include "TechnicPackProcessor.h"
|
||||
#include "FileSystem.h"
|
||||
|
||||
#include "Application.h"
|
||||
|
||||
#include "net/ApiDownload.h"
|
||||
|
||||
Technic::SingleZipPackInstallTask::SingleZipPackInstallTask(const QUrl &sourceUrl, const QString &minecraftVersion)
|
||||
Technic::SingleZipPackInstallTask::SingleZipPackInstallTask(const QUrl& sourceUrl, const QString& minecraftVersion)
|
||||
{
|
||||
m_sourceUrl = sourceUrl;
|
||||
m_minecraftVersion = minecraftVersion;
|
||||
}
|
||||
|
||||
bool Technic::SingleZipPackInstallTask::abort() {
|
||||
if(m_abortable)
|
||||
{
|
||||
bool Technic::SingleZipPackInstallTask::abort()
|
||||
{
|
||||
if (m_abortable) {
|
||||
return m_filesNetJob->abort();
|
||||
}
|
||||
return false;
|
||||
@ -67,12 +67,12 @@ void Technic::SingleZipPackInstallTask::downloadSucceeded()
|
||||
|
||||
// open the zip and find relevant files in it
|
||||
m_packZip.reset(new QuaZip(m_archivePath));
|
||||
if (!m_packZip->open(QuaZip::mdUnzip))
|
||||
{
|
||||
if (!m_packZip->open(QuaZip::mdUnzip)) {
|
||||
emitFailed(tr("Unable to open supplied modpack zip file."));
|
||||
return;
|
||||
}
|
||||
m_extractFuture = QtConcurrent::run(QThreadPool::globalInstance(), MMCZip::extractSubDir, m_packZip.get(), QString(""), extractDir.absolutePath());
|
||||
m_extractFuture =
|
||||
QtConcurrent::run(QThreadPool::globalInstance(), MMCZip::extractSubDir, m_packZip.get(), QString(""), extractDir.absolutePath());
|
||||
connect(&m_extractFutureWatcher, &QFutureWatcher<QStringList>::finished, this, &Technic::SingleZipPackInstallTask::extractFinished);
|
||||
connect(&m_extractFutureWatcher, &QFutureWatcher<QStringList>::canceled, this, &Technic::SingleZipPackInstallTask::extractAborted);
|
||||
m_extractFutureWatcher.setFuture(m_extractFuture);
|
||||
@ -95,8 +95,7 @@ void Technic::SingleZipPackInstallTask::downloadProgressChanged(qint64 current,
|
||||
void Technic::SingleZipPackInstallTask::extractFinished()
|
||||
{
|
||||
m_packZip.reset();
|
||||
if (!m_extractFuture.result())
|
||||
{
|
||||
if (!m_extractFuture.result()) {
|
||||
emitFailed(tr("Failed to extract modpack"));
|
||||
return;
|
||||
}
|
||||
@ -104,30 +103,22 @@ void Technic::SingleZipPackInstallTask::extractFinished()
|
||||
|
||||
qDebug() << "Fixing permissions for extracted pack files...";
|
||||
QDirIterator it(extractDir, QDirIterator::Subdirectories);
|
||||
while (it.hasNext())
|
||||
{
|
||||
while (it.hasNext()) {
|
||||
auto filepath = it.next();
|
||||
QFileInfo file(filepath);
|
||||
auto permissions = QFile::permissions(filepath);
|
||||
auto origPermissions = permissions;
|
||||
if (file.isDir())
|
||||
{
|
||||
if (file.isDir()) {
|
||||
// Folder +rwx for current user
|
||||
permissions |= QFileDevice::Permission::ReadUser | QFileDevice::Permission::WriteUser | QFileDevice::Permission::ExeUser;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
// File +rw for current user
|
||||
permissions |= QFileDevice::Permission::ReadUser | QFileDevice::Permission::WriteUser;
|
||||
}
|
||||
if (origPermissions != permissions)
|
||||
{
|
||||
if (!QFile::setPermissions(filepath, permissions))
|
||||
{
|
||||
if (origPermissions != permissions) {
|
||||
if (!QFile::setPermissions(filepath, permissions)) {
|
||||
logWarning(tr("Could not fix permissions for %1").arg(filepath));
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
qDebug() << "Fixed" << filepath;
|
||||
}
|
||||
}
|
||||
|
@ -28,28 +28,26 @@
|
||||
|
||||
namespace Technic {
|
||||
|
||||
class SingleZipPackInstallTask : public InstanceTask
|
||||
{
|
||||
class SingleZipPackInstallTask : public InstanceTask {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
SingleZipPackInstallTask(const QUrl &sourceUrl, const QString &minecraftVersion);
|
||||
public:
|
||||
SingleZipPackInstallTask(const QUrl& sourceUrl, const QString& minecraftVersion);
|
||||
|
||||
bool canAbort() const override { return true; }
|
||||
bool abort() override;
|
||||
|
||||
protected:
|
||||
protected:
|
||||
void executeTask() override;
|
||||
|
||||
|
||||
private slots:
|
||||
private slots:
|
||||
void downloadSucceeded();
|
||||
void downloadFailed(QString reason);
|
||||
void downloadProgressChanged(qint64 current, qint64 total);
|
||||
void extractFinished();
|
||||
void extractAborted();
|
||||
|
||||
private:
|
||||
private:
|
||||
bool m_abortable = false;
|
||||
|
||||
QUrl m_sourceUrl;
|
||||
@ -61,4 +59,4 @@ private:
|
||||
QFutureWatcher<std::optional<QStringList>> m_extractFutureWatcher;
|
||||
};
|
||||
|
||||
} // namespace Technic
|
||||
} // namespace Technic
|
||||
|
@ -42,8 +42,8 @@
|
||||
|
||||
#include "SolderPackManifest.h"
|
||||
#include "TechnicPackProcessor.h"
|
||||
#include "net/ChecksumValidator.h"
|
||||
#include "net/ApiDownload.h"
|
||||
#include "net/ChecksumValidator.h"
|
||||
|
||||
Technic::SolderPackInstallTask::SolderPackInstallTask(shared_qobject_ptr<QNetworkAccessManager> network,
|
||||
const QUrl& solderUrl,
|
||||
@ -97,8 +97,7 @@ void Technic::SolderPackInstallTask::fileListSucceeded()
|
||||
TechnicSolder::PackBuild build;
|
||||
try {
|
||||
TechnicSolder::loadPackBuild(build, obj);
|
||||
}
|
||||
catch (const JSONValidationError& e) {
|
||||
} catch (const JSONValidationError& e) {
|
||||
emitFailed(tr("Could not understand pack manifest:\n") + e.cause());
|
||||
m_filesNetJob.reset();
|
||||
return;
|
||||
@ -139,17 +138,14 @@ void Technic::SolderPackInstallTask::downloadSucceeded()
|
||||
|
||||
setStatus(tr("Extracting modpack"));
|
||||
m_filesNetJob.reset();
|
||||
m_extractFuture = QtConcurrent::run([this]()
|
||||
{
|
||||
m_extractFuture = QtConcurrent::run([this]() {
|
||||
int i = 0;
|
||||
QString extractDir = FS::PathCombine(m_stagingPath, ".minecraft");
|
||||
FS::ensureFolderPathExists(extractDir);
|
||||
|
||||
while (m_modCount > i)
|
||||
{
|
||||
while (m_modCount > i) {
|
||||
auto path = FS::PathCombine(m_outputDir.path(), QString("%1").arg(i));
|
||||
if (!MMCZip::extractDir(path, extractDir))
|
||||
{
|
||||
if (!MMCZip::extractDir(path, extractDir)) {
|
||||
return false;
|
||||
}
|
||||
i++;
|
||||
@ -182,8 +178,7 @@ void Technic::SolderPackInstallTask::downloadAborted()
|
||||
|
||||
void Technic::SolderPackInstallTask::extractFinished()
|
||||
{
|
||||
if (!m_extractFuture.result())
|
||||
{
|
||||
if (!m_extractFuture.result()) {
|
||||
emitFailed(tr("Failed to extract modpack"));
|
||||
return;
|
||||
}
|
||||
@ -191,30 +186,22 @@ void Technic::SolderPackInstallTask::extractFinished()
|
||||
|
||||
qDebug() << "Fixing permissions for extracted pack files...";
|
||||
QDirIterator it(extractDir, QDirIterator::Subdirectories);
|
||||
while (it.hasNext())
|
||||
{
|
||||
while (it.hasNext()) {
|
||||
auto filepath = it.next();
|
||||
QFileInfo file(filepath);
|
||||
auto permissions = QFile::permissions(filepath);
|
||||
auto origPermissions = permissions;
|
||||
if(file.isDir())
|
||||
{
|
||||
if (file.isDir()) {
|
||||
// Folder +rwx for current user
|
||||
permissions |= QFileDevice::Permission::ReadUser | QFileDevice::Permission::WriteUser | QFileDevice::Permission::ExeUser;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
// File +rw for current user
|
||||
permissions |= QFileDevice::Permission::ReadUser | QFileDevice::Permission::WriteUser;
|
||||
}
|
||||
if(origPermissions != permissions)
|
||||
{
|
||||
if(!QFile::setPermissions(filepath, permissions))
|
||||
{
|
||||
if (origPermissions != permissions) {
|
||||
if (!QFile::setPermissions(filepath, permissions)) {
|
||||
logWarning(tr("Could not fix permissions for %1").arg(filepath));
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
qDebug() << "Fixed" << filepath;
|
||||
}
|
||||
}
|
||||
@ -230,4 +217,3 @@ void Technic::SolderPackInstallTask::extractAborted()
|
||||
{
|
||||
emitFailed(tr("Instance import has been aborted."));
|
||||
}
|
||||
|
||||
|
@ -55,4 +55,4 @@ void loadPackBuild(PackBuild& v, QJsonObject& obj)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
} // namespace TechnicSolder
|
||||
|
@ -18,9 +18,9 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QJsonObject>
|
||||
#include <QString>
|
||||
#include <QVector>
|
||||
#include <QJsonObject>
|
||||
|
||||
namespace TechnicSolder {
|
||||
|
||||
@ -46,4 +46,4 @@ struct PackBuild {
|
||||
|
||||
void loadPackBuild(PackBuild& v, QJsonObject& obj);
|
||||
|
||||
}
|
||||
} // namespace TechnicSolder
|
||||
|
@ -40,8 +40,7 @@ void Technic::TechnicPackProcessor::run(SettingsObjectPtr globalSettings,
|
||||
|
||||
instance.setName(instName);
|
||||
|
||||
if (instIcon != "default")
|
||||
{
|
||||
if (instIcon != "default") {
|
||||
instance.setIconKey(instIcon);
|
||||
}
|
||||
|
||||
@ -53,23 +52,18 @@ void Technic::TechnicPackProcessor::run(SettingsObjectPtr globalSettings,
|
||||
QString modpackJar = FS::PathCombine(minecraftPath, "bin", "modpack.jar");
|
||||
QString versionJson = FS::PathCombine(minecraftPath, "bin", "version.json");
|
||||
QString fmlMinecraftVersion;
|
||||
if (QFile::exists(modpackJar))
|
||||
{
|
||||
if (QFile::exists(modpackJar)) {
|
||||
QuaZip zipFile(modpackJar);
|
||||
if (!zipFile.open(QuaZip::mdUnzip))
|
||||
{
|
||||
if (!zipFile.open(QuaZip::mdUnzip)) {
|
||||
emit failed(tr("Unable to open \"bin/modpack.jar\" file!"));
|
||||
return;
|
||||
}
|
||||
QuaZipDir zipFileRoot(&zipFile, "/");
|
||||
if (zipFileRoot.exists("/version.json"))
|
||||
{
|
||||
if (zipFileRoot.exists("/fmlversion.properties"))
|
||||
{
|
||||
if (zipFileRoot.exists("/version.json")) {
|
||||
if (zipFileRoot.exists("/fmlversion.properties")) {
|
||||
zipFile.setCurrentFile("fmlversion.properties");
|
||||
QuaZipFile file(&zipFile);
|
||||
if (!file.open(QIODevice::ReadOnly))
|
||||
{
|
||||
if (!file.open(QIODevice::ReadOnly)) {
|
||||
emit failed(tr("Unable to open \"fmlversion.properties\"!"));
|
||||
return;
|
||||
}
|
||||
@ -82,30 +76,25 @@ void Technic::TechnicPackProcessor::run(SettingsObjectPtr globalSettings,
|
||||
}
|
||||
zipFile.setCurrentFile("version.json", QuaZip::csSensitive);
|
||||
QuaZipFile file(&zipFile);
|
||||
if (!file.open(QIODevice::ReadOnly))
|
||||
{
|
||||
if (!file.open(QIODevice::ReadOnly)) {
|
||||
emit failed(tr("Unable to open \"version.json\"!"));
|
||||
return;
|
||||
}
|
||||
data = file.readAll();
|
||||
file.close();
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
if (minecraftVersion.isEmpty())
|
||||
emit failed(tr("Could not find \"version.json\" inside \"bin/modpack.jar\", but Minecraft version is unknown"));
|
||||
components->setComponentVersion("net.minecraft", minecraftVersion, true);
|
||||
components->installJarMods({modpackJar});
|
||||
components->installJarMods({ modpackJar });
|
||||
|
||||
// Forge for 1.4.7 and for 1.5.2 require extra libraries.
|
||||
// Figure out the forge version and add it as a component
|
||||
// (the code still comes from the jar mod installed above)
|
||||
if (zipFileRoot.exists("/forgeversion.properties"))
|
||||
{
|
||||
if (zipFileRoot.exists("/forgeversion.properties")) {
|
||||
zipFile.setCurrentFile("forgeversion.properties", QuaZip::csSensitive);
|
||||
QuaZipFile file(&zipFile);
|
||||
if (!file.open(QIODevice::ReadOnly))
|
||||
{
|
||||
if (!file.open(QIODevice::ReadOnly)) {
|
||||
// Really shouldn't happen, but error handling shall not be forgotten
|
||||
emit failed(tr("Unable to open \"forgeversion.properties\""));
|
||||
return;
|
||||
@ -120,8 +109,7 @@ void Technic::TechnicPackProcessor::run(SettingsObjectPtr globalSettings,
|
||||
revision = iniFile["forge.revision.number"].toString();
|
||||
build = iniFile["forge.build.number"].toString();
|
||||
|
||||
if (major.isEmpty() || minor.isEmpty() || revision.isEmpty() || build.isEmpty())
|
||||
{
|
||||
if (major.isEmpty() || minor.isEmpty() || revision.isEmpty() || build.isEmpty()) {
|
||||
emit failed(tr("Invalid \"forgeversion.properties\"!"));
|
||||
return;
|
||||
}
|
||||
@ -133,83 +121,63 @@ void Technic::TechnicPackProcessor::run(SettingsObjectPtr globalSettings,
|
||||
emit succeeded();
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (QFile::exists(versionJson))
|
||||
{
|
||||
} else if (QFile::exists(versionJson)) {
|
||||
QFile file(versionJson);
|
||||
if (!file.open(QIODevice::ReadOnly))
|
||||
{
|
||||
if (!file.open(QIODevice::ReadOnly)) {
|
||||
emit failed(tr("Unable to open \"version.json\"!"));
|
||||
return;
|
||||
}
|
||||
data = file.readAll();
|
||||
file.close();
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
// This is the "Vanilla" modpack, excluded by the search code
|
||||
emit failed(tr("Unable to find a \"version.json\"!"));
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
try {
|
||||
QJsonDocument doc = Json::requireDocument(data);
|
||||
QJsonObject root = Json::requireObject(doc, "version.json");
|
||||
QString packMinecraftVersion = Json::ensureString(root, "inheritsFrom", QString(), "");
|
||||
if (packMinecraftVersion.isEmpty()) {
|
||||
if (fmlMinecraftVersion.isEmpty())
|
||||
{
|
||||
if (fmlMinecraftVersion.isEmpty()) {
|
||||
emit failed(tr("Could not understand \"version.json\":\ninheritsFrom is missing"));
|
||||
return;
|
||||
}
|
||||
packMinecraftVersion = fmlMinecraftVersion;
|
||||
}
|
||||
components->setComponentVersion("net.minecraft", packMinecraftVersion, true);
|
||||
for (auto library: Json::ensureArray(root, "libraries", {}))
|
||||
{
|
||||
if (!library.isObject())
|
||||
{
|
||||
for (auto library : Json::ensureArray(root, "libraries", {})) {
|
||||
if (!library.isObject()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
auto libraryObject = Json::ensureObject(library, {}, "");
|
||||
auto libraryName = Json::ensureString(libraryObject, "name", "", "");
|
||||
|
||||
if ((libraryName.startsWith("net.minecraftforge:forge:") || libraryName.startsWith("net.minecraftforge:fmlloader:")) && libraryName.contains('-'))
|
||||
{
|
||||
if ((libraryName.startsWith("net.minecraftforge:forge:") || libraryName.startsWith("net.minecraftforge:fmlloader:")) &&
|
||||
libraryName.contains('-')) {
|
||||
QString libraryVersion = libraryName.section(':', 2);
|
||||
if (!libraryVersion.startsWith("1.7.10-"))
|
||||
{
|
||||
if (!libraryVersion.startsWith("1.7.10-")) {
|
||||
components->setComponentVersion("net.minecraftforge", libraryName.section('-', 1));
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
// 1.7.10 versions sometimes look like 1.7.10-10.13.4.1614-1.7.10, this filters out the 10.13.4.1614 part
|
||||
components->setComponentVersion("net.minecraftforge", libraryName.section('-', 1, 1));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
// <Technic library name prefix> -> <our component name>
|
||||
static QMap<QString, QString> loaderMap {
|
||||
{"net.minecraftforge:minecraftforge:", "net.minecraftforge"},
|
||||
{"net.fabricmc:fabric-loader:", "net.fabricmc.fabric-loader"},
|
||||
{"org.quiltmc:quilt-loader:", "org.quiltmc.quilt-loader"}
|
||||
};
|
||||
for (const auto& loader : loaderMap.keys())
|
||||
{
|
||||
if (libraryName.startsWith(loader))
|
||||
{
|
||||
static QMap<QString, QString> loaderMap{ { "net.minecraftforge:minecraftforge:", "net.minecraftforge" },
|
||||
{ "net.fabricmc:fabric-loader:", "net.fabricmc.fabric-loader" },
|
||||
{ "org.quiltmc:quilt-loader:", "org.quiltmc.quilt-loader" } };
|
||||
for (const auto& loader : loaderMap.keys()) {
|
||||
if (libraryName.startsWith(loader)) {
|
||||
components->setComponentVersion(loaderMap.value(loader), libraryName.section(':', 2));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (const JSONValidationError &e)
|
||||
{
|
||||
} catch (const JSONValidationError& e) {
|
||||
emit failed(tr("Could not understand \"version.json\":\n") + e.cause());
|
||||
return;
|
||||
}
|
||||
|
@ -18,18 +18,21 @@
|
||||
#include <QString>
|
||||
#include "settings/SettingsObject.h"
|
||||
|
||||
namespace Technic
|
||||
{
|
||||
// not exporting it, only used in SingleZipPackInstallTask, InstanceImportTask and SolderPackInstallTask
|
||||
class TechnicPackProcessor : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
namespace Technic {
|
||||
// not exporting it, only used in SingleZipPackInstallTask, InstanceImportTask and SolderPackInstallTask
|
||||
class TechnicPackProcessor : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
signals:
|
||||
void succeeded();
|
||||
void failed(QString reason);
|
||||
signals:
|
||||
void succeeded();
|
||||
void failed(QString reason);
|
||||
|
||||
public:
|
||||
void run(SettingsObjectPtr globalSettings, const QString &instName, const QString &instIcon, const QString &stagingPath, const QString &minecraftVersion=QString(), const bool isSolder = false);
|
||||
};
|
||||
}
|
||||
public:
|
||||
void run(SettingsObjectPtr globalSettings,
|
||||
const QString& instName,
|
||||
const QString& instIcon,
|
||||
const QString& stagingPath,
|
||||
const QString& minecraftVersion = QString(),
|
||||
const bool isSolder = false);
|
||||
};
|
||||
} // namespace Technic
|
||||
|
Reference in New Issue
Block a user