Revert "Merge in Changes from Prism 9.2"

This reverts commit b4b9051793.
This commit is contained in:
Luna 2025-01-11 14:19:46 -06:00
parent 32b45d0fd7
commit 41e90afbab
140 changed files with 803 additions and 1063 deletions

View File

@ -59,14 +59,14 @@ jobs:
qt_ver: 5
qt_host: linux
qt_arch: ""
qt_version: "5.15.2"
qt_version: "5.12.8"
qt_modules: "qtnetworkauth"
- os: ubuntu-20.04
qt_ver: 6
qt_host: linux
qt_arch: ""
qt_version: "6.5.3"
qt_version: "6.2.4"
qt_modules: "qt5compat qtimageformats qtnetworkauth"
- os: windows-2022
@ -173,7 +173,7 @@ jobs:
- name: Retrieve ccache cache (Windows MinGW-w64)
if: runner.os == 'Windows' && matrix.msystem != '' && inputs.build_type == 'Debug'
uses: actions/cache@v4.2.0
uses: actions/cache@v4.1.1
with:
path: '${{ github.workspace }}\.ccache'
key: ${{ matrix.os }}-mingw-w64-ccache-${{ github.run_id }}
@ -206,7 +206,7 @@ jobs:
if: runner.os == 'Linux'
run: |
sudo apt-get -y update
sudo apt-get -y install ninja-build extra-cmake-modules scdoc appstream libxcb-cursor-dev
sudo apt-get -y install ninja-build extra-cmake-modules scdoc appstream
- name: Install Dependencies (macOS)
if: runner.os == 'macOS'
@ -633,7 +633,7 @@ jobs:
flatpak:
runs-on: ubuntu-latest
container:
image: ghcr.io/flathub-infra/flatpak-github-actions:kde-6.8
image: bilelmoussaoui/flatpak-github-actions:kde-6.7
options: --privileged
steps:
- name: Checkout

View File

@ -389,8 +389,8 @@ if(UNIX AND APPLE)
set(MACOSX_SPARKLE_UPDATE_PUBLIC_KEY "" CACHE STRING "Public key for Sparkle update feed")
set(MACOSX_SPARKLE_UPDATE_FEED_URL "" CACHE STRING "URL for Sparkle update feed")
set(MACOSX_SPARKLE_DOWNLOAD_URL "https://github.com/sparkle-project/Sparkle/releases/download/2.6.4/Sparkle-2.6.4.tar.xz" CACHE STRING "URL to Sparkle release archive")
set(MACOSX_SPARKLE_SHA256 "50612a06038abc931f16011d7903b8326a362c1074dabccb718404ce8e585f0b" CACHE STRING "SHA256 checksum for Sparkle release archive")
set(MACOSX_SPARKLE_DOWNLOAD_URL "https://github.com/sparkle-project/Sparkle/releases/download/2.5.2/Sparkle-2.5.2.tar.xz" CACHE STRING "URL to Sparkle release archive")
set(MACOSX_SPARKLE_SHA256 "572dd67ae398a466f19f343a449e1890bac1ef74885b4739f68f979a8a89884b" CACHE STRING "SHA256 checksum for Sparkle release archive")
set(MACOSX_SPARKLE_DIR "${CMAKE_BINARY_DIR}/frameworks/Sparkle")
# directories to look for dependencies

View File

@ -8,8 +8,6 @@
<string>A Minecraft mod wants to access your microphone.</string>
<key>NSDownloadsFolderUsageDescription</key>
<string>Shattered Prism uses access to your Downloads folder to help you more quickly add mods that can't be automatically downloaded to your instance. You can change where Shattered Prism scans for downloaded mods in Settings or the prompt that appears.</string>
<key>NSLocalNetworkUsageDescription</key>
<string>Minecraft uses the local network to find and connect to LAN servers.</string>
<key>NSPrincipalClass</key>
<string>NSApplication</string>
<key>NSHighResolutionCapable</key>

View File

@ -1,20 +0,0 @@
{
"name": "flite",
"config-opts": [
"--enable-shared",
"--with-audio=pulseaudio"
],
"no-parallel-make": true,
"sources": [
{
"type": "git",
"url": "https://github.com/festvox/flite.git",
"tag": "v2.2",
"commit": "e9e2e37c329dbe98bfeb27a1828ef9a71fa84f88",
"x-checker-data": {
"type": "git",
"tag-pattern": "^v([\\d.]+)$"
}
}
]
}

View File

@ -8,7 +8,11 @@
{
"type": "git",
"url": "https://gitlab.freedesktop.org/libdecor/libdecor.git",
"commit": "c2bd8ad6fa42c0cb17553ce77ad8a87d1f543b1f"
"commit": "73260393a97291c887e1074ab7f318e031be0ac6"
},
{
"type": "patch",
"path": "patches/weird_libdecor.patch"
}
],
"cleanup": [

View File

@ -1,6 +1,6 @@
id: org.lunaislazier.ShatteredPrism
runtime: org.kde.Platform
runtime-version: '6.8'
runtime-version: 6.7
sdk: org.kde.Sdk
sdk-extensions:
- org.freedesktop.Sdk.Extension.openjdk17
@ -19,12 +19,6 @@ finish-args:
- --filesystem=xdg-download:ro
# FTBApp import
- --filesystem=~/.ftba:ro
# Userspace visibility for manual hugepages configuration
# Required for -XX:+UseLargePages
- --filesystem=/sys/kernel/mm/hugepages:ro
# Userspace visibility for transparent hugepages configuration
# Required for -XX:+UseTransparentHugePages
- --filesystem=/sys/kernel/mm/transparent_hugepage:ro
modules:
# Might be needed by some Controller mods (see https://github.com/isXander/Controlify/issues/31)
@ -33,16 +27,11 @@ modules:
# Needed for proper Wayland support
- libdecor.json
# Text to Speech in the game
- flite.json
- name: shatteredprism
buildsystem: cmake-ninja
builddir: true
config-opts:
- -DLauncher_BUILD_PLATFORM=flatpak
# This allows us to manage and update Java independently of this Flatpak
- -DLauncher_ENABLE_JAVA_DOWNLOADER=ON
- -DCMAKE_BUILD_TYPE=RelWithDebInfo
build-options:
env:
@ -58,14 +47,18 @@ modules:
config-opts:
- -DCMAKE_BUILD_TYPE=RelWithDebInfo
- -DBUILD_SHARED_LIBS:BOOL=ON
- -DGLFW_BUILD_WAYLAND:BOOL=ON
- -DGLFW_USE_WAYLAND:BOOL=ON
- -DGLFW_BUILD_DOCS:BOOL=OFF
sources:
- type: git
url: https://github.com/glfw/glfw.git
commit: 7b6aead9fb88b3623e3b3725ebb42670cbe4c579 # 3.4
commit: 3fa2360720eeba1964df3c0ecf4b5df8648a8e52
- type: patch
path: patches/0009-Defer-setting-cursor-position-until-the-cursor-is-lo.patch
path: patches/0003-Don-t-crash-on-calls-to-focus-or-icon.patch
- type: patch
path: patches/0005-Add-warning-about-being-an-unofficial-patch.patch
- type: patch
path: patches/0007-Platform-Prefer-Wayland-over-X11.patch
cleanup:
- /include
- /lib/cmake
@ -75,8 +68,8 @@ modules:
buildsystem: autotools
sources:
- type: archive
url: https://xorg.freedesktop.org/archive/individual/app/xrandr-1.5.3.tar.xz
sha256: f8dd7566adb74147fab9964680b6bbadee87cf406a7fcff51718a5e6949b841c
url: https://xorg.freedesktop.org/archive/individual/app/xrandr-1.5.2.tar.xz
sha256: c8bee4790d9058bacc4b6246456c58021db58a87ddda1a9d0139bf5f18f1f240
x-checker-data:
type: anitya
project-id: 14957
@ -98,8 +91,8 @@ modules:
sources:
- type: archive
dest-filename: gamemode.tar.gz
url: https://api.github.com/repos/FeralInteractive/gamemode/tarball/1.8.2
sha256: 2886d4ce543c78bd2a364316d5e7fd59ef06b71de63f896b37c6d3dc97658f60
url: https://api.github.com/repos/FeralInteractive/gamemode/tarball/1.8.1
sha256: 969cf85b5ca3944f3e315cd73a0ee9bea4f9c968cd7d485e9f4745bc1e679c4e
x-checker-data:
type: json
url: https://api.github.com/repos/FeralInteractive/gamemode/releases/latest

View File

@ -0,0 +1,24 @@
diff --git a/src/wl_window.c b/src/wl_window.c
index 52d3b9eb..4ac4eb5d 100644
--- a/src/wl_window.c
+++ b/src/wl_window.c
@@ -2117,8 +2117,7 @@ void _glfwSetWindowTitleWayland(_GLFWwindow* window, const char* title)
void _glfwSetWindowIconWayland(_GLFWwindow* window,
int count, const GLFWimage* images)
{
- _glfwInputError(GLFW_FEATURE_UNAVAILABLE,
- "Wayland: The platform does not support setting the window icon");
+ fprintf(stderr, "!!! Ignoring Error: Wayland: The platform does not support setting the window icon\n");
}
void _glfwGetWindowPosWayland(_GLFWwindow* window, int* xpos, int* ypos)
@@ -2361,8 +2360,7 @@ void _glfwRequestWindowAttentionWayland(_GLFWwindow* window)
void _glfwFocusWindowWayland(_GLFWwindow* window)
{
- _glfwInputError(GLFW_FEATURE_UNAVAILABLE,
- "Wayland: The platform does not support setting the input focus");
+ fprintf(stderr, "!!! Ignoring Error: Wayland: The platform does not support setting the input focus\n");
}
void _glfwSetWindowMonitorWayland(_GLFWwindow* window,

View File

@ -0,0 +1,17 @@
diff --git a/src/init.c b/src/init.c
index 06dbb3f2..a7c6da86 100644
--- a/src/init.c
+++ b/src/init.c
@@ -449,6 +449,12 @@ GLFWAPI int glfwInit(void)
_glfw.initialized = GLFW_TRUE;
glfwDefaultWindowHints();
+
+ fprintf(stderr, "!!! Patched GLFW from https://github.com/Admicos/minecraft-wayland\n"
+ "!!! If any issues with the window, or some issues with rendering, occur, "
+ "first try with the built-in GLFW, and if that solves the issue, report there first.\n"
+ "!!! Use outside Minecraft is untested, and things might break.\n");
+
return GLFW_TRUE;
}

View File

@ -0,0 +1,20 @@
diff --git a/src/platform.c b/src/platform.c
index c5966ae7..3e7442f9 100644
--- a/src/platform.c
+++ b/src/platform.c
@@ -49,12 +49,12 @@ static const struct
#if defined(_GLFW_COCOA)
{ GLFW_PLATFORM_COCOA, _glfwConnectCocoa },
#endif
-#if defined(_GLFW_X11)
- { GLFW_PLATFORM_X11, _glfwConnectX11 },
-#endif
#if defined(_GLFW_WAYLAND)
{ GLFW_PLATFORM_WAYLAND, _glfwConnectWayland },
#endif
+#if defined(_GLFW_X11)
+ { GLFW_PLATFORM_X11, _glfwConnectX11 },
+#endif
};
GLFWbool _glfwSelectPlatform(int desiredID, _GLFWplatform* platform)

View File

@ -1,59 +0,0 @@
From 9997ae55a47de469ea26f8437c30b51483abda5f Mon Sep 17 00:00:00 2001
From: Dan Klishch <danilklishch@gmail.com>
Date: Sat, 30 Sep 2023 23:38:05 -0400
Subject: Defer setting cursor position until the cursor is locked
---
src/wl_platform.h | 3 +++
src/wl_window.c | 14 ++++++++++++--
2 files changed, 15 insertions(+), 2 deletions(-)
diff --git a/src/wl_platform.h b/src/wl_platform.h
index ca34f66e..cd1f227f 100644
--- a/src/wl_platform.h
+++ b/src/wl_platform.h
@@ -403,6 +403,9 @@ typedef struct _GLFWwindowWayland
int scaleSize;
int compositorPreferredScale;
+ double askedCursorPosX, askedCursorPosY;
+ GLFWbool didAskForSetCursorPos;
+
struct zwp_relative_pointer_v1* relativePointer;
struct zwp_locked_pointer_v1* lockedPointer;
struct zwp_confined_pointer_v1* confinedPointer;
diff --git a/src/wl_window.c b/src/wl_window.c
index 1de26558..0df16747 100644
--- a/src/wl_window.c
+++ b/src/wl_window.c
@@ -2586,8 +2586,9 @@ void _glfwGetCursorPosWayland(_GLFWwindow* window, double* xpos, double* ypos)
void _glfwSetCursorPosWayland(_GLFWwindow* window, double x, double y)
{
- _glfwInputError(GLFW_FEATURE_UNAVAILABLE,
- "Wayland: The platform does not support setting the cursor position");
+ window->wl.didAskForSetCursorPos = true;
+ window->wl.askedCursorPosX = x;
+ window->wl.askedCursorPosY = y;
}
void _glfwSetCursorModeWayland(_GLFWwindow* window, int mode)
@@ -2819,6 +2820,15 @@ static const struct zwp_relative_pointer_v1_listener relativePointerListener =
static void lockedPointerHandleLocked(void* userData,
struct zwp_locked_pointer_v1* lockedPointer)
{
+ _GLFWwindow* window = userData;
+
+ if (window->wl.didAskForSetCursorPos)
+ {
+ window->wl.didAskForSetCursorPos = false;
+ zwp_locked_pointer_v1_set_cursor_position_hint(window->wl.lockedPointer,
+ wl_fixed_from_double(window->wl.askedCursorPosX),
+ wl_fixed_from_double(window->wl.askedCursorPosY));
+ }
}
static void lockedPointerHandleUnlocked(void* userData,
--
2.42.0

View File

@ -0,0 +1,40 @@
diff --git a/src/libdecor.c b/src/libdecor.c
index a9c1106..1aa38b3 100644
--- a/src/libdecor.c
+++ b/src/libdecor.c
@@ -1391,22 +1391,32 @@ calculate_priority(const struct libdecor_plugin_description *plugin_description)
static bool
check_symbol_conflicts(const struct libdecor_plugin_description *plugin_description)
{
+ bool ret = true;
char * const *symbol;
+ void* main_prog = dlopen(NULL, RTLD_LAZY);
+ if (!main_prog) {
+ fprintf(stderr, "Plugin \"%s\" couldn't check conflicting symbols: \"%s\".\n",
+ plugin_description->description, dlerror());
+ return false;
+ }
+
symbol = plugin_description->conflicting_symbols;
while (*symbol) {
dlerror();
- dlsym (RTLD_DEFAULT, *symbol);
+ dlsym (main_prog, *symbol);
if (!dlerror()) {
fprintf(stderr, "Plugin \"%s\" uses conflicting symbol \"%s\".\n",
plugin_description->description, *symbol);
- return false;
+ ret = false;
+ break;
}
symbol++;
}
- return true;
+ dlclose(main_prog);
+ return ret;
}
static struct plugin_loader *

View File

@ -48,7 +48,6 @@
#include "net/PasteUpload.h"
#include "pathmatcher/MultiMatcher.h"
#include "pathmatcher/SimplePrefixMatcher.h"
#include "tasks/Task.h"
#include "tools/GenericProfiler.h"
#include "ui/InstanceWindow.h"
#include "ui/MainWindow.h"
@ -1093,9 +1092,6 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv)
bool Application::createSetupWizard()
{
bool javaRequired = [&]() {
if (BuildConfig.JAVA_DOWNLOADER_ENABLED && m_settings->get("AutomaticJavaDownload").toBool()) {
return false;
}
bool ignoreJavaWizard = m_settings->get("IgnoreJavaWizard").toBool();
if (ignoreJavaWizard) {
return false;
@ -1108,7 +1104,10 @@ bool Application::createSetupWizard()
}
QString currentJavaPath = settings()->get("JavaPath").toString();
QString actualPath = FS::ResolveExecutable(currentJavaPath);
return actualPath.isNull();
if (actualPath.isNull()) {
return true;
}
return false;
}();
bool askjava = BuildConfig.JAVA_DOWNLOADER_ENABLED && !javaRequired && !m_settings->get("AutomaticJavaDownload").toBool() &&
!m_settings->get("AutomaticJavaSwitch").toBool() && !m_settings->get("UserAskedAboutAutomaticJavaDownload").toBool();
@ -1427,7 +1426,6 @@ bool Application::launch(InstancePtr instance, bool online, bool demo, Minecraft
if (m_updateRunning) {
qDebug() << "Cannot launch instances while an update is running. Please try again when updates are completed.";
} else if (instance->canLaunch()) {
QMutexLocker locker(&m_instanceExtrasMutex);
auto& extras = m_instanceExtras[instance->id()];
auto window = extras.window;
if (window) {
@ -1452,7 +1450,7 @@ bool Application::launch(InstancePtr instance, bool online, bool demo, Minecraft
connect(controller.get(), &LaunchController::failed, this, &Application::controllerFailed);
connect(controller.get(), &LaunchController::aborted, this, [this] { controllerFailed(tr("Aborted")); });
addRunningInstance();
QMetaObject::invokeMethod(controller.get(), &Task::start, Qt::QueuedConnection);
controller->start();
return true;
} else if (instance->isRunning()) {
showInstanceWindow(instance, "console");
@ -1470,11 +1468,9 @@ bool Application::kill(InstancePtr instance)
qWarning() << "Attempted to kill instance" << instance->id() << ", which isn't running.";
return false;
}
QMutexLocker locker(&m_instanceExtrasMutex);
auto& extras = m_instanceExtras[instance->id()];
// NOTE: copy of the shared pointer keeps it alive
auto controller = extras.controller;
locker.unlock();
if (controller) {
return controller->abort();
}
@ -1528,14 +1524,12 @@ void Application::controllerSucceeded()
if (!controller)
return;
auto id = controller->id();
QMutexLocker locker(&m_instanceExtrasMutex);
auto& extras = m_instanceExtras[id];
// on success, do...
if (controller->instance()->settings()->get("AutoCloseConsole").toBool()) {
if (extras.window) {
QMetaObject::invokeMethod(extras.window, &QWidget::close, Qt::QueuedConnection);
extras.window->close();
}
}
extras.controller.reset();
@ -1555,7 +1549,6 @@ void Application::controllerFailed(const QString& error)
if (!controller)
return;
auto id = controller->id();
QMutexLocker locker(&m_instanceExtrasMutex);
auto& extras = m_instanceExtras[id];
// on failure, do... nothing
@ -1613,7 +1606,6 @@ InstanceWindow* Application::showInstanceWindow(InstancePtr instance, QString pa
if (!instance)
return nullptr;
auto id = instance->id();
QMutexLocker locker(&m_instanceExtrasMutex);
auto& extras = m_instanceExtras[id];
auto& window = extras.window;
@ -1651,7 +1643,6 @@ void Application::on_windowClose()
m_openWindows--;
auto instWindow = qobject_cast<InstanceWindow*>(QObject::sender());
if (instWindow) {
QMutexLocker locker(&m_instanceExtrasMutex);
auto& extras = m_instanceExtras[instWindow->instanceId()];
extras.window = nullptr;
if (extras.controller) {
@ -1899,7 +1890,7 @@ bool Application::handleDataMigration(const QString& currentData,
matcher->add(std::make_shared<SimplePrefixMatcher>("themes/"));
ProgressDialog diag;
DataMigrationTask task(oldData, currentData, matcher);
DataMigrationTask task(nullptr, oldData, currentData, matcher);
if (diag.execWithTask(&task)) {
qDebug() << "<> Migration succeeded";
setDoNotMigrate();
@ -1938,31 +1929,3 @@ const QString Application::javaPath()
{
return m_settings->get("JavaDir").toString();
}
void Application::addQSavePath(QString path)
{
QMutexLocker locker(&m_qsaveResourcesMutex);
m_qsaveResources[path] = m_qsaveResources.value(path, 0) + 1;
}
void Application::removeQSavePath(QString path)
{
QMutexLocker locker(&m_qsaveResourcesMutex);
auto count = m_qsaveResources.value(path, 0) - 1;
if (count <= 0) {
m_qsaveResources.remove(path);
} else {
m_qsaveResources[path] = count;
}
}
bool Application::checkQSavePath(QString path)
{
QMutexLocker locker(&m_qsaveResourcesMutex);
for (auto partialPath : m_qsaveResources.keys()) {
if (path.startsWith(partialPath) && m_qsaveResources.value(partialPath, 0) > 0) {
return true;
}
}
return false;
}

View File

@ -42,7 +42,6 @@
#include <QDebug>
#include <QFlag>
#include <QIcon>
#include <QMutex>
#include <QUrl>
#include <memory>
@ -279,7 +278,6 @@ class Application : public QApplication {
shared_qobject_ptr<LaunchController> controller;
};
std::map<QString, InstanceXtras> m_instanceExtras;
mutable QMutex m_instanceExtrasMutex;
// main state variables
size_t m_openWindows = 0;
@ -305,13 +303,4 @@ class Application : public QApplication {
QList<QUrl> m_urlsToImport;
QString m_instanceIdToShowWindowOf;
std::unique_ptr<QFile> logFile;
public:
void addQSavePath(QString);
void removeQSavePath(QString);
bool checkQSavePath(QString);
private:
QHash<QString, int> m_qsaveResources;
mutable QMutex m_qsaveResourcesMutex;
};

View File

@ -30,7 +30,6 @@ set(CORE_SOURCES
StringUtils.cpp
QVariantUtils.h
RuntimeContext.h
PSaveFile.h
# Basic instance manipulation tasks (derived from InstanceTask)
InstanceCreationTask.h

View File

@ -12,8 +12,11 @@
#include <QtConcurrent>
DataMigrationTask::DataMigrationTask(const QString& sourcePath, const QString& targetPath, const IPathMatcher::Ptr pathMatcher)
: Task(), m_sourcePath(sourcePath), m_targetPath(targetPath), m_pathMatcher(pathMatcher), m_copy(sourcePath, targetPath)
DataMigrationTask::DataMigrationTask(QObject* parent,
const QString& sourcePath,
const QString& targetPath,
const IPathMatcher::Ptr pathMatcher)
: Task(parent), m_sourcePath(sourcePath), m_targetPath(targetPath), m_pathMatcher(pathMatcher), m_copy(sourcePath, targetPath)
{
m_copy.matcher(m_pathMatcher.get()).whitelist(true);
}

View File

@ -18,7 +18,7 @@
class DataMigrationTask : public Task {
Q_OBJECT
public:
explicit DataMigrationTask(const QString& sourcePath, const QString& targetPath, IPathMatcher::Ptr pathmatcher);
explicit DataMigrationTask(QObject* parent, const QString& sourcePath, const QString& targetPath, IPathMatcher::Ptr pathmatcher);
~DataMigrationTask() override = default;
protected:

View File

@ -45,6 +45,7 @@
#include <QDirIterator>
#include <QFile>
#include <QFileInfo>
#include <QSaveFile>
#include <QStandardPaths>
#include <QStorageInfo>
#include <QTextStream>
@ -53,7 +54,6 @@
#include <system_error>
#include "DesktopServices.h"
#include "PSaveFile.h"
#include "StringUtils.h"
#if defined Q_OS_WIN32
@ -191,8 +191,8 @@ void ensureExists(const QDir& dir)
void write(const QString& filename, const QByteArray& data)
{
ensureExists(QFileInfo(filename).dir());
PSaveFile file(filename);
if (!file.open(PSaveFile::WriteOnly)) {
QSaveFile file(filename);
if (!file.open(QSaveFile::WriteOnly)) {
throw FileSystemException("Couldn't open " + filename + " for writing: " + file.errorString());
}
if (data.size() != file.write(data)) {
@ -213,8 +213,8 @@ void appendSafe(const QString& filename, const QByteArray& data)
buffer = QByteArray();
}
buffer.append(data);
PSaveFile file(filename);
if (!file.open(PSaveFile::WriteOnly)) {
QSaveFile file(filename);
if (!file.open(QSaveFile::WriteOnly)) {
throw FileSystemException("Couldn't open " + filename + " for writing: " + file.errorString());
}
if (buffer.size() != file.write(buffer)) {
@ -971,7 +971,8 @@ bool createShortcut(QString destination, QString target, QStringList args, QStri
if (!args.empty())
argstring = " \"" + args.join("\" \"") + "\"";
stream << "#!/bin/bash" << "\n";
stream << "#!/bin/bash"
<< "\n";
stream << "\"" << target << "\" " << argstring << "\n";
stream.flush();
@ -1015,9 +1016,12 @@ bool createShortcut(QString destination, QString target, QStringList args, QStri
if (!args.empty())
argstring = " '" + args.join("' '") + "'";
stream << "[Desktop Entry]" << "\n";
stream << "Type=Application" << "\n";
stream << "Categories=Game;ActionGame;AdventureGame;Simulation" << "\n";
stream << "[Desktop Entry]"
<< "\n";
stream << "Type=Application"
<< "\n";
stream << "Categories=Game;ActionGame;AdventureGame;Simulation"
<< "\n";
stream << "Exec=\"" << target.toLocal8Bit() << "\"" << argstring.toLocal8Bit() << "\n";
stream << "Name=" << name.toLocal8Bit() << "\n";
if (!icon.isEmpty()) {

View File

@ -61,6 +61,6 @@ void InstanceCreationTask::executeTask()
return;
}
}
if (!m_abort)
emitSucceeded();
}

View File

@ -69,11 +69,9 @@ bool InstanceImportTask::abort()
if (!canAbort())
return false;
bool wasAborted = false;
if (m_task)
wasAborted = m_task->abort();
Task::abort();
return wasAborted;
if (task)
task->abort();
return Task::abort();
}
void InstanceImportTask::executeTask()
@ -106,7 +104,7 @@ void InstanceImportTask::downloadFromUrl()
connect(filesNetJob.get(), &NetJob::stepProgress, this, &InstanceImportTask::propagateStepProgress);
connect(filesNetJob.get(), &NetJob::failed, this, &InstanceImportTask::emitFailed);
connect(filesNetJob.get(), &NetJob::aborted, this, &InstanceImportTask::emitAborted);
m_task.reset(filesNetJob);
task.reset(filesNetJob);
filesNetJob->start();
}
@ -195,7 +193,7 @@ void InstanceImportTask::processZipPack()
stepProgress(*progressStep);
});
connect(zipTask.get(), &Task::succeeded, this, &InstanceImportTask::extractFinished, Qt::QueuedConnection);
connect(zipTask.get(), &Task::succeeded, this, &InstanceImportTask::extractFinished);
connect(zipTask.get(), &Task::aborted, this, &InstanceImportTask::emitAborted);
connect(zipTask.get(), &Task::failed, this, [this, progressStep](QString reason) {
progressStep->state = TaskStepState::Failed;
@ -212,13 +210,12 @@ void InstanceImportTask::processZipPack()
progressStep->status = status;
stepProgress(*progressStep);
});
m_task.reset(zipTask);
task.reset(zipTask);
zipTask->start();
}
void InstanceImportTask::extractFinished()
{
setAbortable(false);
QDir extractDir(m_stagingPath);
qDebug() << "Fixing permissions for extracted pack files...";
@ -292,11 +289,8 @@ void InstanceImportTask::processFlame()
inst_creation_task->setGroup(m_instGroup);
inst_creation_task->setConfirmUpdate(shouldConfirmUpdate());
auto weak = inst_creation_task.toWeakRef();
connect(inst_creation_task.get(), &Task::succeeded, this, [this, weak] {
if (auto sp = weak.lock()) {
setOverride(sp->shouldOverride(), sp->originalInstanceID());
}
connect(inst_creation_task.get(), &Task::succeeded, this, [this, inst_creation_task] {
setOverride(inst_creation_task->shouldOverride(), inst_creation_task->originalInstanceID());
emitSucceeded();
});
connect(inst_creation_task.get(), &Task::failed, this, &InstanceImportTask::emitFailed);
@ -305,12 +299,11 @@ void InstanceImportTask::processFlame()
connect(inst_creation_task.get(), &Task::status, this, &InstanceImportTask::setStatus);
connect(inst_creation_task.get(), &Task::details, this, &InstanceImportTask::setDetails);
connect(this, &Task::aborted, inst_creation_task.get(), &InstanceCreationTask::abort);
connect(inst_creation_task.get(), &Task::aborted, this, &Task::abort);
connect(inst_creation_task.get(), &Task::abortStatusChanged, this, &Task::setAbortable);
m_task.reset(inst_creation_task);
setAbortable(true);
m_task->start();
inst_creation_task->start();
}
void InstanceImportTask::processTechnic()
@ -357,7 +350,7 @@ void InstanceImportTask::processMultiMC()
void InstanceImportTask::processModrinth()
{
shared_qobject_ptr<ModrinthCreationTask> inst_creation_task = nullptr;
ModrinthCreationTask* inst_creation_task = nullptr;
if (!m_extra_info.isEmpty()) {
auto pack_id_it = m_extra_info.constFind("pack_id");
Q_ASSERT(pack_id_it != m_extra_info.constEnd());
@ -374,7 +367,7 @@ void InstanceImportTask::processModrinth()
original_instance_id = original_instance_id_it.value();
inst_creation_task =
makeShared<ModrinthCreationTask>(m_stagingPath, m_globalSettings, m_parent, pack_id, pack_version_id, original_instance_id);
new ModrinthCreationTask(m_stagingPath, m_globalSettings, m_parent, pack_id, pack_version_id, original_instance_id);
} else {
QString pack_id;
if (!m_sourceUrl.isEmpty()) {
@ -383,7 +376,7 @@ void InstanceImportTask::processModrinth()
}
// FIXME: Find a way to get the ID in directly imported ZIPs
inst_creation_task = makeShared<ModrinthCreationTask>(m_stagingPath, m_globalSettings, m_parent, pack_id);
inst_creation_task = new ModrinthCreationTask(m_stagingPath, m_globalSettings, m_parent, pack_id);
}
inst_creation_task->setName(*this);
@ -391,23 +384,20 @@ void InstanceImportTask::processModrinth()
inst_creation_task->setGroup(m_instGroup);
inst_creation_task->setConfirmUpdate(shouldConfirmUpdate());
auto weak = inst_creation_task.toWeakRef();
connect(inst_creation_task.get(), &Task::succeeded, this, [this, weak] {
if (auto sp = weak.lock()) {
setOverride(sp->shouldOverride(), sp->originalInstanceID());
}
connect(inst_creation_task, &Task::succeeded, this, [this, inst_creation_task] {
setOverride(inst_creation_task->shouldOverride(), inst_creation_task->originalInstanceID());
emitSucceeded();
});
connect(inst_creation_task.get(), &Task::failed, this, &InstanceImportTask::emitFailed);
connect(inst_creation_task.get(), &Task::progress, this, &InstanceImportTask::setProgress);
connect(inst_creation_task.get(), &Task::stepProgress, this, &InstanceImportTask::propagateStepProgress);
connect(inst_creation_task.get(), &Task::status, this, &InstanceImportTask::setStatus);
connect(inst_creation_task.get(), &Task::details, this, &InstanceImportTask::setDetails);
connect(inst_creation_task, &Task::failed, this, &InstanceImportTask::emitFailed);
connect(inst_creation_task, &Task::progress, this, &InstanceImportTask::setProgress);
connect(inst_creation_task, &Task::stepProgress, this, &InstanceImportTask::propagateStepProgress);
connect(inst_creation_task, &Task::status, this, &InstanceImportTask::setStatus);
connect(inst_creation_task, &Task::details, this, &InstanceImportTask::setDetails);
connect(inst_creation_task, &Task::finished, inst_creation_task, &InstanceCreationTask::deleteLater);
connect(inst_creation_task.get(), &Task::aborted, this, &Task::abort);
connect(inst_creation_task.get(), &Task::abortStatusChanged, this, &Task::setAbortable);
connect(this, &Task::aborted, inst_creation_task, &InstanceCreationTask::abort);
connect(inst_creation_task, &Task::aborted, this, &Task::abort);
connect(inst_creation_task, &Task::abortStatusChanged, this, &Task::setAbortable);
m_task.reset(inst_creation_task);
setAbortable(true);
m_task->start();
inst_creation_task->start();
}

View File

@ -40,13 +40,16 @@
#include <QUrl>
#include "InstanceTask.h"
#include <memory>
#include <optional>
class QuaZip;
class InstanceImportTask : public InstanceTask {
Q_OBJECT
public:
explicit InstanceImportTask(const QUrl& sourceUrl, QWidget* parent = nullptr, QMap<QString, QString>&& extra_info = {});
virtual ~InstanceImportTask() = default;
bool abort() override;
protected:
@ -67,7 +70,7 @@ class InstanceImportTask : public InstanceTask {
private: /* data */
QUrl m_sourceUrl;
QString m_archivePath;
Task::Ptr m_task;
Task::Ptr task;
enum class ModpackType {
Unknown,
MultiMC,

View File

@ -116,7 +116,7 @@ void JavaCommon::TestCheck::run()
emit finished();
return;
}
checker.reset(new JavaChecker(m_path, "", 0, 0, 0, 0));
checker.reset(new JavaChecker(m_path, "", 0, 0, 0, 0, this));
connect(checker.get(), &JavaChecker::checkFinished, this, &JavaCommon::TestCheck::checkFinished);
checker->start();
}
@ -128,7 +128,7 @@ void JavaCommon::TestCheck::checkFinished(const JavaChecker::Result& result)
emit finished();
return;
}
checker.reset(new JavaChecker(m_path, m_args, m_maxMem, m_maxMem, result.javaVersion.requiresPermGen() ? m_permGen : 0, 0));
checker.reset(new JavaChecker(m_path, m_args, m_maxMem, m_maxMem, result.javaVersion.requiresPermGen() ? m_permGen : 0, 0, this));
connect(checker.get(), &JavaChecker::checkFinished, this, &JavaCommon::TestCheck::checkFinishedWithArgs);
checker->start();
}

View File

@ -64,7 +64,7 @@
#include "launch/steps/TextPrint.h"
#include "tasks/Task.h"
LaunchController::LaunchController() : Task() {}
LaunchController::LaunchController(QObject* parent) : Task(parent) {}
void LaunchController::executeTask()
{

View File

@ -49,7 +49,7 @@ class LaunchController : public Task {
public:
void executeTask() override;
LaunchController();
LaunchController(QObject* parent = nullptr);
virtual ~LaunchController() = default;
void setInstance(InstancePtr instance) { m_instance = instance; }

View File

@ -39,16 +39,8 @@ if [ "x$DEPS_LIST" = "x" ]; then
# Just to be sure...
chmod +x "${LAUNCHER_DIR}/bin/${LAUNCHER_NAME}"
ARGS=("${LAUNCHER_DIR}/${LAUNCHER_NAME}" "${LAUNCHER_DIR}/bin/${LAUNCHER_NAME}")
if [ -f portable.txt ]; then
ARGS+=("-d" "${LAUNCHER_DIR}")
fi
ARGS+=("$@")
# Run the launcher
exec -a "${ARGS[@]}"
exec -a "${LAUNCHER_DIR}/${LAUNCHER_NAME}" "${LAUNCHER_DIR}/bin/${LAUNCHER_NAME}" -d "${LAUNCHER_DIR}" "$@"
# Run the launcher in valgrind
# valgrind --log-file="valgrind.log" --leak-check=full --track-origins=yes "${LAUNCHER_DIR}/bin/${LAUNCHER_NAME}" -d "${LAUNCHER_DIR}" "$@"

View File

@ -378,7 +378,7 @@ std::optional<QStringList> extractDir(QString fileCompressed, QString dir)
if (fileInfo.size() == 22) {
return QStringList();
}
qWarning() << "Could not open archive for unpacking:" << fileCompressed << "Error:" << zip.getZipError();
qWarning() << "Could not open archive for unzipping:" << fileCompressed << "Error:" << zip.getZipError();
;
return std::nullopt;
}
@ -395,7 +395,7 @@ std::optional<QStringList> extractDir(QString fileCompressed, QString subdir, QS
if (fileInfo.size() == 22) {
return QStringList();
}
qWarning() << "Could not open archive for unpacking:" << fileCompressed << "Error:" << zip.getZipError();
qWarning() << "Could not open archive for unzipping:" << fileCompressed << "Error:" << zip.getZipError();
;
return std::nullopt;
}
@ -412,7 +412,7 @@ bool extractFile(QString fileCompressed, QString file, QString target)
if (fileInfo.size() == 22) {
return true;
}
qWarning() << "Could not open archive for unpacking:" << fileCompressed << "Error:" << zip.getZipError();
qWarning() << "Could not open archive for unzipping:" << fileCompressed << "Error:" << zip.getZipError();
return false;
}
return extractRelFile(&zip, file, target);
@ -577,7 +577,7 @@ auto ExtractZipTask::extractZip() -> ZipResult
auto relative_file_name = QDir::fromNativeSeparators(file_name.mid(m_subdirectory.size()));
auto original_name = relative_file_name;
setStatus("Unpacking: " + relative_file_name);
setStatus("Unziping: " + relative_file_name);
// Fix subdirs/files ending with a / getting transformed into absolute paths
if (relative_file_name.startsWith('/'))

View File

@ -1,71 +0,0 @@
// SPDX-License-Identifier: GPL-3.0-only
/*
* Prism Launcher - Minecraft Launcher
* Copyright (c) 2023-2024 Trial97 <alexandru.tripon97@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#pragma once
#include <QFileInfo>
#include <QSaveFile>
#include "Application.h"
#if defined(LAUNCHER_APPLICATION)
/* PSaveFile
* A class that mimics QSaveFile for Windows.
*
* When reading resources, we need to avoid accessing temporary files
* generated by QSaveFile. If we start reading such a file, we may
* inadvertently keep it open while QSaveFile is trying to remove it,
* or we might detect the file just before it is removed, leading to
* race conditions and errors.
*
* Unfortunately, QSaveFile doesn't provide a way to retrieve the
* temporary file name or to set a specific template for the temporary
* file name it uses. By default, QSaveFile appends a `.XXXXXX` suffix
* to the original file name, where the `XXXXXX` part is dynamically
* generated to ensure uniqueness.
*
* This class acts like a lock by adding and removing the target file
* name into/from a global string set, helping to manage access to
* files during critical operations.
*
* Note: Please do not use the `setFileName` function directly, as it
* is not virtual and cannot be overridden.
*/
class PSaveFile : public QSaveFile {
public:
PSaveFile(const QString& name) : QSaveFile(name) { addPath(name); }
PSaveFile(const QString& name, QObject* parent) : QSaveFile(name, parent) { addPath(name); }
virtual ~PSaveFile()
{
if (auto app = APPLICATION_DYN) {
app->removeQSavePath(m_absoluteFilePath);
}
}
private:
void addPath(const QString& path)
{
m_absoluteFilePath = QFileInfo(path).absoluteFilePath() + "."; // add dot for tmp files only
if (auto app = APPLICATION_DYN) {
app->addQSavePath(m_absoluteFilePath);
}
}
QString m_absoluteFilePath;
};
#else
#define PSaveFile QSaveFile
#endif

View File

@ -81,9 +81,9 @@ QString getSupportedJavaArchitecture()
if (arch == "arm64")
return "mac-os-arm64";
if (arch.contains("64"))
return "mac-os-x64";
return "mac-os-64";
if (arch.contains("86"))
return "mac-os-x86";
return "mac-os-86";
// Unknown, maybe something new, appending arch
return "mac-os-" + arch;
} else if (sys == "linux") {

View File

@ -44,8 +44,8 @@
#include "FileSystem.h"
#include "java/JavaUtils.h"
JavaChecker::JavaChecker(QString path, QString args, int minMem, int maxMem, int permGen, int id)
: Task(), m_path(path), m_args(args), m_minMem(minMem), m_maxMem(maxMem), m_permGen(permGen), m_id(id)
JavaChecker::JavaChecker(QString path, QString args, int minMem, int maxMem, int permGen, int id, QObject* parent)
: Task(parent), m_path(path), m_args(args), m_minMem(minMem), m_maxMem(maxMem), m_permGen(permGen), m_id(id)
{}
void JavaChecker::executeTask()

View File

@ -1,6 +1,7 @@
#pragma once
#include <QProcess>
#include <QTimer>
#include <memory>
#include "JavaVersion.h"
#include "QObjectPtr.h"
@ -25,7 +26,7 @@ class JavaChecker : public Task {
enum class Validity { Errored, ReturnedInvalidData, Valid } validity = Validity::Errored;
};
explicit JavaChecker(QString path, QString args, int minMem = 0, int maxMem = 0, int permGen = 0, int id = 0);
explicit JavaChecker(QString path, QString args, int minMem = 0, int maxMem = 0, int permGen = 0, int id = 0, QObject* parent = 0);
signals:
void checkFinished(const Result& result);

View File

@ -163,7 +163,7 @@ void JavaListLoadTask::executeTask()
JavaUtils ju;
QList<QString> candidate_paths = m_only_managed_versions ? getPrismJavaBundle() : ju.FindJavaPaths();
ConcurrentTask::Ptr job(new ConcurrentTask("Java detection", APPLICATION->settings()->get("NumberOfConcurrentTasks").toInt()));
ConcurrentTask::Ptr job(new ConcurrentTask(this, "Java detection", APPLICATION->settings()->get("NumberOfConcurrentTasks").toInt()));
m_job.reset(job);
connect(m_job.get(), &Task::finished, this, &JavaListLoadTask::javaCheckerFinished);
connect(m_job.get(), &Task::progress, this, &Task::setProgress);
@ -171,7 +171,7 @@ void JavaListLoadTask::executeTask()
qDebug() << "Probing the following Java paths: ";
int id = 0;
for (QString candidate : candidate_paths) {
auto checker = new JavaChecker(candidate, "", 0, 0, 0, id);
auto checker = new JavaChecker(candidate, "", 0, 0, 0, id, this);
connect(checker, &JavaChecker::checkFinished, [this](const JavaChecker::Result& result) { m_results << result; });
job->addTask(Task::Ptr(checker));
id++;

View File

@ -102,8 +102,6 @@ QProcessEnvironment CleanEnviroment()
QString newValue = stripVariableEntries(key, value, rawenv.value("LAUNCHER_" + key));
qDebug() << "Env: stripped" << key << value << "to" << newValue;
value = newValue;
}
#if defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD) || defined(Q_OS_OPENBSD)
// Strip IBus

View File

@ -86,10 +86,11 @@ void ManifestDownloadTask::downloadJava(const QJsonDocument& doc)
if (type == "directory") {
FS::ensureFolderPathExists(file);
} else if (type == "link") {
// this is *nix only !
// this is linux only !
auto path = Json::ensureString(meta, "target");
if (!path.isEmpty()) {
QFile::link(path, file);
auto target = FS::PathCombine(file, "../" + path);
QFile(target).link(file);
}
} else if (type == "file") {
// TODO download compressed version if it exists ?

View File

@ -16,7 +16,7 @@
#include "LaunchStep.h"
#include "LaunchTask.h"
LaunchStep::LaunchStep(LaunchTask* parent) : Task(), m_parent(parent)
LaunchStep::LaunchStep(LaunchTask* parent) : Task(parent), m_parent(parent)
{
connect(this, &LaunchStep::readyForLaunch, parent, &LaunchTask::onReadyForLaunch);
connect(this, &LaunchStep::logLine, parent, &LaunchTask::onLogLine);

View File

@ -94,7 +94,7 @@ void CheckJava::executeTask()
// if timestamps are not the same, or something is missing, check!
if (m_javaSignature != storedSignature || storedVersion.size() == 0 || storedArchitecture.size() == 0 ||
storedRealArchitecture.size() == 0 || storedVendor.size() == 0) {
m_JavaChecker.reset(new JavaChecker(realJavaPath, "", 0, 0, 0, 0));
m_JavaChecker.reset(new JavaChecker(realJavaPath, "", 0, 0, 0, 0, this));
emit logLine(QString("Checking Java version..."), MessageLevel::Launcher);
connect(m_JavaChecker.get(), &JavaChecker::checkFinished, this, &CheckJava::checkJavaFinished);
m_JavaChecker->start();

View File

@ -140,8 +140,8 @@ Task::Ptr Index::loadVersion(const QString& uid, const QString& version, Net::Mo
}
auto versionList = get(uid);
auto loadTask =
makeShared<SequentialTask>(tr("Load meta for %1:%2", "This is for the task name that loads the meta index.").arg(uid, version));
auto loadTask = makeShared<SequentialTask>(
this, tr("Load meta for %1:%2", "This is for the task name that loads the meta index.").arg(uid, version));
if (status() != BaseEntity::LoadStatus::Remote || force) {
loadTask->addTask(this->loadTask(mode));
}

View File

@ -34,7 +34,8 @@ VersionList::VersionList(const QString& uid, QObject* parent) : BaseVersionList(
Task::Ptr VersionList::getLoadTask()
{
auto loadTask = makeShared<SequentialTask>(tr("Load meta for %1", "This is for the task name that loads the meta index.").arg(m_uid));
auto loadTask =
makeShared<SequentialTask>(this, tr("Load meta for %1", "This is for the task name that loads the meta index.").arg(m_uid));
loadTask->addTask(APPLICATION->metadataIndex()->loadTask(Net::Mode::Online));
loadTask->addTask(this->loadTask(Net::Mode::Online));
return loadTask;

View File

@ -222,11 +222,10 @@ bool Component::isMoveable()
return true;
}
bool Component::isVersionChangeable(bool wait)
bool Component::isVersionChangeable()
{
auto list = getVersionList();
if (list) {
if (wait)
list->waitToLoad();
return list->count() != 0;
}

View File

@ -72,7 +72,7 @@ class Component : public QObject, public ProblemProvider {
bool isRevertible();
bool isRemovable();
bool isCustom();
bool isVersionChangeable(bool wait = true);
bool isVersionChangeable();
bool isKnownModloader();
QStringList knownConflictingComponents();

View File

@ -38,7 +38,7 @@
* If the component list changes, start over.
*/
ComponentUpdateTask::ComponentUpdateTask(Mode mode, Net::Mode netmode, PackProfile* list) : Task()
ComponentUpdateTask::ComponentUpdateTask(Mode mode, Net::Mode netmode, PackProfile* list, QObject* parent) : Task(parent)
{
d.reset(new ComponentUpdateTaskData);
d->m_profile = list;

View File

@ -14,7 +14,7 @@ class ComponentUpdateTask : public Task {
enum class Mode { Launch, Resolution };
public:
explicit ComponentUpdateTask(Mode mode, Net::Mode netmode, PackProfile* list);
explicit ComponentUpdateTask(Mode mode, Net::Mode netmode, PackProfile* list, QObject* parent = 0);
virtual ~ComponentUpdateTask();
protected:

View File

@ -1141,7 +1141,7 @@ shared_qobject_ptr<LaunchTask> MinecraftInstance::createLaunchTask(AuthSessionPt
// load meta
{
auto mode = session->status != AuthSession::PlayableOffline ? Net::Mode::Online : Net::Mode::Offline;
process->appendStep(makeShared<TaskStepWrapper>(pptr, makeShared<MinecraftLoadAndCheck>(this, mode)));
process->appendStep(makeShared<TaskStepWrapper>(pptr, makeShared<MinecraftLoadAndCheck>(this, mode, pptr)));
}
// check java

View File

@ -2,7 +2,9 @@
#include "MinecraftInstance.h"
#include "PackProfile.h"
MinecraftLoadAndCheck::MinecraftLoadAndCheck(MinecraftInstance* inst, Net::Mode netmode) : m_inst(inst), m_netmode(netmode) {}
MinecraftLoadAndCheck::MinecraftLoadAndCheck(MinecraftInstance* inst, Net::Mode netmode, QObject* parent)
: Task(parent), m_inst(inst), m_netmode(netmode)
{}
void MinecraftLoadAndCheck::executeTask()
{

View File

@ -23,7 +23,7 @@ class MinecraftInstance;
class MinecraftLoadAndCheck : public Task {
Q_OBJECT
public:
explicit MinecraftLoadAndCheck(MinecraftInstance* inst, Net::Mode netmode);
explicit MinecraftLoadAndCheck(MinecraftInstance* inst, Net::Mode netmode, QObject* parent = nullptr);
virtual ~MinecraftLoadAndCheck() = default;
void executeTask() override;

View File

@ -38,6 +38,7 @@
#include <QDebug>
#include <QDir>
#include <QDirIterator>
#include <QSaveFile>
#include <QString>
#include <FileSystem.h>
@ -56,7 +57,6 @@
#include <optional>
#include "FileSystem.h"
#include "PSaveFile.h"
using std::nullopt;
using std::optional;
@ -183,7 +183,7 @@ bool putLevelDatDataToFS(const QFileInfo& file, QByteArray& data)
if (fullFilePath.isNull()) {
return false;
}
PSaveFile f(fullFilePath);
QSaveFile f(fullFilePath);
if (!f.open(QIODevice::WriteOnly)) {
return false;
}

View File

@ -21,7 +21,7 @@
#include <Application.h>
AuthFlow::AuthFlow(AccountData* data, Action action) : Task(), m_data(data)
AuthFlow::AuthFlow(AccountData* data, Action action, QObject* parent, const std::optional<QString> password) : Task(parent), m_data(data)
{
if (data->type == AccountType::MSA) {
if (action == Action::DeviceCode) {

View File

@ -18,7 +18,10 @@ class AuthFlow : public Task {
public:
enum class Action { Refresh, Login, DeviceCode };
explicit AuthFlow(AccountData* data, Action action = Action::Refresh);
explicit AuthFlow(AccountData* data,
Action action = Action::Refresh,
QObject* parent = 0,
std::optional<QString> password = std::nullopt);
virtual ~AuthFlow() = default;
void executeTask() override;

View File

@ -138,7 +138,7 @@ shared_qobject_ptr<AuthFlow> MinecraftAccount::login(bool useDeviceCode, std::op
{
Q_ASSERT(m_currentTask.get() == nullptr);
m_currentTask.reset(new AuthFlow(&data, useDeviceCode ? AuthFlow::Action::DeviceCode : AuthFlow::Action::Login));
m_currentTask.reset(new AuthFlow(&data, useDeviceCode ? AuthFlow::Action::DeviceCode : AuthFlow::Action::Login, this, password));
connect(m_currentTask.get(), &Task::succeeded, this, &MinecraftAccount::authSucceeded);
connect(m_currentTask.get(), &Task::failed, this, &MinecraftAccount::authFailed);
connect(m_currentTask.get(), &Task::aborted, this, [this] { authFailed(tr("Aborted")); });
@ -152,7 +152,7 @@ shared_qobject_ptr<AuthFlow> MinecraftAccount::refresh()
return m_currentTask;
}
m_currentTask.reset(new AuthFlow(&data, AuthFlow::Action::Refresh));
m_currentTask.reset(new AuthFlow(&data, AuthFlow::Action::Refresh, this));
connect(m_currentTask.get(), &Task::succeeded, this, &MinecraftAccount::authSucceeded);
connect(m_currentTask.get(), &Task::failed, this, &MinecraftAccount::authFailed);

View File

@ -75,12 +75,12 @@ void MSADeviceCodeStep::perform()
m_task->setAskRetry(false);
m_task->addNetAction(m_request);
connect(m_task.get(), &Task::finished, this, &MSADeviceCodeStep::deviceAuthorizationFinished);
connect(m_task.get(), &Task::finished, this, &MSADeviceCodeStep::deviceAutorizationFinished);
m_task->start();
}
struct DeviceAuthorizationResponse {
struct DeviceAutorizationResponse {
QString device_code;
QString user_code;
QString verification_uri;
@ -91,17 +91,17 @@ struct DeviceAuthorizationResponse {
QString error_description;
};
DeviceAuthorizationResponse parseDeviceAuthorizationResponse(const QByteArray& data)
DeviceAutorizationResponse parseDeviceAutorizationResponse(const QByteArray& data)
{
QJsonParseError err;
QJsonDocument doc = QJsonDocument::fromJson(data, &err);
if (err.error != QJsonParseError::NoError) {
qWarning() << "Failed to parse device authorization response due to err:" << err.errorString();
qWarning() << "Failed to parse device autorization response due to err:" << err.errorString();
return {};
}
if (!doc.isObject()) {
qWarning() << "Device authorization response is not an object";
qWarning() << "Device autorization response is not an object";
return {};
}
auto obj = doc.object();
@ -112,9 +112,9 @@ DeviceAuthorizationResponse parseDeviceAuthorizationResponse(const QByteArray& d
};
}
void MSADeviceCodeStep::deviceAuthorizationFinished()
void MSADeviceCodeStep::deviceAutorizationFinished()
{
auto rsp = parseDeviceAuthorizationResponse(*m_response);
auto rsp = parseDeviceAutorizationResponse(*m_response);
if (!rsp.error.isEmpty() || !rsp.error_description.isEmpty()) {
qWarning() << "Device authorization failed:" << rsp.error;
emit finished(AccountTaskState::STATE_FAILED_HARD,
@ -210,12 +210,12 @@ AuthenticationResponse parseAuthenticationResponse(const QByteArray& data)
QJsonParseError err;
QJsonDocument doc = QJsonDocument::fromJson(data, &err);
if (err.error != QJsonParseError::NoError) {
qWarning() << "Failed to parse device authorization response due to err:" << err.errorString();
qWarning() << "Failed to parse device autorization response due to err:" << err.errorString();
return {};
}
if (!doc.isObject()) {
qWarning() << "Device authorization response is not an object";
qWarning() << "Device autorization response is not an object";
return {};
}
auto obj = doc.object();

View File

@ -58,7 +58,7 @@ class MSADeviceCodeStep : public AuthStep {
void authorizeWithBrowser(QString url, QString code, int expiresIn);
private slots:
void deviceAuthorizationFinished();
void deviceAutorizationFinished();
void startPoolTimer();
void authenticateUser();
void authenticationFinished();

View File

@ -85,7 +85,8 @@ class CustomOAuthOobReplyHandler : public QOAuthOobReplyHandler {
MSAStep::MSAStep(AccountData* data, bool silent) : AuthStep(data), m_silent(silent)
{
m_clientId = APPLICATION->getMSAClientID();
if (QCoreApplication::applicationFilePath().startsWith("/tmp/.mount_") || APPLICATION->isPortable() || !isSchemeHandlerRegistered())
if (QCoreApplication::applicationFilePath().startsWith("/tmp/.mount_") ||
QFile::exists(FS::PathCombine(APPLICATION->root(), "portable.txt")) || !isSchemeHandlerRegistered())
{
auto replyHandler = new QOAuthHttpServerReplyHandler(this);

View File

@ -57,7 +57,9 @@
#include "tasks/SequentialTask.h"
AutoInstallJava::AutoInstallJava(LaunchTask* parent)
: LaunchStep(parent), m_instance(m_parent->instance()), m_supported_arch(SysInfo::getSupportedJavaArchitecture()) {};
: LaunchStep(parent)
, m_instance(m_parent->instance())
, m_supported_arch(SysInfo::getSupportedJavaArchitecture()) {};
void AutoInstallJava::executeTask()
{
@ -76,7 +78,7 @@ void AutoInstallJava::executeTask()
auto java = std::dynamic_pointer_cast<JavaInstall>(javas->at(i));
if (java && packProfile->getProfile()->getCompatibleJavaMajors().contains(java->id.major())) {
if (!java->is_64bit) {
emit logLine(tr("The automatic Java mechanism detected a 32-bit installation of Java."), MessageLevel::Launcher);
emit logLine(tr("The automatic Java mechanism detected a 32-bit installation of Java."), MessageLevel::Info);
}
setJavaPath(java->path);
return;
@ -134,7 +136,7 @@ void AutoInstallJava::setJavaPath(QString path)
settings->set("OverrideJavaLocation", true);
settings->set("JavaPath", path);
settings->set("AutomaticJava", true);
emit logLine(tr("Compatible Java found at: %1.").arg(path), MessageLevel::Launcher);
emit logLine(tr("Compatible Java found at: %1.").arg(path), MessageLevel::Info);
emitSucceeded();
}
@ -177,7 +179,7 @@ void AutoInstallJava::downloadJava(Meta::Version::Ptr version, QString javaName)
return;
}
#if defined(Q_OS_MACOS)
auto seq = makeShared<SequentialTask>(tr("Install Java"));
auto seq = makeShared<SequentialTask>(this, tr("Install Java"));
seq->addTask(m_current_task);
seq->addTask(makeShared<Java::SymlinkTask>(final_path));
m_current_task = seq;

View File

@ -261,7 +261,7 @@ bool ResourceFolderModel::update()
return true;
}
void ResourceFolderModel::resolveResource(Resource::Ptr res)
void ResourceFolderModel::resolveResource(Resource* res)
{
if (!res->shouldResolve()) {
return;
@ -277,14 +277,11 @@ void ResourceFolderModel::resolveResource(Resource::Ptr res)
m_active_parse_tasks.insert(ticket, task);
connect(
task.get(), &Task::succeeded, this, [this, ticket, res] { onParseSucceeded(ticket, res->internal_id()); },
Qt::ConnectionType::QueuedConnection);
connect(
task.get(), &Task::failed, this, [this, ticket, res] { onParseFailed(ticket, res->internal_id()); },
Qt::ConnectionType::QueuedConnection);
task.get(), &Task::succeeded, this, [=] { onParseSucceeded(ticket, res->internal_id()); }, Qt::ConnectionType::QueuedConnection);
connect(task.get(), &Task::failed, this, [=] { onParseFailed(ticket, res->internal_id()); }, Qt::ConnectionType::QueuedConnection);
connect(
task.get(), &Task::finished, this,
[this, ticket] {
[=] {
m_active_parse_tasks.remove(ticket);
emit parseFinished();
},
@ -320,7 +317,7 @@ void ResourceFolderModel::onUpdateSucceeded()
void ResourceFolderModel::onParseSucceeded(int ticket, QString resource_id)
{
auto iter = m_active_parse_tasks.constFind(ticket);
if (iter == m_active_parse_tasks.constEnd() || !m_resources_index.contains(resource_id))
if (iter == m_active_parse_tasks.constEnd())
return;
int row = m_resources_index[resource_id];
@ -632,7 +629,7 @@ QString ResourceFolderModel::instDirPath() const
void ResourceFolderModel::onParseFailed(int ticket, QString resource_id)
{
auto iter = m_active_parse_tasks.constFind(ticket);
if (iter == m_active_parse_tasks.constEnd() || !m_resources_index.contains(resource_id))
if (iter == m_active_parse_tasks.constEnd())
return;
auto removed_index = m_resources_index[resource_id];

View File

@ -76,7 +76,7 @@ class ResourceFolderModel : public QAbstractListModel {
virtual bool update();
/** Creates a new parse task, if needed, for 'res' and start it.*/
virtual void resolveResource(Resource::Ptr res);
virtual void resolveResource(Resource* res);
[[nodiscard]] qsizetype size() const { return m_resources.size(); }
[[nodiscard]] bool empty() const { return size() == 0; }
@ -285,7 +285,7 @@ void ResourceFolderModel::applyUpdates(QSet<QString>& current_set, QSet<QString>
}
m_resources[row].reset(new_resource);
resolveResource(m_resources.at(row));
resolveResource(m_resources.at(row).get());
emit dataChanged(index(row, 0), index(row, columnCount(QModelIndex()) - 1));
}
}
@ -333,7 +333,7 @@ void ResourceFolderModel::applyUpdates(QSet<QString>& current_set, QSet<QString>
for (auto& added : added_set) {
auto res = new_resources[added];
m_resources.append(res);
resolveResource(m_resources.last());
resolveResource(m_resources.last().get());
}
endInsertRows();

View File

@ -7,7 +7,6 @@
#include <memory>
#include "Application.h"
#include "FileSystem.h"
#include "minecraft/mod/Resource.h"
@ -26,12 +25,16 @@ class BasicFolderLoadTask : public Task {
[[nodiscard]] ResultPtr result() const { return m_result; }
public:
BasicFolderLoadTask(QDir dir) : Task(false), m_dir(dir), m_result(new Result), m_thread_to_spawn_into(thread())
BasicFolderLoadTask(QDir dir) : Task(nullptr, false), m_dir(dir), m_result(new Result), m_thread_to_spawn_into(thread())
{
m_create_func = [](QFileInfo const& entry) -> Resource::Ptr { return makeShared<Resource>(entry); };
}
BasicFolderLoadTask(QDir dir, std::function<Resource::Ptr(QFileInfo const&)> create_function)
: Task(false), m_dir(dir), m_result(new Result), m_create_func(std::move(create_function)), m_thread_to_spawn_into(thread())
: Task(nullptr, false)
, m_dir(dir)
, m_result(new Result)
, m_create_func(std::move(create_function))
, m_thread_to_spawn_into(thread())
{}
[[nodiscard]] bool canAbort() const override { return true; }
@ -49,9 +52,6 @@ class BasicFolderLoadTask : public Task {
m_dir.refresh();
for (auto entry : m_dir.entryInfoList()) {
auto filePath = entry.absoluteFilePath();
if (auto app = APPLICATION_DYN; app && app->checkQSavePath(filePath)) {
continue;
}
auto newFilePath = FS::getUniqueResourceName(filePath);
if (newFilePath != filePath) {
FS::move(filePath, newFilePath);

View File

@ -52,10 +52,11 @@ static bool checkDependencies(std::shared_ptr<GetModDependenciesTask::PackDepend
(!loaders || !sel->version.loaders || sel->version.loaders & loaders);
}
GetModDependenciesTask::GetModDependenciesTask(BaseInstance* instance,
GetModDependenciesTask::GetModDependenciesTask(QObject* parent,
BaseInstance* instance,
ModFolderModel* folder,
QList<std::shared_ptr<PackDependency>> selected)
: SequentialTask(tr("Get dependencies"))
: SequentialTask(parent, tr("Get dependencies"))
, m_selected(selected)
, m_flame_provider{ ModPlatform::ResourceProvider::FLAME, std::make_shared<ResourceDownload::FlameModModel>(*instance),
std::make_shared<FlameAPI>() }
@ -184,7 +185,7 @@ Task::Ptr GetModDependenciesTask::prepareDependencyTask(const ModPlatform::Depen
auto provider = providerName == m_flame_provider.name ? m_flame_provider : m_modrinth_provider;
auto tasks = makeShared<SequentialTask>(
QString("DependencyInfo: %1").arg(dep.addonId.toString().isEmpty() ? dep.version : dep.addonId.toString()));
this, QString("DependencyInfo: %1").arg(dep.addonId.toString().isEmpty() ? dep.version : dep.addonId.toString()));
if (!dep.addonId.toString().isEmpty()) {
tasks->addTask(getProjectInfoTask(pDep));

View File

@ -61,7 +61,10 @@ class GetModDependenciesTask : public SequentialTask {
std::shared_ptr<ResourceAPI> api;
};
explicit GetModDependenciesTask(BaseInstance* instance, ModFolderModel* folder, QList<std::shared_ptr<PackDependency>> selected);
explicit GetModDependenciesTask(QObject* parent,
BaseInstance* instance,
ModFolderModel* folder,
QList<std::shared_ptr<PackDependency>> selected);
auto getDependecies() const -> QList<std::shared_ptr<PackDependency>> { return m_pack_dependencies; }
QHash<QString, PackDependencyExtraInfo> getExtraInfo();

View File

@ -157,7 +157,7 @@ bool validate(QFileInfo file)
} // namespace DataPackUtils
LocalDataPackParseTask::LocalDataPackParseTask(int token, DataPack& dp) : Task(false), m_token(token), m_data_pack(dp) {}
LocalDataPackParseTask::LocalDataPackParseTask(int token, DataPack& dp) : Task(nullptr, false), m_token(token), m_data_pack(dp) {}
bool LocalDataPackParseTask::abort()
{

View File

@ -8,7 +8,6 @@
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonValue>
#include <QRegularExpression>
#include <QString>
#include "FileSystem.h"
@ -16,8 +15,6 @@
#include "minecraft/mod/ModDetails.h"
#include "settings/INIFile.h"
static QRegularExpression newlineRegex("\r\n|\n|\r");
namespace ModUtils {
// NEW format
@ -490,11 +487,11 @@ bool processZIP(Mod& mod, [[maybe_unused]] ProcessingLevel level)
}
// quick and dirty line-by-line parser
auto manifestLines = QString(file.readAll()).split(newlineRegex);
auto manifestLines = file.readAll().split('\n');
QString manifestVersion = "";
for (auto& line : manifestLines) {
if (line.startsWith("Implementation-Version: ", Qt::CaseInsensitive)) {
manifestVersion = line.remove("Implementation-Version: ", Qt::CaseInsensitive);
if (QString(line).startsWith("Implementation-Version: ")) {
manifestVersion = QString(line).remove("Implementation-Version: ");
break;
}
}
@ -733,7 +730,7 @@ bool loadIconFile(const Mod& mod, QPixmap* pixmap)
} // namespace ModUtils
LocalModParseTask::LocalModParseTask(int token, ResourceType type, const QFileInfo& modFile)
: Task(false), m_token(token), m_type(type), m_modFile(modFile), m_result(new Result())
: Task(nullptr, false), m_token(token), m_type(type), m_modFile(modFile), m_result(new Result())
{}
bool LocalModParseTask::abort()

View File

@ -358,7 +358,9 @@ bool validate(QFileInfo file)
} // namespace ResourcePackUtils
LocalResourcePackParseTask::LocalResourcePackParseTask(int token, ResourcePack& rp) : Task(false), m_token(token), m_resource_pack(rp) {}
LocalResourcePackParseTask::LocalResourcePackParseTask(int token, ResourcePack& rp)
: Task(nullptr, false), m_token(token), m_resource_pack(rp)
{}
bool LocalResourcePackParseTask::abort()
{

View File

@ -93,7 +93,7 @@ bool validate(QFileInfo file)
} // namespace ShaderPackUtils
LocalShaderPackParseTask::LocalShaderPackParseTask(int token, ShaderPack& sp) : Task(false), m_token(token), m_shader_pack(sp) {}
LocalShaderPackParseTask::LocalShaderPackParseTask(int token, ShaderPack& sp) : Task(nullptr, false), m_token(token), m_shader_pack(sp) {}
bool LocalShaderPackParseTask::abort()
{

View File

@ -230,7 +230,8 @@ bool validate(QFileInfo file)
} // namespace TexturePackUtils
LocalTexturePackParseTask::LocalTexturePackParseTask(int token, TexturePack& rp) : Task(false), m_token(token), m_texture_pack(rp) {}
LocalTexturePackParseTask::LocalTexturePackParseTask(int token, TexturePack& rp) : Task(nullptr, false), m_token(token), m_texture_pack(rp)
{}
bool LocalTexturePackParseTask::abort()
{

View File

@ -170,7 +170,7 @@ bool validate(QFileInfo file)
} // namespace WorldSaveUtils
LocalWorldSaveParseTask::LocalWorldSaveParseTask(int token, WorldSave& save) : Task(false), m_token(token), m_save(save) {}
LocalWorldSaveParseTask::LocalWorldSaveParseTask(int token, WorldSave& save) : Task(nullptr, false), m_token(token), m_save(save) {}
bool LocalWorldSaveParseTask::abort()
{

View File

@ -36,14 +36,13 @@
#include "ModFolderLoadTask.h"
#include "Application.h"
#include "FileSystem.h"
#include "minecraft/mod/MetadataHandler.h"
#include <QThread>
ModFolderLoadTask::ModFolderLoadTask(QDir mods_dir, QDir index_dir, bool is_indexed, bool clean_orphan)
: Task(false)
: Task(nullptr, false)
, m_mods_dir(mods_dir)
, m_index_dir(index_dir)
, m_is_indexed(is_indexed)
@ -66,9 +65,6 @@ void ModFolderLoadTask::executeTask()
m_mods_dir.refresh();
for (auto entry : m_mods_dir.entryInfoList()) {
auto filePath = entry.absoluteFilePath();
if (auto app = APPLICATION_DYN; app && app->checkQSavePath(filePath)) {
continue;
}
auto newFilePath = FS::getUniqueResourceName(filePath);
if (newFilePath != filePath) {
FS::move(filePath, newFilePath);

View File

@ -16,7 +16,7 @@ class CheckUpdateTask : public Task {
std::list<Version>& mcVersions,
QList<ModPlatform::ModLoaderType> loadersList,
std::shared_ptr<ModFolderModel> mods_folder)
: Task(), m_mods(mods), m_game_versions(mcVersions), m_loaders_list(loadersList), m_mods_folder(mods_folder) {};
: Task(nullptr), m_mods(mods), m_game_versions(mcVersions), m_loaders_list(loadersList), m_mods_folder(mods_folder) {};
struct UpdatableMod {
QString name;

View File

@ -19,32 +19,31 @@ static ModrinthAPI modrinth_api;
static FlameAPI flame_api;
EnsureMetadataTask::EnsureMetadataTask(Mod* mod, QDir dir, ModPlatform::ResourceProvider prov)
: Task(), m_index_dir(dir), m_provider(prov), m_hashingTask(nullptr), m_current_task(nullptr)
: Task(nullptr), m_index_dir(dir), m_provider(prov), m_hashing_task(nullptr), m_current_task(nullptr)
{
auto hashTask = createNewHash(mod);
if (!hashTask)
auto hash_task = createNewHash(mod);
if (!hash_task)
return;
connect(hashTask.get(), &Hashing::Hasher::resultsReady, [this, mod](QString hash) { m_mods.insert(hash, mod); });
connect(hashTask.get(), &Task::failed, [this, mod] { emitFail(mod, "", RemoveFromList::No); });
m_hashingTask = hashTask;
connect(hash_task.get(), &Hashing::Hasher::resultsReady, [this, mod](QString hash) { m_mods.insert(hash, mod); });
connect(hash_task.get(), &Task::failed, [this, mod] { emitFail(mod, "", RemoveFromList::No); });
hash_task->start();
}
EnsureMetadataTask::EnsureMetadataTask(QList<Mod*>& mods, QDir dir, ModPlatform::ResourceProvider prov)
: Task(), m_index_dir(dir), m_provider(prov), m_current_task(nullptr)
: Task(nullptr), m_index_dir(dir), m_provider(prov), m_current_task(nullptr)
{
auto hashTask = makeShared<ConcurrentTask>("MakeHashesTask", APPLICATION->settings()->get("NumberOfConcurrentTasks").toInt());
m_hashingTask = hashTask;
m_hashing_task.reset(new ConcurrentTask(this, "MakeHashesTask", APPLICATION->settings()->get("NumberOfConcurrentTasks").toInt()));
for (auto* mod : mods) {
auto hash_task = createNewHash(mod);
if (!hash_task)
continue;
connect(hash_task.get(), &Hashing::Hasher::resultsReady, [this, mod](QString hash) { m_mods.insert(hash, mod); });
connect(hash_task.get(), &Task::failed, [this, mod] { emitFail(mod, "", RemoveFromList::No); });
hashTask->addTask(hash_task);
m_hashing_task->addTask(hash_task);
}
}
EnsureMetadataTask::EnsureMetadataTask(QHash<QString, Mod*>& mods, QDir dir, ModPlatform::ResourceProvider prov)
: Task(), m_mods(mods), m_index_dir(dir), m_provider(prov), m_current_task(nullptr)
: Task(nullptr), m_mods(mods), m_index_dir(dir), m_provider(prov), m_current_task(nullptr)
{}
Hashing::Hasher::Ptr EnsureMetadataTask::createNewHash(Mod* mod)

View File

@ -20,7 +20,7 @@ class EnsureMetadataTask : public Task {
~EnsureMetadataTask() = default;
Task::Ptr getHashingTask() { return m_hashingTask; }
Task::Ptr getHashingTask() { return m_hashing_task; }
public slots:
bool abort() override;
@ -58,6 +58,6 @@ class EnsureMetadataTask : public Task {
ModPlatform::ResourceProvider m_provider;
QHash<QString, ModPlatform::IndexedVersion> m_temp_versions;
Task::Ptr m_hashingTask;
ConcurrentTask::Ptr m_hashing_task;
Task::Ptr m_current_task;
};

View File

@ -31,19 +31,6 @@ static const QMap<QString, IndexedVersionType::VersionType> s_indexed_version_ty
{ "alpha", IndexedVersionType::VersionType::Alpha }
};
static const QList<ModLoaderType> loaderList = { NeoForge, Forge, Cauldron, LiteLoader, Quilt, Fabric };
QList<ModLoaderType> modLoaderTypesToList(ModLoaderTypes flags)
{
QList<ModLoaderType> flagList;
for (auto flag : loaderList) {
if (flags.testFlag(flag)) {
flagList.append(flag);
}
}
return flagList;
}
IndexedVersionType::IndexedVersionType(const QString& type) : IndexedVersionType(enumFromString(type)) {}
IndexedVersionType::IndexedVersionType(const IndexedVersionType::VersionType& type)

View File

@ -32,7 +32,6 @@ namespace ModPlatform {
enum ModLoaderType { NeoForge = 1 << 0, Forge = 1 << 1, Cauldron = 1 << 2, LiteLoader = 1 << 3, Fabric = 1 << 4, Quilt = 1 << 5 };
Q_DECLARE_FLAGS(ModLoaderTypes, ModLoaderType)
QList<ModLoaderType> modLoaderTypesToList(ModLoaderTypes flags);
enum class ResourceProvider { MODRINTH, FLAME };

View File

@ -144,7 +144,7 @@ void Flame::FileResolvingTask::netJobFinished()
<< " reason: " << parse_error.errorString();
qWarning() << *m_result;
getFlameProjects();
failed(parse_error.errorString());
return;
}

View File

@ -270,35 +270,21 @@ std::optional<ModPlatform::IndexedVersion> FlameAPI::getLatestVersion(QList<ModP
QList<ModPlatform::ModLoaderType> instanceLoaders,
ModPlatform::ModLoaderTypes modLoaders)
{
QHash<ModPlatform::ModLoaderType, ModPlatform::IndexedVersion> bestMatch;
auto checkVersion = [&bestMatch](const ModPlatform::IndexedVersion& version, const ModPlatform::ModLoaderType& loader) {
if (bestMatch.contains(loader)) {
auto best = bestMatch.value(loader);
if (version.date > best.date) {
bestMatch[loader] = version;
}
} else {
bestMatch[loader] = version;
}
};
for (auto file_tmp : versions) {
auto loaders = ModPlatform::modLoaderTypesToList(file_tmp.loaders);
if (loaders.isEmpty()) {
checkVersion(file_tmp, ModPlatform::ModLoaderType(0));
} else {
for (auto loader : loaders) {
checkVersion(file_tmp, loader);
}
}
}
// edge case: mod has installed for forge but the instance is fabric => fabric version will be prioritizated on update
auto currentLoaders = instanceLoaders + ModPlatform::modLoaderTypesToList(modLoaders);
currentLoaders.append(ModPlatform::ModLoaderType(0)); // add a fallback in case the versions do not define a loader
for (auto loader : currentLoaders) {
if (bestMatch.contains(loader)) {
return bestMatch.value(loader);
auto bestVersion = [&versions](ModPlatform::ModLoaderTypes loader) {
std::optional<ModPlatform::IndexedVersion> ver;
for (auto file_tmp : versions) {
if (file_tmp.loaders & loader && (!ver.has_value() || file_tmp.date > ver->date)) {
ver = file_tmp;
}
}
return {};
return ver;
};
for (auto l : instanceLoaders) {
auto ver = bestVersion(l);
if (ver.has_value()) {
return ver;
}
}
return bestVersion(modLoaders);
}

View File

@ -444,7 +444,6 @@ bool FlameCreationTask::createInstance()
setError(tr("Unable to resolve mod IDs:\n") + reason);
loop.quit();
});
connect(m_mod_id_resolver.get(), &Flame::FileResolvingTask::aborted, &loop, &QEventLoop::quit);
connect(m_mod_id_resolver.get(), &Flame::FileResolvingTask::progress, this, &FlameCreationTask::setProgress);
connect(m_mod_id_resolver.get(), &Flame::FileResolvingTask::status, this, &FlameCreationTask::setStatus);
connect(m_mod_id_resolver.get(), &Flame::FileResolvingTask::stepProgress, this, &FlameCreationTask::propagateStepProgress);
@ -677,7 +676,7 @@ void FlameCreationTask::validateZIPResources(QEventLoop& loop)
break;
}
}
auto task = makeShared<ConcurrentTask>("CreateModMetadata", APPLICATION->settings()->get("NumberOfConcurrentTasks").toInt());
auto task = makeShared<ConcurrentTask>(this, "CreateModMetadata", APPLICATION->settings()->get("NumberOfConcurrentTasks").toInt());
auto results = m_mod_id_resolver->getResults().files;
auto folder = FS::PathCombine(m_stagingPath, "minecraft", "mods", ".index");
for (auto file : results) {

View File

@ -103,7 +103,8 @@ void FlamePackExportTask::collectHashes()
setStatus(tr("Finding file hashes..."));
setProgress(1, 5);
auto allMods = mcInstance->loaderModList()->allMods();
ConcurrentTask::Ptr hashingTask(new ConcurrentTask("MakeHashesTask", APPLICATION->settings()->get("NumberOfConcurrentTasks").toInt()));
ConcurrentTask::Ptr hashingTask(
new ConcurrentTask(this, "MakeHashesTask", APPLICATION->settings()->get("NumberOfConcurrentTasks").toInt()));
task.reset(hashingTask);
for (const QFileInfo& file : files) {
const QString relative = gameRoot.relativeFilePath(file.absoluteFilePath());

View File

@ -43,16 +43,11 @@ Task::Ptr NetworkResourceAPI::searchProjects(SearchArgs&& args, SearchCallbacks&
callbacks.on_succeed(doc);
});
// Capture a weak_ptr instead of a shared_ptr to avoid circular dependency issues.
// This prevents the lambda from extending the lifetime of the shared resource,
// as it only temporarily locks the resource when needed.
auto weak = netJob.toWeakRef();
QObject::connect(netJob.get(), &NetJob::failed, [weak, callbacks](const QString& reason) {
QObject::connect(netJob.get(), &NetJob::failed, [netJob, callbacks](const QString& reason) {
int network_error_code = -1;
if (auto netJob = weak.lock()) {
if (auto* failed_action = netJob->getFailedActions().at(0); failed_action)
network_error_code = failed_action->replyStatusCode();
}
callbacks.on_fail(reason, network_error_code);
});
QObject::connect(netJob.get(), &NetJob::aborted, [callbacks] { callbacks.on_abort(); });
@ -107,17 +102,11 @@ Task::Ptr NetworkResourceAPI::getProjectVersions(VersionSearchArgs&& args, Versi
callbacks.on_succeed(doc, args.pack);
});
// Capture a weak_ptr instead of a shared_ptr to avoid circular dependency issues.
// This prevents the lambda from extending the lifetime of the shared resource,
// as it only temporarily locks the resource when needed.
auto weak = netJob.toWeakRef();
QObject::connect(netJob.get(), &NetJob::failed, [weak, callbacks](const QString& reason) {
QObject::connect(netJob.get(), &NetJob::failed, [netJob, callbacks](const QString& reason) {
int network_error_code = -1;
if (auto netJob = weak.lock()) {
if (auto* failed_action = netJob->getFailedActions().at(0); failed_action)
network_error_code = failed_action->replyStatusCode();
}
callbacks.on_fail(reason, network_error_code);
});
@ -164,17 +153,11 @@ Task::Ptr NetworkResourceAPI::getDependencyVersion(DependencySearchArgs&& args,
callbacks.on_succeed(doc, args.dependency);
});
// Capture a weak_ptr instead of a shared_ptr to avoid circular dependency issues.
// This prevents the lambda from extending the lifetime of the shared resource,
// as it only temporarily locks the resource when needed.
auto weak = netJob.toWeakRef();
QObject::connect(netJob.get(), &NetJob::failed, [weak, callbacks](const QString& reason) {
QObject::connect(netJob.get(), &NetJob::failed, [netJob, callbacks](const QString& reason) {
int network_error_code = -1;
if (auto netJob = weak.lock()) {
if (auto* failed_action = netJob->getFailedActions().at(0); failed_action)
network_error_code = failed_action->replyStatusCode();
}
callbacks.on_fail(reason, network_error_code);
});
return netJob;

View File

@ -138,7 +138,7 @@ void PackInstallTask::install()
if (unzipMcDir.exists()) {
// ok, found minecraft dir, move contents to instance dir
if (!FS::move(m_stagingPath + "/unzip/minecraft", m_stagingPath + "/minecraft")) {
emitFailed(tr("Failed to move unpacked Minecraft!"));
emitFailed(tr("Failed to move unzipped Minecraft!"));
return;
}
}

View File

@ -34,7 +34,7 @@ Task::Ptr ModrinthAPI::currentVersions(const QStringList& hashes, QString hash_f
auto body_raw = body.toJson();
netJob->addNetAction(Net::ApiUpload::makeByteArray(QString(BuildConfig.MODRINTH_PROD_URL + "/version_files"), response, body_raw));
netJob->setAskRetry(false);
return netJob;
}

View File

@ -8,7 +8,6 @@
#include "QObjectPtr.h"
#include "ResourceDownloadTask.h"
#include "modplatform/ModIndex.h"
#include "modplatform/helpers/HashUtils.h"
#include "tasks/ConcurrentTask.h"
@ -41,7 +40,7 @@ void ModrinthCheckUpdate::executeTask()
setProgress(0, 9);
auto hashing_task =
makeShared<ConcurrentTask>("MakeModrinthHashesTask", APPLICATION->settings()->get("NumberOfConcurrentTasks").toInt());
makeShared<ConcurrentTask>(this, "MakeModrinthHashesTask", APPLICATION->settings()->get("NumberOfConcurrentTasks").toInt());
for (auto* mod : m_mods) {
auto hash = mod->metadata()->hash;
@ -92,16 +91,21 @@ void ModrinthCheckUpdate::checkVersionsResponse(std::shared_ptr<QByteArray> resp
// it means this specific version is not available
if (project_obj.isEmpty()) {
qDebug() << "Mod " << m_mappings.find(hash).value()->name() << " got an empty response." << "Hash: " << hash;
continue;
}
// Sometimes a version may have multiple files, one with "forge" and one with "fabric",
// so we may want to filter it
QString loader_filter;
for (auto flag : ModPlatform::modLoaderTypesToList(loader)) {
static auto flags = { ModPlatform::ModLoaderType::NeoForge, ModPlatform::ModLoaderType::Forge,
ModPlatform::ModLoaderType::Quilt, ModPlatform::ModLoaderType::Fabric };
for (auto flag : flags) {
if (loader.testFlag(flag)) {
loader_filter = ModPlatform::getModLoaderAsString(flag);
break;
}
}
// Currently, we rely on a couple heuristics to determine whether an update is actually available or not:
// - The file needs to be preferred: It is either the primary file, or the one found via (explicit) usage of the

View File

@ -261,14 +261,12 @@ bool ModrinthCreationTask::createInstance()
mod->setDetails(d);
mods[file.hash.toHex()] = mod;
}
if (file.downloads.empty()) {
setError(tr("The file '%1' is missing a download link. This is invalid in the pack format.").arg(fileName));
return false;
}
qDebug() << "Will try to download" << file.downloads.front() << "to" << file_path;
auto dl = Net::ApiDownload::makeFile(file.downloads.dequeue(), file_path);
dl->addValidator(new Net::ChecksumValidator(file.hashAlgorithm, file.hash));
downloadMods->addNetAction(dl);
if (!file.downloads.empty()) {
// FIXME: This really needs to be put into a ConcurrentTask of
// MultipleOptionsTask's , once those exist :)

View File

@ -72,7 +72,7 @@ auto stringEntry(toml::table table, QString entry_name) -> QString
{
auto node = table[StringUtils::toStdString(entry_name)];
if (!node) {
qWarning() << "Failed to read str property '" + entry_name + "' in mod metadata.";
qCritical() << "Failed to read str property '" + entry_name + "' in mod metadata.";
return {};
}
@ -83,7 +83,7 @@ auto intEntry(toml::table table, QString entry_name) -> int
{
auto node = table[StringUtils::toStdString(entry_name)];
if (!node) {
qWarning() << "Failed to read int property '" + entry_name + "' in mod metadata.";
qCritical() << "Failed to read int property '" + entry_name + "' in mod metadata.";
return {};
}
@ -186,9 +186,12 @@ void V1::updateModIndex(QDir& index_dir, Mod& mod)
}
toml::array loaders;
for (auto loader : ModPlatform::modLoaderTypesToList(mod.loaders)) {
for (auto loader : { ModPlatform::NeoForge, ModPlatform::Forge, ModPlatform::Cauldron, ModPlatform::LiteLoader, ModPlatform::Fabric,
ModPlatform::Quilt }) {
if (mod.loaders & loader) {
loaders.push_back(getModLoaderAsString(loader).toStdString());
}
}
toml::array mcVersions;
for (auto version : mod.mcVersions) {
mcVersions.push_back(version.toStdString());

View File

@ -55,7 +55,7 @@ Task::State FileSink::init(QNetworkRequest& request)
}
wroteAnyData = false;
m_output_file.reset(new PSaveFile(m_filename));
m_output_file.reset(new QSaveFile(m_filename));
if (!m_output_file->open(QIODevice::WriteOnly)) {
qCCritical(taskNetLogC) << "Could not open " + m_filename + " for writing";
return Task::State::Failed;

View File

@ -35,7 +35,8 @@
#pragma once
#include "PSaveFile.h"
#include <QSaveFile>
#include "Sink.h"
namespace Net {
@ -59,6 +60,6 @@ class FileSink : public Sink {
protected:
QString m_filename;
bool wroteAnyData = false;
std::unique_ptr<PSaveFile> m_output_file;
std::unique_ptr<QSaveFile> m_output_file;
};
} // namespace Net

View File

@ -45,7 +45,7 @@
#endif
NetJob::NetJob(QString job_name, shared_qobject_ptr<QNetworkAccessManager> network, int max_concurrent)
: ConcurrentTask(job_name), m_network(network)
: ConcurrentTask(nullptr, job_name), m_network(network)
{
#if defined(LAUNCHER_APPLICATION)
if (APPLICATION_DYN && max_concurrent < 0)

View File

@ -1,6 +1,7 @@
[Icon Theme]
Name=Legacy
Comment=Default Icons
Inherits=default
Directories=8x8,16x16,22x22,24x24,32x32,32x32/instances,48x48,50x50/instances,64x64,128x128/instances,256x256,scalable,scalable/instances
[8x8]

View File

@ -38,7 +38,7 @@
#include <QDebug>
#include "tasks/Task.h"
ConcurrentTask::ConcurrentTask(QString task_name, int max_concurrent) : Task(), m_total_max_size(max_concurrent)
ConcurrentTask::ConcurrentTask(QObject* parent, QString task_name, int max_concurrent) : Task(parent), m_total_max_size(max_concurrent)
{
setObjectName(task_name);
}

View File

@ -48,7 +48,7 @@ class ConcurrentTask : public Task {
public:
using Ptr = shared_qobject_ptr<ConcurrentTask>;
explicit ConcurrentTask(QString task_name = "", int max_concurrent = 6);
explicit ConcurrentTask(QObject* parent = nullptr, QString task_name = "", int max_concurrent = 6);
~ConcurrentTask() override;
// safe to call before starting the task

View File

@ -36,7 +36,7 @@
#include <QDebug>
MultipleOptionsTask::MultipleOptionsTask(const QString& task_name) : ConcurrentTask(task_name, 1) {}
MultipleOptionsTask::MultipleOptionsTask(QObject* parent, const QString& task_name) : ConcurrentTask(parent, task_name, 1) {}
void MultipleOptionsTask::executeNextSubTask()
{

View File

@ -42,7 +42,7 @@
class MultipleOptionsTask : public ConcurrentTask {
Q_OBJECT
public:
explicit MultipleOptionsTask(const QString& task_name = "");
explicit MultipleOptionsTask(QObject* parent = nullptr, const QString& task_name = "");
~MultipleOptionsTask() override = default;
private slots:

View File

@ -38,7 +38,7 @@
#include <QDebug>
#include "tasks/ConcurrentTask.h"
SequentialTask::SequentialTask(QString task_name) : ConcurrentTask(task_name, 1) {}
SequentialTask::SequentialTask(QObject* parent, QString task_name) : ConcurrentTask(parent, task_name, 1) {}
void SequentialTask::subTaskFailed(Task::Ptr task, const QString& msg)
{

View File

@ -47,7 +47,7 @@
class SequentialTask : public ConcurrentTask {
Q_OBJECT
public:
explicit SequentialTask(QString task_name = "");
explicit SequentialTask(QObject* parent = nullptr, QString task_name = "");
~SequentialTask() override = default;
protected slots:

View File

@ -40,7 +40,7 @@
Q_LOGGING_CATEGORY(taskLogC, "launcher.task")
Task::Task(bool show_debug) : m_show_debug(show_debug)
Task::Task(QObject* parent, bool show_debug) : QObject(parent), m_show_debug(show_debug)
{
m_uid = QUuid::createUuid();
setAutoDelete(false);

View File

@ -87,7 +87,7 @@ class Task : public QObject, public QRunnable {
enum class State { Inactive, Running, Succeeded, Failed, AbortedByUser };
public:
explicit Task(bool show_debug_log = true);
explicit Task(QObject* parent = 0, bool show_debug_log = true);
virtual ~Task() = default;
bool isRunning() const;

View File

@ -102,7 +102,7 @@ QString getCreditsHtml()
stream << QString("<p>d-513 %1</p>\n").arg(getGitHub("d-513"));
stream << QString("<p>txtsd %1</p>\n").arg(getWebsite("https://ihavea.quest"));
stream << QString("<p>timoreo %1</p>\n").arg(getGitHub("timoreo22"));
stream << QString("<p>ZekeZ %1</p>\n").arg(getGitHub("ZekeZDev"));
stream << QString("<p>Ezekiel Smith (ZekeSmith) %1</p>\n").arg(getGitHub("ZekeSmith"));
stream << QString("<p>cozyGalvinism %1</p>\n").arg(getGitHub("cozyGalvinism"));
stream << QString("<p>DioEgizio %1</p>\n").arg(getGitHub("DioEgizio"));
stream << QString("<p>flowln %1</p>\n").arg(getGitHub("flowln"));
@ -126,7 +126,7 @@ QString getCreditsHtml()
stream << "<h3>" << QObject::tr("With thanks to", "About Credits") << "</h3>\n";
stream << QString("<p>Boba %1</p>\n").arg(getWebsite("https://bobaonline.neocities.org/"));
stream << QString("<p>AutiOne %1</p>\n").arg(getWebsite("https://auti.one/"));
stream << QString("<p>Davi Rafael %1</p>\n").arg(getWebsite("https://auti.one/"));
stream << QString("<p>Fulmine %1</p>\n").arg(getWebsite("https://fulmine.xyz/"));
stream << QString("<p>ely %1</p>\n").arg(getGitHub("elyrodso"));
stream << QString("<p>gon sawa %1</p>\n").arg(getGitHub("gonsawa"));

View File

@ -46,13 +46,11 @@ BlockedModsDialog::BlockedModsDialog(QWidget* parent, const QString& title, cons
: QDialog(parent), ui(new Ui::BlockedModsDialog), m_mods(mods), m_hash_type(hash_type)
{
m_hashing_task = shared_qobject_ptr<ConcurrentTask>(
new ConcurrentTask("MakeHashesTask", APPLICATION->settings()->get("NumberOfConcurrentTasks").toInt()));
new ConcurrentTask(this, "MakeHashesTask", APPLICATION->settings()->get("NumberOfConcurrentTasks").toInt()));
connect(m_hashing_task.get(), &Task::finished, this, &BlockedModsDialog::hashTaskFinished);
ui->setupUi(this);
ui->buttonBox->button(QDialogButtonBox::Cancel)->setText(tr("Cancel"));
ui->buttonBox->button(QDialogButtonBox::Ok)->setText(tr("OK"));
m_openMissingButton = ui->buttonBox->addButton(tr("Open Missing"), QDialogButtonBox::ActionRole);
connect(m_openMissingButton, &QPushButton::clicked, this, [this]() { openAll(true); });

View File

@ -109,9 +109,6 @@ CopyInstanceDialog::CopyInstanceDialog(InstancePtr original, QWidget* parent)
auto HelpButton = ui->buttonBox->button(QDialogButtonBox::Help);
connect(HelpButton, &QPushButton::clicked, this, &CopyInstanceDialog::help);
HelpButton->setText(tr("Help"));
ui->buttonBox->button(QDialogButtonBox::Cancel)->setText(tr("Cancel"));
ui->buttonBox->button(QDialogButtonBox::Ok)->setText(tr("OK"));
}
CopyInstanceDialog::~CopyInstanceDialog()

View File

@ -15,7 +15,6 @@
#include "EditAccountDialog.h"
#include <DesktopServices.h>
#include <QPushButton>
#include <QUrl>
#include "ui_EditAccountDialog.h"
@ -28,9 +27,6 @@ EditAccountDialog::EditAccountDialog(const QString& text, QWidget* parent, int f
ui->userTextBox->setEnabled(flags & UsernameField);
ui->passTextBox->setEnabled(flags & PasswordField);
ui->buttonBox->button(QDialogButtonBox::Cancel)->setText(tr("Cancel"));
ui->buttonBox->button(QDialogButtonBox::Ok)->setText(tr("OK"));
}
EditAccountDialog::~EditAccountDialog()

View File

@ -51,7 +51,6 @@
#include <icons/IconList.h>
#include <QDebug>
#include <QFileInfo>
#include <QPushButton>
#include <QSaveFile>
#include <QSortFilterProxyModel>
#include <QStack>
@ -86,9 +85,6 @@ ExportInstanceDialog::ExportInstanceDialog(InstancePtr instance, QWidget* parent
auto headerView = ui->treeView->header();
headerView->setSectionResizeMode(QHeaderView::ResizeToContents);
headerView->setSectionResizeMode(0, QHeaderView::Stretch);
ui->buttonBox->button(QDialogButtonBox::Cancel)->setText(tr("Cancel"));
ui->buttonBox->button(QDialogButtonBox::Ok)->setText(tr("OK"));
}
ExportInstanceDialog::~ExportInstanceDialog()

View File

@ -103,9 +103,6 @@ ExportPackDialog::ExportPackDialog(InstancePtr instance, QWidget* parent, ModPla
QHeaderView* headerView = ui->files->header();
headerView->setSectionResizeMode(QHeaderView::ResizeToContents);
headerView->setSectionResizeMode(0, QHeaderView::Stretch);
ui->buttonBox->button(QDialogButtonBox::Cancel)->setText(tr("Cancel"));
ui->buttonBox->button(QDialogButtonBox::Ok)->setText(tr("OK"));
}
ExportPackDialog::~ExportPackDialog()

View File

@ -64,9 +64,6 @@ ExportToModListDialog::ExportToModListDialog(QString name, QList<Mod*> mods, QWi
this->ui->finalText->selectAll();
this->ui->finalText->copy();
});
ui->buttonBox->button(QDialogButtonBox::Cancel)->setText(tr("Cancel"));
ui->buttonBox->button(QDialogButtonBox::Save)->setText(tr("Save"));
triggerImp();
}

View File

@ -63,9 +63,6 @@ IconPickerDialog::IconPickerDialog(QWidget* parent) : QDialog(parent), ui(new Ui
auto buttonAdd = ui->buttonBox->addButton(tr("Add Icon"), QDialogButtonBox::ResetRole);
buttonRemove = ui->buttonBox->addButton(tr("Remove Icon"), QDialogButtonBox::ResetRole);
ui->buttonBox->button(QDialogButtonBox::Cancel)->setText(tr("Cancel"));
ui->buttonBox->button(QDialogButtonBox::Ok)->setText(tr("OK"));
connect(buttonAdd, SIGNAL(clicked(bool)), SLOT(addNewIcon()));
connect(buttonRemove, SIGNAL(clicked(bool)), SLOT(removeSelectedIcon()));

View File

@ -45,9 +45,6 @@ ImportResourceDialog::ImportResourceDialog(QString file_path, PackedResourceType
ui->label->setText(
tr("Choose the instance you would like to import this %1 to.").arg(ResourceUtils::getPackedTypeName(m_resource_type)));
ui->label_file_path->setText(tr("File: %1").arg(m_file_path));
ui->buttonBox->button(QDialogButtonBox::Cancel)->setText(tr("Cancel"));
ui->buttonBox->button(QDialogButtonBox::Ok)->setText(tr("OK"));
}
void ImportResourceDialog::activated(QModelIndex index)

View File

@ -104,8 +104,6 @@ InstallLoaderDialog::InstallLoaderDialog(std::shared_ptr<PackProfile> profile, c
buttons->setOrientation(Qt::Horizontal);
buttons->setStandardButtons(QDialogButtonBox::Cancel | QDialogButtonBox::Ok);
buttons->button(QDialogButtonBox::Ok)->setText(tr("Ok"));
buttons->button(QDialogButtonBox::Cancel)->setText(tr("Cancel"));
connect(buttons, &QDialogButtonBox::accepted, this, &QDialog::accept);
connect(buttons, &QDialogButtonBox::rejected, this, &QDialog::reject);
buttonLayout->addWidget(buttons);

Some files were not shown because too many files have changed in this diff Show More