Merge branch 'develop' of https://github.com/PrismLauncher/PrismLauncher into deps_improve
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
This commit is contained in:
commit
a7d293b3f2
2
.github/workflows/backport.yml
vendored
2
.github/workflows/backport.yml
vendored
@ -24,7 +24,7 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
ref: ${{ github.event.pull_request.head.sha }}
|
ref: ${{ github.event.pull_request.head.sha }}
|
||||||
- name: Create backport PRs
|
- name: Create backport PRs
|
||||||
uses: korthout/backport-action@v2.1.1
|
uses: korthout/backport-action@v2.3.0
|
||||||
with:
|
with:
|
||||||
# Config README: https://github.com/korthout/backport-action#backport-action
|
# Config README: https://github.com/korthout/backport-action#backport-action
|
||||||
pull_description: |-
|
pull_description: |-
|
||||||
|
28
.github/workflows/build.yml
vendored
28
.github/workflows/build.yml
vendored
@ -61,7 +61,7 @@ jobs:
|
|||||||
qt_ver: 6
|
qt_ver: 6
|
||||||
qt_host: windows
|
qt_host: windows
|
||||||
qt_arch: ''
|
qt_arch: ''
|
||||||
qt_version: '6.6.0'
|
qt_version: '6.6.1'
|
||||||
qt_modules: 'qt5compat qtimageformats'
|
qt_modules: 'qt5compat qtimageformats'
|
||||||
qt_tools: ''
|
qt_tools: ''
|
||||||
|
|
||||||
@ -73,7 +73,7 @@ jobs:
|
|||||||
qt_ver: 6
|
qt_ver: 6
|
||||||
qt_host: windows
|
qt_host: windows
|
||||||
qt_arch: 'win64_msvc2019_arm64'
|
qt_arch: 'win64_msvc2019_arm64'
|
||||||
qt_version: '6.6.0'
|
qt_version: '6.6.1'
|
||||||
qt_modules: 'qt5compat qtimageformats'
|
qt_modules: 'qt5compat qtimageformats'
|
||||||
qt_tools: ''
|
qt_tools: ''
|
||||||
|
|
||||||
@ -83,7 +83,7 @@ jobs:
|
|||||||
qt_ver: 6
|
qt_ver: 6
|
||||||
qt_host: mac
|
qt_host: mac
|
||||||
qt_arch: ''
|
qt_arch: ''
|
||||||
qt_version: '6.6.0'
|
qt_version: '6.6.1'
|
||||||
qt_modules: 'qt5compat qtimageformats'
|
qt_modules: 'qt5compat qtimageformats'
|
||||||
qt_tools: ''
|
qt_tools: ''
|
||||||
|
|
||||||
@ -145,7 +145,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Setup ccache
|
- name: Setup ccache
|
||||||
if: (runner.os != 'Windows' || matrix.msystem == '') && inputs.build_type == 'Debug'
|
if: (runner.os != 'Windows' || matrix.msystem == '') && inputs.build_type == 'Debug'
|
||||||
uses: hendrikmuhs/ccache-action@v1.2.10
|
uses: hendrikmuhs/ccache-action@v1.2.11
|
||||||
with:
|
with:
|
||||||
key: ${{ matrix.os }}-qt${{ matrix.qt_ver }}-${{ matrix.architecture }}
|
key: ${{ matrix.os }}-qt${{ matrix.qt_ver }}-${{ matrix.architecture }}
|
||||||
|
|
||||||
@ -517,70 +517,70 @@ jobs:
|
|||||||
|
|
||||||
- name: Upload binary tarball (macOS)
|
- name: Upload binary tarball (macOS)
|
||||||
if: runner.os == 'macOS'
|
if: runner.os == 'macOS'
|
||||||
uses: actions/upload-artifact@v3
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: PrismLauncher-${{ matrix.name }}-${{ env.VERSION }}-${{ inputs.build_type }}
|
name: PrismLauncher-${{ matrix.name }}-${{ env.VERSION }}-${{ inputs.build_type }}
|
||||||
path: PrismLauncher.tar.gz
|
path: PrismLauncher.tar.gz
|
||||||
|
|
||||||
- name: Upload binary zip (Windows)
|
- name: Upload binary zip (Windows)
|
||||||
if: runner.os == 'Windows'
|
if: runner.os == 'Windows'
|
||||||
uses: actions/upload-artifact@v3
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: PrismLauncher-${{ matrix.name }}-${{ env.VERSION }}-${{ inputs.build_type }}
|
name: PrismLauncher-${{ matrix.name }}-${{ env.VERSION }}-${{ inputs.build_type }}
|
||||||
path: ${{ env.INSTALL_DIR }}/**
|
path: ${{ env.INSTALL_DIR }}/**
|
||||||
|
|
||||||
- name: Upload binary zip (Windows, portable)
|
- name: Upload binary zip (Windows, portable)
|
||||||
if: runner.os == 'Windows'
|
if: runner.os == 'Windows'
|
||||||
uses: actions/upload-artifact@v3
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: PrismLauncher-${{ matrix.name }}-Portable-${{ env.VERSION }}-${{ inputs.build_type }}
|
name: PrismLauncher-${{ matrix.name }}-Portable-${{ env.VERSION }}-${{ inputs.build_type }}
|
||||||
path: ${{ env.INSTALL_PORTABLE_DIR }}/**
|
path: ${{ env.INSTALL_PORTABLE_DIR }}/**
|
||||||
|
|
||||||
- name: Upload installer (Windows)
|
- name: Upload installer (Windows)
|
||||||
if: runner.os == 'Windows'
|
if: runner.os == 'Windows'
|
||||||
uses: actions/upload-artifact@v3
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: PrismLauncher-${{ matrix.name }}-Setup-${{ env.VERSION }}-${{ inputs.build_type }}
|
name: PrismLauncher-${{ matrix.name }}-Setup-${{ env.VERSION }}-${{ inputs.build_type }}
|
||||||
path: PrismLauncher-Setup.exe
|
path: PrismLauncher-Setup.exe
|
||||||
|
|
||||||
- name: Upload binary tarball (Linux, Qt 5)
|
- name: Upload binary tarball (Linux, Qt 5)
|
||||||
if: runner.os == 'Linux' && matrix.qt_ver != 6
|
if: runner.os == 'Linux' && matrix.qt_ver != 6
|
||||||
uses: actions/upload-artifact@v3
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: PrismLauncher-${{ runner.os }}-Qt5-${{ env.VERSION }}-${{ inputs.build_type }}
|
name: PrismLauncher-${{ runner.os }}-Qt5-${{ env.VERSION }}-${{ inputs.build_type }}
|
||||||
path: PrismLauncher.tar.gz
|
path: PrismLauncher.tar.gz
|
||||||
|
|
||||||
- name: Upload binary tarball (Linux, portable, Qt 5)
|
- name: Upload binary tarball (Linux, portable, Qt 5)
|
||||||
if: runner.os == 'Linux' && matrix.qt_ver != 6
|
if: runner.os == 'Linux' && matrix.qt_ver != 6
|
||||||
uses: actions/upload-artifact@v3
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: PrismLauncher-${{ runner.os }}-Qt5-Portable-${{ env.VERSION }}-${{ inputs.build_type }}
|
name: PrismLauncher-${{ runner.os }}-Qt5-Portable-${{ env.VERSION }}-${{ inputs.build_type }}
|
||||||
path: PrismLauncher-portable.tar.gz
|
path: PrismLauncher-portable.tar.gz
|
||||||
|
|
||||||
- name: Upload binary tarball (Linux, Qt 6)
|
- name: Upload binary tarball (Linux, Qt 6)
|
||||||
if: runner.os == 'Linux' && matrix.qt_ver !=5
|
if: runner.os == 'Linux' && matrix.qt_ver !=5
|
||||||
uses: actions/upload-artifact@v3
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: PrismLauncher-${{ runner.os }}-Qt6-${{ env.VERSION }}-${{ inputs.build_type }}
|
name: PrismLauncher-${{ runner.os }}-Qt6-${{ env.VERSION }}-${{ inputs.build_type }}
|
||||||
path: PrismLauncher.tar.gz
|
path: PrismLauncher.tar.gz
|
||||||
|
|
||||||
- name: Upload binary tarball (Linux, portable, Qt 6)
|
- name: Upload binary tarball (Linux, portable, Qt 6)
|
||||||
if: runner.os == 'Linux' && matrix.qt_ver != 5
|
if: runner.os == 'Linux' && matrix.qt_ver != 5
|
||||||
uses: actions/upload-artifact@v3
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: PrismLauncher-${{ runner.os }}-Qt6-Portable-${{ env.VERSION }}-${{ inputs.build_type }}
|
name: PrismLauncher-${{ runner.os }}-Qt6-Portable-${{ env.VERSION }}-${{ inputs.build_type }}
|
||||||
path: PrismLauncher-portable.tar.gz
|
path: PrismLauncher-portable.tar.gz
|
||||||
|
|
||||||
- name: Upload AppImage (Linux)
|
- name: Upload AppImage (Linux)
|
||||||
if: runner.os == 'Linux' && matrix.qt_ver != 5
|
if: runner.os == 'Linux' && matrix.qt_ver != 5
|
||||||
uses: actions/upload-artifact@v3
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: PrismLauncher-${{ runner.os }}-${{ env.VERSION }}-${{ inputs.build_type }}-x86_64.AppImage
|
name: PrismLauncher-${{ runner.os }}-${{ env.VERSION }}-${{ inputs.build_type }}-x86_64.AppImage
|
||||||
path: PrismLauncher-${{ runner.os }}-${{ env.VERSION }}-${{ inputs.build_type }}-x86_64.AppImage
|
path: PrismLauncher-${{ runner.os }}-${{ env.VERSION }}-${{ inputs.build_type }}-x86_64.AppImage
|
||||||
|
|
||||||
- name: Upload AppImage Zsync (Linux)
|
- name: Upload AppImage Zsync (Linux)
|
||||||
if: runner.os == 'Linux' && matrix.qt_ver != 5
|
if: runner.os == 'Linux' && matrix.qt_ver != 5
|
||||||
uses: actions/upload-artifact@v3
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: PrismLauncher-${{ runner.os }}-${{ env.VERSION }}-${{ inputs.build_type }}-x86_64.AppImage.zsync
|
name: PrismLauncher-${{ runner.os }}-${{ env.VERSION }}-${{ inputs.build_type }}-x86_64.AppImage.zsync
|
||||||
path: PrismLauncher-Linux-x86_64.AppImage.zsync
|
path: PrismLauncher-Linux-x86_64.AppImage.zsync
|
||||||
|
4
.github/workflows/codeql.yml
vendored
4
.github/workflows/codeql.yml
vendored
@ -13,7 +13,7 @@ jobs:
|
|||||||
submodules: 'true'
|
submodules: 'true'
|
||||||
|
|
||||||
- name: Initialize CodeQL
|
- name: Initialize CodeQL
|
||||||
uses: github/codeql-action/init@v2
|
uses: github/codeql-action/init@v3
|
||||||
with:
|
with:
|
||||||
config-file: ./.github/codeql/codeql-config.yml
|
config-file: ./.github/codeql/codeql-config.yml
|
||||||
queries: security-and-quality
|
queries: security-and-quality
|
||||||
@ -32,4 +32,4 @@ jobs:
|
|||||||
cmake --build build
|
cmake --build build
|
||||||
|
|
||||||
- name: Perform CodeQL Analysis
|
- name: Perform CodeQL Analysis
|
||||||
uses: github/codeql-action/analyze@v2
|
uses: github/codeql-action/analyze@v3
|
||||||
|
2
.github/workflows/trigger_release.yml
vendored
2
.github/workflows/trigger_release.yml
vendored
@ -32,7 +32,7 @@ jobs:
|
|||||||
submodules: "true"
|
submodules: "true"
|
||||||
path: "PrismLauncher-source"
|
path: "PrismLauncher-source"
|
||||||
- name: Download artifacts
|
- name: Download artifacts
|
||||||
uses: actions/download-artifact@v3
|
uses: actions/download-artifact@v4
|
||||||
- name: Grab and store version
|
- name: Grab and store version
|
||||||
run: |
|
run: |
|
||||||
tag_name=$(echo ${{ github.ref }} | grep -oE "[^/]+$")
|
tag_name=$(echo ${{ github.ref }} | grep -oE "[^/]+$")
|
||||||
|
2
.github/workflows/update-flake.yml
vendored
2
.github/workflows/update-flake.yml
vendored
@ -17,7 +17,7 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
- uses: cachix/install-nix-action@6a9a9e84a173d90b3ffb42c5ddaf9ea033fad011 # v23
|
- uses: cachix/install-nix-action@7ac1ec25491415c381d9b62f0657c7a028df52a7 # v24
|
||||||
|
|
||||||
- uses: DeterminateSystems/update-flake-lock@v20
|
- uses: DeterminateSystems/update-flake-lock@v20
|
||||||
with:
|
with:
|
||||||
|
@ -377,7 +377,7 @@ if(UNIX AND APPLE)
|
|||||||
set(MACOSX_BUNDLE_SHORT_VERSION_STRING "${Launcher_VERSION_NAME}")
|
set(MACOSX_BUNDLE_SHORT_VERSION_STRING "${Launcher_VERSION_NAME}")
|
||||||
set(MACOSX_BUNDLE_LONG_VERSION_STRING "${Launcher_VERSION_NAME}")
|
set(MACOSX_BUNDLE_LONG_VERSION_STRING "${Launcher_VERSION_NAME}")
|
||||||
set(MACOSX_BUNDLE_ICON_FILE ${Launcher_Name}.icns)
|
set(MACOSX_BUNDLE_ICON_FILE ${Launcher_Name}.icns)
|
||||||
set(MACOSX_BUNDLE_COPYRIGHT "© 2022-2023 ${Launcher_Copyright_Mac}")
|
set(MACOSX_BUNDLE_COPYRIGHT "${Launcher_Copyright_Mac}")
|
||||||
set(MACOSX_SPARKLE_UPDATE_PUBLIC_KEY "v55ZWWD6QlPoXGV6VLzOTZxZUggWeE51X8cRQyQh6vA=" CACHE STRING "Public key for Sparkle update feed")
|
set(MACOSX_SPARKLE_UPDATE_PUBLIC_KEY "v55ZWWD6QlPoXGV6VLzOTZxZUggWeE51X8cRQyQh6vA=" CACHE STRING "Public key for Sparkle update feed")
|
||||||
set(MACOSX_SPARKLE_UPDATE_FEED_URL "https://prismlauncher.org/feed/appcast.xml" CACHE STRING "URL for Sparkle update feed")
|
set(MACOSX_SPARKLE_UPDATE_FEED_URL "https://prismlauncher.org/feed/appcast.xml" CACHE STRING "URL for Sparkle update feed")
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
## Prism Launcher
|
## Prism Launcher
|
||||||
|
|
||||||
Prism Launcher - Minecraft Launcher
|
Prism Launcher - Minecraft Launcher
|
||||||
Copyright (C) 2022-2023 Prism Launcher Contributors
|
Copyright (C) 2022-2024 Prism Launcher Contributors
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
@ -436,7 +436,7 @@
|
|||||||
Copyright (C) 2007 Johann Ollivier Lapeyre <johann@oxygen-icons.org>
|
Copyright (C) 2007 Johann Ollivier Lapeyre <johann@oxygen-icons.org>
|
||||||
Copyright (C) 2007 Kenneth Wimer <kwwii@bootsplash.org>
|
Copyright (C) 2007 Kenneth Wimer <kwwii@bootsplash.org>
|
||||||
Copyright (C) 2007 Riccardo Iaconelli <riccardo@oxygen-icons.org>
|
Copyright (C) 2007 Riccardo Iaconelli <riccardo@oxygen-icons.org>
|
||||||
|
|
||||||
and others
|
and others
|
||||||
|
|
||||||
This library is free software; you can redistribute it and/or
|
This library is free software; you can redistribute it and/or
|
||||||
|
30
flake.lock
generated
30
flake.lock
generated
@ -21,11 +21,11 @@
|
|||||||
"nixpkgs-lib": "nixpkgs-lib"
|
"nixpkgs-lib": "nixpkgs-lib"
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1698882062,
|
"lastModified": 1704152458,
|
||||||
"narHash": "sha256-HkhafUayIqxXyHH1X8d9RDl1M2CkFgZLjKD3MzabiEo=",
|
"narHash": "sha256-DS+dGw7SKygIWf9w4eNBUZsK+4Ug27NwEWmn2tnbycg=",
|
||||||
"owner": "hercules-ci",
|
"owner": "hercules-ci",
|
||||||
"repo": "flake-parts",
|
"repo": "flake-parts",
|
||||||
"rev": "8c9fa2545007b49a5db5f650ae91f227672c3877",
|
"rev": "88a2cd8166694ba0b6cb374700799cec53aef527",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@ -91,11 +91,11 @@
|
|||||||
},
|
},
|
||||||
"nix-filter": {
|
"nix-filter": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1694857738,
|
"lastModified": 1701697642,
|
||||||
"narHash": "sha256-bxxNyLHjhu0N8T3REINXQ2ZkJco0ABFPn6PIe2QUfqo=",
|
"narHash": "sha256-L217WytWZHSY8GW9Gx1A64OnNctbuDbfslaTEofXXRw=",
|
||||||
"owner": "numtide",
|
"owner": "numtide",
|
||||||
"repo": "nix-filter",
|
"repo": "nix-filter",
|
||||||
"rev": "41fd48e00c22b4ced525af521ead8792402de0ea",
|
"rev": "c843418ecfd0344ecb85844b082ff5675e02c443",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@ -106,11 +106,11 @@
|
|||||||
},
|
},
|
||||||
"nixpkgs": {
|
"nixpkgs": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1700108881,
|
"lastModified": 1704161960,
|
||||||
"narHash": "sha256-+Lqybl8kj0+nD/IlAWPPG/RDTa47gff9nbei0u7BntE=",
|
"narHash": "sha256-QGua89Pmq+FBAro8NriTuoO/wNaUtugt29/qqA8zeeM=",
|
||||||
"owner": "nixos",
|
"owner": "nixos",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "7414e9ee0b3e9903c24d3379f577a417f0aae5f1",
|
"rev": "63143ac2c9186be6d9da6035fa22620018c85932",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@ -123,11 +123,11 @@
|
|||||||
"nixpkgs-lib": {
|
"nixpkgs-lib": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"dir": "lib",
|
"dir": "lib",
|
||||||
"lastModified": 1698611440,
|
"lastModified": 1703961334,
|
||||||
"narHash": "sha256-jPjHjrerhYDy3q9+s5EAsuhyhuknNfowY6yt6pjn9pc=",
|
"narHash": "sha256-M1mV/Cq+pgjk0rt6VxoyyD+O8cOUiai8t9Q6Yyq4noY=",
|
||||||
"owner": "NixOS",
|
"owner": "NixOS",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "0cbe9f69c234a7700596e943bfae7ef27a31b735",
|
"rev": "b0d36bd0a420ecee3bc916c91886caca87c894e9",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@ -153,11 +153,11 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1700064067,
|
"lastModified": 1703939133,
|
||||||
"narHash": "sha256-1ZWNDzhu8UlVCK7+DUN9dVQfiHX1bv6OQP9VxstY/gs=",
|
"narHash": "sha256-Gxe+mfOT6bL7wLC/tuT2F+V+Sb44jNr8YsJ3cyIl4Mo=",
|
||||||
"owner": "cachix",
|
"owner": "cachix",
|
||||||
"repo": "pre-commit-hooks.nix",
|
"repo": "pre-commit-hooks.nix",
|
||||||
"rev": "e558068cba67b23b4fbc5537173dbb43748a17e8",
|
"rev": "9d3d7e18c6bc4473d7520200d4ddab12f8402d38",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
id: org.prismlauncher.PrismLauncher
|
id: org.prismlauncher.PrismLauncher
|
||||||
runtime: org.kde.Platform
|
runtime: org.kde.Platform
|
||||||
runtime-version: "5.15-23.08"
|
runtime-version: 5.15-23.08
|
||||||
sdk: org.kde.Sdk
|
sdk: org.kde.Sdk
|
||||||
sdk-extensions:
|
sdk-extensions:
|
||||||
- org.freedesktop.Sdk.Extension.openjdk17
|
- org.freedesktop.Sdk.Extension.openjdk17
|
||||||
@ -104,18 +104,15 @@ modules:
|
|||||||
- install -Dm755 ../data/gamemoderun -t /app/bin
|
- install -Dm755 ../data/gamemoderun -t /app/bin
|
||||||
sources:
|
sources:
|
||||||
- type: archive
|
- type: archive
|
||||||
archive-type: tar-gzip
|
dest-filename: gamemode.tar.gz
|
||||||
url: https://api.github.com/repos/FeralInteractive/gamemode/tarball/1.7
|
url: https://api.github.com/repos/FeralInteractive/gamemode/tarball/1.8.1
|
||||||
sha256: 57ce73ba605d1cf12f8d13725006a895182308d93eba0f69f285648449641803
|
sha256: 969cf85b5ca3944f3e315cd73a0ee9bea4f9c968cd7d485e9f4745bc1e679c4e
|
||||||
x-checker-data:
|
x-checker-data:
|
||||||
type: json
|
type: json
|
||||||
url: https://api.github.com/repos/FeralInteractive/gamemode/releases/latest
|
url: https://api.github.com/repos/FeralInteractive/gamemode/releases/latest
|
||||||
version-query: .tag_name
|
version-query: .tag_name
|
||||||
url-query: .tarball_url
|
url-query: .tarball_url
|
||||||
timestamp-query: .published_at
|
timestamp-query: .published_at
|
||||||
# from https://github.com/flathub/net.gaijin.WarThunder/blob/7ea6f7a9f84b9c77150c003a7059dc03f8dcbc7f/gamemode.patch
|
|
||||||
- type: patch
|
|
||||||
path: patches/gamemode.patch
|
|
||||||
cleanup:
|
cleanup:
|
||||||
- /include
|
- /include
|
||||||
- /lib/pkgconfig
|
- /lib/pkgconfig
|
||||||
|
@ -1,12 +0,0 @@
|
|||||||
diff -ruN a/common/common-pidfds.c b/common/common-pidfds.c
|
|
||||||
--- a/common/common-pidfds.c 2021-02-18 20:00:12.000000000 +0100
|
|
||||||
+++ b/common/common-pidfds.c 2023-09-07 08:57:42.954362763 +0200
|
|
||||||
@@ -58,6 +58,8 @@
|
|
||||||
{
|
|
||||||
return (int)syscall(__NR_pidfd_open, pid, flags);
|
|
||||||
}
|
|
||||||
+#else
|
|
||||||
+#include <sys/pidfd.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* pidfd functions */
|
|
@ -1 +1 @@
|
|||||||
Subproject commit 45094ca570be383d06df729b6972830ec63bd3df
|
Subproject commit 55a8e460c6343229597a13e973ba4855c27a1c4c
|
@ -132,6 +132,15 @@
|
|||||||
#include "gamemode_client.h"
|
#include "gamemode_client.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(Q_OS_LINUX)
|
||||||
|
#include <sys/statvfs.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(Q_OS_FREEBSD) || defined(Q_OS_OPENBSD)
|
||||||
|
#include <sys/mount.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined(Q_OS_MAC)
|
#if defined(Q_OS_MAC)
|
||||||
#if defined(SPARKLE_ENABLED)
|
#if defined(SPARKLE_ENABLED)
|
||||||
#include "updater/MacSparkleUpdater.h"
|
#include "updater/MacSparkleUpdater.h"
|
||||||
@ -485,8 +494,7 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
qDebug() << qPrintable(BuildConfig.LAUNCHER_DISPLAYNAME) << ", (c) 2022-2023 "
|
qDebug() << qPrintable(BuildConfig.LAUNCHER_DISPLAYNAME + ", " + QString(BuildConfig.LAUNCHER_COPYRIGHT).replace("\n", ", "));
|
||||||
<< qPrintable(QString(BuildConfig.LAUNCHER_COPYRIGHT).replace("\n", ", "));
|
|
||||||
qDebug() << "Version : " << BuildConfig.printableVersionString();
|
qDebug() << "Version : " << BuildConfig.printableVersionString();
|
||||||
qDebug() << "Platform : " << BuildConfig.BUILD_PLATFORM;
|
qDebug() << "Platform : " << BuildConfig.BUILD_PLATFORM;
|
||||||
qDebug() << "Git commit : " << BuildConfig.GIT_COMMIT;
|
qDebug() << "Git commit : " << BuildConfig.GIT_COMMIT;
|
||||||
@ -658,6 +666,9 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv)
|
|||||||
|
|
||||||
// The cat
|
// The cat
|
||||||
m_settings->registerSetting("TheCat", false);
|
m_settings->registerSetting("TheCat", false);
|
||||||
|
m_settings->registerSetting("CatOpacity", 100);
|
||||||
|
|
||||||
|
m_settings->registerSetting("StatusBarVisible", true);
|
||||||
|
|
||||||
m_settings->registerSetting("ToolbarsLocked", false);
|
m_settings->registerSetting("ToolbarsLocked", false);
|
||||||
|
|
||||||
@ -988,6 +999,37 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// notify user if /tmp is mounted with `noexec` (#1693)
|
||||||
|
{
|
||||||
|
bool is_tmp_noexec = false;
|
||||||
|
|
||||||
|
#if defined(Q_OS_LINUX)
|
||||||
|
|
||||||
|
struct statvfs tmp_stat;
|
||||||
|
statvfs("/tmp", &tmp_stat);
|
||||||
|
is_tmp_noexec = tmp_stat.f_flag & ST_NOEXEC;
|
||||||
|
|
||||||
|
#elif defined(Q_OS_FREEBSD) || defined(Q_OS_OPENBSD)
|
||||||
|
|
||||||
|
struct statfs tmp_stat;
|
||||||
|
statfs("/tmp", &tmp_stat);
|
||||||
|
is_tmp_noexec = tmp_stat.f_flags & MNT_NOEXEC;
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (is_tmp_noexec) {
|
||||||
|
auto infoMsg =
|
||||||
|
tr("Your /tmp directory is currently mounted with the 'noexec' flag enabled.\n"
|
||||||
|
"Some versions of Minecraft may not launch.\n");
|
||||||
|
auto msgBox = new QMessageBox(QMessageBox::Information, tr("Incompatible system configuration"), infoMsg, QMessageBox::Ok);
|
||||||
|
msgBox->setDefaultButton(QMessageBox::Ok);
|
||||||
|
msgBox->setAttribute(Qt::WA_DeleteOnClose);
|
||||||
|
msgBox->setMinimumWidth(460);
|
||||||
|
msgBox->adjustSize();
|
||||||
|
msgBox->open();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (createSetupWizard()) {
|
if (createSetupWizard()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -1471,6 +1513,17 @@ InstanceWindow* Application::showInstanceWindow(InstancePtr instance, QString pa
|
|||||||
auto& window = extras.window;
|
auto& window = extras.window;
|
||||||
|
|
||||||
if (window) {
|
if (window) {
|
||||||
|
// If the window is minimized on macOS or Windows, activate and bring it up
|
||||||
|
#ifdef Q_OS_MACOS
|
||||||
|
if (window->isMinimized()) {
|
||||||
|
window->setWindowState(window->windowState() & ~Qt::WindowMinimized);
|
||||||
|
}
|
||||||
|
#elif defined(Q_OS_WIN)
|
||||||
|
if (window->isMinimized()) {
|
||||||
|
window->showNormal();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
window->raise();
|
window->raise();
|
||||||
window->activateWindow();
|
window->activateWindow();
|
||||||
} else {
|
} else {
|
||||||
@ -1478,6 +1531,7 @@ InstanceWindow* Application::showInstanceWindow(InstancePtr instance, QString pa
|
|||||||
m_openWindows++;
|
m_openWindows++;
|
||||||
connect(window, &InstanceWindow::isClosing, this, &Application::on_windowClose);
|
connect(window, &InstanceWindow::isClosing, this, &Application::on_windowClose);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!page.isEmpty()) {
|
if (!page.isEmpty()) {
|
||||||
window->selectPage(page);
|
window->selectPage(page);
|
||||||
}
|
}
|
||||||
|
@ -64,6 +64,8 @@ BaseInstance::BaseInstance(SettingsObjectPtr globalSettings, SettingsObjectPtr s
|
|||||||
|
|
||||||
m_settings->registerSetting("lastLaunchTime", 0);
|
m_settings->registerSetting("lastLaunchTime", 0);
|
||||||
m_settings->registerSetting("totalTimePlayed", 0);
|
m_settings->registerSetting("totalTimePlayed", 0);
|
||||||
|
if (m_settings->get("totalTimePlayed").toLongLong() < 0)
|
||||||
|
m_settings->reset("totalTimePlayed");
|
||||||
m_settings->registerSetting("lastTimePlayed", 0);
|
m_settings->registerSetting("lastTimePlayed", 0);
|
||||||
|
|
||||||
m_settings->registerSetting("linkedInstances", "[]");
|
m_settings->registerSetting("linkedInstances", "[]");
|
||||||
|
@ -142,9 +142,8 @@ void InstanceCopyTask::copyFinished()
|
|||||||
if (!m_keepPlaytime) {
|
if (!m_keepPlaytime) {
|
||||||
inst->resetTimePlayed();
|
inst->resetTimePlayed();
|
||||||
}
|
}
|
||||||
if (m_useLinks)
|
|
||||||
inst->addLinkedInstanceId(m_origInstance->id());
|
|
||||||
if (m_useLinks) {
|
if (m_useLinks) {
|
||||||
|
inst->addLinkedInstanceId(m_origInstance->id());
|
||||||
auto allowed_symlinks_file = QFileInfo(FS::PathCombine(inst->gameRoot(), "allowed_symlinks.txt"));
|
auto allowed_symlinks_file = QFileInfo(FS::PathCombine(inst->gameRoot(), "allowed_symlinks.txt"));
|
||||||
|
|
||||||
QByteArray allowed_symlinks;
|
QByteArray allowed_symlinks;
|
||||||
|
@ -157,20 +157,6 @@ void MojangVersionFormat::readVersionProperties(const QJsonObject& in, VersionFi
|
|||||||
Bits::readString(in, "id", out->minecraftVersion);
|
Bits::readString(in, "id", out->minecraftVersion);
|
||||||
Bits::readString(in, "mainClass", out->mainClass);
|
Bits::readString(in, "mainClass", out->mainClass);
|
||||||
Bits::readString(in, "minecraftArguments", out->minecraftArguments);
|
Bits::readString(in, "minecraftArguments", out->minecraftArguments);
|
||||||
if (out->minecraftArguments.isEmpty()) {
|
|
||||||
QString processArguments;
|
|
||||||
Bits::readString(in, "processArguments", processArguments);
|
|
||||||
QString toCompare = processArguments.toLower();
|
|
||||||
if (toCompare == "legacy") {
|
|
||||||
out->minecraftArguments = " ${auth_player_name} ${auth_session}";
|
|
||||||
} else if (toCompare == "username_session") {
|
|
||||||
out->minecraftArguments = "--username ${auth_player_name} --session ${auth_session}";
|
|
||||||
} else if (toCompare == "username_session_version") {
|
|
||||||
out->minecraftArguments = "--username ${auth_player_name} --session ${auth_session} --version ${profile_name}";
|
|
||||||
} else if (!toCompare.isEmpty()) {
|
|
||||||
out->addProblem(ProblemSeverity::Error, QObject::tr("processArguments is set to unknown value '%1'").arg(processArguments));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Bits::readString(in, "type", out->type);
|
Bits::readString(in, "type", out->type);
|
||||||
|
|
||||||
Bits::readString(in, "assets", out->assets);
|
Bits::readString(in, "assets", out->assets);
|
||||||
|
@ -306,7 +306,6 @@ void ResourceFolderModel::applyUpdates(QSet<QString>& current_set, QSet<QString>
|
|||||||
auto removed_it = m_resources.begin() + removed_index;
|
auto removed_it = m_resources.begin() + removed_index;
|
||||||
|
|
||||||
Q_ASSERT(removed_it != m_resources.end());
|
Q_ASSERT(removed_it != m_resources.end());
|
||||||
Q_ASSERT(removed_set.contains(removed_it->get()->internal_id()));
|
|
||||||
|
|
||||||
if ((*removed_it)->isResolving()) {
|
if ((*removed_it)->isResolving()) {
|
||||||
auto ticket = (*removed_it)->resolutionTicket();
|
auto ticket = (*removed_it)->resolutionTicket();
|
||||||
|
@ -184,7 +184,9 @@ Task::Ptr GetModDependenciesTask::prepareDependencyTask(const ModPlatform::Depen
|
|||||||
|
|
||||||
ResourceAPI::DependencySearchArgs args = { dep, m_version, m_loaderType };
|
ResourceAPI::DependencySearchArgs args = { dep, m_version, m_loaderType };
|
||||||
ResourceAPI::DependencySearchCallbacks callbacks;
|
ResourceAPI::DependencySearchCallbacks callbacks;
|
||||||
|
callbacks.on_fail = [](QString reason, int) {
|
||||||
|
qCritical() << tr("A network error occurred. Could not load project dependencies:%1").arg(reason);
|
||||||
|
};
|
||||||
callbacks.on_succeed = [dep, provider, pDep, level, this](auto& doc, [[maybe_unused]] auto& pack) {
|
callbacks.on_succeed = [dep, provider, pDep, level, this](auto& doc, [[maybe_unused]] auto& pack) {
|
||||||
try {
|
try {
|
||||||
QJsonArray arr;
|
QJsonArray arr;
|
||||||
|
@ -149,6 +149,7 @@ void EnsureMetadataTask::executeTask()
|
|||||||
if (m_current_task)
|
if (m_current_task)
|
||||||
m_current_task.reset();
|
m_current_task.reset();
|
||||||
});
|
});
|
||||||
|
connect(project_task.get(), &Task::failed, this, &EnsureMetadataTask::emitFailed);
|
||||||
|
|
||||||
m_current_task = project_task;
|
m_current_task = project_task;
|
||||||
project_task->start();
|
project_task->start();
|
||||||
|
@ -122,6 +122,8 @@ struct ExtraPackData {
|
|||||||
QString wikiUrl;
|
QString wikiUrl;
|
||||||
QString discordUrl;
|
QString discordUrl;
|
||||||
|
|
||||||
|
QString status;
|
||||||
|
|
||||||
QString body;
|
QString body;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -96,6 +96,7 @@ class ResourceAPI {
|
|||||||
};
|
};
|
||||||
struct VersionSearchCallbacks {
|
struct VersionSearchCallbacks {
|
||||||
std::function<void(QJsonDocument&, ModPlatform::IndexedPack)> on_succeed;
|
std::function<void(QJsonDocument&, ModPlatform::IndexedPack)> on_succeed;
|
||||||
|
std::function<void(QString const& reason, int network_error_code)> on_fail;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ProjectInfoArgs {
|
struct ProjectInfoArgs {
|
||||||
@ -118,6 +119,7 @@ class ResourceAPI {
|
|||||||
|
|
||||||
struct DependencySearchCallbacks {
|
struct DependencySearchCallbacks {
|
||||||
std::function<void(QJsonDocument&, const ModPlatform::Dependency&)> on_succeed;
|
std::function<void(QJsonDocument&, const ModPlatform::Dependency&)> on_succeed;
|
||||||
|
std::function<void(QString const& reason, int network_error_code)> on_fail;
|
||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -119,7 +119,6 @@ void Flame::FileResolvingTask::netJobFinished()
|
|||||||
connect(m_checkJob.get(), &NetJob::failed, this, [this, step_progress](QString reason) {
|
connect(m_checkJob.get(), &NetJob::failed, this, [this, step_progress](QString reason) {
|
||||||
step_progress->state = TaskStepState::Failed;
|
step_progress->state = TaskStepState::Failed;
|
||||||
stepProgress(*step_progress);
|
stepProgress(*step_progress);
|
||||||
emitFailed(reason);
|
|
||||||
});
|
});
|
||||||
connect(m_checkJob.get(), &NetJob::stepProgress, this, &FileResolvingTask::propagateStepProgress);
|
connect(m_checkJob.get(), &NetJob::stepProgress, this, &FileResolvingTask::propagateStepProgress);
|
||||||
connect(m_checkJob.get(), &NetJob::progress, this, [this, step_progress](qint64 current, qint64 total) {
|
connect(m_checkJob.get(), &NetJob::progress, this, [this, step_progress](qint64 current, qint64 total) {
|
||||||
|
@ -24,7 +24,7 @@ bool FlameCheckUpdate::abort()
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
ModPlatform::IndexedPack getProjectInfo(ModPlatform::IndexedVersion& ver_info)
|
ModPlatform::IndexedPack FlameCheckUpdate::getProjectInfo(ModPlatform::IndexedVersion& ver_info)
|
||||||
{
|
{
|
||||||
ModPlatform::IndexedPack pack;
|
ModPlatform::IndexedPack pack;
|
||||||
|
|
||||||
@ -57,6 +57,7 @@ ModPlatform::IndexedPack getProjectInfo(ModPlatform::IndexedVersion& ver_info)
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
connect(get_project_job, &NetJob::failed, this, &FlameCheckUpdate::emitFailed);
|
||||||
QObject::connect(get_project_job, &NetJob::finished, [&loop, get_project_job] {
|
QObject::connect(get_project_job, &NetJob::finished, [&loop, get_project_job] {
|
||||||
get_project_job->deleteLater();
|
get_project_job->deleteLater();
|
||||||
loop.quit();
|
loop.quit();
|
||||||
@ -68,7 +69,7 @@ ModPlatform::IndexedPack getProjectInfo(ModPlatform::IndexedVersion& ver_info)
|
|||||||
return pack;
|
return pack;
|
||||||
}
|
}
|
||||||
|
|
||||||
ModPlatform::IndexedVersion getFileInfo(int addonId, int fileId)
|
ModPlatform::IndexedVersion FlameCheckUpdate::getFileInfo(int addonId, int fileId)
|
||||||
{
|
{
|
||||||
ModPlatform::IndexedVersion ver;
|
ModPlatform::IndexedVersion ver;
|
||||||
|
|
||||||
@ -100,7 +101,7 @@ ModPlatform::IndexedVersion getFileInfo(int addonId, int fileId)
|
|||||||
qDebug() << doc;
|
qDebug() << doc;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
connect(get_file_info_job, &NetJob::failed, this, &FlameCheckUpdate::emitFailed);
|
||||||
QObject::connect(get_file_info_job, &NetJob::finished, [&loop, get_file_info_job] {
|
QObject::connect(get_file_info_job, &NetJob::finished, [&loop, get_file_info_job] {
|
||||||
get_file_info_job->deleteLater();
|
get_file_info_job->deleteLater();
|
||||||
loop.quit();
|
loop.quit();
|
||||||
|
@ -22,6 +22,9 @@ class FlameCheckUpdate : public CheckUpdateTask {
|
|||||||
void executeTask() override;
|
void executeTask() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
ModPlatform::IndexedPack getProjectInfo(ModPlatform::IndexedVersion& ver_info);
|
||||||
|
ModPlatform::IndexedVersion getFileInfo(int addonId, int fileId);
|
||||||
|
|
||||||
NetJob* m_net_job = nullptr;
|
NetJob* m_net_job = nullptr;
|
||||||
|
|
||||||
bool m_was_aborted = false;
|
bool m_was_aborted = false;
|
||||||
|
@ -227,6 +227,7 @@ bool FlameCreationTask::updateInstance()
|
|||||||
m_files_to_remove.append(old_minecraft_dir.absoluteFilePath(relative_path));
|
m_files_to_remove.append(old_minecraft_dir.absoluteFilePath(relative_path));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
connect(job.get(), &Task::failed, this, [](QString reason) { qCritical() << "Failed to get files: " << reason; });
|
||||||
connect(job.get(), &Task::finished, &loop, &QEventLoop::quit);
|
connect(job.get(), &Task::finished, &loop, &QEventLoop::quit);
|
||||||
|
|
||||||
m_process_update_file_info_job = job;
|
m_process_update_file_info_job = job;
|
||||||
@ -427,6 +428,9 @@ bool FlameCreationTask::createInstance()
|
|||||||
// Don't add managed info to packs without an ID (most likely imported from ZIP)
|
// Don't add managed info to packs without an ID (most likely imported from ZIP)
|
||||||
if (!m_managed_id.isEmpty())
|
if (!m_managed_id.isEmpty())
|
||||||
instance.setManagedPack("flame", m_managed_id, m_pack.name, m_managed_version_id, m_pack.version);
|
instance.setManagedPack("flame", m_managed_id, m_pack.name, m_managed_version_id, m_pack.version);
|
||||||
|
else
|
||||||
|
instance.setManagedPack("flame", "", name(), "", "");
|
||||||
|
|
||||||
instance.setName(name());
|
instance.setName(name());
|
||||||
|
|
||||||
m_mod_id_resolver.reset(new Flame::FileResolvingTask(APPLICATION->network(), m_pack));
|
m_mod_id_resolver.reset(new Flame::FileResolvingTask(APPLICATION->network(), m_pack));
|
||||||
|
@ -323,6 +323,7 @@ void FlamePackExportTask::getProjectsInfo()
|
|||||||
}
|
}
|
||||||
buildZip();
|
buildZip();
|
||||||
});
|
});
|
||||||
|
connect(projTask.get(), &Task::failed, this, &FlamePackExportTask::emitFailed);
|
||||||
task.reset(projTask);
|
task.reset(projTask);
|
||||||
task->start();
|
task->start();
|
||||||
}
|
}
|
||||||
|
@ -102,6 +102,13 @@ Task::Ptr NetworkResourceAPI::getProjectVersions(VersionSearchArgs&& args, Versi
|
|||||||
|
|
||||||
callbacks.on_succeed(doc, args.pack);
|
callbacks.on_succeed(doc, args.pack);
|
||||||
});
|
});
|
||||||
|
QObject::connect(netJob.get(), &NetJob::failed, [&netJob, callbacks](QString reason) {
|
||||||
|
int network_error_code = -1;
|
||||||
|
if (auto* failed_action = netJob->getFailedActions().at(0); failed_action && failed_action->m_reply)
|
||||||
|
network_error_code = failed_action->m_reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
|
||||||
|
|
||||||
|
callbacks.on_fail(reason, network_error_code);
|
||||||
|
});
|
||||||
|
|
||||||
return netJob;
|
return netJob;
|
||||||
}
|
}
|
||||||
@ -146,6 +153,12 @@ Task::Ptr NetworkResourceAPI::getDependencyVersion(DependencySearchArgs&& args,
|
|||||||
|
|
||||||
callbacks.on_succeed(doc, args.dependency);
|
callbacks.on_succeed(doc, args.dependency);
|
||||||
});
|
});
|
||||||
|
QObject::connect(netJob.get(), &NetJob::failed, [&netJob, callbacks](QString reason) {
|
||||||
|
int network_error_code = -1;
|
||||||
|
if (auto* failed_action = netJob->getFailedActions().at(0); failed_action && failed_action->m_reply)
|
||||||
|
network_error_code = failed_action->m_reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
|
||||||
|
|
||||||
|
callbacks.on_fail(reason, network_error_code);
|
||||||
|
});
|
||||||
return netJob;
|
return netJob;
|
||||||
}
|
}
|
||||||
|
@ -72,9 +72,7 @@ void ModrinthCheckUpdate::executeTask()
|
|||||||
auto response = std::make_shared<QByteArray>();
|
auto response = std::make_shared<QByteArray>();
|
||||||
auto job = api.latestVersions(hashes, best_hash_type, m_game_versions, m_loaders, response);
|
auto job = api.latestVersions(hashes, best_hash_type, m_game_versions, m_loaders, response);
|
||||||
|
|
||||||
QEventLoop lock;
|
connect(job.get(), &Task::succeeded, this, [this, response, mappings, best_hash_type, job] {
|
||||||
|
|
||||||
connect(job.get(), &Task::succeeded, this, [this, response, &mappings, best_hash_type, job] {
|
|
||||||
QJsonParseError parse_error{};
|
QJsonParseError parse_error{};
|
||||||
QJsonDocument doc = QJsonDocument::fromJson(*response, &parse_error);
|
QJsonDocument doc = QJsonDocument::fromJson(*response, &parse_error);
|
||||||
if (parse_error.error != QJsonParseError::NoError) {
|
if (parse_error.error != QJsonParseError::NoError) {
|
||||||
@ -82,7 +80,7 @@ void ModrinthCheckUpdate::executeTask()
|
|||||||
<< " reason: " << parse_error.errorString();
|
<< " reason: " << parse_error.errorString();
|
||||||
qWarning() << *response;
|
qWarning() << *response;
|
||||||
|
|
||||||
failed(parse_error.errorString());
|
emitFailed(parse_error.errorString());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -167,19 +165,17 @@ void ModrinthCheckUpdate::executeTask()
|
|||||||
m_deps.append(std::make_shared<GetModDependenciesTask::PackDependency>(pack, project_ver));
|
m_deps.append(std::make_shared<GetModDependenciesTask::PackDependency>(pack, project_ver));
|
||||||
}
|
}
|
||||||
} catch (Json::JsonException& e) {
|
} catch (Json::JsonException& e) {
|
||||||
failed(e.cause() + " : " + e.what());
|
emitFailed(e.cause() + " : " + e.what());
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
emitSucceeded();
|
||||||
});
|
});
|
||||||
|
|
||||||
connect(job.get(), &Task::finished, &lock, &QEventLoop::quit);
|
connect(job.get(), &Task::failed, this, &ModrinthCheckUpdate::emitFailed);
|
||||||
|
|
||||||
setStatus(tr("Waiting for the API response from Modrinth..."));
|
setStatus(tr("Waiting for the API response from Modrinth..."));
|
||||||
setProgress(1, 3);
|
setProgress(1, 3);
|
||||||
|
|
||||||
m_net_job = qSharedPointerObjectCast<NetJob, Task>(job);
|
m_net_job = qSharedPointerObjectCast<NetJob, Task>(job);
|
||||||
job->start();
|
job->start();
|
||||||
|
|
||||||
lock.exec();
|
|
||||||
|
|
||||||
emitSucceeded();
|
|
||||||
}
|
}
|
||||||
|
@ -226,6 +226,9 @@ bool ModrinthCreationTask::createInstance()
|
|||||||
// Don't add managed info to packs without an ID (most likely imported from ZIP)
|
// Don't add managed info to packs without an ID (most likely imported from ZIP)
|
||||||
if (!m_managed_id.isEmpty())
|
if (!m_managed_id.isEmpty())
|
||||||
instance.setManagedPack("modrinth", m_managed_id, m_managed_name, m_managed_version_id, version());
|
instance.setManagedPack("modrinth", m_managed_id, m_managed_name, m_managed_version_id, version());
|
||||||
|
else
|
||||||
|
instance.setManagedPack("modrinth", "", name(), "", "");
|
||||||
|
|
||||||
instance.setName(name());
|
instance.setName(name());
|
||||||
instance.saveNow();
|
instance.saveNow();
|
||||||
|
|
||||||
@ -289,7 +292,7 @@ bool ModrinthCreationTask::createInstance()
|
|||||||
// Only change the name if it didn't use a custom name, so that the previous custom name
|
// Only change the name if it didn't use a custom name, so that the previous custom name
|
||||||
// is preserved, but if we're using the original one, we update the version string.
|
// is preserved, but if we're using the original one, we update the version string.
|
||||||
// NOTE: This needs to come before the copyManagedPack call!
|
// NOTE: This needs to come before the copyManagedPack call!
|
||||||
if (inst->name().contains(inst->getManagedPackVersionName())) {
|
if (inst->name().contains(inst->getManagedPackVersionName()) && inst->name() != instance.name()) {
|
||||||
if (askForChangingInstanceName(m_parent, inst->name(), instance.name()) == InstanceNameChange::ShouldChange)
|
if (askForChangingInstanceName(m_parent, inst->name(), instance.name()) == InstanceNameChange::ShouldChange)
|
||||||
inst->setName(instance.name());
|
inst->setName(instance.name());
|
||||||
}
|
}
|
||||||
|
@ -104,6 +104,8 @@ void Modrinth::loadExtraPackData(ModPlatform::IndexedPack& pack, QJsonObject& ob
|
|||||||
pack.extraData.donate.append(donate);
|
pack.extraData.donate.append(donate);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pack.extraData.status = Json::ensureString(obj, "status");
|
||||||
|
|
||||||
pack.extraData.body = Json::ensureString(obj, "body").remove("<br>");
|
pack.extraData.body = Json::ensureString(obj, "body").remove("<br>");
|
||||||
|
|
||||||
pack.extraDataLoaded = true;
|
pack.extraDataLoaded = true;
|
||||||
|
@ -95,6 +95,8 @@ void loadIndexedInfo(Modpack& pack, QJsonObject& obj)
|
|||||||
pack.extra.donate.append(donate);
|
pack.extra.donate.append(donate);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pack.extra.status = Json::ensureString(obj, "status");
|
||||||
|
|
||||||
pack.extraInfoLoaded = true;
|
pack.extraInfoLoaded = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -77,6 +77,8 @@ struct ModpackExtra {
|
|||||||
QString discordUrl;
|
QString discordUrl;
|
||||||
|
|
||||||
QList<DonationData> donate;
|
QList<DonationData> donate;
|
||||||
|
|
||||||
|
QString status;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ModpackVersion {
|
struct ModpackVersion {
|
||||||
|
@ -36,6 +36,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "NetJob.h"
|
#include "NetJob.h"
|
||||||
|
#include "tasks/ConcurrentTask.h"
|
||||||
#if defined(LAUNCHER_APPLICATION)
|
#if defined(LAUNCHER_APPLICATION)
|
||||||
#include "Application.h"
|
#include "Application.h"
|
||||||
#endif
|
#endif
|
||||||
@ -56,18 +57,15 @@ auto NetJob::addNetAction(NetAction::Ptr action) -> bool
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void NetJob::startNext()
|
void NetJob::executeNextSubTask()
|
||||||
{
|
{
|
||||||
if (m_queue.isEmpty() && m_doing.isEmpty()) {
|
// We're finished, check for failures and retry if we can (up to 3 times)
|
||||||
// We're finished, check for failures and retry if we can (up to 3 times)
|
if (isRunning() && m_queue.isEmpty() && m_doing.isEmpty() && !m_failed.isEmpty() && m_try < 3) {
|
||||||
if (!m_failed.isEmpty() && m_try < 3) {
|
m_try += 1;
|
||||||
m_try += 1;
|
while (!m_failed.isEmpty())
|
||||||
while (!m_failed.isEmpty())
|
m_queue.enqueue(m_failed.take(*m_failed.keyBegin()));
|
||||||
m_queue.enqueue(m_failed.take(*m_failed.keyBegin()));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
ConcurrentTask::executeNextSubTask();
|
||||||
ConcurrentTask::startNext();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto NetJob::size() const -> int
|
auto NetJob::size() const -> int
|
||||||
|
@ -55,8 +55,6 @@ class NetJob : public ConcurrentTask {
|
|||||||
explicit NetJob(QString job_name, shared_qobject_ptr<QNetworkAccessManager> network);
|
explicit NetJob(QString job_name, shared_qobject_ptr<QNetworkAccessManager> network);
|
||||||
~NetJob() override = default;
|
~NetJob() override = default;
|
||||||
|
|
||||||
void startNext() override;
|
|
||||||
|
|
||||||
auto size() const -> int;
|
auto size() const -> int;
|
||||||
|
|
||||||
auto canAbort() const -> bool override;
|
auto canAbort() const -> bool override;
|
||||||
@ -69,6 +67,9 @@ class NetJob : public ConcurrentTask {
|
|||||||
// Qt can't handle auto at the start for some reason?
|
// Qt can't handle auto at the start for some reason?
|
||||||
bool abort() override;
|
bool abort() override;
|
||||||
|
|
||||||
|
protected slots:
|
||||||
|
void executeNextSubTask() override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void updateState() override;
|
void updateState() override;
|
||||||
|
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
qt.*.debug=false
|
qt.*.debug=false
|
||||||
# don't log credentials by default
|
# don't log credentials by default
|
||||||
launcher.auth.credentials.debug=false
|
launcher.auth.credentials.debug=false
|
||||||
|
katabasis.*.debug=false
|
||||||
# remove the debug lines, other log levels still get through
|
# remove the debug lines, other log levels still get through
|
||||||
launcher.task.net.download.debug=false
|
launcher.task.net.download.debug=false
|
||||||
# enable or disable whole catageries
|
# enable or disable whole catageries
|
||||||
|
@ -58,14 +58,14 @@ void ImgurUpload::init()
|
|||||||
|
|
||||||
QNetworkReply* ImgurUpload::getReply(QNetworkRequest& request)
|
QNetworkReply* ImgurUpload::getReply(QNetworkRequest& request)
|
||||||
{
|
{
|
||||||
auto file = new QFile(m_fileInfo.absoluteFilePath());
|
auto file = new QFile(m_fileInfo.absoluteFilePath(), this);
|
||||||
|
|
||||||
if (!file->open(QFile::ReadOnly)) {
|
if (!file->open(QFile::ReadOnly)) {
|
||||||
emitFailed();
|
emitFailed();
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
QHttpMultiPart* multipart = new QHttpMultiPart(QHttpMultiPart::FormDataType);
|
QHttpMultiPart* multipart = new QHttpMultiPart(QHttpMultiPart::FormDataType, this);
|
||||||
file->setParent(multipart);
|
file->setParent(multipart);
|
||||||
QHttpPart filePart;
|
QHttpPart filePart;
|
||||||
filePart.setBodyDevice(file);
|
filePart.setBodyDevice(file);
|
||||||
|
@ -54,6 +54,7 @@ bool INIFile::saveFile(QString fileName)
|
|||||||
insert("ConfigVersion", "1.2");
|
insert("ConfigVersion", "1.2");
|
||||||
QSettings _settings_obj{ fileName, QSettings::Format::IniFormat };
|
QSettings _settings_obj{ fileName, QSettings::Format::IniFormat };
|
||||||
_settings_obj.setFallbacksEnabled(false);
|
_settings_obj.setFallbacksEnabled(false);
|
||||||
|
_settings_obj.clear();
|
||||||
|
|
||||||
for (Iterator iter = begin(); iter != end(); iter++)
|
for (Iterator iter = begin(); iter != end(); iter++)
|
||||||
_settings_obj.setValue(iter.key(), iter.value());
|
_settings_obj.setValue(iter.key(), iter.value());
|
||||||
|
@ -35,7 +35,6 @@
|
|||||||
*/
|
*/
|
||||||
#include "ConcurrentTask.h"
|
#include "ConcurrentTask.h"
|
||||||
|
|
||||||
#include <QCoreApplication>
|
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include "tasks/Task.h"
|
#include "tasks/Task.h"
|
||||||
|
|
||||||
@ -47,9 +46,9 @@ ConcurrentTask::ConcurrentTask(QObject* parent, QString task_name, int max_concu
|
|||||||
|
|
||||||
ConcurrentTask::~ConcurrentTask()
|
ConcurrentTask::~ConcurrentTask()
|
||||||
{
|
{
|
||||||
for (auto task : m_queue) {
|
for (auto task : m_doing) {
|
||||||
if (task)
|
if (task)
|
||||||
task->deleteLater();
|
task->disconnect(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -65,15 +64,13 @@ void ConcurrentTask::addTask(Task::Ptr task)
|
|||||||
|
|
||||||
void ConcurrentTask::executeTask()
|
void ConcurrentTask::executeTask()
|
||||||
{
|
{
|
||||||
// Start one task, startNext handles starting the up to the m_total_max_size
|
for (auto i = 0; i < m_total_max_size; i++)
|
||||||
// while tracking the number currently being done
|
QMetaObject::invokeMethod(this, &ConcurrentTask::executeNextSubTask, Qt::QueuedConnection);
|
||||||
QMetaObject::invokeMethod(this, &ConcurrentTask::startNext, Qt::QueuedConnection);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ConcurrentTask::abort()
|
bool ConcurrentTask::abort()
|
||||||
{
|
{
|
||||||
m_queue.clear();
|
m_queue.clear();
|
||||||
m_aborted = true;
|
|
||||||
|
|
||||||
if (m_doing.isEmpty()) {
|
if (m_doing.isEmpty()) {
|
||||||
// Don't call emitAborted() here, we want to bypass the 'is the task running' check
|
// Don't call emitAborted() here, we want to bypass the 'is the task running' check
|
||||||
@ -108,29 +105,36 @@ void ConcurrentTask::clear()
|
|||||||
m_failed.clear();
|
m_failed.clear();
|
||||||
m_queue.clear();
|
m_queue.clear();
|
||||||
|
|
||||||
m_aborted = false;
|
|
||||||
|
|
||||||
m_progress = 0;
|
m_progress = 0;
|
||||||
m_stepProgress = 0;
|
m_stepProgress = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConcurrentTask::startNext()
|
void ConcurrentTask::executeNextSubTask()
|
||||||
{
|
{
|
||||||
if (m_aborted || m_doing.count() > m_total_max_size)
|
if (!isRunning()) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
if (m_queue.isEmpty() && m_doing.isEmpty() && !wasSuccessful()) {
|
if (m_doing.count() >= m_total_max_size) {
|
||||||
emitSucceeded();
|
return;
|
||||||
|
}
|
||||||
|
if (m_queue.isEmpty()) {
|
||||||
|
if (m_doing.isEmpty()) {
|
||||||
|
if (m_failed.isEmpty())
|
||||||
|
emitSucceeded();
|
||||||
|
else
|
||||||
|
emitFailed(tr("One or more subtasks failed"));
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_queue.isEmpty())
|
startSubTask(m_queue.dequeue());
|
||||||
return;
|
}
|
||||||
|
|
||||||
Task::Ptr next = m_queue.dequeue();
|
|
||||||
|
|
||||||
|
void ConcurrentTask::startSubTask(Task::Ptr next)
|
||||||
|
{
|
||||||
connect(next.get(), &Task::succeeded, this, [this, next]() { subTaskSucceeded(next); });
|
connect(next.get(), &Task::succeeded, this, [this, next]() { subTaskSucceeded(next); });
|
||||||
connect(next.get(), &Task::failed, this, [this, next](QString msg) { subTaskFailed(next, msg); });
|
connect(next.get(), &Task::failed, this, [this, next](QString msg) { subTaskFailed(next, msg); });
|
||||||
|
// this should never happen but if it does, it's better to fail the task than get stuck
|
||||||
connect(next.get(), &Task::aborted, this, [this, next] { subTaskFailed(next, "Aborted"); });
|
connect(next.get(), &Task::aborted, this, [this, next] { subTaskFailed(next, "Aborted"); });
|
||||||
|
|
||||||
connect(next.get(), &Task::status, this, [this, next](QString msg) { subTaskStatus(next, msg); });
|
connect(next.get(), &Task::status, this, [this, next](QString msg) { subTaskStatus(next, msg); });
|
||||||
@ -140,55 +144,42 @@ void ConcurrentTask::startNext()
|
|||||||
connect(next.get(), &Task::progress, this, [this, next](qint64 current, qint64 total) { subTaskProgress(next, current, total); });
|
connect(next.get(), &Task::progress, this, [this, next](qint64 current, qint64 total) { subTaskProgress(next, current, total); });
|
||||||
|
|
||||||
m_doing.insert(next.get(), next);
|
m_doing.insert(next.get(), next);
|
||||||
qsizetype num_starts = qMin(m_queue.size(), m_total_max_size - m_doing.size());
|
|
||||||
auto task_progress = std::make_shared<TaskStepProgress>(next->getUid());
|
auto task_progress = std::make_shared<TaskStepProgress>(next->getUid());
|
||||||
m_task_progress.insert(next->getUid(), task_progress);
|
m_task_progress.insert(next->getUid(), task_progress);
|
||||||
|
|
||||||
updateState();
|
updateState();
|
||||||
updateStepProgress(*task_progress.get(), Operation::ADDED);
|
updateStepProgress(*task_progress.get(), Operation::ADDED);
|
||||||
|
|
||||||
QCoreApplication::processEvents();
|
|
||||||
|
|
||||||
QMetaObject::invokeMethod(next.get(), &Task::start, Qt::QueuedConnection);
|
QMetaObject::invokeMethod(next.get(), &Task::start, Qt::QueuedConnection);
|
||||||
|
}
|
||||||
|
|
||||||
// Allow going up the number of concurrent tasks in case of tasks being added in the middle of a running task.
|
void ConcurrentTask::subTaskFinished(Task::Ptr task, TaskStepState state)
|
||||||
for (int i = 0; i < num_starts; i++)
|
{
|
||||||
QMetaObject::invokeMethod(this, &ConcurrentTask::startNext, Qt::QueuedConnection);
|
m_done.insert(task.get(), task);
|
||||||
|
(state == TaskStepState::Succeeded ? m_succeeded : m_failed).insert(task.get(), task);
|
||||||
|
|
||||||
|
m_doing.remove(task.get());
|
||||||
|
|
||||||
|
auto task_progress = m_task_progress.value(task->getUid());
|
||||||
|
task_progress->state = state;
|
||||||
|
|
||||||
|
disconnect(task.get(), 0, this, 0);
|
||||||
|
|
||||||
|
emit stepProgress(*task_progress);
|
||||||
|
updateState();
|
||||||
|
updateStepProgress(*task_progress, Operation::REMOVED);
|
||||||
|
QMetaObject::invokeMethod(this, &ConcurrentTask::executeNextSubTask, Qt::QueuedConnection);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConcurrentTask::subTaskSucceeded(Task::Ptr task)
|
void ConcurrentTask::subTaskSucceeded(Task::Ptr task)
|
||||||
{
|
{
|
||||||
m_done.insert(task.get(), task);
|
subTaskFinished(task, TaskStepState::Succeeded);
|
||||||
m_succeeded.insert(task.get(), task);
|
|
||||||
|
|
||||||
m_doing.remove(task.get());
|
|
||||||
auto task_progress = m_task_progress.value(task->getUid());
|
|
||||||
task_progress->state = TaskStepState::Succeeded;
|
|
||||||
|
|
||||||
disconnect(task.get(), 0, this, 0);
|
|
||||||
|
|
||||||
emit stepProgress(*task_progress);
|
|
||||||
updateState();
|
|
||||||
updateStepProgress(*task_progress, Operation::REMOVED);
|
|
||||||
startNext();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConcurrentTask::subTaskFailed(Task::Ptr task, [[maybe_unused]] const QString& msg)
|
void ConcurrentTask::subTaskFailed(Task::Ptr task, [[maybe_unused]] const QString& msg)
|
||||||
{
|
{
|
||||||
m_done.insert(task.get(), task);
|
subTaskFinished(task, TaskStepState::Failed);
|
||||||
m_failed.insert(task.get(), task);
|
|
||||||
|
|
||||||
m_doing.remove(task.get());
|
|
||||||
|
|
||||||
auto task_progress = m_task_progress.value(task->getUid());
|
|
||||||
task_progress->state = TaskStepState::Failed;
|
|
||||||
|
|
||||||
disconnect(task.get(), 0, this, 0);
|
|
||||||
|
|
||||||
emit stepProgress(*task_progress);
|
|
||||||
updateState();
|
|
||||||
updateStepProgress(*task_progress, Operation::REMOVED);
|
|
||||||
startNext();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConcurrentTask::subTaskStatus(Task::Ptr task, const QString& msg)
|
void ConcurrentTask::subTaskStatus(Task::Ptr task, const QString& msg)
|
||||||
|
@ -72,10 +72,11 @@ class ConcurrentTask : public Task {
|
|||||||
protected slots:
|
protected slots:
|
||||||
void executeTask() override;
|
void executeTask() override;
|
||||||
|
|
||||||
virtual void startNext();
|
virtual void executeNextSubTask();
|
||||||
|
|
||||||
void subTaskSucceeded(Task::Ptr);
|
void subTaskSucceeded(Task::Ptr);
|
||||||
void subTaskFailed(Task::Ptr, const QString& msg);
|
virtual void subTaskFailed(Task::Ptr, const QString& msg);
|
||||||
|
void subTaskFinished(Task::Ptr, TaskStepState);
|
||||||
void subTaskStatus(Task::Ptr task, const QString& msg);
|
void subTaskStatus(Task::Ptr task, const QString& msg);
|
||||||
void subTaskDetails(Task::Ptr task, const QString& msg);
|
void subTaskDetails(Task::Ptr task, const QString& msg);
|
||||||
void subTaskProgress(Task::Ptr task, qint64 current, qint64 total);
|
void subTaskProgress(Task::Ptr task, qint64 current, qint64 total);
|
||||||
@ -90,6 +91,8 @@ class ConcurrentTask : public Task {
|
|||||||
|
|
||||||
virtual void updateState();
|
virtual void updateState();
|
||||||
|
|
||||||
|
void startSubTask(Task::Ptr task);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
QString m_name;
|
QString m_name;
|
||||||
QString m_step_status;
|
QString m_step_status;
|
||||||
@ -107,6 +110,4 @@ class ConcurrentTask : public Task {
|
|||||||
|
|
||||||
qint64 m_stepProgress = 0;
|
qint64 m_stepProgress = 0;
|
||||||
qint64 m_stepTotalProgress = 100;
|
qint64 m_stepTotalProgress = 100;
|
||||||
|
|
||||||
bool m_aborted = false;
|
|
||||||
};
|
};
|
||||||
|
@ -36,9 +36,9 @@
|
|||||||
|
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
|
|
||||||
MultipleOptionsTask::MultipleOptionsTask(QObject* parent, const QString& task_name) : SequentialTask(parent, task_name) {}
|
MultipleOptionsTask::MultipleOptionsTask(QObject* parent, const QString& task_name) : ConcurrentTask(parent, task_name, 1) {}
|
||||||
|
|
||||||
void MultipleOptionsTask::startNext()
|
void MultipleOptionsTask::executeNextSubTask()
|
||||||
{
|
{
|
||||||
if (m_done.size() != m_failed.size()) {
|
if (m_done.size() != m_failed.size()) {
|
||||||
emitSucceeded();
|
emitSucceeded();
|
||||||
@ -51,7 +51,7 @@ void MultipleOptionsTask::startNext()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ConcurrentTask::startNext();
|
ConcurrentTask::executeNextSubTask();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MultipleOptionsTask::updateState()
|
void MultipleOptionsTask::updateState()
|
||||||
|
@ -34,18 +34,18 @@
|
|||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "SequentialTask.h"
|
#include "ConcurrentTask.h"
|
||||||
|
|
||||||
/* This task type will attempt to do run each of it's subtasks in sequence,
|
/* This task type will attempt to do run each of it's subtasks in sequence,
|
||||||
* until one of them succeeds. When that happens, the remaining tasks will not run.
|
* until one of them succeeds. When that happens, the remaining tasks will not run.
|
||||||
* */
|
* */
|
||||||
class MultipleOptionsTask : public SequentialTask {
|
class MultipleOptionsTask : public ConcurrentTask {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
explicit MultipleOptionsTask(QObject* parent = nullptr, const QString& task_name = "");
|
explicit MultipleOptionsTask(QObject* parent = nullptr, const QString& task_name = "");
|
||||||
~MultipleOptionsTask() override = default;
|
~MultipleOptionsTask() override = default;
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void startNext() override;
|
void executeNextSubTask() override;
|
||||||
void updateState() override;
|
void updateState() override;
|
||||||
};
|
};
|
||||||
|
@ -36,18 +36,15 @@
|
|||||||
#include "SequentialTask.h"
|
#include "SequentialTask.h"
|
||||||
|
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
|
#include "tasks/ConcurrentTask.h"
|
||||||
|
|
||||||
SequentialTask::SequentialTask(QObject* parent, QString task_name) : ConcurrentTask(parent, task_name, 1) {}
|
SequentialTask::SequentialTask(QObject* parent, QString task_name) : ConcurrentTask(parent, task_name, 1) {}
|
||||||
|
|
||||||
void SequentialTask::startNext()
|
void SequentialTask::subTaskFailed(Task::Ptr task, const QString& msg)
|
||||||
{
|
{
|
||||||
if (m_failed.size() > 0) {
|
emitFailed(msg);
|
||||||
emitFailed(tr("One of the tasks failed!"));
|
qWarning() << msg;
|
||||||
qWarning() << m_failed.constBegin()->get()->failReason();
|
ConcurrentTask::subTaskFailed(task, msg);
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ConcurrentTask::startNext();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SequentialTask::updateState()
|
void SequentialTask::updateState()
|
||||||
|
@ -50,7 +50,9 @@ class SequentialTask : public ConcurrentTask {
|
|||||||
explicit SequentialTask(QObject* parent = nullptr, QString task_name = "");
|
explicit SequentialTask(QObject* parent = nullptr, QString task_name = "");
|
||||||
~SequentialTask() override = default;
|
~SequentialTask() override = default;
|
||||||
|
|
||||||
|
protected slots:
|
||||||
|
virtual void subTaskFailed(Task::Ptr, const QString& msg) override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void startNext() override;
|
|
||||||
void updateState() override;
|
void updateState() override;
|
||||||
};
|
};
|
||||||
|
@ -186,6 +186,7 @@ MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent), ui(new Ui::MainWi
|
|||||||
|
|
||||||
ui->instanceToolBar->addContextMenuAction(ui->newsToolBar->toggleViewAction());
|
ui->instanceToolBar->addContextMenuAction(ui->newsToolBar->toggleViewAction());
|
||||||
ui->instanceToolBar->addContextMenuAction(ui->instanceToolBar->toggleViewAction());
|
ui->instanceToolBar->addContextMenuAction(ui->instanceToolBar->toggleViewAction());
|
||||||
|
ui->instanceToolBar->addContextMenuAction(ui->actionToggleStatusBar);
|
||||||
ui->instanceToolBar->addContextMenuAction(ui->actionLockToolbars);
|
ui->instanceToolBar->addContextMenuAction(ui->actionLockToolbars);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -319,6 +320,14 @@ MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent), ui(new Ui::MainWi
|
|||||||
setCatBackground(cat_enable);
|
setCatBackground(cat_enable);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Togglable status bar
|
||||||
|
{
|
||||||
|
bool statusBarVisible = APPLICATION->settings()->get("StatusBarVisible").toBool();
|
||||||
|
ui->actionToggleStatusBar->setChecked(statusBarVisible);
|
||||||
|
connect(ui->actionToggleStatusBar, &QAction::toggled, this, &MainWindow::setStatusBarVisibility);
|
||||||
|
setStatusBarVisibility(statusBarVisible);
|
||||||
|
}
|
||||||
|
|
||||||
// Lock toolbars
|
// Lock toolbars
|
||||||
{
|
{
|
||||||
bool toolbarsLocked = APPLICATION->settings()->get("ToolbarsLocked").toBool();
|
bool toolbarsLocked = APPLICATION->settings()->get("ToolbarsLocked").toBool();
|
||||||
@ -451,10 +460,16 @@ QMenu* MainWindow::createPopupMenu()
|
|||||||
QMenu* filteredMenu = QMainWindow::createPopupMenu();
|
QMenu* filteredMenu = QMainWindow::createPopupMenu();
|
||||||
filteredMenu->removeAction(ui->mainToolBar->toggleViewAction());
|
filteredMenu->removeAction(ui->mainToolBar->toggleViewAction());
|
||||||
|
|
||||||
|
filteredMenu->addAction(ui->actionToggleStatusBar);
|
||||||
filteredMenu->addAction(ui->actionLockToolbars);
|
filteredMenu->addAction(ui->actionLockToolbars);
|
||||||
|
|
||||||
return filteredMenu;
|
return filteredMenu;
|
||||||
}
|
}
|
||||||
|
void MainWindow::setStatusBarVisibility(bool state)
|
||||||
|
{
|
||||||
|
statusBar()->setVisible(state);
|
||||||
|
APPLICATION->settings()->set("StatusBarVisible", state);
|
||||||
|
}
|
||||||
void MainWindow::lockToolbars(bool state)
|
void MainWindow::lockToolbars(bool state)
|
||||||
{
|
{
|
||||||
ui->mainToolBar->setMovable(!state);
|
ui->mainToolBar->setMovable(!state);
|
||||||
|
@ -205,6 +205,8 @@ class MainWindow : public QMainWindow {
|
|||||||
|
|
||||||
void globalSettingsClosed();
|
void globalSettingsClosed();
|
||||||
|
|
||||||
|
void setStatusBarVisibility(bool);
|
||||||
|
|
||||||
void lockToolbars(bool);
|
void lockToolbars(bool);
|
||||||
|
|
||||||
#ifndef Q_OS_MAC
|
#ifndef Q_OS_MAC
|
||||||
|
@ -176,6 +176,7 @@
|
|||||||
<addaction name="actionChangeTheme"/>
|
<addaction name="actionChangeTheme"/>
|
||||||
<addaction name="separator"/>
|
<addaction name="separator"/>
|
||||||
<addaction name="actionCAT"/>
|
<addaction name="actionCAT"/>
|
||||||
|
<addaction name="actionToggleStatusBar"/>
|
||||||
<addaction name="actionLockToolbars"/>
|
<addaction name="actionLockToolbars"/>
|
||||||
<addaction name="separator"/>
|
<addaction name="separator"/>
|
||||||
</widget>
|
</widget>
|
||||||
@ -257,6 +258,14 @@
|
|||||||
<string>It's a fluffy kitty :3</string>
|
<string>It's a fluffy kitty :3</string>
|
||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
|
<action name="actionToggleStatusBar">
|
||||||
|
<property name="checkable">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Status Bar</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
<action name="actionLockToolbars">
|
<action name="actionLockToolbars">
|
||||||
<property name="checkable">
|
<property name="checkable">
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
|
@ -174,8 +174,7 @@ AboutDialog::AboutDialog(QWidget* parent) : QDialog(parent), ui(new Ui::AboutDia
|
|||||||
QString urlText("<html><head/><body><p><a href=\"%1\">%1</a></p></body></html>");
|
QString urlText("<html><head/><body><p><a href=\"%1\">%1</a></p></body></html>");
|
||||||
ui->urlLabel->setText(urlText.arg(BuildConfig.LAUNCHER_GIT));
|
ui->urlLabel->setText(urlText.arg(BuildConfig.LAUNCHER_GIT));
|
||||||
|
|
||||||
QString copyText("© 2022-2023 %1");
|
ui->copyLabel->setText(BuildConfig.LAUNCHER_COPYRIGHT);
|
||||||
ui->copyLabel->setText(copyText.arg(BuildConfig.LAUNCHER_COPYRIGHT));
|
|
||||||
|
|
||||||
connect(ui->closeButton, SIGNAL(clicked()), SLOT(close()));
|
connect(ui->closeButton, SIGNAL(clicked()), SLOT(close()));
|
||||||
|
|
||||||
|
@ -15,7 +15,6 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <net/NetJob.h>
|
|
||||||
#include <QDialog>
|
#include <QDialog>
|
||||||
|
|
||||||
namespace Ui {
|
namespace Ui {
|
||||||
@ -31,7 +30,4 @@ class AboutDialog : public QDialog {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
Ui::AboutDialog* ui;
|
Ui::AboutDialog* ui;
|
||||||
|
|
||||||
NetJob::Ptr netJob;
|
|
||||||
QByteArray dataSink;
|
|
||||||
};
|
};
|
||||||
|
@ -334,6 +334,8 @@ auto ModUpdateDialog::ensureMetadata() -> bool
|
|||||||
connect(modrinth_task.get(), &EnsureMetadataTask::metadataFailed, [this, &should_try_others](Mod* candidate) {
|
connect(modrinth_task.get(), &EnsureMetadataTask::metadataFailed, [this, &should_try_others](Mod* candidate) {
|
||||||
onMetadataFailed(candidate, should_try_others.find(candidate->internal_id()).value(), ModPlatform::ResourceProvider::MODRINTH);
|
onMetadataFailed(candidate, should_try_others.find(candidate->internal_id()).value(), ModPlatform::ResourceProvider::MODRINTH);
|
||||||
});
|
});
|
||||||
|
connect(modrinth_task.get(), &EnsureMetadataTask::failed,
|
||||||
|
[this](QString reason) { CustomMessageBox::selectable(this, tr("Error"), reason, QMessageBox::Critical)->exec(); });
|
||||||
|
|
||||||
if (modrinth_task->getHashingTask())
|
if (modrinth_task->getHashingTask())
|
||||||
seq.addTask(modrinth_task->getHashingTask());
|
seq.addTask(modrinth_task->getHashingTask());
|
||||||
@ -347,6 +349,8 @@ auto ModUpdateDialog::ensureMetadata() -> bool
|
|||||||
connect(flame_task.get(), &EnsureMetadataTask::metadataFailed, [this, &should_try_others](Mod* candidate) {
|
connect(flame_task.get(), &EnsureMetadataTask::metadataFailed, [this, &should_try_others](Mod* candidate) {
|
||||||
onMetadataFailed(candidate, should_try_others.find(candidate->internal_id()).value(), ModPlatform::ResourceProvider::FLAME);
|
onMetadataFailed(candidate, should_try_others.find(candidate->internal_id()).value(), ModPlatform::ResourceProvider::FLAME);
|
||||||
});
|
});
|
||||||
|
connect(flame_task.get(), &EnsureMetadataTask::failed,
|
||||||
|
[this](QString reason) { CustomMessageBox::selectable(this, tr("Error"), reason, QMessageBox::Critical)->exec(); });
|
||||||
|
|
||||||
if (flame_task->getHashingTask())
|
if (flame_task->getHashingTask())
|
||||||
seq.addTask(flame_task->getHashingTask());
|
seq.addTask(flame_task->getHashingTask());
|
||||||
@ -400,6 +404,8 @@ void ModUpdateDialog::onMetadataFailed(Mod* mod, bool try_others, ModPlatform::R
|
|||||||
auto task = makeShared<EnsureMetadataTask>(mod, index_dir, next(first_choice));
|
auto task = makeShared<EnsureMetadataTask>(mod, index_dir, next(first_choice));
|
||||||
connect(task.get(), &EnsureMetadataTask::metadataReady, [this](Mod* candidate) { onMetadataEnsured(candidate); });
|
connect(task.get(), &EnsureMetadataTask::metadataReady, [this](Mod* candidate) { onMetadataEnsured(candidate); });
|
||||||
connect(task.get(), &EnsureMetadataTask::metadataFailed, [this](Mod* candidate) { onMetadataFailed(candidate, false); });
|
connect(task.get(), &EnsureMetadataTask::metadataFailed, [this](Mod* candidate) { onMetadataFailed(candidate, false); });
|
||||||
|
connect(task.get(), &EnsureMetadataTask::failed,
|
||||||
|
[this](QString reason) { CustomMessageBox::selectable(this, tr("Error"), reason, QMessageBox::Critical)->exec(); });
|
||||||
|
|
||||||
m_second_try_metadata->addTask(task);
|
m_second_try_metadata->addTask(task);
|
||||||
} else {
|
} else {
|
||||||
|
@ -458,6 +458,7 @@ void InstanceView::paintEvent([[maybe_unused]] QPaintEvent* event)
|
|||||||
QPainter painter(this->viewport());
|
QPainter painter(this->viewport());
|
||||||
|
|
||||||
if (m_catVisible) {
|
if (m_catVisible) {
|
||||||
|
painter.setOpacity(APPLICATION->settings()->get("CatOpacity").toFloat() / 100);
|
||||||
int widWidth = this->viewport()->width();
|
int widWidth = this->viewport()->width();
|
||||||
int widHeight = this->viewport()->height();
|
int widHeight = this->viewport()->height();
|
||||||
if (m_catPixmap.width() < widWidth)
|
if (m_catPixmap.width() < widWidth)
|
||||||
@ -468,6 +469,7 @@ void InstanceView::paintEvent([[maybe_unused]] QPaintEvent* event)
|
|||||||
QRect rectOfPixmap = pixmap.rect();
|
QRect rectOfPixmap = pixmap.rect();
|
||||||
rectOfPixmap.moveBottomRight(this->viewport()->rect().bottomRight());
|
rectOfPixmap.moveBottomRight(this->viewport()->rect().bottomRight());
|
||||||
painter.drawPixmap(rectOfPixmap.topLeft(), pixmap);
|
painter.drawPixmap(rectOfPixmap.topLeft(), pixmap);
|
||||||
|
painter.setOpacity(1.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
|
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
|
||||||
|
@ -158,13 +158,14 @@ void VisualGroup::drawHeader(QPainter* painter, const QStyleOptionViewItem& opti
|
|||||||
painter->setRenderHint(QPainter::Antialiasing);
|
painter->setRenderHint(QPainter::Antialiasing);
|
||||||
|
|
||||||
// sizes and offsets, to keep things consistent below
|
// sizes and offsets, to keep things consistent below
|
||||||
int arrowOffsetLeft = fontMetrics.height() / 2 + 7;
|
const int arrowOffsetLeft = fontMetrics.height() / 2 + 7;
|
||||||
int textOffsetLeft = arrowOffsetLeft * 2;
|
const int textOffsetLeft = arrowOffsetLeft * 2;
|
||||||
int arrowSize = 6;
|
const int centerHeight = optRect.top() + fontMetrics.height() / 2;
|
||||||
int centerHeight = optRect.top() + fontMetrics.height() / 2;
|
const QString& textToDraw = text.isEmpty() ? QObject::tr("Ungrouped") : text;
|
||||||
|
|
||||||
// BEGIN: arrow
|
// BEGIN: arrow
|
||||||
{
|
{
|
||||||
|
constexpr int arrowSize = 6;
|
||||||
QPolygon arrowPolygon;
|
QPolygon arrowPolygon;
|
||||||
if (collapsed) {
|
if (collapsed) {
|
||||||
arrowPolygon << QPoint(arrowOffsetLeft - arrowSize / 2, centerHeight - arrowSize)
|
arrowPolygon << QPoint(arrowOffsetLeft - arrowSize / 2, centerHeight - arrowSize)
|
||||||
@ -188,9 +189,26 @@ void VisualGroup::drawHeader(QPainter* painter, const QStyleOptionViewItem& opti
|
|||||||
textRect.setHeight(fontMetrics.height());
|
textRect.setHeight(fontMetrics.height());
|
||||||
textRect.setRight(textRect.right() - 7);
|
textRect.setRight(textRect.right() - 7);
|
||||||
|
|
||||||
painter->drawText(textRect, Qt::AlignLeft | Qt::AlignVCenter, !text.isEmpty() ? text : QObject::tr("Ungrouped"));
|
painter->drawText(textRect, Qt::AlignLeft | Qt::AlignVCenter, textToDraw);
|
||||||
}
|
}
|
||||||
// END: text
|
// END: text
|
||||||
|
|
||||||
|
// BEGIN: horizontal line
|
||||||
|
{
|
||||||
|
penColor.setAlphaF(0.05);
|
||||||
|
pen.setColor(penColor);
|
||||||
|
painter->setPen(pen);
|
||||||
|
// startPoint is left + arrow + text + space
|
||||||
|
const int startPoint =
|
||||||
|
optRect.left() + fontMetrics.height() + fontMetrics.size(Qt::AlignLeft | Qt::AlignVCenter, textToDraw).width() + 20;
|
||||||
|
painter->setRenderHint(QPainter::Antialiasing, false);
|
||||||
|
QPolygon polygon;
|
||||||
|
// for some reason the height (yPos) doesn't look centered, so we are adding 1 to the center height
|
||||||
|
const int lineHeight = centerHeight + 1;
|
||||||
|
polygon << QPoint(startPoint, lineHeight) << QPoint(optRect.right() - 3, lineHeight);
|
||||||
|
painter->drawPolyline(polygon);
|
||||||
|
}
|
||||||
|
// END: horizontal line
|
||||||
}
|
}
|
||||||
|
|
||||||
int VisualGroup::totalHeight() const
|
int VisualGroup::totalHeight() const
|
||||||
|
@ -221,6 +221,9 @@ void LauncherPage::applySettings()
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Cat
|
||||||
|
s->set("CatOpacity", ui->catOpacitySpinBox->value());
|
||||||
|
|
||||||
// Mods
|
// Mods
|
||||||
s->set("ModMetadataDisabled", ui->metadataDisableBtn->isChecked());
|
s->set("ModMetadataDisabled", ui->metadataDisableBtn->isChecked());
|
||||||
s->set("ModDependenciesDisabled", ui->dependenciesDisableBtn->isChecked());
|
s->set("ModDependenciesDisabled", ui->dependenciesDisableBtn->isChecked());
|
||||||
@ -276,6 +279,9 @@ void LauncherPage::loadSettings()
|
|||||||
ui->sortByNameBtn->setChecked(true);
|
ui->sortByNameBtn->setChecked(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Cat
|
||||||
|
ui->catOpacitySpinBox->setValue(s->get("CatOpacity").toInt());
|
||||||
|
|
||||||
// Mods
|
// Mods
|
||||||
ui->metadataDisableBtn->setChecked(s->get("ModMetadataDisabled").toBool());
|
ui->metadataDisableBtn->setChecked(s->get("ModMetadataDisabled").toBool());
|
||||||
ui->metadataWarningLabel->setHidden(!ui->metadataDisableBtn->isChecked());
|
ui->metadataWarningLabel->setHidden(!ui->metadataDisableBtn->isChecked());
|
||||||
|
@ -186,7 +186,7 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QCheckBox" name="dependenciesDisableBtn">
|
<widget class="QCheckBox" name="dependenciesDisableBtn">
|
||||||
<property name="toolTip">
|
<property name="toolTip">
|
||||||
<string>Disable the automatic detection, installation, and updating of mod dependencies.</string>
|
<string>Disable the automatic detection, installation, and updating of mod dependencies.</string>
|
||||||
@ -300,6 +300,54 @@
|
|||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QGroupBox" name="catBox">
|
||||||
|
<property name="title">
|
||||||
|
<string>Cat</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QGridLayout" name="gridLayout_5">
|
||||||
|
<item row="0" column="0">
|
||||||
|
<widget class="QLabel" name="catOpacityLabel">
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Set the cat's opacity. 0% is fully transparent and 100% is fully opaque.</string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Opacity</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="2">
|
||||||
|
<widget class="QSpinBox" name="catOpacitySpinBox">
|
||||||
|
<property name="specialValueText">
|
||||||
|
<string/>
|
||||||
|
</property>
|
||||||
|
<property name="suffix">
|
||||||
|
<string>%</string>
|
||||||
|
</property>
|
||||||
|
<property name="maximum">
|
||||||
|
<number>100</number>
|
||||||
|
</property>
|
||||||
|
<property name="value">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="1">
|
||||||
|
<spacer name="horizontalSpacer">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>40</width>
|
||||||
|
<height>20</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QGroupBox" name="toolsBox">
|
<widget class="QGroupBox" name="toolsBox">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
|
@ -206,7 +206,7 @@
|
|||||||
<item>
|
<item>
|
||||||
<widget class="QCheckBox" name="onlineFixes">
|
<widget class="QCheckBox" name="onlineFixes">
|
||||||
<property name="toolTip">
|
<property name="toolTip">
|
||||||
<string><html><head/><body><p>Emulates usages of old online services which are no longer operating.</p><p>This currently allows modern skins to be used.</p></body></html></string>
|
<string><html><head/><body><p>Emulates usages of old online services which are no longer operating.</p><p>Current fixes include: skin and online mode support.</p></body></html></string>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Enable online fixes (experimental)</string>
|
<string>Enable online fixes (experimental)</string>
|
||||||
|
@ -346,7 +346,7 @@ void InstanceSettingsPage::loadSettings()
|
|||||||
#ifdef Q_OS_LINUX
|
#ifdef Q_OS_LINUX
|
||||||
ui->lineEditOpenALPath->setPlaceholderText(APPLICATION->m_detectedOpenALPath);
|
ui->lineEditOpenALPath->setPlaceholderText(APPLICATION->m_detectedOpenALPath);
|
||||||
#else
|
#else
|
||||||
ui->lineEditGLFWPath->setPlaceholderText(tr("Path to %1 library file").arg(BuildConfig.OPENAL_LIBRARY_NAME));
|
ui->lineEditOpenALPath->setPlaceholderText(tr("Path to %1 library file").arg(BuildConfig.OPENAL_LIBRARY_NAME));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Performance
|
// Performance
|
||||||
|
@ -605,7 +605,7 @@
|
|||||||
<item>
|
<item>
|
||||||
<widget class="QCheckBox" name="onlineFixes">
|
<widget class="QCheckBox" name="onlineFixes">
|
||||||
<property name="toolTip">
|
<property name="toolTip">
|
||||||
<string><html><head/><body><p>Emulates usages of old online services which are no longer operating.</p><p>This currently allows modern skins to be used.</p></body></html></string>
|
<string><html><head/><body><p>Emulates usages of old online services which are no longer operating.</p><p>Current fixes include: skin and online mode support.</p></body></html></string>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Enable online fixes (experimental)</string>
|
<string>Enable online fixes (experimental)</string>
|
||||||
|
@ -131,6 +131,22 @@ ManagedPackPage::~ManagedPackPage()
|
|||||||
|
|
||||||
void ManagedPackPage::openedImpl()
|
void ManagedPackPage::openedImpl()
|
||||||
{
|
{
|
||||||
|
if (m_inst->getManagedPackID().isEmpty()) {
|
||||||
|
ui->packVersion->hide();
|
||||||
|
ui->packVersionLabel->hide();
|
||||||
|
ui->packOrigin->hide();
|
||||||
|
ui->packOriginLabel->hide();
|
||||||
|
ui->versionsComboBox->hide();
|
||||||
|
ui->updateButton->hide();
|
||||||
|
ui->updateToVersionLabel->hide();
|
||||||
|
ui->updateFromFileButton->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
|
||||||
|
|
||||||
|
ui->packName->setText(m_inst->name());
|
||||||
|
ui->changelogTextBrowser->setText(tr("This is a local modpack.\n"
|
||||||
|
"This can be updated only using a file in %1 format\n")
|
||||||
|
.arg(displayName()));
|
||||||
|
return;
|
||||||
|
}
|
||||||
ui->packName->setText(m_inst->getManagedPackName());
|
ui->packName->setText(m_inst->getManagedPackName());
|
||||||
ui->packVersion->setText(m_inst->getManagedPackVersionName());
|
ui->packVersion->setText(m_inst->getManagedPackVersionName());
|
||||||
ui->packOrigin->setText(tr("Website: <a href=%1>%2</a> | Pack ID: %3 | Version ID: %4")
|
ui->packOrigin->setText(tr("Website: <a href=%1>%2</a> | Pack ID: %3 | Version ID: %4")
|
||||||
@ -355,6 +371,8 @@ void ModrinthManagedPackPage::update()
|
|||||||
void ModrinthManagedPackPage::updateFromFile()
|
void ModrinthManagedPackPage::updateFromFile()
|
||||||
{
|
{
|
||||||
auto output = QFileDialog::getOpenFileUrl(this, tr("Choose update file"), QDir::homePath(), "Modrinth pack (*.mrpack *.zip)");
|
auto output = QFileDialog::getOpenFileUrl(this, tr("Choose update file"), QDir::homePath(), "Modrinth pack (*.mrpack *.zip)");
|
||||||
|
if (output.isEmpty())
|
||||||
|
return;
|
||||||
QMap<QString, QString> extra_info;
|
QMap<QString, QString> extra_info;
|
||||||
extra_info.insert("pack_id", m_inst->getManagedPackID());
|
extra_info.insert("pack_id", m_inst->getManagedPackID());
|
||||||
extra_info.insert("pack_version_id", QString());
|
extra_info.insert("pack_version_id", QString());
|
||||||
@ -472,7 +490,7 @@ void FlameManagedPackPage::parseManagedPack()
|
|||||||
QString FlameManagedPackPage::url() const
|
QString FlameManagedPackPage::url() const
|
||||||
{
|
{
|
||||||
// FIXME: We should display the websiteUrl field, but this requires doing the API request first :(
|
// FIXME: We should display the websiteUrl field, but this requires doing the API request first :(
|
||||||
return {};
|
return "https://www.curseforge.com/projects/" + m_inst->getManagedPackID();
|
||||||
}
|
}
|
||||||
|
|
||||||
void FlameManagedPackPage::suggestVersion()
|
void FlameManagedPackPage::suggestVersion()
|
||||||
@ -519,6 +537,8 @@ void FlameManagedPackPage::update()
|
|||||||
void FlameManagedPackPage::updateFromFile()
|
void FlameManagedPackPage::updateFromFile()
|
||||||
{
|
{
|
||||||
auto output = QFileDialog::getOpenFileUrl(this, tr("Choose update file"), QDir::homePath(), "CurseForge pack (*.zip)");
|
auto output = QFileDialog::getOpenFileUrl(this, tr("Choose update file"), QDir::homePath(), "CurseForge pack (*.zip)");
|
||||||
|
if (output.isEmpty())
|
||||||
|
return;
|
||||||
|
|
||||||
QMap<QString, QString> extra_info;
|
QMap<QString, QString> extra_info;
|
||||||
extra_info.insert("pack_id", m_inst->getManagedPackID());
|
extra_info.insert("pack_id", m_inst->getManagedPackID());
|
||||||
|
@ -242,7 +242,7 @@ void ModFolderPage::updateMods(bool includeDeps)
|
|||||||
if (m_instance != nullptr && m_instance->isRunning()) {
|
if (m_instance != nullptr && m_instance->isRunning()) {
|
||||||
auto response =
|
auto response =
|
||||||
CustomMessageBox::selectable(this, tr("Confirm Update"),
|
CustomMessageBox::selectable(this, tr("Confirm Update"),
|
||||||
tr("If you update mods while the game is running may cause mod duplication and game crashes.\n"
|
tr("Updating mods while the game is running may cause mod duplication and game crashes.\n"
|
||||||
"The old files may not be deleted as they are in use.\n"
|
"The old files may not be deleted as they are in use.\n"
|
||||||
"Are you sure you want to do this?"),
|
"Are you sure you want to do this?"),
|
||||||
QMessageBox::Warning, QMessageBox::Yes | QMessageBox::No, QMessageBox::No)
|
QMessageBox::Warning, QMessageBox::Yes | QMessageBox::No, QMessageBox::No)
|
||||||
|
@ -295,13 +295,6 @@ void VersionPage::on_actionRemove_triggered()
|
|||||||
m_container->refreshContainer();
|
m_container->refreshContainer();
|
||||||
}
|
}
|
||||||
|
|
||||||
void VersionPage::on_actionInstall_mods_triggered()
|
|
||||||
{
|
|
||||||
if (m_container) {
|
|
||||||
m_container->selectPage("mods");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void VersionPage::on_actionAdd_to_Minecraft_jar_triggered()
|
void VersionPage::on_actionAdd_to_Minecraft_jar_triggered()
|
||||||
{
|
{
|
||||||
auto list = GuiUtil::BrowseForFiles("jarmod", tr("Select jar mods"), tr("Minecraft.jar mods (*.zip *.jar)"),
|
auto list = GuiUtil::BrowseForFiles("jarmod", tr("Select jar mods"), tr("Minecraft.jar mods (*.zip *.jar)"),
|
||||||
|
@ -80,7 +80,6 @@ class VersionPage : public QMainWindow, public BasePage {
|
|||||||
void on_actionAdd_Agents_triggered();
|
void on_actionAdd_Agents_triggered();
|
||||||
void on_actionRevert_triggered();
|
void on_actionRevert_triggered();
|
||||||
void on_actionEdit_triggered();
|
void on_actionEdit_triggered();
|
||||||
void on_actionInstall_mods_triggered();
|
|
||||||
void on_actionCustomize_triggered();
|
void on_actionCustomize_triggered();
|
||||||
void on_actionDownload_All_triggered();
|
void on_actionDownload_All_triggered();
|
||||||
|
|
||||||
|
@ -207,6 +207,10 @@ void ResourceModel::loadEntry(QModelIndex& entry)
|
|||||||
return;
|
return;
|
||||||
versionRequestSucceeded(doc, pack, entry);
|
versionRequestSucceeded(doc, pack, entry);
|
||||||
};
|
};
|
||||||
|
if (!callbacks.on_fail)
|
||||||
|
callbacks.on_fail = [](QString reason, int) {
|
||||||
|
QMessageBox::critical(nullptr, tr("Error"), tr("A network error occurred. Could not load project versions:%1").arg(reason));
|
||||||
|
};
|
||||||
|
|
||||||
if (auto job = m_api->getProjectVersions(std::move(args), std::move(callbacks)); job)
|
if (auto job = m_api->getProjectVersions(std::move(args), std::move(callbacks)); job)
|
||||||
runInfoJob(job);
|
runInfoJob(job);
|
||||||
@ -230,6 +234,12 @@ void ResourceModel::loadEntry(QModelIndex& entry)
|
|||||||
return;
|
return;
|
||||||
QMessageBox::critical(nullptr, tr("Error"), tr("A network error occurred. Could not load project info:%1").arg(reason));
|
QMessageBox::critical(nullptr, tr("Error"), tr("A network error occurred. Could not load project info:%1").arg(reason));
|
||||||
};
|
};
|
||||||
|
if (!callbacks.on_abort)
|
||||||
|
callbacks.on_abort = [this] {
|
||||||
|
if (!s_running_models.constFind(this).value())
|
||||||
|
return;
|
||||||
|
qCritical() << tr("The request was aborted for an unknown reason");
|
||||||
|
};
|
||||||
|
|
||||||
if (auto job = m_api->getProjectInfo(std::move(args), std::move(callbacks)); job)
|
if (auto job = m_api->getProjectInfo(std::move(args), std::move(callbacks)); job)
|
||||||
runInfoJob(job);
|
runInfoJob(job);
|
||||||
|
@ -200,6 +200,11 @@ void ResourcePage::updateUi()
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (current_pack->extraDataLoaded) {
|
if (current_pack->extraDataLoaded) {
|
||||||
|
if (current_pack->extraData.status == "archived") {
|
||||||
|
text += "<br><br>" + tr("<b>This project has been archived. It will not receive any further updates unless the author decides "
|
||||||
|
"to unarchive the project.</b>");
|
||||||
|
}
|
||||||
|
|
||||||
if (!current_pack->extraData.donate.isEmpty()) {
|
if (!current_pack->extraData.donate.isEmpty()) {
|
||||||
text += "<br><br>" + tr("Donate information: ");
|
text += "<br><br>" + tr("Donate information: ");
|
||||||
auto donateToStr = [](ModPlatform::DonationData& donate) -> QString {
|
auto donateToStr = [](ModPlatform::DonationData& donate) -> QString {
|
||||||
@ -404,9 +409,9 @@ void ResourcePage::openUrl(const QUrl& url)
|
|||||||
auto jump = [url, slug, model, view] {
|
auto jump = [url, slug, model, view] {
|
||||||
for (int row = 0; row < model->rowCount({}); row++) {
|
for (int row = 0; row < model->rowCount({}); row++) {
|
||||||
const QModelIndex index = model->index(row);
|
const QModelIndex index = model->index(row);
|
||||||
const auto pack = model->data(index, Qt::UserRole).value<ModPlatform::IndexedPack>();
|
const auto pack = model->data(index, Qt::UserRole).value<ModPlatform::IndexedPack::Ptr>();
|
||||||
|
|
||||||
if (pack.slug == slug) {
|
if (pack->slug == slug) {
|
||||||
view->setCurrentIndex(index);
|
view->setCurrentIndex(index);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -170,6 +170,10 @@ void ListModel::performPaginatedSearch()
|
|||||||
|
|
||||||
callbacks.on_fail = [this](QString reason) { searchRequestFailed(reason); };
|
callbacks.on_fail = [this](QString reason) { searchRequestFailed(reason); };
|
||||||
callbacks.on_succeed = [this](auto& doc, auto& pack) { searchRequestForOneSucceeded(doc); };
|
callbacks.on_succeed = [this](auto& doc, auto& pack) { searchRequestForOneSucceeded(doc); };
|
||||||
|
callbacks.on_abort = [this] {
|
||||||
|
qCritical() << "Search task aborted by an unknown reason!";
|
||||||
|
searchRequestFailed("Abborted");
|
||||||
|
};
|
||||||
static const FlameAPI api;
|
static const FlameAPI api;
|
||||||
if (auto job = api.getProjectInfo({ projectId }, std::move(callbacks)); job) {
|
if (auto job = api.getProjectInfo({ projectId }, std::move(callbacks)); job) {
|
||||||
jobPtr = job;
|
jobPtr = job;
|
||||||
|
@ -34,6 +34,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "FlamePage.h"
|
#include "FlamePage.h"
|
||||||
|
#include "ui/dialogs/CustomMessageBox.h"
|
||||||
#include "ui_FlamePage.h"
|
#include "ui_FlamePage.h"
|
||||||
|
|
||||||
#include <QKeyEvent>
|
#include <QKeyEvent>
|
||||||
@ -193,6 +194,8 @@ void FlamePage::onSelectionChanged(QModelIndex curr, [[maybe_unused]] QModelInde
|
|||||||
suggestCurrent();
|
suggestCurrent();
|
||||||
});
|
});
|
||||||
QObject::connect(netJob, &NetJob::finished, this, [response, netJob] { netJob->deleteLater(); });
|
QObject::connect(netJob, &NetJob::finished, this, [response, netJob] { netJob->deleteLater(); });
|
||||||
|
connect(netJob, &NetJob::failed,
|
||||||
|
[this](QString reason) { CustomMessageBox::selectable(this, tr("Error"), reason, QMessageBox::Critical)->exec(); });
|
||||||
netJob->start();
|
netJob->start();
|
||||||
} else {
|
} else {
|
||||||
for (auto version : current.versions) {
|
for (auto version : current.versions) {
|
||||||
|
@ -140,6 +140,10 @@ void ModpackListModel::performPaginatedSearch()
|
|||||||
|
|
||||||
callbacks.on_fail = [this](QString reason) { searchRequestFailed(reason); };
|
callbacks.on_fail = [this](QString reason) { searchRequestFailed(reason); };
|
||||||
callbacks.on_succeed = [this](auto& doc, auto& pack) { searchRequestForOneSucceeded(doc); };
|
callbacks.on_succeed = [this](auto& doc, auto& pack) { searchRequestForOneSucceeded(doc); };
|
||||||
|
callbacks.on_abort = [this] {
|
||||||
|
qCritical() << "Search task aborted by an unknown reason!";
|
||||||
|
searchRequestFailed("Aborted");
|
||||||
|
};
|
||||||
static const ModrinthAPI api;
|
static const ModrinthAPI api;
|
||||||
if (auto job = api.getProjectInfo({ projectId }, std::move(callbacks)); job) {
|
if (auto job = api.getProjectInfo({ projectId }, std::move(callbacks)); job) {
|
||||||
jobPtr = job;
|
jobPtr = job;
|
||||||
|
@ -35,6 +35,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "ModrinthPage.h"
|
#include "ModrinthPage.h"
|
||||||
|
#include "ui/dialogs/CustomMessageBox.h"
|
||||||
#include "ui_ModrinthPage.h"
|
#include "ui_ModrinthPage.h"
|
||||||
|
|
||||||
#include "ModrinthModel.h"
|
#include "ModrinthModel.h"
|
||||||
@ -182,6 +183,8 @@ void ModrinthPage::onSelectionChanged(QModelIndex curr, [[maybe_unused]] QModelI
|
|||||||
suggestCurrent();
|
suggestCurrent();
|
||||||
});
|
});
|
||||||
QObject::connect(netJob, &NetJob::finished, this, [response, netJob] { netJob->deleteLater(); });
|
QObject::connect(netJob, &NetJob::finished, this, [response, netJob] { netJob->deleteLater(); });
|
||||||
|
connect(netJob, &NetJob::failed,
|
||||||
|
[this](QString reason) { CustomMessageBox::selectable(this, tr("Error"), reason, QMessageBox::Critical)->exec(); });
|
||||||
netJob->start();
|
netJob->start();
|
||||||
} else
|
} else
|
||||||
updateUI();
|
updateUI();
|
||||||
@ -235,6 +238,8 @@ void ModrinthPage::onSelectionChanged(QModelIndex curr, [[maybe_unused]] QModelI
|
|||||||
suggestCurrent();
|
suggestCurrent();
|
||||||
});
|
});
|
||||||
QObject::connect(netJob, &NetJob::finished, this, [response, netJob] { netJob->deleteLater(); });
|
QObject::connect(netJob, &NetJob::finished, this, [response, netJob] { netJob->deleteLater(); });
|
||||||
|
connect(netJob, &NetJob::failed,
|
||||||
|
[this](QString reason) { CustomMessageBox::selectable(this, tr("Error"), reason, QMessageBox::Critical)->exec(); });
|
||||||
netJob->start();
|
netJob->start();
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
@ -262,6 +267,11 @@ void ModrinthPage::updateUI()
|
|||||||
text += "<br>" + tr(" by ") + QString("<a href=%1>%2</a>").arg(std::get<1>(current.author).toString(), std::get<0>(current.author));
|
text += "<br>" + tr(" by ") + QString("<a href=%1>%2</a>").arg(std::get<1>(current.author).toString(), std::get<0>(current.author));
|
||||||
|
|
||||||
if (current.extraInfoLoaded) {
|
if (current.extraInfoLoaded) {
|
||||||
|
if (current.extra.status == "archived") {
|
||||||
|
text += "<br><br>" + tr("<b>This project has been archived. It will not receive any further updates unless the author decides "
|
||||||
|
"to unarchive the project.</b>");
|
||||||
|
}
|
||||||
|
|
||||||
if (!current.extra.donate.isEmpty()) {
|
if (!current.extra.donate.isEmpty()) {
|
||||||
text += "<br><br>" + tr("Donate information: ");
|
text += "<br><br>" + tr("Donate information: ");
|
||||||
auto donateToStr = [](Modrinth::DonationData& donate) -> QString {
|
auto donateToStr = [](Modrinth::DonationData& donate) -> QString {
|
||||||
|
@ -34,6 +34,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "TechnicPage.h"
|
#include "TechnicPage.h"
|
||||||
|
#include "ui/dialogs/CustomMessageBox.h"
|
||||||
#include "ui/widgets/ProjectItem.h"
|
#include "ui/widgets/ProjectItem.h"
|
||||||
#include "ui_TechnicPage.h"
|
#include "ui_TechnicPage.h"
|
||||||
|
|
||||||
@ -208,6 +209,8 @@ void TechnicPage::suggestCurrent()
|
|||||||
|
|
||||||
metadataLoaded();
|
metadataLoaded();
|
||||||
});
|
});
|
||||||
|
connect(jobPtr.get(), &NetJob::failed,
|
||||||
|
[this](QString reason) { CustomMessageBox::selectable(this, tr("Error"), reason, QMessageBox::Critical)->exec(); });
|
||||||
|
|
||||||
jobPtr = netJob;
|
jobPtr = netJob;
|
||||||
jobPtr->start();
|
jobPtr->start();
|
||||||
@ -258,6 +261,8 @@ void TechnicPage::metadataLoaded()
|
|||||||
netJob->addNetAction(Net::ApiDownload::makeByteArray(QUrl(url), response));
|
netJob->addNetAction(Net::ApiDownload::makeByteArray(QUrl(url), response));
|
||||||
|
|
||||||
QObject::connect(netJob.get(), &NetJob::succeeded, this, &TechnicPage::onSolderLoaded);
|
QObject::connect(netJob.get(), &NetJob::succeeded, this, &TechnicPage::onSolderLoaded);
|
||||||
|
connect(jobPtr.get(), &NetJob::failed,
|
||||||
|
[this](QString reason) { CustomMessageBox::selectable(this, tr("Error"), reason, QMessageBox::Critical)->exec(); });
|
||||||
|
|
||||||
jobPtr = netJob;
|
jobPtr = netJob;
|
||||||
jobPtr->start();
|
jobPtr->start();
|
||||||
|
@ -88,7 +88,7 @@ void ProjectItemDelegate::paint(QPainter* painter, const QStyleOptionViewItem& o
|
|||||||
}
|
}
|
||||||
|
|
||||||
{ // Description painting
|
{ // Description painting
|
||||||
auto description = index.data(UserDataTypes::DESCRIPTION).toString();
|
auto description = index.data(UserDataTypes::DESCRIPTION).toString().simplified();
|
||||||
|
|
||||||
QTextLayout text_layout(description, opt.font);
|
QTextLayout text_layout(description, opt.font);
|
||||||
|
|
||||||
|
@ -102,14 +102,7 @@ void VariableSizedImageObject::loadImage(QTextDocument* doc, const QUrl& source,
|
|||||||
|
|
||||||
auto full_entry_path = entry->getFullPath();
|
auto full_entry_path = entry->getFullPath();
|
||||||
auto source_url = source;
|
auto source_url = source;
|
||||||
connect(job, &NetJob::succeeded, this, [this, doc, full_entry_path, source_url, posInDocument] {
|
auto loadImage = [this, doc, full_entry_path, source_url, posInDocument](const QImage& image) {
|
||||||
qDebug() << "Loaded resource at" << full_entry_path;
|
|
||||||
|
|
||||||
// If we flushed, don't proceed.
|
|
||||||
if (!m_fetching_images.contains(source_url))
|
|
||||||
return;
|
|
||||||
|
|
||||||
QImage image(full_entry_path);
|
|
||||||
doc->addResource(QTextDocument::ImageResource, source_url, image);
|
doc->addResource(QTextDocument::ImageResource, source_url, image);
|
||||||
|
|
||||||
parseImage(doc, image, posInDocument);
|
parseImage(doc, image, posInDocument);
|
||||||
@ -121,6 +114,23 @@ void VariableSizedImageObject::loadImage(QTextDocument* doc, const QUrl& source,
|
|||||||
doc->setPageSize(size);
|
doc->setPageSize(size);
|
||||||
|
|
||||||
m_fetching_images.remove(source_url);
|
m_fetching_images.remove(source_url);
|
||||||
|
};
|
||||||
|
connect(job, &NetJob::succeeded, this, [this, full_entry_path, source_url, loadImage] {
|
||||||
|
qDebug() << "Loaded resource at:" << full_entry_path;
|
||||||
|
// If we flushed, don't proceed.
|
||||||
|
if (!m_fetching_images.contains(source_url))
|
||||||
|
return;
|
||||||
|
|
||||||
|
QImage image(full_entry_path);
|
||||||
|
loadImage(image);
|
||||||
|
});
|
||||||
|
connect(job, &NetJob::failed, this, [this, full_entry_path, source_url, loadImage](QString reason) {
|
||||||
|
qWarning() << "Failed resource at:" << full_entry_path << " because:" << reason;
|
||||||
|
// If we flushed, don't proceed.
|
||||||
|
if (!m_fetching_images.contains(source_url))
|
||||||
|
return;
|
||||||
|
|
||||||
|
loadImage(QImage());
|
||||||
});
|
});
|
||||||
connect(job, &NetJob::finished, job, &NetJob::deleteLater);
|
connect(job, &NetJob::finished, job, &NetJob::deleteLater);
|
||||||
|
|
||||||
|
@ -436,8 +436,8 @@ PrismUpdaterApp::PrismUpdaterApp(int& argc, char** argv) : QApplication(argc, ar
|
|||||||
}
|
}
|
||||||
|
|
||||||
{ // log debug program info
|
{ // log debug program info
|
||||||
qDebug() << qPrintable(BuildConfig.LAUNCHER_DISPLAYNAME) << "Updater"
|
qDebug() << qPrintable(BuildConfig.LAUNCHER_DISPLAYNAME + " Updater, " +
|
||||||
<< ", (c) 2022-2023 " << qPrintable(QString(BuildConfig.LAUNCHER_COPYRIGHT).replace("\n", ", "));
|
QString(BuildConfig.LAUNCHER_COPYRIGHT).replace("\n", ", "));
|
||||||
qDebug() << "Version : " << BuildConfig.printableVersionString();
|
qDebug() << "Version : " << BuildConfig.printableVersionString();
|
||||||
qDebug() << "Git commit : " << BuildConfig.GIT_COMMIT;
|
qDebug() << "Git commit : " << BuildConfig.GIT_COMMIT;
|
||||||
qDebug() << "Git refspec : " << BuildConfig.GIT_REFSPEC;
|
qDebug() << "Git refspec : " << BuildConfig.GIT_REFSPEC;
|
||||||
|
@ -25,13 +25,14 @@ set(LEGACY_SRC
|
|||||||
legacy/org/prismlauncher/legacy/LegacyLauncher.java
|
legacy/org/prismlauncher/legacy/LegacyLauncher.java
|
||||||
legacy/org/prismlauncher/legacy/fix/online/Handler.java
|
legacy/org/prismlauncher/legacy/fix/online/Handler.java
|
||||||
legacy/org/prismlauncher/legacy/fix/online/OnlineFixes.java
|
legacy/org/prismlauncher/legacy/fix/online/OnlineFixes.java
|
||||||
|
legacy/org/prismlauncher/legacy/fix/online/OnlineModeFix.java
|
||||||
legacy/org/prismlauncher/legacy/fix/online/SkinFix.java
|
legacy/org/prismlauncher/legacy/fix/online/SkinFix.java
|
||||||
legacy/org/prismlauncher/legacy/utils/Base64.java
|
legacy/org/prismlauncher/legacy/utils/Base64.java
|
||||||
legacy/org/prismlauncher/legacy/utils/api/MojangApi.java
|
legacy/org/prismlauncher/legacy/utils/api/MojangApi.java
|
||||||
legacy/org/prismlauncher/legacy/utils/api/Texture.java
|
legacy/org/prismlauncher/legacy/utils/api/Texture.java
|
||||||
legacy/org/prismlauncher/legacy/utils/json/JsonParseException.java
|
legacy/org/prismlauncher/legacy/utils/json/JsonParseException.java
|
||||||
legacy/org/prismlauncher/legacy/utils/json/JsonParser.java
|
legacy/org/prismlauncher/legacy/utils/json/JsonParser.java
|
||||||
legacy/org/prismlauncher/legacy/utils/url/CustomUrlConnection.java
|
legacy/org/prismlauncher/legacy/utils/url/ByteArrayUrlConnection.java
|
||||||
legacy/org/prismlauncher/legacy/utils/url/UrlUtils.java
|
legacy/org/prismlauncher/legacy/utils/url/UrlUtils.java
|
||||||
legacy/net/minecraft/Launcher.java
|
legacy/net/minecraft/Launcher.java
|
||||||
legacy/org/prismlauncher/legacy/LegacyProxy.java
|
legacy/org/prismlauncher/legacy/LegacyProxy.java
|
||||||
|
@ -53,11 +53,16 @@ final class Handler extends URLStreamHandler {
|
|||||||
protected URLConnection openConnection(URL address, Proxy proxy) throws IOException {
|
protected URLConnection openConnection(URL address, Proxy proxy) throws IOException {
|
||||||
URLConnection result;
|
URLConnection result;
|
||||||
|
|
||||||
// try skin fix
|
// try various fixes...
|
||||||
result = SkinFix.openConnection(address, proxy);
|
result = SkinFix.openConnection(address, proxy);
|
||||||
if (result != null)
|
if (result != null)
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
|
result = OnlineModeFix.openConnection(address, proxy);
|
||||||
|
if (result != null)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
// ...then give up and make the request directly
|
||||||
return UrlUtils.openConnection(address, proxy);
|
return UrlUtils.openConnection(address, proxy);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -46,6 +46,8 @@ import java.net.URLStreamHandlerFactory;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Fixes skins by redirecting to other URLs.
|
* Fixes skins by redirecting to other URLs.
|
||||||
|
* Thanks to MineOnline for the implementation from which this was inspired!
|
||||||
|
* See https://github.com/ahnewark/MineOnline/tree/main/src/main/java/gg/codie/mineonline/protocol.
|
||||||
*
|
*
|
||||||
* @see {@link Handler}
|
* @see {@link Handler}
|
||||||
* @see {@link UrlUtils}
|
* @see {@link UrlUtils}
|
||||||
|
@ -0,0 +1,66 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-3.0-only
|
||||||
|
/*
|
||||||
|
* Prism Launcher - Minecraft Launcher
|
||||||
|
* Copyright (C) 2023 TheKodeToad <TheKodeToad@proton.me>
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* Linking this library statically or dynamically with other modules is
|
||||||
|
* making a combined work based on this library. Thus, the terms and
|
||||||
|
* conditions of the GNU General Public License cover the whole
|
||||||
|
* combination.
|
||||||
|
*
|
||||||
|
* As a special exception, the copyright holders of this library give
|
||||||
|
* you permission to link this library with independent modules to
|
||||||
|
* produce an executable, regardless of the license terms of these
|
||||||
|
* independent modules, and to copy and distribute the resulting
|
||||||
|
* executable under terms of your choice, provided that you also meet,
|
||||||
|
* for each linked independent module, the terms and conditions of the
|
||||||
|
* license of that module. An independent module is a module which is
|
||||||
|
* not derived from or based on this library. If you modify this
|
||||||
|
* library, you may extend this exception to your version of the
|
||||||
|
* library, but you are not obliged to do so. If you do not wish to do
|
||||||
|
* so, delete this exception statement from your version.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.prismlauncher.legacy.fix.online;
|
||||||
|
|
||||||
|
import org.prismlauncher.legacy.utils.url.UrlUtils;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.MalformedURLException;
|
||||||
|
import java.net.Proxy;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.net.URLConnection;
|
||||||
|
|
||||||
|
public final class OnlineModeFix {
|
||||||
|
public static URLConnection openConnection(URL address, Proxy proxy) throws IOException {
|
||||||
|
// we start with "http://www.minecraft.net/game/joinserver.jsp?user=..."
|
||||||
|
if (!(address.getHost().equals("www.minecraft.net") && address.getPath().equals("/game/joinserver.jsp")))
|
||||||
|
return null;
|
||||||
|
|
||||||
|
// change it to "https://session.minecraft.net/game/joinserver.jsp?user=..."
|
||||||
|
// this seems to be the modern version of the same endpoint...
|
||||||
|
// maybe Mojang planned to patch old versions of the game to use it
|
||||||
|
// if it ever disappears this should be changed to use sessionserver.mojang.com/session/minecraft/join
|
||||||
|
// which of course has a different usage requiring JSON serialisation...
|
||||||
|
URL url;
|
||||||
|
try {
|
||||||
|
url = new URL("https", "session.minecraft.net", address.getPort(), address.getFile());
|
||||||
|
} catch (MalformedURLException e) {
|
||||||
|
throw new AssertionError("url should be valid", e);
|
||||||
|
}
|
||||||
|
|
||||||
|
return UrlUtils.openConnection(url, proxy);
|
||||||
|
}
|
||||||
|
}
|
@ -54,7 +54,7 @@ package org.prismlauncher.legacy.fix.online;
|
|||||||
|
|
||||||
import org.prismlauncher.legacy.utils.api.MojangApi;
|
import org.prismlauncher.legacy.utils.api.MojangApi;
|
||||||
import org.prismlauncher.legacy.utils.api.Texture;
|
import org.prismlauncher.legacy.utils.api.Texture;
|
||||||
import org.prismlauncher.legacy.utils.url.CustomUrlConnection;
|
import org.prismlauncher.legacy.utils.url.ByteArrayUrlConnection;
|
||||||
import org.prismlauncher.legacy.utils.url.UrlUtils;
|
import org.prismlauncher.legacy.utils.url.UrlUtils;
|
||||||
|
|
||||||
import java.awt.AlphaComposite;
|
import java.awt.AlphaComposite;
|
||||||
@ -97,9 +97,9 @@ final class SkinFix {
|
|||||||
|
|
||||||
URLConnection connection = UrlUtils.openConnection(texture.getUrl(), proxy);
|
URLConnection connection = UrlUtils.openConnection(texture.getUrl(), proxy);
|
||||||
try (InputStream in = connection.getInputStream()) {
|
try (InputStream in = connection.getInputStream()) {
|
||||||
// thank you craftycodie!
|
// thank you ahnewark!
|
||||||
// this is heavily based on
|
// this is heavily based on
|
||||||
// https://github.com/craftycodie/MineOnline/blob/4f4f86f9d051e0a6fd7ff0b95b2a05f7437683d7/src/main/java/gg/codie/mineonline/gui/textures/TextureHelper.java#L17
|
// https://github.com/ahnewark/MineOnline/blob/4f4f86f9d051e0a6fd7ff0b95b2a05f7437683d7/src/main/java/gg/codie/mineonline/gui/textures/TextureHelper.java#L17
|
||||||
BufferedImage image = ImageIO.read(in);
|
BufferedImage image = ImageIO.read(in);
|
||||||
Graphics2D graphics = image.createGraphics();
|
Graphics2D graphics = image.createGraphics();
|
||||||
graphics.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER));
|
graphics.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER));
|
||||||
@ -131,7 +131,7 @@ final class SkinFix {
|
|||||||
image = image.getSubimage(0, 0, 64, 32);
|
image = image.getSubimage(0, 0, 64, 32);
|
||||||
ImageIO.write(image, "png", out);
|
ImageIO.write(image, "png", out);
|
||||||
|
|
||||||
return new CustomUrlConnection(out.toByteArray());
|
return new ByteArrayUrlConnection(out.toByteArray());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,16 +40,12 @@ import java.io.IOException;
|
|||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.net.HttpURLConnection;
|
import java.net.HttpURLConnection;
|
||||||
|
|
||||||
public final class CustomUrlConnection extends HttpURLConnection {
|
public final class ByteArrayUrlConnection extends HttpURLConnection {
|
||||||
private final InputStream in;
|
private final InputStream in;
|
||||||
|
|
||||||
public CustomUrlConnection(byte[] data) {
|
public ByteArrayUrlConnection(byte[] data) {
|
||||||
this(new ByteArrayInputStream(data));
|
|
||||||
}
|
|
||||||
|
|
||||||
public CustomUrlConnection(InputStream in) {
|
|
||||||
super(null);
|
super(null);
|
||||||
this.in = in;
|
this.in = new ByteArrayInputStream(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -58,12 +54,7 @@ public final class CustomUrlConnection extends HttpURLConnection {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void disconnect() {
|
public void disconnect() {}
|
||||||
try {
|
|
||||||
in.close();
|
|
||||||
} catch (IOException e) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public InputStream getInputStream() throws IOException {
|
public InputStream getInputStream() throws IOException {
|
@ -101,7 +101,7 @@ public final class UrlUtils {
|
|||||||
} catch (IOException | Error | RuntimeException e) {
|
} catch (IOException | Error | RuntimeException e) {
|
||||||
throw e; // rethrow if possible
|
throw e; // rethrow if possible
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
throw new AssertionError(e); // oh dear! this isn't meant to happen
|
throw new AssertionError("openConnection should not throw", e); // oh dear! this isn't meant to happen
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -81,10 +81,9 @@ public final class EntryPoint {
|
|||||||
PreLaunchAction action = PreLaunchAction.PROCEED;
|
PreLaunchAction action = PreLaunchAction.PROCEED;
|
||||||
|
|
||||||
try (BufferedReader reader = new BufferedReader(new InputStreamReader(System.in, StandardCharsets.UTF_8))) {
|
try (BufferedReader reader = new BufferedReader(new InputStreamReader(System.in, StandardCharsets.UTF_8))) {
|
||||||
String line;
|
|
||||||
|
|
||||||
while (action == PreLaunchAction.PROCEED) {
|
while (action == PreLaunchAction.PROCEED) {
|
||||||
if ((line = reader.readLine()) != null)
|
String line = reader.readLine();
|
||||||
|
if (line != null)
|
||||||
action = parseLine(line, params);
|
action = parseLine(line, params);
|
||||||
else
|
else
|
||||||
action = PreLaunchAction.ABORT;
|
action = PreLaunchAction.ABORT;
|
||||||
@ -105,7 +104,7 @@ public final class EntryPoint {
|
|||||||
return ExitCode.ABORT;
|
return ExitCode.ABORT;
|
||||||
}
|
}
|
||||||
|
|
||||||
setProperties(params);
|
SystemProperties.apply(params);
|
||||||
|
|
||||||
String launcherType = params.getString("launcher");
|
String launcherType = params.getString("launcher");
|
||||||
|
|
||||||
@ -141,43 +140,10 @@ public final class EntryPoint {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void setProperties(Parameters params) {
|
|
||||||
String launcherBrand = params.getString("launcherBrand", null);
|
|
||||||
String launcherVersion = params.getString("launcherVersion", null);
|
|
||||||
String name = params.getString("instanceName", null);
|
|
||||||
String iconId = params.getString("instanceIconKey", null);
|
|
||||||
String iconPath = params.getString("instanceIconPath", null);
|
|
||||||
String windowTitle = params.getString("windowTitle", null);
|
|
||||||
String windowDimensions = params.getString("windowParams", null);
|
|
||||||
|
|
||||||
if (launcherBrand != null)
|
|
||||||
System.setProperty("minecraft.launcher.brand", launcherBrand);
|
|
||||||
if (launcherVersion != null)
|
|
||||||
System.setProperty("minecraft.launcher.version", launcherVersion);
|
|
||||||
|
|
||||||
// set useful properties for mods
|
|
||||||
if (name != null)
|
|
||||||
System.setProperty("org.prismlauncher.instance.name", name);
|
|
||||||
if (iconId != null)
|
|
||||||
System.setProperty("org.prismlauncher.instance.icon.id", iconId);
|
|
||||||
if (iconPath != null)
|
|
||||||
System.setProperty("org.prismlauncher.instance.icon.path", iconPath);
|
|
||||||
if (windowTitle != null)
|
|
||||||
System.setProperty("org.prismlauncher.window.title", windowTitle);
|
|
||||||
if (windowDimensions != null)
|
|
||||||
System.setProperty("org.prismlauncher.window.dimensions", windowDimensions);
|
|
||||||
|
|
||||||
// set multimc properties for compatibility
|
|
||||||
if (name != null)
|
|
||||||
System.setProperty("multimc.instance.title", name);
|
|
||||||
if (iconId != null)
|
|
||||||
System.setProperty("multimc.instance.icon", iconId);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static PreLaunchAction parseLine(String input, Parameters params) throws ParseException {
|
private static PreLaunchAction parseLine(String input, Parameters params) throws ParseException {
|
||||||
switch (input) {
|
switch (input) {
|
||||||
case "":
|
case "":
|
||||||
break;
|
return PreLaunchAction.PROCEED;
|
||||||
|
|
||||||
case "launch":
|
case "launch":
|
||||||
return PreLaunchAction.LAUNCH;
|
return PreLaunchAction.LAUNCH;
|
||||||
@ -192,9 +158,9 @@ public final class EntryPoint {
|
|||||||
throw new ParseException(input, "[key] [value]");
|
throw new ParseException(input, "[key] [value]");
|
||||||
|
|
||||||
params.add(pair[0], pair[1]);
|
params.add(pair[0], pair[1]);
|
||||||
}
|
|
||||||
|
|
||||||
return PreLaunchAction.PROCEED;
|
return PreLaunchAction.PROCEED;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private enum PreLaunchAction { PROCEED, LAUNCH, ABORT }
|
private enum PreLaunchAction { PROCEED, LAUNCH, ABORT }
|
||||||
|
38
libraries/launcher/org/prismlauncher/SystemProperties.java
Normal file
38
libraries/launcher/org/prismlauncher/SystemProperties.java
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
package org.prismlauncher;
|
||||||
|
|
||||||
|
import org.prismlauncher.utils.Parameters;
|
||||||
|
|
||||||
|
public final class SystemProperties {
|
||||||
|
public static void apply(Parameters params) {
|
||||||
|
String launcherBrand = params.getString("launcherBrand", null);
|
||||||
|
String launcherVersion = params.getString("launcherVersion", null);
|
||||||
|
String name = params.getString("instanceName", null);
|
||||||
|
String iconId = params.getString("instanceIconKey", null);
|
||||||
|
String iconPath = params.getString("instanceIconPath", null);
|
||||||
|
String windowTitle = params.getString("windowTitle", null);
|
||||||
|
String windowDimensions = params.getString("windowParams", null);
|
||||||
|
|
||||||
|
if (launcherBrand != null)
|
||||||
|
System.setProperty("minecraft.launcher.brand", launcherBrand);
|
||||||
|
if (launcherVersion != null)
|
||||||
|
System.setProperty("minecraft.launcher.version", launcherVersion);
|
||||||
|
|
||||||
|
// set useful properties for mods
|
||||||
|
if (name != null)
|
||||||
|
System.setProperty("org.prismlauncher.instance.name", name);
|
||||||
|
if (iconId != null)
|
||||||
|
System.setProperty("org.prismlauncher.instance.icon.id", iconId);
|
||||||
|
if (iconPath != null)
|
||||||
|
System.setProperty("org.prismlauncher.instance.icon.path", iconPath);
|
||||||
|
if (windowTitle != null)
|
||||||
|
System.setProperty("org.prismlauncher.window.title", windowTitle);
|
||||||
|
if (windowDimensions != null)
|
||||||
|
System.setProperty("org.prismlauncher.window.dimensions", windowDimensions);
|
||||||
|
|
||||||
|
// set multimc properties for compatibility
|
||||||
|
if (name != null)
|
||||||
|
System.setProperty("multimc.instance.title", name);
|
||||||
|
if (iconId != null)
|
||||||
|
System.setProperty("multimc.instance.icon", iconId);
|
||||||
|
}
|
||||||
|
}
|
@ -54,15 +54,9 @@
|
|||||||
|
|
||||||
package org.prismlauncher.utils;
|
package org.prismlauncher.utils;
|
||||||
|
|
||||||
import org.prismlauncher.utils.logging.Log;
|
|
||||||
|
|
||||||
import java.applet.Applet;
|
|
||||||
import java.io.File;
|
|
||||||
import java.lang.invoke.MethodHandle;
|
import java.lang.invoke.MethodHandle;
|
||||||
import java.lang.invoke.MethodHandles;
|
import java.lang.invoke.MethodHandles;
|
||||||
import java.lang.invoke.MethodType;
|
import java.lang.invoke.MethodType;
|
||||||
import java.lang.reflect.Field;
|
|
||||||
import java.lang.reflect.Modifier;
|
|
||||||
|
|
||||||
public final class ReflectionUtils {
|
public final class ReflectionUtils {
|
||||||
private static final MethodHandles.Lookup LOOKUP = MethodHandles.lookup();
|
private static final MethodHandles.Lookup LOOKUP = MethodHandles.lookup();
|
||||||
|
@ -14,8 +14,8 @@ set(Launcher_DisplayName "Prism Launcher")
|
|||||||
set(Launcher_Name "${Launcher_CommonName}" PARENT_SCOPE)
|
set(Launcher_Name "${Launcher_CommonName}" PARENT_SCOPE)
|
||||||
set(Launcher_DisplayName "${Launcher_DisplayName}" PARENT_SCOPE)
|
set(Launcher_DisplayName "${Launcher_DisplayName}" PARENT_SCOPE)
|
||||||
|
|
||||||
set(Launcher_Copyright "Prism Launcher Contributors\\n© 2021-2022 PolyMC Contributors \\n© 2012-2021 MultiMC Contributors")
|
set(Launcher_Copyright "© 2022-2024 Prism Launcher Contributors\\n© 2021-2022 PolyMC Contributors\\n© 2012-2021 MultiMC Contributors")
|
||||||
set(Launcher_Copyright_Mac "Prism Launcher Contributors, © 2021-2022 PolyMC Contributors and © 2012-2021 MultiMC Contributors" PARENT_SCOPE)
|
set(Launcher_Copyright_Mac "© 2022-2024 Prism Launcher Contributors, © 2021-2022 PolyMC Contributors and © 2012-2021 MultiMC Contributors" PARENT_SCOPE)
|
||||||
set(Launcher_Copyright "${Launcher_Copyright}" PARENT_SCOPE)
|
set(Launcher_Copyright "${Launcher_Copyright}" PARENT_SCOPE)
|
||||||
set(Launcher_Domain "prismlauncher.org" PARENT_SCOPE)
|
set(Launcher_Domain "prismlauncher.org" PARENT_SCOPE)
|
||||||
set(Launcher_UserAgent "${Launcher_CommonName}/${Launcher_VERSION_NAME}" PARENT_SCOPE)
|
set(Launcher_UserAgent "${Launcher_CommonName}/${Launcher_VERSION_NAME}" PARENT_SCOPE)
|
||||||
|
@ -37,13 +37,13 @@ class BasicTask_MultiStep : public Task {
|
|||||||
class BigConcurrentTask : public ConcurrentTask {
|
class BigConcurrentTask : public ConcurrentTask {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
void startNext() override
|
void executeNextSubTask() override
|
||||||
{
|
{
|
||||||
// This is here only to help fill the stack a bit more quickly (if there's an issue, of course :^))
|
// This is here only to help fill the stack a bit more quickly (if there's an issue, of course :^))
|
||||||
// Each tasks thus adds 1024 * 4 bytes to the stack, at the very least.
|
// Each tasks thus adds 1024 * 4 bytes to the stack, at the very least.
|
||||||
[[maybe_unused]] volatile std::array<uint32_t, 1024> some_data_on_the_stack{};
|
[[maybe_unused]] volatile std::array<uint32_t, 1024> some_data_on_the_stack{};
|
||||||
|
|
||||||
ConcurrentTask::startNext();
|
ConcurrentTask::executeNextSubTask();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -71,11 +71,14 @@ class BigConcurrentTaskThread : public QThread {
|
|||||||
quit();
|
quit();
|
||||||
});
|
});
|
||||||
|
|
||||||
m_deadline.start();
|
if (thread() != QThread::currentThread()) {
|
||||||
|
QMetaObject::invokeMethod(this, &BigConcurrentTaskThread::start_timer, Qt::QueuedConnection);
|
||||||
|
}
|
||||||
big_task.run();
|
big_task.run();
|
||||||
|
|
||||||
exec();
|
exec();
|
||||||
}
|
}
|
||||||
|
void start_timer() { m_deadline.start(); }
|
||||||
|
|
||||||
public:
|
public:
|
||||||
bool passed_the_deadline = false;
|
bool passed_the_deadline = false;
|
||||||
|
Loading…
Reference in New Issue
Block a user