aboutsummaryrefslogtreecommitdiff
path: root/launcher
diff options
context:
space:
mode:
Diffstat (limited to 'launcher')
-rw-r--r--launcher/Application.cpp1
-rw-r--r--launcher/InstanceImportTask.cpp22
-rw-r--r--launcher/InstanceImportTask.h1
-rwxr-xr-xlauncher/Launcher.in2
-rw-r--r--launcher/MMCZip.cpp60
-rw-r--r--launcher/minecraft/PackProfile.cpp39
-rw-r--r--launcher/minecraft/PackProfile.h10
-rw-r--r--launcher/ui/pages/instance/VersionPage.cpp22
-rw-r--r--launcher/ui/pages/instance/VersionPage.h7
-rw-r--r--launcher/ui/pages/instance/VersionPage.ui13
10 files changed, 129 insertions, 48 deletions
diff --git a/launcher/Application.cpp b/launcher/Application.cpp
index 2956d798..aed862dc 100644
--- a/launcher/Application.cpp
+++ b/launcher/Application.cpp
@@ -79,6 +79,7 @@
#include <iostream>
#include <mutex>
+#include <QFileOpenEvent>
#include <QAccessible>
#include <QCommandLineParser>
#include <QDir>
diff --git a/launcher/InstanceImportTask.cpp b/launcher/InstanceImportTask.cpp
index 70bf5784..080828a8 100644
--- a/launcher/InstanceImportTask.cpp
+++ b/launcher/InstanceImportTask.cpp
@@ -66,7 +66,12 @@ bool InstanceImportTask::abort()
if (m_filesNetJob)
m_filesNetJob->abort();
- m_extractFuture.cancel();
+ if (m_extractFuture.isRunning()) {
+ // NOTE: The tasks created by QtConcurrent::run() can't actually get cancelled,
+ // but we can use this call to check the state when the extraction finishes.
+ m_extractFuture.cancel();
+ m_extractFuture.waitForFinished();
+ }
return Task::abort();
}
@@ -185,18 +190,20 @@ void InstanceImportTask::processZipPack()
// make sure we extract just the pack
m_extractFuture = QtConcurrent::run(QThreadPool::globalInstance(), MMCZip::extractSubDir, m_packZip.get(), root, extractDir.absolutePath());
connect(&m_extractFutureWatcher, &QFutureWatcher<QStringList>::finished, this, &InstanceImportTask::extractFinished);
- connect(&m_extractFutureWatcher, &QFutureWatcher<QStringList>::canceled, this, &InstanceImportTask::extractAborted);
m_extractFutureWatcher.setFuture(m_extractFuture);
}
void InstanceImportTask::extractFinished()
{
m_packZip.reset();
- if (!m_extractFuture.result())
- {
+
+ if (m_extractFuture.isCanceled())
+ return;
+ if (!m_extractFuture.result().has_value()) {
emitFailed(tr("Failed to extract modpack"));
return;
}
+
QDir extractDir(m_stagingPath);
qDebug() << "Fixing permissions for extracted pack files...";
@@ -250,11 +257,6 @@ void InstanceImportTask::extractFinished()
}
}
-void InstanceImportTask::extractAborted()
-{
- emitAborted();
-}
-
void InstanceImportTask::processFlame()
{
FlameCreationTask* inst_creation_task = nullptr;
@@ -361,7 +363,7 @@ void InstanceImportTask::processModrinth()
} else {
QString pack_id;
if (!m_sourceUrl.isEmpty()) {
- QRegularExpression regex(R"(data\/(.*)\/versions)");
+ QRegularExpression regex(R"(data\/([^\/]*)\/versions)");
pack_id = regex.match(m_sourceUrl.toString()).captured(1);
}
diff --git a/launcher/InstanceImportTask.h b/launcher/InstanceImportTask.h
index 6b8ac966..7fda439f 100644
--- a/launcher/InstanceImportTask.h
+++ b/launcher/InstanceImportTask.h
@@ -81,7 +81,6 @@ private slots:
void downloadProgressChanged(qint64 current, qint64 total);
void downloadAborted();
void extractFinished();
- void extractAborted();
private: /* data */
NetJob::Ptr m_filesNetJob;
diff --git a/launcher/Launcher.in b/launcher/Launcher.in
index 68fac26a..1a23f255 100755
--- a/launcher/Launcher.in
+++ b/launcher/Launcher.in
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/usr/bin/env bash
# Basic start script for running the launcher with the libs packaged with it.
function printerror {
diff --git a/launcher/MMCZip.cpp b/launcher/MMCZip.cpp
index f6600343..c6d56543 100644
--- a/launcher/MMCZip.cpp
+++ b/launcher/MMCZip.cpp
@@ -275,7 +275,8 @@ bool MMCZip::findFilesInZip(QuaZip * zip, const QString & what, QStringList & re
// ours
std::optional<QStringList> MMCZip::extractSubDir(QuaZip *zip, const QString & subdir, const QString &target)
{
- QDir directory(target);
+ auto target_top_dir = QUrl::fromLocalFile(target);
+
QStringList extracted;
qDebug() << "Extracting subdir" << subdir << "from" << zip->getZipName() << "to" << target;
@@ -294,48 +295,53 @@ std::optional<QStringList> MMCZip::extractSubDir(QuaZip *zip, const QString & su
return std::nullopt;
}
- do
- {
- QString name = zip->getCurrentFileName();
- if(!name.startsWith(subdir))
- {
+ do {
+ QString file_name = zip->getCurrentFileName();
+ if (!file_name.startsWith(subdir))
continue;
- }
- name.remove(0, subdir.size());
- auto original_name = name;
+ auto relative_file_name = QDir::fromNativeSeparators(file_name.remove(0, subdir.size()));
+ auto original_name = relative_file_name;
+
+ // Fix subdirs/files ending with a / getting transformed into absolute paths
+ if (relative_file_name.startsWith('/'))
+ relative_file_name = relative_file_name.mid(1);
// Fix weird "folders with a single file get squashed" thing
- QString path;
- if(name.contains('/') && !name.endsWith('/')){
- path = name.section('/', 0, -2) + "/";
- FS::ensureFolderPathExists(FS::PathCombine(target, path));
+ QString sub_path;
+ if (relative_file_name.contains('/') && !relative_file_name.endsWith('/')) {
+ sub_path = relative_file_name.section('/', 0, -2) + '/';
+ FS::ensureFolderPathExists(FS::PathCombine(target, sub_path));
- name = name.split('/').last();
+ relative_file_name = relative_file_name.split('/').last();
}
- QString absFilePath;
- if(name.isEmpty())
- {
- absFilePath = directory.absoluteFilePath(name) + "/";
+ QString target_file_path;
+ if (relative_file_name.isEmpty()) {
+ target_file_path = target + '/';
+ } else {
+ target_file_path = FS::PathCombine(target_top_dir.path(), sub_path, relative_file_name);
+ if (relative_file_name.endsWith('/') && !target_file_path.endsWith('/'))
+ target_file_path += '/';
}
- else
- {
- absFilePath = directory.absoluteFilePath(path + name);
+
+ if (!target_top_dir.isParentOf(QUrl::fromLocalFile(target_file_path))) {
+ qWarning() << "Extracting" << relative_file_name << "was cancelled, because it was effectively outside of the target path" << target;
+ return std::nullopt;
}
- if (!JlCompress::extractFile(zip, "", absFilePath))
- {
- qWarning() << "Failed to extract file" << original_name << "to" << absFilePath;
+ if (!JlCompress::extractFile(zip, "", target_file_path)) {
+ qWarning() << "Failed to extract file" << original_name << "to" << target_file_path;
JlCompress::removeFile(extracted);
return std::nullopt;
}
- extracted.append(absFilePath);
- QFile::setPermissions(absFilePath, QFileDevice::Permission::ReadUser | QFileDevice::Permission::WriteUser | QFileDevice::Permission::ExeUser);
+ extracted.append(target_file_path);
+ QFile::setPermissions(target_file_path, QFileDevice::Permission::ReadUser | QFileDevice::Permission::WriteUser | QFileDevice::Permission::ExeUser);
- qDebug() << "Extracted file" << name << "to" << absFilePath;
+ qDebug() << "Extracted file" << relative_file_name << "to" << target_file_path;
} while (zip->goToNextFile());
+
return extracted;
}
diff --git a/launcher/minecraft/PackProfile.cpp b/launcher/minecraft/PackProfile.cpp
index da7c1d84..aff05dbc 100644
--- a/launcher/minecraft/PackProfile.cpp
+++ b/launcher/minecraft/PackProfile.cpp
@@ -1,7 +1,10 @@
-// SPDX-License-Identifier: GPL-3.0-only
+// SPDX-FileCopyrightText: 2022-2023 Sefa Eyeoglu <contact@scrumplex.net>
+//
+// SPDX-License-Identifier: GPL-3.0-only AND Apache-2.0
+
/*
* Prism Launcher - Minecraft Launcher
- * Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net>
+ * Copyright (C) 2022-2023 Sefa Eyeoglu <contact@scrumplex.net>
* Copyright (C) 2022 TheKodeToad <TheKodeToad@proton.me>
*
* This program is free software: you can redistribute it and/or modify
@@ -49,6 +52,7 @@
#include "minecraft/OneSixVersionFormat.h"
#include "FileSystem.h"
#include "minecraft/MinecraftInstance.h"
+#include "minecraft/ProfileUtils.h"
#include "Json.h"
#include "PackProfile.h"
@@ -730,16 +734,47 @@ void PackProfile::invalidateLaunchProfile()
void PackProfile::installJarMods(QStringList selectedFiles)
{
+ // FIXME: get rid of _internal
installJarMods_internal(selectedFiles);
}
void PackProfile::installCustomJar(QString selectedFile)
{
+ // FIXME: get rid of _internal
installCustomJar_internal(selectedFile);
}
+bool PackProfile::installComponents(QStringList selectedFiles)
+{
+ const QString patchDir = FS::PathCombine(d->m_instance->instanceRoot(), "patches");
+ if (!FS::ensureFolderPathExists(patchDir))
+ return false;
+
+ bool result = true;
+ for (const QString& source : selectedFiles) {
+ const QFileInfo sourceInfo(source);
+
+ auto versionFile = ProfileUtils::parseJsonFile(sourceInfo, false);
+ const QString target = FS::PathCombine(patchDir, versionFile->uid + ".json");
+
+ if (!QFile::copy(source, target)) {
+ qWarning() << "Component" << source << "could not be copied to target" << target;
+ result = false;
+ continue;
+ }
+
+ appendComponent(makeShared<Component>(this, versionFile->uid, versionFile));
+ }
+
+ scheduleSave();
+ invalidateLaunchProfile();
+
+ return result;
+}
+
void PackProfile::installAgents(QStringList selectedFiles)
{
+ // FIXME: get rid of _internal
installAgents_internal(selectedFiles);
}
diff --git a/launcher/minecraft/PackProfile.h b/launcher/minecraft/PackProfile.h
index 731cd0ba..d144d875 100644
--- a/launcher/minecraft/PackProfile.h
+++ b/launcher/minecraft/PackProfile.h
@@ -1,7 +1,10 @@
-// SPDX-License-Identifier: GPL-3.0-only
+// SPDX-FileCopyrightText: 2022-2023 Sefa Eyeoglu <contact@scrumplex.net>
+//
+// SPDX-License-Identifier: GPL-3.0-only AND Apache-2.0
+
/*
* Prism Launcher - Minecraft Launcher
- * Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net>
+ * Copyright (C) 2022-2023 Sefa Eyeoglu <contact@scrumplex.net>
* Copyright (C) 2022 TheKodeToad <TheKodeToad@proton.me>
*
* This program is free software: you can redistribute it and/or modify
@@ -86,6 +89,9 @@ public:
/// install a jar/zip as a replacement for the main jar
void installCustomJar(QString selectedFile);
+ /// install MMC/Prism component files
+ bool installComponents(QStringList selectedFiles);
+
/// install Java agent files
void installAgents(QStringList selectedFiles);
diff --git a/launcher/ui/pages/instance/VersionPage.cpp b/launcher/ui/pages/instance/VersionPage.cpp
index 94315395..7fff3b93 100644
--- a/launcher/ui/pages/instance/VersionPage.cpp
+++ b/launcher/ui/pages/instance/VersionPage.cpp
@@ -1,8 +1,11 @@
-// SPDX-License-Identifier: GPL-3.0-only
+// SPDX-FileCopyrightText: 2022-2023 Sefa Eyeoglu <contact@scrumplex.net>
+//
+// SPDX-License-Identifier: GPL-3.0-only AND Apache-2.0
+
/*
* Prism Launcher - Minecraft Launcher
* Copyright (c) 2022 Jamie Mansfield <jmansfield@cadixdev.org>
- * Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net>
+ * Copyright (C) 2022-2023 Sefa Eyeoglu <contact@scrumplex.net>
* Copyright (C) 2022 TheKodeToad <TheKodeToad@proton.me>
*
* This program is free software: you can redistribute it and/or modify
@@ -282,6 +285,7 @@ void VersionPage::updateButtons(int row)
ui->actionRevert->setEnabled(controlsEnabled && patch && patch->isRevertible());
ui->actionDownload_All->setEnabled(controlsEnabled);
ui->actionAdd_Empty->setEnabled(controlsEnabled);
+ ui->actionImport_Components->setEnabled(controlsEnabled);
ui->actionReload->setEnabled(controlsEnabled);
ui->actionInstall_mods->setEnabled(controlsEnabled);
ui->actionReplace_Minecraft_jar->setEnabled(controlsEnabled);
@@ -375,6 +379,20 @@ void VersionPage::on_actionReplace_Minecraft_jar_triggered()
updateButtons();
}
+void VersionPage::on_actionImport_Components_triggered()
+{
+ QStringList list = GuiUtil::BrowseForFiles("component", tr("Select components"), tr("Components (*.json)"),
+ APPLICATION->settings()->get("CentralModsDir").toString(), this->parentWidget());
+
+ if (!list.isEmpty()) {
+ if (!m_profile->installComponents(list)) {
+ QMessageBox::warning(this, tr("Failed to import components"),
+ tr("Some components could not be imported. Check logs for details"));
+ }
+ }
+
+ updateButtons();
+}
void VersionPage::on_actionAdd_Agents_triggered()
{
diff --git a/launcher/ui/pages/instance/VersionPage.h b/launcher/ui/pages/instance/VersionPage.h
index 183bad9a..d0087714 100644
--- a/launcher/ui/pages/instance/VersionPage.h
+++ b/launcher/ui/pages/instance/VersionPage.h
@@ -1,7 +1,11 @@
-// SPDX-License-Identifier: GPL-3.0-only
+// SPDX-FileCopyrightText: 2022-2023 Sefa Eyeoglu <contact@scrumplex.net>
+//
+// SPDX-License-Identifier: GPL-3.0-only AND Apache-2.0
+
/*
* Prism Launcher - Minecraft Launcher
* Copyright (c) 2022 Jamie Mansfield <jmansfield@cadixdev.org>
+ * Copyright (C) 2022-2023 Sefa Eyeoglu <contact@scrumplex.net>
* Copyright (C) 2022 TheKodeToad <TheKodeToad@proton.me>
*
* This program is free software: you can redistribute it and/or modify
@@ -86,6 +90,7 @@ private slots:
void on_actionMove_down_triggered();
void on_actionAdd_to_Minecraft_jar_triggered();
void on_actionReplace_Minecraft_jar_triggered();
+ void on_actionImport_Components_triggered();
void on_actionAdd_Agents_triggered();
void on_actionRevert_triggered();
void on_actionEdit_triggered();
diff --git a/launcher/ui/pages/instance/VersionPage.ui b/launcher/ui/pages/instance/VersionPage.ui
index 4cd50885..4777eafe 100644
--- a/launcher/ui/pages/instance/VersionPage.ui
+++ b/launcher/ui/pages/instance/VersionPage.ui
@@ -108,6 +108,7 @@
<addaction name="actionReplace_Minecraft_jar"/>
<addaction name="actionAdd_Agents"/>
<addaction name="actionAdd_Empty"/>
+ <addaction name="actionImport_Components"/>
<addaction name="separator"/>
<addaction name="actionMinecraftFolder"/>
<addaction name="actionLibrariesFolder"/>
@@ -226,10 +227,10 @@
</action>
<action name="actionAdd_Agents">
<property name="text">
- <string>Add Agents</string>
+ <string>Add Agents</string>
</property>
<property name="toolTip">
- <string>Add Java agents.</string>
+ <string>Add Java agents.</string>
</property>
</action>
<action name="actionAdd_Empty">
@@ -272,6 +273,14 @@
<string>Open the instance's local libraries folder.</string>
</property>
</action>
+ <action name="actionImport_Components">
+ <property name="text">
+ <string>Import Components</string>
+ </property>
+ <property name="toolTip">
+ <string>Import existing component JSON files.</string>
+ </property>
+ </action>
</widget>
<customwidgets>
<customwidget>