Compare commits

...

772 commits

Author SHA1 Message Date
Alexandru Ionut Tripon 031015b332
chore(deps): update korthout/backport-action action to v4.4 (#5441)
Some checks failed
Nix / Build (${{ matrix.system }}) (macos-26, aarch64-darwin) (push) Has been cancelled
Nix / Build (${{ matrix.system }}) (ubuntu-22.04, x86_64-linux) (push) Has been cancelled
Nix / Build (${{ matrix.system }}) (ubuntu-22.04-arm, aarch64-linux) (push) Has been cancelled
2026-04-22 20:08:16 +00:00
Alexandru Ionut Tripon b4f34b87d6
chore(deps): update cachix/install-nix-action digest to 6165592 (#5325) 2026-04-22 20:07:58 +00:00
Alexandru Ionut Tripon de8ad56e60
chore(nix): update lockfile (#5307) 2026-04-22 20:07:36 +00:00
Alexandru Ionut Tripon b65f25fcfe
chore(deps): update hendrikmuhs/ccache-action action to v1.2.23 (#5440) 2026-04-22 19:03:01 +00:00
renovate[bot] f14701ffb7
chore(deps): update korthout/backport-action action to v4.4 2026-04-21 21:05:28 +00:00
renovate[bot] 672cd4d59c
chore(deps): update cachix/install-nix-action digest to 6165592 2026-04-21 21:05:23 +00:00
renovate[bot] a7c91796b3
chore(deps): update hendrikmuhs/ccache-action action to v1.2.23 2026-04-21 09:23:37 +00:00
Alexandru Ionut Tripon 5a9fdffd7d
chore(deps): update softprops/action-gh-release action to v3 (#5369) 2026-04-20 10:43:38 +00:00
Alexandru Ionut Tripon e154413b1d
ci(container): actually use amd64 runner for amd64 (#5436) 2026-04-20 06:35:22 +00:00
Seth Flynn 541e5ca9fe
ci(container): actually use amd64 runner for amd64
Signed-off-by: Seth Flynn <getchoo@tuta.io>
2026-04-20 01:06:38 -04:00
Alexandru Ionut Tripon 48f240703f
feat: add Manage Skins menu item to accounts button in MainWindow (#5414) 2026-04-19 20:44:25 +00:00
Alexandru Ionut Tripon b595488487
NetJob: do not automatically retry on 404 Not Found response (#5416) 2026-04-19 20:44:13 +00:00
Alexandru Ionut Tripon e7322a4507
fix world size uninitialized memory and UI refresh signal (#5418) 2026-04-19 20:44:06 +00:00
github-actions[bot] c67de94b3d chore(nix): update lockfile
Flake lock file updates:

• Updated input 'nixpkgs':
    'https://releases.nixos.org/nixos/unstable/nixos-26.05pre971119.8110df5ad7ab/nixexprs.tar.xz?narHash=sha256-D4ely1FsBcvtj/qSrNhSWpq%2BCUZKNiKwJIxpxnfy9o4%3D' (2026-03-28)
  → 'https://releases.nixos.org/nixos/unstable/nixos-26.05pre980183.4bd9165a9165/nixexprs.tar.xz?narHash=sha256-Gk2T0tDDDAs319hp/ak%2BbAIUG5bPMvnNEjPV8CS86Fg%3D' (2026-04-14)
2026-04-19 00:47:57 +00:00
Alexandru Ionut Tripon e7a03d311c
ProgressDialog: allow finished tasks to be re-displayed once restarted (#5412) 2026-04-17 14:00:07 +00:00
Alexandru Ionut Tripon af8225e2da
Improve checksum mismatch logging (#5413) 2026-04-17 13:59:58 +00:00
Alexandru Ionut Tripon 49e9f96327
Fixes for task abort logic (#5415) 2026-04-17 13:59:42 +00:00
captivator cbaf45084e fix world size uninitialized memory and UI refresh signal
Signed-off-by: captivator <84224501+qaptivator@users.noreply.github.com>
2026-04-17 15:28:12 +03:00
captivator 03799bf258
apply reviewer suggestion: use explicit MSA check again
Co-authored-by: Alexandru Ionut Tripon <alexandru.tripon97@gmail.com>
Signed-off-by: captivator <84224501+qaptivator@users.noreply.github.com>
2026-04-17 13:47:08 +03:00
captivator 4344f5eef9
apply reviewer suggestion: use explicit MSA check
Co-authored-by: Alexandru Ionut Tripon <alexandru.tripon97@gmail.com>
Signed-off-by: captivator <84224501+qaptivator@users.noreply.github.com>
2026-04-17 13:46:43 +03:00
Alexandru Ionut Tripon 4872ec634c
chore: bump develop version to 12.0.0 (#5339) 2026-04-17 07:12:35 +00:00
Octol1ttle 85613cfadc
Don't use new Qt method
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-04-17 11:12:46 +05:00
0x189D7997 4a59e6012d
NetJob: do not automatically retry on 404 response
Signed-off-by: 0x189D7997 <199489335+0x189D7997@users.noreply.github.com>
2026-04-17 03:45:33 +00:00
0x189D7997 ffded2ccac
Fix(NetJob): do not call emitAborted() when not running
Signed-off-by: 0x189D7997 <199489335+0x189D7997@users.noreply.github.com>
2026-04-17 02:56:04 +00:00
0x189D7997 15b39af92e
Fix(Task): check if task is still running before calling emitAborted()
Signed-off-by: 0x189D7997 <199489335+0x189D7997@users.noreply.github.com>
2026-04-17 02:11:06 +00:00
0x189D7997 4ed3aa1f1c
Fix(InstanceCreationTask): propagate abort signal to super
Signed-off-by: 0x189D7997 <199489335+0x189D7997@users.noreply.github.com>
2026-04-17 02:07:09 +00:00
captivator 7d0d9a3827 feat: add Manage Skins menu item to accounts button in MainWindow
Assisted-by: Gemini:3-Flash
Signed-off-by: captivator <84224501+qaptivator@users.noreply.github.com>
2026-04-17 04:15:48 +03:00
Octol1ttle b9fa4ffc00
fix(ProgressDialog): allow finished tasks to be re-displayed once restarted
Cherry-picked from libcurl (lmao)

Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-04-16 22:04:43 +05:00
Tayou f40cbf816e
fix text overlap in project item views (#5406) 2026-04-16 09:45:45 +00:00
Octol1ttle 3ee45691ab
change: improve checksum mismatch logging
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-04-16 11:32:58 +05:00
Alexandru Ionut Tripon 8a68c625fb
Windows installer: Disable skipping files (#5385) 2026-04-15 21:08:25 +00:00
Alexandru Ionut Tripon 8eb9a9971b
Search by project id (#) improvement (#5303) 2026-04-15 20:41:57 +00:00
Alexandru Ionut Tripon 44e3ae59e4
Low RAM warning fixes (#5392) 2026-04-15 20:39:08 +00:00
Alexandru Ionut Tripon 8901da68c7
chore(deps): update actions/cache action to v5.0.5 (#5386) 2026-04-15 20:38:24 +00:00
so5iso4ka fa54329711
fix text overlap in project item views
Signed-off-by: so5iso4ka <so5iso4ka@icloud.com>
2026-04-15 22:44:17 +03:00
renovate[bot] cddbb0e970
chore(deps): update softprops/action-gh-release action to v3 2026-04-15 09:43:32 +00:00
renovate[bot] da50f0e9e3
chore(deps): update actions/cache action to v5.0.5 2026-04-15 09:43:28 +00:00
0x189D7997 28c42d04b6
Limit normal search fallback to 404 respnse
Signed-off-by: 0x189D7997 <199489335+0x189D7997@users.noreply.github.com>
2026-04-14 23:51:34 +00:00
Octol1ttle 5d9622db21
Use newlines more often in macOS dialog for a nicer look
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-04-14 23:24:10 +05:00
Alexandru Ionut Tripon 7e8db63882
Fix infinite loop in SkinManageDialog (#5388) 2026-04-14 16:30:03 +00:00
Alexandru Ionut Tripon 519d8f7385
add a option to skip meta refresh on launch (#5267) 2026-04-14 16:29:30 +00:00
Alexandru Ionut Tripon ece83eb637
fix: force metadata version list refreshes to reload (#5349) 2026-04-14 16:29:05 +00:00
Alexandru Ionut Tripon 06282c0363
fix pessimizing-move warning (#5361) 2026-04-14 16:28:01 +00:00
Alexandru Ionut Tripon a0c5893a98
Task: Warn when disposing while running (#5371) 2026-04-14 16:27:24 +00:00
Alexandru Ionut Tripon fbec685eb5
Fix Copy/Upload buttons not working in ScreenshotsPage (#5387) 2026-04-14 16:26:12 +00:00
Octol1ttle 0b578fa767
fix(EnsureAvailableMemory/macOS): warn based on memory pressure rather than available RAM
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-04-14 18:58:47 +05:00
Octol1ttle ae331cfc9a
change(EnsureAvailableMemory): rephrase warning message
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-04-14 18:43:52 +05:00
Octol1ttle 575be16d3e
fix(EnsureAvailableMemory): do not warn if available memory could not be read
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-04-14 12:47:48 +05:00
Octol1ttle d5db0c6c1b
fix(SkinList): do not consider non-png files correctly
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-04-14 00:39:34 +05:00
Octol1ttle 1fec781251
fix(ScreenshotsPage): fix QString::arg in string with no arguments
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-04-13 23:44:13 +05:00
Octol1ttle 08de904e21
fix(ScreenshotsPage): disable "Copy Image" when selecting multiple screenshots
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-04-13 23:44:13 +05:00
Octol1ttle 7a1d2e41a1
refactor(ScreenshotsPage): clang-tidy
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-04-13 23:44:13 +05:00
Octol1ttle 1b650622ea
fix(ScreenshotsPage): use correct selection collection
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-04-13 22:57:13 +05:00
Octol1ttle 88035b9815
change(Windows installer): disable skipping files
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-04-13 21:05:30 +05:00
Octol1ttle ae7e143537
change(Task): warn when disposing while running
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-04-12 13:48:15 +05:00
DioEgizio b230645d53
Updater: Do not reset current task in finished signal (#5370) 2026-04-12 08:22:19 +00:00
Octol1ttle 9b270f783e
fix(updater): do not reset current task in finished signal
The order of signals in case of a success is "succeeded"->"finished"

The "succeeded" signal may launch another download if the updater needs to fetch more pages
But if we reset the task then the newly started download will be disposed and the updater will softlock

Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-04-12 13:02:46 +05:00
Andrei Damian ac54df366b fix pessimizing-move warning
Signed-off-by: Andrei Damian <andreidaamian@gmail.com>
2026-04-11 12:08:06 +03:00
Alexandru Ionut Tripon a17a45c748
enable modpack changelog for modrinth page (#5354) 2026-04-11 05:19:09 +00:00
Alexandru Ionut Tripon a488eb6d5d
fix pack upgrade (#5345) 2026-04-10 17:04:55 +00:00
Trial97 f3ff0a730a enable modpack changelog for modrinth page
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2026-04-10 19:29:56 +03:00
Alexandru Ionut Tripon 966ecd00bd
Allow disabling low RAM warning (#5333) 2026-04-10 09:14:47 +00:00
Octol1ttle 4b3aedd5d0
Change LowMemWarning default to always enabled
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-04-10 11:53:37 +05:00
morsz 2219c37d7f
fix: force metadata version list refreshes to reload
manual refreshes on version selection screens could reuse cached metadata and skip downloading updated manifests, so new versions would not appear until Prism was restarted. pass an explicit forced reload through the shared version list loading path and use it from refresh actions so manual refresh always reloads metadata

Signed-off-by: morsz <morsz@morsz.dev>
2026-04-10 02:19:28 +02:00
Trial97 b7344af313 fix pack upgrade
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2026-04-10 00:36:05 +03:00
Trial97 9bccda0a79 chore: bump develop version to 12.0.0
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2026-04-09 23:32:02 +03:00
Alexandru Ionut Tripon 013bb5cac3
fix McClient (#5332) 2026-04-09 20:23:53 +00:00
Alexandru Ionut Tripon e8afd48c67
Don't count JAR mods when checking offline libraries (#5334) 2026-04-09 20:18:41 +00:00
Alexandru Ionut Tripon 2ef22124cd
CI/Nix: Bump macOS (#5335) 2026-04-09 20:16:54 +00:00
Alexandru Ionut Tripon 6b9d2dbb64
fix(PrintInstanceInfo): add break before OS info (#5336) 2026-04-09 20:16:13 +00:00
Octol1ttle 658a1391f8
change(EnsureAvailableMemory): add lenience
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-04-09 22:35:32 +05:00
Octol1ttle 4cf8cf7d18
fix(PrintInstanceInfo): add break before OS info
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-04-09 20:53:42 +05:00
Octol1ttle 724c9a4a2c
fix(CI/nix): bump macOS
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-04-09 20:40:22 +05:00
Octol1ttle ec4484282c
fix: don't count JAR mods when checking offline libraries
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-04-09 20:31:39 +05:00
Octol1ttle c044ed36af
feat: allow disabling low RAM warning
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-04-09 19:34:11 +05:00
Octol1ttle 91616ae9b6
refactor: McClient
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-04-09 19:03:35 +05:00
Octol1ttle 2fe0569bd6
fix(McClient): do not use unsigned type for response length
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-04-09 17:41:25 +05:00
0x189D7997 364968a6b4
Use network_error_code from callbacks
Signed-off-by: 0x189D7997 <199489335+0x189D7997@users.noreply.github.com>
2026-04-07 12:57:09 +00:00
Alexandru Ionut Tripon 194b72f180
Fix CurseForge recommended RAM check (#5310) 2026-04-06 16:36:59 +00:00
Felix Schnabel 68efc9b9df
Fix Flame recommended RAM check
Signed-off-by: Felix Schnabel <f.schnabel@tum.de>
2026-04-06 17:59:27 +02:00
0x189D7997 fdd1a5dde8
oops forgot again
Signed-off-by: 0x189D7997 <199489335+0x189D7997@users.noreply.github.com>
2026-04-04 13:35:06 +00:00
0x189D7997 4151db6c94
Fallback to normal search on error and apply same changes to ResourceModel
Signed-off-by: 0x189D7997 <199489335+0x189D7997@users.noreply.github.com>
2026-04-04 13:12:23 +00:00
0x189D7997 4706f894e3
Activate search by project id only for numarical values for CurseForge
Signed-off-by: 0x189D7997 <199489335+0x189D7997@users.noreply.github.com>
2026-04-04 07:29:19 +00:00
0x189D7997 bf75d50baf
Make search by id fail quietly
Signed-off-by: 0x189D7997 <199489335+0x189D7997@users.noreply.github.com>
2026-04-04 07:27:29 +00:00
0x189D7997 983bf34807
Allow requesting project info without manual retry on fail
Signed-off-by: 0x189D7997 <199489335+0x189D7997@users.noreply.github.com>
2026-04-04 07:17:58 +00:00
DioEgizio b0f7ae1223
Add back drag and dropping to screenshots page (#5300) 2026-04-03 21:10:02 +00:00
Alexandru Ionut Tripon 447333c3f9
LaunchController: fix double task finish (#5301) 2026-04-03 20:37:39 +00:00
Octol1ttle 29c4f2f0e8
LaunchController: replace Q_ASSERT_X with regular Q_ASSERT
the info specified in the where/what arguments isn't more helpful compared to the default output of Q_ASSERT

Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-04-03 21:22:24 +05:00
Octol1ttle ad325960e7
LaunchController: clang-tidy
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-04-03 21:21:44 +05:00
Octol1ttle c367cc1c59
LaunchController: fix double finish
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-04-03 21:15:37 +05:00
leia uwu 35526b53f9
Add back drag and dropping to screenshots page
Fixes #4548

And #1503 was technically fixed when drag and drop was disabled but can also be closed as this does not reintroduce the issue

Signed-off-by: leia uwu <leia@tutamail.com>
2026-04-03 12:24:05 -03:00
Alexandru Ionut Tripon 3656335666
CI: verify clang-tidy config before running (#5291) 2026-04-03 12:08:05 +00:00
Alexandru Ionut Tripon 16bd9c2743
fix heap overflow with unstable version comparation (#5252) 2026-04-03 11:54:09 +00:00
Octol1ttle a79cb5a9fc
change(CI): run clang-tidy quietly and only for files in compilation database
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-04-03 16:42:46 +05:00
Octol1ttle d2eae3b072
change(CI): verify clang-tidy config before running
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-04-03 16:42:45 +05:00
Trial97 087ffb26ba
clang-tidy: fix warnings
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2026-04-03 14:39:27 +03:00
Trial97 8427626e56
add modrinth pre-release support to flexVer implementation
extended the flexVer implementation to consider any space that is after
a numeric section as a pre-release.

Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2026-04-03 13:59:06 +03:00
Trial97 5a0931d3cf
fix heap overflow with unstable version comparation
fixes #5210
fixes #5251 (the removeDuplicates line)

The issue was mostly with the Version parsing and compring
implementation.
Refactored that based on the https://git.sleeping.town/exa/FlexVer
examples.

Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2026-04-03 13:59:06 +03:00
Alexandru Ionut Tripon 156b7f365e
fix: clang-tidy action (#5292) 2026-04-03 10:34:43 +00:00
Alexandru Ionut Tripon 67a1aee306
Allow selecting multiple items in Network Error dialog (#5296) 2026-04-03 06:37:28 +00:00
0x189D7997 c58562a304
Allow selecting multiple items in Network Error dialog
Signed-off-by: 0x189D7997 <199489335+0x189D7997@users.noreply.github.com>
2026-04-02 13:20:03 +00:00
Alexandru Ionut Tripon a3c5f1f6f2
Fix weird utf archive (#5186) 2026-04-02 09:55:40 +00:00
Trial97 9c81e74061
nix: update to llvmPackages_22
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2026-04-02 00:41:31 +03:00
Trial97 1f3403677c
update clang-tidy config
feat from @Octol1ttle

Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2026-04-02 00:40:51 +03:00
Alexandru Ionut Tripon a4c9e294da
fixes crash on servers with invalid packet (#5289) 2026-04-01 10:24:39 +00:00
Trial97 0689e58ca2 fixes crash on servers with invalid packet
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2026-04-01 11:28:10 +03:00
DioEgizio 1450ffca18
fix incorrect mod side beeing saved (#5283) 2026-03-31 18:46:02 +00:00
DioEgizio 2b390a4ca3
fix world import (#5282) 2026-03-31 18:45:25 +00:00
DioEgizio 3d1f495bd5
Correctly append PRISMLAUNCHER_DISABLE_GLVULKAN to AppImage env (#5286) 2026-03-31 18:23:36 +00:00
Octol1ttle 9b06c0699c
fix(CI): correctly append PRISMLAUNCHER_DISABLE_GLVULKAN to AppImage environment
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-03-31 23:03:01 +05:00
Trial97 fbc45699c1
fix incorrect mod side beeing saved
fixes #5262

Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2026-03-31 00:46:46 +03:00
Trial97 83d82c2519
fix world import
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2026-03-30 23:52:48 +03:00
Alexandru Ionut Tripon 31be615f7b
chore(nix): update lockfile (#5278) 2026-03-29 16:50:56 +00:00
Seth Flynn 17048a586a
Use Launcher_ENVName for launcher environment variable names (#5226) 2026-03-29 06:56:04 +00:00
github-actions[bot] 071be5f700 chore(nix): update lockfile
Flake lock file updates:

• Updated input 'nixpkgs':
    'https://releases.nixos.org/nixos/25.11/nixos-25.11.7849.812b3986fd15/nixexprs.tar.xz?narHash=sha256-d2Q5VNbc91GloTZNByC4u3JS8Tj5BjfuOF19/vuJ/iM%3D' (2026-03-20)
  → 'https://releases.nixos.org/nixos/25.11/nixos-25.11.8107.1073dad219cb/nixexprs.tar.xz?narHash=sha256-cUgsPWt0NJz21K4i/5191mWaizw4XtT20WFqyxzSuQI%3D' (2026-03-24)
2026-03-29 00:43:39 +00:00
Seth Flynn 01a4a6a528
build(devcontainer): explicitly include vulkan headers (#5276) 2026-03-28 20:19:03 +00:00
Seth Flynn 2b9620b6a6
build(devcontainer): explicitly include vulkan headers
Signed-off-by: Seth Flynn <getchoo@tuta.io>
2026-03-28 15:46:20 -04:00
Alexandru Ionut Tripon 7ffec104dc
chore(deps): update cachix/install-nix-action digest to 96951a3 (#5242) 2026-03-28 10:10:59 +00:00
renovate[bot] f191947ad5
chore(deps): update cachix/install-nix-action digest to 96951a3 2026-03-28 00:50:01 +00:00
DioEgizio 63a8b43119 chore: clang-format
Signed-off-by: DioEgizio <dioegizio@protonmail.com>
2026-03-27 07:24:15 +01:00
Trial97 40b7cab3ed
add a option to skip meta refresh on launch
related to https://github.com/PrismLauncher/PrismLauncher/issues/3785
It doesn't fix it but it should at least allow users to skip the
redownload of the meta files.
So in a previous PR I added an automated way to refresh all the meta
from the original index, to the component index to the actual index.

Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2026-03-27 00:23:23 +02:00
DioEgizio eb44bdc3b3 fix: fix PRISMLAUNCHER_JAVA_PATHS
also set Launcher_ENVName as parent scope directly

Signed-off-by: DioEgizio <dioegizio@protonmail.com>
2026-03-26 22:07:02 +01:00
Alexandru Ionut Tripon 75f951fec9
Add Renovate labels automatically (#5265) 2026-03-26 20:09:37 +00:00
Alexandru Ionut Tripon 39bc1a72dc
chore(deps): update hendrikmuhs/ccache-action action to v1.2.22 (#5263) 2026-03-26 19:46:20 +00:00
Alexandru Ionut Tripon 43c4223413
chore(deps): update korthout/backport-action action to v4.3.0 (#5264) 2026-03-26 19:45:50 +00:00
Alexandru Ionut Tripon c7fd66cf97
Revert "Sort modpack entries by version, rather than publishing date" (#5243) 2026-03-26 18:05:19 +00:00
Alexandru Ionut Tripon 1b05e33202
do not delete mod on cancel (#5238) 2026-03-26 18:04:58 +00:00
DioEgizio 1ea0c7570f fix: dehardcode PRISMLAUNCHER_JAVA_PATHS too
Signed-off-by: DioEgizio <dioegizio@protonmail.com>
2026-03-26 18:33:44 +01:00
DioEgizio bf42cfdcf2 fix: rename LAUNCHER_DISABLE_GLVULKAN to PRISMLAUNCHER_DISABLE_GLVULKAN
for consistency with other env vars

this also introduces LAUNCHER_ENVNAME in BuildConfig/program_info for rebranded configurations

Signed-off-by: DioEgizio <dioegizio@protonmail.com>
2026-03-26 18:33:44 +01:00
Alexandru Ionut Tripon 5ad45a4098
Warn user on launch if there is not enough available RAM (#5249) 2026-03-26 17:00:48 +00:00
Octol1ttle eed2facb66
change(renovate.json): add labels automatically
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-03-26 21:41:53 +05:00
renovate[bot] 47ad0703b2
chore(deps): update korthout/backport-action action to v4.3.0 2026-03-26 16:28:19 +00:00
renovate[bot] d0ac15a275
chore(deps): update hendrikmuhs/ccache-action action to v1.2.22 2026-03-26 16:28:16 +00:00
Alexandru Ionut Tripon 9f5f1bcf10
Enable automatic update checking by default (#5259) 2026-03-26 16:09:48 +00:00
Alexandru Ionut Tripon 64c78fadc1
Improve NetJob failure dialog (#5260) 2026-03-26 16:09:40 +00:00
Octol1ttle 3a48d13c07
feat(NetworkJobFailedDialog): implement URL copying
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-03-26 10:46:37 +05:00
TheKodeToad 7bb746dfab
Safer dialog
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2026-03-26 10:46:37 +05:00
TheKodeToad 4bc72ccca4
My tweaks
Use a tree view instead of table view, remove toggle button (janky)

Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2026-03-26 10:46:37 +05:00
TheKodeToad e6d7e5cdae
Backport new NetJob failure dialog from Octol1ttle's libcurl PR
Co-authored-by: Octol1ttle <l1ttleofficial@outlook.com>
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2026-03-26 10:46:37 +05:00
Octol1ttle b3fa99dd2f
change: enable automatic update checking by default
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-03-26 09:29:02 +05:00
Octol1ttle 69fe3e3b1a
feat: warn user on launch if there is not enough available RAM
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-03-24 12:09:11 +05:00
Trial97 6674f1e803
Revert "Sort modpack entries by version, rather than publishing date"
This reverts commit 9e3893fd62.

Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2026-03-23 19:57:07 +02:00
timoreo c16a25faef
make OpenJ9 logo square (#5240) 2026-03-23 16:04:44 +00:00
Tayou 19eba5c6bc
make OpenJ9 logo square
Signed-off-by: Tayou <git@tayou.org>
2026-03-23 14:27:54 +01:00
Alexandru Ionut Tripon f91accdce8
Log error if file open/commit fails (#5235) 2026-03-23 13:11:39 +00:00
Alexandru Ionut Tripon 6c6dc55dc0
Update update-flake.yml with new labels (#5231) 2026-03-23 12:58:09 +00:00
Trial97 3a65ed4c25
do not delete mod on cancel
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2026-03-23 13:26:57 +02:00
DioEgizio e90ecdaeea
rate limit the FTB mod downloads (#5237) 2026-03-23 08:48:27 +00:00
Trial97 5136c15833
rate limit the FTB mod downloads
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2026-03-23 10:14:23 +02:00
Rachel Powers f0f26bbfaf
add robot type label
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2026-03-22 21:58:39 -07:00
Octol1ttle 838687fb2e
fix: log error if file open/commit fails
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-03-23 01:07:05 +05:00
Alexandru Ionut Tripon 09823dbb4a
chore(nix): update lockfile (#5230) 2026-03-22 06:38:12 +00:00
Rachel Powers 0daf4669ad
add priority label
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2026-03-21 19:51:52 -07:00
Rachel Powers 988ec79bc7
Update update-flake.yml with new labels
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2026-03-21 19:48:38 -07:00
github-actions[bot] d43c2133b8 chore(nix): update lockfile
Flake lock file updates:

• Updated input 'nixpkgs':
    'https://releases.nixos.org/nixos/25.11/nixos-25.11.7516.3e20095fe3c6/nixexprs.tar.xz?narHash=sha256-C/pSy3nRByzeKFcdtv4pNc8uYuT02pBdQB4BE3knKus%3D' (2026-03-13)
  → 'https://releases.nixos.org/nixos/25.11/nixos-25.11.7849.812b3986fd15/nixexprs.tar.xz?narHash=sha256-d2Q5VNbc91GloTZNByC4u3JS8Tj5BjfuOF19/vuJ/iM%3D' (2026-03-20)
2026-03-22 00:39:45 +00:00
Seth Flynn eed06a78f2
build(cmake): avoid re-defining _FORTIFY_SOURCE (#5228) 2026-03-21 20:11:35 +00:00
Seth Flynn e9fab9ada3
build(cmake): avoid re-defining _FORTIFY_SOURCE
Previously, applying this to anything except the default `Debug` build
configuration opened us up to issues with packaging systems (i.e.,
Arch's `makepkg` and Flatpak) who already define this OOTB. Specifically
matching the configurations we want to apply this to and checking if this
is applied globally by `$CFLAGS` or similar should prevent this
re-definition, restoring the behavior from before 8477cc4 and 5d0eeae

Signed-off-by: Seth Flynn <getchoo@tuta.io>
2026-03-21 15:41:09 -04:00
DioEgizio 03543a0cbb
Add CLI option to open main window when launching instance (#5107) 2026-03-21 13:17:28 +00:00
Alexandru Ionut Tripon 39bb912aab
feat: ibm semeru runtime open edition support (openj9 jvm) (#5138) 2026-03-21 10:01:04 +00:00
Rachel Powers 2f62b8ef06
fix: allow disabling gl and vulkan features with an envvar and disable it by default on appimage/portable (#5224) 2026-03-21 01:29:51 +00:00
Rachel Powers 731866c577
Overwrite component update task when it has different network mode (#5216) 2026-03-20 23:29:49 +00:00
Rachel Powers d0705a9406
handle mod formatting codes (#4550) 2026-03-20 23:16:00 +00:00
Rachel Powers 26a2b35a3b
Sort modpack versions properly (#5170) 2026-03-20 23:00:39 +00:00
DioEgizio 2514c8b21f
fix: only enable fortify on optimized builds (#5223) 2026-03-20 17:52:11 +00:00
DioEgizio 696039e1ce
fix: also export LIBGL_KOPPER_DRI2=1 on zink (#5222) 2026-03-20 17:51:30 +00:00
DioEgizio e524fa5b6b fix: allow disabling gl and vulkan features with an envvar and disable it by default on appimage/portable
the previous approach didn't work with runtime symbol lookup errors

Signed-off-by: DioEgizio <83089242+DioEgizio@users.noreply.github.com>
2026-03-20 17:03:07 +01:00
DioEgizio 5d0eeae04c fix: only enable fortify on optimized builds
also enables optimization and enables LTO on relwithdebinfo

Signed-off-by: DioEgizio <83089242+DioEgizio@users.noreply.github.com>
2026-03-20 16:38:15 +01:00
DioEgizio f945422246 fix: also export LIBGL_KOPPER_DRI2=1 on zink
fixes crashes on certain X11 systems

Signed-off-by: DioEgizio <83089242+DioEgizio@users.noreply.github.com>
2026-03-20 14:59:07 +01:00
DioEgizio 348907f7d1
ci(container): create manifests for all tags (#5220) 2026-03-19 23:15:25 +00:00
Seth Flynn b7677c81d2
ci(container): create manifests for all tags
Signed-off-by: Seth Flynn <getchoo@tuta.io>
2026-03-19 18:59:01 -04:00
Seth Flynn 5cf20d935d
ci(container): fix digest image reference for manifest (#5219) 2026-03-19 20:57:09 +00:00
Seth Flynn 24fea7b8a8
ci(container): fix digest image reference for manifest
Signed-off-by: Seth Flynn <getchoo@tuta.io>
2026-03-19 16:29:47 -04:00
Octol1ttle cd006d642b
fix(PackProfile): overwrite update task when it has different network mode
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-03-19 10:54:15 +05:00
Alexandru Ionut Tripon 04786023b0
Some small cleanups (#4772) 2026-03-18 20:29:26 +00:00
Alexandru Ionut Tripon b00e5e3f64
chore(deps): update hendrikmuhs/ccache-action action to v1.2.21 (#5208) 2026-03-18 20:23:42 +00:00
Rachel Powers 109e453bf2
chore(deps): update cachix/cachix-action action to v17 (#5215) 2026-03-18 20:23:08 +00:00
Alexandru Ionut Tripon 8e8bc5aa0f
fix: URL import fix for Linux (#5141) 2026-03-18 20:18:22 +00:00
renovate[bot] 4c3a7c492b
chore(deps): update cachix/cachix-action action to v17 2026-03-18 19:51:48 +00:00
Alexandru Ionut Tripon bc809d78d3
fix heap buffer overflow (#5213) 2026-03-18 19:33:19 +00:00
Rachel Powers c61249d648
chore(deps): update actions/cache action to v5.0.4 (#5214) 2026-03-18 16:54:08 +00:00
Rachel Powers 3f23985a97
JavaChecker: Add support for ppc64 and ppc64le architectures (#5212) 2026-03-18 16:49:59 +00:00
renovate[bot] 06c29564cc
chore(deps): update actions/cache action to v5.0.4 2026-03-18 16:32:46 +00:00
Trial97 3967fde405
fix heap buffer overflow
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2026-03-18 18:13:14 +02:00
Trung Lê cd06eee030
JavaChecker: Add support for ppc64 and ppc64le architectures
Signed-off-by: Trung Lê <8@tle.id.au>
2026-03-19 00:18:23 +11:00
Alexandru Ionut Tripon 53385fdfea
Fix #4695: Update java path label and tooltip (#5198) 2026-03-18 05:38:53 +00:00
Seth Flynn 289a7e3859
ci(container): login to ghcr to fetch digests for manifest (#5206) 2026-03-18 05:38:22 +00:00
Seth Flynn 1ce90fa6c0
build: use app id for mime package name (#5205) 2026-03-18 05:28:01 +00:00
renovate[bot] cf1722110e
chore(deps): update hendrikmuhs/ccache-action action to v1.2.21 2026-03-18 03:57:15 +00:00
Seth Flynn 877832c713
Use clang-tidy in CMake and CI (#5051) 2026-03-18 03:40:12 +00:00
Seth Flynn 3d7d9b4e7c
Refactor global C/CXX flags in CMake (#5133) 2026-03-18 01:23:12 +00:00
Seth Flynn 8477cc4cd6
build(cmake): refactor global c/cxx build flags
Signed-off-by: Seth Flynn <getchoo@tuta.io>
2026-03-17 20:52:34 -04:00
Seth Flynn a5a6da8a45
ci(container): login to ghcr to fetch digests for manifest
Podman should be able to find the images we push in the previous step
now........hopefully

Signed-off-by: Seth Flynn <getchoo@tuta.io>
2026-03-17 20:22:54 -04:00
Seth Flynn e8a7e2ebb5
build: use app id for mime package name
Signed-off-by: Seth Flynn <getchoo@tuta.io>
2026-03-17 18:35:11 -04:00
Seth Flynn 067a992378
ci(clang-tidy): disable pch
This would previously make most of our files error out with
`error: __OPTIMIZE__ predefined macro was enabled in PCH file but is currently disabled`

Signed-off-by: Seth Flynn <getchoo@tuta.io>
2026-03-17 15:47:03 -04:00
Seth Flynn 33056c913d
ci: run clang-tidy
Co-authored-by: Octol1ttle <l1ttleofficial@outlook.com
Signed-off-by: Seth Flynn <getchoo@tuta.io>
2026-03-17 15:46:57 -04:00
Alexandru Ionut Tripon 4ae1296314
Dehardcode branding in Linux manuals and Windows app info, make .mrpack MIME file name unique (#5202) 2026-03-17 19:34:36 +00:00
Alexandru Ionut Tripon adf9d67030
mod versions now list in newest first order (#5194) 2026-03-17 19:24:03 +00:00
Octol1ttle 0e732bf499
dehardcode branding in Linux manual and Windows app info
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-03-17 20:25:16 +05:00
Metehan 77e36c7d68 Fix #4695: Clarify Java auto-download path in settings UI
Signed-off-by: Metehan <metehancekci9@gmail.com>
2026-03-17 18:18:33 +03:00
DioEgizio 5dd90996b9
feat+fix: Rework modrinth fallback for blocked mods a bit (#4499) 2026-03-17 14:47:29 +00:00
Octol1ttle 61d08d1870
change(CMakeLists): make .mrpack XML file name unique to avoid conflicts
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-03-17 19:22:57 +05:00
DioEgizio 9d5f4059bf feat+fix: Rework modrinth fallback for blocked mods a bit
Signed-off-by: DioEgizio <83089242+DioEgizio@users.noreply.github.com>
2026-03-17 15:16:57 +01:00
Ludgie 085a3b0fab
feat: ibm semeru runtime open edition support
Signed-off-by: Ludgie <ludgie@odate.eu>
2026-03-17 13:51:37 +01:00
Alexandru Ionut Tripon 5979052337
chore(deps): update azure/login action to v3 (#5200) 2026-03-17 11:17:53 +00:00
renovate[bot] 7d62e72024
chore(deps): update azure/login action to v3 2026-03-17 10:14:21 +00:00
Alexandru Ionut Tripon c7d43f1685
Modrith api optional changelog (#5197) 2026-03-17 08:50:37 +00:00
Trial97 441fb4a891
load the path name with local8Bit if not utf
extended to the symlinks stuff so I geneeralized the function:
- if I can get the utf8(the best outcome) I will use fromUtf8
- if not I will fall back to normal funciton and decode it with
fromLocal8Bit

This convention applies to:
- archive_entry_pathname
- archive_entry_symlink
- archive_entry_hardlink

Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2026-03-17 09:12:27 +02:00
Alexandru Ionut Tripon 662a448080
feat: curseforge modpack downloading via binaryname:// uri (#4872) 2026-03-17 06:03:41 +00:00
DioEgizio 49cc358154
chore(deps): update cachix/install-nix-action digest to 1ca7d21 (#5163) 2026-03-17 05:16:23 +00:00
DioEgizio 90a3769d33
chore(deps): update actions/create-github-app-token action to v3 (#5174) 2026-03-17 05:16:08 +00:00
DioEgizio c661322a36
Actually update blocked/blocking workflow (#5192) 2026-03-17 05:15:53 +00:00
DioEgizio d1252d4ea3
chore(deps): update hendrikmuhs/ccache-action action to v1.2.21 (#5195) 2026-03-17 05:15:19 +00:00
DioEgizio 658c7e27d0
change(CMakeLists): dehardcode app names (#5196) 2026-03-17 05:14:55 +00:00
DioEgizio d97847e9ab
Updated Resource Pack Formats (#5199) 2026-03-17 05:13:37 +00:00
Seth Flynn 720ea089b3
chore(nix): add clang-tidy-diff wrapper
Signed-off-by: Seth Flynn <getchoo@tuta.io>
2026-03-16 21:59:08 -04:00
Seth Flynn 25387c5b6c
build(cmake): add support for clang-tidy
Signed-off-by: Seth Flynn <getchoo@tuta.io>
2026-03-16 21:54:39 -04:00
Seth Flynn 6b90403550
build(cmake): don't duplicate resources to launcher sources
Signed-off-by: Seth Flynn <getchoo@tuta.io>
2026-03-16 21:54:38 -04:00
Trial97 d78ab048d4
mod versions now list in newest first order
superseeds #4239 because the original author went unresponsive
Closes #4052

Clicking a _pack_ in _menu_ -> _edit_ -> _mods_. Fixed minecraft version
being in ascending order left-to-right (e.g. 1.21.6, 1.21.7, 1.21.8).
Now version are shown in descending order (e.g. 1.21.8, 1.21.7, 1.21.6).

Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2026-03-17 00:47:57 +02:00
Trial97 d3f8dfe65c
Updated Resource Pack Formats
superseeds #4242
also this adds support for min_format and max_format and the major.minor
versioning.

Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2026-03-17 00:40:49 +02:00
Rachel Powers 67fe365ae0
chore: clang-tidy work adjacent to changelog api fix
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2026-03-16 14:58:20 -07:00
Rachel Powers e16235c1ca
fix: don't always ask for the changelog from modrinth
- per https://discordapp.com/channels/734077874708938864/974050507150729236/1461487847142985982

  `/project/<id>/version` now has an `include_changelog` query param
  which can be set to false to save oodles of bandwidth

Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2026-03-16 14:57:35 -07:00
mctaylors 6f7ba83168
change(CMakeLists): MORE dehardcoding
Signed-off-by: mctaylors <cantsendmails@mctaylors.ru>
2026-03-17 00:11:44 +03:00
renovate[bot] 0a5cca899e
chore(deps): update hendrikmuhs/ccache-action action to v1.2.21 2026-03-16 20:27:44 +00:00
Danhoby c301e3cbb4
Fix URL import for Linux
Signed-off-by: Danhoby <37343749+Dan4oby@users.noreply.github.com>

Fix macos scheme

Signed-off-by: Danhoby <37343749+Dan4oby@users.noreply.github.com>
2026-03-16 22:07:01 +03:00
Alexandru Ionut Tripon 98c3129424
chore(nix): update lockfile (#5180) 2026-03-16 18:15:12 +00:00
Octol1ttle 90c4107199
Actually update blocked/blocking workflow
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-03-16 23:11:52 +05:00
DioEgizio ab72536248
Fix infinite update (#5187) 2026-03-16 18:10:50 +00:00
DioEgizio ea67f17974
Update issue templates to match new labels (#5189) 2026-03-16 17:29:55 +00:00
DioEgizio 0434e16762
Update blocked/blocking workflow to match new labels (#5190) 2026-03-16 17:29:25 +00:00
DioEgizio 1c92ef83e5
Log OS, CPU, RAM and GPUs on all systems (#5169) 2026-03-16 17:28:59 +00:00
Octol1ttle 81f9837e37
Update blocked/blocking workflow to match new labels
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-03-16 16:45:18 +05:00
Octol1ttle d221a0a449
feat: print hardware information in launch log
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-03-16 15:04:46 +05:00
Octol1ttle de96b6ae87
change: update issue templates to match new labels
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-03-16 15:04:28 +05:00
Alexandru Ionut Tripon cc22702ea5
Remove stale workflow (#5167) 2026-03-16 07:54:26 +00:00
Alexandru Ionut Tripon 5772a8ac93
Reshuffle launch log (#5179) 2026-03-16 07:54:02 +00:00
Trial97 47f4b85435
codeql: fixed warnings
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2026-03-16 00:30:57 +02:00
Trial97 37590c8ffe
fix updater infinitly checking if there is an update
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2026-03-16 00:30:32 +02:00
Trial97 3f97d65224
codeql: fix some warnings
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2026-03-15 23:32:10 +02:00
Trial97 cf024e228f
fix utf8 archive that doesn't mark the file as utf8
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2026-03-15 23:28:54 +02:00
DioEgizio 3cdb464feb
InstanceList: include lowercase "windows.h" (#5185) 2026-03-15 21:00:04 +00:00
Octol1ttle 13d9e0be4d
InstanceList: clean up includes
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-03-16 01:43:05 +05:00
Octol1ttle 764600704d
fix(InstanceList): include lowercase windows.h
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-03-16 01:42:59 +05:00
DioEgizio 14ca5f15f2
Mark accounts with errors in dropdown (#5181) 2026-03-15 12:02:40 +00:00
Octol1ttle fac0ad7493
feat: mark accounts with errors
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-03-15 16:07:55 +05:00
github-actions[bot] d510ad01c6 chore(nix): update lockfile
Flake lock file updates:

• Updated input 'nixpkgs':
    'https://releases.nixos.org/nixos/25.11/nixos-25.11.7198.71caefce12ba/nixexprs.tar.xz?narHash=sha256-uKkU4cS3lkh3zlnUf%2BQRX6zd5LHOM0mrqhEvZ5fqqHM%3D' (2026-03-06)
  → 'https://releases.nixos.org/nixos/25.11/nixos-25.11.7516.3e20095fe3c6/nixexprs.tar.xz?narHash=sha256-C/pSy3nRByzeKFcdtv4pNc8uYuT02pBdQB4BE3knKus%3D' (2026-03-13)
2026-03-15 00:42:34 +00:00
Octol1ttle 76bbd0f9ca
change: reshuffle launch log
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-03-15 02:03:49 +05:00
renovate[bot] ec874f7f21
chore(deps): update actions/create-github-app-token action to v3 2026-03-14 00:52:59 +00:00
Alexandru Ionut Tripon 14da23b06f
Use LLVM-based stdenv for Nix build/shell (#5155) 2026-03-13 21:08:08 +00:00
Alexandru Ionut Tripon a1e3a28666
LaunchController: minor fixes (#5129) 2026-03-13 17:53:59 +00:00
Octol1ttle 31eb4c67ba
improve error message
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-03-13 16:59:57 +05:00
TheCourierNV 9e3893fd62
Sort modpack entries by version, rather than publishing date
This fixes issues the display order while using packs like Fabolously Optimized, who release
versions out of order

Signed-off-by: TheCourierNV <andreascart04@gmail.com>
2026-03-12 22:19:33 +01:00
Seth Flynn 8cb9262b09
ci(container): try to fix manifest creation (#5157) 2026-03-12 07:45:23 +00:00
Octol1ttle d65b140d73
change(Actions): remove stale workflow
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-03-12 12:07:03 +05:00
renovate[bot] bf65a7385c
chore(deps): update cachix/install-nix-action digest to 1ca7d21 2026-03-10 21:55:39 +00:00
DioEgizio faf23c053d
fix crash when updating datapacks (#5158) 2026-03-10 10:48:58 +00:00
Alexandru Ionut Tripon 8b33c6e06e
chore(deps): update korthout/backport-action action to v4.2.0 (#5039) 2026-03-10 10:42:15 +00:00
Alexandru Ionut Tripon 0845218da8
chore(deps): update github artifact actions (major) (#5154) 2026-03-10 10:41:50 +00:00
Alexandru Ionut Tripon 18889939c2
chore(deps): update docker/metadata-action action to v6 (#5156) 2026-03-10 10:40:42 +00:00
Alexandru Ionut Tripon 7bef408598
Ask before deleting saves as part of a Modpack update (#4622) 2026-03-10 10:25:37 +00:00
Alexandru Ionut Tripon d29912608d
fix zip path traversal (#5034) 2026-03-10 10:22:48 +00:00
Alexandru Ionut Tripon 6d868f689c
fix no name instances (#5055) 2026-03-10 10:21:56 +00:00
Alexandru Ionut Tripon 48eade763a
Apply suggestions from code review
Co-authored-by: Octol1ttle <l1ttleofficial@outlook.com>
Signed-off-by: Alexandru Ionut Tripon <alexandru.tripon97@gmail.com>
2026-03-10 10:10:19 +02:00
Trial97 464a04a2cb
ensure that save lock isunlocked on success
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2026-03-10 09:26:30 +02:00
Trial97 56936cf485
fix zip path traversal
this makes sure that the file is in the given root

Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2026-03-10 09:26:12 +02:00
Trial97 0b26d24c9b
ask user if he wants to delete saves on modpack update
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2026-03-10 09:25:13 +02:00
Trial97 eb15897b1a
reset scroll on resource change
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2026-03-10 09:24:53 +02:00
Trial97 5767479c21
handle mod formatting codes
fixes #4535
this changes the info frame to be an actuall scrollbar so if the
description is too long the text is not directly cut off, and let's the
user to view it all.

This is may not be the best ui decssion but feel free to pick this issue
up yourself or suggest changes to this PR(the important bit is in the
cpp file).

Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2026-03-10 09:24:53 +02:00
Trial97 d958a91ce9
fix crash when updating datapacks
parent PR #5101
so for datapacks and datapacks only we need an extra check.
Why? Because Datapacks are treated as ModLoaderType but they aren't a
modloader. So the modLoaderTypesToList will generate an empty list even
if loader is 64 (not 0).

Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2026-03-10 08:55:33 +02:00
Seth Flynn 367de94f31
ci(container): try to fix manifest creation
Signed-off-by: Seth Flynn <getchoo@tuta.io>
2026-03-09 21:05:45 -04:00
renovate[bot] 7348cb9dc9
chore(deps): update github artifact actions 2026-03-10 01:04:56 +00:00
renovate[bot] a46fb0df86
chore(deps): update docker/metadata-action action to v6 2026-03-10 01:04:52 +00:00
Seth Flynn 437242169d
Push development container to GHCR (#5132) 2026-03-10 00:48:16 +00:00
Seth Flynn f47df1eebf
build(nix): use LLVM-based stdenv
Since we use so much LLVM-based tooling, might as well use it for the
main compiler

This also allows for a bit of parity with our Debian-based development
container

Signed-off-by: Seth Flynn <getchoo@tuta.io>
2026-03-09 19:10:42 -04:00
Seth Flynn 6763a7fa39
ci: push devcontainer to ghcr
Signed-off-by: Seth Flynn <getchoo@tuta.io>
2026-03-09 19:03:04 -04:00
Alexandru Ionut Tripon 1bc5f18b04
chore(deps): update github artifact actions (major) (#5109) 2026-03-09 22:26:45 +00:00
Alexandru Ionut Tripon 0068eef222
chore(deps): update cachix/install-nix-action digest to 2126ae7 (#5126) 2026-03-09 22:26:30 +00:00
Alexandru Ionut Tripon c24c4add50
actions(macos): build .dmg disk images (#5135) 2026-03-09 21:58:31 +00:00
mctaylors 4bba4aaebf
fix(actions): this is a certified bash classic
Signed-off-by: mctaylors <cantsendmails@mctaylors.ru>
2026-03-09 23:36:47 +03:00
Alexandru Ionut Tripon 9dcb5b7da4
fix %INST_JAVA% incorrect path format on windows (#5072) 2026-03-09 20:22:25 +00:00
renovate[bot] 3ab187a4fe
chore(deps): update cachix/install-nix-action digest to 2126ae7 2026-03-09 20:16:36 +00:00
Alexandru Ionut Tripon 6d5a3278cc
Open correct wiki URL when opened from main window (#5130) 2026-03-09 20:11:11 +00:00
Alexandru Ionut Tripon ac8a51290b
change(cmake): dehardcode launcher names in info.plist (#5136) 2026-03-09 20:11:08 +00:00
Alexandru Ionut Tripon 0a3953524a
change(CMakeLists.txt): dehardcode launcher name (#5142) 2026-03-09 20:05:56 +00:00
mctaylors 7c5d54f8aa
change(CMakeLists.txt): dehardcode launcher name
Signed-off-by: mctaylors <cantsendmails@mctaylors.ru>
2026-03-08 19:07:30 +03:00
Alexandru Ionut Tripon b518259f57
chore(nix): update lockfile (#5140) 2026-03-08 11:26:59 +00:00
github-actions[bot] 7eb2c2a2f7 chore(nix): update lockfile
Flake lock file updates:

• Updated input 'nixpkgs':
    'https://releases.nixos.org/nixos/25.11/nixos-25.11.6561.1267bb4920d0/nixexprs.tar.xz?narHash=sha256-8rDP2AfBFi0DI9idtlWeK73XWJScPvwgokuYkSnVY/Y%3D' (2026-02-25)
  → 'https://releases.nixos.org/nixos/25.11/nixos-25.11.7198.71caefce12ba/nixexprs.tar.xz?narHash=sha256-uKkU4cS3lkh3zlnUf%2BQRX6zd5LHOM0mrqhEvZ5fqqHM%3D' (2026-03-06)
2026-03-08 00:37:04 +00:00
mctaylors 7472a2bb94
change(cmake): i'm not sure but
Signed-off-by: mctaylors <cantsendmails@mctaylors.ru>
2026-03-07 01:25:19 +03:00
mctaylors a4ea7839dc
actions(macos): add .dmg because GHA didn't liked it
Signed-off-by: mctaylors <cantsendmails@mctaylors.ru>
2026-03-07 01:06:52 +03:00
Seth Flynn 352b98db8e
Enable warnings as errors (#5101) 2026-03-06 07:42:39 +00:00
mctaylors 0aa2ceffec
actions(macos): keep .zip and upload .dmg on release
Signed-off-by: mctaylors <cantsendmails@mctaylors.ru>
2026-03-05 22:20:46 +03:00
renovate[bot] cd9efa2e42
chore(deps): update korthout/backport-action action to v4.2.0 2026-03-05 19:09:15 +00:00
mctaylors 3768d38b54
change(cmake): certified vim skill issue
Signed-off-by: mctaylors <cantsendmails@mctaylors.ru>
2026-03-05 21:52:08 +03:00
mctaylors e71d0b082d
change(cmake): dehardcode launcher names in info.plist
Signed-off-by: mctaylors <cantsendmails@mctaylors.ru>
Co-authored-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-03-05 21:16:20 +03:00
Octol1ttle 068bbba570
change: use BUILDSYSTEM_TARGETS to apply warnings
Co-authored-by: Seth Flynn <getchoo@tuta.io>
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-03-05 18:16:55 +05:00
mctaylors 07ddbb76f1
actions(macos): build .dmg disk images
Signed-off-by: mctaylors <cantsendmails@mctaylors.ru>
2026-03-05 14:34:23 +03:00
renovate[bot] e3ea57c96b
chore(deps): update github artifact actions 2026-03-05 09:39:53 +00:00
Octol1ttle 979973b313
fix: open correct wiki URL when opened from the Help *menu*
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-03-04 22:16:48 +05:00
Octol1ttle 314a7fc67d
fix(LaunchController): use separate message for account errors
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-03-04 21:46:29 +05:00
Octol1ttle f7941b6431
fix(LaunchController): emit failed with correct reason
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-03-04 21:46:20 +05:00
Alexandru Ionut Tripon b114d043f6
Use an owning QByteArray in ByteArraySink (#5050) 2026-03-02 16:53:22 +00:00
Alexandru Ionut Tripon 52e6e35fc9
chore(nix): update lockfile (#4984) 2026-03-02 07:14:04 +00:00
Alexandru Ionut Tripon 8da890a1fc
Add a development container (#5091) 2026-03-02 06:57:26 +00:00
github-actions[bot] f61acde6de chore(nix): update lockfile
Flake lock file updates:

• Updated input 'libnbtplusplus':
    'github:PrismLauncher/libnbtplusplus/531449ba1c930c98e0bcf5d332b237a8566f9d78?narHash=sha256-qhmjaRkt%2BO7A%2Bgu6HjUkl7QzOEb4r8y8vWZMG2R/C6o%3D' (2025-04-16)
  → 'github:PrismLauncher/libnbtplusplus/687e43031df0dc641984b4256bcca50d5b3f7de3?narHash=sha256-7itkptyjoRcXfGLwg1/jxajetZ3a4mDc66%2Bw4X6yW8s%3D' (2026-02-25)
• Updated input 'nixpkgs':
    'https://releases.nixos.org/nixos/25.11/nixos-25.11.4882.fa83fd837f30/nixexprs.tar.xz?narHash=sha256-kzEnMXuhOsr6tE6QvuTvdolZ3VqnOMzU8EOTGXsP9RU%3D' (2026-01-28)
  → 'https://releases.nixos.org/nixos/25.11/nixos-25.11.6561.1267bb4920d0/nixexprs.tar.xz?narHash=sha256-8rDP2AfBFi0DI9idtlWeK73XWJScPvwgokuYkSnVY/Y%3D' (2026-02-25)
2026-03-01 00:41:18 +00:00
Octol1ttle 0dfb6c99e1
fix(ModrinthCheckUpdate): guard list access
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-02-26 17:49:12 +05:00
Octol1ttle 9cf9ec5341
fix(InstanceList): count() should be int as all usages expect int
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-02-26 17:49:12 +05:00
Octol1ttle f26a4f897c
fix ignoring return value of function declared with 'nodiscard' attribute
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-02-26 17:49:12 +05:00
Octol1ttle eda4592f19
Fix implicit fallthrough
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-02-26 17:49:12 +05:00
Octol1ttle 110d1a8fcf
Update libnbtplusplus
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-02-26 17:49:11 +05:00
Octol1ttle ec4b36b299
Fix compiler warnings
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-02-26 17:49:11 +05:00
Octol1ttle 94da1308ac
Refactor warning enabling, enable warnings-as-errors
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-02-26 17:49:11 +05:00
Matthew_Cash eae13f705f
Add CLI option to open main window when launching instance
Signed-off-by: Matthew_Cash <matthew@matthew-cash.com>
2026-02-25 20:27:06 -08:00
DioEgizio 83e0b93938
Remove testsdata symlinks (#5090) 2026-02-25 16:37:24 +00:00
Seth Flynn 6b7f7a2477
Update clang-tidy config (#5098) 2026-02-25 07:45:59 +00:00
Octol1ttle dde1d21cbc
run clang-format to apply new qualifier alignment
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-02-25 12:31:31 +05:00
Octol1ttle 1486e40f14
.clang-format: explicitly specify qualifier alignment
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-02-25 12:27:52 +05:00
Octol1ttle e8d0163aa4
Update .clang-tidy configuration file
Enables most of checks provided by clang-tidy, with checks that do not fit us excluded. The table containing naming conventions was using wrong values, that was fixed and now tidy correctly warns and fixes naming convention issues

Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-02-25 12:27:52 +05:00
Alexandru Ionut Tripon c36fadee70
Fix backface culling re-enabling with elytra preview on (#5093) 2026-02-24 21:57:10 +00:00
Octol1ttle a3eba815dd
fix backface culling reenabling with elytra preview
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-02-24 12:17:51 +05:00
Seth Flynn 69bf4d53e1
build: add dev container
Signed-off-by: Seth Flynn <getchoo@tuta.io>
2026-02-23 16:51:30 -05:00
Rachel Powers 8855e16230
tests: remove testsdata symlinks
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2026-02-23 12:40:26 -07:00
Alexandru Ionut Tripon 4ed77a940c
URL protocol modpack import for any encoded URL (#4990) 2026-02-22 21:58:08 +00:00
Alexandru Ionut Tripon eb26dcd516
fix: parse world_gen_settings.dat for seed (#5071) 2026-02-22 21:57:00 +00:00
Alexandru Ionut Tripon a6c5a85639
Actually check for updates on launch (#5076) 2026-02-22 21:56:46 +00:00
Danhoby 92e9264230 Danhoby <37343749+Dan4oby@users.noreply.github.com>
DCO Remediation Commit for Danhoby <37343749+Dan4oby@users.noreply.github.com>

I, Danhoby <37343749+Dan4oby@users.noreply.github.com>, hereby add my Signed-off-by to this commit: 1bd07392e07417956f45ed56bede6f31f1dc8d2d
I, Danhoby <37343749+Dan4oby@users.noreply.github.com>, hereby add my Signed-off-by to this commit: c1003dec2f3b6925453680b90a168300b0cba42a
I, Danhoby <37343749+Dan4oby@users.noreply.github.com>, hereby add my Signed-off-by to this commit: 9d5d7742a5e1f583578685087f8785909d386997

Signed-off-by: Danhoby <37343749+Dan4oby@users.noreply.github.com>
2026-02-22 20:04:15 +03:00
Danhoby 6e09f01714 Fix issues
Signed-off-by: Danhoby <37343749+Dan4oby@users.noreply.github.com>
2026-02-22 20:04:15 +03:00
Danhoby 9d534d5a8f Fix import
Signed-off-by: Danhoby <37343749+Dan4oby@users.noreply.github.com>
2026-02-22 20:04:15 +03:00
Danhoby 88d7bccd02 Implement URL protocol import modpack functionality
Signed-off-by: Danhoby <37343749+Dan4oby@users.noreply.github.com>
2026-02-22 20:04:15 +03:00
Alexandru Ionut Tripon 574b75fac0
fix tweakers (#4913) 2026-02-21 22:16:26 +00:00
DioEgizio a49ab221d9
OtherLogsPage: Remove CR when removing LF (#5073) 2026-02-21 20:12:38 +00:00
DioEgizio f685aca18e
OtherLogsPage: Fix some strings not being translatable (#5074) 2026-02-21 20:12:27 +00:00
DioEgizio ba9aed84aa
Don't show progress dialog when automatically checking for updates (#5075) 2026-02-21 20:11:44 +00:00
DioEgizio d33a27656c
NewsDialog: Save and restore geometry (#5077) 2026-02-21 20:11:16 +00:00
DioEgizio f24b74f71b
Skin renderer: Do not enable backface culling (#5078) 2026-02-21 20:10:45 +00:00
Octol1ttle 3422fa5c5a
fix(SkinOpenGLWindow): do not enable backface culling
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-02-21 12:36:59 +05:00
Trial97 9d4bde7f96
fix tweakers
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2026-02-20 23:43:27 +02:00
Octol1ttle d8a25f55e4
feat(NewsDialog): save and restore geometry
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-02-21 00:21:53 +05:00
Octol1ttle 61c6eb0b4f
change(PrismExternalUpdater): don't show progress dialog when autochecking
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-02-21 00:00:27 +05:00
Octol1ttle dbe2770682
fix(PrismExternalUpdater): actually check for updates on launch
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-02-20 23:57:13 +05:00
Octol1ttle 668cbf4ee0
fix(OtherLogsPage): make UI strings translatable
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-02-20 23:00:17 +05:00
Octol1ttle 3f11b185a8
fix(OtherLogsPage): remove CR when removing LF
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-02-20 22:54:10 +05:00
deiseil 0a4427f9c3
fix %INST_JAVA% incorrect path format on windows
Signed-off-by: deiseil <32784127+deiseil@users.noreply.github.com>
2026-02-20 17:56:50 +01:00
Trial97 e0139185c8
fix: parse world_gen_settings.dat for seed
fixes #5064
Minecraft moved the world gen settins outside the level.dat file.
So now we need to check data/minecraft/world_gen_settings.dat for the
seed.
I did not bother with zip files(I did not even see the zip file in the
launcher so I will not bother with it)

Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2026-02-20 15:28:15 +02:00
TheKodeToad eac55d849c
Stop showing a star on the oldest java (#5056) 2026-02-19 13:22:48 +00:00
TheKodeToad 61d55b4223
fix crash with skin format (#5000) 2026-02-18 12:51:19 +00:00
TheKodeToad 3c076bfcf6
Stop showing a star on the oldest java
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2026-02-18 12:40:36 +00:00
TheKodeToad 1ac986b7c8
Remove std::unique_ptr from ByteArraySink
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2026-02-18 09:16:36 +00:00
TheKodeToad 316121ba8f
Use an owning QByteArray in ByteArraySink
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2026-02-18 00:31:05 +00:00
Alexandru Ionut Tripon 4a46726cc9
Don't manually format UUIDs (#5045) 2026-02-17 20:40:53 +00:00
Alexandru Ionut Tripon 71abf3beec
Download game files during instance creation (#4944) 2026-02-17 20:23:06 +00:00
Alexandru Ionut Tripon 2b84053011
Highlight resources incompatible with the Minecraft version (#5010) 2026-02-17 20:16:13 +00:00
Alexandru Ionut Tripon b20aa9a35c
fix(flame): avoid double-fail assert in file resolving (#5043) 2026-02-17 20:15:48 +00:00
Octol1ttle d81fa77d1f
fix: don't manually format UUIDs
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-02-18 01:14:35 +05:00
Alexandru Ionut Tripon d7fc37cd42
ui: making trackpad scrolling smoother across all listing views (#5029) 2026-02-17 20:11:14 +00:00
Alexandru Ionut Tripon 9bf2792c7f
refactor!: LaunchController (#4885) 2026-02-17 19:52:43 +00:00
Octol1ttle 6f0e053f4d
chore: add TODO for potential future race condition
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-02-18 00:19:32 +05:00
Octol1ttle 9f94b00925
change: use different message when launching with no account selected
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-02-18 00:19:32 +05:00
Octol1ttle f7deeb0db4
no recursion
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-02-18 00:19:32 +05:00
Octol1ttle 5d0360ccec
style things
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-02-18 00:19:32 +05:00
Octol1ttle a9f3be9f45
refactor: LaunchController
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-02-18 00:19:30 +05:00
Alexandru Ionut Tripon ba325a6012
Fix InstanceStaging reentry crash during Modrinth pack updates (#4982) 2026-02-17 18:28:27 +00:00
DioEgizio 76e78d358f
fix linting errors in CONTRIBUTING, run Nix on .md file changes (#5046) 2026-02-17 06:24:37 +00:00
Octol1ttle 894787bdfd
change(Actions): run Nix checks when Markdown files are changed
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-02-17 11:04:40 +05:00
Octol1ttle 67101751c8
fix(CONTRIBUTING): linting errors
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-02-17 11:04:40 +05:00
Seth Flynn e59e6f463c
add AI Policy (#5006) 2026-02-17 00:10:55 +00:00
Tayou 996ab61dab
remove duplicate note
Signed-off-by: Tayou <git@tayou.org>
2026-02-17 00:57:31 +01:00
Tayou c4b4d67d78
Update CONTRIBUTING.md
Co-authored-by: Seth Flynn <getchoo@tuta.io>
Signed-off-by: Tayou <git@tayou.org>
2026-02-17 00:30:56 +01:00
m0nstrum 3576c2f101 fix(flame): gate modrinth fallback parsing on success
Signed-off-by: m0nstrum <m0nstrum@proton.me>
2026-02-16 23:22:16 +03:00
m0nstrum f2cf982ea8 fix(flame): avoid double-fail assert in file resolving
Signed-off-by: m0nstrum <m0nstrum@proton.me>
2026-02-16 16:58:34 +03:00
Tayou 699df07613
fix: spelling
Signed-off-by: Tayou <git@tayou.org>
2026-02-15 11:17:35 +01:00
Işık 44eb2dc290
ui: implement smooth scrolling across all listing views
Signed-off-by: Işık <kimurathankurai@gmail.com>
2026-02-14 18:39:41 +03:00
Alexandru Ionut Tripon e334a8c0f4
fix: remove unused qt plugins on linux appimage and portable (#5026) 2026-02-14 15:16:28 +00:00
DioEgizio 247e5fcc6c fix: remove unused qt plugins on linux appimage and portable
Signed-off-by: DioEgizio <83089242+DioEgizio@users.noreply.github.com>
2026-02-14 13:42:53 +01:00
Rachel Powers 295a8493b8
Update CONTRIBUTING.md
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2026-02-14 03:34:36 -07:00
Tayou 4ba9c4b1a5
Update CONTRIBUTING.md
Co-authored-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
Signed-off-by: Tayou <git@tayou.org>
2026-02-14 10:16:20 +01:00
Tayou 44056043b1
Update CONTRIBUTING.md
Co-authored-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
Signed-off-by: Tayou <git@tayou.org>
2026-02-14 10:15:33 +01:00
DioEgizio 232e9fde09
fix: disable qt debug in every non-debug build (#5022) 2026-02-14 08:48:32 +00:00
DioEgizio 4f12814893
feat: disable pch on codeql build (#5023) 2026-02-13 22:07:08 +00:00
DioEgizio 00eb04db58 feat: disable pch on codeql build
this allows us to notice when no-pch builds break

Signed-off-by: DioEgizio <83089242+DioEgizio@users.noreply.github.com>
2026-02-13 18:28:47 +01:00
DioEgizio 61c13655d3 fix: disable qt debug in every non-debug build
without this change it was still enabled in RelWithDebInfo

Signed-off-by: DioEgizio <83089242+DioEgizio@users.noreply.github.com>
2026-02-13 18:11:55 +01:00
Alexandru Ionut Tripon a90c438655
fix: replace gnome icons with oxygen ones in the multimc icon theme (#5012) 2026-02-13 07:15:23 +00:00
Alexandru Ionut Tripon e6f2d824ab
Allow -Duser.language to be overriden (#5017) 2026-02-13 06:33:37 +00:00
TheKodeToad 71278ff7ea
Add opt-in for showing mod incompatibilities
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2026-02-12 22:37:15 +00:00
TheKodeToad b664846030
Allow multiple compat issues to be displayed, make game version incompat clearer
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2026-02-12 22:36:59 +00:00
TheKodeToad 6bbbfa06d1
Allow -Duser.language to be overriden
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2026-02-12 22:18:42 +00:00
TheKodeToad 1ad0628ca3
fix(SkinManageDialog): add missing QMenu include (#5015) 2026-02-12 21:49:42 +00:00
Rachel Powers 13b6aab7c1
add marplotlib attribution
Co-authored-by: TheKodeToad <TheKodeToad@proton.me>
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2026-02-12 14:36:16 -07:00
Alfred Wingate 67836213c5
fix(SkinManageDialog): add missing QMenu include
launcher/ui/dialogs/skins/SkinManageDialog.cpp: In member function ‘void SkinManageDialog::show_context_menu(const QPoint&)’:
launcher/ui/dialogs/skins/SkinManageDialog.cpp:344:18: error: variable ‘QMenu myMenu’ has initializer but incomplete type
  344 |     QMenu myMenu(tr("Context menu"), this);
      |                  ^~

Include appears to have been dropped transitively in either
0ba2c09787 or 45df360e4c

Signed-off-by: Alfred Wingate <parona@protonmail.com>
2026-02-12 23:26:27 +02:00
DioEgizio 43d2010960 fix: replace gnome icons with oxygen ones in the multimc icon theme
debian really wants this because of dfsg

Signed-off-by: DioEgizio <83089242+DioEgizio@users.noreply.github.com>
2026-02-12 22:05:18 +01:00
DioEgizio c0c9185a09
fix(macos): fix margins on macos (#4977) 2026-02-12 20:37:02 +00:00
TheKodeToad 9cb33b519f
Render incompatibility highlight and warning
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2026-02-12 18:56:57 +00:00
TheKodeToad 081d2f1e51
Reduce duplication in ResourceFolderModel subclasses
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2026-02-12 18:56:56 +00:00
TheKodeToad e2d503456f
Detect resources incompatible with the MC version
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2026-02-12 18:56:38 +00:00
Tayou ca16d85258
chore(docs): add AI policy
AI policy mostly plagiarized from matplotlib: https://matplotlib.org/devdocs/devel/contribute.html#generative-ai

Signed-off-by: Tayou <git@tayou.org>
2026-02-12 15:05:14 +01:00
Alexandru Ionut Tripon 157ae6fb72
Application.h cleanup (#4502) 2026-02-11 15:44:19 +00:00
Octol1ttle e5fe2c100e
change button text in Modrinth and Flame imports
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-02-11 20:32:36 +05:00
Trial97 fe5aee2619
fix crash with skin format
fixes #4994
All the formats lower than Format_Indexed8 will have less information
and can't be used directly.
Also added the check for alphaChannel check just to be sure.

Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2026-02-11 13:35:40 +02:00
Octol1ttle f59e5b2df9
change: set abort button to "Skip" when downloading game files
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-02-10 22:42:19 +05:00
Rachel Powers 7cda5e738f
refactor(console): attach console early (#4481) 2026-02-10 08:40:44 +00:00
Rachel Powers 45df360e4c
Reduce include chain further, forward declare settings and log model
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2026-02-09 20:03:10 -07:00
Rachel Powers 0ba2c09787
refactor(Application.h): reduce include chain
Include only what's absolutely necessary to reduce headers pulled into a
translation unit. If you need access to
instance's from `APPLICATION` include `BaseInstance.h` separately

Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2026-02-09 19:16:58 -07:00
Rachel Powers ffd50e318a
refactor(console): attach console early
also use RAII guard to free it instead of tracking it with a member variable

Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2026-02-09 16:52:35 -07:00
Abhinav Acharya 13c3111163
Merge branch 'PrismLauncher:develop' into fix/modpack-update-emit-succeeded-crash 2026-02-09 12:18:47 -05:00
Seth Flynn 35121f26fd
docs(README): use prismlauncher.org/nightly redirect for dev builds (#4987) 2026-02-09 07:07:46 +00:00
Seth Flynn 7ebc603963
docs(README): use prismlauncher.org/nightly redirect for dev builds
Signed-off-by: Seth Flynn <getchoo@tuta.io>
2026-02-08 18:26:54 -05:00
abhicommands 68f98491d5
Fix InstanceStaging success reentry assertion crash
Signed-off-by: abhicommands <114682464+abhicommands@users.noreply.github.com>
2026-02-06 22:42:32 -05:00
DioEgizio 0229c0fd0c
feat: Auto handle Http 429 Too Many Requests with retry (#4946) 2026-02-06 16:59:29 +00:00
Rachel Powers e8da9ee4fb
feat: Auto handle Http 429 Too Many Requests with retry
- Must be explicitly enabled for a request
- Uses Retry-After Header if present, falls back to exponential back off
  starting with 10 seconds
- if retry delay is greater than 1 minute or it retries more than 3
  times then fail with a "Rate Limited" reason
- Sets task status to inform user of retry.

Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2026-02-06 09:36:09 -07:00
DioEgizio b13f40df51 fix(macos): fix margins on macos
Signed-off-by: DioEgizio <83089242+DioEgizio@users.noreply.github.com>
2026-02-06 16:53:25 +01:00
TheKodeToad 9ca3739465
Remove outdated 'friends for the purpose of limiting access to deprecated stuff' comment
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2026-02-06 11:18:24 +00:00
TheKodeToad 8cbcadaca2
PSaveFile: use a type alias instead of a macro
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2026-02-06 11:18:23 +00:00
TheKodeToad 327a554d42
MangoHud: rename to LibraryUtils
It handles more than mangohud

Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2026-02-06 11:17:12 +00:00
TheKodeToad 248eb13ab9
Agent: Simplify and avoid unnecessary shared_ptr
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2026-02-06 11:17:12 +00:00
TheKodeToad 77ebf65c7d
GradleSpecifier: use defaulted == operator
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2026-02-06 11:17:12 +00:00
TheKodeToad 2f524c7a80
GradleSpecifier: directly initialise in constructor
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2026-02-06 11:17:12 +00:00
TheKodeToad eba6ffb37b
GradleSpecifier: Use std::optional instead of DefaultVariable
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2026-02-06 11:17:12 +00:00
Alexandru Ionut Tripon 9171e2b2e1
Cache news feed (#4964) 2026-02-05 10:51:07 +00:00
Alexandru Ionut Tripon 620567e435
Remove retrieving Xbox API token for gamertag (#4958) 2026-02-04 19:26:14 +00:00
Alexandru Ionut Tripon 2c95df4271
Actions: Unhardcode AppImage signing key ID (#4936) 2026-02-04 18:43:16 +00:00
Sefa Eyeoglu 2030b481bf
feat: cache news feed
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2026-02-04 18:29:00 +01:00
Alexandru Ionut Tripon f1a4721a6a
start core update task only if not running already (#4955) 2026-02-04 08:59:43 +00:00
Alexandru Ionut Tripon a3c17034c0
Turn off debug assertions in Release builds (#4959) 2026-02-04 05:38:49 +00:00
Octol1ttle d35155ca66
change(accounts): stop retrieving Xbox API token for gamertag
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-02-04 09:11:30 +05:00
Octol1ttle 31971b2746
fix: don't return instance if creation didn't succeed
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-02-04 09:11:09 +05:00
Octol1ttle 4afbd9da01
oops
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-02-04 09:11:09 +05:00
Octol1ttle d464c1ea68
fix: properly set details in InstanceCreationTask
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-02-04 09:11:09 +05:00
Octol1ttle f085a0ef25
fix: use translated "Aborted"
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-02-04 09:11:09 +05:00
Octol1ttle 7bcd2dd768
fix: properly emit aborted instead of failed
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-02-04 09:11:09 +05:00
Octol1ttle 625f0060a1
feat: download game files during instance creation
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-02-04 09:11:09 +05:00
Octol1ttle aa9896031d
refactor(InstanceCreationTask): return created instance to caller
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-02-04 09:11:08 +05:00
Rachel Powers d888ecaf11
fix: turn off debug assert in release builds
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2026-02-03 17:18:47 -07:00
Alexandru Ionut Tripon 9e86c44f7c
Harden CI permissions (#4950) 2026-02-03 22:09:41 +00:00
Alexandru Ionut Tripon 083671e4b3
Improvements to ComponentUpdateTask (#4942) 2026-02-03 22:07:09 +00:00
Alexandru Ionut Tripon 131e8711aa
launcher/minecract/auth/AccountList.cpp: add missing QIcon include (#4956) 2026-02-03 21:59:41 +00:00
Tayou 12dfbb7255
Remove XboxProfileStep (#4957) 2026-02-03 21:14:10 +00:00
Octol1ttle 8e992a324c
change(AuthFlow): remove XboxProfileStep
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-02-03 21:28:44 +05:00
Octol1ttle 9fac7065a7
fix(XboxAuthorizationStep): set x-xbl-contract-version
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-02-03 21:26:18 +05:00
Alfred Wingate 8a53949f67
launcher/minecract/auth/AccountList.cpp: add missing QIcon include
In member function ‘virtual QVariant AccountList::data(const QModelIndex&, int) const’:
/var/tmp/portage/games-action/prismlauncher-9999/work/prismlauncher-9999/launcher/minecraft/auth/AccountList.cpp:331:35: error: incomplete type ‘QIcon’ used in nested name specifier
  331 |                     return QIcon::fromTheme("noaccount").pixmap(24, 24);
      |

Fixes: fc1e29111b
Signed-off-by: Alfred Wingate <parona@protonmail.com>
2026-02-03 14:41:16 +02:00
Octol1ttle 27172dd1bd
change(Actions): unhardcode AppImage signing key ID
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-02-03 17:16:03 +05:00
Tayou fe81ad3fc8
ci: always run required checks (#4954) 2026-02-03 11:33:59 +00:00
Trial97 bc6a6e959b
start core update task only if not running already
This line crashes develop builds because the task is running already.

Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2026-02-03 12:10:09 +02:00
Seth Flynn 0e06c57efe
ci: always run required checks
Signed-off-by: Seth Flynn <getchoo@tuta.io>
2026-02-02 22:14:15 -05:00
Seth Flynn ed7101ba1e
Fix symlink instance copying on Windows (#4947) 2026-02-03 02:45:11 +00:00
Rachel Powers da019c8425
fix: windows filelink results needs to capture by refrence
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2026-02-02 18:35:26 -07:00
Seth Flynn f476b2b726
Use Merge Groups for primary CI (#4948) 2026-02-02 17:42:21 -05:00
Seth Flynn add9e55493
ci: use permissionless runner token by default
Runner token permissions should be explicitly declared at the job-level

Signed-off-by: Seth Flynn <getchoo@tuta.io>
2026-02-02 17:01:07 -05:00
Seth Flynn e0ad6a2b3b
ci(codeql): explicitly grant runner token permissions
This allows us to make our runner token only have read-only permissions
by default

Signed-off-by: Seth Flynn <getchoo@tuta.io>
2026-02-02 17:01:07 -05:00
Seth Flynn f85e2ddb15
ci(blocked-prs): restrict runner token permissions
These can run without any permissions since we use our own app for auth

Signed-off-by: Seth Flynn <getchoo@tuta.io>
2026-02-02 17:01:07 -05:00
Seth Flynn a770cc1128
ci(build+codeql): run for merge groups
Signed-off-by: Seth Flynn <getchoo@tuta.io>
2026-02-02 16:53:10 -05:00
Alexandru Ionut Tripon 3c6953845c
chore(nix): update lockfile (#4931) 2026-02-02 15:11:11 +02:00
Octol1ttle 02d1878a36
fix: manually copy task info when connecting
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-02-02 13:28:19 +05:00
Octol1ttle a58e3049b9
change(ComponentUpdateTask): add status, details, and progress
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-02-02 13:27:10 +05:00
Octol1ttle f007d90076
fix(ComponentUpdateTask): allow aborting
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-02-02 13:08:45 +05:00
Octol1ttle 2338455076 change(Actions): run tests with more output
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-02-01 09:59:21 +01:00
Octol1ttle e7382fd43d fix(ModrinthCheckUpdate): always increment loader index
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-02-01 07:57:14 +01:00
Alexandru Ionut Tripon a884e36b96
fix build on qt 6.4 (#4920) 2026-02-01 05:22:46 +02:00
Seth Flynn 2c6ce2fd8c
bump qt warning levels (#4928) 2026-01-31 22:20:20 -05:00
Seth Flynn baef2da03d
Bump 11.0.0 (#4924) 2026-01-31 22:15:38 -05:00
github-actions[bot] 2f9bc39eb6 chore(nix): update lockfile
Flake lock file updates:

• Updated input 'nixpkgs':
    'https://releases.nixos.org/nixos/25.11/nixos-25.11.4506.078d69f03934/nixexprs.tar.xz?narHash=sha256-Xu%2B7iYcAuOvsI2wdkUcIEmkqEJbvvE6n7qR9QNjJyP4%3D' (2026-01-22)
  → 'https://releases.nixos.org/nixos/25.11/nixos-25.11.4882.fa83fd837f30/nixexprs.tar.xz?narHash=sha256-kzEnMXuhOsr6tE6QvuTvdolZ3VqnOMzU8EOTGXsP9RU%3D' (2026-01-28)
2026-02-01 00:41:54 +00:00
Trial97 5232ebe989
bump qt warninig levels
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2026-02-01 00:22:23 +02:00
Trial97 399c6c80ed
bump to 11.0.0
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2026-01-31 23:20:16 +02:00
Trial97 f943331e39
fix codeql
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2026-01-31 21:46:36 +02:00
Alexandru Ionut Tripon 76ba65a113
fix build (#4918) 2026-01-31 21:24:42 +02:00
Trial97 611b1b6911
fix build
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2026-01-31 20:55:09 +02:00
Alexandru Ionut Tripon ef1e35d585
Track dependencies in Mods page (#3738) 2026-01-31 20:28:01 +02:00
Alexandru Ionut Tripon e541e6dd80
Add back FTB modpack support (#3559) 2026-01-31 20:26:46 +02:00
Alexandru Ionut Tripon fda9e74972
Remove systeminfo; move getSystemRam into SysInfo.h (#4323) 2026-01-31 20:24:40 +02:00
Alexandru Ionut Tripon 411b4b0649
update to qt 6.10.2, build codeql on the qt version we still want to support, sign DLLs on windows (#4909) 2026-01-31 19:29:41 +02:00
Alexandru Ionut Tripon cd993671cf
update local pack by url (#4474) 2026-01-31 14:03:52 +02:00
Alexandru Ionut Tripon 3270288031
Add configurable option on ScrollMessageBox (#4335) 2026-01-31 14:03:32 +02:00
DioEgizio 8781ac5f64 chore: trusted signing is now artifact signing
see https://github.com/Azure/artifact-signing-action/issues/107

Signed-off-by: DioEgizio <83089242+DioEgizio@users.noreply.github.com>
2026-01-31 10:07:12 +01:00
DioEgizio db7685259e fix: sign DLLs too on windows
should fix issues with Smart App Control

Signed-off-by: DioEgizio <83089242+DioEgizio@users.noreply.github.com>
2026-01-31 10:02:00 +01:00
Alexandru Ionut Tripon 9f745ec83e
Mention nightly Flatpak in docs (#4887) 2026-01-31 10:38:52 +02:00
DioEgizio b1857508f7 chore: update to Qt 6.10.2 on windows and linux appimage/portable
also switches codeql to build on Qt 6.4.3, to make sure prism still builds on the oldest version we still wanna support.
for this reason, codeql also now runs tests (to see if they don't fail on 6.4.3). While doing this I also noticed our qt requirement is 6.4, as we use Qt::Literals::StringLiterals

Signed-off-by: DioEgizio <83089242+DioEgizio@users.noreply.github.com>
2026-01-30 17:38:30 +01:00
Alexandru Ionut Tripon 204f9c5d8e
Abort launch when there are libraries missing (#4899) 2026-01-30 13:10:46 +02:00
Alexandru Ionut Tripon 6809d46ab6
remove followSymlinks calls (#4650) 2026-01-30 13:10:26 +02:00
Alexandru Ionut Tripon 7f9d5d07f8
chore(deps): update actions/cache action to v5.0.3 (#4898) 2026-01-30 13:09:59 +02:00
Alexandru Ionut Tripon 3a1bbdbe3a
Remove double spaces in logging (#4900) 2026-01-30 13:09:48 +02:00
Sefa Eyeoglu 27577e9d61
add more loaders to override setting (#4701) 2026-01-30 10:31:35 +01:00
Octol1ttle ffd1e7bc33
improve wording
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-01-29 19:54:02 +05:00
Octol1ttle 158a7bbc34
got clang-format'd 💀
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-01-29 19:27:06 +05:00
Octol1ttle 584dc47da5
chore: remove double spaces from logs
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-01-29 19:15:27 +05:00
Octol1ttle 193840b237
style: reorder includes
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-01-29 18:17:22 +05:00
Octol1ttle d4817a5669
feat: abort launch when there are libraries missing
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-01-29 18:14:23 +05:00
renovate[bot] 5d9fc6091a
chore(deps): update actions/cache action to v5.0.3 2026-01-29 12:51:54 +00:00
Alexandru Ionut Tripon b69dbc2224
MSAStep: Log server errors (#4895) 2026-01-29 14:51:18 +02:00
Octol1ttle 665aa4c546
change(MSAStep): log server errors
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-01-29 17:11:30 +05:00
Alexandru Ionut Tripon 70cbbf5b07
Trim whitespace from path values in settings (#4886) 2026-01-28 08:48:53 +02:00
Seth Flynn 301d978d9c
chore(nix): update lockfile (#4600) 2026-01-27 18:39:53 -05:00
Seth Flynn 81335aa1aa
docs(README): mention nightly flatpak
Signed-off-by: Seth Flynn <getchoo@tuta.io>
2026-01-27 18:38:11 -05:00
Seth Flynn 82b7c9786c
docs(README): remove mentions of community in-development packages
Most of these no longer exist or are prone to breakage

Signed-off-by: Seth Flynn <getchoo@tuta.io>
2026-01-27 18:35:14 -05:00
Seth Flynn cf63bccfd7
fix(MinecraftSettingsWidget): trim whitespace from path values
Should help in mitigating common mistakes in copy/pasting

Signed-off-by: Seth Flynn <getchoo@tuta.io>
2026-01-27 17:59:12 -05:00
Alexandru Ionut Tripon ec709e339b
fix: remove flatpak submodule (#4878) 2026-01-27 18:32:11 +02:00
Octol1ttle 5de150b8dd
fix: remove flatpak submodule
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-01-27 20:35:53 +05:00
Alexandru Ionut Tripon 915626de9d
Allow overriding URL for downloading legacy FML libs (#4862) 2026-01-27 16:48:01 +02:00
Octol1ttle caec4ef96c
feat: allow overriding URL for downloading legacy FML libs
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-01-27 19:26:02 +05:00
Octol1ttle f0a17d82d9
refactor: FMLLibrariesTask -> LegacyFMLLibrariesTask
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-01-27 19:24:13 +05:00
Alexandru Ionut Tripon 7945a7c626
Make Minecraft resource URL override consistent with other overrides (#4860) 2026-01-27 14:04:24 +02:00
Alexandru Ionut Tripon e4a4d42bca
Remove in-tree flatpak (#4856) 2026-01-27 14:01:53 +02:00
Alexandru Ionut Tripon 4f3c778b4d
PackProfile: don't reset dirty if component list saving failed (#4870) 2026-01-27 13:57:54 +02:00
Alexandru Ionut Tripon 9e4dc64fa9
properly redraw viewport when scroll happens (#4857) 2026-01-27 13:56:01 +02:00
2lay abf3a65695 feat: curseforge modpack downloading via binaryname:// uri
Signed-off-by: 2lay <git@2lay.net>
2026-01-26 19:39:28 +01:00
Octol1ttle c6072ff434
fix(PackProfile): don't reset dirty if component list saving failed
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-01-26 21:53:51 +05:00
Alexandru Ionut Tripon 9776fb8d68
Actions: Use low-cost runner for simple workflows (#4863) 2026-01-25 19:24:54 +02:00
Octol1ttle 70f9b88e45
change(Actions): use low-cost runner for simple workflows
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-01-25 21:09:36 +05:00
Octol1ttle 1cdddd93ad
style: don't use keyword as variable name
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-01-25 17:05:43 +05:00
Octol1ttle 3f0af19ed3
refactor: make Minecraft resource URL override consistent with other overrides
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-01-25 16:45:52 +05:00
Alexandru Ionut Tripon 33deb1da3f
MinecraftSettingsWidget: Swap window width/height spinboxes (#4853) 2026-01-25 10:28:23 +02:00
Alexandru Ionut Tripon 1184a28a05
MSAStep: Tighten isSchemeHandlerRegistered check (#4841) 2026-01-25 10:28:13 +02:00
Trial97 7baaa05683
properly redraw viewport when scroll happens
fixes #1504

Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2026-01-25 10:23:10 +02:00
Seth Flynn 3833b1e292
build(flatpak): remove
See https://github.com/PrismLauncher/flatpak

Signed-off-by: Seth Flynn <getchoo@tuta.io>
2026-01-25 00:44:28 -05:00
github-actions[bot] 6348eafbda chore(nix): update lockfile
Flake lock file updates:

• Updated input 'nixpkgs':
    'https://releases.nixos.org/nixos/25.11/nixos-25.11.2222.b3aad468604d/nixexprs.tar.xz?lastModified=1766201043&narHash=sha256-v9nbQe0BgwBx%2BKcxRf6i2kbS8EwKjBFRjAawA91B/OE%3D&rev=b3aad468604d3e488d627c0b43984eb60e75e782' (2025-12-20)
  → 'https://releases.nixos.org/nixos/25.11/nixos-25.11.4506.078d69f03934/nixexprs.tar.xz?narHash=sha256-Xu%2B7iYcAuOvsI2wdkUcIEmkqEJbvvE6n7qR9QNjJyP4%3D' (2026-01-22)
2026-01-25 00:33:45 +00:00
Octol1ttle dd220e61be
"British roots ending with '-our' usually have '-or' in American English" thanks clion
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-01-24 17:13:48 +05:00
Octol1ttle b4f892cf42
fix(MinecraftSettingsWidget): swap width and height spinboxes to be in their expected positions
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-01-24 17:13:15 +05:00
Alexandru Ionut Tripon 60a3745e50
Print custom environment variables during instance launch (#4832) 2026-01-22 22:49:33 +02:00
Alexandru Ionut Tripon 1a135af7de
refactor: replace std::list with std::vector (#4833) 2026-01-22 22:48:52 +02:00
Alexandru Ionut Tripon 79b76726db
chore(config): migrate Renovate config (#4827) 2026-01-22 22:47:10 +02:00
Alexandru Ionut Tripon 2554c37964
Add asserts to invalid Task states (#4835) 2026-01-22 22:40:43 +02:00
Alexandru Ionut Tripon 8abaea382d
Add missing returns after task signal activation (#4836) 2026-01-22 22:39:43 +02:00
Alexandru Ionut Tripon 2c59b3342c
ModrinthCheckUpdate: Don't send a request that is doomed to fail (#4840) 2026-01-22 22:39:20 +02:00
Octol1ttle 87b3a2ef99
fix(MSAStep): tighten isSchemeHandlerRegistered check
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-01-23 01:00:01 +05:00
Octol1ttle fa040fc959
rename Assert.h because it causes conflicts???
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-01-23 00:34:34 +05:00
Octol1ttle 29afecdbde
ModrinthCheckUpdate: don't send a request that is doomed to fail
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-01-22 22:34:44 +05:00
Octol1ttle 6cb07e203b
fix(ResourceFolderModel): don't read state from off-thread task
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-01-22 22:10:13 +05:00
Octol1ttle 1cd78bf94a
code review
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-01-21 19:15:12 +05:00
Octol1ttle e27246c3f9
fix: add missing returns after emitSucceeded
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-01-21 18:30:31 +05:00
Octol1ttle 507de0fcbd
fix: add missing returns after emitFailed/Aborted
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-01-21 18:30:31 +05:00
Octol1ttle 490df18fd5
Introduce macro to assert and return the assertion condition
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-01-21 18:02:38 +05:00
Octol1ttle 9ac0314d7a
Add asserts to invalid Task states
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-01-21 17:10:14 +05:00
Octol1ttle 06d9079be1
fix: don't manually check for instance overrides
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-01-21 16:11:25 +05:00
Alexandru Ionut Tripon b276ede6e5
initilize world size (#4784) 2026-01-21 12:45:05 +02:00
Octol1ttle 19b9557c19
refactor: replace std::list with std::vector
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-01-21 12:19:55 +05:00
Octol1ttle ca5e1e0f1b
feat: print custom environment variables in log
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-01-21 11:46:59 +05:00
Octol1ttle 2842defe7f
refactor: use variables for string literals
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-01-21 11:46:31 +05:00
renovate[bot] de4d8429be
chore(config): migrate config renovate.json 2026-01-20 17:46:23 +00:00
Alexandru Ionut Tripon ef747055af
Do not delete LaunchController before we're done using it (#4822) 2026-01-20 16:24:57 +02:00
Octol1ttle 4b72870d49
refactor+fix: do not delete LaunchController before we're done using it, unify code for handling LaunchController finishing
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-01-20 15:57:52 +05:00
Alexandru Ionut Tripon f60535dd68
Reformat with editorconfig, add clang-format target (#4556) 2026-01-18 22:57:05 +02:00
Seth Flynn 14df798d78
chore(deps): update azure/trusted-signing-action action to v1 (#4775) 2026-01-18 15:54:55 -05:00
Seth Flynn 70a6d11059
chore(deps): update actions/cache action to v5.0.2 (#4789) 2026-01-18 15:54:16 -05:00
Seth Flynn 5fcd11bec3
hack: resolve dependencies for imageformats on mingw (#4739) 2026-01-18 15:53:55 -05:00
Seth Flynn fd91f87c21
style: re-format tree with editorconfig
```
find $PWD \
  -type f \
  ! -path '*/.git/*' ! -path '*/flatpak/shared-modules/*' \
  ! -path '*/libraries/*' ! -path '*/testdata/*' ! -name '*.patch' \
  ! -name '*.svg' ! -name '*.scd' ! -path '*/program_info/LICENSE' \
  ! -path '*/COPYING.md' ! -path '*/cmake/*' ! -name '.gitmodules' \
  -exec eclint -fix {} \;
```

Signed-off-by: Seth Flynn <getchoo@tuta.io>
2026-01-18 15:48:07 -05:00
Seth Flynn 686ad72e03
build: add clang-format target
Through the power of CMake itself, we can format our files

Signed-off-by: Seth Flynn <getchoo@tuta.io>
2026-01-18 15:48:01 -05:00
Tayou 1c4d378fc4
fix: improve we couldn't launch after 3 tries message (#4805) 2026-01-18 20:25:34 +01:00
Alexandru Ionut Tripon e8b5d49154
Take $GRADLE_USER_HOME into account when looking for JDKs (#4790) 2026-01-18 01:17:46 +02:00
DioEgizio d5da7c9bde fix: improve we couldn't launch after 3 tries message
Signed-off-by: DioEgizio <83089242+DioEgizio@users.noreply.github.com>
2026-01-17 22:05:57 +01:00
DioEgizio a98ec194be hack: resolve dependencies for imageformats on mingw
Signed-off-by: DioEgizio <83089242+DioEgizio@users.noreply.github.com>
2026-01-17 20:45:33 +01:00
Trial97 479d5aff77
add note to FTB page
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2026-01-17 18:15:55 +02:00
Trial97 77f41a2a29
fix build
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2026-01-17 18:15:55 +02:00
Trial97 09f548f688
initilize world size
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2026-01-17 17:34:47 +02:00
Trial97 6a41932e65
add more loaders to ovveride setting
fixes #4624

Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2026-01-17 17:34:05 +02:00
Trial97 e5aa5e298f
remove followSymlinks calls
most probably they were used incorectly anyway

Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2026-01-17 17:31:51 +02:00
Trial97 0b81260cab
update local pack by url
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2026-01-17 17:30:43 +02:00
Trial97 38ac238cfa
fix packwiz log spam
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2026-01-17 17:26:22 +02:00
Trial97 fcc557a79d
add cancel to confirm disable dialog
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2026-01-17 17:26:22 +02:00
Trial97 3b3e246501
only emit changes when the count changes
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2026-01-17 17:26:22 +02:00
Trial97 85071e8919
only emit changes on the modified collumns
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2026-01-17 17:26:22 +02:00
Alexandru Ionut Tripon f3495bc4c0
Apply suggestions from code review
Co-authored-by: TheKodeToad <TheKodeToad@proton.me>
Signed-off-by: Alexandru Ionut Tripon <alexandru.tripon97@gmail.com>
2026-01-17 17:26:22 +02:00
Trial97 67a724f990
improve toggle message
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2026-01-17 17:26:22 +02:00
Trial97 35750ebada
update toggle message box
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2026-01-17 17:26:22 +02:00
Trial97 1735814d42
add confirmation dialog
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2026-01-17 17:26:22 +02:00
Alexandru Ionut Tripon 8c824ed3d6
Update launcher/minecraft/mod/ModFolderModel.cpp
Co-authored-by: TheKodeToad <TheKodeToad@proton.me>
Signed-off-by: Alexandru Ionut Tripon <alexandru.tripon97@gmail.com>
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2026-01-17 17:26:22 +02:00
Trial97 c9426da64d
Update launcher/minecraft/mod/ModFolderModel.cpp
Co-authored-by: TheKodeToad <TheKodeToad@proton.me>
Signed-off-by: Alexandru Ionut Tripon <alexandru.tripon97@gmail.com>
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2026-01-17 17:26:21 +02:00
Trial97 1a82a83e36
rework parse dependency function
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2026-01-17 17:26:21 +02:00
Trial97 36e540ed11
fix toggle action
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2026-01-17 17:26:21 +02:00
Trial97 ba4d9cadc4
change to QSet to remove duplicates
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2026-01-17 17:26:21 +02:00
Trial97 947656df0f
feat: display mod dependencies
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2026-01-17 17:26:21 +02:00
Trial97 66f0f95fd7
feat: make dependencies auto disable/enable
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2026-01-17 17:26:21 +02:00
Trial97 22539a4ff8
feat: add requireBy and requires columns
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2026-01-17 17:26:21 +02:00
Trial97 bacce134c0
feat: store provider dependencies
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2026-01-17 17:26:21 +02:00
Trial97 8cf41be77f
feat: decode dependencies from mod jar
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2026-01-17 17:26:21 +02:00
Trial97 7ee4b35aee
chore: update link and sync with other providers changes
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2026-01-17 17:25:20 +02:00
Trial97 c27bc436da
Revert "chore: remove FTB modpack support"
This reverts commit ff07714e8c.

Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2026-01-17 17:25:20 +02:00
Alexandru Ionut Tripon 2e8256e322
fix ftb import for old packs (#4787) 2026-01-17 17:03:59 +02:00
Sefa Eyeoglu ff34760868
fix build (#4795) 2026-01-17 15:41:57 +01:00
Trial97 d05b996c8a
fix build
also fixed some warninigs of unused vars and formated the code again

Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2026-01-17 02:28:56 +02:00
Alexandru Ionut Tripon 78bc6657f4
Allow moving accounts in list (#4647) 2026-01-17 02:08:19 +02:00
Alexandru Ionut Tripon edf1840225
Add icons in settings account list (#4684) 2026-01-17 02:08:02 +02:00
Trial97 3496b7b3a0
fix ftb import for old packs
fixes #4786

Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2026-01-17 01:22:25 +02:00
TheKodeToad 6848d60cad
refactor!!!: migrate from shared pointers (#4673) 2026-01-16 20:32:17 +00:00
SandaruKasa 267e8f1d33 Take $GRADLE_USER_HOME into account when looking for JDKs
Signed-off-by: SandaruKasa <sandarukasa@ya.ru>
2026-01-16 21:16:14 +03:00
renovate[bot] 70de524c3a
chore(deps): update actions/cache action to v5.0.2 2026-01-16 17:59:15 +00:00
renovate[bot] 3ce765fba0
chore(deps): update azure/trusted-signing-action action to v1 2026-01-15 02:07:09 +00:00
Alexandru Ionut Tripon 5f89187719
Fix instance and settings window minimum size (#4769) 2026-01-14 23:24:12 +02:00
Alexandru Ionut Tripon 07100658a8
Allow opting out of pre-compiled headers (#4768) 2026-01-14 23:21:26 +02:00
TheKodeToad d283726494
Fix new instance window being too large
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2026-01-14 17:07:58 +00:00
TheKodeToad 40c6f79b5f
Fix settings window being too large
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2026-01-14 17:07:58 +00:00
TheKodeToad 90e3c59bd8
Fix JavaWizardWidget compilation without PCH
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2026-01-14 16:20:32 +00:00
TheKodeToad 3a16cf3081
Allow toggling pre-compiled headers
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2026-01-14 16:20:26 +00:00
Alexandru Ionut Tripon 9ced66e990
Fix for Prism failing to recognize some shader pack ZIP archives added manually by the user (#4745) 2026-01-14 13:51:47 +02:00
Alexandru Ionut Tripon 2f1ab0162b
IconList: Make sure we always set new path (#4753) 2026-01-14 13:50:46 +02:00
Alexandru Ionut Tripon 5a9382d29b
chore: make appimage use portals for file picking (#4759) 2026-01-14 13:50:29 +02:00
Alexandru Ionut Tripon 35e64ae2c6
accept libarchive warning result (#4761) 2026-01-14 13:50:01 +02:00
Trial97 a6d6ff9926
accept libarchive warning result
this is the intended behavior to treat warnings as ok, because
teoretically the file was extracted, even if the time of the file can't
be set

Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2026-01-14 00:17:17 +02:00
DioEgizio 1b15643fcd chore: make appimage use portals for file picking
much better than Qt's ugly default one

Signed-off-by: DioEgizio <83089242+DioEgizio@users.noreply.github.com>
2026-01-13 15:35:58 +01:00
Seth Flynn c2fc0a30b7
Free up disk space on Flatpak builds so they don't crash (#4755) 2026-01-13 01:14:57 -05:00
Octol1ttle eafce5d5f6
hack: try to free up disk space on Flatpak builds so they don't crash
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-01-12 23:30:14 +05:00
Alexandru Ionut Tripon 92a2e3b894
auth: improve status messages (#4750) 2026-01-12 20:11:52 +02:00
Octol1ttle 6cbedbe184
fix(IconList): make sure we always set new path
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-01-12 23:00:45 +05:00
SwitchAxe 809e766aec Fixed formatting
Signed-off-by: SwitchAxe <sofiacerasuoli@gmail.com>
2026-01-12 16:44:01 +01:00
SwitchAxe 7f0f90fcce Improved the check for the assets dir
Signed-off-by: SwitchAxe <sofiacerasuoli@gmail.com>
2026-01-12 14:43:54 +01:00
Octol1ttle 6cddc28e9b
auth: improve status messages
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-01-12 16:48:46 +05:00
SwitchAxe 8aba994312 Made the loop more efficient
Signed-off-by: SwitchAxe <sofiacerasuoli@gmail.com>
2026-01-12 03:36:52 +01:00
Sofia 6321db5942
Update launcher/minecraft/mod/tasks/LocalShaderPackParseTask.cpp
Co-authored-by: Octol1ttle <l1ttleofficial@outlook.com>
Signed-off-by: Sofia <75943257+SwitchAxe@users.noreply.github.com>
2026-01-12 03:25:43 +01:00
SwitchAxe 6ac9de7a11 Fixed Indentation
Signed-off-by: SwitchAxe <sofiacerasuoli@gmail.com>
2026-01-12 02:35:36 +01:00
SwitchAxe 9a93696915 Added support for shader packs with a top-level parent directory
Signed-off-by: SwitchAxe <sofiacerasuoli@gmail.com>
2026-01-12 02:13:56 +01:00
Alexandru Ionut Tripon 5a6f94fe79
Update copyright year (#4740) 2026-01-12 00:22:13 +02:00
Alexandru Ionut Tripon b7e508870d
Set current auth step description in correct method (#4733) 2026-01-12 00:22:01 +02:00
Alexandru Ionut Tripon 73dc92cedd
Fix auto-join getting stuck disabled (#4711) 2026-01-12 00:21:51 +02:00
Trial97 508a66aedd
Update copyright year
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2026-01-12 00:00:56 +02:00
Octol1ttle 01c1840531
refactor(InstanceList): use vector<unique_ptr> to store instances
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-01-11 21:00:04 +05:00
Octol1ttle c24fd2f570
refactor(instance creation): use RAII lock to suspend instance settings saving
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-01-11 21:00:04 +05:00
Octol1ttle 3937819305
CapeChange: use dummy sink
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-01-11 21:00:04 +05:00
Octol1ttle 549405ab2f
refactor!!!: migrate from shared pointers
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-01-11 21:00:03 +05:00
Octol1ttle f0813b578e
fix(AuthFlow): set current step description in correct method
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-01-11 20:05:00 +05:00
Alexandru Ionut Tripon c64d871a28
Network: log server response on error (#4726) 2026-01-11 15:19:26 +02:00
Alexandru Ionut Tripon 136ad59fad
Fix environment variables always being discarded and custom commands always being overriden (#4718) 2026-01-11 15:19:17 +02:00
Alexandru Ionut Tripon 2b04da0c36
Fix shaderpacks folder being hidden (#4707) 2026-01-11 15:19:00 +02:00
Octol1ttle 7f3790bf73
change(NetRequest): log server response on error
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-01-11 00:19:10 +05:00
Alexandru Ionut Tripon 62e17cd19e
fix modrinth environments filter (#4704) 2026-01-10 18:36:38 +02:00
TheKodeToad cbe77872fa
Bump to 10.0.2 (#4713)
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2026-01-09 15:57:24 -07:00
Sefa Eyeoglu 100b2aa6da
format the code (#4717) 2026-01-09 22:36:35 +01:00
TheKodeToad 01228cc0b7
Fix broken EnvironmentVariables and CustomCommands when tab is inactive
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2026-01-09 21:13:12 +00:00
Trial97 53acc60983
format the code
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2026-01-09 22:28:25 +02:00
Mark Deneen 133842d6a8
Disable tooltips if using gamescope / Steam Deck. (#4096)
* Disable tooltips if using gamescope / Steam Deck.

On a Steam Deck, Prism Launcher's window is scaled to fit the screen.
Whenever a tool tip is shown, it is often display outside of the window,
causing the compositor to scale the view to fit the new bounding box.

This effect is quite jarring, and I don't like it.  This patch adds a
small global event filter which swallows up the tool tip events.  It is
currently not configurable, although I suppose that could be an option.

Signed-off-by: Mark Deneen <mdeneen@gmail.com>

* Move tooltip filter addition from the Main Window to the Application.

Signed-off-by: Mark Deneen <mdeneen@gmail.com>

* Add license information to new files

Signed-off-by: Mark Deneen <mdeneen@gmail.com>

* Remove other authors, they should not have been added in the first place

Signed-off-by: Mark Deneen <mdeneen@gmail.com>

* Correct the years as well

Signed-off-by: Mark Deneen <mdeneen@gmail.com>

* Update launcher/ui/ToolTipFilter.cpp

Co-authored-by: Alexandru Ionut Tripon <alexandru.tripon97@gmail.com>
Signed-off-by: Mark Deneen <mdeneen@gmail.com>

* Update launcher/ui/ToolTipFilter.h

Co-authored-by: Alexandru Ionut Tripon <alexandru.tripon97@gmail.com>
Signed-off-by: Mark Deneen <mdeneen@gmail.com>

---------

Signed-off-by: Mark Deneen <mdeneen@gmail.com>
Co-authored-by: Alexandru Ionut Tripon <alexandru.tripon97@gmail.com>
2026-01-09 22:13:45 +02:00
Alexandru Ionut Tripon 99c5c7b990
remove curseforge api key validation (#4700) 2026-01-09 22:13:08 +02:00
Alexandru Ionut Tripon 1d659b5c68
fix jpg icons (#4706) 2026-01-09 22:12:58 +02:00
TheKodeToad c7501b747e
fix curseforge import (#4699) 2026-01-09 19:24:21 +00:00
TheKodeToad e856f60804
Fix auto-join getting stuck disabled
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2026-01-09 18:42:46 +00:00
Trial97 3f53670cc2
fix jpg icons
fixes #4686 and fixes #4666
Forces jpg and jpeg to go through QPixmap first then to Icon.
The original behaivior used the QIcon internal engine to build the
QPixmap causing some inconsitencies.

Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2026-01-09 16:36:05 +02:00
TheKodeToad 3e7ef5ee17
Fix shaderpacks folder being hidden on Windows
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2026-01-09 13:54:14 +00:00
Trial97 a97c15d0fb
fix modrinth environments filter
fixes #4630
reversed the conditions to check for side because somewhere the mod side
is no initilized(easier to check one line than search where it is not
initialized)

Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2026-01-09 12:07:03 +02:00
Trial97 7f952d9fdf
remove curseforge api key validation
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2026-01-08 23:34:06 +02:00
Trial97 398689637d
fix curseforge import
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2026-01-08 23:12:31 +02:00
Alexandru Ionut Tripon 3b1a5dd3c0
Remove prismlauncher-qt5-git badge from README (#4696) 2026-01-08 18:24:13 +02:00
Elliott Tallis ada0401137
Remove prismlauncher-qt5-git badge from README
AUR has been deleted since Qt 5 builds are no longer possible

Signed-off-by: Elliott Tallis <tallis.elliott@gmail.com>
2026-01-08 15:54:24 +00:00
Alexandru Ionut Tripon 3e5990f8ec
Update build instructions links in README (#4688) 2026-01-07 21:34:27 +02:00
Dylan Renwick e91d05922a
Update build instructions links in README
Signed-off-by: Dylan Renwick <skidsirongenesisdev@gmail.com>
2026-01-07 14:08:01 -05:00
Octol1ttle fa88edf8c3
Use real move instead of remove-then-insert
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>

Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-01-07 20:21:03 +05:00
TheKodeToad 9be292b845
Use AccountList as model in ProfileSelectDialog
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2026-01-07 11:28:41 +00:00
TheKodeToad fc1e29111b
Add icons to account list
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2026-01-07 11:28:38 +00:00
Alexandru Ionut Tripon d191f83a62
Check that mouse press is inside view rectangle of CheckComboBox (#4681) 2026-01-07 12:26:22 +02:00
Alexandru Ionut Tripon 6ae06249cb
Skip asking for offline name when using offline account (#4680) 2026-01-07 12:25:53 +02:00
Octol1ttle 39e283169e
fix(CheckComboBox): check that mouse press is inside view rectangle
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-01-07 14:03:38 +05:00
Octol1ttle 2e6efab913
fix: skip asking for offline name when using offline account
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-01-07 13:27:04 +05:00
Seth Flynn c3bcfec5e4
Fix AppImage zsync information (#4671) 2026-01-06 18:52:32 -05:00
Seth Flynn 4037446051
build(appimage): use tag for version when available
Signed-off-by: Seth Flynn <getchoo@tuta.io>
2026-01-06 18:40:20 -05:00
Octol1ttle 40af45bb1c
feat: allow moving accounts in list
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>

Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-01-07 04:17:47 +05:00
Seth Flynn 20055aa2fa
Automatically use vcpkg to build on macOS and Windows (#4670) 2026-01-06 17:38:07 -05:00
Seth Flynn 44bf3aad29
build(macos/windows): automatically use vcpkg
Previously `CMAKE_TOOLCHAIN_FILE` needed to be set manually, which was
kinda pointless when vcpkg is already installed and meant to be used

Signed-off-by: Seth Flynn <getchoo@tuta.io>
2026-01-06 17:08:44 -05:00
Alexandru Ionut Tripon 31da9f51f0
Don't use .index for shaderpacks (#4658) 2026-01-06 23:53:17 +02:00
Alexandru Ionut Tripon 3b967ee195
Bump to 10.0.1 (#4662) 2026-01-06 23:36:55 +02:00
TheKodeToad 3a7366a998
Fix oversights and make requested changes
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2026-01-06 20:16:46 +00:00
TheKodeToad e4991d81d7
Avoid some errors (less noisy log)
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2026-01-06 17:55:44 +00:00
TheKodeToad 398305eb66
Less destructive delete
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2026-01-06 17:54:16 +00:00
TheKodeToad ea7122b641
Bump to 10.0.1
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2026-01-06 17:49:45 +00:00
TheKodeToad d625a28112
Properly show shaderpacks in export
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2026-01-06 16:47:05 +00:00
TheKodeToad 1cf48dfd85
Don't use .index for shaderpacks
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2026-01-06 15:05:23 +00:00
Alexandru Ionut Tripon 639268798b
fix manifest generation for linux (#4649) 2026-01-06 17:01:44 +02:00
Alexandru Ionut Tripon db0bdc6bed
Modified the plist to categorize it as a game [Mac] (#4619) 2026-01-06 14:19:11 +02:00
Alexandru Ionut Tripon 318a12cee6
change(program_info): more brand unhardcoding (#4648) 2026-01-06 14:16:17 +02:00
Alexandru Ionut Tripon 9b7630485f
use libarchive to extract release files (#4641) 2026-01-06 14:15:35 +02:00
Trial97 681c635f0e
fix manifest generation for linux
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2026-01-06 14:01:51 +02:00
Octol1ttle abd482db4a
change(program_info): unhardcode brand from macOS bundle GUI identifier
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-01-06 16:54:46 +05:00
Octol1ttle c46eaec046
change(program_info): unhardcode brand from Windows files
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-01-06 16:54:13 +05:00
Alexandru Ionut Tripon d6942089cd
Change enum style guideline to PascalCase (#4623) 2026-01-06 12:57:23 +02:00
Alexandru Ionut Tripon 009b65cc1d
refactor: remove broken Qt includes (#4643) 2026-01-06 12:54:42 +02:00
Octol1ttle 56392a20ed
refactor: remove broken Qt includes
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-01-06 15:51:47 +05:00
Trial97 7b0896a0b9
use libarchive to extract release files
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2026-01-06 12:51:23 +02:00
Alexandru Ionut Tripon b32bc08b34
ci: actually sign windows builds in Release env (#4632) 2026-01-05 20:34:47 +02:00
Seth Flynn 939093d648
ci: actually sign windows builds in Release env
Signed-off-by: Seth Flynn <getchoo@tuta.io>
2026-01-05 13:32:03 -05:00
TheKodeToad 55102d4113
Change enum style guideline to PascalCase
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2026-01-04 10:16:28 +00:00
David Kaluta 094425552b
Modified the plist to categorize it as a game
Signed-off-by: David Kaluta <mail@dkaluta.com>
2026-01-02 13:42:41 +02:00
Alexandru Ionut Tripon fe2e171fa1
feat: use Qt 6.10.1 outside mac and use sharun for portable builds too (#4599) 2025-12-31 14:25:26 +02:00
DioEgizio 36ffd6b4ee chore: bump to ubuntu 24.04
no reason to keep using 22.04 with sharun

Signed-off-by: DioEgizio <83089242+DioEgizio@users.noreply.github.com>
2025-12-31 09:18:15 +01:00
DioEgizio 015ee05311 chore: simplify Launcher.in quite a bit
not necessary anymore with sharun

Signed-off-by: DioEgizio <83089242+DioEgizio@users.noreply.github.com>
2025-12-31 09:18:15 +01:00
DioEgizio 20f9784881 feat: Qt 6.10.1 outside macOS
Signed-off-by: DioEgizio <83089242+DioEgizio@users.noreply.github.com>
2025-12-31 09:18:15 +01:00
Alexandru Ionut Tripon 840bed0666
Include ARM Linux portable builds in releases (#4609) 2025-12-31 08:46:41 +02:00
Alexandru Ionut Tripon 7e4e1de68e
Remove some CI jobs (#4608) 2025-12-31 08:43:07 +02:00
Alexandru Ionut Tripon 3aab71ea3d
ci: use Release env for releases (#4605) 2025-12-31 08:36:39 +02:00
Alexandru Ionut Tripon b9e8ddac2b
Add qtimageformats to Nix wrapper (#4606) 2025-12-31 08:35:13 +02:00
Seth Flynn c059e812a0
ci: fail releases on unmatched files
This previously let bugs slip in, like not uploading the Linux ARM
tarball

Signed-off-by: Seth Flynn <getchoo@tuta.io>
2025-12-30 20:47:58 -05:00
Seth Flynn d4230349e3
ci: upload portable linux arm tarball to releases
Signed-off-by: Seth Flynn <getchoo@tuta.io>
2025-12-30 20:47:35 -05:00
Seth Flynn abe0c8e687
ci(flatpak): only build for x86_64
The flatpaks from CI aren't very usable in the first place, but also
take longer to complete than regular builds, as well as contribute to
our concurrent job limit. Dropping ARM builds shouldn't have much
impact, but this can obviously be reversed if people want it

Signed-off-by: Seth Flynn <getchoo@tuta.io>
2025-12-30 20:07:56 -05:00
Seth Flynn 698e1dd7cf
ci(nix): don't build for intel macs
These are being dropped by Nixpkgs itself soon in the near future, with
few users (on top of reduced usage of our flake/cache). We also already
have coverage for macOS builds through the aarch64-darwin target, so
this doesn't have a big impact on our end either

Obviously can be reverted if enough people want it

Signed-off-by: Seth Flynn <getchoo@tuta.io>
2025-12-30 20:07:41 -05:00
Seth Flynn df1573abfd
chore: use go-appimage soft fork until the pgp pr is merged (#4588) 2025-12-30 19:56:01 -05:00
Seth Flynn 99d00957b7
fix(nix): add qtimageformats to wrapper
Signed-off-by: Seth Flynn <getchoo@tuta.io>
2025-12-30 19:52:11 -05:00
Seth Flynn 44e927a69e
ci: only sign windows artifacts in Release environment
`CI_HAS_ACCESS_TO_AZURE` is only set in our Release env

Signed-off-by: Seth Flynn <getchoo@tuta.io>
2025-12-30 19:35:30 -05:00
Seth Flynn d1313cbd2d
ci: use Release env for releases
This ensures we have access to Azure on CI runs for tags

Signed-off-by: Seth Flynn <getchoo@tuta.io>
2025-12-30 19:32:38 -05:00
DioEgizio 16635ca9fc feat: use sharun for portable builds too
Signed-off-by: DioEgizio <83089242+DioEgizio@users.noreply.github.com>
2025-12-29 08:42:14 +01:00
DioEgizio 57c4b71c61 fix: improve a bit the FTB packs are also on cf notice
Co-authored-by: TheKodeToad <TheKodeToad@proton.me>
Signed-off-by: DioEgizio <83089242+DioEgizio@users.noreply.github.com>
2025-12-27 15:10:30 +01:00
DioEgizio 31dd8cd9f8 chore: add new ftb packs are also on cf notice
Signed-off-by: DioEgizio <83089242+DioEgizio@users.noreply.github.com>
2025-12-27 15:10:30 +01:00
Alexandru Ionut Tripon 993da92199
feat: Use precompiled headers for 130-180% speedup (#4494) 2025-12-26 23:41:37 +02:00
Alexandru Ionut Tripon e3c79b3427
CMakeLists: fix ASan compile options (#4590) 2025-12-26 23:40:31 +02:00
Alexandru Ionut Tripon 91bd74198e
fix(APIPage.ui): resolve duplicate name (#4591) 2025-12-26 23:40:11 +02:00
Octol1ttle de092922d7
fix(APIPage.ui): resolve duplicate name
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2025-12-26 20:06:05 +05:00
Octol1ttle 1fdc33669b
CMakeLists: fix ASan compile options
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2025-12-26 19:57:44 +05:00
DioEgizio a4b142681d chore: use go-appimage soft fork until the pgp pr is merged
revert this once it's merged!

Signed-off-by: DioEgizio <83089242+DioEgizio@users.noreply.github.com>
2025-12-26 15:27:18 +01:00
Alexandru Ionut Tripon 8e3be68c65
Force disable xrandr if it is unavailable (#4578) 2025-12-26 12:10:39 +02:00
Blake Batson e0c2fbbcde Force disable xrandr if it is unavailable
lwjgl2 optionally requires the xrandr command line utility on linux, but
does not check if the executable actually exists before trying to use
it. We can force it to fall back to the xf86videomode implementation
by checking for the executable ourselves, and force disabling xrandr
with this boolean [1] if it does not exist.

Link: 2df01dd762/src/java/org/lwjgl/opengl/LinuxDisplay.java (L214) [1]
Signed-off-by: Blake Batson <bbatson101@gmail.com>
2025-12-25 14:09:50 -05:00
Alexandru Ionut Tripon 76d1cd1b4e
fix mod update remaining disabled on second open (#4573) 2025-12-24 00:10:32 +02:00
Alexandru Ionut Tripon 072eaa32ec
preserve original file extension when importing modpack icon (#4565) 2025-12-23 22:44:53 +02:00
Trial97 7f68f2fe3b
fix mod update remaining disabled on second open
fixes
https://discord.com/channels/1031648380885147709/1450161125172707390/1453013386144124929
basically when opening the edit window a second time the model doesn't
get any updates as the data is already loaded into the memory.

Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2025-12-23 22:32:52 +02:00
Alexandru Ionut Tripon c59db39e06
match disabled mods on uninstall (#4544) 2025-12-22 23:55:25 +02:00
Alexandru Ionut Tripon d18a6909c1
fix Pre-release filter (#4563) 2025-12-22 23:45:37 +02:00
Trial97 8e96beeda0
preserve original file extension when importing modpack icon
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2025-12-22 22:50:43 +02:00
Alexandru Ionut Tripon 9504ed500a
build(mingw): use dwarf debug info (#4554) 2025-12-22 20:12:16 +02:00
Trial97 b1408775b3
fix Pre-release filter
introduced here https://github.com/PrismLauncher/PrismLauncher/pull/3260
fixes #4415
reason: some snapshot have Pre-Release in our meta but when searching in
Modrinth this needs to be translated to -pre and the reverse needed to
be done for filtering after we fetched the version.
Now there are snapshots with -pre in name and that works with Modrinth
but when we translate it back we replace it with Pre-Release so the
easeiest patch is just to double the version(one with -pre one with
Pre-Release)

The correct one would be to complicate the code and identify the
versions that need the transition and only apply this for those.

Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2025-12-22 19:55:47 +02:00
Alexandru Ionut Tripon 8a84f5fc1d
fix legacy skin model (#4511) 2025-12-22 19:32:25 +02:00
Alexandru Ionut Tripon c723b3abe8
Update launcher/minecraft/skins/SkinModel.cpp
Co-authored-by: DioEgizio <83089242+DioEgizio@users.noreply.github.com>
Signed-off-by: Alexandru Ionut Tripon <alexandru.tripon97@gmail.com>
2025-12-22 18:22:32 +02:00
Trial97 4b96c5736c
add copyright for modrinth code
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2025-12-22 18:20:06 +02:00
timoreo c7bf324e64
build(nix): use nixos-25.11 channel for nixpkgs (#4559) 2025-12-22 17:00:36 +01:00
Seth Flynn 5ee33814b6
build(nix): use nixos-25.11 channel for nixpkgs
This makes `clangd` work again, thanks to
https://github.com/NixOS/nixpkgs/pull/462747

• Updated input 'nixpkgs':
    'github:NixOS/nixpkgs/c6245e83d836d0433170a16eb185cefe0572f8b8' (2025-12-18)
  → 'https://releases.nixos.org/nixos/25.11/nixos-25.11.2222.b3aad468604d/nixexprs.tar.xz?lastModified=1766201043&narHash=sha256-v9nbQe0BgwBx%2BKcxRf6i2kbS8EwKjBFRjAawA91B/OE%3D&rev=b3aad468604d3e488d627c0b43984eb60e75e782' (2025-12-20)

Signed-off-by: Seth Flynn <getchoo@tuta.io>
2025-12-22 10:27:11 -05:00
Seth Flynn ea84621d2f
Make blocked/stacked pr detection more flexible with capitalization (#4557) 2025-12-22 09:54:56 -05:00
Seth Flynn d85ff94f03
build(mingw): use dwarf debug info
As it turns out, LLDB can load Windows crash dumps!

This allows us go back to the regular (better supported) DWARF debuginfo
format used by MinGW, as now we have a tool that can both parse those
symbols *and* Windows' crash dumps. The biggest advantage here is that
once again, MinGW crash dumps can be easily inspected on Linux

Signed-off-by: Seth Flynn <getchoo@tuta.io>
2025-12-22 09:53:42 -05:00
Seth Flynn 39c4e7c79b
fix(build): handle CMAKE_BUILD_TYPE with generator expressions (#4553) 2025-12-22 09:50:19 -05:00
Rachel Powers 586364e3b6
Make blocked/stacked pr detection more flexible with capitalization
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2025-12-22 02:51:58 -07:00
Seth Flynn 85849fea41
fix(build): handle CMAKE_BUILD_TYPE with generator expressions
Since we've started using ninja's multi-config generator, evaluating
CMAKE_BUILD_TYPE at configure-time is no longer reliable. Thankfully,
CMake offers "generator expressions" that are evaluated during build
system generation, which allows us to continue using these conditional
flags without much headache

Signed-off-by: Seth Flynn <getchoo@tuta.io>
2025-12-22 03:21:10 -05:00
Alexandru Ionut Tripon ee21ad836f
fix modrinth modpack allways download latest (#4549) 2025-12-22 10:09:42 +02:00
Trial97 d7745d97f2
fix modrinth modpack allways download latest
fixes #4547
introduced by #3828
made a mistake to use addonId instead ov fileId
this only applies to modrinth
on curseforge I could not reproduce this bug

Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2025-12-21 22:45:57 +02:00
Alexandru Ionut Tripon 49b66d8a54
chore(nix): update lockfile (#4545) 2025-12-21 09:50:46 +02:00
timoreo 52240cc64c
fix accounts crash (#4543) 2025-12-21 05:33:14 +01:00
github-actions[bot] 6732d7f99c chore(nix): update lockfile
Flake lock file updates:

• Updated input 'nixpkgs':
    'github:NixOS/nixpkgs/2fbfb1d73d239d2402a8fe03963e37aab15abe8b?narHash=sha256-9VvC20PJPsleGMewwcWYKGzDIyjckEz8uWmT0vCDYK0%3D' (2025-12-11)
  → 'github:NixOS/nixpkgs/c6245e83d836d0433170a16eb185cefe0572f8b8?narHash=sha256-G/WVghka6c4bAzMhTwT2vjLccg/awmHkdKSd2JrycLc%3D' (2025-12-18)
2025-12-21 00:31:41 +00:00
Trial97 08c45684de
match disabled mods on uninstall
fixes #4537
This ensures that when looking to uninstall a resource prism will
consider the disabled ones to.
Right now we have a guard in place to prevent resources using the same
name so this check will allways match with the correct resouce.

Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2025-12-20 23:54:31 +02:00
Trial97 f4b22dae90
fix accounts crash
fixes #4541
introduced in
3c46d8a412
The original commit introduced m_name but never used it.
When the endActivity would be called with a count of 0 this would crash
the laucnher.
How to reproduce: try to switch your skin in quick succession until you
get 429 too many requests as response to the login.
I will also presume this is not the only crash caused by this(hopefully
it is as it was not catched for four years)

Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2025-12-20 23:23:27 +02:00
Alexandru Ionut Tripon d3f59a8a43
fix(skin-preview): smoother chessboard background contrast (#4534) 2025-12-20 18:51:04 +02:00
Tayou 5c6c92f286
fix skin preview leg rendering (#4538) 2025-12-20 13:00:06 +01:00
Tayou fcf201755c
fix skin preview leg rendering
Signed-off-by: Tayou <git@tayou.org>
2025-12-20 08:50:49 +01:00
Rachel Powers 42b72d676c
fix(skin-preview): smoother chessboard background contrast
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2025-12-19 16:53:31 -07:00
Alexandru Ionut Tripon 877b824c3b
fix skin depth (#4524) 2025-12-19 20:26:51 +02:00
Alexandru Ionut Tripon 2f540ffc61
fix elytra preview (#4525) 2025-12-19 20:26:35 +02:00
Seth Flynn 53fbc39ad1
Use sharun to bundle AppImage (#4515) 2025-12-19 03:43:51 -05:00
Alexandru Ionut Tripon d1df515bcc
Updated App icon for macOS 26 (#4160) 2025-12-19 10:37:25 +02:00
Trial97 e360a95c23
fix elytra preview
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2025-12-19 01:14:19 +02:00
Trial97 624d506fac
fix skin depth
The skin overlay was drawn together with the original skin making it
blend weirdly. By drawing the overlay after the skin this blends with
the body corectly.

Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2025-12-19 00:01:39 +02:00
Alexandru Ionut Tripon 53e090f035
Trim unexpected info from pack.mcmeta (#4522) 2025-12-18 23:51:15 +02:00
Dylan Schooner 51b47050f9 Check specifically for GarbageAtEnd error
- Out parameter for garbage data\n- Rename parseUntilMalformed to parseUntilGarbage

Signed-off-by: Dylan Schooner <dschooner05@gmail.com>
2025-12-18 15:23:48 -05:00
Dylan Schooner 9c7fe72f9c Use Json::parseUntilMalformed in McClient::parseResponse
Signed-off-by: Dylan Schooner <dschooner05@gmail.com>
2025-12-18 14:14:29 -05:00
Dylan Schooner e1eee6e3ca Add Json::parseUntilMalformed helper
Signed-off-by: Dylan Schooner <dschooner05@gmail.com>
2025-12-18 13:33:13 -05:00
Dylan Schooner 43fce3ae46 Trim unexpected info from pack.mcmeta
Signed-off-by: Dylan Schooner <dschooner05@gmail.com>
2025-12-18 12:34:41 -05:00
Alexandru Ionut Tripon 018ff600f6
Use static image when opengl context is not available (#4509) 2025-12-18 13:21:00 +02:00
Seth Flynn 5d5f22e672
ci(linux): verify appstream info for appimages
Signed-off-by: Seth Flynn <getchoo@tuta.io>
2025-12-17 23:53:47 -05:00
Seth Flynn e39e59acb6
revert: "fix(launcher): set correct bin path for self-contained appimages"
Refs: b1b4b5d
Signed-off-by: Seth Flynn <getchoo@tuta.io>
2025-12-17 23:53:47 -05:00
Seth Flynn 1d8bf82ef8
revert: "fix(appimage): launch external processes with bundled linker"
Refs: c305ed4
Signed-off-by: Seth Flynn <getchoo@tuta.io>
2025-12-17 23:53:46 -05:00
Seth Flynn 06e99e2990
build(linux): use sharun for appimage bundling
This should fix issues with OpenGL, as well as help as avoid using some
annoying (and fragile) hacks to locate our actual binary/other resources

Signed-off-by: Seth Flynn <getchoo@tuta.io>
2025-12-17 23:53:42 -05:00
Trial97 f7111b6ec1
fix legacy skin model
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2025-12-17 00:03:19 +02:00
Alexandru Ionut Tripon 3c570f9e9c
Update launcher/ui/dialogs/skins/SkinManageDialog.cpp
Signed-off-by: Alexandru Ionut Tripon <alexandru.tripon97@gmail.com>
2025-12-16 20:56:41 +02:00
Alexandru Ionut Tripon 1dd8c9606f
server player req: parse malformed json (#4512) 2025-12-16 16:35:20 +02:00
Tayou 5ebd386797
server player req: parse malformed json
ATM10 server seems to send a extra json object after the default response, that we need to cut off.
Signed-off-by: Tayou <git@tayou.org>
Co-authored-by: Trial97 <alexandru.tripon97@gmail.com>
2025-12-16 14:51:01 +01:00
Trial97 177e7b272b
Use static image when opengl context is not available
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2025-12-16 13:36:28 +02:00
Alexandru Ionut Tripon 8cfed54399
fix: actually fix toml++ on fedora (#4506) 2025-12-16 10:27:25 +02:00
DioEgizio 9aa1a4d11b fix: actually fix toml++ on fedora
oops

Signed-off-by: DioEgizio <83089242+DioEgizio@users.noreply.github.com>
2025-12-16 08:44:56 +01:00
Alexandru Ionut Tripon 92a12b5617
chore(deps): update korthout/backport-action action to v4.0.1 (#4500) 2025-12-16 08:50:49 +02:00
renovate[bot] 981b3fc48e
chore(deps): update korthout/backport-action action to v4.0.1 2025-12-15 18:07:32 +00:00
Rachel Powers e53093c4b4
feat: Use pre-compiled headers
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2025-12-14 21:15:23 -07:00
Richard Voigtmann e7f801c4c4
Add suggestion from code review
Co-authored-by: DioEgizio <83089242+DioEgizio@users.noreply.github.com>
Signed-off-by: Richard Voigtmann <71901885+ShadowPaint-SP@users.noreply.github.com>
2025-12-14 11:07:19 +01:00
Richard Voigtmann e46b0335ab xCode version check
Signed-off-by: Richard Voigtmann <richard.v.voigtmann@gmail.com>
2025-12-14 09:46:53 +01:00
Richard Voigtmann e125f4767f removed unnecessary Option from actool command and failsafe attempt for older versions
Signed-off-by: Richard Voigtmann <richard.v.voigtmann@gmail.com>
2025-12-14 02:14:27 +01:00
Richard Voigtmann 7f740e4ad6 added mono to brew because macos 26 runner doesnt include it
Signed-off-by: Richard Voigtmann <richard.v.voigtmann@gmail.com>
2025-12-13 21:50:40 +01:00
Richard Voigtmann 7cb623e800 bumped macos runner version to 26
Signed-off-by: Richard Voigtmann <richard.v.voigtmann@gmail.com>
2025-12-13 15:57:58 +01:00
Richard Voigtmann d53b785a1c implemented recommended changes -reverted .icns file instellation
Signed-off-by: Richard Voigtmann <richard.v.voigtmann@gmail.com>
2025-12-12 16:12:00 +01:00
Richard Voigtmann a7dd3aeaab replaced binary with in ci building of Icons
Signed-off-by: Richard Voigtmann <richard.v.voigtmann@gmail.com>
2025-12-11 11:58:11 +01:00
TheKodeToad 283d49ba35
Merge remote-tracking branch 'upstream/develop' into desysteminfo
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2025-12-07 11:58:21 +00:00
TheKodeToad 19aab36a4d
Merge branch 'develop' into desysteminfo
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2025-11-23 16:23:27 +00:00
TheKodeToad 5465f17916
Check for __clang__ too
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2025-11-15 10:33:27 +00:00
Dylan Schooner efe302b197 Change visibility of ui ptr back to private
Signed-off-by: Dylan Schooner <dschooner05@gmail.com>
2025-11-11 08:31:41 -05:00
Dylan d0a296208a
Update launcher/ui/dialogs/ScrollMessageBox.h
Co-authored-by: Alexandru Ionut Tripon <alexandru.tripon97@gmail.com>
Signed-off-by: Dylan <60893964+dsch7705@users.noreply.github.com>
2025-11-10 06:46:34 -05:00
Dylan Schooner 11a2ba63b3 Pass option as constructor parameter
Signed-off-by: Dylan Schooner <dschooner05@gmail.com>
2025-11-10 04:52:26 -05:00
Dylan Schooner 55dc9e6a84 Add optionCheckBox to ScrollMessageBox ui
Add 'Disable unavailable mods' option on check update failure

Signed-off-by: Dylan Schooner <dschooner05@gmail.com>
2025-11-10 03:24:00 -05:00
TheKodeToad 7f7649f13d
Replace some NULLs with nullptr
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2025-11-08 19:38:30 +00:00
TheKodeToad c4971479f8
Remove systeminfo
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2025-11-08 19:37:19 +00:00
Richard Voigtmann b0594dbb06 updated Assets.car to the icon suggestion from hw2007
Signed-off-by: Richard Voigtmann <richard.v.voigtmann@gmail.com>
2025-09-22 09:56:14 +02:00
Richard Voigtmann d0737eecc5 Added macOS 26 Liquid Glass Icon Support. See: #4149
Signed-off-by: Richard Voigtmann <richard.v.voigtmann@gmail.com>
2025-09-20 19:42:04 +02:00
624 changed files with 17123 additions and 6842 deletions

View file

@ -16,3 +16,4 @@ BraceWrapping:
BreakBeforeBraces: Custom
BreakConstructorInitializers: BeforeComma
Cpp11BracedListStyle: false
QualifierAlignment: Left

View file

@ -1,23 +1,32 @@
Checks:
- modernize-use-using
- readability-avoid-const-params-in-decls
- misc-unused-parameters,
- readability-identifier-naming
FormatStyle: file
# ^ Without unused-parameters the readability-identifier-naming check doesn't cause any warnings.
Checks:
"bugprone-*,clang-analyzer-*,cppcoreguidelines-*,hicpp-*,misc-*,modernize-*,performance-*,portability-*,readability-*,
-*-magic-numbers,
-*-non-private-member-variables-in-classes,
-*-special-member-functions,
-bugprone-easily-swappable-parameters,
-cppcoreguidelines-owning-memory,
-cppcoreguidelines-pro-type-static-cast-downcast,
-modernize-use-nodiscard,
-modernize-use-trailing-return-type,
-portability-avoid-pragma-once,
-readability-avoid-unconditional-preprocessor-if,
-readability-function-cognitive-complexity,
-readability-identifier-length,
-readability-redundant-access-specifiers"
CheckOptions:
- { key: readability-identifier-naming.ClassCase, value: PascalCase }
- { key: readability-identifier-naming.EnumCase, value: PascalCase }
- { key: readability-identifier-naming.FunctionCase, value: camelCase }
- { key: readability-identifier-naming.GlobalVariableCase, value: camelCase }
- { key: readability-identifier-naming.GlobalFunctionCase, value: camelCase }
- { key: readability-identifier-naming.GlobalConstantCase, value: SCREAMING_SNAKE_CASE }
- { key: readability-identifier-naming.MacroDefinitionCase, value: SCREAMING_SNAKE_CASE }
- { key: readability-identifier-naming.ClassMemberCase, value: camelCase }
- { key: readability-identifier-naming.PrivateMemberPrefix, value: m_ }
- { key: readability-identifier-naming.ProtectedMemberPrefix, value: m_ }
- { key: readability-identifier-naming.PrivateStaticMemberPrefix, value: s_ }
- { key: readability-identifier-naming.ProtectedStaticMemberPrefix, value: s_ }
- { key: readability-identifier-naming.PublicStaticConstantCase, value: SCREAMING_SNAKE_CASE }
- { key: readability-identifier-naming.EnumConstantCase, value: SCREAMING_SNAKE_CASE }
misc-include-cleaner.MissingIncludes: false
readability-identifier-naming.DefaultCase: "camelBack"
readability-identifier-naming.NamespaceCase: "CamelCase"
readability-identifier-naming.ClassCase: "CamelCase"
readability-identifier-naming.ClassConstantCase: "CamelCase"
readability-identifier-naming.EnumCase: "CamelCase"
readability-identifier-naming.EnumConstantCase: "CamelCase"
readability-identifier-naming.MacroDefinitionCase: "UPPER_CASE"
readability-identifier-naming.ClassMemberPrefix: "m_"
readability-identifier-naming.StaticConstantPrefix: "s_"
readability-identifier-naming.StaticVariablePrefix: "s_"
readability-identifier-naming.GlobalConstantPrefix: "g_"
readability-implicit-bool-conversion.AllowPointerConditions: true

View file

@ -1,6 +1,6 @@
name: Bug Report
description: File a bug report
labels: [bug]
labels: ["bug: unconfirmed", "status: needs triage"]
body:
- type: markdown
attributes:

View file

@ -1,7 +1,7 @@
# Template based on https://gitlab.archlinux.org/archlinux/rfcs/-/blob/0ba3b61e987e197f8d1901709409b8564958f78a/rfcs/0000-template.rst
name: Request for Comment (RFC)
description: Propose a larger change and start a discussion.
labels: [rfc]
labels: ["type: enhancement", "status: needs discussion", "status: needs triage"]
body:
- type: markdown
attributes:
@ -44,8 +44,8 @@ body:
attributes:
label: Unresolved Questions
description: |
Are there any portions of your proposal which need to be discussed with the community before the RFC can proceed?
Be careful here -- an RFC with a lot of remaining questions is likely to be stalled.
Are there any portions of your proposal which need to be discussed with the community before the RFC can proceed?
Be careful here -- an RFC with a lot of remaining questions is likely to be stalled.
If your RFC is mostly unresolved questions and not too much substance, it may not be ready.
placeholder: Do a lot of users care about the cat?
validations:

View file

@ -1,6 +1,6 @@
name: Suggestion
description: Make a suggestion
labels: [enhancement]
labels: ["type: enhancement", "status: needs triage"]
body:
- type: markdown
attributes:

View file

@ -27,6 +27,18 @@ runs:
using: composite
steps:
- name: Cleanup Qt installation on Linux
shell: bash
run: |
rm -rf "$QT_PLUGIN_PATH"/printsupport
rm -rf "$QT_PLUGIN_PATH"/sqldrivers
rm -rf "$QT_PLUGIN_PATH"/help
rm -rf "$QT_PLUGIN_PATH"/designer
rm -rf "$QT_PLUGIN_PATH"/qmltooling
rm -rf "$QT_PLUGIN_PATH"/qmlls
rm -rf "$QT_PLUGIN_PATH"/qmllint
rm -rf "$QT_PLUGIN_PATH"/platformthemes/libqgtk3.so
- name: Setup build variables
shell: bash
run: |
@ -52,32 +64,52 @@ runs:
- name: Package AppImage
shell: bash
env:
VERSION: ${{ inputs.version }}
VERSION: ${{ github.ref_type == 'tag' && github.ref_name || inputs.version }}
BUILD_DIR: build
INSTALL_APPIMAGE_DIR: install-appdir
GPG_PRIVATE_KEY: ${{ inputs.gpg-private-key }}
run: |
cmake --install ${{ env.BUILD_DIR }} --config ${{ inputs.build-type }} --prefix ${{ env.INSTALL_APPIMAGE_DIR }}/usr
cp ${{ env.INSTALL_APPIMAGE_DIR }}/usr/share/metainfo/org.prismlauncher.PrismLauncher.{metainfo,appdata}.xml
cmake --install ${{ env.BUILD_DIR }} --config ${{ inputs.build-type }} --prefix ${{ env.INSTALL_APPIMAGE_DIR }}
if [ '${{ inputs.gpg-private-key-id }}' != '' ]; then
echo "$GPG_PRIVATE_KEY" > privkey.asc
gpg --import privkey.asc
gpg --export --armor 9C7A2C9B62603299 > pubkey.asc
gpg --export --armor ${{ inputs.gpg-private-key-id }} > pubkey.asc
else
echo ":warning: Skipped code signing for Linux AppImage, as gpg key was not present." >> $GITHUB_STEP_SUMMARY
fi
appimagetool -s deploy "$INSTALL_APPIMAGE_DIR"/usr/share/applications/*.desktop
cp ~/bin/AppImageUpdate.AppImage "$INSTALL_APPIMAGE_DIR"/usr/bin/
# FIXME(@getchoo): Validate AppStream information when https://github.com/probonopd/go-appimage/pull/379 is merged
sharun lib4bin \
--hard-links \
--with-hooks \
--dst-dir "$INSTALL_APPIMAGE_DIR" \
"$INSTALL_APPIMAGE_DIR"/bin/* "$QT_PLUGIN_PATH"/*/*.so
cp ~/bin/AppImageUpdate.AppImage "$INSTALL_APPIMAGE_DIR"/bin/
# FIXME(@getchoo): gamemode doesn't seem to be very portable with DBus. Find a way to make it work!
find "$INSTALL_APPIMAGE_DIR" -name '*gamemode*' -exec rm {} +
#disable OpenGL and Vulkan launcher features until https://github.com/VHSgunzo/sharun/issues/35
echo "PRISMLAUNCHER_DISABLE_GLVULKAN=1" >> "$INSTALL_APPIMAGE_DIR"/.env
#makes the launcher use portals for file picking
echo "QT_QPA_PLATFORMTHEME=xdgdesktopportal" >> "$INSTALL_APPIMAGE_DIR"/.env
ln -s org.prismlauncher.PrismLauncher.metainfo.xml "$INSTALL_APPIMAGE_DIR"/share/metainfo/org.prismlauncher.PrismLauncher.appdata.xml
ln -s share/applications/org.prismlauncher.PrismLauncher.desktop "$INSTALL_APPIMAGE_DIR"
ln -s share/icons/hicolor/256x256/apps/org.prismlauncher.PrismLauncher.png "$INSTALL_APPIMAGE_DIR"
mv "$INSTALL_APPIMAGE_DIR"/{sharun,AppRun}
ls -la "$INSTALL_APPIMAGE_DIR"
if [[ "${{ github.ref_type }}" == "tag" ]]; then
APPIMAGE_DEST="PrismLauncher-Linux-$APPIMAGE_ARCH.AppImage"
else
APPIMAGE_DEST="PrismLauncher-Linux-$VERSION-${{ inputs.build-type }}-$APPIMAGE_ARCH.AppImage"
fi
mkappimage \
--no-appstream \
--updateinformation "gh-releases-zsync|${{ github.repository_owner }}|${{ github.event.repository.name }}|latest|PrismLauncher-Linux-$APPIMAGE_ARCH.AppImage.zsync" \
"$INSTALL_APPIMAGE_DIR" \
"PrismLauncher-Linux-$VERSION-${{ inputs.build-type }}-$APPIMAGE_ARCH.AppImage"
"$APPIMAGE_DEST"
- name: Package portable tarball
shell: bash
@ -89,28 +121,33 @@ runs:
cmake --install ${{ env.BUILD_DIR }} --config ${{ inputs.build-type }} --prefix ${{ env.INSTALL_PORTABLE_DIR }}
cmake --install ${{ env.BUILD_DIR }} --config ${{ inputs.build-type }} --prefix ${{ env.INSTALL_PORTABLE_DIR }} --component portable
#the linked cmark .so is of the version that ubuntu uses, so without this it breaks on most updated distros
mkdir ${{ env.INSTALL_PORTABLE_DIR }}/lib
cp /lib/$APPIMAGE_ARCH-linux-gnu/libcmark.so.0.* ${{ env.INSTALL_PORTABLE_DIR }}/lib
sharun lib4bin \
--with-hooks \
--hard-links \
--dst-dir "$INSTALL_PORTABLE_DIR" \
"$INSTALL_PORTABLE_DIR"/bin/* "$QT_PLUGIN_PATH"/*/*.so
for l in $(find ${{ env.INSTALL_PORTABLE_DIR }} -type f); do l=${l#$(pwd)/}; l=${l#${{ env.INSTALL_PORTABLE_DIR }}/}; l=${l#./}; echo $l; done > ${{ env.INSTALL_PORTABLE_DIR }}/manifest.txt
# FIXME(@getchoo): gamemode doesn't seem to be very portable with DBus. Find a way to make it work!
find "$INSTALL_PORTABLE_DIR" -name '*gamemode*' -exec rm {} +
for l in $(find ${{ env.INSTALL_PORTABLE_DIR }} -type f -o -type l); do l=${l#$(pwd)/}; l=${l#${{ env.INSTALL_PORTABLE_DIR }}/}; l=${l#./}; echo $l; done > ${{ env.INSTALL_PORTABLE_DIR }}/manifest.txt
cd ${{ env.INSTALL_PORTABLE_DIR }}
tar -czf ../PrismLauncher-portable.tar.gz *
- name: Upload binary tarball
uses: actions/upload-artifact@v6
uses: actions/upload-artifact@v7
with:
name: PrismLauncher-${{ inputs.artifact-name }}-Qt6-Portable-${{ inputs.version }}-${{ inputs.build-type }}
path: PrismLauncher-portable.tar.gz
- name: Upload AppImage
uses: actions/upload-artifact@v6
uses: actions/upload-artifact@v7
with:
name: PrismLauncher-${{ runner.os }}-${{ inputs.version }}-${{ inputs.build-type }}-${{ env.APPIMAGE_ARCH }}.AppImage
path: PrismLauncher-${{ runner.os }}-${{ inputs.version }}-${{ inputs.build-type }}-${{ env.APPIMAGE_ARCH }}.AppImage
path: PrismLauncher-${{ runner.os }}-*${{ env.APPIMAGE_ARCH }}.AppImage
- name: Upload AppImage Zsync
uses: actions/upload-artifact@v6
uses: actions/upload-artifact@v7
with:
name: PrismLauncher-${{ runner.os }}-${{ inputs.version }}-${{ inputs.build-type }}-${{ env.APPIMAGE_ARCH }}.AppImage.zsync
path: PrismLauncher-${{ runner.os }}-${{ inputs.version }}-${{ inputs.build-type }}-${{ env.APPIMAGE_ARCH }}.AppImage.zsync
path: PrismLauncher-${{ runner.os }}-*${{ env.APPIMAGE_ARCH }}.AppImage.zsync

View file

@ -96,16 +96,36 @@ runs:
fi
ditto -c -k --sequesterRsrc --keepParent "Prism Launcher.app" ../PrismLauncher.zip
- name: Create DMG
shell: bash
env:
INSTALL_DIR: install
run: |
cd ${{ env.INSTALL_DIR }}
mkdir -p src
cp -R "Prism Launcher.app" src/
ln -s /Applications src/
hdiutil create \
-volname "Prism Launcher ${{ inputs.version }}" \
-srcfolder src \
-ov -format ULMO \
"../PrismLauncher.dmg"
- name: Make Sparkle signature
shell: bash
run: |
if [ '${{ inputs.sparkle-ed25519-key }}' != '' ]; then
echo '${{ inputs.sparkle-ed25519-key }}' > ed25519-priv.pem
signature=$(/opt/homebrew/opt/openssl@3/bin/openssl pkeyutl -sign -rawin -in ${{ github.workspace }}/PrismLauncher.zip -inkey ed25519-priv.pem | openssl base64 | tr -d \\n)
signature_zip=$(/opt/homebrew/opt/openssl@3/bin/openssl pkeyutl -sign -rawin -in ${{ github.workspace }}/PrismLauncher.zip -inkey ed25519-priv.pem | openssl base64 | tr -d \\n)
signature_dmg=$(/opt/homebrew/opt/openssl@3/bin/openssl pkeyutl -sign -rawin -in ${{ github.workspace }}/PrismLauncher.dmg -inkey ed25519-priv.pem | openssl base64 | tr -d \\n)
rm ed25519-priv.pem
cat >> $GITHUB_STEP_SUMMARY << EOF
### Artifact Information :information_source:
- :memo: Sparkle Signature (ed25519): \`$signature\`
- :memo: Sparkle Signature (ed25519): \`$signature_zip\` (ZIP)
- :memo: Sparkle Signature (ed25519): \`$signature_dmg\` (DMG)
EOF
else
cat >> $GITHUB_STEP_SUMMARY << EOF
@ -115,7 +135,13 @@ runs:
fi
- name: Upload binary tarball
uses: actions/upload-artifact@v6
uses: actions/upload-artifact@v7
with:
name: PrismLauncher-${{ inputs.artifact-name }}-${{ inputs.version }}-${{ inputs.build-type }}
path: PrismLauncher.zip
- name: Upload disk image
uses: actions/upload-artifact@v7
with:
name: PrismLauncher-${{ inputs.artifact-name }}-${{ inputs.version }}-${{ inputs.build-type }}.dmg
path: PrismLauncher.dmg

View file

@ -54,32 +54,33 @@ runs:
Get-ChildItem ${{ env.INSTALL_DIR }} -Recurse | ForEach FullName | Resolve-Path -Relative | %{ $_.TrimStart('.\') } | %{ $_.TrimStart('${{ env.INSTALL_DIR }}') } | %{ $_.TrimStart('\') } | Out-File -FilePath ${{ env.INSTALL_DIR }}/manifest.txt
- name: Emit warning for unsigned builds
if: ${{ github.ref_name != 'develop' || inputs.azure-client-id == '' }}
if: ${{ env.CI_HAS_ACCESS_TO_AZURE == '' || inputs.azure-client-id == '' }}
shell: pwsh
run: |
":warning: Skipped code signing for Windows, as certificate was not present." >> $env:GITHUB_STEP_SUMMARY
- name: Login to Azure
if: ${{ github.ref_name == 'develop' && inputs.azure-client-id != '' }}
uses: azure/login@v2
if: ${{ env.CI_HAS_ACCESS_TO_AZURE != '' && inputs.azure-client-id != '' }}
uses: azure/login@v3
with:
client-id: ${{ inputs.azure-client-id }}
tenant-id: ${{ inputs.azure-tenant-id }}
subscription-id: ${{ inputs.azure-subscription-id }}
- name: Sign executables
if: ${{ github.ref_name == 'develop' && inputs.azure-client-id != '' }}
uses: azure/trusted-signing-action@v0
if: ${{ env.CI_HAS_ACCESS_TO_AZURE != '' && inputs.azure-client-id != '' }}
uses: azure/artifact-signing-action@v1
with:
endpoint: https://eus.codesigning.azure.net/
trusted-signing-account-name: PrismLauncher
certificate-profile-name: PrismLauncher
files: |
${{ github.workspace }}\install\prismlauncher.exe
${{ github.workspace }}\install\prismlauncher_filelink.exe
${{ github.workspace }}\install\prismlauncher_updater.exe
files-folder: ${{ github.workspace }}\install\
files-folder-filter: dll,exe
files-folder-recurse: true
files-folder-depth: 2
# recommended in https://github.com/Azure/artifact-signing-action#timestamping-1
timestamp-rfc3161: 'http://timestamp.acs.microsoft.com'
timestamp-digest: 'SHA256'
# TODO(@getchoo): Is this all really needed???
# https://github.com/Azure/trusted-signing-action/blob/fc390cf8ed0f14e248a542af1d838388a47c7a7c/docs/OIDC.md
exclude-environment-credential: true
@ -140,8 +141,8 @@ runs:
makensis -NOCD "${{ github.workspace }}/${{ env.BUILD_DIR }}/program_info/win_install.nsi"
- name: Sign installer
if: ${{ github.ref_name == 'develop' && inputs.azure-client-id != '' }}
uses: azure/trusted-signing-action@v0
if: ${{ env.CI_HAS_ACCESS_TO_AZURE != '' && inputs.azure-client-id != '' }}
uses: azure/artifact-signing-action@v1
with:
endpoint: https://eus.codesigning.azure.net/
trusted-signing-account-name: PrismLauncher
@ -150,6 +151,9 @@ runs:
files: |
${{ github.workspace }}\PrismLauncher-Setup.exe
# recommended in https://github.com/Azure/artifact-signing-action#timestamping-1
timestamp-rfc3161: 'http://timestamp.acs.microsoft.com'
timestamp-digest: 'SHA256'
# TODO(@getchoo): Is this all really needed???
# https://github.com/Azure/trusted-signing-action/blob/fc390cf8ed0f14e248a542af1d838388a47c7a7c/docs/OIDC.md
exclude-environment-credential: true
@ -164,19 +168,19 @@ runs:
exclude-interactive-browser-credential: true
- name: Upload binary zip
uses: actions/upload-artifact@v6
uses: actions/upload-artifact@v7
with:
name: PrismLauncher-${{ inputs.artifact-name }}-${{ inputs.version }}-${{ inputs.build-type }}
path: install/**
- name: Upload portable zip
uses: actions/upload-artifact@v6
uses: actions/upload-artifact@v7
with:
name: PrismLauncher-${{ inputs.artifact-name }}-Portable-${{ inputs.version }}-${{ inputs.build-type }}
path: install-portable/**
- name: Upload installer
uses: actions/upload-artifact@v6
uses: actions/upload-artifact@v7
with:
name: PrismLauncher-${{ inputs.artifact-name }}-Setup-${{ inputs.version }}-${{ inputs.build-type }}
path: PrismLauncher-Setup.exe

View file

@ -21,7 +21,6 @@ inputs:
qt-version:
description: Version of Qt to use
required: true
default: 6.9.3
outputs:
build-type:
@ -56,7 +55,7 @@ runs:
# TODO(@getchoo): Get this working on MSYS2!
- name: Setup ccache
if: ${{ (runner.os != 'Windows' || inputs.msystem == '') && inputs.build-type == 'Debug' }}
uses: hendrikmuhs/ccache-action@v1.2.20
uses: hendrikmuhs/ccache-action@v1.2.23
with:
variant: sccache
create-symlink: ${{ runner.os != 'Windows' }}
@ -78,6 +77,5 @@ runs:
with:
aqtversion: "==3.1.*"
version: ${{ inputs.qt-version }}
arch: ${{ inputs.qt-architecture }}
modules: qtimageformats qtnetworkauth
cache: ${{ inputs.build-type == 'Debug' }}

View file

@ -1,4 +1,5 @@
name: Setup Linux dependencies
description: Install and setup dependencies for building Prism Launcher
runs:
using: composite
@ -12,29 +13,7 @@ runs:
dpkg-dev \
ninja-build extra-cmake-modules pkg-config scdoc \
cmark gamemode-dev libarchive-dev libcmark-dev libqrencode-dev zlib1g-dev \
libxcb-cursor-dev
# TODO(@getchoo): Install with the above when all targets use Ubuntu 24.04
- name: Install tomlplusplus
if: ${{ runner.arch == 'ARM64' }}
shell: bash
run: |
sudo apt-get -y install libtomlplusplus-dev
# FIXME(@getchoo): THIS IS HORRIBLE TO DO!
# Install tomlplusplus from Ubuntu 24.04, since it never got backported to 22.04
# I've done too much to continue keeping this as a submodule....
- name: Install tomlplusplus from 24.04
if: ${{ runner.arch != 'ARM64' }}
shell: bash
run: |
deb_arch="$(dpkg-architecture -q DEB_HOST_ARCH)"
curl -Lo libtomlplusplus-dev.deb http://mirrors.kernel.org/ubuntu/pool/universe/t/tomlplusplus/libtomlplusplus-dev_3.4.0+ds-0.2build1_"$deb_arch".deb
curl -Lo libtomlplusplus3t64.deb http://mirrors.kernel.org/ubuntu/pool/universe/t/tomlplusplus/libtomlplusplus3t64_3.4.0+ds-0.2build1_"$deb_arch".deb
sudo dpkg -i libtomlplusplus3t64.deb
sudo dpkg -i libtomlplusplus-dev.deb
rm *.deb
sudo apt-get install -f
libxcb-cursor-dev libtomlplusplus-dev libvulkan-dev
- name: Setup AppImage tooling
shell: bash
@ -56,19 +35,20 @@ runs:
;;
esac
gh release download \
--repo VHSgunzo/sharun \
--pattern "sharun-$APPIMAGE_ARCH-aio" \
--output ~/bin/sharun
# FIXME!: revert this to probonopd/go-appimage once https://github.com/probonopd/go-appimage/pull/377 is merged!
gh release download continuous \
--repo probonopd/go-appimage \
--pattern "appimagetool-*-$APPIMAGE_ARCH.AppImage" \
--output ~/bin/appimagetool
gh release download continuous \
--repo probonopd/go-appimage \
--repo DioEgizio/go-appimage \
--pattern "mkappimage-*-$APPIMAGE_ARCH.AppImage" \
--output ~/bin/mkappimage
chmod +x ~/bin/appimagetool ~/bin/mkappimage
echo "$HOME/bin" >> "$GITHUB_PATH"
gh release download \
--repo AppImageCommunity/AppImageUpdate \
--pattern "AppImageUpdate-$APPIMAGE_ARCH.AppImage" \
--output ~/bin/AppImageUpdate.AppImage
chmod +x ~/bin/AppImageUpdate.AppImage
chmod +x ~/bin/*
echo "$HOME/bin" >> "$GITHUB_PATH"

View file

@ -14,7 +14,7 @@ runs:
shell: bash
run: |
brew update
brew install ninja extra-cmake-modules temurin@17
brew install ninja extra-cmake-modules temurin@17 mono
- name: Set JAVA_HOME
shell: bash
@ -44,4 +44,4 @@ runs:
- name: Setup vcpkg environment
shell: bash
run: |
echo "CMAKE_TOOLCHAIN_FILE=$VCPKG_INSTALLATION_ROOT/scripts/buildsystems/vcpkg.cmake" >> "$GITHUB_ENV"
echo "VCPKG_ROOT=$VCPKG_INSTALLATION_ROOT" >> "$GITHUB_ENV"

View file

@ -1,4 +1,5 @@
name: Setup Windows Dependencies
description: Install and setup dependencies for building Prism Launcher
inputs:
build-type:
@ -57,7 +58,7 @@ runs:
if: ${{ inputs.msystem == '' }}
shell: bash
run: |
echo "CMAKE_TOOLCHAIN_FILE=$VCPKG_INSTALLATION_ROOT/scripts/buildsystems/vcpkg.cmake" >> "$GITHUB_ENV"
echo "VCPKG_ROOT=$VCPKG_INSTALLATION_ROOT" >> "$GITHUB_ENV"
- name: Setup MSYS2 (MinGW)
if: ${{ inputs.msystem != '' }}
@ -90,7 +91,7 @@ runs:
- name: Retrieve ccache cache (MinGW)
if: ${{ inputs.msystem != '' && inputs.build-type == 'Debug' }}
uses: actions/cache@v5.0.1
uses: actions/cache@v5.0.5
with:
path: '${{ github.workspace }}\.ccache'
key: ${{ runner.os }}-mingw-w64-ccache-${{ github.run_id }}

View file

@ -8,8 +8,7 @@ on:
# the GitHub repository. This means that it should not evaluate user input in a
# way that allows code injection.
permissions:
contents: read
permissions: {}
jobs:
backport:
@ -19,13 +18,13 @@ jobs:
actions: write # for korthout/backport-action to create PR with workflow changes
name: Backport Pull Request
if: github.repository_owner == 'PrismLauncher' && github.event.pull_request.merged == true && (github.event_name != 'labeled' || startsWith('backport', github.event.label.name))
runs-on: ubuntu-latest
runs-on: ubuntu-slim
steps:
- uses: actions/checkout@v6
with:
ref: ${{ github.event.pull_request.head.sha }}
- name: Create backport PRs
uses: korthout/backport-action@v4.0.0
uses: korthout/backport-action@v4.4
with:
# Config README: https://github.com/korthout/backport-action#backport-action
pull_description: |-

View file

@ -14,15 +14,17 @@ on:
required: true
type: number
permissions: {}
jobs:
blocked_status:
name: Check Blocked Status
runs-on: ubuntu-latest
runs-on: ubuntu-slim
steps:
- name: Generate token
id: generate-token
uses: actions/create-github-app-token@v2
uses: actions/create-github-app-token@v3
with:
app-id: ${{ vars.PULL_REQUEST_APP_ID }}
private-key: ${{ secrets.PULL_REQUEST_APP_PRIVATE_KEY }}
@ -76,11 +78,11 @@ jobs:
run: |
prs=$(
jq -c '
.prBody as $body
.prBody as $body
| (
$body |
reduce (
. | scan("blocked (?:by|on):? #([0-9]+)")
$body |
reduce (
. | scan("[Bb]locked (?:[Bb]y|[Oo]n):? #([0-9]+)")
| map({
"type": "Blocked on",
"number": ( . | tonumber )
@ -88,17 +90,17 @@ jobs:
) as $i ([]; . + [$i[]])
) as $bprs
| (
$body |
reduce (
. | scan("stacked on:? #([0-9]+)")
$body |
reduce (
. | scan("[Ss]tacked [Oo]n:? #([0-9]+)")
| map({
"type": "Stacked on",
"number": ( . | tonumber )
})
) as $i ([]; . + [$i[]])
) as $sprs
| ($bprs + $sprs) as $prs
| {
| ($bprs + $sprs) as $prs
| {
"blocking": $prs,
"numBlocking": ( $prs | length),
}
@ -126,7 +128,7 @@ jobs:
"number": .number,
"merged": .merged,
"state": (if .state == "open" then "Open" elif .merged then "Merged" else "Closed" end),
"labels": (reduce .labels[].name as $l ([]; . + [$l])),
"labels": (reduce .labels[].name as $l ([]; . + [$l])),
"basePrUrl": .html_url,
"baseRepoName": .head.repo.name,
"baseRepoOwner": .head.repo.owner.login,
@ -143,19 +145,19 @@ jobs:
echo "current_blocking=$(jq -c 'map(
select(
(.type == "Stacked on" and (.merged | not)) or
(.type == "Blocked on" and (.state == "Open"))
(.type == "Blocked on" and (.state == "Open"))
) | .number
)' <<< "$blocked_pr_data" )";
} >> "$GITHUB_OUTPUT"
- name: Add 'blocked' Label if Missing
id: label_blocked
if: (fromJSON(steps.pr_ids.outputs.prs).numBlocking > 0) && !contains(fromJSON(env.JOB_DATA).prLabels, 'blocked') && !fromJSON(steps.blocking_data.outputs.all_merged)
if: "(fromJSON(steps.pr_ids.outputs.prs).numBlocking > 0) && !contains(fromJSON(env.JOB_DATA).prLabels, 'status: blocked') && !fromJSON(steps.blocking_data.outputs.all_merged)"
continue-on-error: true
env:
GH_TOKEN: ${{ steps.generate-token.outputs.token }}
run: |
gh -R ${{ github.repository }} issue edit --add-label 'blocked' "$PR_NUMBER"
gh -R ${{ github.repository }} issue edit --add-label 'status: blocked' "$PR_NUMBER"
- name: Remove 'blocked' Label if All Dependencies Are Merged
id: unlabel_blocked
@ -164,7 +166,7 @@ jobs:
env:
GH_TOKEN: ${{ steps.generate-token.outputs.token }}
run: |
gh -R ${{ github.repository }} issue edit --remove-label 'blocked' "$PR_NUMBER"
gh -R ${{ github.repository }} issue edit --remove-label 'status: blocked' "$PR_NUMBER"
- name: Apply 'blocking' Label to Unmerged Dependencies
id: label_blocking
@ -175,7 +177,7 @@ jobs:
BLOCKING_ISSUES: ${{ steps.blocking_data.outputs.current_blocking }}
run: |
while read -r pr ; do
gh -R ${{ github.repository }} issue edit --add-label 'blocking' "$pr" || true
gh -R ${{ github.repository }} issue edit --add-label 'status: blocking' "$pr" || true
done < <(jq -c '.[]' <<< "$BLOCKING_ISSUES")
- name: Apply Blocking PR Status Check

View file

@ -5,63 +5,18 @@ concurrency:
cancel-in-progress: true
on:
push:
branches:
- "develop"
- "release-*"
paths:
# File types
- "**.cpp"
- "**.h"
- "**.java"
- "**.ui"
# Directories
- "buildconfig/**"
- "cmake/**"
- "launcher/**"
- "libraries/**"
- "program_info/**"
- "tests/**"
# Files
- "CMakeLists.txt"
- "COPYING.md"
# Workflows
- ".github/workflows/build.yml"
- ".github/actions/package/**"
- ".github/actions/setup-dependencies/**"
merge_group:
types: [checks_requested]
pull_request:
paths:
# File types
- "**.cpp"
- "**.h"
- "**.java"
- "**.ui"
# Directories
- "buildconfig/**"
- "cmake/**"
- "launcher/**"
- "libraries/**"
- "program_info/**"
- "tests/**"
# Files
- "CMakeLists.txt"
- "COPYING.md"
# Workflows
- ".github/workflows/build.yml"
- ".github/actions/package/**"
- ".github/actions/setup-dependencies/**"
workflow_call:
inputs:
build-type:
description: Type of build (Debug or Release)
type: string
default: Debug
environment:
description: Deployment environment to run under
type: string
workflow_dispatch:
inputs:
build-type:
@ -69,11 +24,16 @@ on:
type: string
default: Debug
permissions: {}
jobs:
build:
name: Build (${{ matrix.artifact-name }})
environment: ${{ inputs.environment || '' }}
permissions:
contents: read
# Required for Azure Trusted Signing
id-token: write
# Required for vcpkg binary cache
@ -83,17 +43,15 @@ jobs:
fail-fast: false
matrix:
include:
- os: ubuntu-22.04
- os: ubuntu-24.04
artifact-name: Linux
cmake-preset: linux
qt-version: 6.10.2
# NOTE(@getchoo): Yes, we're intentionally using 24.04 here!!!
#
# It's not really documented anywhere AFAICT, but upstream Qt binaries
# *for the same version* are compiled against 24.04 on ARM, and *not* 22.04 like x64
- os: ubuntu-24.04-arm
artifact-name: Linux-aarch64
cmake-preset: linux
qt-version: 6.10.2
- os: windows-2022
artifact-name: Windows-MinGW-w64
@ -112,16 +70,19 @@ jobs:
cmake-preset: windows_msvc
# TODO(@getchoo): This is the default in setup-dependencies/windows. Why isn't it working?!?!
vcvars-arch: amd64
qt-version: 6.10.2
- os: windows-11-arm
artifact-name: Windows-MSVC-arm64
cmake-preset: windows_msvc
vcvars-arch: arm64
qt-version: 6.10.2
- os: macos-14
- os: macos-26
artifact-name: macOS
cmake-preset: macos_universal
macosx-deployment-target: 12.0
qt-version: 6.9.3
runs-on: ${{ matrix.os }}
@ -155,7 +116,7 @@ jobs:
artifact-name: ${{ matrix.artifact-name }}
msystem: ${{ matrix.msystem }}
vcvars-arch: ${{ matrix.vcvars-arch }}
qt-architecture: ${{ matrix.qt-architecture }}
qt-version: ${{ matrix.qt-version }}
##
# BUILD
@ -214,6 +175,8 @@ jobs:
- name: Package (Windows)
if: ${{ runner.os == 'Windows' }}
uses: ./.github/actions/package/windows
env:
CI_HAS_ACCESS_TO_AZURE: ${{ vars.CI_HAS_ACCESS_TO_AZURE || '' }}
with:
version: ${{ steps.short-version.outputs.version }}
build-type: ${{ steps.setup-dependencies.outputs.build-type }}

53
.github/workflows/clang-tidy.yml vendored Normal file
View file

@ -0,0 +1,53 @@
name: Clang-Tidy Code Scanning
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
on:
merge_group:
types: [checks_requested]
pull_request:
permissions: {}
jobs:
clang-tidy:
name: Run Clang-Tidy
runs-on: ubuntu-latest
permissions:
contents: read
security-events: write
steps:
- name: Checkout repository
uses: actions/checkout@v6
with:
fetch-depth: 0 # Required for diffing later on
submodules: "true"
- name: Setup sccache
uses: hendrikmuhs/ccache-action@v1.2.23
with:
variant: sccache
- name: Install Nix
uses: cachix/install-nix-action@v31
- name: Run build
# TODO(@getchoo): Figure out how to make this work with PCH
run: |
nix develop --command bash -c '
cmake -B build -D Launcher_USE_PCH=OFF -D CMAKE_CXX_COMPILER_LAUNCHER=sccache && cmake --build build
'
# TODO: Use SARIF after https://github.com/psastras/sarif-rs/issues/638 is fixed
- name: Run clang-tidy-diff
env:
BASE_REF: ${{ github.event.pull_request.base.sha || github.event.merge_group.base_sha }}
run: |
nix develop --command bash -c '
clang-tidy -verify-config && git diff -U0 --no-color "$BASE_REF" | clang-tidy-diff.py -p1 -quiet -only-check-in-db
'

View file

@ -5,63 +5,21 @@ concurrency:
cancel-in-progress: true
on:
push:
branches:
- "develop"
- "release-*"
paths:
# File types
- "**.cpp"
- "**.h"
- "**.java"
- "**.ui"
# Directories
- "buildconfig/**"
- "cmake/**"
- "launcher/**"
- "libraries/**"
- "program_info/**"
- "tests/**"
# Files
- "CMakeLists.txt"
- "COPYING.md"
# Workflows
- ".github/codeql/**"
- ".github/workflows/codeql.yml"
- ".github/actions/setup-dependencies/**"
merge_group:
types: [checks_requested]
pull_request:
paths:
# File types
- "**.cpp"
- "**.h"
- "**.java"
- "**.ui"
# Directories
- "buildconfig/**"
- "cmake/**"
- "launcher/**"
- "libraries/**"
- "program_info/**"
- "tests/**"
# Files
- "CMakeLists.txt"
- "COPYING.md"
# Workflows
- ".github/codeql/**"
- ".github/workflows/codeql.yml"
- ".github/actions/setup-dependencies/**"
workflow_dispatch:
permissions: {}
jobs:
CodeQL:
runs-on: ubuntu-latest
permissions:
contents: read
security-events: write
steps:
- name: Checkout repository
uses: actions/checkout@v6
@ -79,11 +37,16 @@ jobs:
uses: ./.github/actions/setup-dependencies
with:
build-type: Debug
qt-version: 6.4.3
- name: Configure and Build
run: |
cmake --preset linux
cmake --preset linux -DLauncher_USE_PCH=OFF
cmake --build --preset linux --config Debug
- name: Run tests
run: |
ctest --preset linux --build-config Debug --extra-verbose --output-on-failure
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v4

174
.github/workflows/container.yml vendored Normal file
View file

@ -0,0 +1,174 @@
name: Development Container
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
on:
merge_group:
types: [checks_requested]
pull_request:
workflow_dispatch:
permissions: {}
env:
REGISTRY: ghcr.io
jobs:
build:
name: Build (${{ matrix.arch }})
permissions:
contents: read
packages: write
outputs:
image-name: ${{ steps.image-name.outputs.image-name }}
strategy:
fail-fast: false
matrix:
include:
- arch: arm64
os: ubuntu-24.04-arm
- arch: amd64
os: ubuntu-24.04
runs-on: ${{ matrix.os }}
steps:
- name: Set image name
id: image-name
run: |
echo "image-name=${REGISTRY}/${GITHUB_REPOSITORY_OWNER,,}/devcontainer" >> "$GITHUB_OUTPUT"
- name: Install Podman
uses: redhat-actions/podman-install@main
# TODO(@getchoo): Always use this when the action properly supports ARM
if: ${{ runner.arch == 'X64' || runner.arch == 'X86' }}
with:
github-token: ${{ github.token }}
- name: Checkout repository
uses: actions/checkout@v6
- name: Determine metadata for image
id: image-metadata
uses: docker/metadata-action@v6
with:
images: |
${{ steps.image-name.outputs.image-name }}
flavor: |
latest=false
tags: |
type=raw,value=latest,enable=${{ github.event.merge_group.base_ref == 'refs/heads/develop' }}
type=sha
type=sha,format=long
type=ref,event=branch
type=ref,event=tag
- name: Build image
id: build-image
uses: redhat-actions/buildah-build@v2
with:
containerfiles: |
./Containerfile
tags: ${{ steps.image-metadata.outputs.tags }}
labels: ${{ steps.image-metadata.outputs.labels }}
- name: Push image
id: push-image
if: ${{ github.event_name != 'pull_request' }}
uses: redhat-actions/push-to-registry@v2
with:
tags: ${{ steps.build-image.outputs.tags }}
username: ${{ github.repository_owner }}
password: ${{ github.token }}
tls-verify: true
- name: Export image digest
if: ${{ github.event_name != 'pull_request' }}
env:
DIGEST: ${{ steps.push-image.outputs.digest }}
run: |
mkdir -p "$RUNNER_TEMP"/digests
touch "$RUNNER_TEMP"/digests/"${DIGEST#sha256:}"
- name: Upload digest artifact
if: ${{ github.event_name != 'pull_request' }}
uses: actions/upload-artifact@v7
with:
name: digests-${{ matrix.arch }}
path: ${{ runner.temp }}/digests/*
if-no-files-found: error
retention-days: 1
manifest:
name: Create manifest
needs: [ build ]
if: ${{ github.event_name != 'pull_request' }}
permissions:
contents: read
packages: write
runs-on: ubuntu-24.04
steps:
- name: Download digests
uses: actions/download-artifact@v8
with:
path: ${{ runner.temp }}/digests
pattern: digests-*
merge-multiple: true
- name: Install Podman
# TODO(@getchoo): Always use this when the action properly supports ARM
if: ${{ runner.arch == 'X64' || runner.arch == 'X86' }}
uses: redhat-actions/podman-install@main
with:
github-token: ${{ github.token }}
- name: Login to registry
uses: redhat-actions/podman-login@v1
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.repository_owner }}
password: ${{ github.token }}
- name: Determine metadata for manifest
id: manifest-metadata
uses: docker/metadata-action@v6
with:
images: |
${{ needs.build.outputs.image-name }}
flavor: |
latest=false
tags: |
type=raw,value=latest,enable=${{ github.event.merge_group.base_ref == 'refs/heads/develop' }}
type=sha
type=sha,format=long
type=ref,event=branch
type=ref,event=tag
- name: Create manifest list
working-directory: ${{ runner.temp }}/digests
env:
IMAGE_NAME: ${{ needs.build.outputs.image-name }}
run: |
while read -r tag; do
podman manifest create "$tag" \
$(printf "$IMAGE_NAME@sha256:%s " *)
done <<< "$DOCKER_METADATA_OUTPUT_TAGS"
- name: Push manifest
uses: redhat-actions/push-to-registry@v2
with:
tags: ${{ steps.manifest-metadata.outputs.tags }}
username: ${{ github.repository_owner }}
password: ${{ github.token }}
tls-verify: true

View file

@ -1,105 +0,0 @@
name: Flatpak
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
on:
push:
branches:
- "develop"
- "release-*"
# We don't do anything with these artifacts on releases. They go to Flathub
tags-ignore:
- "*"
paths:
# File types
- "**.cpp"
- "**.h"
- "**.java"
- "**.ui"
# Build files
- "flatpak/**"
# Directories
- "buildconfig/**"
- "cmake/**"
- "launcher/**"
- "libraries/**"
- "program_info/**"
- "tests/**"
# Files
- "CMakeLists.txt"
- "COPYING.md"
# Workflows
- ".github/workflows/flatpak.yml"
pull_request:
paths:
# File types
- "**.cpp"
- "**.h"
- "**.java"
- "**.ui"
# Build files
- "flatpak/**"
# Directories
- "buildconfig/**"
- "cmake/**"
- "launcher/**"
- "libraries/**"
- "program_info/**"
- "tests/**"
# Files
- "CMakeLists.txt"
- "COPYING.md"
# Workflows
- ".github/workflows/flatpak.yml"
workflow_dispatch:
permissions:
contents: read
jobs:
build:
name: Build (${{ matrix.arch }})
strategy:
fail-fast: false
matrix:
include:
- os: ubuntu-22.04
arch: x86_64
- os: ubuntu-22.04-arm
arch: aarch64
runs-on: ${{ matrix.os }}
container:
image: ghcr.io/flathub-infra/flatpak-github-actions:kde-6.10
options: --privileged
steps:
- name: Checkout repository
uses: actions/checkout@v6
with:
submodules: true
- name: Set short version
shell: bash
run: |
echo "VERSION=${GITHUB_SHA::7}" >> "$GITHUB_ENV"
- name: Build Flatpak
uses: flatpak/flatpak-github-actions/flatpak-builder@v6
with:
bundle: PrismLauncher-${{ runner.os }}-${{ env.VERSION }}-Flatpak.flatpak
manifest-path: flatpak/org.prismlauncher.PrismLauncher.yml
arch: ${{ matrix.arch }}

View file

@ -11,19 +11,21 @@ on:
required: true
type: number
permissions: {}
jobs:
update-blocked-status:
name: Update Blocked Status
runs-on: ubuntu-latest
runs-on: ubuntu-slim
# a pr that was a `blocking:<id>` label was merged.
# find the open pr's it was blocked by and trigger a refresh of their state
if: ${{ github.event_name == 'workflow_dispatch' || github.event.pull_request.merged == true && contains(github.event.pull_request.labels.*.name, 'blocking') }}
if: "${{ github.event_name == 'workflow_dispatch' || github.event.pull_request.merged == true && contains(github.event.pull_request.labels.*.name, 'status: blocking') }}"
steps:
- name: Generate token
id: generate-token
uses: actions/create-github-app-token@v2
uses: actions/create-github-app-token@v3
with:
app-id: ${{ vars.PULL_REQUEST_APP_ID }}
private-key: ${{ secrets.PULL_REQUEST_APP_PRIVATE_KEY }}
@ -35,10 +37,10 @@ jobs:
PR_NUMBER: ${{ inputs.pr_id || github.event.pull_request.number }}
run: |
blocked_prs=$(
gh -R ${{ github.repository }} pr list --label 'blocked' --json 'number,body' \
gh -R ${{ github.repository }} pr list --label 'status: blocked' --json 'number,body' \
| jq -c --argjson pr "$PR_NUMBER" '
reduce ( .[] | select(
.body |
.body |
scan("(?:blocked (?:by|on)|stacked on):? #([0-9]+)") |
map(tonumber) |
any(.[]; . == $pr)
@ -47,7 +49,7 @@ jobs:
)
{
echo "deps=$blocked_prs"
echo "numdeps=$(jq -r '. | length' <<< "$blocked_prs")"
echo "numdeps=$(jq -r '. | length' <<< "$blocked_prs")"
} >> "$GITHUB_OUTPUT"
- name: Trigger Blocked PR Workflows for Dependants

View file

@ -17,6 +17,7 @@ on:
- "**.h"
- "**.java"
- "**.ui"
- "**.md"
# Build files
- "**.nix"
@ -33,7 +34,6 @@ on:
# Files
- "CMakeLists.txt"
- "COPYING.md"
# Workflows
- ".github/workflows/nix.yml"
@ -44,6 +44,7 @@ on:
- "**.h"
- "**.java"
- "**.ui"
- "**.md"
# Build files
- "**.nix"
@ -60,14 +61,12 @@ on:
# Files
- "CMakeLists.txt"
- "COPYING.md"
# Workflows
- ".github/workflows/nix.yml"
workflow_dispatch:
permissions:
contents: read
permissions: {}
env:
DEBUG: ${{ github.ref_type != 'tag' }}
@ -76,6 +75,9 @@ jobs:
build:
name: Build (${{ matrix.system }})
permissions:
contents: read
strategy:
fail-fast: false
matrix:
@ -86,10 +88,7 @@ jobs:
- os: ubuntu-22.04-arm
system: aarch64-linux
- os: macos-15-intel
system: x86_64-darwin
- os: macos-14
- os: macos-26
system: aarch64-darwin
runs-on: ${{ matrix.os }}
@ -112,7 +111,7 @@ jobs:
# For in-tree builds
- name: Setup Cachix
if: ${{ github.event_name == 'push' || github.event_name == 'workflow_dispatch' }}
uses: cachix/cachix-action@v16
uses: cachix/cachix-action@v17
with:
name: prismlauncher
authToken: ${{ secrets.CACHIX_AUTH_TOKEN }}

View file

@ -4,14 +4,16 @@ on:
release:
types: [ released ]
permissions:
contents: read
permissions: {}
jobs:
winget:
name: Winget
runs-on: windows-latest
permissions:
contents: read
runs-on: ubuntu-slim
steps:
- name: Publish on Winget

View file

@ -5,17 +5,28 @@ on:
tags:
- "*"
permissions: {}
jobs:
build_release:
name: Build Release
uses: ./.github/workflows/build.yml
permissions:
contents: read
# Required for Azure Trusted Signing
id-token: write
# Required for vcpkg binary cache
packages: write
with:
build-type: Release
environment: Release
secrets: inherit
create_release:
needs: build_release
runs-on: ubuntu-latest
permissions:
contents: write
runs-on: ubuntu-slim
outputs:
upload_url: ${{ steps.create_release.outputs.upload_url }}
steps:
@ -25,7 +36,7 @@ jobs:
submodules: "true"
path: "PrismLauncher-source"
- name: Download artifacts
uses: actions/download-artifact@v7
uses: actions/download-artifact@v8
- name: Grab and store version
run: |
tag_name=$(echo ${{ github.ref }} | grep -oE "[^/]+$")
@ -34,11 +45,13 @@ jobs:
run: |
mv ${{ github.workspace }}/PrismLauncher-source PrismLauncher-${{ env.VERSION }}
mv PrismLauncher-Linux-Qt6-Portable*/PrismLauncher-portable.tar.gz PrismLauncher-Linux-Qt6-Portable-${{ env.VERSION }}.tar.gz
mv PrismLauncher-Linux-aarch64-Qt6-Portable*/PrismLauncher-portable.tar.gz PrismLauncher-Linux-aarch64-Qt6-Portable-${{ env.VERSION }}.tar.gz
mv PrismLauncher-*.AppImage/PrismLauncher-*-x86_64.AppImage PrismLauncher-Linux-x86_64.AppImage
mv PrismLauncher-*.AppImage.zsync/PrismLauncher-*-x86_64.AppImage.zsync PrismLauncher-Linux-x86_64.AppImage.zsync
mv PrismLauncher-*.AppImage/PrismLauncher-*-aarch64.AppImage PrismLauncher-Linux-aarch64.AppImage
mv PrismLauncher-*.AppImage.zsync/PrismLauncher-*-aarch64.AppImage.zsync PrismLauncher-Linux-aarch64.AppImage.zsync
mv PrismLauncher-macOS*/PrismLauncher.zip PrismLauncher-macOS-${{ env.VERSION }}.zip
mv PrismLauncher-macOS*/PrismLauncher.dmg PrismLauncher-macOS-${{ env.VERSION }}.dmg
tar --exclude='.git' -czf PrismLauncher-${{ env.VERSION }}.tar.gz PrismLauncher-${{ env.VERSION }}
@ -81,13 +94,14 @@ jobs:
- name: Create release
id: create_release
uses: softprops/action-gh-release@v2
uses: softprops/action-gh-release@v3
with:
token: ${{ secrets.GITHUB_TOKEN }}
tag_name: ${{ github.ref }}
name: Prism Launcher ${{ env.VERSION }}
draft: true
prerelease: false
fail_on_unmatched_files: true
files: |
PrismLauncher-Linux-x86_64.AppImage
PrismLauncher-Linux-x86_64.AppImage.zsync
@ -108,4 +122,5 @@ jobs:
PrismLauncher-Windows-MSVC-Portable-${{ env.VERSION }}.zip
PrismLauncher-Windows-MSVC-Setup-${{ env.VERSION }}.exe
PrismLauncher-macOS-${{ env.VERSION }}.zip
PrismLauncher-macOS-${{ env.VERSION }}.dmg
PrismLauncher-${{ env.VERSION }}.tar.gz

View file

@ -1,29 +0,0 @@
name: Stale
on:
schedule:
# run weekly on sunday
- cron: "0 0 * * 0"
workflow_dispatch:
jobs:
label:
name: Label issues and PRs
runs-on: ubuntu-latest
permissions:
issues: write
pull-requests: write
steps:
- uses: actions/stale@v10
with:
days-before-stale: 60
days-before-close: -1 # Don't close anything
exempt-issue-labels: rfc,nostale,help wanted
exempt-all-milestones: true
exempt-all-assignees: true
operations-per-run: 1000
stale-issue-label: inactive
stale-pr-label: inactive

View file

@ -6,25 +6,30 @@ on:
- cron: "0 0 * * 0"
workflow_dispatch:
permissions:
contents: write
pull-requests: write
permissions: {}
jobs:
update-flake:
if: github.repository == 'PrismLauncher/PrismLauncher'
runs-on: ubuntu-latest
permissions:
contents: write
pull-requests: write
runs-on: ubuntu-slim
steps:
- uses: actions/checkout@v6
- uses: cachix/install-nix-action@4e002c8ec80594ecd40e759629461e26c8abed15 # v31
- uses: cachix/install-nix-action@616559265b40713947b9c190a8ff4b507b5df49b # v31
- uses: DeterminateSystems/update-flake-lock@v28
with:
commit-msg: "chore(nix): update lockfile"
pr-title: "chore(nix): update lockfile"
pr-labels: |
Linux
packaging
simple change
platform: Linux
area: packaging
complexity: low
priority: low
type: robot
changelog:omit

3
.gitmodules vendored
View file

@ -1,6 +1,3 @@
[submodule "libraries/libnbtplusplus"]
path = libraries/libnbtplusplus
url = https://github.com/PrismLauncher/libnbtplusplus.git
[submodule "flatpak/shared-modules"]
path = flatpak/shared-modules
url = https://github.com/flathub/shared-modules.git

View file

@ -1,6 +1,9 @@
cmake_minimum_required(VERSION 3.22) # minimum version required by Qt
cmake_minimum_required(VERSION 3.25) # Required for features like `CMAKE_MSVC_DEBUG_INFORMATION_FORMAT`
project(Launcher)
project(Launcher LANGUAGES C CXX)
if(APPLE)
enable_language(OBJC OBJCXX)
endif()
string(COMPARE EQUAL "${CMAKE_SOURCE_DIR}" "${CMAKE_BUILD_DIR}" IS_IN_SOURCE_BUILD)
if(IS_IN_SOURCE_BUILD)
@ -27,119 +30,103 @@ set(CMAKE_C_STANDARD_REQUIRED true)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_C_STANDARD 11)
include(GenerateExportHeader)
if(MSVC)
# /GS Adds buffer security checks, default on but incuded anyway to mirror gcc's fstack-protector flag
# /permissive- specify standards-conforming compiler behavior, also enabled by Qt6, default on with std:c++20
# Use /W4 as /Wall includes unnesserey warnings such as added padding to structs
set(CMAKE_CXX_FLAGS "/GS /permissive- /W4 ${CMAKE_CXX_FLAGS}")
# /EHs Enables stack unwind semantics for standard C++ exceptions to ensure stackframes are unwound
# and object deconstructors are called when an exception is caught.
# without it memory leaks and a warning is printed
# /EHc tells the compiler to assume that functions declared as extern "C" never throw a C++ exception
# This appears to not always be a defualt compiler option in CMAKE
set(CMAKE_CXX_FLAGS "/EHsc ${CMAKE_CXX_FLAGS}")
add_compile_definitions($<$<NOT:$<CONFIG:Debug>>:QT_NO_DEBUG>)
add_compile_definitions(QT_WARN_DEPRECATED_UP_TO=0x060400)
add_compile_definitions(QT_DISABLE_DEPRECATED_UP_TO=0x060400)
# LINK accepts /SUBSYSTEM whics sets if we are a WINDOWS (gui) or a CONSOLE programs
# This implicitly selects an entrypoint specific to the subsystem selected
# qtmain/QtEntryPointLib provides the correct entrypoint (wWinMain) for gui programs
# Additinaly LINK autodetects we use a GUI so we can omit /SUBSYSTEM
# This allows tests to still use have console without using seperate linker flags
# /LTCG allows for linking wholy optimizated programs
# /MANIFEST:NO disables generating a manifest file, we instead provide our own
# /STACK sets the stack reserve size, ATL's pack list needs 3-4 MiB as of November 2022, provide 8 MiB
set(CMAKE_EXE_LINKER_FLAGS "/LTCG /MANIFEST:NO /STACK:8388608 ${CMAKE_EXE_LINKER_FLAGS}")
if(CMAKE_CXX_COMPILER_FRONTEND_VARIANT STREQUAL "MSVC")
add_compile_options(
# /GS Adds buffer security checks, default on but included anyway to mirror gcc's fstack-protector flag
"$<$<COMPILE_LANGUAGE:C,CXX>:/GS>"
# /Gw helps reduce binary size
# /Gy allows the compiler to package individual functions
# /guard:cf enables control flow guard
"$<$<AND:$<CONFIG:Release,RelWithDebInfo>,$<COMPILE_LANGUAGE:C,CXX>>:/Gw;/Gy;/guard:cf>"
)
add_link_options(
# /LTCG allows for linking wholy optimizated programs
# /MANIFEST:NO disables generating a manifest file, we instead provide our own
# /STACK sets the stack reserve size, ATL's pack list needs 3-4 MiB as of November 2022, provide 8 MiB
"$<$<COMPILE_LANGUAGE:C,CXX>:/LTCG;/MANIFEST:NO;/STACK:8388608>"
)
# /GL enables whole program optimizations
# /Gw helps reduce binary size
# /Gy allows the compiler to package individual functions
# /guard:cf enables control flow guard
foreach(lang C CXX)
set("CMAKE_${lang}_FLAGS_RELEASE" "/GL /Gw /Gy /guard:cf")
endforeach()
# NOTE: With Clang, this is implemented as regular LTO and only used during linking
if(NOT CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
add_compile_options("$<$<AND:$<CONFIG:Release,RelWithDebInfo>,$<COMPILE_LANGUAGE:C,CXX>>:/GL>")
endif()
# See https://github.com/ccache/ccache/issues/1040
# Note, CMake 3.25 replaces this with CMAKE_MSVC_DEBUG_INFORMATION_FORMAT
# See https://cmake.org/cmake/help/v3.25/variable/CMAKE_MSVC_DEBUG_INFORMATION_FORMAT.html
foreach(config DEBUG RELWITHDEBINFO)
foreach(lang C CXX)
set(flags_var "CMAKE_${lang}_FLAGS_${config}")
string(REGEX REPLACE "/Z[Ii]" "/Z7" ${flags_var} "${${flags_var}}")
endforeach()
endforeach()
# TODO(@getchoo): Is sccache affected by this? Would be nice to use `ProgramDatabase`....
set(CMAKE_MSVC_DEBUG_INFORMATION_FORMAT "$<$<CONFIG:Debug,RelWithDebInfo>:Embedded>")
if(CMAKE_MSVC_RUNTIME_LIBRARY STREQUAL "MultiThreadedDLL")
set(CMAKE_MAP_IMPORTED_CONFIG_DEBUG Release "")
set(CMAKE_MAP_IMPORTED_CONFIG_RELWITHDEBINFO Release "")
endif()
else()
set(CMAKE_CXX_FLAGS "-Wall -pedantic -fstack-protector-strong --param=ssp-buffer-size=4 ${CMAKE_CXX_FLAGS}")
add_compile_options("$<$<COMPILE_LANGUAGE:C,CXX>:-fstack-protector-strong;--param=ssp-buffer-size=4>")
# Avoid re-defining _FORTIFY_SOURCE, as it can cause redefinition errors in setups that use it by default (i.e., package builds)
if(NOT (CMAKE_C_FLAGS MATCHES "-D_FORTIFY_SOURCE" OR CMAKE_CXX_FLAGS MATCHES "-D_FORTIFY_SOURCE"))
# NOTE: _FORTIFY_SOURCE requires optimizations in most newer versions of glibc
add_compile_options("$<$<AND:$<COMPILE_LANGUAGE:C,CXX>,$<CONFIG:Release,RelWithDebInfo>>:-D_FORTIFY_SOURCE=2>")
endif()
# ATL's pack list needs more than the default 1 Mib stack on windows
if(WIN32)
set(CMAKE_EXE_LINKER_FLAGS "-Wl,--stack,8388608 ${CMAKE_EXE_LINKER_FLAGS}")
# Emit PDBs for WinDbg, etc.
if(CMAKE_BUILD_TYPE STREQUAL "Debug" OR CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo")
set(CMAKE_EXE_LINKER_FLAGS "-Wl,--pdb= ${CMAKE_EXE_LINKER_FLAGS}")
foreach(lang C CXX)
set("CMAKE_${lang}_FLAGS" "-gcodeview ${CMAKE_${lang}_FLAGS}")
# Force-enabling this to use generator expressions like TARGET_PDB_FILE
# (and because we can actually emit PDBs)
set("CMAKE_${lang}_LINKER_SUPPORTS_PDB" ON)
endforeach()
endif()
if(CMAKE_SYSTEM_NAME STREQUAL "Windows")
add_link_options("$<$<COMPILE_LANGUAGE:C,CXX>:-Wl,--stack,8388608>")
# -ffunction-sections and -fdata-sections help reduce binary size
# -mguard=cf enables Control Flow Guard
# TODO: Look into -gc-sections to further reduce binary size
foreach(lang C CXX)
set("CMAKE_${lang}_FLAGS_RELEASE" "-ffunction-sections -fdata-sections -mguard=cf")
endforeach()
add_compile_options("$<$<AND:$<CONFIG:Release,RelWithDebInfo>,$<COMPILE_LANGUAGE:C,CXX>>:-ffunction-sections;-fdata-sections;-mguard=cf>")
endif()
endif()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DQT_WARN_DEPRECATED_UP_TO=0x060200")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DQT_DISABLE_DEPRECATED_UP_TO=0x060000")
# set CXXFLAGS for build targets
set(CMAKE_CXX_FLAGS_RELEASE "-O2 -D_FORTIFY_SOURCE=2 ${CMAKE_CXX_FLAGS_RELEASE}")
# Export compile commands for debug builds if we can (useful in LSPs like clangd)
# https://cmake.org/cmake/help/v3.31/variable/CMAKE_EXPORT_COMPILE_COMMANDS.html
if(CMAKE_GENERATOR STREQUAL "Unix Makefiles" OR CMAKE_GENERATOR MATCHES "^Ninja")
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
endif()
option(USE_CLANG_TIDY "Enable the use of clang-tidy during compilation" OFF)
if(USE_CLANG_TIDY)
find_program(CLANG_TIDY clang-tidy OPTIONAL)
if(CLANG_TIDY)
message(STATUS "Using clang-tidy during compilation")
set(CLANG_TIDY_COMMAND "${CLANG_TIDY}" "--config-file=${CMAKE_SOURCE_DIR}/.clang-tidy")
set(CMAKE_CXX_CLANG_TIDY ${CLANG_TIDY_COMMAND})
else()
message(WARNING "Unable to find `clang-tidy`. Not using during compilation")
endif()
endif()
option(DEBUG_ADDRESS_SANITIZER "Enable Address Sanitizer in Debug builds" OFF)
# If this is a Debug build turn on address sanitiser
if ((CMAKE_BUILD_TYPE STREQUAL "Debug" OR CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo") AND DEBUG_ADDRESS_SANITIZER)
if (DEBUG_ADDRESS_SANITIZER)
message(STATUS "Address Sanitizer enabled for Debug builds, Turn it off with -DDEBUG_ADDRESS_SANITIZER=off")
if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")
if (CMAKE_CXX_COMPILER_FRONTEND_VARIANT STREQUAL "MSVC")
# using clang with clang-cl front end
message(STATUS "Address Sanitizer available on Clang MSVC frontend")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /fsanitize=address /Oy-")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /fsanitize=address /Oy-")
else()
# AppleClang and Clang
message(STATUS "Address Sanitizer available on Clang")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address -fno-omit-frame-pointer -fsanitize=undefined -fno-sanitize-recover=null")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address -fno-omit-frame-pointer -fsanitize=undefined -fno-sanitize-recover=null")
endif()
elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
# GCC
message(STATUS "Address Sanitizer available on GCC")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address -fno-omit-frame-pointer -fsanitize=undefined -fno-sanitize-recover")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address -fno-omit-frame-pointer -fsanitize=undefined -fno-sanitize-recover")
link_libraries("asan")
elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
message(STATUS "Address Sanitizer available on MSVC")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /fsanitize=address /Oy-")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /fsanitize=address /Oy-")
set(USE_ASAN_COMPILE_OPTIONS $<AND:$<CONFIG:Debug,RelWithDebInfo>,$<COMPILE_LANGUAGE:C,CXX>>)
if (CMAKE_CXX_COMPILER_FRONTEND_VARIANT STREQUAL "MSVC")
message(STATUS "Using Address Sanitizer compile options for MSVC frontend")
add_compile_options(
$<${USE_ASAN_COMPILE_OPTIONS}:/fsanitize=address>
$<${USE_ASAN_COMPILE_OPTIONS}:/Oy->
)
elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")
message(STATUS "Using Address Sanitizer compile options for GCC/Clang")
add_compile_options(
$<${USE_ASAN_COMPILE_OPTIONS}:-fsanitize=address,undefined>
$<${USE_ASAN_COMPILE_OPTIONS}:-fno-omit-frame-pointer>
$<${USE_ASAN_COMPILE_OPTIONS}:-fno-sanitize-recover=null>
)
link_libraries("asan" "ubsan")
else()
message(STATUS "Address Sanitizer not available on compiler ${CMAKE_CXX_COMPILER_ID}")
endif()
@ -155,8 +142,9 @@ if(ENABLE_LTO)
if(ipo_supported)
set(CMAKE_INTERPROCEDURAL_OPTIMIZATION_RELEASE TRUE)
set(CMAKE_INTERPROCEDURAL_OPTIMIZATION_MINSIZEREL TRUE)
set(CMAKE_INTERPROCEDURAL_OPTIMIZATION_RELWITHDEBINFO TRUE)
if(CMAKE_BUILD_TYPE)
if(CMAKE_BUILD_TYPE STREQUAL "Release" OR CMAKE_BUILD_TYPE STREQUAL "MinSizeRel")
if(NOT CMAKE_BUILD_TYPE STREQUAL "Debug")
message(STATUS "IPO / LTO enabled")
else()
message(STATUS "Not enabling IPO / LTO on debug builds")
@ -185,12 +173,13 @@ endif()
######## Set URLs ########
set(Launcher_NEWS_RSS_URL "https://prismlauncher.org/feed/feed.xml" CACHE STRING "URL to fetch Prism Launcher's news RSS feed from.")
set(Launcher_NEWS_OPEN_URL "https://prismlauncher.org/news" CACHE STRING "URL that gets opened when the user clicks 'More News'")
set(Launcher_HELP_URL "https://prismlauncher.org/wiki/help-pages/%1" CACHE STRING "URL (with arg %1 to be substituted with page-id) that gets opened when the user requests help")
set(Launcher_WIKI_URL "https://prismlauncher.org/wiki/" CACHE STRING "URL that gets opened when the user clicks 'Launcher Help'")
set(Launcher_HELP_URL "https://prismlauncher.org/wiki/help-pages/%1" CACHE STRING "URL (with arg %1 to be substituted with page-id) that gets opened when the user requests help in a dialog window")
set(Launcher_LOGIN_CALLBACK_URL "https://prismlauncher.org/successful-login" CACHE STRING "URL that gets opened when the user successfully logins.")
set(Launcher_FMLLIBS_BASE_URL "https://files.prismlauncher.org/fmllibs/" CACHE STRING "URL for FML Libraries.")
set(Launcher_LEGACY_FMLLIBS_BASE_URL "https://files.prismlauncher.org/fmllibs/" CACHE STRING "URL for legacy (<=1.5.2) FML Libraries.")
######## Set version numbers ########
set(Launcher_VERSION_MAJOR 10)
set(Launcher_VERSION_MAJOR 12)
set(Launcher_VERSION_MINOR 0)
set(Launcher_VERSION_PATCH 0)
@ -232,6 +221,8 @@ set(Launcher_SUBREDDIT_URL "https://prismlauncher.org/reddit" CACHE STRING "URL
# Builds
set(Launcher_QT_VERSION_MAJOR "6" CACHE STRING "Major Qt version to build against")
option(Launcher_USE_PCH "Use precompiled headers where possible" ON)
# Java downloader
set(Launcher_ENABLE_JAVA_DOWNLOADER_DEFAULT ON)
@ -297,7 +288,7 @@ set(Launcher_BUILD_TIMESTAMP "${TODAY}")
# Find the required Qt parts
if(Launcher_QT_VERSION_MAJOR EQUAL 6)
set(QT_VERSION_MAJOR 6)
find_package(Qt6 REQUIRED COMPONENTS Core CoreTools Widgets Concurrent Network Test Xml NetworkAuth OpenGL)
find_package(Qt6 6.4 REQUIRED COMPONENTS Core CoreTools Widgets Concurrent Network Test Xml NetworkAuth OpenGL)
find_package(Qt6 COMPONENTS DBus)
list(APPEND Launcher_QT_DBUS Qt6::DBus)
else()
@ -337,7 +328,7 @@ if(NOT LibArchive_FOUND)
pkg_check_modules(libarchive REQUIRED IMPORTED_TARGET libarchive)
endif()
find_package(tomlplusplus 3.2.0 REQUIRED)
find_package(tomlplusplus 3.2.0)
# fallback to pkgconfig, important especially as many distros package toml++ built with meson
if(NOT tomlplusplus_FOUND)
find_package(PkgConfig REQUIRED)
@ -379,7 +370,7 @@ if(UNIX AND APPLE)
# Mac bundle settings
set(MACOSX_BUNDLE_BUNDLE_NAME "${Launcher_DisplayName}")
set(MACOSX_BUNDLE_INFO_STRING "${Launcher_DisplayName}: A custom launcher for Minecraft that allows you to easily manage multiple installations of Minecraft at once.")
set(MACOSX_BUNDLE_GUI_IDENTIFIER "org.prismlauncher.${Launcher_Name}")
set(MACOSX_BUNDLE_GUI_IDENTIFIER "${Launcher_AppID}")
set(MACOSX_BUNDLE_BUNDLE_VERSION "${Launcher_VERSION_NAME}")
set(MACOSX_BUNDLE_SHORT_VERSION_STRING "${Launcher_VERSION_NAME}")
set(MACOSX_BUNDLE_LONG_VERSION_STRING "${Launcher_VERSION_NAME}")
@ -399,6 +390,52 @@ if(UNIX AND APPLE)
# Add the icon
install(FILES ${Launcher_Branding_ICNS} DESTINATION ${RESOURCES_DEST_DIR} RENAME ${Launcher_Name}.icns)
find_program(ACTOOL_EXE actool DOC "Path to the apple asset catalog compiler")
if(ACTOOL_EXE)
execute_process(
COMMAND xcodebuild -version
OUTPUT_VARIABLE XCODE_VERSION_OUTPUT
OUTPUT_STRIP_TRAILING_WHITESPACE
)
string(REGEX MATCH "Xcode ([0-9]+\.[0-9]+)" XCODE_VERSION_MATCH "${XCODE_VERSION_OUTPUT}")
if(XCODE_VERSION_MATCH)
set(XCODE_VERSION ${CMAKE_MATCH_1})
else()
set(XCODE_VERSION 0.0)
endif()
if(XCODE_VERSION VERSION_GREATER_EQUAL 26.0)
set(ASSETS_OUT_DIR "${CMAKE_BINARY_DIR}/program_info")
set(GENERATED_ASSETS_CAR "${ASSETS_OUT_DIR}/Assets.car")
set(ICON_SOURCE "${CMAKE_CURRENT_SOURCE_DIR}/${Launcher_Branding_MAC_ICON}")
add_custom_command(
OUTPUT "${GENERATED_ASSETS_CAR}"
COMMAND ${ACTOOL_EXE} "${ICON_SOURCE}"
--compile "${ASSETS_OUT_DIR}"
--output-partial-info-plist /dev/null
--app-icon ${Launcher_Name}
--enable-on-demand-resources NO
--target-device mac
--minimum-deployment-target ${CMAKE_OSX_DEPLOYMENT_TARGET}
--platform macosx
DEPENDS "${ICON_SOURCE}"
COMMENT "Compiling asset catalog (${ICON_SOURCE})"
VERBATIM
)
add_custom_target(compile_assets ALL DEPENDS "${GENERATED_ASSETS_CAR}")
install(FILES "${GENERATED_ASSETS_CAR}" DESTINATION "${RESOURCES_DEST_DIR}")
else()
message(WARNING "Xcode ${XCODE_VERSION} is too old. Minimum required version is 26.0. Not compiling liquid glass icons.")
endif()
else()
message(WARNING "actool not found. Cannot compile macOS app icons.\n"
"Install Xcode command line tools: 'xcode-select --install'")
endif()
elseif(UNIX)
include(KDEInstallDirs)
@ -413,7 +450,7 @@ elseif(UNIX)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${Launcher_MetaInfo} DESTINATION ${KDE_INSTALL_METAINFODIR})
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/${Launcher_SVG} DESTINATION "${KDE_INSTALL_ICONDIR}/hicolor/scalable/apps")
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/${Launcher_PNG_256} DESTINATION "${KDE_INSTALL_ICONDIR}/hicolor/256x256/apps" RENAME "${Launcher_AppID}.png")
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/${Launcher_mrpack_MIMEInfo} DESTINATION ${KDE_INSTALL_MIMEDIR})
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${Launcher_MIMEInfo} DESTINATION ${KDE_INSTALL_MIMEDIR})
install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/launcher/qtlogging.ini" DESTINATION "share/${Launcher_Name}")
@ -451,7 +488,6 @@ option(NBT_USE_ZLIB "Build NBT library with zlib support" OFF)
option(NBT_BUILD_TESTS "Build NBT library tests" OFF) #FIXME: fix unit tests.
add_subdirectory(libraries/libnbtplusplus)
add_subdirectory(libraries/systeminfo) # system information library
add_subdirectory(libraries/launcher) # java based launcher part for Minecraft
add_subdirectory(libraries/javacheck) # java compatibility checker

View file

@ -1,214 +1,222 @@
{
"$schema": "https://cmake.org/cmake/help/latest/_downloads/3e2d73bff478d88a7de0de736ba5e361/schema.json",
"version": 8,
"cmakeMinimumRequired": {
"major": 3,
"minor": 28
},
"configurePresets": [
{
"name": "base",
"hidden": true,
"binaryDir": "build",
"installDir": "install",
"generator": "Ninja Multi-Config",
"cacheVariables": {
"Launcher_BUILD_ARTIFACT": "$penv{ARTIFACT_NAME}",
"Launcher_BUILD_PLATFORM": "$penv{BUILD_PLATFORM}",
"Launcher_ENABLE_JAVA_DOWNLOADER": "ON",
"ENABLE_LTO": "ON"
}
},
{
"name": "linux",
"displayName": "Linux",
"inherits": [
"base"
],
"condition": {
"type": "equals",
"lhs": "${hostSystemName}",
"rhs": "Linux"
}
},
{
"name": "macos",
"displayName": "macOS",
"inherits": [
"base"
],
"condition": {
"type": "equals",
"lhs": "${hostSystemName}",
"rhs": "Darwin"
}
},
{
"name": "macos_universal",
"displayName": "macOS (Universal Binary)",
"inherits": [
"macos"
],
"cacheVariables": {
"CMAKE_OSX_ARCHITECTURES": "x86_64;arm64",
"VCPKG_TARGET_TRIPLET": "universal-osx"
}
},
{
"name": "windows_mingw",
"displayName": "Windows (MinGW)",
"inherits": [
"base"
],
"condition": {
"type": "equals",
"lhs": "${hostSystemName}",
"rhs": "Windows"
}
},
{
"name": "windows_msvc",
"displayName": "Windows (MSVC)",
"inherits": [
"base"
],
"condition": {
"type": "equals",
"lhs": "${hostSystemName}",
"rhs": "Windows"
}
}
],
"buildPresets": [
{
"name": "linux",
"displayName": "Linux",
"condition": {
"type": "equals",
"lhs": "${hostSystemName}",
"rhs": "Linux"
},
"configurePreset": "linux"
},
{
"name": "macos",
"displayName": "macOS",
"condition": {
"type": "equals",
"lhs": "${hostSystemName}",
"rhs": "Darwin"
},
"configurePreset": "macos"
},
{
"name": "macos_universal",
"displayName": "macOS (Universal Binary)",
"inherits": [
"macos"
],
"configurePreset": "macos_universal"
},
{
"name": "windows_mingw",
"displayName": "Windows (MinGW)",
"condition": {
"type": "equals",
"lhs": "${hostSystemName}",
"rhs": "Windows"
},
"configurePreset": "windows_mingw"
},
{
"name": "windows_msvc",
"displayName": "Windows (MSVC)",
"condition": {
"type": "equals",
"lhs": "${hostSystemName}",
"rhs": "Windows"
},
"configurePreset": "windows_msvc"
}
],
"testPresets": [
{
"name": "base",
"hidden": true,
"output": {
"outputOnFailure": true
},
"execution": {
"noTestsAction": "error"
},
"filter": {
"exclude": {
"name": "^example64|example$"
}
}
},
{
"name": "linux",
"displayName": "Linux",
"inherits": [
"base"
],
"condition": {
"type": "equals",
"lhs": "${hostSystemName}",
"rhs": "Linux"
},
"configurePreset": "linux"
},
{
"name": "macos",
"displayName": "macOS",
"inherits": [
"base"
],
"condition": {
"type": "equals",
"lhs": "${hostSystemName}",
"rhs": "Darwin"
},
"configurePreset": "macos"
},
{
"name": "macos_universal",
"displayName": "macOS (Universal Binary)",
"inherits": [
"base"
],
"condition": {
"type": "equals",
"lhs": "${hostSystemName}",
"rhs": "Darwin"
},
"configurePreset": "macos_universal"
},
{
"name": "windows_mingw",
"displayName": "Windows (MinGW)",
"inherits": [
"base"
],
"condition": {
"type": "equals",
"lhs": "${hostSystemName}",
"rhs": "Windows"
},
"configurePreset": "windows_mingw"
},
{
"name": "windows_msvc",
"displayName": "Windows (MSVC)",
"inherits": [
"base"
],
"condition": {
"type": "equals",
"lhs": "${hostSystemName}",
"rhs": "Windows"
},
"configurePreset": "windows_msvc"
}
]
"$schema": "https://cmake.org/cmake/help/latest/_downloads/3e2d73bff478d88a7de0de736ba5e361/schema.json",
"version": 8,
"cmakeMinimumRequired": {
"major": 3,
"minor": 28
},
"configurePresets": [
{
"name": "base",
"hidden": true,
"binaryDir": "build",
"installDir": "install",
"generator": "Ninja Multi-Config",
"cacheVariables": {
"Launcher_BUILD_ARTIFACT": "$penv{ARTIFACT_NAME}",
"Launcher_BUILD_PLATFORM": "$penv{BUILD_PLATFORM}",
"Launcher_ENABLE_JAVA_DOWNLOADER": "ON",
"ENABLE_LTO": "ON"
}
},
{
"name": "linux",
"displayName": "Linux",
"inherits": [
"base"
],
"condition": {
"type": "equals",
"lhs": "${hostSystemName}",
"rhs": "Linux"
}
},
{
"name": "macos",
"displayName": "macOS",
"inherits": [
"base"
],
"condition": {
"type": "equals",
"lhs": "${hostSystemName}",
"rhs": "Darwin"
},
"cacheVariables": {
"CMAKE_TOOLCHAIN_FILE": "$penv{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake"
}
},
{
"name": "macos_universal",
"displayName": "macOS (Universal Binary)",
"inherits": [
"macos"
],
"cacheVariables": {
"CMAKE_TOOLCHAIN_FILE": "$penv{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake",
"CMAKE_OSX_ARCHITECTURES": "x86_64;arm64",
"VCPKG_TARGET_TRIPLET": "universal-osx"
}
},
{
"name": "windows_mingw",
"displayName": "Windows (MinGW)",
"inherits": [
"base"
],
"condition": {
"type": "equals",
"lhs": "${hostSystemName}",
"rhs": "Windows"
}
},
{
"name": "windows_msvc",
"displayName": "Windows (MSVC)",
"inherits": [
"base"
],
"condition": {
"type": "equals",
"lhs": "${hostSystemName}",
"rhs": "Windows"
},
"cacheVariables": {
"CMAKE_TOOLCHAIN_FILE": "$penv{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake"
}
}
],
"buildPresets": [
{
"name": "linux",
"displayName": "Linux",
"condition": {
"type": "equals",
"lhs": "${hostSystemName}",
"rhs": "Linux"
},
"configurePreset": "linux"
},
{
"name": "macos",
"displayName": "macOS",
"condition": {
"type": "equals",
"lhs": "${hostSystemName}",
"rhs": "Darwin"
},
"configurePreset": "macos"
},
{
"name": "macos_universal",
"displayName": "macOS (Universal Binary)",
"inherits": [
"macos"
],
"configurePreset": "macos_universal"
},
{
"name": "windows_mingw",
"displayName": "Windows (MinGW)",
"condition": {
"type": "equals",
"lhs": "${hostSystemName}",
"rhs": "Windows"
},
"configurePreset": "windows_mingw"
},
{
"name": "windows_msvc",
"displayName": "Windows (MSVC)",
"condition": {
"type": "equals",
"lhs": "${hostSystemName}",
"rhs": "Windows"
},
"configurePreset": "windows_msvc"
}
],
"testPresets": [
{
"name": "base",
"hidden": true,
"output": {
"outputOnFailure": true,
"verbosity": "extra"
},
"execution": {
"noTestsAction": "error"
},
"filter": {
"exclude": {
"name": "^example64|example$"
}
}
},
{
"name": "linux",
"displayName": "Linux",
"inherits": [
"base"
],
"condition": {
"type": "equals",
"lhs": "${hostSystemName}",
"rhs": "Linux"
},
"configurePreset": "linux"
},
{
"name": "macos",
"displayName": "macOS",
"inherits": [
"base"
],
"condition": {
"type": "equals",
"lhs": "${hostSystemName}",
"rhs": "Darwin"
},
"configurePreset": "macos"
},
{
"name": "macos_universal",
"displayName": "macOS (Universal Binary)",
"inherits": [
"base"
],
"condition": {
"type": "equals",
"lhs": "${hostSystemName}",
"rhs": "Darwin"
},
"configurePreset": "macos_universal"
},
{
"name": "windows_mingw",
"displayName": "Windows (MinGW)",
"inherits": [
"base"
],
"condition": {
"type": "equals",
"lhs": "${hostSystemName}",
"rhs": "Windows"
},
"configurePreset": "windows_mingw"
},
{
"name": "windows_msvc",
"displayName": "Windows (MSVC)",
"inherits": [
"base"
],
"condition": {
"type": "equals",
"lhs": "${hostSystemName}",
"rhs": "Windows"
},
"configurePreset": "windows_msvc"
}
]
}

View file

@ -1,5 +1,52 @@
# Contributions Guidelines
## Restrictions on Generative AI Usage (AI Policy)
> [!NOTE]
> The following is adapted from [matplotlib's contributing guide](https://matplotlib.org/devdocs/devel/contribute.html#generative-ai) and the [Linux Kernel policy guide](https://www.kernel.org/doc./html/next/process/coding-assistants.html)
We expect authentic engagement in our community.
- Do not post output from Large Language Models or similar generative AI as comments on GitHub or our discord server, as such comments tend to be formulaic and low-quality content.
- If you use generative AI tools as an aid in developing code or documentation changes, ensure that you fully understand the proposed changes and can explain why they are the correct approach.
Make sure you have added value based on your personal competency to your contributions.
Just taking some input, feeding it to an AI and posting the result is not of value to the project.
To preserve precious core developer capacity, we reserve the right to rigorously reject seemingly AI generated low-value contributions.
### Signed-off-by and Developer Certificate of Origin
AI agents MUST NOT add Signed-off-by tags. Only humans can legally certify the Developer Certificate of Origin (DCO). The human submitter is responsible for:
- Reviewing all AI-generated code
- Ensuring compliance with licensing requirements
- Adding their own Signed-off-by tag to certify the DCO
- Taking full responsibility for the contribution
See [Signing your work](#signing-your-work) for more information.
### Attribution
When AI tools contribute to development, proper attribution helps track the evolving role of AI in the development process. Contributions should include an Assisted-by tag in the commit message with the following format:
```text
Assisted-by: AGENT_NAME:MODEL_VERSION [TOOL1] [TOOL2]
```
Where:
- `AGENT_NAME` is the name of the AI tool or framework
- `MODEL_VERSION` is the specific model version used
- `[TOOL1] [TOOL2]` are optional specialized analysis tools used (e.g., coccinelle, sparse, smatch, clang-tidy)
Basic development tools (git, gcc, make, editors) should not be listed.
Example:
```text
Assisted-by: Claude:claude-3-opus coccinelle sparse
```
## Code style
All files are formatted with `clang-format` using the configuration in `.clang-format`. Ensure it is run on changed files before committing!
@ -13,7 +60,8 @@ Please also follow the project's conventions for C++:
- Public, private or protected `static const` class data members should be formatted as `SCREAMING_SNAKE_CASE`: `MAX_VALUE`.
- Class function members should be formatted as `camelCase` without a prefix: `incrementCounter`.
- Global functions and non-`const` global variables should be formatted as `camelCase` without a prefix: `globalData`.
- `const` global variables, macros, and enum constants should be formatted as `SCREAMING_SNAKE_CASE`: `LIGHT_GRAY`.
- `const` global variables and macros should be formatted as `SCREAMING_SNAKE_CASE`: `LIGHT_GRAY`.
- enum constants should be formatted as `PascalCase`: `CamelusBactrianus`
- Avoid inventing acronyms or abbreviations especially for a name of multiple words - like `tp` for `texturePack`.
- Avoid using `[[nodiscard]]` unless ignoring the return value is likely to cause a bug in cases such as:
- A function allocates memory or another resource and the caller needs to clean it up.
@ -30,7 +78,7 @@ Here is what these conventions with the formatting configuration look like:
constexpr double PI = 3.14159;
enum class PizzaToppings { HAM_AND_PINEAPPLE, OREO_AND_KETCHUP };
enum class PizzaToppings { HamAndPineapple, OreoAndKetchup };
struct Person {
QString name;

View file

@ -1,7 +1,7 @@
## Prism Launcher
Prism Launcher - Minecraft Launcher
Copyright (C) 2022-2025 Prism Launcher Contributors
Copyright (C) 2022-2026 Prism Launcher Contributors
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

74
Containerfile Normal file
View file

@ -0,0 +1,74 @@
ARG DEBIAN_VERSION=stable-slim
FROM docker.io/library/debian:${DEBIAN_VERSION}
ARG QT_ABI=gcc_64
ARG QT_ARCH=
ARG QT_HOST=linux
ARG QT_TARGET=desktop
ARG QT_VERSION=6.10.2
ARG DEBIAN_FRONTEND=noninteractive
RUN apt-get update \
&& apt-get --assume-yes upgrade \
&& apt-get --assume-yes autopurge
# Use Adoptium for Java 17
RUN apt-get --assume-yes --no-install-recommends install \
apt-transport-https ca-certificates curl gpg
RUN curl -L https://packages.adoptium.net/artifactory/api/gpg/key/public | gpg --dearmor | tee /etc/apt/trusted.gpg.d/adoptium.gpg
RUN echo "deb https://packages.adoptium.net/artifactory/deb $(awk -F= '/^VERSION_CODENAME/{print$2}' /etc/os-release) main" | tee /etc/apt/sources.list.d/adoptium.list
RUN apt-get update
# Install base dependencies
RUN apt-get --assume-yes --no-install-recommends install \
# Compilers
clang lld llvm temurin-17-jdk \
# Build system
cmake ninja-build extra-cmake-modules pkg-config \
# Dependencies
cmark gamemode-dev libarchive-dev libcmark-dev libgamemode0 libgl1-mesa-dev libqrencode-dev libtomlplusplus-dev libvulkan-dev scdoc zlib1g-dev \
# Tooling
clang-format clang-tidy git
# Use LLD by default for faster linking
ENV CMAKE_LINKER_TYPE=lld
# Prepare and install Qt
## Setup UTF-8 locale (required, apparently)
RUN apt-get --assume-yes --no-install-recommends install locales
RUN echo "C.UTF-8 UTF-8" > /etc/locale.gen
RUN locale-gen
ENV LC_ALL=C.UTF-8
## Some libraries are required for the official binaries
RUN apt-get --assume-yes --no-install-recommends install \
libglib2.0-0t64 libxkbcommon0 python3-pip
RUN pip3 install --break-system-packages aqtinstall
RUN aqt install-qt \
${QT_HOST} ${QT_TARGET} ${QT_VERSION} ${QT_ARCH} \
--outputdir /opt/qt \
--modules qtimageformats qtnetworkauth
ENV PATH=/opt/qt/${QT_VERSION}/${QT_ABI}/bin:$PATH
ENV QT_PLUGIN_PATH=/opt/qt/${QT_VERSION}/${QT_ABI}/plugins/
## We don't use these. Nuke them
RUN rm -rf \
"$QT_PLUGIN_PATH"/designer \
"$QT_PLUGIN_PATH"/help \
# "$QT_PLUGIN_PATH"/platformthemes/libqgtk3.so \
"$QT_PLUGIN_PATH"/printsupport \
"$QT_PLUGIN_PATH"/qmllint \
"$QT_PLUGIN_PATH"/qmlls \
"$QT_PLUGIN_PATH"/qmltooling \
"$QT_PLUGIN_PATH"/sqldrivers
# Setup workspace
RUN mkdir /work
WORKDIR /work
ENTRYPOINT ["bash"]
CMD ["-i"]

View file

@ -27,17 +27,13 @@ Please understand that these builds are not intended for most users. There may b
There are development builds available through:
- [GitHub Actions](https://github.com/PrismLauncher/PrismLauncher/actions) (includes builds from pull requests opened by contributors)
- [nightly.link](https://nightly.link/PrismLauncher/PrismLauncher/workflows/build/develop) (this will always point only to the latest version of develop)
- [nightly.link](https://prismlauncher.org/nightly) (this will always point only to the latest version of develop)
These have debug information in the binaries, so their file sizes are relatively larger.
Prebuilt Development builds are provided for **Linux**, **Windows** and **macOS**.
For **Arch**, **Debian**, **Fedora**, **OpenSUSE (Tumbleweed)** and **Gentoo**, respectively, you can use these packages for the latest development versions:
[![prismlauncher-git](https://img.shields.io/badge/aur-prismlauncher--git-1793D1?label=AUR&logo=archlinux&logoColor=white)](https://aur.archlinux.org/packages/prismlauncher-git) [![prismlauncher-git](https://img.shields.io/badge/aur-prismlauncher--qt5--git-1793D1?label=AUR&logo=archlinux&logoColor=white)](https://aur.archlinux.org/packages/prismlauncher-qt5-git) [![prismlauncher-git](https://img.shields.io/badge/mpr-prismlauncher--git-A80030?label=MPR&logo=debian&logoColor=white)](https://mpr.makedeb.org/packages/prismlauncher-git)<br />[![prismlauncher-nightly](https://img.shields.io/badge/copr-prismlauncher--nightly-51A2DA?label=COPR&logo=fedora&logoColor=white)](https://copr.fedorainfracloud.org/coprs/g3tchoo/prismlauncher/) [![prismlauncher-nightly](https://img.shields.io/badge/OBS-prismlauncher--nightly-3AB6A9?logo=opensuse&logoColor=white)](https://build.opensuse.org/project/show/home:getchoo) [![prismlauncher-9999](https://img.shields.io/badge/gentoo-prismlauncher--9999-4D4270?label=Gentoo&logo=gentoo&logoColor=white)](https://packages.gentoo.org/packages/games-action/prismlauncher)
These packages are also available to all the distributions based on the ones mentioned above.
On Linux, we also offer our own [Flatpak nightly repository](https://github.com/PrismLauncher/flatpak). Most software centers are able to install it by opening [this link](https://flatpak.prismlauncher.org/prismlauncher-nightly.flatpakref).
## Community & Support
@ -61,12 +57,7 @@ The translation effort for Prism Launcher is hosted on [Weblate](https://hosted.
## Building
If you want to build Prism Launcher yourself, check the build instructions:
- [Windows](https://prismlauncher.org/wiki/development/build-instructions/windows/)
- [Linux](https://prismlauncher.org/wiki/development/build-instructions/linux/)
- [MacOS](https://prismlauncher.org/wiki/development/build-instructions/macos/)
- [OpenBSD](https://prismlauncher.org/wiki/development/build-instructions/openbsd/)
If you want to build Prism Launcher yourself, check the [build instructions](https://prismlauncher.org/wiki/development/build-instructions).
## Sponsors & Partners

View file

@ -33,7 +33,6 @@
* limitations under the License.
*/
#include <qstringliteral.h>
#include <QObject>
#include "BuildConfig.h"
@ -51,6 +50,7 @@ Config::Config()
LAUNCHER_GIT = "@Launcher_Git@";
LAUNCHER_APPID = "@Launcher_AppID@";
LAUNCHER_SVGFILENAME = "@Launcher_SVGFileName@";
LAUNCHER_ENVNAME = "@Launcher_ENVName@";
USER_AGENT = "@Launcher_UserAgent@";
@ -106,13 +106,14 @@ Config::Config()
NEWS_RSS_URL = "@Launcher_NEWS_RSS_URL@";
NEWS_OPEN_URL = "@Launcher_NEWS_OPEN_URL@";
WIKI_URL = "@Launcher_WIKI_URL@";
HELP_URL = "@Launcher_HELP_URL@";
LOGIN_CALLBACK_URL = "@Launcher_LOGIN_CALLBACK_URL@";
IMGUR_CLIENT_ID = "@Launcher_IMGUR_CLIENT_ID@";
MSA_CLIENT_ID = "@Launcher_MSA_CLIENT_ID@";
FLAME_API_KEY = "@Launcher_CURSEFORGE_API_KEY@";
META_URL = "@Launcher_META_URL@";
FMLLIBS_BASE_URL = "@Launcher_FMLLIBS_BASE_URL@";
LEGACY_FMLLIBS_BASE_URL = "@Launcher_LEGACY_FMLLIBS_BASE_URL@";
GLFW_LIBRARY_NAME = "@Launcher_GLFW_LIBRARY_NAME@";
OPENAL_LIBRARY_NAME = "@Launcher_OPENAL_LIBRARY_NAME@";

View file

@ -54,6 +54,7 @@ class Config {
QString LAUNCHER_GIT;
QString LAUNCHER_APPID;
QString LAUNCHER_SVGFILENAME;
QString LAUNCHER_ENVNAME;
/// The major version number.
int VERSION_MAJOR;
@ -128,7 +129,12 @@ class Config {
QString NEWS_OPEN_URL;
/**
* URL (with arg %1 to be substituted with page-id) that gets opened when the user requests help
* URL that gets opened when the user clicks 'Launcher Help'
*/
QString WIKI_URL;
/**
* URL (with arg %1 to be substituted with page-id) that gets opened when the user requests help in a dialog window
*/
QString HELP_URL;
@ -169,10 +175,10 @@ class Config {
QString DEFAULT_RESOURCE_BASE = "https://resources.download.minecraft.net/";
QString LIBRARY_BASE = "https://libraries.minecraft.net/";
QString IMGUR_BASE_URL = "https://api.imgur.com/3/";
QString FMLLIBS_BASE_URL;
QString LEGACY_FMLLIBS_BASE_URL;
QString TRANSLATION_FILES_URL;
QString MODPACKSCH_API_BASE_URL = "https://api.modpacks.ch/";
QString FTB_API_BASE_URL = "https://api.feed-the-beast.com/v1/modpacks/public";
QString LEGACY_FTB_CDN_BASE_URL = "https://dist.creeper.host/FTB2/";

View file

@ -1,163 +0,0 @@
#
# Function to set compiler warnings with reasonable defaults at the project level.
# Taken from https://github.com/aminya/project_options/blob/main/src/CompilerWarnings.cmake
# under the folowing license:
#
# MIT License
#
# Copyright (c) 2022-2100 Amin Yahyaabadi
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
#
include_guard()
function(_set_project_warnings_add_target_link_option TARGET OPTIONS)
target_link_options(${_project_name} INTERFACE ${OPTIONS})
endfunction()
# Set the compiler warnings
#
# https://clang.llvm.org/docs/DiagnosticsReference.html
# https://github.com/lefticus/cppbestpractices/blob/master/02-Use_the_Tools_Available.md
function(
set_project_warnings
_project_name
MSVC_WARNINGS
CLANG_WARNINGS
GCC_WARNINGS
)
if("${MSVC_WARNINGS}" STREQUAL "")
set(MSVC_WARNINGS
/W4 # Baseline reasonable warnings
/w14242 # 'identifier': conversion from 'type1' to 'type1', possible loss of data
/w14254 # 'operator': conversion from 'type1:field_bits' to 'type2:field_bits', possible loss of data
/w14263 # 'function': member function does not override any base class virtual member function
/w14265 # 'classname': class has virtual functions, but destructor is not virtual instances of this class may not
# be destructed correctly
/w14287 # 'operator': unsigned/negative constant mismatch
/we4289 # nonstandard extension used: 'variable': loop control variable declared in the for-loop is used outside
# the for-loop scope
/w14296 # 'operator': expression is always 'boolean_value'
/w14311 # 'variable': pointer truncation from 'type1' to 'type2'
/w14545 # expression before comma evaluates to a function which is missing an argument list
/w14546 # function call before comma missing argument list
/w14547 # 'operator': operator before comma has no effect; expected operator with side-effect
/w14549 # 'operator': operator before comma has no effect; did you intend 'operator'?
/w14555 # expression has no effect; expected expression with side- effect
/w14619 # pragma warning: there is no warning number 'number'
/w14640 # Enable warning on thread un-safe static member initialization
/w14826 # Conversion from 'type1' to 'type_2' is sign-extended. This may cause unexpected runtime behavior.
/w14905 # wide string literal cast to 'LPSTR'
/w14906 # string literal cast to 'LPWSTR'
/w14928 # illegal copy-initialization; more than one user-defined conversion has been implicitly applied
/permissive- # standards conformance mode for MSVC compiler.
/we4062 # forbid omitting a possible value of an enum in a switch statement
)
endif()
if("${CLANG_WARNINGS}" STREQUAL "")
set(CLANG_WARNINGS
-Wall
-Wextra # reasonable and standard
-Wshadow # warn the user if a variable declaration shadows one from a parent context
-Wnon-virtual-dtor # warn the user if a class with virtual functions has a non-virtual destructor. This helps
# catch hard to track down memory errors
-Wold-style-cast # warn for c-style casts
-Wcast-align # warn for potential performance problem casts
-Wunused # warn on anything being unused
-Woverloaded-virtual # warn if you overload (not override) a virtual function
-Wpedantic # warn if non-standard C++ is used
-Wconversion # warn on type conversions that may lose data
-Wsign-conversion # warn on sign conversions
-Wnull-dereference # warn if a null dereference is detected
-Wdouble-promotion # warn if float is implicit promoted to double
-Wformat=2 # warn on security issues around functions that format output (ie printf)
-Wimplicit-fallthrough # warn on statements that fallthrough without an explicit annotation
# -Wgnu-zero-variadic-macro-arguments (part of -pedantic) is triggered by every qCDebug() call and therefore results
# in a lot of noise. This warning is only notifying us that clang is emulating the GCC behaviour
# instead of the exact standard wording so we can safely ignore it
-Wno-gnu-zero-variadic-macro-arguments
-Werror=switch # forbid omitting a possible value of an enum in a switch statement
)
endif()
if("${GCC_WARNINGS}" STREQUAL "")
set(GCC_WARNINGS
${CLANG_WARNINGS}
-Wmisleading-indentation # warn if indentation implies blocks where blocks do not exist
-Wduplicated-cond # warn if if / else chain has duplicated conditions
-Wduplicated-branches # warn if if / else branches have duplicated code
-Wlogical-op # warn about logical operations being used where bitwise were probably wanted
-Wuseless-cast # warn if you perform a cast to the same type
-Werror=switch # forbid omitting a possible value of an enum in a switch statement
)
endif()
if(MSVC)
set(PROJECT_WARNINGS_CXX ${MSVC_WARNINGS})
elseif(CMAKE_CXX_COMPILER_ID MATCHES ".*Clang")
set(PROJECT_WARNINGS_CXX ${CLANG_WARNINGS})
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
set(PROJECT_WARNINGS_CXX ${GCC_WARNINGS})
else()
message(AUTHOR_WARNING "No compiler warnings set for CXX compiler: '${CMAKE_CXX_COMPILER_ID}'")
# TODO support Intel compiler
endif()
# Add C warnings
set(PROJECT_WARNINGS_C "${PROJECT_WARNINGS_CXX}")
list(
REMOVE_ITEM
PROJECT_WARNINGS_C
-Wnon-virtual-dtor
-Wold-style-cast
-Woverloaded-virtual
-Wuseless-cast
-Wextra-semi
-Werror=switch # forbid omitting a possible value of an enum in a switch statement
)
target_compile_options(
${_project_name}
INTERFACE # C++ warnings
$<$<COMPILE_LANGUAGE:CXX>:${PROJECT_WARNINGS_CXX}>
# C warnings
$<$<COMPILE_LANGUAGE:C>:${PROJECT_WARNINGS_C}>
)
# If we are using the compiler as a linker driver pass the warnings to it
# (most useful when using LTO or warnings as errors)
if(CMAKE_CXX_LINK_EXECUTABLE MATCHES "^<CMAKE_CXX_COMPILER>")
_set_project_warnings_add_target_link_option(
${_project_name} "$<$<COMPILE_LANGUAGE:CXX>:${PROJECT_WARNINGS_CXX}>"
)
endif()
if(CMAKE_C_LINK_EXECUTABLE MATCHES "^<CMAKE_C_COMPILER>")
_set_project_warnings_add_target_link_option(
${_project_name} "$<$<COMPILE_LANGUAGE:C>:${PROJECT_WARNINGS_C}>"
)
endif()
endfunction()

View file

@ -7,7 +7,7 @@
<key>NSMicrophoneUsageDescription</key>
<string>A Minecraft mod wants to access your microphone.</string>
<key>NSDownloadsFolderUsageDescription</key>
<string>Prism uses access to your Downloads folder to help you more quickly add mods that can't be automatically downloaded to your instance. You can change where Prism scans for downloaded mods in Settings or the prompt that appears.</string>
<string>${Launcher_DisplayName} uses access to your Downloads folder to help you more quickly add mods that can't be automatically downloaded to your instance. You can change where ${Launcher_DisplayName} scans for downloaded mods in Settings or the prompt that appears.</string>
<key>NSLocalNetworkUsageDescription</key>
<string>Minecraft uses the local network to find and connect to LAN servers.</string>
<key>NSPrincipalClass</key>
@ -21,7 +21,9 @@
<key>CFBundleGetInfoString</key>
<string>${MACOSX_BUNDLE_INFO_STRING}</string>
<key>CFBundleIconFile</key>
<string>${MACOSX_BUNDLE_ICON_FILE}</string>
<string>${Launcher_Name}</string>
<key>CFBundleIconName</key>
<string>${Launcher_Name}</string>
<key>CFBundleIdentifier</key>
<string>${MACOSX_BUNDLE_GUI_IDENTIFIER}</string>
<key>CFBundleInfoDictionaryVersion</key>
@ -42,6 +44,8 @@
<true/>
<key>LSRequiresCarbon</key>
<true/>
<key>LSApplicationCategoryType</key>
<string>public.app-category.games</string>
<key>NSHumanReadableCopyright</key>
<string>${MACOSX_BUNDLE_COPYRIGHT}</string>
<key>SUPublicEDKey</key>
@ -57,7 +61,7 @@
<string>mrpack</string>
</array>
<key>CFBundleTypeName</key>
<string>Prism Launcher instance</string>
<string>${Launcher_DisplayName} instance</string>
<key>CFBundleTypeOSTypes</key>
<array>
<string>TEXT</string>
@ -83,10 +87,11 @@
</dict>
<dict>
<key>CFBundleURLName</key>
<string>Prismlauncher</string>
<string>${Launcher_Name}</string>
<key>CFBundleURLSchemes</key>
<array>
<string>prismlauncher</string>
<string>${MACOSX_BUNDLE_EXECUTABLE_NAME}</string>
</array>
</dict>
</array>

View file

@ -3,11 +3,11 @@
"libnbtplusplus": {
"flake": false,
"locked": {
"lastModified": 1744811532,
"narHash": "sha256-qhmjaRkt+O7A+gu6HjUkl7QzOEb4r8y8vWZMG2R/C6o=",
"lastModified": 1772016279,
"narHash": "sha256-7itkptyjoRcXfGLwg1/jxajetZ3a4mDc66+w4X6yW8s=",
"owner": "PrismLauncher",
"repo": "libnbtplusplus",
"rev": "531449ba1c930c98e0bcf5d332b237a8566f9d78",
"rev": "687e43031df0dc641984b4256bcca50d5b3f7de3",
"type": "github"
},
"original": {
@ -18,18 +18,15 @@
},
"nixpkgs": {
"locked": {
"lastModified": 1765472234,
"narHash": "sha256-9VvC20PJPsleGMewwcWYKGzDIyjckEz8uWmT0vCDYK0=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "2fbfb1d73d239d2402a8fe03963e37aab15abe8b",
"type": "github"
"lastModified": 1776169885,
"narHash": "sha256-Gk2T0tDDDAs319hp/ak+bAIUG5bPMvnNEjPV8CS86Fg=",
"rev": "4bd9165a9165d7b5e33ae57f3eecbcb28fb231c9",
"type": "tarball",
"url": "https://releases.nixos.org/nixos/unstable/nixos-26.05pre980183.4bd9165a9165/nixexprs.tar.xz"
},
"original": {
"owner": "NixOS",
"ref": "nixos-unstable",
"repo": "nixpkgs",
"type": "github"
"type": "tarball",
"url": "https://channels.nixos.org/nixos-unstable/nixexprs.tar.xz"
}
},
"root": {

View file

@ -9,7 +9,7 @@
};
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
nixpkgs.url = "https://channels.nixos.org/nixos-unstable/nixexprs.tar.xz";
libnbtplusplus = {
url = "github:PrismLauncher/libnbtplusplus";
@ -42,7 +42,7 @@
let
pkgs = nixpkgsFor.${system};
llvm = pkgs.llvmPackages_19;
llvm = pkgs.llvmPackages_22;
in
{
@ -85,7 +85,9 @@
let
pkgs = nixpkgsFor.${system};
llvm = pkgs.llvmPackages_19;
llvm = pkgs.llvmPackages_22;
python = pkgs.python3;
mkShell = pkgs.mkShell.override { inherit (llvm) stdenv; };
packages' = self.packages.${system};
@ -131,18 +133,36 @@
in
{
default = pkgs.mkShell {
default = mkShell {
name = "prism-launcher";
inputsFrom = [ packages'.prismlauncher-unwrapped ];
packages = with pkgs; [
ccache
packages = [
pkgs.ccache
llvm.clang-tools
python # NOTE(@getchoo): Required for run-clang-tidy, etc.
(pkgs.stdenvNoCC.mkDerivation {
pname = "clang-tidy-diff";
inherit (llvm.clang) version;
nativeBuildInputs = [
pkgs.installShellFiles
python.pkgs.wrapPython
];
dontUnpack = true;
dontConfigure = true;
dontBuild = true;
postInstall = "installBin ${llvm.libclang.python}/share/clang/clang-tidy-diff.py";
postFixup = "wrapPythonPrograms";
})
];
cmakeBuildType = "Debug";
cmakeFlags = [ "-GNinja" ] ++ packages'.prismlauncher.cmakeFlags;
cmakeFlags = [ "-GNinja" ] ++ packages'.prismlauncher-unwrapped.cmakeFlags;
dontFixCmake = true;
shellHook = ''
@ -165,16 +185,24 @@
formatter = forAllSystems (system: nixpkgsFor.${system}.nixfmt-rfc-style);
overlays.default = final: prev: {
prismlauncher-unwrapped = prev.callPackage ./nix/unwrapped.nix {
inherit
libnbtplusplus
self
;
};
overlays.default =
final: prev:
prismlauncher = final.callPackage ./nix/wrapper.nix { };
};
let
llvm = final.llvmPackages_22 or prev.llvmPackages_22;
in
{
prismlauncher-unwrapped = prev.callPackage ./nix/unwrapped.nix {
inherit (llvm) stdenv;
inherit
libnbtplusplus
self
;
};
prismlauncher = final.callPackage ./nix/wrapper.nix { };
};
packages = forAllSystems (
system:

View file

@ -1,14 +0,0 @@
name: cmark
buildsystem: cmake-ninja
builddir: true
config-opts:
- -DCMAKE_TESTS=OFF
sources:
- type: archive
url: https://github.com/commonmark/cmark/archive/0.31.1.tar.gz
sha256: 3da93db5469c30588cfeb283d9d62edfc6ded9eb0edc10a4f5bbfb7d722ea802
x-checker-data:
type: anitya
project-id: 9159
stable-only: true
url-template: https://github.com/commonmark/cmark/archive/$version.tar.gz

View file

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

View file

@ -1,18 +0,0 @@
{
"name": "libdecor",
"buildsystem": "meson",
"config-opts": [
"-Ddemo=false"
],
"sources": [
{
"type": "git",
"url": "https://gitlab.freedesktop.org/libdecor/libdecor.git",
"commit": "c2bd8ad6fa42c0cb17553ce77ad8a87d1f543b1f"
}
],
"cleanup": [
"/include",
"/lib/pkgconfig"
]
}

View file

@ -1,154 +0,0 @@
id: org.prismlauncher.PrismLauncher
runtime: org.kde.Platform
runtime-version: '6.10'
sdk: org.kde.Sdk
sdk-extensions:
- org.freedesktop.Sdk.Extension.openjdk17
command: prismlauncher
finish-args:
- --share=ipc
- --socket=x11
- --socket=wayland
- --device=all
- --share=network
- --socket=pulseaudio
# for Discord RPC mods
- --filesystem=xdg-run/app/com.discordapp.Discord:create
# Mod drag&drop
- --filesystem=xdg-download:ro
# FTBApp import
- --filesystem=~/.ftba:ro
# Userspace visibility for manual hugepages configuration
# Required for -XX:+UseLargePages
- --filesystem=/sys/kernel/mm/hugepages:ro
# Userspace visibility for transparent hugepages configuration
# Required for -XX:+UseTransparentHugePages
- --filesystem=/sys/kernel/mm/transparent_hugepage:ro
modules:
- cmark.yml
- tomlplusplus.yml
# Might be needed by some Controller mods (see https://github.com/isXander/Controlify/issues/31)
- shared-modules/libusb/libusb.json
# Needed for proper Wayland support
- libdecor.json
# Text to Speech in the game
- flite.json
- name: prismlauncher
buildsystem: cmake-ninja
builddir: true
config-opts:
- -DLauncher_BUILD_PLATFORM=flatpak
# This allows us to manage and update Java independently of this Flatpak
- -DLauncher_ENABLE_JAVA_DOWNLOADER=ON
- -DCMAKE_BUILD_TYPE=RelWithDebInfo
build-options:
env:
JAVA_HOME: /usr/lib/sdk/openjdk17/jvm/openjdk-17
JAVA_COMPILER: /usr/lib/sdk/openjdk17/jvm/openjdk-17/bin/javac
run-tests: true
sources:
- type: dir
path: ../
- name: glfw
buildsystem: cmake-ninja
config-opts:
- -DCMAKE_BUILD_TYPE=RelWithDebInfo
- -DBUILD_SHARED_LIBS:BOOL=ON
- -DGLFW_BUILD_WAYLAND:BOOL=ON
- -DGLFW_BUILD_DOCS:BOOL=OFF
sources:
- type: git
url: https://github.com/glfw/glfw.git
commit: 7b6aead9fb88b3623e3b3725ebb42670cbe4c579 # 3.4
- type: patch
path: patches/0009-Defer-setting-cursor-position-until-the-cursor-is-lo.patch
cleanup:
- /include
- /lib/cmake
- /lib/pkgconfig
- name: xrandr
buildsystem: autotools
sources:
- type: archive
url: https://xorg.freedesktop.org/archive/individual/app/xrandr-1.5.3.tar.xz
sha256: f8dd7566adb74147fab9964680b6bbadee87cf406a7fcff51718a5e6949b841c
x-checker-data:
type: anitya
project-id: 14957
stable-only: true
url-template: https://xorg.freedesktop.org/archive/individual/app/xrandr-$version.tar.xz
cleanup:
- /share/man
- /bin/xkeystone
- name: gamemode
buildsystem: meson
config-opts:
- -Dwith-sd-bus-provider=no-daemon
- -Dwith-examples=false
post-install:
# gamemoderun is installed for users who want to use wrapper commands
# post-install is running inside the build dir, we need it from the source though
- install -Dm755 ../data/gamemoderun -t /app/bin
sources:
- type: archive
dest-filename: gamemode.tar.gz
url: https://api.github.com/repos/FeralInteractive/gamemode/tarball/1.8.2
sha256: 2886d4ce543c78bd2a364316d5e7fd59ef06b71de63f896b37c6d3dc97658f60
x-checker-data:
type: json
url: https://api.github.com/repos/FeralInteractive/gamemode/releases/latest
version-query: .tag_name
url-query: .tarball_url
timestamp-query: .published_at
cleanup:
- /include
- /lib/pkgconfig
- /lib/libgamemodeauto.a
- name: glxinfo
buildsystem: meson
config-opts:
- --bindir=/app/mesa-demos
- -Degl=disabled
- -Dglut=disabled
- -Dosmesa=disabled
- -Dvulkan=disabled
- -Dwayland=disabled
post-install:
- mv -v /app/mesa-demos/glxinfo /app/bin
sources:
- type: archive
url: https://archive.mesa3d.org/demos/mesa-demos-9.0.0.tar.xz
sha256: 3046a3d26a7b051af7ebdd257a5f23bfeb160cad6ed952329cdff1e9f1ed496b
x-checker-data:
type: anitya
project-id: 16781
stable-only: true
url-template: https://archive.mesa3d.org/demos/mesa-demos-$version.tar.xz
cleanup:
- /include
- /mesa-demos
- /share
modules:
- shared-modules/glu/glu-9.json
- name: enhance
buildsystem: simple
build-commands:
- install -Dm755 prime-run /app/bin/prime-run
- mv /app/bin/prismlauncher /app/bin/prismrun
- install -Dm755 prismlauncher /app/bin/prismlauncher
sources:
- type: file
path: prime-run
- type: file
path: prismlauncher

View file

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

View file

@ -1,4 +0,0 @@
#!/bin/sh
export __NV_PRIME_RENDER_OFFLOAD=1 __VK_LAYER_NV_optimus=NVIDIA_only __GLX_VENDOR_LIBRARY_NAME=nvidia
exec "$@"

View file

@ -1,11 +0,0 @@
#!/bin/bash
# discord RPC
for i in {0..9}; do
test -S "$XDG_RUNTIME_DIR"/discord-ipc-"$i" || ln -sf {app/com.discordapp.Discord,"$XDG_RUNTIME_DIR"}/discord-ipc-"$i";
done
export PATH="${PATH}${PATH:+:}/usr/lib/extensions/vulkan/gamescope/bin:/usr/lib/extensions/vulkan/MangoHud/bin"
export VK_LAYER_PATH="/usr/lib/extensions/vulkan/share/vulkan/implicit_layer.d/"
exec /app/bin/prismrun "$@"

@ -1 +0,0 @@
Subproject commit 73f08ed2c3187f6648ca04ebef030930a6c9f0be

View file

@ -1,6 +0,0 @@
name: tomlplusplus
buildsystem: cmake-ninja
sources:
- type: archive
url: https://github.com/marzer/tomlplusplus/archive/v3.4.0.tar.gz
sha256: 8517f65938a4faae9ccf8ebb36631a38c1cadfb5efa85d9a72e15b9e97d25155

View file

@ -50,6 +50,7 @@
#include "tools/GenericProfiler.h"
#include "ui/InstanceWindow.h"
#include "ui/MainWindow.h"
#include "ui/ToolTipFilter.h"
#include "ui/ViewLogWindow.h"
#include "ui/dialogs/ProgressDialog.h"
@ -125,12 +126,11 @@
#include <LocalPeer.h>
#include <stdlib.h>
#include <sys.h>
#include "SysInfo.h"
#ifdef Q_OS_LINUX
#include <dlfcn.h>
#include "MangoHud.h"
#include "LibraryUtils.h"
#include "gamemode_client.h"
#endif
@ -157,7 +157,6 @@
#endif
#include <windows.h>
#include <QStyleHints>
#include "console/WindowsConsole.h"
#endif
#include "console/Console.h"
@ -291,21 +290,9 @@ std::tuple<QDateTime, QString, QString, QString, QString> read_lock_File(const Q
Application::Application(int& argc, char** argv) : QApplication(argc, argv)
{
#if defined Q_OS_WIN32
// attach the parent console if stdout not already captured
if (AttachWindowsConsole()) {
consoleAttached = true;
if (auto err = EnableAnsiSupport(); !err) {
isANSIColorConsole = true;
} else {
std::cout << "Error setting up ansi console" << err.message() << std::endl;
}
}
#else
if (console::isConsole()) {
isANSIColorConsole = true;
}
#endif
setOrganizationName(BuildConfig.LAUNCHER_NAME);
setOrganizationDomain(BuildConfig.LAUNCHER_DOMAIN);
@ -331,6 +318,7 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv)
{ { "a", "profile" }, "Use the account specified by its profile name (only valid in combination with --launch)", "profile" },
{ { "o", "offline" }, "Launch offline, with given player name (only valid in combination with --launch)", "offline" },
{ "alive", "Write a small '" + liveCheckFile + "' file after the launcher starts" },
{ "show-window", "Show the main launcher window (useful in combination with --launch)" },
{ { "I", "import" }, "Import instance or resource from specified local path or URL", "url" },
{ "show", "Opens the window for the specified instance (by instance ID)", "show" } });
// Has to be positional for some OS to handle that properly
@ -346,12 +334,13 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv)
m_worldToJoin = parser.value("world");
m_profileToUse = parser.value("profile");
if (parser.isSet("offline")) {
m_offline = true;
m_launchOffline = true;
m_offlineName = parser.value("offline");
}
m_liveCheck = parser.isSet("alive");
m_instanceIdToShowWindowOf = parser.value("show");
m_showMainWindow = parser.isSet("show-window");
for (auto url : parser.values("import")) {
m_urlsToImport.append(normalizeImportUrl(url));
@ -363,7 +352,7 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv)
}
// error if --launch is missing with --server or --profile
if ((!m_serverToJoin.isEmpty() || !m_worldToJoin.isEmpty() || !m_profileToUse.isEmpty() || m_offline) &&
if ((!m_serverToJoin.isEmpty() || !m_worldToJoin.isEmpty() || !m_profileToUse.isEmpty() || m_launchOffline) &&
m_instanceIdToLaunch.isEmpty()) {
std::cerr << "--server, --profile and --offline can only be used in combination with --launch!" << std::endl;
m_status = Application::Failed;
@ -371,25 +360,7 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv)
}
QString origcwdPath = QDir::currentPath();
#if defined(Q_OS_LINUX)
const QString binFilePath = applicationFilePath();
const bool isAppImage = binFilePath.startsWith("/tmp/.mount_");
// Yes, this can technically trigger the logic below if someone makes an AppImage with an actual launcher exe named "ld-linux"
// Please don't :)
const bool executedFromLinker = QFileInfo(binFilePath).fileName().startsWith("ld-linux");
// NOTE(@getchoo): In order for `go-appimage` to generate self-contained AppImages, it executes apps from a bundled linker at
// <root>/lib64
// This is not the path to our actual binary, which we want
QString binPath;
if (isAppImage && executedFromLinker) {
binPath = FS::PathCombine(applicationDirPath(), "../usr/bin");
} else {
binPath = applicationDirPath();
}
#else
QString binPath = applicationDirPath();
#endif
{
// Root path is used for updates and portable data
@ -423,7 +394,7 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv)
} else {
QDir foo;
if (DesktopServices::isSnap()) {
foo = QDir(getenv("SNAP_USER_COMMON"));
foo = QDir(qEnvironmentVariable("SNAP_USER_COMMON"));
} else {
foo = QDir(FS::PathCombine(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation), ".."));
}
@ -509,7 +480,7 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv)
if (!m_profileToUse.isEmpty()) {
launch.args["profile"] = m_profileToUse;
}
if (m_offline) {
if (m_launchOffline) {
launch.args["offline_enabled"] = "true";
launch.args["offline_name"] = m_offlineName;
}
@ -543,12 +514,13 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv)
logFile = std::unique_ptr<QFile>(new QFile(logBase.arg(0)));
if (!logFile->open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate)) {
showFatalErrorMessage("The launcher data folder is not writable!",
QString("The launcher couldn't create a log file - the data folder is not writable.\n"
QString("The launcher couldn't create a log file - %1.\n"
"\n"
"Make sure you have write permissions to the data folder.\n"
"(%1)\n"
"(%2)\n"
"\n"
"The launcher cannot continue until you fix this problem.")
.arg(logFile->errorString())
.arg(dataPath));
return;
}
@ -620,25 +592,25 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv)
{
qInfo() << qPrintable(BuildConfig.LAUNCHER_DISPLAYNAME + ", " + QString(BuildConfig.LAUNCHER_COPYRIGHT).replace("\n", ", "));
qInfo() << "Version : " << BuildConfig.printableVersionString();
qInfo() << "Platform : " << BuildConfig.BUILD_PLATFORM;
qInfo() << "Git commit : " << BuildConfig.GIT_COMMIT;
qInfo() << "Git refspec : " << BuildConfig.GIT_REFSPEC;
qInfo() << "Compiled for : " << BuildConfig.systemID();
qInfo() << "Compiled by : " << BuildConfig.compilerID();
qInfo() << "Build Artifact : " << BuildConfig.BUILD_ARTIFACT;
qInfo() << "Updates Enabled : " << (updaterEnabled() ? "Yes" : "No");
qInfo() << "Version :" << BuildConfig.printableVersionString();
qInfo() << "Platform :" << BuildConfig.BUILD_PLATFORM;
qInfo() << "Git commit :" << BuildConfig.GIT_COMMIT;
qInfo() << "Git refspec :" << BuildConfig.GIT_REFSPEC;
qInfo() << "Compiled for :" << BuildConfig.systemID();
qInfo() << "Compiled by :" << BuildConfig.compilerID();
qInfo() << "Build Artifact :" << BuildConfig.BUILD_ARTIFACT;
qInfo() << "Updates Enabled :" << (updaterEnabled() ? "Yes" : "No");
if (adjustedBy.size()) {
qInfo() << "Work dir before adjustment : " << origcwdPath;
qInfo() << "Work dir after adjustment : " << QDir::currentPath();
qInfo() << "Adjusted by : " << adjustedBy;
qInfo() << "Work dir before adjustment :" << origcwdPath;
qInfo() << "Work dir after adjustment :" << QDir::currentPath();
qInfo() << "Adjusted by :" << adjustedBy;
} else {
qInfo() << "Work dir : " << QDir::currentPath();
qInfo() << "Work dir :" << QDir::currentPath();
}
qInfo() << "Binary path : " << binPath;
qInfo() << "Application root path : " << m_rootPath;
qInfo() << "Binary path :" << binPath;
qInfo() << "Application root path :" << m_rootPath;
if (!m_instanceIdToLaunch.isEmpty()) {
qInfo() << "ID of instance to launch : " << m_instanceIdToLaunch;
qInfo() << "ID of instance to launch :" << m_instanceIdToLaunch;
}
if (!m_serverToJoin.isEmpty()) {
qInfo() << "Address of server to join :" << m_serverToJoin;
@ -655,11 +627,11 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv)
if (check.write(payload) == payload.size()) {
check.close();
} else {
qWarning() << "Could not write into" << liveCheckFile << "!";
qWarning() << "Could not write into" << liveCheckFile << "error:" << check.errorString();
check.remove(); // also closes file!
}
} else {
qWarning() << "Could not open" << liveCheckFile << "for writing!";
qWarning() << "Could not open" << liveCheckFile << "for writing:" << check.errorString();
}
}
@ -702,8 +674,8 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv)
QFontInfo consoleFontInfo(consoleFont);
QString resolvedDefaultMonospace = consoleFontInfo.family();
QFont resolvedFont(resolvedDefaultMonospace);
qDebug() << "Detected default console font:" << resolvedDefaultMonospace
<< ", substitutions:" << resolvedFont.substitutions().join(',');
qDebug().nospace() << "Detected default console font: " << resolvedDefaultMonospace
<< ", substitutions: " << resolvedFont.substitutions().join(',');
m_settings->registerSetting("ConsoleFont", resolvedDefaultMonospace);
m_settings->registerSetting("ConsoleFontSize", defaultSize);
@ -761,8 +733,9 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv)
// Memory
m_settings->registerSetting({ "MinMemAlloc", "MinMemoryAlloc" }, 512);
m_settings->registerSetting({ "MaxMemAlloc", "MaxMemoryAlloc" }, SysInfo::suitableMaxMem());
m_settings->registerSetting({ "MaxMemAlloc", "MaxMemoryAlloc" }, SysInfo::defaultMaxJvmMem());
m_settings->registerSetting("PermGen", 128);
m_settings->registerSetting("LowMemWarning", true);
// Java Settings
m_settings->registerSetting("JavaPath", "");
@ -805,6 +778,7 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv)
m_settings->registerSetting("ModMetadataDisabled", false);
m_settings->registerSetting("ModDependenciesDisabled", false);
m_settings->registerSetting("SkipModpackUpdatePrompt", false);
m_settings->registerSetting("ShowModIncompat", false);
// Minecraft offline player name
m_settings->registerSetting("LastOfflinePlayerName", "");
@ -845,6 +819,8 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv)
m_settings->registerSetting("UpdateDialogGeometry", "");
m_settings->registerSetting("NewsGeometry", "");
m_settings->registerSetting("ModDownloadGeometry", "");
m_settings->registerSetting("RPDownloadGeometry", "");
m_settings->registerSetting("TPDownloadGeometry", "");
@ -879,25 +855,23 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv)
}
}
{
auto resetIfInvalid = [this](const Setting* setting) {
if (const QUrl url(setting->get().toString()); !url.isValid() || (url.scheme() != "http" && url.scheme() != "https")) {
m_settings->reset(setting->id());
}
};
// Meta URL
m_settings->registerSetting("MetaURLOverride", "");
QUrl metaUrl(m_settings->get("MetaURLOverride").toString());
// get rid of invalid meta urls
if (!metaUrl.isValid() || (metaUrl.scheme() != "http" && metaUrl.scheme() != "https"))
m_settings->reset("MetaURLOverride");
resetIfInvalid(m_settings->registerSetting("MetaURLOverride", "").get());
// Resource URL
m_settings->registerSetting("ResourceURL", BuildConfig.DEFAULT_RESOURCE_BASE);
resetIfInvalid(m_settings->registerSetting({ "ResourceURLOverride", "ResourceURL" }, "").get());
QUrl resourceUrl(m_settings->get("ResourceURL").toString());
// get rid of invalid resource urls
if (!resourceUrl.isValid() || (resourceUrl.scheme() != "http" && resourceUrl.scheme() != "https"))
m_settings->reset("ResourceURL");
// Legacy FML libs URL
resetIfInvalid(m_settings->registerSetting("LegacyFMLLibsURLOverride", "").get());
}
m_settings->registerSetting("MetaRefreshOnLaunch", true);
m_settings->registerSetting("CloseAfterLaunch", false);
m_settings->registerSetting("QuitAfterGameStop", false);
@ -917,6 +891,7 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv)
m_settings->set("FlameKeyOverride", flameKey);
m_settings->reset("CFKeyOverride");
}
m_settings->registerSetting("FallbackMRBlockedMods", true);
m_settings->registerSetting("ModrinthToken", "");
m_settings->registerSetting("UserAgentOverride", "");
@ -928,7 +903,7 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv)
// Init page provider
{
m_globalSettingsProvider = std::make_shared<GenericPageProvider>(tr("Settings"));
m_globalSettingsProvider = std::make_unique<GenericPageProvider>(tr("Settings"));
m_globalSettingsProvider->addPage<LauncherPage>();
m_globalSettingsProvider->addPage<LanguagePage>();
m_globalSettingsProvider->addPage<AppearancePage>();
@ -1005,11 +980,11 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv)
// instance path: check for problems with '!' in instance path and warn the user in the log
// and remember that we have to show him a dialog when the gui starts (if it does so)
QString instDir = m_settings->get("InstanceDir").toString();
qInfo() << "Instance path : " << instDir;
qInfo() << "Instance path :" << instDir;
if (FS::checkProblemticPathJava(QDir(instDir))) {
qWarning() << "Your instance path contains \'!\' and this is known to cause java problems!";
}
m_instances.reset(new InstanceList(m_settings, instDir, this));
m_instances.reset(new InstanceList(m_settings.get(), instDir, this));
connect(InstDirSetting.get(), &Setting::SettingChanged, m_instances.get(), &InstanceList::on_InstFolderChanged);
qInfo() << "Loading Instances...";
m_instances->loadList();
@ -1043,6 +1018,7 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv)
m_metacache->addBase("translations", QDir("translations").absolutePath());
m_metacache->addBase("meta", QDir("meta").absolutePath());
m_metacache->addBase("java", QDir("cache/java").absolutePath());
m_metacache->addBase("feed", QDir("cache/feed").absolutePath());
m_metacache->Load();
qInfo() << "<> Cache initialized.";
}
@ -1055,12 +1031,12 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv)
m_profilers.insert("jvisualvm", std::shared_ptr<BaseProfilerFactory>(new JVisualVMFactory()));
m_profilers.insert("generic", std::shared_ptr<BaseProfilerFactory>(new GenericProfilerFactory()));
for (auto profiler : m_profilers.values()) {
profiler->registerSettings(m_settings);
profiler->registerSettings(m_settings.get());
}
// Create the MCEdit thing... why is this here?
{
m_mcedit.reset(new MCEditTool(m_settings));
m_mcedit.reset(new MCEditTool(m_settings.get()));
}
#ifdef Q_OS_MACOS
@ -1217,6 +1193,10 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv)
}
}
if (qgetenv("XDG_CURRENT_DESKTOP") == "gamescope") {
installEventFilter(new ToolTipFilter);
}
if (createSetupWizard()) {
return;
}
@ -1377,8 +1357,11 @@ void Application::performMainStartupAction()
qDebug() << " Launching with account" << m_profileToUse;
}
launch(inst, !m_offline, false, targetToJoin, accountToUse, m_offlineName);
return;
launch(inst, m_launchOffline ? LaunchMode::Offline : LaunchMode::Normal, targetToJoin, accountToUse, m_offlineName);
if (!m_showMainWindow) {
return;
}
}
}
if (!m_instanceIdToShowWindowOf.isEmpty()) {
@ -1431,16 +1414,6 @@ Application::~Application()
{
// Shut down logger by setting the logger function to nothing
qInstallMessageHandler(nullptr);
#if defined Q_OS_WIN32
// Detach from Windows console
if (consoleAttached) {
fclose(stdout);
fclose(stdin);
fclose(stderr);
FreeConsole();
}
#endif
}
void Application::messageReceived(const QByteArray& message)
@ -1482,7 +1455,7 @@ void Application::messageReceived(const QByteArray& message)
bool offline = received.args["offline_enabled"] == "true";
QString offlineName = received.args["offline_name"];
InstancePtr instance;
BaseInstance* instance;
if (!id.isEmpty()) {
instance = instances()->getInstanceById(id);
if (!instance) {
@ -1510,23 +1483,23 @@ void Application::messageReceived(const QByteArray& message)
}
}
launch(instance, !offline, false, serverObject, accountObject, offlineName);
launch(instance, offline ? LaunchMode::Offline : LaunchMode::Normal, serverObject, accountObject, offlineName);
} else {
qWarning() << "Received invalid message" << message;
}
}
std::shared_ptr<TranslationsModel> Application::translations()
TranslationsModel* Application::translations()
{
return m_translations;
return m_translations.get();
}
std::shared_ptr<JavaInstallList> Application::javalist()
JavaInstallList* Application::javalist()
{
if (!m_javalist) {
m_javalist.reset(new JavaInstallList());
}
return m_javalist;
return m_javalist.get();
}
QIcon Application::logo()
@ -1545,9 +1518,8 @@ bool Application::openJsonEditor(const QString& filename)
}
}
bool Application::launch(InstancePtr instance,
bool online,
bool demo,
bool Application::launch(BaseInstance* instance,
LaunchMode mode,
MinecraftTarget::Ptr targetToJoin,
MinecraftAccountPtr accountToUse,
const QString& offlineName)
@ -1566,8 +1538,7 @@ bool Application::launch(InstancePtr instance,
auto& controller = extras.controller;
controller.reset(new LaunchController());
controller->setInstance(instance);
controller->setOnline(online);
controller->setDemo(demo);
controller->setLaunchMode(mode);
controller->setProfiler(profilers().value(instance->settings()->get("Profiler").toString(), nullptr).get());
controller->setTargetToJoin(targetToJoin);
controller->setAccountToUse(accountToUse);
@ -1577,9 +1548,7 @@ bool Application::launch(InstancePtr instance,
} else if (m_mainWindow) {
controller->setParentWidget(m_mainWindow);
}
connect(controller.get(), &LaunchController::succeeded, this, &Application::controllerSucceeded);
connect(controller.get(), &LaunchController::failed, this, &Application::controllerFailed);
connect(controller.get(), &LaunchController::aborted, this, [this] { controllerFailed(tr("Aborted")); });
connect(controller.get(), &LaunchController::finished, this, &Application::controllerFinished);
addRunningInstance();
QMetaObject::invokeMethod(controller.get(), &Task::start, Qt::QueuedConnection);
return true;
@ -1593,7 +1562,7 @@ bool Application::launch(InstancePtr instance,
return false;
}
bool Application::kill(InstancePtr instance)
bool Application::kill(BaseInstance* instance)
{
if (!instance->isRunning()) {
qWarning() << "Attempted to kill instance" << instance->id() << ", which isn't running.";
@ -1602,7 +1571,7 @@ bool Application::kill(InstancePtr instance)
QMutexLocker locker(&m_instanceExtrasMutex);
auto& extras = m_instanceExtras[instance->id()];
// NOTE: copy of the shared pointer keeps it alive
auto controller = extras.controller;
auto& controller = extras.controller;
locker.unlock();
if (controller) {
return controller->abort();
@ -1651,7 +1620,7 @@ void Application::updateIsRunning(bool running)
m_updateRunning = running;
}
void Application::controllerSucceeded()
void Application::controllerFinished()
{
auto controller = qobject_cast<LaunchController*>(sender());
if (!controller)
@ -1659,10 +1628,11 @@ void Application::controllerSucceeded()
auto id = controller->id();
QMutexLocker locker(&m_instanceExtrasMutex);
auto& extras = m_instanceExtras[id];
auto& extras = m_instanceExtras.at(id);
const bool wasSuccessful = controller->wasSuccessful();
// on success, do...
if (controller->instance()->settings()->get("AutoCloseConsole").toBool()) {
if (wasSuccessful && controller->instance()->settings()->get("AutoCloseConsole").toBool()) {
if (extras.window) {
QMetaObject::invokeMethod(extras.window, &QWidget::close, Qt::QueuedConnection);
}
@ -1672,29 +1642,8 @@ void Application::controllerSucceeded()
// quit when there are no more windows.
if (shouldExitNow()) {
m_status = Status::Succeeded;
exit(0);
}
}
void Application::controllerFailed(const QString& error)
{
Q_UNUSED(error);
auto controller = qobject_cast<LaunchController*>(sender());
if (!controller)
return;
auto id = controller->id();
QMutexLocker locker(&m_instanceExtrasMutex);
auto& extras = m_instanceExtras[id];
// on failure, do... nothing
extras.controller.reset();
subRunningInstance();
// quit when there are no more windows.
if (shouldExitNow()) {
m_status = Status::Failed;
exit(1);
m_status = wasSuccessful ? Succeeded : Failed;
exit(wasSuccessful ? 0 : 1);
}
}
@ -1751,7 +1700,7 @@ ViewLogWindow* Application::showLogWindow()
return m_viewLogWindow;
}
InstanceWindow* Application::showInstanceWindow(InstancePtr instance, QString page)
InstanceWindow* Application::showInstanceWindow(BaseInstance* instance, QString page)
{
if (!instance)
return nullptr;
@ -1863,22 +1812,22 @@ void Application::updateProxySettings(QString proxyTypeStr, QString addr, int po
qDebug() << proxyDesc;
}
shared_qobject_ptr<HttpMetaCache> Application::metacache()
HttpMetaCache* Application::metacache()
{
return m_metacache;
return m_metacache.get();
}
shared_qobject_ptr<QNetworkAccessManager> Application::network()
QNetworkAccessManager* Application::network()
{
return m_network;
return m_network.get();
}
shared_qobject_ptr<Meta::Index> Application::metadataIndex()
Meta::Index* Application::metadataIndex()
{
if (!m_metadataIndex) {
m_metadataIndex.reset(new Meta::Index());
}
return m_metadataIndex;
return m_metadataIndex.get();
}
void Application::updateCapabilities()
@ -1893,7 +1842,7 @@ void Application::updateCapabilities()
if (gamemode_query_status() >= 0)
m_capabilities |= SupportsGameMode;
if (!MangoHud::getLibraryString().isEmpty())
if (!LibraryUtils::findMangoHud().isEmpty())
m_capabilities |= SupportsMangoHud;
#endif
}
@ -1901,8 +1850,8 @@ void Application::updateCapabilities()
void Application::detectLibraries()
{
#ifdef Q_OS_LINUX
m_detectedGLFWPath = MangoHud::findLibrary(BuildConfig.GLFW_LIBRARY_NAME);
m_detectedOpenALPath = MangoHud::findLibrary(BuildConfig.OPENAL_LIBRARY_NAME);
m_detectedGLFWPath = LibraryUtils::find(BuildConfig.GLFW_LIBRARY_NAME);
m_detectedOpenALPath = LibraryUtils::find(BuildConfig.OPENAL_LIBRARY_NAME);
qDebug() << "Detected native libraries:" << m_detectedGLFWPath << m_detectedOpenALPath;
#endif
}
@ -2009,7 +1958,7 @@ bool Application::handleDataMigration(const QString& currentData,
auto setDoNotMigrate = [&nomigratePath] {
QFile file(nomigratePath);
if (!file.open(QIODevice::WriteOnly)) {
qWarning() << "setDoNotMigrate failed; Failed to open file '" << file.fileName() << "' for writing!";
qWarning() << "setDoNotMigrate failed; Failed to open file" << file.fileName() << "for writing:" << file.errorString();
}
};
@ -2063,7 +2012,7 @@ void Application::triggerUpdateCheck()
}
}
QUrl Application::normalizeImportUrl(QString const& url)
QUrl Application::normalizeImportUrl(const QString& url)
{
auto local_file = QFileInfo(url);
if (local_file.exists()) {

View file

@ -37,6 +37,8 @@
#pragma once
#include <memory>
#include <QApplication>
#include <QDateTime>
#include <QDebug>
@ -44,12 +46,10 @@
#include <QIcon>
#include <QMutex>
#include <QUrl>
#include <memory>
#include <BaseInstance.h>
#include "QObjectPtr.h"
#include "launch/LogModel.h"
#include "minecraft/launch/MinecraftTarget.h"
#include "minecraft/auth/MinecraftAccount.h"
class LaunchController;
class LocalPeer;
@ -74,6 +74,12 @@ class ITheme;
class MCEditTool;
class ThemeManager;
class IconTheme;
class BaseInstance;
class LogModel;
struct MinecraftTarget;
class MinecraftAccount;
namespace Meta {
class Index;
@ -91,7 +97,6 @@ class Index;
#define APPLICATION_DYN (dynamic_cast<Application*>(QCoreApplication::instance()))
class Application : public QApplication {
// friends for the purpose of limiting access to deprecated stuff
Q_OBJECT
public:
enum Status { StartingUp, Failed, Succeeded, Initialized };
@ -112,7 +117,7 @@ class Application : public QApplication {
bool event(QEvent* event) override;
std::shared_ptr<SettingsObject> settings() const { return m_settings; }
SettingsObject* settings() const { return m_settings.get(); }
qint64 timeSinceStart() const { return m_startTime.msecsTo(QDateTime::currentDateTime()); }
@ -120,21 +125,21 @@ class Application : public QApplication {
ThemeManager* themeManager() { return m_themeManager.get(); }
shared_qobject_ptr<ExternalUpdater> updater() { return m_updater; }
ExternalUpdater* updater() { return m_updater.get(); }
void triggerUpdateCheck();
std::shared_ptr<TranslationsModel> translations();
TranslationsModel* translations();
std::shared_ptr<JavaInstallList> javalist();
JavaInstallList* javalist();
std::shared_ptr<InstanceList> instances() const { return m_instances; }
InstanceList* instances() const { return m_instances.get(); }
std::shared_ptr<IconList> icons() const { return m_icons; }
IconList* icons() const { return m_icons.get(); }
MCEditTool* mcedit() const { return m_mcedit.get(); }
shared_qobject_ptr<AccountList> accounts() const { return m_accounts; }
AccountList* accounts() const { return m_accounts.get(); }
Status status() const { return m_status; }
@ -142,11 +147,11 @@ class Application : public QApplication {
void updateProxySettings(QString proxyTypeStr, QString addr, int port, QString user, QString password);
shared_qobject_ptr<QNetworkAccessManager> network();
QNetworkAccessManager* network();
shared_qobject_ptr<HttpMetaCache> metacache();
HttpMetaCache* metacache();
shared_qobject_ptr<Meta::Index> metadataIndex();
Meta::Index* metadataIndex();
void updateCapabilities();
@ -182,7 +187,7 @@ class Application : public QApplication {
*/
bool openJsonEditor(const QString& filename);
InstanceWindow* showInstanceWindow(InstancePtr instance, QString page = QString());
InstanceWindow* showInstanceWindow(BaseInstance* instance, QString page = QString());
MainWindow* showMainWindow(bool minimized = false);
ViewLogWindow* showLogWindow();
@ -194,7 +199,7 @@ class Application : public QApplication {
bool updaterEnabled();
QString updaterBinaryName();
QUrl normalizeImportUrl(QString const& url);
QUrl normalizeImportUrl(const QString& url);
signals:
void updateAllowedChanged(bool status);
@ -209,20 +214,18 @@ class Application : public QApplication {
#endif
public slots:
bool launch(InstancePtr instance,
bool online = true,
bool demo = false,
MinecraftTarget::Ptr targetToJoin = nullptr,
MinecraftAccountPtr accountToUse = nullptr,
bool launch(BaseInstance* instance,
LaunchMode mode = LaunchMode::Normal,
std::shared_ptr<MinecraftTarget> targetToJoin = nullptr,
shared_qobject_ptr<MinecraftAccount> accountToUse = nullptr,
const QString& offlineName = QString());
bool kill(InstancePtr instance);
bool kill(BaseInstance* instance);
void closeCurrentWindow();
private slots:
void on_windowClose();
void messageReceived(const QByteArray& message);
void controllerSucceeded();
void controllerFailed(const QString& error);
void controllerFinished();
void setupWizardFinished(int status);
private:
@ -238,23 +241,27 @@ class Application : public QApplication {
void subRunningInstance();
bool shouldExitNow() const;
private:
QHash<QString, int> m_qsaveResources;
mutable QMutex m_qsaveResourcesMutex;
private:
QDateTime m_startTime;
shared_qobject_ptr<QNetworkAccessManager> m_network;
std::unique_ptr<QNetworkAccessManager> m_network;
shared_qobject_ptr<ExternalUpdater> m_updater;
shared_qobject_ptr<AccountList> m_accounts;
std::unique_ptr<ExternalUpdater> m_updater;
std::unique_ptr<AccountList> m_accounts;
shared_qobject_ptr<HttpMetaCache> m_metacache;
shared_qobject_ptr<Meta::Index> m_metadataIndex;
std::unique_ptr<HttpMetaCache> m_metacache;
std::unique_ptr<Meta::Index> m_metadataIndex;
std::shared_ptr<SettingsObject> m_settings;
std::shared_ptr<InstanceList> m_instances;
std::shared_ptr<IconList> m_icons;
std::shared_ptr<JavaInstallList> m_javalist;
std::shared_ptr<TranslationsModel> m_translations;
std::shared_ptr<GenericPageProvider> m_globalSettingsProvider;
std::unique_ptr<SettingsObject> m_settings;
std::unique_ptr<InstanceList> m_instances;
std::unique_ptr<IconList> m_icons;
std::unique_ptr<JavaInstallList> m_javalist;
std::unique_ptr<TranslationsModel> m_translations;
std::unique_ptr<GenericPageProvider> m_globalSettingsProvider;
std::unique_ptr<MCEditTool> m_mcedit;
QSet<QString> m_features;
std::unique_ptr<ThemeManager> m_themeManager;
@ -271,15 +278,10 @@ class Application : public QApplication {
Qt::ApplicationState m_prevAppState = Qt::ApplicationInactive;
#endif
#if defined Q_OS_WIN32
// used on Windows to attach the standard IO streams
bool consoleAttached = false;
#endif
// FIXME: attach to instances instead.
struct InstanceXtras {
InstanceWindow* window = nullptr;
shared_qobject_ptr<LaunchController> controller;
std::unique_ptr<LaunchController> controller;
};
std::map<QString, InstanceXtras> m_instanceExtras;
mutable QMutex m_instanceExtrasMutex;
@ -307,20 +309,17 @@ class Application : public QApplication {
QString m_serverToJoin;
QString m_worldToJoin;
QString m_profileToUse;
bool m_offline = false;
bool m_launchOffline = false;
QString m_offlineName;
bool m_liveCheck = false;
QList<QUrl> m_urlsToImport;
QString m_instanceIdToShowWindowOf;
bool m_showMainWindow = false;
std::unique_ptr<QFile> logFile;
shared_qobject_ptr<LogModel> logModel;
std::unique_ptr<LogModel> logModel;
public:
void addQSavePath(QString);
void removeQSavePath(QString);
bool checkQSavePath(QString);
private:
QHash<QString, int> m_qsaveResources;
mutable QMutex m_qsaveResourcesMutex;
};

25
launcher/AssertHelpers.h Normal file
View file

@ -0,0 +1,25 @@
// SPDX-License-Identifier: GPL-3.0-only
/*
* Prism Launcher - Minecraft Launcher
* Copyright (C) 2025 Octol1ttle <l1ttleofficial@outlook.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#pragma once
#if defined(ASSERT_NEVER)
#error ASSERT_NEVER already defined
#else
#define ASSERT_NEVER(cond) (Q_ASSERT((cond) == false), (cond))
#endif

View file

@ -45,6 +45,7 @@
#include "Application.h"
#include "Json.h"
#include "launch/LaunchTask.h"
#include "settings/INISettingsObject.h"
#include "settings/OverrideSetting.h"
#include "settings/Setting.h"
@ -53,7 +54,7 @@
#include "Commandline.h"
#include "FileSystem.h"
int getConsoleMaxLines(SettingsObjectPtr settings)
int getConsoleMaxLines(SettingsObject* settings)
{
auto lineSetting = settings->getSetting("ConsoleMaxLines");
bool conversionOk = false;
@ -65,14 +66,14 @@ int getConsoleMaxLines(SettingsObjectPtr settings)
return maxLines;
}
bool shouldStopOnConsoleOverflow(SettingsObjectPtr settings)
bool shouldStopOnConsoleOverflow(SettingsObject* settings)
{
return settings->get("ConsoleOverflowStop").toBool();
}
BaseInstance::BaseInstance(SettingsObjectPtr globalSettings, SettingsObjectPtr settings, const QString& rootDir) : QObject()
BaseInstance::BaseInstance(SettingsObject* globalSettings, std::unique_ptr<SettingsObject> settings, const QString& rootDir) : QObject()
{
m_settings = settings;
m_settings = std::move(settings);
m_global_settings = globalSettings;
m_rootDir = rootDir;
@ -122,10 +123,13 @@ BaseInstance::BaseInstance(SettingsObjectPtr globalSettings, SettingsObjectPtr s
m_settings->registerSetting("ManagedPackName", "");
m_settings->registerSetting("ManagedPackVersionID", "");
m_settings->registerSetting("ManagedPackVersionName", "");
m_settings->registerSetting("ManagedPackURL", "");
m_settings->registerSetting("Profiler", "");
}
BaseInstance::~BaseInstance() {}
QString BaseInstance::getPreLaunchCommand()
{
return settings()->get("PreLaunchCommand").toString();
@ -335,11 +339,11 @@ QString BaseInstance::instanceRoot() const
return m_rootDir;
}
SettingsObjectPtr BaseInstance::settings()
SettingsObject* BaseInstance::settings()
{
loadSpecificSettings();
return m_settings;
return m_settings.get();
}
bool BaseInstance::canLaunch() const
@ -467,9 +471,9 @@ QStringList BaseInstance::extraArguments()
return Commandline::splitArgs(settings()->get("JvmArgs").toString());
}
shared_qobject_ptr<LaunchTask> BaseInstance::getLaunchTask()
LaunchTask* BaseInstance::getLaunchTask()
{
return m_launchProcess;
return m_launchProcess.get();
}
void BaseInstance::updateRuntimeContext()

View file

@ -64,9 +64,6 @@ class Task;
class LaunchTask;
class BaseInstance;
// pointer for lazy people
using InstancePtr = std::shared_ptr<BaseInstance>;
/// Shortcut saving target representations
enum class ShortcutTarget { Desktop, Applications, Other };
@ -78,8 +75,8 @@ struct ShortcutData {
};
/// Console settings
int getConsoleMaxLines(SettingsObjectPtr settings);
bool shouldStopOnConsoleOverflow(SettingsObjectPtr settings);
int getConsoleMaxLines(SettingsObject* settings);
bool shouldStopOnConsoleOverflow(SettingsObject* settings);
/*!
* \brief Base class for instances.
@ -89,11 +86,11 @@ bool shouldStopOnConsoleOverflow(SettingsObjectPtr settings);
* To create a new instance type, create a new class inheriting from this class
* and implement the pure virtual functions.
*/
class BaseInstance : public QObject, public std::enable_shared_from_this<BaseInstance> {
class BaseInstance : public QObject {
Q_OBJECT
protected:
/// no-touchy!
BaseInstance(SettingsObjectPtr globalSettings, SettingsObjectPtr settings, const QString& rootDir);
BaseInstance(SettingsObject* globalSettings, std::unique_ptr<SettingsObject> settings, const QString& rootDir);
public: /* types */
enum class Status {
@ -103,7 +100,7 @@ class BaseInstance : public QObject, public std::enable_shared_from_this<BaseIns
public:
/// virtual destructor to make sure the destruction is COMPLETE
virtual ~BaseInstance() {}
virtual ~BaseInstance();
virtual void saveNow() = 0;
@ -193,7 +190,7 @@ class BaseInstance : public QObject, public std::enable_shared_from_this<BaseIns
*
* \return A pointer to this instance's settings object.
*/
virtual SettingsObjectPtr settings();
virtual SettingsObject* settings();
/*!
* \brief Loads settings specific to an instance type if they're not already loaded.
@ -204,10 +201,10 @@ class BaseInstance : public QObject, public std::enable_shared_from_this<BaseIns
virtual QList<Task::Ptr> createUpdateTask() = 0;
/// returns a valid launcher (task container)
virtual shared_qobject_ptr<LaunchTask> createLaunchTask(AuthSessionPtr account, MinecraftTarget::Ptr targetToJoin) = 0;
virtual LaunchTask* createLaunchTask(AuthSessionPtr account, MinecraftTarget::Ptr targetToJoin) = 0;
/// returns the current launch task (if any)
shared_qobject_ptr<LaunchTask> getLaunchTask();
LaunchTask* getLaunchTask();
/*!
* Create envrironment variables for running the instance
@ -286,7 +283,7 @@ class BaseInstance : public QObject, public std::enable_shared_from_this<BaseIns
protected:
void changeStatus(Status newStatus);
SettingsObjectPtr globalSettings() const { return m_global_settings.lock(); }
SettingsObject* globalSettings() const { return m_global_settings; }
bool isSpecificSettingsLoaded() const { return m_specific_settings_loaded; }
void setSpecificSettingsLoaded(bool loaded) { m_specific_settings_loaded = loaded; }
@ -297,7 +294,7 @@ class BaseInstance : public QObject, public std::enable_shared_from_this<BaseIns
*/
void propertiesChanged(BaseInstance* inst);
void launchTaskChanged(shared_qobject_ptr<LaunchTask>);
void launchTaskChanged(LaunchTask*);
void runningStatusChanged(bool running);
@ -310,10 +307,10 @@ class BaseInstance : public QObject, public std::enable_shared_from_this<BaseIns
protected: /* data */
QString m_rootDir;
SettingsObjectPtr m_settings;
std::unique_ptr<SettingsObject> m_settings;
// InstanceFlags m_flags;
bool m_isRunning = false;
shared_qobject_ptr<LaunchTask> m_launchProcess;
std::unique_ptr<LaunchTask> m_launchProcess;
QDateTime m_timeStarted;
RuntimeContext m_runtimeContext;
@ -323,7 +320,7 @@ class BaseInstance : public QObject, public std::enable_shared_from_this<BaseIns
bool m_hasUpdate = false;
bool m_hasBrokenVersion = false;
SettingsObjectWeakPtr m_global_settings;
SettingsObject* m_global_settings;
bool m_specific_settings_loaded = false;
};

View file

@ -24,6 +24,7 @@
*/
class BaseVersion {
public:
// TODO: delete
using Ptr = std::shared_ptr<BaseVersion>;
virtual ~BaseVersion() {}
/*!

View file

@ -63,7 +63,7 @@ class BaseVersionList : public QAbstractListModel {
* The task returned by this function should reset the model when it's done.
* \return A pointer to a task that reloads the version list.
*/
virtual Task::Ptr getLoadTask() = 0;
virtual Task::Ptr getLoadTask(bool forceReload = false) = 0;
//! Checks whether or not the list is loaded. If this returns false, the list should be
// loaded.

View file

@ -26,13 +26,13 @@ set(CORE_SOURCES
NullInstance.h
MMCZip.h
MMCZip.cpp
archive/ArchiveReader.cpp
archive/ArchiveReader.h
archive/ArchiveWriter.cpp
archive/ArchiveWriter.h
archive/ExportToZipTask.cpp
archive/ArchiveReader.cpp
archive/ArchiveReader.h
archive/ArchiveWriter.cpp
archive/ArchiveWriter.h
archive/ExportToZipTask.cpp
archive/ExportToZipTask.h
archive/ExtractZipTask.cpp
archive/ExtractZipTask.cpp
archive/ExtractZipTask.h
StringUtils.h
StringUtils.cpp
@ -75,9 +75,6 @@ set(CORE_SOURCES
# RW lock protected map
RWStorage.h
# A variable that has an implicit default value and keeps track of changes
DefaultVariable.h
# a smart pointer wrapper intended for safer use with Qt signal/slot mechanisms
QObjectPtr.h
@ -102,14 +99,17 @@ set(CORE_SOURCES
MMCTime.cpp
MTPixmapCache.h
# Assertion helper
AssertHelpers.h
)
if (UNIX AND NOT CYGWIN AND NOT APPLE)
set(CORE_SOURCES
${CORE_SOURCES}
# MangoHud
MangoHud.h
MangoHud.cpp
# LibraryUtils
LibraryUtils.h
LibraryUtils.cpp
)
endif()
@ -119,6 +119,7 @@ set(NET_SOURCES
net/ChecksumValidator.h
net/Download.cpp
net/Download.h
net/DummySink.h
net/FileSink.cpp
net/FileSink.h
net/HttpMetaCache.cpp
@ -243,15 +244,13 @@ set(MINECRAFT_SOURCES
minecraft/auth/steps/MSAStep.h
minecraft/auth/steps/XboxAuthorizationStep.cpp
minecraft/auth/steps/XboxAuthorizationStep.h
minecraft/auth/steps/XboxProfileStep.cpp
minecraft/auth/steps/XboxProfileStep.h
minecraft/auth/steps/XboxUserStep.cpp
minecraft/auth/steps/XboxUserStep.h
minecraft/update/AssetUpdateTask.h
minecraft/update/AssetUpdateTask.cpp
minecraft/update/FMLLibrariesTask.cpp
minecraft/update/FMLLibrariesTask.h
minecraft/update/LegacyFMLLibrariesTask.cpp
minecraft/update/LegacyFMLLibrariesTask.h
minecraft/update/FoldersTask.cpp
minecraft/update/FoldersTask.h
minecraft/update/LibrariesTask.cpp
@ -261,6 +260,10 @@ set(MINECRAFT_SOURCES
minecraft/launch/ClaimAccount.h
minecraft/launch/CreateGameFolders.cpp
minecraft/launch/CreateGameFolders.h
minecraft/launch/EnsureAvailableMemory.cpp
minecraft/launch/EnsureAvailableMemory.h
minecraft/launch/EnsureOfflineLibraries.cpp
minecraft/launch/EnsureOfflineLibraries.h
minecraft/launch/ModMinecraftJar.cpp
minecraft/launch/ModMinecraftJar.h
minecraft/launch/ExtractNatives.cpp
@ -346,6 +349,7 @@ set(MINECRAFT_SOURCES
minecraft/mod/TexturePackFolderModel.h
minecraft/mod/TexturePackFolderModel.cpp
minecraft/mod/ShaderPackFolderModel.h
minecraft/mod/ShaderPackFolderModel.cpp
minecraft/mod/tasks/ResourceFolderLoadTask.h
minecraft/mod/tasks/ResourceFolderLoadTask.cpp
minecraft/mod/tasks/LocalModParseTask.h
@ -525,6 +529,11 @@ set(FTB_SOURCES
modplatform/import_ftb/PackInstallTask.cpp
modplatform/import_ftb/PackHelpers.h
modplatform/import_ftb/PackHelpers.cpp
modplatform/ftb/FTBPackInstallTask.h
modplatform/ftb/FTBPackInstallTask.cpp
modplatform/ftb/FTBPackManifest.h
modplatform/ftb/FTBPackManifest.cpp
)
set(FLAME_SOURCES
@ -621,10 +630,10 @@ set(PRISMUPDATER_SOURCES
# Zip
MMCZip.h
MMCZip.cpp
archive/ArchiveReader.cpp
archive/ArchiveReader.h
archive/ArchiveWriter.cpp
archive/ArchiveWriter.h
archive/ArchiveReader.cpp
archive/ArchiveReader.h
archive/ArchiveWriter.cpp
archive/ArchiveWriter.h
# Time
MMCTime.h
@ -790,6 +799,8 @@ SET(LAUNCHER_SOURCES
ApplicationMessage.cpp
SysInfo.h
SysInfo.cpp
HardwareInfo.cpp
HardwareInfo.h
# console utils
console/Console.h
@ -806,23 +817,6 @@ SET(LAUNCHER_SOURCES
KonamiCode.h
KonamiCode.cpp
# Bundled resources
resources/backgrounds/backgrounds.qrc
resources/multimc/multimc.qrc
resources/pe_dark/pe_dark.qrc
resources/pe_light/pe_light.qrc
resources/pe_colored/pe_colored.qrc
resources/pe_blue/pe_blue.qrc
resources/breeze_dark/breeze_dark.qrc
resources/breeze_light/breeze_light.qrc
resources/OSX/OSX.qrc
resources/iOS/iOS.qrc
resources/flat/flat.qrc
resources/flat_white/flat_white.qrc
resources/documents/documents.qrc
resources/shaders/shaders.qrc
"${CMAKE_CURRENT_BINARY_DIR}/../${Launcher_Branding_LogoQRC}"
# Icons
icons/MMCIcon.h
icons/MMCIcon.cpp
@ -842,6 +836,8 @@ SET(LAUNCHER_SOURCES
ui/InstanceWindow.cpp
ui/ViewLogWindow.h
ui/ViewLogWindow.cpp
ui/ToolTipFilter.h
ui/ToolTipFilter.cpp
# FIXME: maybe find a better home for this.
FileIgnoreProxy.cpp
@ -890,6 +886,7 @@ SET(LAUNCHER_SOURCES
ui/themes/CatPainter.h
# Processes
LaunchMode.h
LaunchController.h
LaunchController.cpp
@ -1000,6 +997,13 @@ SET(LAUNCHER_SOURCES
ui/pages/modplatform/atlauncher/AtlUserInteractionSupportImpl.cpp
ui/pages/modplatform/atlauncher/AtlUserInteractionSupportImpl.h
ui/pages/modplatform/ftb/FtbFilterModel.cpp
ui/pages/modplatform/ftb/FtbFilterModel.h
ui/pages/modplatform/ftb/FtbListModel.cpp
ui/pages/modplatform/ftb/FtbListModel.h
ui/pages/modplatform/ftb/FtbPage.cpp
ui/pages/modplatform/ftb/FtbPage.h
ui/pages/modplatform/legacy_ftb/Page.cpp
ui/pages/modplatform/legacy_ftb/Page.h
ui/pages/modplatform/legacy_ftb/ListModel.h
@ -1063,6 +1067,8 @@ SET(LAUNCHER_SOURCES
ui/dialogs/ImportResourceDialog.h
ui/dialogs/MSALoginDialog.cpp
ui/dialogs/MSALoginDialog.h
ui/dialogs/NetworkJobFailedDialog.cpp
ui/dialogs/NetworkJobFailedDialog.h
ui/dialogs/NewComponentDialog.cpp
ui/dialogs/NewComponentDialog.h
ui/dialogs/NewInstanceDialog.cpp
@ -1229,6 +1235,7 @@ qt_wrap_ui(LAUNCHER_UI
ui/pages/modplatform/import_ftb/ImportFTBPage.ui
ui/pages/modplatform/ImportPage.ui
ui/pages/modplatform/OptionalModDialog.ui
ui/pages/modplatform/ftb/FtbPage.ui
ui/pages/modplatform/modrinth/ModrinthPage.ui
ui/pages/modplatform/technic/TechnicPage.ui
ui/widgets/CustomCommands.ui
@ -1244,6 +1251,7 @@ qt_wrap_ui(LAUNCHER_UI
ui/dialogs/ProfileSetupDialog.ui
ui/dialogs/ProgressDialog.ui
ui/dialogs/NewInstanceDialog.ui
ui/dialogs/NetworkJobFailedDialog.ui
ui/dialogs/NewComponentDialog.ui
ui/dialogs/NewsDialog.ui
ui/dialogs/ProfileSelectDialog.ui
@ -1282,6 +1290,7 @@ qt_add_resources(LAUNCHER_RESOURCES
resources/OSX/OSX.qrc
resources/iOS/iOS.qrc
resources/flat/flat.qrc
resources/flat_white/flat_white.qrc
resources/documents/documents.qrc
resources/shaders/shaders.qrc
"${CMAKE_CURRENT_BINARY_DIR}/../${Launcher_Branding_LogoQRC}"
@ -1298,18 +1307,29 @@ if(WIN32)
set(LAUNCHER_RCS ${CMAKE_CURRENT_BINARY_DIR}/../${Launcher_Branding_WindowsRC})
endif()
include(CompilerWarnings)
######## Precompiled Headers ###########
if(${Launcher_USE_PCH})
message(STATUS "Using precompiled headers for applicable launcher targets")
set(PRECOMPILED_HEADERS
include/base.pch.hpp
include/qtcore.pch.hpp
include/qtgui.pch.hpp
)
endif()
####### Targets ########
# Add executable
add_library(Launcher_logic STATIC ${LOGIC_SOURCES} ${LAUNCHER_SOURCES} ${LAUNCHER_UI} ${LAUNCHER_RESOURCES})
set_project_warnings(Launcher_logic
"${Launcher_MSVC_WARNINGS}"
"${Launcher_CLANG_WARNINGS}"
"${Launcher_GCC_WARNINGS}")
target_include_directories(Launcher_logic PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
target_compile_definitions(Launcher_logic PUBLIC LAUNCHER_APPLICATION)
if(${Launcher_USE_PCH})
target_precompile_headers(Launcher_logic PRIVATE ${PRECOMPILED_HEADERS})
endif()
target_link_libraries(Launcher_logic
systeminfo
Launcher_murmur2
nbt++
${ZLIB_LIBRARIES}
@ -1386,9 +1406,12 @@ if(APPLE)
endif()
endif()
target_link_libraries(Launcher_logic)
add_executable(${Launcher_Name} MACOSX_BUNDLE WIN32 main.cpp ${LAUNCHER_RCS})
if(${Launcher_USE_PCH})
target_precompile_headers(${Launcher_Name} REUSE_FROM Launcher_logic)
endif()
target_link_libraries(${Launcher_Name} Launcher_logic)
if(DEFINED Launcher_APP_BINARY_NAME)
@ -1412,17 +1435,21 @@ install(TARGETS ${Launcher_Name}
)
# Deploy PDBs
if(WIN32 AND (CMAKE_BUILD_TYPE STREQUAL "Debug" OR CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo"))
install(FILES $<TARGET_PDB_FILE:${Launcher_Name}> DESTINATION ${BINARY_DEST_DIR})
if(CMAKE_CXX_LINKER_SUPPORTS_PDB)
install(FILES $<TARGET_PDB_FILE:${Launcher_Name}> DESTINATION ${BINARY_DEST_DIR} OPTIONAL)
endif()
if(Launcher_BUILD_UPDATER)
# Updater
add_library(prism_updater_logic STATIC ${PRISMUPDATER_SOURCES} ${TASKS_SOURCES} ${PRISMUPDATER_UI})
target_include_directories(prism_updater_logic PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
if(${Launcher_USE_PCH})
target_precompile_headers(prism_updater_logic PRIVATE ${PRECOMPILED_HEADERS})
endif()
target_link_libraries(prism_updater_logic
${ZLIB_LIBRARIES}
systeminfo
BuildConfig
Qt${QT_VERSION_MAJOR}::Widgets
Qt${QT_VERSION_MAJOR}::Core
@ -1440,6 +1467,10 @@ if(Launcher_BUILD_UPDATER)
target_sources("${Launcher_Name}_updater" PRIVATE updater/prismupdater/updater.exe.manifest)
target_link_libraries("${Launcher_Name}_updater" prism_updater_logic)
if(${Launcher_USE_PCH})
target_precompile_headers("${Launcher_Name}_updater" REUSE_FROM prism_updater_logic)
endif()
if(DEFINED Launcher_APP_BINARY_NAME)
set_target_properties("${Launcher_Name}_updater" PROPERTIES OUTPUT_NAME "${Launcher_APP_BINARY_NAME}_updater")
endif()
@ -1455,22 +1486,22 @@ if(Launcher_BUILD_UPDATER)
)
# Deploy PDBs
if(WIN32 AND (CMAKE_BUILD_TYPE STREQUAL "Debug" OR CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo"))
install(FILES $<TARGET_PDB_FILE:${Launcher_Name}_updater> DESTINATION ${BINARY_DEST_DIR})
if(CMAKE_CXX_LINKER_SUPPORTS_PDB)
install(FILES $<TARGET_PDB_FILE:${Launcher_Name}_updater> DESTINATION ${BINARY_DEST_DIR} OPTIONAL)
endif()
endif()
if(WIN32 OR (DEFINED Launcher_BUILD_FILELINKER AND Launcher_BUILD_FILELINKER))
# File link
add_library(filelink_logic STATIC ${LINKEXE_SOURCES})
set_project_warnings(filelink_logic
"${Launcher_MSVC_WARNINGS}"
"${Launcher_CLANG_WARNINGS}"
"${Launcher_GCC_WARNINGS}")
target_include_directories(filelink_logic PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
if(${Launcher_USE_PCH})
target_precompile_headers(filelink_logic PRIVATE ${PRECOMPILED_HEADERS})
endif()
target_link_libraries(filelink_logic
systeminfo
BuildConfig
Qt${QT_VERSION_MAJOR}::Widgets
Qt${QT_VERSION_MAJOR}::Core
@ -1480,8 +1511,12 @@ if(WIN32 OR (DEFINED Launcher_BUILD_FILELINKER AND Launcher_BUILD_FILELINKER))
)
add_executable("${Launcher_Name}_filelink" WIN32 filelink/filelink_main.cpp)
target_sources("${Launcher_Name}_filelink" PRIVATE filelink/filelink.exe.manifest)
if(${Launcher_USE_PCH})
target_precompile_headers("${Launcher_Name}_filelink" REUSE_FROM filelink_logic)
endif()
# HACK: Fix manifest issues with Ninja in release mode (and only release mode) and MSVC
# I have no idea why this works or why it's needed. UPDATE THIS IF YOU EDIT THE MANIFEST!!! -@getchoo
# Thank you 2018 CMake mailing list thread https://cmake.cmake.narkive.com/LnotZXus/conflicting-msvc-manifests
@ -1506,8 +1541,8 @@ if(WIN32 OR (DEFINED Launcher_BUILD_FILELINKER AND Launcher_BUILD_FILELINKER))
)
# Deploy PDBs
if(WIN32 AND (CMAKE_BUILD_TYPE STREQUAL "Debug" OR CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo"))
install(FILES $<TARGET_PDB_FILE:${Launcher_Name}_filelink> DESTINATION ${BINARY_DEST_DIR})
if(CMAKE_CXX_LINKER_SUPPORTS_PDB)
install(FILES $<TARGET_PDB_FILE:${Launcher_Name}_filelink> DESTINATION ${BINARY_DEST_DIR} OPTIONAL)
endif()
endif()
@ -1518,6 +1553,26 @@ if (UNIX AND APPLE AND Launcher_ENABLE_UPDATER)
install(DIRECTORY ${MACOSX_SPARKLE_DIR}/Sparkle.framework DESTINATION ${FRAMEWORK_DEST_DIR} USE_SOURCE_PERMISSIONS)
endif()
# Set basic compiler warning/error flags for all targets
get_property(Launcher_TARGETS DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY BUILDSYSTEM_TARGETS)
foreach(target ${Launcher_TARGETS})
message(STATUS "Enabling all warnings as errors for target '${target}'")
if (CMAKE_CXX_COMPILER_FRONTEND_VARIANT STREQUAL "MSVC")
target_compile_options(${target} PRIVATE /W4 /WX /permissive-)
else()
target_compile_options(${target} PRIVATE -Wall -Wextra -Wpedantic -Werror)
endif()
endforeach()
# Disable some warnings in main launcher target due to being present in a lot of places. TODO: Fix them.
if (CMAKE_CXX_COMPILER_FRONTEND_VARIANT STREQUAL "MSVC")
target_compile_options(Launcher_logic PRIVATE /wd4100) # C4100 - unused parameter
target_compile_options(${Launcher_Name} PRIVATE /wd4100) # C4100 - unused parameter
else()
target_compile_options(Launcher_logic PRIVATE -Wno-unused-parameter -Wno-missing-field-initializers)
target_compile_options(${Launcher_Name} PRIVATE -Wno-unused-parameter -Wno-missing-field-initializers)
endif()
#### The bundle mess! ####
# Bundle utilities are used to complete packages for different platforms - they add all the libraries that would otherwise be missing on the target system.
# NOTE: it seems that this absolutely has to be here, and nowhere else.
@ -1567,6 +1622,49 @@ if(WIN32 OR (UNIX AND APPLE))
SCRIPT ${QT_DEPLOY_SCRIPT}
COMPONENT bundle
)
# FIXME: remove this crap once we stop using msys2
if(MINGW)
# i've not found a solution better than injecting the config vars like this...
# with install(CODE" for everything everything just breaks
install(CODE "
set(QT_PLUGINS_DIR \"${QT_PLUGINS_DIR}\")
set(QT_LIBS_DIR \"${QT_LIBS_DIR}\")
set(QT_LIBEXECS_DIR \"${QT_LIBEXECS_DIR}\")
set(CMAKE_SYSTEM_LIBRARY_PATH \"${CMAKE_SYSTEM_LIBRARY_PATH}\")
set(CMAKE_INSTALL_PREFIX \"${CMAKE_INSTALL_PREFIX}\")
"
COMPONENT bundle)
install(CODE [[
file(GLOB QT_IMAGEFORMAT_DLLS "${QT_PLUGINS_DIR}/imageformats/*.dll")
set(CMAKE_GET_RUNTIME_DEPENDENCIES_TOOL objdump)
file(GET_RUNTIME_DEPENDENCIES
RESOLVED_DEPENDENCIES_VAR imageformatdeps
LIBRARIES ${QT_IMAGEFORMAT_DLLS}
DIRECTORIES
${CMAKE_SYSTEM_LIBRARY_PATH}
${QT_PLUGINS_DIR}
${QT_LIBS_DIR}
${QT_LIBEXECS_DIR}
PRE_EXCLUDE_REGEXES
"^(api-ms-win|ext-ms)-.*\\.dll$"
# FIXME: Why aren't these caught by the below regex???
"^azure.*\\.dll$"
"^vcruntime.*\\.dll$"
POST_EXCLUDE_REGEXES
"system32"
)
foreach(_lib ${imageformatdeps})
file(INSTALL
DESTINATION ${CMAKE_INSTALL_PREFIX}
TYPE SHARED_LIBRARY
FOLLOW_SYMLINK_CHAIN
FILES ${_lib}
)
endforeach()
]]
COMPONENT bundle)
endif()
# Add qt.conf - this makes Qt stop looking for things outside the bundle
install(
@ -1580,3 +1678,15 @@ if(WIN32 OR (UNIX AND APPLE))
COMPONENT bundle
)
endif()
find_program(CLANG_FORMAT clang-format OPTIONAL)
if(CLANG_FORMAT)
message(STATUS "Creating clang-format target")
add_custom_target(
clang-format
COMMAND ${CLANG_FORMAT} -i --style=file:${CMAKE_SOURCE_DIR}/.clang-format ${LOGIC_SOURCES} ${LAUNCHER_SOURCES} ${PRISMUPDATER_SOURCES} ${LINKEXE_SOURCES} ${PRECOMPILED_HEADERS}
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
)
else()
message(WARNING "Unable to find `clang-format`. Not creating custom target")
endif()

View file

@ -63,7 +63,7 @@ void DataMigrationTask::dryRunFinished()
void DataMigrationTask::dryRunAborted()
{
emitFailed(tr("Aborted"));
emitAborted();
}
void DataMigrationTask::copyFinished()
@ -81,5 +81,5 @@ void DataMigrationTask::copyFinished()
void DataMigrationTask::copyAborted()
{
emitFailed(tr("Aborted"));
emitAborted();
}

View file

@ -1,23 +0,0 @@
#pragma once
template <typename T>
class DefaultVariable {
public:
DefaultVariable(const T& value) { defaultValue = value; }
DefaultVariable<T>& operator=(const T& value)
{
currentValue = value;
is_default = currentValue == defaultValue;
is_explicit = true;
return *this;
}
operator const T&() const { return is_default ? defaultValue : currentValue; }
bool isDefault() const { return is_default; }
bool isExplicit() const { return is_explicit; }
private:
T currentValue;
T defaultValue;
bool is_default = true;
bool is_explicit = false;
};

View file

@ -2,7 +2,6 @@
/*
* Prism Launcher - Minecraft Launcher
* Copyright (C) 2022 dada513 <dada513@protonmail.com>
* Copyright (C) 2025 Seth Flynn <getchoo@tuta.io>
*
* 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
@ -76,15 +75,6 @@ bool isFlatpak()
#endif
}
bool isSelfContained()
{
#ifdef Q_OS_LINUX
return QFileInfo(QCoreApplication::applicationFilePath()).fileName().startsWith("ld-linux");
#else
return false;
#endif
}
bool isSnap()
{
#ifdef Q_OS_LINUX

View file

@ -37,11 +37,6 @@ bool openUrl(const QUrl& url);
*/
bool isFlatpak();
/**
* Determine whether the launcher is running in a self-contained Linux bundle
*/
bool isSelfContained();
/**
* Determine whether the launcher is running in a Snap environment
*/

View file

@ -44,4 +44,4 @@ QIcon FastFileIconProvider::icon(const QFileInfo& info) const
}
return QApplication::style()->standardIcon(icon);
}
}

View file

@ -23,4 +23,4 @@
class FastFileIconProvider : public QFileIconProvider {
public:
QIcon icon(const QFileInfo& info) const override;
};
};

View file

@ -266,7 +266,21 @@ bool FileIgnoreProxy::filterAcceptsRow(int sourceRow, const QModelIndex& sourceP
bool FileIgnoreProxy::ignoreFile(QFileInfo fileInfo) const
{
return m_ignoreFiles.contains(fileInfo.fileName()) || m_ignoreFilePaths.covers(relPath(fileInfo.absoluteFilePath()));
if (m_ignoreFiles.contains(fileInfo.fileName())) {
return true;
}
for (const auto& suffix : m_ignoreFilesSuffixes) {
if (fileInfo.fileName().endsWith(suffix)) {
return true;
}
}
if (m_ignoreFilePaths.covers(relPath(fileInfo.absoluteFilePath()))) {
return true;
}
return false;
}
bool FileIgnoreProxy::filterFile(const QFileInfo& file) const

View file

@ -66,6 +66,7 @@ class FileIgnoreProxy : public QSortFilterProxyModel {
// list of file names that need to be removed completely from model
inline QStringList& ignoreFilesWithName() { return m_ignoreFiles; }
inline QStringList& ignoreFilesWithSuffix() { return m_ignoreFilesSuffixes; }
// list of relative paths that need to be removed completely from model
inline SeparatorPrefixTree<'/'>& ignoreFilesWithPath() { return m_ignoreFilePaths; }
@ -85,5 +86,6 @@ class FileIgnoreProxy : public QSortFilterProxyModel {
const QString m_root;
SeparatorPrefixTree<'/'> m_blocked;
QStringList m_ignoreFiles;
QStringList m_ignoreFilesSuffixes;
SeparatorPrefixTree<'/'> m_ignoreFilePaths;
};

View file

@ -4,7 +4,6 @@
* Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net>
* Copyright (C) 2022 TheKodeToad <TheKodeToad@proton.me>
* Copyright (C) 2022 Rachel Powers <508861+Ryex@users.noreply.github.com>
* Copyright (C) 2025 Seth Flynn <getchoo@tuta.io>
*
* 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
@ -283,6 +282,9 @@ bool copyFileAttributes(QString src, QString dst)
if (attrs == INVALID_FILE_ATTRIBUTES)
return false;
return SetFileAttributesW(dst.toStdWString().c_str(), attrs);
#else
Q_UNUSED(src);
Q_UNUSED(dst);
#endif
return true;
}
@ -433,7 +435,7 @@ void create_link::make_link_list(const QString& offset)
link_file(src, "");
} else {
if (m_debug)
qDebug() << "linking recursively:" << src << "to" << dst << ", max_depth:" << m_max_depth;
qDebug().nospace() << "linking recursively: " << src << " to " << dst << ", max_depth: " << m_max_depth;
QDir src_dir(src);
QDirIterator source_it(src, QDir::Filter::Files | QDir::Filter::Hidden, QDirIterator::Subdirectories);
@ -593,7 +595,7 @@ void create_link::runPrivileged(const QString& offset)
}
ExternalLinkFileProcess* linkFileProcess = new ExternalLinkFileProcess(serverName, m_useHardLinks, this);
connect(linkFileProcess, &ExternalLinkFileProcess::processExited, this, [this, gotResults]() { emit finishedPrivileged(gotResults); });
connect(linkFileProcess, &ExternalLinkFileProcess::processExited, this, [this, &gotResults]() { emit finishedPrivileged(gotResults); });
connect(linkFileProcess, &ExternalLinkFileProcess::finished, linkFileProcess, &QObject::deleteLater);
linkFileProcess->start();
@ -773,34 +775,6 @@ QString ResolveExecutable(QString path)
return pathInfo.absoluteFilePath();
}
std::unique_ptr<QProcess> createProcess(const QString& program, const QStringList& arguments)
{
qDebug() << "Creating process for" << program;
auto proc = std::unique_ptr<QProcess>(new QProcess());
#if defined(Q_OS_LINUX)
if (DesktopServices::isSelfContained()) {
const auto linkerPath = QCoreApplication::applicationFilePath();
qDebug() << "Wrapping" << program << "with self-contained linker at" << linkerPath;
QStringList wrappedArguments;
wrappedArguments << "--inhibit-cache" << program;
wrappedArguments += arguments;
proc->setProgram(linkerPath);
proc->setArguments(wrappedArguments);
} else {
proc->setProgram(program);
proc->setArguments(arguments);
}
#else
proc->setProgram(program);
proc->setArguments(arguments);
#endif
return proc;
}
/**
* Normalize path
*
@ -979,7 +953,10 @@ QString createShortcut(QString destination, QString target, QStringList args, QS
qWarning() << "Couldn't create directories within application";
return QString();
}
info.open(QIODevice::WriteOnly | QIODevice::Text);
if (!info.open(QIODevice::WriteOnly | QIODevice::Text)) {
qWarning() << "Failed to open file" << info.fileName() << "for writing:" << info.errorString();
return QString();
}
QFile(icon).rename(resources.path() + "/Icon.icns");
@ -987,7 +964,10 @@ QString createShortcut(QString destination, QString target, QStringList args, QS
QString exec = binaryDir.path() + "/Run.command";
QFile f(exec);
f.open(QIODevice::WriteOnly | QIODevice::Text);
if (!f.open(QIODevice::WriteOnly | QIODevice::Text)) {
qWarning() << "Failed to open file" << f.fileName() << "for writing:" << f.errorString();
return QString();
}
QTextStream stream(&f);
auto argstring = quoteArgs(args, "\"", "\\\"");
@ -1030,7 +1010,7 @@ QString createShortcut(QString destination, QString target, QStringList args, QS
destination += ".desktop";
QFile f(destination);
if (!f.open(QIODevice::WriteOnly | QIODevice::Text)) {
qWarning() << "Failed to open file '" << f.fileName() << "' for writing!";
qWarning() << "Failed to open file" << f.fileName() << "for writing:" << f.errorString();
return QString();
}
QTextStream stream(&f);
@ -1129,17 +1109,17 @@ QString createShortcut(QString destination, QString target, QStringList args, QS
hres = ppf->Save(wsz, TRUE);
if (FAILED(hres)) {
qWarning() << "IPresistFile->Save() failed";
qWarning() << "hres = " << hres;
qWarning() << "hres =" << hres;
}
ppf->Release();
} else {
qWarning() << "Failed to query IPersistFile interface from IShellLink instance";
qWarning() << "hres = " << hres;
qWarning() << "hres =" << hres;
}
psl->Release();
} else {
qWarning() << "Failed to create IShellLink instance";
qWarning() << "hres = " << hres;
qWarning() << "hres =" << hres;
}
// go away COM, nobody likes you
@ -1428,14 +1408,14 @@ bool win_ioctl_clone(const std::wstring& src_path, const std::wstring& dst_path,
ULONG fs_flags;
if (!GetVolumeInformationByHandleW(hSourceFile, nullptr, 0, nullptr, nullptr, &fs_flags, nullptr, 0)) {
ec = std::error_code(GetLastError(), std::system_category());
qDebug() << "Failed to get Filesystem information for " << src_path.c_str();
qDebug() << "Failed to get Filesystem information for" << src_path.c_str();
CloseHandle(hSourceFile);
return false;
}
if (!(fs_flags & FILE_SUPPORTS_BLOCK_REFCOUNTING)) {
SetLastError(ERROR_NOT_CAPABLE);
ec = std::error_code(GetLastError(), std::system_category());
qWarning() << "Filesystem at " << src_path.c_str() << " does not support reflink";
qWarning() << "Filesystem at" << src_path.c_str() << "does not support reflink";
CloseHandle(hSourceFile);
return false;
}

View file

@ -4,7 +4,6 @@
* Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net>
* Copyright (C) 2022 TheKodeToad <TheKodeToad@proton.me>
* Copyright (C) 2022 Rachel Powers <508861+Ryex@users.noreply.github.com>
* Copyright (C) 2025 Seth Flynn <getchoo@tuta.io>
*
* 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
@ -43,13 +42,11 @@
#include <system_error>
#include <QCoreApplication>
#include <QDir>
#include <QFlags>
#include <QLocalServer>
#include <QObject>
#include <QPair>
#include <QProcess>
#include <QThread>
namespace FS {
@ -336,14 +333,6 @@ QString pathTruncate(const QString& path, int depth);
*/
QString ResolveExecutable(QString path);
/**
* Create a QProcess instance
*
* This wrapper is currently only required for wrapping binaries called in
* self-contained AppImages (like those created by `go-appimage`)
*/
std::unique_ptr<QProcess> createProcess(const QString& program, const QStringList& arguments);
/**
* Normalize path
*

View file

@ -172,7 +172,8 @@ int inf(QFile* source, std::function<bool(const QByteArray&)> handleBlock)
assert(ret != Z_STREAM_ERROR); /* state not clobbered */
switch (ret) {
case Z_NEED_DICT:
ret = Z_DATA_ERROR; /* and fall through */
ret = Z_DATA_ERROR;
[[fallthrough]];
case Z_DATA_ERROR:
case Z_MEM_ERROR:
(void)inflateEnd(&strm);
@ -215,4 +216,4 @@ QString GZip::readGzFileByBlocks(QFile* source, std::function<bool(const QByteAr
{
auto ret = inf(source, handleBlock);
return zerr(ret);
}
}

346
launcher/HardwareInfo.cpp Normal file
View file

@ -0,0 +1,346 @@
// SPDX-License-Identifier: GPL-3.0-only
/*
* Prism Launcher - Minecraft Launcher
* Copyright (C) 2026 Octol1ttle <l1ttleofficial@outlook.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include "HardwareInfo.h"
#include <QCoreApplication>
#include <QOffscreenSurface>
#include <QOpenGLFunctions>
#include <QProcessEnvironment>
#include "BuildConfig.h"
#ifndef Q_OS_MACOS
#include <QVulkanInstance>
#include <QVulkanWindow>
#endif
namespace {
bool vulkanInfo(QStringList& out)
{
if (!QProcessEnvironment::systemEnvironment()
.value(QStringLiteral("%1_DISABLE_GLVULKAN").arg(BuildConfig.LAUNCHER_ENVNAME))
.isEmpty()) {
return false;
}
#ifndef Q_OS_MACOS
QVulkanInstance inst;
if (!inst.create()) {
qWarning() << "Vulkan instance creation failed, VkResult:" << inst.errorCode();
out << "Couldn't get Vulkan device information";
return false;
}
QVulkanWindow window;
window.setVulkanInstance(&inst);
for (auto device : window.availablePhysicalDevices()) {
const auto supportedVulkanVersion = QVersionNumber(VK_API_VERSION_MAJOR(device.apiVersion), VK_API_VERSION_MINOR(device.apiVersion),
VK_API_VERSION_PATCH(device.apiVersion));
out << QString("Found Vulkan device: %1 (API version %2)").arg(device.deviceName).arg(supportedVulkanVersion.toString());
}
#endif
return true;
}
bool openGlInfo(QStringList& out)
{
if (!QProcessEnvironment::systemEnvironment()
.value(QStringLiteral("%1_DISABLE_GLVULKAN").arg(BuildConfig.LAUNCHER_ENVNAME))
.isEmpty()) {
return false;
}
QOpenGLContext ctx;
if (!ctx.create()) {
qWarning() << "OpenGL context creation failed";
out << "Couldn't get OpenGL device information";
return false;
}
QOffscreenSurface surface;
surface.create();
ctx.makeCurrent(&surface);
auto* f = ctx.functions();
f->initializeOpenGLFunctions();
auto toQString = [](const GLubyte* str) { return QString(reinterpret_cast<const char*>(str)); };
out << "OpenGL driver vendor: " + toQString(f->glGetString(GL_VENDOR));
out << "OpenGL renderer: " + toQString(f->glGetString(GL_RENDERER));
out << "OpenGL driver version: " + toQString(f->glGetString(GL_VERSION));
return true;
}
} // namespace
#ifndef Q_OS_LINUX
QStringList HardwareInfo::gpuInfo()
{
QStringList info;
vulkanInfo(info);
openGlInfo(info);
return info;
}
#endif
#ifdef Q_OS_WINDOWS
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <QSettings>
#include "windows.h"
QString HardwareInfo::cpuInfo()
{
const QSettings registry(R"(HKEY_LOCAL_MACHINE\HARDWARE\DESCRIPTION\System\CentralProcessor\0)", QSettings::NativeFormat);
return registry.value("ProcessorNameString").toString();
}
uint64_t HardwareInfo::totalRamMiB()
{
MEMORYSTATUSEX status;
status.dwLength = sizeof status;
if (GlobalMemoryStatusEx(&status) == TRUE) {
// transforming bytes -> mib
return status.ullTotalPhys / 1024 / 1024;
}
qWarning() << "Could not get total RAM: GlobalMemoryStatusEx";
return 0;
}
uint64_t HardwareInfo::availableRamMiB()
{
MEMORYSTATUSEX status;
status.dwLength = sizeof status;
if (GlobalMemoryStatusEx(&status) == TRUE) {
// transforming bytes -> mib
return status.ullAvailPhys / 1024 / 1024;
}
qWarning() << "Could not get available RAM: GlobalMemoryStatusEx";
return 0;
}
#elif defined(Q_OS_MACOS)
#include "sys/sysctl.h"
QString HardwareInfo::cpuInfo()
{
std::array<char, 512> buffer;
size_t bufferSize = buffer.size();
if (sysctlbyname("machdep.cpu.brand_string", &buffer, &bufferSize, nullptr, 0) == 0) {
return QString(buffer.data());
}
qWarning() << "Could not get CPU model: sysctlbyname";
return "";
}
uint64_t HardwareInfo::totalRamMiB()
{
uint64_t memsize;
size_t memsizeSize = sizeof memsize;
if (sysctlbyname("hw.memsize", &memsize, &memsizeSize, nullptr, 0) == 0) {
// transforming bytes -> mib
return memsize / 1024 / 1024;
}
qWarning() << "Could not get total RAM: sysctlbyname";
return 0;
}
uint64_t HardwareInfo::availableRamMiB()
{
return 0;
}
MacOSHardwareInfo::MemoryPressureLevel MacOSHardwareInfo::memoryPressureLevel()
{
uint32_t level;
size_t levelSize = sizeof level;
if (sysctlbyname("kern.memorystatus_vm_pressure_level", &level, &levelSize, nullptr, 0) == 0) {
return static_cast<MemoryPressureLevel>(level);
}
qWarning() << "Could not get memory pressure level: sysctlbyname";
return MemoryPressureLevel::Normal;
}
QString MacOSHardwareInfo::memoryPressureLevelName()
{
// The names are internal, users refer to levels by their graph colors in Activity Monitor
switch (memoryPressureLevel()) {
case MemoryPressureLevel::Normal:
return "Green";
case MemoryPressureLevel::Warning:
return "Yellow";
case MemoryPressureLevel::Critical:
return "Red";
}
}
#elif defined(Q_OS_LINUX)
#include <fstream>
namespace {
QString afterColon(QString& str)
{
return str.remove(0, str.indexOf(':') + 2).trimmed();
}
} // namespace
QString HardwareInfo::cpuInfo()
{
std::ifstream cpuin("/proc/cpuinfo");
for (std::string line; std::getline(cpuin, line);) {
// model name : AMD Ryzen 7 5800X 8-Core Processor
if (QString str = QString::fromStdString(line); str.startsWith("model name")) {
return afterColon(str);
}
}
qWarning() << "Could not get CPU model: /proc/cpuinfo";
return "unknown";
}
uint64_t readMemInfo(QString searchTarget)
{
std::ifstream memin("/proc/meminfo");
for (std::string line; std::getline(memin, line);) {
// MemTotal: 16287480 kB
if (QString str = QString::fromStdString(line); str.startsWith(searchTarget)) {
bool ok = false;
const uint total = str.simplified().section(' ', 1, 1).toUInt(&ok);
if (!ok) {
qWarning() << "Could not read /proc/meminfo: failed to parse string:" << str;
return 0;
}
// transforming kib -> mib
return total / 1024;
}
}
qWarning() << "Could not read /proc/meminfo: search target not found:" << searchTarget;
return 0;
}
uint64_t HardwareInfo::totalRamMiB()
{
return readMemInfo("MemTotal");
}
uint64_t HardwareInfo::availableRamMiB()
{
return readMemInfo("MemAvailable");
}
QStringList HardwareInfo::gpuInfo()
{
QStringList list;
const bool vulkanSuccess = vulkanInfo(list);
const bool openGlSuccess = openGlInfo(list);
if (vulkanSuccess || openGlSuccess) {
return list;
}
std::array<char, 512> buffer;
FILE* lspci = popen("lspci -k", "r");
if (!lspci) {
return { "Could not detect GPUs: lspci is not present" };
}
bool readingGpuInfo = false;
QString currentModel = "";
while (fgets(buffer.data(), 512, lspci) != nullptr) {
QString str(buffer.data());
// clang-format off
// 04:00.0 VGA compatible controller: Advanced Micro Devices, Inc. [AMD/ATI] Ellesmere [Radeon RX 470/480/570/570X/580/580X/590] (rev e7)
// Subsystem: Sapphire Technology Limited Radeon RX 580 Pulse 4GB
// Kernel driver in use: amdgpu
// Kernel modules: amdgpu
// clang-format on
if (str.contains("VGA compatible controller")) {
readingGpuInfo = true;
} else if (!str.startsWith('\t')) {
readingGpuInfo = false;
}
if (!readingGpuInfo) {
continue;
}
if (str.contains("Subsystem")) {
currentModel = "Found GPU: " + afterColon(str);
}
if (str.contains("Kernel driver in use")) {
currentModel += " (using driver " + afterColon(str);
}
if (str.contains("Kernel modules")) {
currentModel += ", available drivers: " + afterColon(str) + ")";
list.append(currentModel);
}
}
pclose(lspci);
return list;
}
#else
QString HardwareInfo::cpuInfo()
{
return "unknown";
}
#if defined(Q_OS_FREEBSD) || defined(Q_OS_OPENBSD)
#include <cstdio>
uint64_t HardwareInfo::totalRamMiB()
{
char buff[512];
FILE* fp = popen("sysctl hw.physmem", "r");
if (fp != nullptr) {
if (fgets(buff, 512, fp) != nullptr) {
std::string str(buff);
uint64_t mem = std::stoull(str.substr(12, std::string::npos));
// transforming kib -> mib
return mem / 1024;
}
}
return 0;
}
#else
uint64_t HardwareInfo::totalRamMiB()
{
return 0;
}
#endif
uint64_t HardwareInfo::availableRamMiB()
{
return 0;
}
#endif

42
launcher/HardwareInfo.h Normal file
View file

@ -0,0 +1,42 @@
// SPDX-License-Identifier: GPL-3.0-only
/*
* Prism Launcher - Minecraft Launcher
* Copyright (C) 2026 Octol1ttle <l1ttleofficial@outlook.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#pragma once
#include <QString>
#include <cstdint>
namespace HardwareInfo {
QString cpuInfo();
uint64_t totalRamMiB();
uint64_t availableRamMiB();
QStringList gpuInfo();
} // namespace HardwareInfo
#ifdef Q_OS_MACOS
namespace MacOSHardwareInfo {
enum class MemoryPressureLevel : uint8_t {
Normal = 1,
Warning = 2,
Critical = 4,
};
MemoryPressureLevel memoryPressureLevel();
QString memoryPressureLevelName();
} // namespace MacOSHardwareInfo
#endif

View file

@ -189,4 +189,4 @@ void InstanceCopyPrefs::enableDontLinkSaves(bool b)
void InstanceCopyPrefs::enableUseClone(bool b)
{
useClone = b;
}
}

View file

@ -8,7 +8,7 @@
#include "settings/INISettingsObject.h"
#include "tasks/Task.h"
InstanceCopyTask::InstanceCopyTask(InstancePtr origInstance, const InstanceCopyPrefs& prefs)
InstanceCopyTask::InstanceCopyTask(BaseInstance* origInstance, const InstanceCopyPrefs& prefs)
{
m_origInstance = origInstance;
m_keepPlaytime = prefs.isKeepPlaytimeEnabled();
@ -64,7 +64,6 @@ void InstanceCopyTask::executeTask()
savesCopy = std::make_unique<FS::copy>(FS::PathCombine(m_origInstance->gameRoot(), "saves"),
FS::PathCombine(staging_mc_dir, "saves"));
savesCopy->followSymlinks(true);
(*savesCopy)(true);
setProgress(0, savesCopy->totalCopied());
connect(savesCopy.get(), &FS::copy::fileCopied, [this](QString src) { setProgress(m_progress + 1, m_progressTotal); });
@ -126,11 +125,11 @@ void InstanceCopyTask::executeTask()
return !there_were_errors;
}
FS::copy folderCopy(m_origInstance->instanceRoot(), m_stagingPath);
folderCopy.followSymlinks(false).matcher(m_matcher);
folderCopy.matcher(m_matcher);
folderCopy(true);
setProgress(0, folderCopy.totalCopied());
connect(&folderCopy, &FS::copy::fileCopied, [this](QString src) { setProgress(m_progress + 1, m_progressTotal); });
connect(&folderCopy, &FS::copy::fileCopied, [this]() { setProgress(m_progress + 1, m_progressTotal); });
return folderCopy();
});
connect(&m_copyFutureWatcher, &QFutureWatcher<bool>::finished, this, &InstanceCopyTask::copyFinished);
@ -147,9 +146,9 @@ void InstanceCopyTask::copyFinished()
}
// FIXME: shouldn't this be able to report errors?
auto instanceSettings = std::make_shared<INISettingsObject>(FS::PathCombine(m_stagingPath, "instance.cfg"));
auto instanceSettings = std::make_unique<INISettingsObject>(FS::PathCombine(m_stagingPath, "instance.cfg"));
InstancePtr inst(new NullInstance(m_globalSettings, instanceSettings, m_stagingPath));
BaseInstance* inst(new NullInstance(m_globalSettings, std::move(instanceSettings), m_stagingPath));
inst->setName(name());
inst->setIconKey(m_instIcon);
if (!m_keepPlaytime) {
@ -197,4 +196,4 @@ bool InstanceCopyTask::abort()
return true;
}
return false;
}
}

View file

@ -15,7 +15,7 @@
class InstanceCopyTask : public InstanceTask {
Q_OBJECT
public:
explicit InstanceCopyTask(InstancePtr origInstance, const InstanceCopyPrefs& prefs);
explicit InstanceCopyTask(BaseInstance* origInstance, const InstanceCopyPrefs& prefs);
protected:
//! Entry point for tasks.
@ -26,7 +26,7 @@ class InstanceCopyTask : public InstanceTask {
private:
/* data */
InstancePtr m_origInstance;
BaseInstance* m_origInstance;
QFuture<bool> m_copyFuture;
QFutureWatcher<bool> m_copyFutureWatcher;
Filter m_matcher;

View file

@ -2,7 +2,24 @@
#include <QDebug>
#include <QFile>
#include "FileSystem.h"
#include "InstanceTask.h"
#include "minecraft/MinecraftLoadAndCheck.h"
#include "tasks/SequentialTask.h"
bool InstanceCreationTask::abort()
{
if (!canAbort()) {
return false;
}
m_abort = true;
if (m_gameFilesTask) {
return m_gameFilesTask->abort();
}
return InstanceTask::abort();
}
void InstanceCreationTask::executeTask()
{
@ -19,13 +36,14 @@ void InstanceCreationTask::executeTask()
return;
}
if (!createInstance()) {
m_instance = createInstance();
if (!m_instance) {
if (m_abort)
return;
qWarning() << "Instance creation failed!";
if (!m_error_message.isEmpty()) {
qWarning() << "Reason: " << m_error_message;
qWarning() << "Reason:" << m_error_message;
emitFailed(tr("Error while creating new instance:\n%1").arg(m_error_message));
} else {
emitFailed(tr("Error while creating new instance."));
@ -44,7 +62,7 @@ void InstanceCreationTask::executeTask()
setStatus(tr("Removing old conflicting files..."));
qDebug() << "Removing old files";
for (const QString& path : m_files_to_remove) {
for (const QString& path : m_filesToRemove) {
if (!QFile::exists(path))
continue;
@ -61,6 +79,57 @@ void InstanceCreationTask::executeTask()
return;
}
}
if (!m_abort)
emitSucceeded();
if (!m_abort) {
setAbortable(true);
setAbortButtonText(tr("Skip"));
qDebug() << "Downloading game files";
auto updateTasks = m_instance->createUpdateTask();
if (updateTasks.isEmpty()) {
emitSucceeded();
return;
}
auto task = makeShared<SequentialTask>();
task->addTask(makeShared<MinecraftLoadAndCheck>(m_instance.get(), Net::Mode::Online));
for (const auto& t : updateTasks) {
task->addTask(t);
}
connect(task.get(), &Task::finished, this, [this, task] {
if (task->wasSuccessful() || m_abort) {
emitSucceeded();
} else {
emitFailed(tr("Could not download game files: %1").arg(task->failReason()));
}
});
propagateFromOther(task.get());
setDetails(tr("Downloading game files"));
m_gameFilesTask = task;
m_gameFilesTask->start();
}
}
void InstanceCreationTask::scheduleToDelete(QWidget* parent, QDir dir, QString path, bool checkDisabled)
{
if (path.isEmpty()) {
return;
}
if (path.startsWith("saves/")) {
if (m_shouldDeleteSaves == ShouldDeleteSaves::NotAsked) {
m_shouldDeleteSaves = askIfShouldDeleteSaves(parent);
}
if (m_shouldDeleteSaves == ShouldDeleteSaves::No) {
return;
}
}
qDebug() << "Scheduling" << path << "for removal";
m_filesToRemove.append(dir.absoluteFilePath(path));
if (checkDisabled) {
if (path.endsWith(".disabled")) { // remove it if it was enabled/disabled by user
m_filesToRemove.append(dir.absoluteFilePath(path.chopped(9)));
} else {
m_filesToRemove.append(dir.absoluteFilePath(path + ".disabled"));
}
}
}

View file

@ -2,6 +2,7 @@
#include "BaseVersion.h"
#include "InstanceTask.h"
#include "minecraft/MinecraftInstance.h"
class InstanceCreationTask : public InstanceTask {
Q_OBJECT
@ -9,6 +10,8 @@ class InstanceCreationTask : public InstanceTask {
InstanceCreationTask() = default;
virtual ~InstanceCreationTask() = default;
bool abort() override;
protected:
void executeTask() final override;
@ -27,20 +30,24 @@ class InstanceCreationTask : public InstanceTask {
/**
* Creates a new instance.
*
* Returns whether the instance creation was successful (true) or not (false).
* Returns the instance if it was created or nullptr otherwise.
*/
virtual bool createInstance() { return false; };
virtual std::unique_ptr<MinecraftInstance> createInstance() { return nullptr; }
QString getError() const { return m_error_message; }
protected:
void setError(const QString& message) { m_error_message = message; };
void scheduleToDelete(QWidget* parent, QDir dir, QString path, bool checkDisabled = false);
protected:
bool m_abort = false;
QStringList m_files_to_remove;
QStringList m_filesToRemove;
ShouldDeleteSaves m_shouldDeleteSaves;
private:
QString m_error_message;
std::unique_ptr<MinecraftInstance> m_instance;
Task::Ptr m_gameFilesTask;
};

View file

@ -42,7 +42,7 @@
#include "InstanceList.h"
#include "ui/dialogs/CustomMessageBox.h"
QString askToUpdateInstanceDirName(InstancePtr instance, const QString& oldName, const QString& newName, QWidget* parent)
QString askToUpdateInstanceDirName(BaseInstance* instance, const QString& oldName, const QString& newName, QWidget* parent)
{
if (oldName == newName)
return QString();

View file

@ -37,7 +37,7 @@
#include "BaseInstance.h"
/// Update instanceRoot to make it sync with name/id; return newRoot if a directory rename happened
QString askToUpdateInstanceDirName(InstancePtr instance, const QString& oldName, const QString& newName, QWidget* parent);
QString askToUpdateInstanceDirName(BaseInstance* instance, const QString& oldName, const QString& newName, QWidget* parent);
/// Check if there are linked instances, and display a warning; return true if the operation should proceed
bool checkLinkedInstances(const QString& id, QWidget* parent, const QString& verb);

View file

@ -150,22 +150,15 @@ void InstanceImportTask::processZipPack()
extractDir.cd("minecraft");
m_modpackType = ModpackType::Technic;
stop = true;
} else {
QFileInfo fileInfo(fileName);
if (fileInfo.fileName() == "instance.cfg") {
qDebug() << "MultiMC:" << true;
m_modpackType = ModpackType::MultiMC;
root = cleanPath(fileInfo.path());
stop = true;
return true;
}
if (fileInfo.fileName() == "manifest.json") {
qDebug() << "Flame:" << true;
m_modpackType = ModpackType::Flame;
root = cleanPath(fileInfo.path());
stop = true;
return true;
}
} else if (fileName == "manifest.json") {
qDebug() << "Flame:" << true;
m_modpackType = ModpackType::Flame;
stop = true;
} else if (QFileInfo fileInfo(fileName); fileInfo.fileName() == "instance.cfg") {
qDebug() << "MultiMC:" << true;
m_modpackType = ModpackType::MultiMC;
root = cleanPath(fileInfo.path());
stop = true;
}
QCoreApplication::processEvents();
return true;
@ -271,7 +264,7 @@ bool installIcon(QString root, QString instIconKey)
if (iconList->iconFileExists(instIconKey)) {
iconList->deleteIcon(instIconKey);
}
iconList->installIcon(importIconPath, instIconKey + ".png");
iconList->installIcon(importIconPath, instIconKey + "." + QFileInfo(importIconPath).suffix());
return true;
}
return false;
@ -329,6 +322,7 @@ void InstanceImportTask::processFlame()
connect(inst_creation_task.get(), &Task::aborted, this, &InstanceImportTask::emitAborted);
connect(inst_creation_task.get(), &Task::abortStatusChanged, this, &Task::setAbortable);
connect(inst_creation_task.get(), &Task::abortButtonTextChanged, this, &Task::setAbortButtonText);
connect(inst_creation_task.get(), &Task::warningLogged, this, [this](const QString& line) { m_Warnings.append(line); });
@ -348,9 +342,9 @@ void InstanceImportTask::processTechnic()
void InstanceImportTask::processMultiMC()
{
QString configPath = FS::PathCombine(m_stagingPath, "instance.cfg");
auto instanceSettings = std::make_shared<INISettingsObject>(configPath);
auto instanceSettings = std::make_unique<INISettingsObject>(configPath);
NullInstance instance(m_globalSettings, instanceSettings, m_stagingPath);
NullInstance instance(m_globalSettings, std::move(instanceSettings), m_stagingPath);
// reset time played on import... because packs.
instance.resetTimePlayed();
@ -428,6 +422,7 @@ void InstanceImportTask::processModrinth()
connect(inst_creation_task.get(), &Task::aborted, this, &InstanceImportTask::emitAborted);
connect(inst_creation_task.get(), &Task::abortStatusChanged, this, &Task::setAbortable);
connect(inst_creation_task.get(), &Task::abortButtonTextChanged, this, &Task::setAbortButtonText);
connect(inst_creation_task.get(), &Task::warningLogged, this, [this](const QString& line) { m_Warnings.append(line); });

View file

@ -34,42 +34,37 @@
* limitations under the License.
*/
#include "InstanceList.h"
#include <QDebug>
#include <QDir>
#include <QDirIterator>
#include <QFile>
#include <QFileInfo>
#include <QFileSystemWatcher>
#include <QJsonArray>
#include <QJsonDocument>
#include <QMimeData>
#include <QPair>
#include <QSet>
#include <QStack>
#include <QTextStream>
#include <QThread>
#include <QTimer>
#include <QUuid>
#include <QXmlStreamReader>
#include "BaseInstance.h"
#include "ExponentialSeries.h"
#include "FileSystem.h"
#include "InstanceList.h"
#include "InstanceTask.h"
#include "NullInstance.h"
#include "WatchLock.h"
#include "minecraft/MinecraftInstance.h"
#include "minecraft/ShortcutUtils.h"
#include "settings/INISettingsObject.h"
#ifdef Q_OS_WIN32
#include <Windows.h>
#include <windows.h>
#endif
const static int GROUP_FILE_FORMAT_VERSION = 1;
InstanceList::InstanceList(SettingsObjectPtr settings, const QString& instDir, QObject* parent)
InstanceList::InstanceList(SettingsObject* settings, const QString& instDir, QObject* parent)
: QAbstractListModel(parent), m_globalSettings(settings)
{
resumeWatch();
@ -143,7 +138,7 @@ QMimeData* InstanceList::mimeData(const QModelIndexList& indexes) const
QStringList InstanceList::getLinkedInstancesById(const QString& id) const
{
QStringList linkedInstances;
for (auto inst : m_instances) {
for (auto& inst : m_instances) {
if (inst->isLinkedToInstanceId(id))
linkedInstances.append(inst->id());
}
@ -153,15 +148,15 @@ QStringList InstanceList::getLinkedInstancesById(const QString& id) const
int InstanceList::rowCount(const QModelIndex& parent) const
{
Q_UNUSED(parent);
return m_instances.count();
return count();
}
QModelIndex InstanceList::index(int row, int column, const QModelIndex& parent) const
{
Q_UNUSED(parent);
if (row < 0 || row >= m_instances.size())
if (row < 0 || row >= count())
return QModelIndex();
return createIndex(row, column, (void*)m_instances.at(row).get());
return createIndex(row, column, m_instances.at(row).get());
}
QVariant InstanceList::data(const QModelIndex& index, int role) const
@ -266,7 +261,7 @@ void InstanceList::setInstanceGroup(const InstanceId& id, GroupId name)
if (changed) {
increaseGroupCount(name);
auto idx = getInstIndex(inst.get());
auto idx = getInstIndex(inst);
emit dataChanged(index(idx), index(idx), { GroupRole });
saveGroupList();
}
@ -457,7 +452,7 @@ void InstanceList::deleteInstance(const InstanceId& id)
}
}
static QMap<InstanceId, InstanceLocator> getIdMapping(const QList<InstancePtr>& list)
static QMap<InstanceId, InstanceLocator> getIdMapping(const std::vector<std::unique_ptr<BaseInstance>>& list)
{
QMap<InstanceId, InstanceLocator> out;
int i = 0;
@ -466,7 +461,7 @@ static QMap<InstanceId, InstanceLocator> getIdMapping(const QList<InstancePtr>&
if (out.contains(id)) {
qWarning() << "Duplicate ID" << id << "in instance list";
}
out[id] = std::make_pair(item, i);
out[id] = std::make_pair(item.get(), i);
i++;
}
return out;
@ -504,17 +499,16 @@ InstanceList::InstListError InstanceList::loadList()
{
auto existingIds = getIdMapping(m_instances);
QList<InstancePtr> newList;
std::vector<std::unique_ptr<BaseInstance>> newList;
for (auto& id : discoverInstances()) {
if (existingIds.contains(id)) {
auto instPair = existingIds[id];
existingIds.remove(id);
qInfo() << "Should keep and soft-reload" << id;
} else {
InstancePtr instPtr = loadInstance(id);
std::unique_ptr<BaseInstance> instPtr = loadInstance(id);
if (instPtr) {
newList.append(instPtr);
newList.push_back(std::move(instPtr));
}
}
}
@ -566,8 +560,8 @@ InstanceList::InstListError InstanceList::loadList()
void InstanceList::updateTotalPlayTime()
{
totalPlayTime = 0;
for (auto const& itr : m_instances) {
totalPlayTime += itr.get()->totalTimePlayed();
for (const auto& itr : m_instances) {
totalPlayTime += itr->totalTimePlayed();
}
}
@ -578,12 +572,12 @@ void InstanceList::saveNow()
}
}
void InstanceList::add(const QList<InstancePtr>& t)
void InstanceList::add(std::vector<std::unique_ptr<BaseInstance>>& t)
{
beginInsertRows(QModelIndex(), m_instances.count(), m_instances.count() + t.size() - 1);
m_instances.append(t);
beginInsertRows(QModelIndex(), count(), static_cast<int>(count() + t.size() - 1));
for (auto& ptr : t) {
connect(ptr.get(), &BaseInstance::propertiesChanged, this, &InstanceList::propertiesChanged);
m_instances.push_back(std::move(ptr));
connect(m_instances.back().get(), &BaseInstance::propertiesChanged, this, &InstanceList::propertiesChanged);
}
endInsertRows();
}
@ -613,26 +607,26 @@ void InstanceList::providerUpdated()
}
}
InstancePtr InstanceList::getInstanceById(QString instId) const
BaseInstance* InstanceList::getInstanceById(QString instId) const
{
if (instId.isEmpty())
return InstancePtr();
return nullptr;
for (auto& inst : m_instances) {
if (inst->id() == instId) {
return inst;
return inst.get();
}
}
return InstancePtr();
return nullptr;
}
InstancePtr InstanceList::getInstanceByManagedName(const QString& managed_name) const
BaseInstance* InstanceList::getInstanceByManagedName(const QString& managed_name) const
{
if (managed_name.isEmpty())
return {};
for (auto instance : m_instances) {
for (auto& instance : m_instances) {
if (instance->getManagedPackName() == managed_name)
return instance;
return instance.get();
}
return {};
@ -640,14 +634,14 @@ InstancePtr InstanceList::getInstanceByManagedName(const QString& managed_name)
QModelIndex InstanceList::getInstanceIndexById(const QString& id) const
{
return index(getInstIndex(getInstanceById(id).get()));
return index(getInstIndex(getInstanceById(id)));
}
int InstanceList::getInstIndex(BaseInstance* inst) const
{
int count = m_instances.count();
int count = this->count();
for (int i = 0; i < count; i++) {
if (inst == m_instances[i].get()) {
if (inst == m_instances.at(i).get()) {
return i;
}
}
@ -663,15 +657,15 @@ void InstanceList::propertiesChanged(BaseInstance* inst)
}
}
InstancePtr InstanceList::loadInstance(const InstanceId& id)
std::unique_ptr<BaseInstance> InstanceList::loadInstance(const InstanceId& id)
{
if (!m_groupsLoaded) {
loadGroupList();
}
auto instanceRoot = FS::PathCombine(m_instDir, id);
auto instanceSettings = std::make_shared<INISettingsObject>(FS::PathCombine(instanceRoot, "instance.cfg"));
InstancePtr inst;
auto instanceSettings = std::make_unique<INISettingsObject>(FS::PathCombine(instanceRoot, "instance.cfg"));
std::unique_ptr<BaseInstance> inst;
instanceSettings->registerSetting("InstanceType", "");
@ -680,9 +674,9 @@ InstancePtr InstanceList::loadInstance(const InstanceId& id)
// NOTE: Some launcher versions didn't save the InstanceType properly. We will just bank on the probability that this is probably a
// OneSix instance
if (inst_type == "OneSix" || inst_type.isEmpty()) {
inst.reset(new MinecraftInstance(m_globalSettings, instanceSettings, instanceRoot));
inst.reset(new MinecraftInstance(m_globalSettings, std::move(instanceSettings), instanceRoot));
} else {
inst.reset(new NullInstance(m_globalSettings, instanceSettings, instanceRoot));
inst.reset(new NullInstance(m_globalSettings, std::move(instanceSettings), instanceRoot));
}
qDebug() << "Loaded instance" << inst->name() << "from" << inst->instanceRoot();
@ -911,20 +905,20 @@ class InstanceStaging : public Task {
const unsigned maxBackoff = 16;
public:
InstanceStaging(InstanceList* parent, InstanceTask* child, SettingsObjectPtr settings)
: m_parent(parent), backoff(minBackoff, maxBackoff)
InstanceStaging(InstanceList* parent, InstanceTask* child, SettingsObject* settings) : m_parent(parent), backoff(minBackoff, maxBackoff)
{
m_stagingPath = parent->getStagedInstancePath();
m_child.reset(child);
m_child->setStagingPath(m_stagingPath);
m_child->setParentSettings(std::move(settings));
m_child->setParentSettings(settings);
connect(child, &Task::succeeded, this, &InstanceStaging::childSucceeded);
connect(child, &Task::failed, this, &InstanceStaging::childFailed);
connect(child, &Task::aborted, this, &InstanceStaging::childAborted);
connect(child, &Task::abortStatusChanged, this, &InstanceStaging::setAbortable);
connect(child, &Task::abortButtonTextChanged, this, &InstanceStaging::setAbortButtonText);
connect(child, &Task::status, this, &InstanceStaging::setStatus);
connect(child, &Task::details, this, &InstanceStaging::setDetails);
connect(child, &Task::progress, this, &InstanceStaging::setProgress);
@ -932,22 +926,21 @@ class InstanceStaging : public Task {
connect(&m_backoffTimer, &QTimer::timeout, this, &InstanceStaging::childSucceeded);
}
virtual ~InstanceStaging() {}
~InstanceStaging() override = default;
// FIXME/TODO: add ability to abort during instance commit retries
bool abort() override
{
if (!canAbort())
if (!canAbort()) {
return false;
}
m_child->abort();
return Task::abort();
return m_child->abort();
}
bool canAbort() const override { return (m_child && m_child->canAbort()); }
protected:
virtual void executeTask() override
void executeTask() override
{
if (m_stagingPath.isNull()) {
emitFailed(tr("Could not create staging folder"));
@ -962,12 +955,14 @@ class InstanceStaging : public Task {
void childSucceeded()
{
unsigned sleepTime = backoff();
if (m_parent->commitStagedInstance(m_stagingPath, *m_child.get(), m_child->group(), *m_child.get())) {
if (m_parent->commitStagedInstance(m_stagingPath, *m_child, m_child->group(), *m_child)) {
m_backoffTimer.stop();
emitSucceeded();
return;
}
// we actually failed, retry?
if (sleepTime == maxBackoff) {
m_backoffTimer.stop();
emitFailed(tr("Failed to commit instance, even after multiple retries. It is being blocked by something."));
return;
}
@ -976,12 +971,14 @@ class InstanceStaging : public Task {
}
void childFailed(const QString& reason)
{
m_backoffTimer.stop();
m_parent->destroyStagingPath(m_stagingPath);
emitFailed(reason);
}
void childAborted()
{
m_backoffTimer.stop();
m_parent->destroyStagingPath(m_stagingPath);
emitAborted();
}
@ -995,7 +992,7 @@ class InstanceStaging : public Task {
*/
ExponentialSeries backoff;
QString m_stagingPath;
unique_qobject_ptr<InstanceTask> m_child;
std::unique_ptr<InstanceTask> m_child;
QTimer m_backoffTimer;
};
@ -1028,15 +1025,14 @@ QString InstanceList::getStagedInstancePath()
}
bool InstanceList::commitStagedInstance(const QString& path,
InstanceName const& instanceName,
const InstanceName& instanceName,
QString groupName,
InstanceTask const& commiting)
const InstanceTask& commiting)
{
if (groupName.isEmpty() && !groupName.isNull())
groupName = QString();
QString instID;
InstancePtr inst;
auto should_override = commiting.shouldOverride();

View file

@ -50,7 +50,7 @@ struct InstanceName;
using InstanceId = QString;
using GroupId = QString;
using InstanceLocator = std::pair<InstancePtr, int>;
using InstanceLocator = std::pair<BaseInstance*, int>;
enum class InstCreateError { NoCreateError = 0, NoSuchVersion, UnknownCreateError, InstExists, CantCreateDir };
@ -73,7 +73,7 @@ class InstanceList : public QAbstractListModel {
Q_OBJECT
public:
explicit InstanceList(SettingsObjectPtr settings, const QString& instDir, QObject* parent = 0);
explicit InstanceList(SettingsObject* settings, const QString& instDir, QObject* parent = 0);
virtual ~InstanceList();
public:
@ -96,17 +96,17 @@ class InstanceList : public QAbstractListModel {
*/
enum InstListError { NoError = 0, UnknownError };
InstancePtr at(int i) const { return m_instances.at(i); }
BaseInstance* at(int i) const { return m_instances.at(i).get(); }
int count() const { return m_instances.count(); }
int count() const { return static_cast<int>(m_instances.size()); }
InstListError loadList();
void saveNow();
/* O(n) */
InstancePtr getInstanceById(QString id) const;
BaseInstance* getInstanceById(QString id) const;
/* O(n) */
InstancePtr getInstanceByManagedName(const QString& managed_name) const;
BaseInstance* getInstanceByManagedName(const QString& managed_name) const;
QModelIndex getInstanceIndexById(const QString& id) const;
QStringList getGroups();
bool isGroupCollapsed(const QString& groupName);
@ -179,11 +179,11 @@ class InstanceList : public QAbstractListModel {
void updateTotalPlayTime();
void suspendWatch();
void resumeWatch();
void add(const QList<InstancePtr>& list);
void add(std::vector<std::unique_ptr<BaseInstance>>& list);
void loadGroupList();
void saveGroupList();
QList<InstanceId> discoverInstances();
InstancePtr loadInstance(const InstanceId& id);
std::unique_ptr<BaseInstance> loadInstance(const InstanceId& id);
void increaseGroupCount(const QString& group);
void decreaseGroupCount(const QString& group);
@ -192,11 +192,11 @@ class InstanceList : public QAbstractListModel {
int m_watchLevel = 0;
int totalPlayTime = 0;
bool m_dirty = false;
QList<InstancePtr> m_instances;
std::vector<std::unique_ptr<BaseInstance>> m_instances;
// id -> refs
QMap<QString, int> m_groupNameCache;
SettingsObjectPtr m_globalSettings;
SettingsObject* m_globalSettings;
QString m_instDir;
QFileSystemWatcher* m_watcher;
// FIXME: this is so inefficient that looking at it is almost painful.

View file

@ -21,26 +21,26 @@
class InstancePageProvider : protected QObject, public BasePageProvider {
Q_OBJECT
public:
explicit InstancePageProvider(InstancePtr parent) { inst = parent; }
explicit InstancePageProvider(BaseInstance* parent) { inst = parent; }
virtual ~InstancePageProvider() = default;
virtual QList<BasePage*> getPages() override
{
QList<BasePage*> values;
values.append(new LogPage(inst));
std::shared_ptr<MinecraftInstance> onesix = std::dynamic_pointer_cast<MinecraftInstance>(inst);
values.append(new VersionPage(onesix.get()));
values.append(ManagedPackPage::createPage(onesix.get()));
auto modsPage = new ModFolderPage(onesix.get(), onesix->loaderModList());
MinecraftInstance* onesix = dynamic_cast<MinecraftInstance*>(inst);
values.append(new VersionPage(onesix));
values.append(ManagedPackPage::createPage(onesix));
auto modsPage = new ModFolderPage(onesix, onesix->loaderModList());
modsPage->setFilter("%1 (*.zip *.jar *.litemod *.nilmod)");
values.append(modsPage);
values.append(new CoreModFolderPage(onesix.get(), onesix->coreModList()));
values.append(new NilModFolderPage(onesix.get(), onesix->nilModList()));
values.append(new ResourcePackPage(onesix.get(), onesix->resourcePackList()));
values.append(new GlobalDataPackPage(onesix.get()));
values.append(new TexturePackPage(onesix.get(), onesix->texturePackList()));
values.append(new ShaderPackPage(onesix.get(), onesix->shaderPackList()));
values.append(new NotesPage(onesix.get()));
values.append(new CoreModFolderPage(onesix, onesix->coreModList()));
values.append(new NilModFolderPage(onesix, onesix->nilModList()));
values.append(new ResourcePackPage(onesix, onesix->resourcePackList()));
values.append(new GlobalDataPackPage(onesix));
values.append(new TexturePackPage(onesix, onesix->texturePackList()));
values.append(new ShaderPackPage(onesix, onesix->shaderPackList()));
values.append(new NotesPage(onesix));
values.append(new WorldListPage(onesix, onesix->worldList()));
values.append(new ServersPage(onesix));
values.append(new ScreenshotsPage(FS::PathCombine(onesix->gameRoot(), "screenshots")));
@ -52,5 +52,5 @@ class InstancePageProvider : protected QObject, public BasePageProvider {
virtual QString dialogTitle() override { return tr("Edit Instance (%1)").arg(inst->name()); }
protected:
InstancePtr inst;
BaseInstance* inst;
};

View file

@ -1,4 +1,5 @@
#include "InstanceTask.h"
#include <QDir>
#include "Application.h"
#include "settings/SettingsObject.h"
@ -82,3 +83,13 @@ void InstanceName::setName(InstanceName& other)
}
InstanceTask::InstanceTask() : Task(), InstanceName() {}
ShouldDeleteSaves askIfShouldDeleteSaves(QWidget* parent)
{
auto dialog = CustomMessageBox::selectable(parent, QObject::tr("Delete Existing Save Files"),
QObject::tr("An earlier version of this mod pack installed save files.\n"
"Would you like to remove those existing saves as part of this update?"),
QMessageBox::Question, QMessageBox::No | QMessageBox::Yes);
auto result = dialog->exec();
return result == QMessageBox::Yes ? ShouldDeleteSaves::Yes : ShouldDeleteSaves::No;
}

View file

@ -8,6 +8,8 @@ enum class InstanceNameChange { ShouldChange, ShouldKeep };
[[nodiscard]] InstanceNameChange askForChangingInstanceName(QWidget* parent, const QString& old_name, const QString& new_name);
enum class ShouldUpdate { Update, SkipUpdating, Cancel };
[[nodiscard]] ShouldUpdate askIfShouldUpdate(QWidget* parent, QString original_version_name);
enum class ShouldDeleteSaves { NotAsked, Yes, No };
[[nodiscard]] ShouldDeleteSaves askIfShouldDeleteSaves(QWidget* parent);
struct InstanceName {
public:
@ -35,7 +37,7 @@ class InstanceTask : public Task, public InstanceName {
InstanceTask();
~InstanceTask() override = default;
void setParentSettings(SettingsObjectPtr settings) { m_globalSettings = settings; }
void setParentSettings(SettingsObject* settings) { m_globalSettings = settings; }
void setStagingPath(const QString& stagingPath) { m_stagingPath = stagingPath; }
@ -60,7 +62,7 @@ class InstanceTask : public Task, public InstanceName {
}
protected: /* data */
SettingsObjectPtr m_globalSettings;
SettingsObject* m_globalSettings;
QString m_instIcon;
QString m_instGroup;
QString m_stagingPath;

View file

@ -101,6 +101,21 @@ QJsonArray requireArray(const QJsonDocument& doc, const QString& what)
return doc.array();
}
QJsonDocument parseUntilGarbage(const QByteArray& json, QJsonParseError* error, QString* garbage)
{
auto doc = QJsonDocument::fromJson(json, error);
if (error->error == QJsonParseError::GarbageAtEnd) {
qsizetype offset = error->offset;
QByteArray validJson = json.left(offset);
doc = QJsonDocument::fromJson(validJson, error);
if (garbage)
*garbage = json.right(json.size() - offset);
}
return doc;
}
void writeString(QJsonObject& to, const QString& key, const QString& value)
{
if (!value.isEmpty()) {
@ -288,7 +303,7 @@ QStringList toStringList(const QString& jsonString)
return {};
try {
return requireIsArrayOf<QString>(doc);
} catch (Json::JsonException& e) {
} catch (Json::JsonException&) {
return {};
}
}

View file

@ -107,6 +107,9 @@ QJsonArray toJsonArray(const QList<T>& container)
////////////////// READING ////////////////////
// Attempt to parse JSON up until garbage is encountered
QJsonDocument parseUntilGarbage(const QByteArray& json, QJsonParseError* error = nullptr, QString* garbage = nullptr);
/// @throw JsonException
template <typename T>
T requireIsType(const QJsonValue& value, const QString& what = "Value");

View file

@ -41,21 +41,16 @@
#include "minecraft/auth/AccountList.h"
#include "ui/InstanceWindow.h"
#include "ui/MainWindow.h"
#include "ui/dialogs/CustomMessageBox.h"
#include "ui/dialogs/MSALoginDialog.h"
#include "ui/dialogs/ProfileSelectDialog.h"
#include "ui/dialogs/ProfileSetupDialog.h"
#include "ui/dialogs/ProgressDialog.h"
#include <QHostAddress>
#include <QHostInfo>
#include <QInputDialog>
#include <QLineEdit>
#include <QList>
#include <QPushButton>
#include <QRegularExpression>
#include <QStringList>
#include <utility>
#include "BuildConfig.h"
#include "JavaCommon.h"
@ -63,7 +58,7 @@
#include "tasks/Task.h"
#include "ui/dialogs/ChooseOfflineNameDialog.h"
LaunchController::LaunchController() : Task() {}
LaunchController::LaunchController() = default;
void LaunchController::executeTask()
{
@ -86,9 +81,17 @@ void LaunchController::decideAccount()
return;
}
// Find an account to use.
auto accounts = APPLICATION->accounts();
if (accounts->count() <= 0 || !accounts->anyAccountIsValid()) {
// Select the account to use. If the instance has a specific account set, that will be used. Otherwise, the default account will be used
auto* accounts = APPLICATION->accounts();
const auto instanceAccountId = m_instance->settings()->get("InstanceAccountId").toString();
const auto instanceAccountIndex = accounts->findAccountByProfileId(instanceAccountId);
if (instanceAccountIndex == -1 || instanceAccountId.isEmpty()) {
m_accountToUse = accounts->defaultAccount();
} else {
m_accountToUse = accounts->at(instanceAccountIndex);
}
if (!accounts->anyAccountIsValid()) {
// Tell the user they need to log in at least one account in order to play.
auto reply = CustomMessageBox::selectable(m_parentWidget, tr("No Accounts"),
tr("In order to play Minecraft, you must have at least one Microsoft "
@ -106,15 +109,6 @@ void LaunchController::decideAccount()
}
}
// Select the account to use. If the instance has a specific account set, that will be used. Otherwise, the default account will be used
auto instanceAccountId = m_instance->settings()->get("InstanceAccountId").toString();
auto instanceAccountIndex = accounts->findAccountByProfileId(instanceAccountId);
if (instanceAccountIndex == -1 || instanceAccountId.isEmpty()) {
m_accountToUse = accounts->defaultAccount();
} else {
m_accountToUse = accounts->at(instanceAccountIndex);
}
if (!m_accountToUse) {
// If no default account is set, ask the user which one to use.
ProfileSelectDialog selectDialog(tr("Which account would you like to use?"), ProfileSelectDialog::GlobalDefaultCheckbox,
@ -132,35 +126,134 @@ void LaunchController::decideAccount()
}
}
bool LaunchController::askPlayDemo()
LaunchDecision LaunchController::decideLaunchMode()
{
if (!m_accountToUse || m_wantedLaunchMode == LaunchMode::Demo) {
m_actualLaunchMode = LaunchMode::Demo;
return LaunchDecision::Continue;
}
if (m_wantedLaunchMode == LaunchMode::Normal) {
if (m_accountToUse->shouldRefresh() || m_accountToUse->accountState() == AccountState::Offline) {
// Force account refresh on the account used to launch the instance updating the AccountState
// only on first try and if it is not meant to be offline
m_accountToUse->refresh();
}
}
const auto* accounts = APPLICATION->accounts();
MinecraftAccountPtr accountToCheck = nullptr;
if (m_accountToUse->accountType() != AccountType::Offline) {
accountToCheck = m_accountToUse->ownsMinecraft() ? m_accountToUse : nullptr;
} else if (const auto defaultAccount = accounts->defaultAccount(); defaultAccount && defaultAccount->ownsMinecraft()) {
accountToCheck = defaultAccount;
} else {
for (int i = 0; i < accounts->count(); i++) {
if (const auto account = accounts->at(i); account->ownsMinecraft()) {
accountToCheck = account;
break;
}
}
}
if (!accountToCheck) {
m_actualLaunchMode = LaunchMode::Demo;
return LaunchDecision::Continue;
}
auto state = accountToCheck->accountState();
if (state == AccountState::Unchecked || state == AccountState::Errored) {
accountToCheck->refresh();
state = AccountState::Working;
}
if (state == AccountState::Working) {
// refresh is in progress, we need to wait for it to finish to proceed.
ProgressDialog progDialog(m_parentWidget);
progDialog.setSkipButton(true, tr("Abort"));
// TODO: this relies on tasks' synchronous signal dispatching nature
// TODO: meaning currentTask can't complete and become null while this code is running
// TODO: this code will produce a race condition when tasks become fully async
auto task = accountToCheck->currentTask();
progDialog.execWithTask(task.get());
if (task->getState() == State::AbortedByUser) {
return LaunchDecision::Abort;
}
state = accountToCheck->accountState();
}
QString reauthReason;
switch (state) {
case AccountState::Errored:
reauthReason = tr("An error occurred while refreshing '%1'").arg(accountToCheck->profileName());
break;
case AccountState::Expired:
reauthReason = tr("'%1' has expired and needs to be reauthenticated").arg(accountToCheck->profileName());
break;
case AccountState::Disabled:
reauthReason = tr("The launcher's client identification has changed");
break;
case AccountState::Gone:
reauthReason = tr("'%1' no longer exists on the servers").arg(accountToCheck->profileName());
break;
default:
m_actualLaunchMode =
state == AccountState::Online && m_wantedLaunchMode == LaunchMode::Normal ? LaunchMode::Normal : LaunchMode::Offline;
return LaunchDecision::Continue; // All good to go
}
if (reauthenticateAccount(accountToCheck, reauthReason)) {
return LaunchDecision::Undecided;
}
return LaunchDecision::Abort;
}
bool LaunchController::askPlayDemo() const
{
QMessageBox box(m_parentWidget);
box.setWindowTitle(tr("Play demo?"));
box.setText(
tr("This account does not own Minecraft.\nYou need to purchase the game first to play it.\n\nDo you want to play "
"the demo?"));
QString text = m_accountToUse
? tr("This account does not own Minecraft.\nYou need to purchase the game first to play the full version.")
: tr("No account was selected for launch.");
text += tr("\n\nDo you want to play the demo?");
box.setText(text);
box.setIcon(QMessageBox::Warning);
auto demoButton = box.addButton(tr("Play Demo"), QMessageBox::ButtonRole::YesRole);
auto cancelButton = box.addButton(tr("Cancel"), QMessageBox::ButtonRole::NoRole);
const auto* demoButton = box.addButton(tr("Play Demo"), QMessageBox::ButtonRole::YesRole);
auto* cancelButton = box.addButton(tr("Cancel"), QMessageBox::ButtonRole::NoRole);
box.setDefaultButton(cancelButton);
box.exec();
return box.clickedButton() == demoButton;
}
QString LaunchController::askOfflineName(QString playerName, bool demo, bool* ok)
QString LaunchController::askOfflineName(const QString& playerName, bool* ok) const
{
if (ok != nullptr) {
*ok = false;
}
// we ask the user for a player name
QString message = tr("Choose your offline mode player name.");
if (demo) {
message = tr("Choose your demo mode player name.");
QString message;
switch (m_actualLaunchMode) {
case LaunchMode::Normal:
Q_ASSERT(false);
return "";
case LaunchMode::Demo:
message = tr("Choose your demo mode player name");
break;
case LaunchMode::Offline:
if (m_wantedLaunchMode == LaunchMode::Normal) {
message = tr("You are not connected to the Internet, launching in offline mode\n\n");
}
message += tr("Choose your offline mode player name");
break;
}
QString lastOfflinePlayerName = APPLICATION->settings()->get("LastOfflinePlayerName").toString();
const QString lastOfflinePlayerName = APPLICATION->settings()->get("LastOfflinePlayerName").toString();
QString usedname = lastOfflinePlayerName.isEmpty() ? playerName : lastOfflinePlayerName;
ChooseOfflineNameDialog dialog(message, m_parentWidget);
@ -170,8 +263,7 @@ QString LaunchController::askOfflineName(QString playerName, bool demo, bool* ok
return {};
}
const QString name = dialog.getUsername();
usedname = name;
usedname = dialog.getUsername();
APPLICATION->settings()->set("LastOfflinePlayerName", usedname);
if (ok != nullptr) {
@ -184,180 +276,69 @@ void LaunchController::login()
{
decideAccount();
if (!m_accountToUse) {
// if no account is selected, ask about demo
if (!m_demo) {
m_demo = askPlayDemo();
}
if (m_demo) {
// we ask the user for a player name
LaunchDecision decision = decideLaunchMode();
while (decision == LaunchDecision::Undecided) {
decision = decideLaunchMode();
}
if (decision == LaunchDecision::Abort) {
emitAborted();
return;
}
if (m_actualLaunchMode == LaunchMode::Demo) {
if (m_wantedLaunchMode == LaunchMode::Demo || askPlayDemo()) {
bool ok = false;
auto name = askOfflineName("Player", m_demo, &ok);
auto name = askOfflineName("Player", &ok);
if (ok) {
m_session = std::make_shared<AuthSession>();
static const QRegularExpression s_removeChars("[{}-]");
m_session->MakeDemo(name, MinecraftAccount::uuidFromUsername(name).toString().remove(s_removeChars));
m_session->MakeDemo(name, MinecraftAccount::uuidFromUsername(name).toString(QUuid::Id128));
launchInstance();
return;
}
}
// if no account is selected, we bail
emitFailed(tr("No account selected for launch."));
emitFailed(tr("No account selected for launch"));
return;
}
// we loop until the user succeeds in logging in or gives up
bool tryagain = true;
unsigned int tries = 0;
m_session = std::make_shared<AuthSession>();
m_session->launchMode = m_actualLaunchMode;
m_accountToUse->fillSession(m_session);
if ((m_accountToUse->accountType() != AccountType::Offline && m_accountToUse->accountState() == AccountState::Offline) ||
m_accountToUse->shouldRefresh()) {
// Force account refresh on the account used to launch the instance updating the AccountState
// only on first try and if it is not meant to be offline
m_accountToUse->refresh();
}
while (tryagain) {
if (tries > 0 && tries % 3 == 0) {
auto result =
QMessageBox::question(m_parentWidget, tr("Continue launch?"),
tr("It looks like we couldn't launch after %1 tries. Do you want to continue trying?").arg(tries));
if (result == QMessageBox::No) {
if (m_accountToUse->accountType() != AccountType::Offline) {
if (m_actualLaunchMode == LaunchMode::Normal && !m_accountToUse->hasProfile()) {
// Now handle setting up a profile name here...
if (ProfileSetupDialog dialog(m_accountToUse, m_parentWidget); dialog.exec() != QDialog::Accepted) {
emitAborted();
return;
}
}
tries++;
m_session = std::make_shared<AuthSession>();
m_session->wants_online = m_online;
m_session->demo = m_demo;
m_accountToUse->fillSession(m_session);
MinecraftAccountPtr accountToCheck;
if (m_accountToUse->ownsMinecraft())
accountToCheck = m_accountToUse;
else if (const MinecraftAccountPtr defaultAccount = APPLICATION->accounts()->defaultAccount();
defaultAccount != nullptr && defaultAccount->ownsMinecraft()) {
accountToCheck = defaultAccount;
} else {
for (int i = 0; i < APPLICATION->accounts()->count(); i++) {
MinecraftAccountPtr account = APPLICATION->accounts()->at(i);
if (account->ownsMinecraft())
accountToCheck = account;
}
}
if (accountToCheck == nullptr) {
if (!m_session->demo)
m_session->demo = askPlayDemo();
if (m_session->demo)
launchInstance();
else
emitFailed(tr("Launch cancelled - account does not own Minecraft."));
return;
}
switch (accountToCheck->accountState()) {
case AccountState::Offline: {
m_session->wants_online = false;
}
/* fallthrough */
case AccountState::Online: {
if (!m_session->wants_online) {
// we ask the user for a player name
bool ok = false;
QString name;
if (m_offlineName.isEmpty()) {
name = askOfflineName(m_session->player_name, m_session->demo, &ok);
if (!ok) {
tryagain = false;
break;
}
} else {
name = m_offlineName;
}
m_session->MakeOffline(name);
// offline flavored game from here :3
} else if (m_accountToUse == accountToCheck && !m_accountToUse->hasProfile()) {
// Now handle setting up a profile name here...
ProfileSetupDialog dialog(m_accountToUse, m_parentWidget);
if (dialog.exec() == QDialog::Accepted) {
tryagain = true;
continue;
} else {
emitFailed(tr("Received undetermined session status during login."));
return;
}
if (m_actualLaunchMode == LaunchMode::Offline && m_accountToUse->accountType() != AccountType::Offline) {
bool ok = false;
QString name = m_offlineName;
if (name.isEmpty()) {
name = askOfflineName(m_session->player_name, &ok);
if (!ok) {
emitAborted();
return;
}
if (m_accountToUse->accountType() == AccountType::Offline)
m_session->wants_online = false;
// we own Minecraft, there is a profile, it's all ready to go!
launchInstance();
return;
}
case AccountState::Errored:
// This means some sort of soft error that we can fix with a refresh ... so let's refresh.
case AccountState::Unchecked: {
accountToCheck->refresh();
}
/* fallthrough */
case AccountState::Working: {
// refresh is in progress, we need to wait for it to finish to proceed.
ProgressDialog progDialog(m_parentWidget);
progDialog.setSkipButton(true, tr("Abort"));
auto task = accountToCheck->currentTask();
progDialog.execWithTask(task.get());
// don't retry if aborted
if (task->getState() == Task::State::AbortedByUser)
tryagain = false;
continue;
}
case AccountState::Expired: {
if (reauthenticateAccount(accountToCheck))
continue;
return;
}
case AccountState::Disabled: {
auto errorString = tr("The launcher's client identification has changed. Please remove '%1' and try again.")
.arg(accountToCheck->profileName());
QMessageBox::warning(m_parentWidget, tr("Client identification changed"), errorString, QMessageBox::StandardButton::Ok,
QMessageBox::StandardButton::Ok);
emitFailed(errorString);
return;
}
case AccountState::Gone: {
auto errorString =
tr("'%1' no longer exists on the servers. It may have been migrated, in which case please add the new account "
"you migrated this one to.")
.arg(accountToCheck->profileName());
QMessageBox::warning(m_parentWidget, tr("Account gone"), errorString, QMessageBox::StandardButton::Ok,
QMessageBox::StandardButton::Ok);
emitFailed(errorString);
return;
}
m_session->MakeOffline(name);
}
}
emitFailed(tr("Failed to launch."));
launchInstance();
}
bool LaunchController::reauthenticateAccount(MinecraftAccountPtr account)
bool LaunchController::reauthenticateAccount(const MinecraftAccountPtr& account, const QString& reason)
{
auto button = QMessageBox::warning(
m_parentWidget, tr("Account refresh failed"),
tr("'%1' has expired and needs to be reauthenticated. Do you want to reauthenticate this account?").arg(account->profileName()),
m_parentWidget, tr("Account refresh failed"), tr("%1. Do you want to reauthenticate this account?").arg(reason),
QMessageBox::StandardButton::Yes | QMessageBox::StandardButton::No, QMessageBox::StandardButton::Yes);
if (button == QMessageBox::StandardButton::Yes) {
auto accounts = APPLICATION->accounts();
bool isDefault = accounts->defaultAccount() == account;
auto* accounts = APPLICATION->accounts();
const bool isDefault = accounts->defaultAccount() == account;
accounts->removeAccount(accounts->index(accounts->findAccountByProfileId(account->profileId())));
if (account->accountType() == AccountType::MSA) {
auto newAccount = MSALoginDialog::newAccount(m_parentWidget);
@ -365,8 +346,9 @@ bool LaunchController::reauthenticateAccount(MinecraftAccountPtr account)
if (newAccount != nullptr) {
accounts->addAccount(newAccount);
if (isDefault)
if (isDefault) {
accounts->setDefaultAccount(newAccount);
}
if (m_accountToUse == account) {
m_accountToUse = nullptr;
@ -377,14 +359,13 @@ bool LaunchController::reauthenticateAccount(MinecraftAccountPtr account)
}
}
emitFailed(tr("The account has expired and needs to be reauthenticated"));
return false;
}
void LaunchController::launchInstance()
{
Q_ASSERT_X(m_instance != NULL, "launchInstance", "instance is NULL");
Q_ASSERT_X(m_session.get() != nullptr, "launchInstance", "session is NULL");
Q_ASSERT(m_instance != nullptr);
Q_ASSERT(m_session.get() != nullptr);
if (!m_instance->reloadSettings()) {
QMessageBox::critical(m_parentWidget, tr("Error!"), tr("Couldn't load the instance profile."));
@ -398,37 +379,36 @@ void LaunchController::launchInstance()
return;
}
auto console = qobject_cast<InstanceWindow*>(m_parentWidget);
auto showConsole = m_instance->settings()->get("ShowConsole").toBool();
const auto* console = qobject_cast<InstanceWindow*>(m_parentWidget);
const auto showConsole = m_instance->settings()->get("ShowConsole").toBool();
if (!console && showConsole) {
APPLICATION->showInstanceWindow(m_instance);
}
connect(m_launcher.get(), &LaunchTask::readyForLaunch, this, &LaunchController::readyForLaunch);
connect(m_launcher.get(), &LaunchTask::succeeded, this, &LaunchController::onSucceeded);
connect(m_launcher.get(), &LaunchTask::failed, this, &LaunchController::onFailed);
connect(m_launcher.get(), &LaunchTask::requestProgress, this, &LaunchController::onProgressRequested);
connect(m_launcher, &LaunchTask::readyForLaunch, this, &LaunchController::readyForLaunch);
connect(m_launcher, &LaunchTask::succeeded, this, &LaunchController::onSucceeded);
connect(m_launcher, &LaunchTask::failed, this, &LaunchController::onFailed);
connect(m_launcher, &LaunchTask::requestProgress, this, &LaunchController::onProgressRequested);
// Prepend Online and Auth Status
QString online_mode;
if (m_session->wants_online) {
if (m_actualLaunchMode == LaunchMode::Normal) {
online_mode = "online";
// Prepend Server Status
QStringList servers = { "login.microsoftonline.com", "session.minecraft.net", "textures.minecraft.net", "api.mojang.com" };
const QStringList servers = { "login.microsoftonline.com", "session.minecraft.net", "textures.minecraft.net", "api.mojang.com" };
m_launcher->prependStep(makeShared<PrintServers>(m_launcher.get(), servers));
m_launcher->prependStep(makeShared<PrintServers>(m_launcher, servers));
} else {
online_mode = m_demo ? "demo" : "offline";
online_mode = m_actualLaunchMode == LaunchMode::Demo ? "demo" : "offline";
}
m_launcher->prependStep(
makeShared<TextPrint>(m_launcher.get(), "Launched instance in " + online_mode + " mode\n", MessageLevel::Launcher));
m_launcher->prependStep(makeShared<TextPrint>(m_launcher, "Launched instance in " + online_mode + " mode\n", MessageLevel::Launcher));
// Prepend Version
{
auto versionString = QString("%1 version: %2 (%3)")
.arg(BuildConfig.LAUNCHER_DISPLAYNAME, BuildConfig.printableVersionString(), BuildConfig.BUILD_PLATFORM);
m_launcher->prependStep(makeShared<TextPrint>(m_launcher.get(), versionString + "\n\n", MessageLevel::Launcher));
m_launcher->prependStep(makeShared<TextPrint>(m_launcher, versionString + "\n", MessageLevel::Launcher));
}
m_launcher->start();
}
@ -485,10 +465,10 @@ void LaunchController::onFailed(QString reason)
if (m_instance->settings()->get("ShowConsoleOnError").toBool()) {
APPLICATION->showInstanceWindow(m_instance, "console");
}
emitFailed(reason);
emitFailed(std::move(reason));
}
void LaunchController::onProgressRequested(Task* task)
void LaunchController::onProgressRequested(Task* task) const
{
ProgressDialog progDialog(m_parentWidget);
progDialog.setSkipButton(true, tr("Abort"));

View file

@ -36,30 +36,30 @@
#pragma once
#include <BaseInstance.h>
#include <tools/BaseProfiler.h>
#include <QObject>
#include "minecraft/auth/MinecraftAccount.h"
#include "minecraft/launch/MinecraftTarget.h"
class InstanceWindow;
enum class LaunchDecision { Undecided, Continue, Abort };
class LaunchController : public Task {
Q_OBJECT
public:
void executeTask() override;
LaunchController();
virtual ~LaunchController() = default;
~LaunchController() override = default;
void setInstance(InstancePtr instance) { m_instance = instance; }
void setInstance(BaseInstance* instance) { m_instance = instance; }
InstancePtr instance() { return m_instance; }
BaseInstance* instance() const { return m_instance; }
void setOnline(bool online) { m_online = online; }
void setLaunchMode(const LaunchMode mode) { m_wantedLaunchMode = mode; }
void setOfflineName(const QString& offlineName) { m_offlineName = offlineName; }
void setDemo(bool demo) { m_demo = demo; }
void setProfiler(BaseProfilerFactory* profiler) { m_profiler = profiler; }
void setParentWidget(QWidget* widget) { m_parentWidget = widget; }
@ -68,7 +68,7 @@ class LaunchController : public Task {
void setAccountToUse(MinecraftAccountPtr accountToUse) { m_accountToUse = std::move(accountToUse); }
QString id() { return m_instance->id(); }
QString id() const { return m_instance->id(); }
bool abort() override;
@ -76,27 +76,28 @@ class LaunchController : public Task {
void login();
void launchInstance();
void decideAccount();
bool askPlayDemo();
QString askOfflineName(QString playerName, bool demo, bool* ok = nullptr);
bool reauthenticateAccount(MinecraftAccountPtr account);
LaunchDecision decideLaunchMode();
bool askPlayDemo() const;
QString askOfflineName(const QString& playerName, bool* ok = nullptr) const;
bool reauthenticateAccount(const MinecraftAccountPtr& account, const QString& reason);
private slots:
void readyForLaunch();
void onSucceeded();
void onFailed(QString reason);
void onProgressRequested(Task* task);
void onProgressRequested(Task* task) const;
private:
LaunchMode m_wantedLaunchMode = LaunchMode::Normal;
LaunchMode m_actualLaunchMode = LaunchMode::Normal;
BaseProfilerFactory* m_profiler = nullptr;
bool m_online = true;
QString m_offlineName;
bool m_demo = false;
InstancePtr m_instance;
BaseInstance* m_instance = nullptr;
QWidget* m_parentWidget = nullptr;
InstanceWindow* m_console = nullptr;
MinecraftAccountPtr m_accountToUse = nullptr;
AuthSessionPtr m_session;
shared_qobject_ptr<LaunchTask> m_launcher;
MinecraftTarget::Ptr m_targetToJoin;
AuthSessionPtr m_session = nullptr;
LaunchTask* m_launcher = nullptr;
MinecraftTarget::Ptr m_targetToJoin = nullptr;
};

25
launcher/LaunchMode.h Normal file
View file

@ -0,0 +1,25 @@
// SPDX-License-Identifier: GPL-3.0-only
/*
* Prism Launcher - Minecraft Launcher
* Copyright (C) 2026 Octol1ttle <l1ttleofficial@outlook.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#pragma once
enum class LaunchMode {
Normal,
Offline,
Demo,
};

View file

@ -15,92 +15,28 @@ fi
LAUNCHER_NAME=@Launcher_APP_BINARY_NAME@
LAUNCHER_ENVNAME=@Launcher_ENVName@
LAUNCHER_DIR="$(dirname "$(readlink -f "$0")")"
echo "Launcher Dir: ${LAUNCHER_DIR}"
# Set up env.
# Pass our custom variables separately so that the launcher can remove them for child processes
export LAUNCHER_LD_LIBRARY_PATH="${LAUNCHER_DIR}/lib@LIB_SUFFIX@"
export LAUNCHER_LD_PRELOAD=""
export LAUNCHER_QT_PLUGIN_PATH="${LAUNCHER_DIR}/plugins"
export LAUNCHER_QT_FONTPATH="${LAUNCHER_DIR}/fonts"
# Makes the launcher use portals for file picking
export QT_QPA_PLATFORMTHEME=xdgdesktopportal
export LD_LIBRARY_PATH="$LAUNCHER_LD_LIBRARY_PATH:$LD_LIBRARY_PATH"
export LD_PRELOAD="$LAUNCHER_LD_PRELOAD:$LD_PRELOAD"
export QT_PLUGIN_PATH="$LAUNCHER_QT_PLUGIN_PATH:$QT_PLUGIN_PATH"
export QT_FONTPATH="$LAUNCHER_QT_FONTPATH:$QT_FONTPATH"
# Detect missing dependencies...
DEPS_LIST=`ldd "${LAUNCHER_DIR}"/plugins/*/*.so 2>/dev/null | grep "not found" | sort -u | awk -vORS=", " '{ print $1 }'`
if [ "x$DEPS_LIST" = "x" ]; then
# We have all our dependencies. Run the launcher.
echo "No missing dependencies found."
# Just to be sure...
chmod +x "${LAUNCHER_DIR}/bin/${LAUNCHER_NAME}"
ARGS=("${LAUNCHER_DIR}/${LAUNCHER_NAME}" "${LAUNCHER_DIR}/bin/${LAUNCHER_NAME}")
if [ -f portable.txt ]; then
ARGS+=("-d" "${LAUNCHER_DIR}")
fi
ARGS+=("$@")
# Run the launcher
exec -a "${ARGS[@]}"
# Run the launcher in valgrind
# valgrind --log-file="valgrind.log" --leak-check=full --track-origins=yes "${LAUNCHER_DIR}/bin/${LAUNCHER_NAME}" -d "${LAUNCHER_DIR}" "$@"
# Run the launcher with callgrind, delay instrumentation
# valgrind --log-file="valgrind.log" --tool=callgrind --instr-atstart=no "${LAUNCHER_DIR}/bin/${LAUNCHER_NAME}" -d "${LAUNCHER_DIR}" "$@"
# use callgrind_control -i on/off to profile actions
# Exit with launcher's exit code.
# exit $?
else
# apt
if which apt-file &>/dev/null; then
LIBRARIES=`echo "$DEPS_LIST" | grep -oP "[^, ]*" | sort -u`
COMMAND_LIBS=`for LIBRARY in $LIBRARIES; do apt-file -l search $LIBRARY; done`
COMMAND_LIBS=`echo "$COMMAND_LIBS" | sort -u | awk -vORS=" " '{ print $1 }'`
INSTALL_CMD="sudo apt-get install $COMMAND_LIBS"
# pacman
elif which pkgfile &>/dev/null; then
LIBRARIES=`echo "$DEPS_LIST" | grep -oP "[^, ]*" | sort -u`
COMMAND_LIBS=`for LIBRARY in $LIBRARIES; do pkgfile $LIBRARY; done`
COMMAND_LIBS=`echo "$COMMAND_LIBS" | sort -u | awk -vORS=" " '{ print $1 }'`
INSTALL_CMD="sudo pacman -S $COMMAND_LIBS"
# dnf
elif which dnf &>/dev/null; then
LIBRARIES=`echo "$DEPS_LIST" | grep -oP "[^, ]*" | sort -u`
COMMAND_LIBS=`for LIBRARY in $LIBRARIES; do dnf whatprovides -q $LIBRARY; done`
COMMAND_LIBS=`echo "$COMMAND_LIBS" | grep -v 'Repo' | sort -u | awk -vORS=" " '{ print $1 }'`
INSTALL_CMD="sudo dnf install $COMMAND_LIBS"
# yum
elif which yum &>/dev/null; then
LIBRARIES=`echo "$DEPS_LIST" | grep -oP "[^, ]*" | sort -u`
COMMAND_LIBS=`for LIBRARY in $LIBRARIES; do yum whatprovides $LIBRARY; done`
COMMAND_LIBS=`echo "$COMMAND_LIBS" | sort -u | awk -vORS=" " '{ print $1 }'`
INSTALL_CMD="sudo yum install $COMMAND_LIBS"
# zypper
elif which zypper &>/dev/null; then
LIBRARIES=`echo "$DEPS_LIST" | grep -oP "[^, ]*" | sort -u`
COMMAND_LIBS=`for LIBRARY in $LIBRARIES; do zypper wp $LIBRARY; done`
COMMAND_LIBS=`echo "$COMMAND_LIBS" | sort -u | awk -vORS=" " '{ print $1 }'`
INSTALL_CMD="sudo zypper install $COMMAND_LIBS"
# emerge
elif which pfl &>/dev/null; then
LIBRARIES=`echo "$DEPS_LIST" | grep -oP "[^, ]*" | sort -u`
COMMAND_LIBS=`for LIBRARY in $LIBRARIES; do pfl $LIBRARY; done`
COMMAND_LIBS=`echo "$COMMAND_LIBS" | sort -u | awk -vORS=" " '{ print $1 }'`
INSTALL_CMD="sudo emerge $COMMAND_LIBS"
fi
MESSAGE="Error: The launcher is missing the following libraries that it needs to work correctly:\n\t${DEPS_LIST}\nPlease install them from your distribution's package manager."
MESSAGE="$MESSAGE\n\nHint (please apply common sense): $INSTALL_CMD\n"
printerror "$MESSAGE"
exit 1
# disable OpenGL and Vulkan launcher features on sharun until https://github.com/VHSgunzo/sharun/issues/35
if [[ -f "${LAUNCHER_DIR}/sharun" ]]; then
export ${LAUNCHER_ENVNAME}_DISABLE_GLVULKAN=1
fi
# Just to be sure...
chmod +x "${LAUNCHER_DIR}/bin/${LAUNCHER_NAME}"
ARGS=("${LAUNCHER_DIR}/${LAUNCHER_NAME}" "${LAUNCHER_DIR}/bin/${LAUNCHER_NAME}")
if [ -f portable.txt ]; then
ARGS+=("-d" "${LAUNCHER_DIR}")
fi
ARGS+=("$@")
# Run the launcher
exec -a "${ARGS[@]}"

View file

@ -25,7 +25,7 @@
#include "FileSystem.h"
#include "Json.h"
#include "MangoHud.h"
#include "LibraryUtils.h"
#ifdef __GLIBC__
#ifndef _GNU_SOURCE
@ -36,9 +36,9 @@
#include <linux/limits.h>
#endif
namespace MangoHud {
namespace LibraryUtils {
QString getLibraryString()
QString findMangoHud()
{
/**
* Guess MangoHud install location by searching for vulkan layers in this order:
@ -123,7 +123,7 @@ QString getLibraryString()
#ifdef __GLIBC__
// Check whether mangohud is usable on a glibc based system
QString libraryPath = findLibrary(libraryName);
QString libraryPath = find(libraryName);
if (!libraryPath.isEmpty()) {
return libraryPath;
}
@ -138,7 +138,7 @@ QString getLibraryString()
return {};
}
QString findLibrary(QString libName)
QString find(QString libName)
{
#ifdef __GLIBC__
const char* library = libName.toLocal8Bit().constData();
@ -161,11 +161,11 @@ QString findLibrary(QString libName)
dlclose(handle);
return fullPath;
#else
qWarning() << "MangoHud::findLibrary is not implemented on this platform";
qWarning() << "LibraryUtils::find is not implemented on this platform";
return {};
#endif
}
} // namespace MangoHud
} // namespace LibraryUtils
#ifdef UNDEF_GNU_SOURCE
#undef _GNU_SOURCE

View file

@ -21,9 +21,9 @@
#include <QString>
#include <QStringList>
namespace MangoHud {
namespace LibraryUtils {
QString getLibraryString();
QString findMangoHud();
QString findLibrary(QString libName);
} // namespace MangoHud
QString find(QString libName);
} // namespace LibraryUtils

View file

@ -16,7 +16,6 @@
*/
#include <MMCTime.h>
#include <qobject.h>
#include <QDateTime>
#include <QObject>
@ -99,4 +98,4 @@ QString Time::humanReadableDuration(double duration, int precision)
os.flush();
return outStr;
}
}

View file

@ -56,18 +56,18 @@ bool mergeZipFiles(ArchiveWriter& into, QFileInfo from, QSet<QString>& contained
return r.parse([&into, &contained, &filter, from](ArchiveReader::File* f) {
auto filename = f->filename();
if (filter && !filter(filename)) {
qDebug() << "Skipping file " << filename << " from " << from.fileName() << " - filtered";
qDebug() << "Skipping file" << filename << "from" << from.fileName() << "- filtered";
f->skip();
return true;
}
if (contained.contains(filename)) {
qDebug() << "Skipping already contained file " << filename << " from " << from.fileName();
qDebug() << "Skipping already contained file" << filename << "from" << from.fileName();
f->skip();
return true;
}
contained.insert(filename);
if (!into.addFile(f)) {
qCritical() << "Failed to copy data of " << filename << " into the jar";
qCritical() << "Failed to copy data of" << filename << "into the jar";
return false;
}
return true;
@ -149,7 +149,7 @@ bool createModdedJar(QString sourceJarPath, QString targetJarPath, const QList<M
qCritical() << "Failed to add" << mod->fileinfo().fileName() << "to the jar.";
return false;
}
qDebug() << "Adding folder " << filename.fileName() << " from " << filename.absoluteFilePath();
qDebug() << "Adding folder" << filename.fileName() << "from" << filename.absoluteFilePath();
} else {
// Make sure we do not continue launching when something is missing or undefined...
zipOut.close();
@ -233,7 +233,7 @@ std::optional<QStringList> extractSubDir(ArchiveReader* zip, const QString& subd
<< target;
return false;
}
if (!f->writeFile(ext, target_file_path)) {
if (!f->writeFile(ext, target_file_path, target)) {
qWarning() << "Failed to extract file" << original_name << "to" << target_file_path;
return false;
}
@ -321,7 +321,7 @@ bool collectFileListRecursively(const QString& rootDir, const QString& subDir, Q
for (const auto& e : entries) {
if (excludeFilter && excludeFilter(e)) {
QString relativeFilePath = rootDirectory.relativeFilePath(e.absoluteFilePath());
qDebug() << "Skipping file " << relativeFilePath;
qDebug() << "Skipping file" << relativeFilePath;
continue;
}

View file

@ -28,4 +28,4 @@ QString markdownToHTML(const QString& markdown)
free(buffer);
return htmlStr;
}
}

View file

@ -21,4 +21,4 @@
#include <cmark.h>
#include <QString>
QString markdownToHTML(const QString& markdown);
QString markdownToHTML(const QString& markdown);

View file

@ -1,6 +1,5 @@
#pragma once
#include <qlogging.h>
#include <QString>
#include <compare>

View file

@ -41,8 +41,8 @@
class NullInstance : public BaseInstance {
Q_OBJECT
public:
NullInstance(SettingsObjectPtr globalSettings, SettingsObjectPtr settings, const QString& rootDir)
: BaseInstance(globalSettings, settings, rootDir)
NullInstance(SettingsObject* globalSettings, std::unique_ptr<SettingsObject> settings, const QString& rootDir)
: BaseInstance(globalSettings, std::move(settings), rootDir)
{
setVersionBroken(true);
}
@ -52,7 +52,7 @@ class NullInstance : public BaseInstance {
QString getStatusbarDescription() override { return tr("Unknown instance type"); };
QSet<QString> traits() const override { return {}; };
QString instanceConfigFolder() const override { return instanceRoot(); };
shared_qobject_ptr<LaunchTask> createLaunchTask(AuthSessionPtr, MinecraftTarget::Ptr) override { return nullptr; }
LaunchTask* createLaunchTask(AuthSessionPtr, MinecraftTarget::Ptr) override { return nullptr; }
QList<Task::Ptr> createUpdateTask() override { return {}; }
QProcessEnvironment createEnvironment() override { return QProcessEnvironment(); }
QProcessEnvironment createLaunchEnvironment() override { return QProcessEnvironment(); }

View file

@ -67,5 +67,5 @@ class PSaveFile : public QSaveFile {
QString m_absoluteFilePath;
};
#else
#define PSaveFile QSaveFile
#endif
using PSaveFile = QSaveFile;
#endif

View file

@ -66,4 +66,4 @@ inline QVariant fromList(QList<T> val)
return variantList;
}
} // namespace QVariantUtils
} // namespace QVariantUtils

View file

@ -31,7 +31,7 @@
ResourceDownloadTask::ResourceDownloadTask(ModPlatform::IndexedPack::Ptr pack,
ModPlatform::IndexedVersion version,
const std::shared_ptr<ResourceFolderModel> packs,
ResourceFolderModel* packs,
bool is_indexed)
: m_pack(std::move(pack)), m_pack_version(std::move(version)), m_pack_model(packs)
{
@ -88,7 +88,7 @@ void ResourceDownloadTask::downloadSucceeded()
m_pack_model->uninstallResource(oldFilename, true);
// also rename the shader config file
if (dynamic_cast<ShaderPackFolderModel*>(m_pack_model.get()) != nullptr) {
if (dynamic_cast<ShaderPackFolderModel*>(m_pack_model) != nullptr) {
QFileInfo oldConfig(m_pack_model->dir(), oldFilename + ".txt");
QFileInfo newConfig(m_pack_model->dir(), getFilename() + ".txt");
@ -103,8 +103,8 @@ void ResourceDownloadTask::downloadSucceeded()
void ResourceDownloadTask::downloadFailed(QString reason)
{
emitFailed(reason);
m_filesNetJob.reset();
emitFailed(reason);
}
void ResourceDownloadTask::downloadProgressChanged(qint64 current, qint64 total)

View file

@ -32,7 +32,7 @@ class ResourceDownloadTask : public SequentialTask {
public:
explicit ResourceDownloadTask(ModPlatform::IndexedPack::Ptr pack,
ModPlatform::IndexedVersion version,
std::shared_ptr<ResourceFolderModel> packs,
ResourceFolderModel* packs,
bool is_indexed = true);
const QString& getFilename() const { return m_pack_version.fileName; }
const QVariant& getVersionID() const { return m_pack_version.fileId; }
@ -44,7 +44,7 @@ class ResourceDownloadTask : public SequentialTask {
private:
ModPlatform::IndexedPack::Ptr m_pack;
ModPlatform::IndexedVersion m_pack_version;
const std::shared_ptr<ResourceFolderModel> m_pack_model;
ResourceFolderModel* m_pack_model;
NetJob::Ptr m_filesNetJob;
LocalResourceUpdateTask::Ptr m_update_task;

View file

@ -41,7 +41,7 @@ struct RuntimeContext {
return javaRealArchitecture;
}
void updateFromInstanceSettings(SettingsObjectPtr instanceSettings)
void updateFromInstanceSettings(SettingsObject* instanceSettings)
{
javaArchitecture = instanceSettings->get("JavaArchitecture").toString();
javaRealArchitecture = instanceSettings->get("JavaRealArchitecture").toString();

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