Compare commits

..

902 commits

Author SHA1 Message Date
Alexandru Ionut Tripon
d2fa7cf7f7
When auth is down, launch into offline mode (#5647)
Some checks failed
Nix / Build (aarch64-darwin) (push) Has been cancelled
Nix / Build (x86_64-linux) (push) Has been cancelled
Nix / Build (aarch64-linux) (push) Has been cancelled
2026-06-26 13:23:39 +00:00
Alexandru Ionut Tripon
585aa6e674
Add the option to sort instances by total playtime (#5714) 2026-06-26 12:18:44 +00:00
Alexandru Ionut Tripon
475ab8a208
Trim whitespace from environment variables (#5704) 2026-06-26 12:17:49 +00:00
Alexandru Ionut Tripon
62f537dd8d
Sort mod Minecraft versions as version lists (#5705) 2026-06-26 11:55:20 +00:00
DioEgizio
9c2c641531
fix: remove remaining 16x16 new.png (#5721)
Some checks are pending
Nix / Build (aarch64-darwin) (push) Waiting to run
Nix / Build (x86_64-linux) (push) Waiting to run
Nix / Build (aarch64-linux) (push) Waiting to run
2026-06-25 09:41:26 +00:00
DioEgizio
402379a841
Fixed dependencies not enabling/disabling other dependencies (#5717) 2026-06-25 09:31:29 +00:00
DioEgizio
cb56c641d7 fix: remove remaining 16x16 new.png
Signed-off-by: DioEgizio <dioegizio@protonmail.com>
2026-06-25 09:44:31 +02:00
DioEgizio
5b051e7d49
Use native APIs for GPU discovery (#5602) 2026-06-25 07:40:50 +00:00
James Zhou
f181b5d0d7 fix: recursive mod dependencies
Signed-off-by: James Zhou <yunchengzhou@gmail.com>
2026-06-24 10:39:01 -04:00
Anceph
4dc107b1fa
Change "By playtime" to "By total time played"
Co-authored-by: TheKodeToad <TheKodeToad@proton.me>
Signed-off-by: Anceph <41387237+Anceph@users.noreply.github.com>
2026-06-24 13:12:16 +03:00
Anceph
34783c10fe
Remove the comment
Signed-off-by: Anceph <41387237+Anceph@users.noreply.github.com>
2026-06-24 00:49:43 +03:00
Anceph
a607373ced Added the option to sort instances by total playtime (#5701)
Signed-off-by: Anceph <yucehasan31@gmail.com>
2026-06-24 00:23:31 +03:00
Andrey Kurlin
9752f9dfd7 fix: sort mod Minecraft versions as version lists
Signed-off-by: Andrey Kurlin <superkurlin2013@yandex.ru>
2026-06-21 23:58:54 +05:00
Andrey Kurlin
0175653881 fix: trim whitespace from environment variables
Signed-off-by: Andrey Kurlin <superkurlin2013@yandex.ru>
2026-06-21 21:18:54 +05:00
Alexandru Ionut Tripon
f654ce8212
Show process start error string in logs (#5644)
Some checks failed
Nix / Build (aarch64-darwin) (push) Has been cancelled
Nix / Build (x86_64-linux) (push) Has been cancelled
Nix / Build (aarch64-linux) (push) Has been cancelled
2026-06-17 09:57:12 +00:00
Alexandru Ionut Tripon
a8643739f0
Added missing tab stops and/or fixed their order (#5662) 2026-06-17 09:57:06 +00:00
Alexandru Ionut Tripon
d8d2f383e9
Include Flame API key in CDN downloads (#5671) 2026-06-17 09:55:30 +00:00
Tayou
2425d2f8a3
merge dialogs
Signed-off-by: Tayou <git@tayou.org>
2026-06-12 16:33:50 +02:00
Octol1ttle
b387a1f793
change(ApiHeaderProxy): include Flame API key for CDN downloads
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-06-12 19:24:06 +05:00
Tayou
d71cfc33a2
show error code in dialog, change text for no internet
Signed-off-by: Tayou <git@tayou.org>
2026-06-11 19:51:12 +02:00
Tayou
5f59aa5829
Show error message when device code authorization fails (#5645)
Some checks failed
Nix / Build (aarch64-darwin) (push) Has been cancelled
Nix / Build (x86_64-linux) (push) Has been cancelled
Nix / Build (aarch64-linux) (push) Has been cancelled
2026-06-11 13:25:36 +00:00
Tayou
768d12259b
add info & retry dialog
Signed-off-by: Tayou <git@tayou.org>
2026-06-11 14:39:19 +02:00
Tayou
0a3adb7912
on server errors, treat account as offline
Signed-off-by: Tayou <git@tayou.org>
2026-06-11 14:39:19 +02:00
Octol1ttle
a90e3d403d
fix(LauncherPartLaunch): show process start error string
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-06-10 17:19:55 +05:00
Octol1ttle
8de7aa2b17
fix(JavaChecker): show process start error string
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-06-10 17:10:33 +05:00
Dominik Pakuła
022d2fe7cd Added missing tab stops and/or fixed their order
Signed-off-by: Dominik Pakuła <domi@domi.click>
2026-06-09 19:27:54 +02:00
Tayou
803115cfde
add category selector to icon picker dialog (#4397)
Some checks failed
Nix / Build (aarch64-darwin) (push) Has been cancelled
Nix / Build (x86_64-linux) (push) Has been cancelled
Nix / Build (aarch64-linux) (push) Has been cancelled
2026-06-04 17:58:00 +00:00
Octol1ttle
81159fd9d7
fix(MSADeviceCodeStep): show network request error message
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-06-04 22:37:17 +05:00
Octol1ttle
f99a0883af
change(HardwareInfo/Windows): sort GPUs by performance, use smart pointers, log errors better
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-06-04 22:31:15 +05:00
Tayou
502a5175e2
fix category filtering
I have no idea how this worked at all when I made the commit originally, but it works now, just as well as it did on the prior commit.

Further improvements, using subfolders and other metadata will be in another PR.
Signed-off-by: Tayou <git@tayou.org>
2026-06-04 19:07:24 +02:00
Octol1ttle
6c15077731
fix(LoggedProcess): show process start error string
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-06-04 20:27:53 +05:00
Alexandru Ionut Tripon
6f3574f328
Fix memory leak and crash with data packs modal (#5551)
Some checks are pending
Nix / Build (aarch64-darwin) (push) Waiting to run
Nix / Build (x86_64-linux) (push) Waiting to run
Nix / Build (aarch64-linux) (push) Waiting to run
2026-06-04 05:38:22 +00:00
Seth Flynn
dd5261f7ad
Don't remove old Microsoft accounts until they're successfully reauthenticated (#5620) 2026-06-04 03:57:25 +00:00
Seth Flynn
ad85dc3291
AccountList: Skip refresh when !shouldRefresh (#5614) 2026-06-04 03:50:14 +00:00
Seth Flynn
77f5f92634
fix(nix): add jdk25 to wrapper (#5637) 2026-06-04 03:42:25 +00:00
Sefa Eyeoglu
5c1d783293
fix(nix): add jdk25 to wrapper
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2026-06-03 21:04:01 +02:00
cat
ea2d0d0644
AccountList: Skip refresh when !shouldRefresh
Signed-off-by: cat <cat@plan9.rocks>
2026-06-02 19:06:24 +00:00
Octol1ttle
f6d1b29b04
fix(LaunchController): don't remove account unless we have a new one
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-06-01 13:27:53 +05:00
Seth Flynn
bf8d1ca1f8
chore(deps): update determinatesystems/magic-nix-cache-action action to v14 (#5606) 2026-06-01 04:37:34 +00:00
Alexandru Ionut Tripon
cc466b44c3
chore(deps): update azure/artifact-signing-action action to v2 (#5547) 2026-06-01 04:37:16 +00:00
renovate[bot]
99291186b2
chore(deps): update determinatesystems/magic-nix-cache-action action to v14 2026-05-29 06:04:43 +00:00
renovate[bot]
2bf64efaf2
chore(deps): update azure/artifact-signing-action action to v2 2026-05-28 18:34:22 +00:00
Octol1ttle
ccc23c8bc3
change: use native APIs for GPU discovery
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-05-28 15:19:31 +05:00
TheKodeToad
fa61e58cd9
Replace exec with open and handle saving geometry in signal listener
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2026-05-28 09:20:57 +01:00
Seth Flynn
f5d7e76ac4
fix renovate using old label (#5549) 2026-05-27 22:50:58 +00:00
Sefa Eyeoglu
f67a670bcf
chore(deps): update korthout/backport-action action to v4.5 (#5466) 2026-05-23 20:27:34 +00:00
Seth Flynn
a80995ab7e
fix(nix): switch to KF6 ECM (#5545) 2026-05-23 20:17:57 +00:00
Sefa Eyeoglu
64abd37e05
clang-tidy: clang-analyzer-* (#5103) 2026-05-23 20:11:37 +00:00
Sefa Eyeoglu
23c34f495f
Fix offline accounts not being refreshed during launch (#5542) 2026-05-23 20:03:21 +00:00
Sefa Eyeoglu
d7fc7fd855
revert: "change: enable automatically enabling automatic merging on backport PRs" (#5540) 2026-05-23 20:02:08 +00:00
Alexandru Ionut Tripon
22bfe0628f
chore(deps): update cachix/install-nix-action digest to 8aa0397 (#5469) 2026-05-23 19:59:24 +00:00
renovate[bot]
d4d032afea
chore(deps): update korthout/backport-action action to v4.5 2026-05-22 18:59:55 +00:00
renovate[bot]
61cdabd40e
chore(deps): update cachix/install-nix-action digest to 8aa0397 2026-05-22 18:59:51 +00:00
Tayou
43c11a8555
Log components in instance logs (#5560) 2026-05-18 13:11:12 +00:00
Octol1ttle
547b4c0d3a
feat(instance logs): log components
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-05-18 12:18:44 +05:00
TheKodeToad
28eba8ed43
Fix memory leak and crash with data packs modal
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2026-05-15 13:01:41 +01:00
Octol1ttle
f4567bcc8c
fix renovate using old label
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-05-15 14:14:46 +05:00
Sefa Eyeoglu
8ba5444c6b
fix(nix): switch to KF6 ECM
The override can be removed after
https://github.com/NixOS/nixpkgs/pull/518987 reaches nixos-unstable

See https://github.com/NixOS/nixpkgs/pull/513691

Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2026-05-14 12:27:25 +02:00
Seth Flynn
de60d804a1
change(bug_report.yml): use input type where short answer is preferred (#5544) 2026-05-14 03:57:29 +00:00
Sefa Eyeoglu
8a7b17f958
flake.lock: Update
Flake lock file updates:

• Updated input 'nixpkgs':
    'https://releases.nixos.org/nixos/unstable/nixos-26.05pre990025.15f4ee454b1d/nixexprs.tar.xz?narHash=sha256-fN6ynMvcdwPDB09LpWJNO5ogu%2BHFydrBWXJywoI/NNg%3D' (2026-04-30)
  → 'https://releases.nixos.org/nixos/unstable/nixos-26.05pre995699.da5ad661ba4e/nixexprs.tar.xz?narHash=sha256-rNDJzV2JTV5SUTwv1cgKZYMdyoUYU9/YfegSaUf3QfY%3D' (2026-05-10)

Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2026-05-13 21:14:24 +02:00
mctaylors
558e5bc155
change(bug_report.yml): use input type where short answer is preferred
Signed-off-by: mctaylors <95250141+mctaylors@users.noreply.github.com>
2026-05-13 22:09:55 +03:00
Octol1ttle
bc1f9db653
fix offline accounts not being refreshed during launch
Closes #5435
Closes #5537

Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-05-13 17:59:03 +05:00
Trial97
6699d3eca0
clang-tidy: clang-analyzer-*
This commit aims to fix all clang-analyzer-* warnings from clang-tidy.
Here is the list of the ones found in project:
    "clang-analyzer-core.uninitialized.UndefReturn",
    "clang-analyzer-deadcode.DeadStores",
    "clang-analyzer-optin.core.EnumCastOutOfRange",
Some exceptions:
  clang-analyzer-cplusplus.NewDeleteLeaks -> may need to disable it as
is a false positive
  clang-analyzer-optin.cplusplus.VirtualCall -> may need to disable it
(or refactor a bunch of code to drop the virtual from those functions)

Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2026-05-13 10:20:26 +03:00
Seth Flynn
40824a187d
revert: "change: enable automatically enabling automatic merging on backport PRs"
Refs: d741b40
Signed-off-by: Seth Flynn <getchoo@tuta.io>
2026-05-13 02:23:28 -04:00
Alexandru Ionut Tripon
323c25d83b
Enable automatically enabling automatic merging on backport PRs (#5534) 2026-05-12 20:25:55 +00:00
Tayou
8d8951475c
Do not open account select dialog if there are no accounts (#5535) 2026-05-12 18:50:38 +00:00
Octol1ttle
d6db750797
fix: do not open account select dialog if there are no valid accounts
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-05-12 00:19:57 +05:00
Alexandru Ionut Tripon
ecc551b44e
Don't delete base directories when evicting metacache (#5513) 2026-05-11 11:15:43 +00:00
Octol1ttle
d741b403a9
change: enable automatically enabling automatic merging on backport PRs
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-05-11 15:43:26 +05:00
Tayou
0fee29559f
Fixes to translations (#5512) 2026-05-11 09:49:06 +00:00
Alexandru Ionut Tripon
d146972671
Suppress sfinae-incomplete warning (#5523) 2026-05-09 21:07:58 +00:00
Alexandru Ionut Tripon
c9d07adbbe
add file name column (#5505) 2026-05-09 21:03:47 +00:00
Octol1ttle
993eb40481
fix: suppress sfinae-incomplete warning
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-05-10 01:46:29 +05:00
Trial97
670f49309c
chore(clang-tidy): fix clang tidy warnings
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2026-05-09 23:26:23 +03:00
Trial97
b7381d8088
add size column for datapacks
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2026-05-09 23:26:23 +03:00
Trial97
bac959bc6f
chore(clang-tidy): fix clang tidy warnings
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2026-05-09 23:26:21 +03:00
Trial97
4c9081a934
add file name column
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2026-05-09 23:20:43 +03:00
Alexandru Ionut Tripon
7fcadcd7a2
Add some weird modrinth headers (#5506) 2026-05-09 19:52:55 +00:00
Trial97
97d570b343 chore(clang-tidy): fix clang tidy warnings
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2026-05-08 20:41:10 +03:00
Trial97
f9e007ca2b add update reason
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2026-05-08 20:41:10 +03:00
Trial97
a63048d7e2 chore(clang-tidy): fix clang tidy warnings
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2026-05-08 20:41:10 +03:00
Trial97
ca721f9d67 add special modrinth header
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2026-05-08 20:41:10 +03:00
Alexandru Ionut Tripon
18924e43da
fix Atl path traversal (#5511) 2026-05-07 21:16:14 +00:00
Alexandru Ionut Tripon
5d3411f412
fix: ignore non-existent or empty paths in processURLs (#5442) 2026-05-07 18:20:07 +00:00
Octol1ttle
564fca8c9b
fix: don't delete base directories when evicting metacache
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-05-07 20:48:19 +05:00
Octol1ttle
d59b4b0ad7
fix(translations): do not reset user language if translations index is missing
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-05-07 20:15:38 +05:00
Octol1ttle
49aef77f3f
fix(translations): redownload index if it is missing after file reloading
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-05-07 20:11:24 +05:00
Trial97
daa9e07e33 chore(clang-tidy): fix clang tidy warnings
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2026-05-07 15:02:50 +03:00
Trial97
4cbfe7fb0e fix atl path traversal
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2026-05-07 14:43:44 +03:00
Alexandru Ionut Tripon
5f7aa2fbdb
fix change version (#5504) 2026-05-07 11:28:13 +00:00
Alexandru Ionut Tripon
95a62a5dde
Fixes to 'Use system locale' (#5485) 2026-05-07 10:58:27 +00:00
Alexandru Ionut Tripon
d548cb2e44
INIFile: add file name to error logging (#5502) 2026-05-07 10:54:11 +00:00
Alexandru Ionut Tripon
813cff612c
Fix wrong Xbox failure string (#5492) 2026-05-07 10:53:57 +00:00
Alexandru Ionut Tripon
101127273c
chore(nix): update lockfile (#5454) 2026-05-07 10:53:46 +00:00
Trial97
b174dec0d2 fix change version triggering an intial search
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2026-05-07 08:31:49 +03:00
Trial97
4463c21c98 chore(clang-tidy): fix clang tidy warnings
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2026-05-07 08:31:49 +03:00
Octol1ttle
e7dbdf3489
INIFile: add file name to error logging
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-05-05 18:57:18 +05:00
TheKodeToad
4f58197edb
changed "Ok" to "OK" (#5331) 2026-05-05 09:21:29 +00:00
Octol1ttle
0a3f7da7e7
XboxAuthorizationStep: clang-tidy
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-05-05 13:42:45 +05:00
Alexandru Ionut Tripon
ac7c8adea2
Use "Discrete" key from switcheroo if present (#5487) 2026-05-04 20:38:17 +00:00
Alexandru Ionut Tripon
692e0ec00d
Fixes to PrismExternalUpdater (#5486) 2026-05-04 20:37:50 +00:00
Alexandru Ionut Tripon
773285054d
fix: trim whitespaces from ManagedPackURL (#5444) 2026-05-04 20:37:21 +00:00
Alexandru Ionut Tripon
5d8cdb429b
add setting to controll game assets download (#5355) 2026-05-04 20:37:06 +00:00
Alexandru Ionut Tripon
fb745777c3
Improve clang-tidy CI speed by only running autogen & autorcc (#5293) 2026-05-04 20:36:09 +00:00
Alexandru Ionut Tripon
7a94f6b4ae
Fix: Remove trademark and special characters from instance folder names (#5204) 2026-05-04 20:34:56 +00:00
Tayou
c4eb008d58
fix other logs page crash (#5458) 2026-05-04 16:03:09 +00:00
Tayou
882b8e1bf8
Fix Cmd+Q on macOS closing active window instead of quitting (#5427) 2026-05-04 15:50:11 +00:00
Octol1ttle
a021c86871
XboxAuthorizationStep: fix wrong failure string
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-05-04 20:23:27 +05:00
Tayou
bbd8c1e745
use custom QSortFilterProxyModel impl
Signed-off-by: Tayou <git@tayou.org>
2026-05-04 15:40:38 +02:00
Tayou
0c4c8703a3
rename IconPickerCategory and make public
Signed-off-by: Tayou <git@tayou.org>
2026-05-04 15:40:06 +02:00
Tayou
74308fcaa5
add category selector to icon picker dialog
it uses some regex shenanigans for this, probably not ideal, idk if theres a good way to filter the icons without adding extra metadata or storing them in subfolders

Signed-off-by: Tayou <git@tayou.org>
2026-05-04 15:40:06 +02:00
Octol1ttle
87f7c812c7
TranslationsModel: clang-tidy and code quality
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-05-04 12:39:23 +05:00
Octol1ttle
2d920da737
change(PrismExternalUpdater): allow unskipping versions by clicking "Remind Me Later"
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-05-03 18:47:35 +05:00
Octol1ttle
0f9be64d6c
fix(PrismExternalUpdater): do not show "No updates available" when ignoring skipped version during autocheck
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-05-03 18:47:35 +05:00
Octol1ttle
ae33c82268
fix(PrismExternalUpdater): show progress dialog immediately
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-05-03 18:47:35 +05:00
Octol1ttle
53dda7cd32
PrismExternalUpdater: clang-tidy
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-05-03 18:47:35 +05:00
Octol1ttle
f6096d21db
fix: use "Discrete" key from switcheroo if present
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-05-03 18:43:55 +05:00
Octol1ttle
1f291a2d79
change(updater): ignore skipped versions when update check is triggered by user
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-05-03 16:49:10 +05:00
Octol1ttle
8b159bacd8
change(LanguageSelectionWidget): 'Use system locale' -> 'Use system regional standards'
Closes #5358

Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-05-03 16:33:05 +05:00
Octol1ttle
e449aae6c8
fix(TranslationsModel): use current language instead of default when turning off 'Use system locale'
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-05-03 16:25:32 +05:00
Octol1ttle
6b5615ece9
fix(TranslationsModel): use proper way to get system locale
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-05-03 16:23:45 +05:00
github-actions[bot]
781e50cdbe chore(nix): update lockfile
Flake lock file updates:

• Updated input 'nixpkgs':
    'https://releases.nixos.org/nixos/unstable/nixos-26.05pre980183.4bd9165a9165/nixexprs.tar.xz?narHash=sha256-Gk2T0tDDDAs319hp/ak%2BbAIUG5bPMvnNEjPV8CS86Fg%3D' (2026-04-14)
  → 'https://releases.nixos.org/nixos/unstable/nixos-26.05pre990025.15f4ee454b1d/nixexprs.tar.xz?narHash=sha256-fN6ynMvcdwPDB09LpWJNO5ogu%2BHFydrBWXJywoI/NNg%3D' (2026-04-30)
2026-05-03 00:54:49 +00:00
so5iso4ka
e9cdef65e6
fix(OtherLogsPage): handle empty log lines
Signed-off-by: so5iso4ka <so5iso4ka@icloud.com>
2026-04-26 18:04:29 +03:00
Octol1ttle
6e0d9b8ca0
change: improve clang-tidy CI speed by only running autogen & autorcc
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
2026-04-24 12:11:03 +05:00
Alexandru Ionut Tripon
031015b332
chore(deps): update korthout/backport-action action to v4.4 (#5441) 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
captivator
5ad8372e16 fix: trim whitespaces from ManagedPackURL
Signed-off-by: captivator <84224501+qaptivator@users.noreply.github.com>
2026-04-22 15:38:04 +03:00
captivator
92eeeaf14f fix: ignore non-existent or empty paths in processURLs
Assisted-by: Gemini:3-Flash
Signed-off-by: captivator <84224501+qaptivator@users.noreply.github.com>
2026-04-22 12:27:18 +03: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
Trial97
418222cd6f
add setting to controll game assets download
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2026-04-19 23:51:48 +03: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
Danny
9621b59573 Change menu role for close action in MainWindow
Fixes issue in Mac OS where pressing Cmd+Q closes only the current window instead of quitting the application.

menuRole is consulted only by Qt's native macOS menu-bar integration, so this change has no effect on Windows, Linux, or BSD.

Fixes #1382

Signed-off-by: Danny <dannydjdk@users.noreply.github.com>
Assisted-by: Claude:claude-opus-4-7
2026-04-17 22:29:57 -05: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
oosh
f2c5916205 changed "Ok" to "OK"
Signed-off-by: oosh <ovtennakoon@gmail.com>
2026-04-10 10:23:18 +10: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
Trial97
66b5bd9618
add more invalid chars for folder name check
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2026-04-03 09:57:47 +03: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
633 changed files with 18945 additions and 8471 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:
@ -23,14 +23,14 @@ body:
- macOS
- Linux
- Other
- type: textarea
- type: input
attributes:
label: Version of Prism Launcher
description: The version of Prism Launcher used in the bug report.
placeholder: Prism Launcher 5.0
validations:
required: true
- type: textarea
- type: input
attributes:
label: Version of Qt
description: The version of Qt used in the bug report. You can find it in Help -> About Prism Launcher -> About Qt.

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,7 +64,7 @@ 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
@ -63,7 +75,7 @@ runs:
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
@ -78,16 +90,26 @@ runs:
# 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 \
--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
@ -108,24 +130,24 @@ runs:
# 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); do l=${l#$(pwd)/}; l=${l#${{ env.INSTALL_PORTABLE_DIR }}/}; l=${l#./}; echo $l; done > ${{ env.INSTALL_PORTABLE_DIR }}/manifest.txt
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

@ -61,7 +61,7 @@ runs:
- name: Login to Azure
if: ${{ env.CI_HAS_ACCESS_TO_AZURE != '' && inputs.azure-client-id != '' }}
uses: azure/login@v2
uses: azure/login@v3
with:
client-id: ${{ inputs.azure-client-id }}
tenant-id: ${{ inputs.azure-tenant-id }}
@ -69,17 +69,18 @@ runs:
- name: Sign executables
if: ${{ env.CI_HAS_ACCESS_TO_AZURE != '' && inputs.azure-client-id != '' }}
uses: azure/trusted-signing-action@v0
uses: azure/artifact-signing-action@v2
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
@ -141,7 +142,7 @@ runs:
- name: Sign installer
if: ${{ env.CI_HAS_ACCESS_TO_AZURE != '' && inputs.azure-client-id != '' }}
uses: azure/trusted-signing-action@v0
uses: azure/artifact-signing-action@v2
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

@ -55,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' }}

View file

@ -1,4 +1,5 @@
name: Setup Linux dependencies
description: Install and setup dependencies for building Prism Launcher
runs:
using: composite

View file

@ -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.5
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,57 +5,9 @@ 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:
@ -72,6 +24,8 @@ on:
type: string
default: Debug
permissions: {}
jobs:
build:
name: Build (${{ matrix.artifact-name }})
@ -79,6 +33,7 @@ jobs:
environment: ${{ inputs.environment || '' }}
permissions:
contents: read
# Required for Azure Trusted Signing
id-token: write
# Required for vcpkg binary cache
@ -91,12 +46,12 @@ jobs:
- os: ubuntu-24.04
artifact-name: Linux
cmake-preset: linux
qt-version: 6.10.1
qt-version: 6.10.2
- os: ubuntu-24.04-arm
artifact-name: Linux-aarch64
cmake-preset: linux
qt-version: 6.10.1
qt-version: 6.10.2
- os: windows-2022
artifact-name: Windows-MinGW-w64
@ -115,13 +70,13 @@ 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.1
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.1
qt-version: 6.10.2
- os: macos-26
artifact-name: macOS

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

@ -0,0 +1,48 @@
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: Install Nix
uses: cachix/install-nix-action@v31
- name: Run source generators
# 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 && cmake --build build --target autogen autorcc
'
# 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,12 +37,16 @@ jobs:
uses: ./.github/actions/setup-dependencies
with:
build-type: Debug
qt-version: 6.10.1
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,102 +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
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,7 +88,7 @@ jobs:
- os: ubuntu-22.04-arm
system: aarch64-linux
- os: macos-14
- os: macos-26
system: aarch64-darwin
runs-on: ${{ matrix.os }}
@ -101,7 +103,7 @@ jobs:
# For PRs
- name: Setup Nix Magic Cache
if: ${{ github.event_name == 'pull_request' }}
uses: DeterminateSystems/magic-nix-cache-action@v13
uses: DeterminateSystems/magic-nix-cache-action@v14
with:
diagnostic-endpoint: ""
use-flakehub: false
@ -109,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,10 +5,18 @@ 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
@ -16,7 +24,9 @@ jobs:
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:
@ -26,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 "[^/]+$")
@ -41,6 +51,7 @@ jobs:
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 }}
@ -83,7 +94,7 @@ 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 }}
@ -111,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@8aa03977d8d733052d78f4e008a241fd1dbf36b3 # 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,4 +1,4 @@
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 LANGUAGES C CXX)
if(APPLE)
@ -13,6 +13,10 @@ endif()
##################################### Set CMake options #####################################
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
set(CMAKE_AUTOUIC ON)
set(CMAKE_AUTOGEN_ORIGIN_DEPENDS OFF)
set(CMAKE_GLOBAL_AUTOGEN_TARGET ON)
set(CMAKE_GLOBAL_AUTORCC_TARGET ON)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake/")
@ -30,79 +34,82 @@ 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}")
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
@ -139,8 +146,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")
@ -169,12 +177,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)
@ -216,6 +225,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)
@ -281,7 +292,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()
@ -363,7 +374,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}")
@ -408,7 +419,7 @@ if(UNIX AND APPLE)
COMMAND ${ACTOOL_EXE} "${ICON_SOURCE}"
--compile "${ASSETS_OUT_DIR}"
--output-partial-info-plist /dev/null
--app-icon PrismLauncher
--app-icon ${Launcher_Name}
--enable-on-demand-resources NO
--target-device mac
--minimum-deployment-target ${CMAKE_OSX_DEPLOYMENT_TARGET}
@ -425,7 +436,7 @@ if(UNIX AND APPLE)
else()
message(WARNING "actool not found. Cannot compile macOS app icons.\n"
"Install Xcode command line tools: 'xcode-select --install'")
"Install Xcode command line tools: 'xcode-select --install'")
endif()
@ -443,7 +454,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}")
@ -481,7 +492,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 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/";
@ -188,8 +194,10 @@ class Config {
QString MODRINTH_STAGING_URL = "https://staging-api.modrinth.com/v2";
QString MODRINTH_PROD_URL = "https://api.modrinth.com/v2";
QStringList MODRINTH_MRPACK_HOSTS{ "cdn.modrinth.com", "github.com", "raw.githubusercontent.com", "gitlab.com" };
QString MODRINTH_DOWNLOAD_HOST = "cdn.modrinth.com";
QString FLAME_BASE_URL = "https://api.curseforge.com/v1";
QString FLAME_DOWNLOAD_HOST = "edge.forgecdn.net";
QString versionString() const;
/**

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>
@ -44,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>
@ -59,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>
@ -85,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>

16
flake.lock generated
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,15 +18,15 @@
},
"nixpkgs": {
"locked": {
"lastModified": 1766473571,
"narHash": "sha256-QvjEJNgMVuOootbR+DEfbiW+zSK57U32CE0jmVdcNjQ=",
"rev": "76701a179d3a98b07653e2b0409847499b2a07d3",
"lastModified": 1778443072,
"narHash": "sha256-rNDJzV2JTV5SUTwv1cgKZYMdyoUYU9/YfegSaUf3QfY=",
"rev": "da5ad661ba4e5ef59ba743f0d112cbc30e474f32",
"type": "tarball",
"url": "https://releases.nixos.org/nixos/25.11/nixos-25.11.2403.76701a179d3a/nixexprs.tar.xz"
"url": "https://releases.nixos.org/nixos/unstable/nixos-26.05pre995699.da5ad661ba4e/nixexprs.tar.xz"
},
"original": {
"type": "tarball",
"url": "https://channels.nixos.org/nixos-25.11/nixexprs.tar.xz"
"url": "https://channels.nixos.org/nixos-unstable/nixexprs.tar.xz"
}
},
"root": {

View file

@ -9,7 +9,7 @@
};
inputs = {
nixpkgs.url = "https://channels.nixos.org/nixos-25.11/nixexprs.tar.xz";
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;
@ -405,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), ".."));
}
@ -491,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;
}
@ -525,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;
}
@ -588,39 +578,37 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv)
}
{
bool migrated = false;
if (!migrated)
migrated = handleDataMigration(
dataPath, FS::PathCombine(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation), "../../PolyMC"), "PolyMC",
"polymc.cfg");
if (!migrated)
migrated = handleDataMigration(
dataPath, FS::PathCombine(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation), "../../multimc"), "MultiMC",
"multimc.cfg");
auto migrated = handleDataMigration(
dataPath, FS::PathCombine(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation), "../../PolyMC"), "PolyMC",
"polymc.cfg");
if (!migrated) {
handleDataMigration(dataPath,
FS::PathCombine(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation), "../../multimc"),
"MultiMC", "multimc.cfg");
}
}
{
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;
@ -637,11 +625,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();
}
}
@ -684,8 +672,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);
@ -743,8 +731,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", "");
@ -787,6 +776,8 @@ 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);
m_settings->registerSetting("DownloadGameFilesDuringInstanceCreation", true);
// Minecraft offline player name
m_settings->registerSetting("LastOfflinePlayerName", "");
@ -827,6 +818,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", "");
@ -861,25 +854,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);
@ -899,6 +890,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", "");
@ -910,7 +902,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>();
@ -943,15 +935,6 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv)
qInfo() << "<> Network done.";
}
// load translations
{
m_translations.reset(new TranslationsModel("translations"));
auto bcp47Name = m_settings->get("Language").toString();
m_translations->selectLanguage(bcp47Name);
qInfo() << "Your language is" << bcp47Name;
qInfo() << "<> Translations loaded.";
}
// Instance icons
{
auto setting = APPLICATION->settings()->getSetting("IconsDir");
@ -987,11 +970,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();
@ -1025,24 +1008,30 @@ 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.";
}
// now we have network, download translation updates
m_translations->downloadIndex();
// load translations
{
m_translations.reset(new TranslationsModel("translations"));
m_translations->downloadIndex();
qInfo() << "Your language is" << m_translations->selectedLanguage();
qInfo() << "<> Translations loaded.";
}
// FIXME: what to do with these?
m_profilers.insert("jprofiler", std::shared_ptr<BaseProfilerFactory>(new JProfilerFactory()));
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
@ -1199,6 +1188,10 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv)
}
}
if (qgetenv("XDG_CURRENT_DESKTOP") == "gamescope") {
installEventFilter(new ToolTipFilter);
}
if (createSetupWizard()) {
return;
}
@ -1359,8 +1352,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()) {
@ -1413,16 +1409,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)
@ -1464,7 +1450,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) {
@ -1492,23 +1478,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()
@ -1527,9 +1513,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)
@ -1548,8 +1533,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);
@ -1559,9 +1543,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;
@ -1575,7 +1557,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.";
@ -1584,7 +1566,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();
@ -1633,7 +1615,7 @@ void Application::updateIsRunning(bool running)
m_updateRunning = running;
}
void Application::controllerSucceeded()
void Application::controllerFinished()
{
auto controller = qobject_cast<LaunchController*>(sender());
if (!controller)
@ -1641,10 +1623,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);
}
@ -1654,29 +1637,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);
}
}
@ -1733,7 +1695,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;
@ -1845,22 +1807,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()
@ -1875,7 +1837,7 @@ void Application::updateCapabilities()
if (gamemode_query_status() >= 0)
m_capabilities |= SupportsGameMode;
if (!MangoHud::getLibraryString().isEmpty())
if (!LibraryUtils::findMangoHud().isEmpty())
m_capabilities |= SupportsMangoHud;
#endif
}
@ -1883,8 +1845,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
}
@ -1991,7 +1953,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();
}
};
@ -2045,7 +2007,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

@ -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
@ -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
@ -1200,76 +1206,6 @@ if(WIN32)
)
endif()
qt_wrap_ui(LAUNCHER_UI
ui/MainWindow.ui
ui/setupwizard/PasteWizardPage.ui
ui/setupwizard/AutoJavaWizardPage.ui
ui/setupwizard/LoginWizardPage.ui
ui/pages/global/AccountListPage.ui
ui/pages/global/JavaPage.ui
ui/pages/global/LauncherPage.ui
ui/pages/global/APIPage.ui
ui/pages/global/ProxyPage.ui
ui/pages/global/ExternalToolsPage.ui
ui/pages/instance/ExternalResourcesPage.ui
ui/pages/instance/NotesPage.ui
ui/pages/instance/LogPage.ui
ui/pages/instance/ServersPage.ui
ui/pages/instance/OtherLogsPage.ui
ui/pages/instance/VersionPage.ui
ui/pages/instance/ManagedPackPage.ui
ui/pages/instance/WorldListPage.ui
ui/pages/instance/ScreenshotsPage.ui
ui/pages/modplatform/atlauncher/AtlOptionalModDialog.ui
ui/pages/modplatform/atlauncher/AtlPage.ui
ui/pages/modplatform/CustomPage.ui
ui/pages/modplatform/ResourcePage.ui
ui/pages/modplatform/flame/FlamePage.ui
ui/pages/modplatform/legacy_ftb/Page.ui
ui/pages/modplatform/import_ftb/ImportFTBPage.ui
ui/pages/modplatform/ImportPage.ui
ui/pages/modplatform/OptionalModDialog.ui
ui/pages/modplatform/modrinth/ModrinthPage.ui
ui/pages/modplatform/technic/TechnicPage.ui
ui/widgets/CustomCommands.ui
ui/widgets/EnvironmentVariables.ui
ui/widgets/InfoFrame.ui
ui/widgets/ModFilterWidget.ui
ui/widgets/SubTaskProgressBar.ui
ui/widgets/AppearanceWidget.ui
ui/widgets/MinecraftSettingsWidget.ui
ui/widgets/JavaSettingsWidget.ui
ui/dialogs/CopyInstanceDialog.ui
ui/dialogs/CreateShortcutDialog.ui
ui/dialogs/ProfileSetupDialog.ui
ui/dialogs/ProgressDialog.ui
ui/dialogs/NewInstanceDialog.ui
ui/dialogs/NewComponentDialog.ui
ui/dialogs/NewsDialog.ui
ui/dialogs/ProfileSelectDialog.ui
ui/dialogs/ExportInstanceDialog.ui
ui/dialogs/ExportPackDialog.ui
ui/dialogs/ExportToModListDialog.ui
ui/dialogs/IconPickerDialog.ui
ui/dialogs/ImportResourceDialog.ui
ui/dialogs/MSALoginDialog.ui
ui/dialogs/AboutDialog.ui
ui/dialogs/ReviewMessageBox.ui
ui/dialogs/ScrollMessageBox.ui
ui/dialogs/BlockedModsDialog.ui
ui/dialogs/ChooseProviderDialog.ui
ui/dialogs/skins/SkinManageDialog.ui
ui/dialogs/ChooseOfflineNameDialog.ui
)
qt_wrap_ui(PRISM_UPDATE_UI
ui/dialogs/UpdateAvailableDialog.ui
)
if (NOT Apple)
set (LAUNCHER_UI ${LAUNCHER_UI} ${PRISM_UPDATE_UI})
endif()
qt_add_resources(LAUNCHER_RESOURCES
resources/backgrounds/backgrounds.qrc
resources/multimc/multimc.qrc
@ -1282,45 +1218,40 @@ 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}"
)
qt_wrap_ui(PRISMUPDATER_UI
updater/prismupdater/SelectReleaseDialog.ui
ui/widgets/SubTaskProgressBar.ui
ui/dialogs/ProgressDialog.ui
)
######## Windows resource files ########
if(WIN32)
set(LAUNCHER_RCS ${CMAKE_CURRENT_BINARY_DIR}/../${Launcher_Branding_WindowsRC})
endif()
include(CompilerWarnings)
######## Precompiled Headers ###########
set(PRECOMPILED_HEADERS
include/base.pch.hpp
include/qtcore.pch.hpp
include/qtgui.pch.hpp
)
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}")
add_library(Launcher_logic STATIC ${LOGIC_SOURCES} ${LAUNCHER_SOURCES} ${LAUNCHER_RESOURCES})
target_include_directories(Launcher_logic PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
target_compile_definitions(Launcher_logic PUBLIC LAUNCHER_APPLICATION)
target_precompile_headers(Launcher_logic PRIVATE ${PRECOMPILED_HEADERS})
if(${Launcher_USE_PCH})
target_precompile_headers(Launcher_logic PRIVATE ${PRECOMPILED_HEADERS})
endif()
target_link_libraries(Launcher_logic
systeminfo
Launcher_murmur2
nbt++
${ZLIB_LIBRARIES}
@ -1397,10 +1328,12 @@ if(APPLE)
endif()
endif()
target_link_libraries(Launcher_logic)
add_executable(${Launcher_Name} MACOSX_BUNDLE WIN32 main.cpp ${LAUNCHER_RCS})
target_precompile_headers(${Launcher_Name} REUSE_FROM Launcher_logic)
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)
@ -1430,12 +1363,15 @@ endif()
if(Launcher_BUILD_UPDATER)
# Updater
add_library(prism_updater_logic STATIC ${PRISMUPDATER_SOURCES} ${TASKS_SOURCES} ${PRISMUPDATER_UI})
add_library(prism_updater_logic STATIC ${PRISMUPDATER_SOURCES} ${TASKS_SOURCES})
target_include_directories(prism_updater_logic PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
target_precompile_headers(prism_updater_logic PRIVATE ${PRECOMPILED_HEADERS})
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
@ -1452,7 +1388,10 @@ if(Launcher_BUILD_UPDATER)
add_executable("${Launcher_Name}_updater" WIN32 updater/prismupdater/updater_main.cpp)
target_sources("${Launcher_Name}_updater" PRIVATE updater/prismupdater/updater.exe.manifest)
target_link_libraries("${Launcher_Name}_updater" prism_updater_logic)
target_precompile_headers("${Launcher_Name}_updater" REUSE_FROM 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")
@ -1477,16 +1416,14 @@ 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})
target_precompile_headers(filelink_logic PRIVATE ${PRECOMPILED_HEADERS})
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
@ -1496,9 +1433,11 @@ 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)
target_precompile_headers("${Launcher_Name}_filelink" REUSE_FROM filelink_logic)
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
@ -1536,6 +1475,28 @@ 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()
# sfinae-incomplete is a new GCC warning and triggers in Qt headers
# no-unknown-warning-option so that compilers that don't have sfinae-incomplete don't error
target_compile_options(Launcher_logic PRIVATE -Wno-unused-parameter -Wno-missing-field-initializers -Wno-unknown-warning-option -Wno-sfinae-incomplete)
target_compile_options(${Launcher_Name} PRIVATE -Wno-unused-parameter -Wno-missing-field-initializers -Wno-unknown-warning-option -Wno-sfinae-incomplete)
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.
@ -1585,6 +1546,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(
@ -1598,3 +1602,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

@ -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

@ -36,6 +36,7 @@
*/
#include "FileSystem.h"
#include <qcontainerfwd.h>
#include <QPair>
#include "BuildConfig.h"
@ -282,6 +283,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;
}
@ -432,7 +436,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);
@ -592,7 +596,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();
@ -680,6 +684,32 @@ bool deletePath(QString path)
return err.value() == 0;
}
bool deleteContents(const QString& path)
{
const QFileInfo info(path);
if (!info.exists()) {
return true;
}
if (!info.isDir()) {
qWarning() << "Attempted to delete contents of non-directory path:" << path;
return false;
}
bool ret = true;
for (const auto& entry : fs::directory_iterator(StringUtils::toStdString(path))) {
std::error_code err;
fs::remove_all(entry.path(), err);
if (err.value() != 0) {
qWarning().nospace() << "Could not delete directory entry " << entry.path() << ": " << QString::fromStdString(err.message());
ret = false;
}
}
return ret;
}
bool trash(QString path, QString* pathInTrash)
{
// FIXME: Figure out trash in Flatpak. Qt seemingly doesn't use the Trash portal
@ -793,68 +823,33 @@ QString NormalizePath(QString path)
}
}
static const QString BAD_WIN_CHARS = "<>:\"|?*\r\n";
static const QString BAD_NTFS_CHARS = "<>:\"|?*";
static const QString BAD_HFS_CHARS = ":";
static const QString BAD_FILENAME_CHARS = BAD_WIN_CHARS + "\\/";
QString RemoveInvalidFilenameChars(QString string, QChar replaceWith)
namespace {
const QString g_badChars = "<>:\"|?*\r\n!";
QString removeChars(QString source, QChar replace, const QString& extraChars = "")
{
for (int i = 0; i < string.length(); i++)
if (string.at(i) < ' ' || BAD_FILENAME_CHARS.contains(string.at(i)))
string[i] = replaceWith;
return string;
}
QString RemoveInvalidPathChars(QString path, QChar replaceWith)
{
QString invalidChars;
#ifdef Q_OS_WIN
invalidChars = BAD_WIN_CHARS;
#endif
// the null character is ignored in this check as it was not a problem until now
switch (statFS(path).fsType) {
case FilesystemType::FAT: // similar to NTFS
/* fallthrough */
case FilesystemType::NTFS:
/* fallthrough */
case FilesystemType::REFS: // similar to NTFS(should be available only on windows)
invalidChars += BAD_NTFS_CHARS;
break;
// case FilesystemType::EXT:
// case FilesystemType::EXT_2_OLD:
// case FilesystemType::EXT_2_3_4:
// case FilesystemType::XFS:
// case FilesystemType::BTRFS:
// case FilesystemType::NFS:
// case FilesystemType::ZFS:
case FilesystemType::APFS:
/* fallthrough */
case FilesystemType::HFS:
/* fallthrough */
case FilesystemType::HFSPLUS:
/* fallthrough */
case FilesystemType::HFSX:
invalidChars += BAD_HFS_CHARS;
break;
// case FilesystemType::FUSEBLK:
// case FilesystemType::F2FS:
// case FilesystemType::UNKNOWN:
default:
break;
auto badChars = g_badChars;
if (!extraChars.isEmpty()) {
badChars += extraChars;
}
if (invalidChars.size() != 0) {
for (int i = 0; i < path.length(); i++) {
if (path.at(i) < ' ' || invalidChars.contains(path.at(i))) {
path[i] = replaceWith;
}
for (auto& c : source) {
if (c.unicode() < 0x20 || !c.isPrint() || badChars.contains(c)) {
c = replace;
}
}
return path;
return source;
}
} // namespace
QString RemoveInvalidFilenameChars(QString string, QChar replaceWith)
{
return removeChars(std::move(string), replaceWith, "\\/");
}
QString RemoveInvalidPathChars(QString string, QChar replaceWith)
{
return removeChars(std::move(string), replaceWith);
}
QString DirNameFromString(QString string, QString inDir)
@ -950,7 +945,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");
@ -958,7 +956,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, "\"", "\\\"");
@ -1001,7 +1002,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);
@ -1100,17 +1101,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
@ -1399,14 +1400,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

@ -291,6 +291,13 @@ bool move(const QString& source, const QString& dest);
*/
bool deletePath(QString path);
/**
* Delete a folder's contents recursively but not the folder itself.
* @param path The path to the folder.
* @return Whether the deletion was completely successful.
*/
bool deleteContents(const QString& path);
bool removeFiles(QStringList listFile);
/**

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);
}
}

355
launcher/HardwareInfo.cpp Normal file
View file

@ -0,0 +1,355 @@
// 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 <QDebug>
#include <QStringList>
#if defined(Q_OS_MACOS) || defined(Q_OS_LINUX)
namespace {
QString afterColon(QString str)
{
return str.remove(0, str.indexOf(':') + 2).trimmed();
}
template <typename F>
bool readFromOutput(const char* command, F function)
{
FILE* file = popen(command, "r"); // NOLINT(*-command-processor)
if (!file) {
qWarning().nospace() << "Could not execute command '" << command << "': " << strerror(errno);
return false;
}
constexpr size_t bufferSize = 512;
std::array<char, bufferSize> buffer{};
while (fgets(buffer.data(), bufferSize, file) != nullptr) {
function(buffer.data());
}
const int exitCode = pclose(file);
if (exitCode != 0) {
if (exitCode == -1) {
qWarning().nospace() << "Could not close stream for command '" << command << "': " << strerror(errno);
} else {
qWarning().nospace() << "Command '" << command << "' exited with code " << exitCode;
}
return false;
}
return true;
}
} // namespace
#endif
#ifdef Q_OS_WINDOWS
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <QSettings>
#include <dxgi1_6.h>
#include <windows.h>
#include <wrl/client.h>
using Microsoft::WRL::ComPtr;
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;
}
QStringList HardwareInfo::gpuInfo()
{
ComPtr<IDXGIFactory6> factory;
HRESULT hr = CreateDXGIFactory1(IID_PPV_ARGS(&factory));
if (FAILED(hr)) {
qWarning() << "Could not create DXGI factory:" << Qt::hex << hr;
return { "GPU discovery failed: could not create DXGI factory" };
}
UINT i = 0;
ComPtr<IDXGIAdapter> adapter;
QStringList out;
while (factory->EnumAdapterByGpuPreference(i, DXGI_GPU_PREFERENCE_HIGH_PERFORMANCE, IID_PPV_ARGS(&adapter)) != DXGI_ERROR_NOT_FOUND) {
DXGI_ADAPTER_DESC desc;
hr = adapter->GetDesc(&desc);
if (SUCCEEDED(hr)) {
out << "GPU: " + QString::fromWCharArray(desc.Description); // NOLINT(*-pro-bounds-array-to-pointer-decay, *-no-array-decay)
} else {
qWarning() << "Could not get DXGI adapter description:" << Qt::hex << hr;
}
++i;
}
return out;
}
#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 { buffer.data() };
}
qWarning() << "Could not get CPU model: sysctlbyname";
return "";
}
uint64_t HardwareInfo::totalRamMiB()
{
uint64_t memsize = 0;
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 = 0;
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";
default:
Q_ASSERT(false);
return "";
}
}
QStringList HardwareInfo::gpuInfo()
{
QStringList out;
const bool success = readFromOutput("system_profiler SPDisplaysDataType", [&](const QString& str) {
// Chipset Model: Intel HD Graphics 620
if (str.contains("Chipset Model")) {
out << "GPU: " + afterColon(str);
}
});
if (!success) {
return { "GPU discovery failed: could not read from system_profiler" };
}
return out;
}
#elif defined(Q_OS_LINUX)
#include <fstream>
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 (const QString str = QString::fromStdString(line); str.startsWith("model name")) {
return afterColon(str);
}
}
qWarning() << "Could not get CPU model: /proc/cpuinfo";
return "unknown";
}
namespace {
uint64_t readMemInfo(const QString& searchTarget)
{
std::ifstream memin("/proc/meminfo");
for (std::string line; std::getline(memin, line);) {
// MemTotal: 16287480 kB
if (const 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;
}
} // namespace
uint64_t HardwareInfo::totalRamMiB()
{
return readMemInfo("MemTotal");
}
uint64_t HardwareInfo::availableRamMiB()
{
return readMemInfo("MemAvailable");
}
QStringList HardwareInfo::gpuInfo()
{
bool readingGpuInfo = false;
QString gpu;
QString driverInUse = "NONE";
QString driversAvailable = "NONE";
QStringList out;
const bool success = readFromOutput("lspci -k", [&](const QString& str) {
// 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") || str.contains("3D controller")) {
readingGpuInfo = true;
} else if (!str.startsWith('\t')) {
if (readingGpuInfo) {
out << QString("GPU: %1 (driver in use: %2; drivers available: %3)").arg(gpu, driverInUse, driversAvailable);
driverInUse = "NONE";
driversAvailable = "NONE";
}
readingGpuInfo = false;
}
if (!readingGpuInfo) {
return;
}
const QString value = afterColon(str);
if (str.contains("Subsystem")) {
gpu = value;
}
if (str.contains("Kernel driver in use")) {
driverInUse = value;
}
if (str.contains("Kernel modules")) {
driversAvailable = value;
}
});
if (!success) {
return { "GPU discovery failed: could not read from lspci" };
}
return out;
}
#else
QString HardwareInfo::cpuInfo()
{
return "unknown";
}
#if defined(Q_OS_FREEBSD) || defined(Q_OS_OPENBSD)
#include <cstdio>
uint64_t HardwareInfo::totalRamMiB()
{
uint64_t out = 0;
const bool success = readFromOutput("sysctl hw.physmem", [&](const QString& str) {
const uint64_t mem = str.mid(12).toULong();
// transforming kib -> mib
out = mem / 1024;
});
if (!success) {
qWarning() << "Could not get total RAM: could not read from sysctl";
return 0;
}
return out;
}
#else
uint64_t HardwareInfo::totalRamMiB()
{
return 0;
}
#endif
uint64_t HardwareInfo::availableRamMiB()
{
return 0;
}
QStringList HardwareInfo::gpuInfo()
{
return { "GPU discovery failed: not implemented for this OS" };
}
#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,25 @@
#include <QDebug>
#include <QFile>
#include "FileSystem.h"
#include "Application.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 +37,15 @@ void InstanceCreationTask::executeTask()
return;
}
if (!createInstance()) {
if (m_abort)
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,9 +64,10 @@ void InstanceCreationTask::executeTask()
setStatus(tr("Removing old conflicting files..."));
qDebug() << "Removing old files";
for (const QString& path : m_files_to_remove) {
if (!QFile::exists(path))
for (const QString& path : m_filesToRemove) {
if (!QFile::exists(path)) {
continue;
}
qDebug() << "Removing" << path;
@ -61,6 +82,61 @@ void InstanceCreationTask::executeTask()
return;
}
}
if (!m_abort)
emitSucceeded();
if (!m_abort) {
if (!APPLICATION->settings()->get("DownloadGameFilesDuringInstanceCreation").toBool()) {
emitSucceeded();
return;
}
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, const QDir& dir, const 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, const QDir& dir, const 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;
@ -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

@ -303,7 +303,7 @@ QStringList toStringList(const QString& jsonString)
return {};
try {
return requireIsArrayOf<QString>(doc);
} catch (Json::JsonException& e) {
} catch (Json::JsonException&) {
return {};
}
}

View file

@ -40,22 +40,18 @@
#include "minecraft/auth/AccountData.h"
#include "minecraft/auth/AccountList.h"
#include "net/NetUtils.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 +59,7 @@
#include "tasks/Task.h"
#include "ui/dialogs/ChooseOfflineNameDialog.h"
LaunchController::LaunchController() : Task() {}
LaunchController::LaunchController() = default;
void LaunchController::executeTask()
{
@ -86,9 +82,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,16 +110,7 @@ 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 (!m_accountToUse && accounts->anyAccountIsValid()) {
// 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,
m_parentWidget);
@ -132,46 +127,146 @@ void LaunchController::decideAccount()
}
}
bool LaunchController::askPlayDemo()
LaunchDecision LaunchController::decideLaunchMode()
{
if (!m_accountToUse || m_wantedLaunchMode == LaunchMode::Demo) {
m_actualLaunchMode = LaunchMode::Demo;
return LaunchDecision::Continue;
}
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();
const bool needsRefresh =
m_wantedLaunchMode == LaunchMode::Normal && (state == AccountState::Offline || accountToCheck->shouldRefresh());
if (state == AccountState::Unchecked || state == AccountState::Errored || needsRefresh) {
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)
{
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 title, message;
title = tr("Player name");
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) {
auto netErr = m_accountToUse->accountData()->networkError;
if (Net::isServerError(netErr)) {
title = tr("Auth servers offline");
message = tr("The Minecraft authentication servers are currently unavailable, launching in offline mode.\n\n");
} else {
title = tr("No internet connection");
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);
dialog.setWindowTitle(tr("Player name"));
dialog.setWindowTitle(title);
dialog.setUsername(usedname);
if (dialog.exec() != QDialog::Accepted) {
return {};
}
const QString name = dialog.getUsername();
usedname = name;
usedname = dialog.getUsername();
APPLICATION->settings()->set("LastOfflinePlayerName", usedname);
if (ok != nullptr) {
@ -184,189 +279,79 @@ 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;
accounts->removeAccount(accounts->index(accounts->findAccountByProfileId(account->profileId())));
auto* accounts = APPLICATION->accounts();
const bool isDefault = accounts->defaultAccount() == account;
if (account->accountType() == AccountType::MSA) {
auto newAccount = MSALoginDialog::newAccount(m_parentWidget);
if (newAccount != nullptr) {
accounts->removeAccount(accounts->index(accounts->findAccountByProfileId(account->profileId())));
accounts->addAccount(newAccount);
if (isDefault)
if (isDefault) {
accounts->setDefaultAccount(newAccount);
}
if (m_accountToUse == account) {
m_accountToUse = nullptr;
@ -377,14 +362,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 +382,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 +468,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);
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,12 +15,18 @@ fi
LAUNCHER_NAME=@Launcher_APP_BINARY_NAME@
LAUNCHER_ENVNAME=@Launcher_ENVName@
LAUNCHER_DIR="$(dirname "$(readlink -f "$0")")"
echo "Launcher Dir: ${LAUNCHER_DIR}"
# Makes the launcher use portals for file picking
export QT_QPA_PLATFORMTHEME=xdgdesktopportal
# 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}"
@ -33,4 +39,4 @@ fi
ARGS+=("$@")
# Run the launcher
exec -a "${ARGS[@]}"
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

@ -114,7 +114,7 @@ void LoggedProcess::on_error(QProcess::ProcessError error)
{
switch (error) {
case QProcess::FailedToStart: {
emit log({ tr("The process failed to start.") }, MessageLevel::Fatal);
emit log({ tr("The process failed to start: %1").arg(errorString()) }, MessageLevel::Fatal);
changeState(LoggedProcess::FailedToStart);
break;
}

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

@ -14,26 +14,26 @@
else \
type = Qt::DirectConnection;
#define DEFINE_FUNC_NO_PARAM(NAME, RET_TYPE) \
#define DEFINE_FUNC_NO_PARAM(NAME, RET_TYPE, RET_DEF) \
static RET_TYPE NAME() \
{ \
RET_TYPE ret; \
RET_TYPE ret = RET_DEF; \
GET_TYPE() \
QMetaObject::invokeMethod(s_instance, "_" #NAME, type, Q_RETURN_ARG(RET_TYPE, ret)); \
return ret; \
}
#define DEFINE_FUNC_ONE_PARAM(NAME, RET_TYPE, PARAM_1_TYPE) \
#define DEFINE_FUNC_ONE_PARAM(NAME, RET_TYPE, RET_DEF, PARAM_1_TYPE) \
static RET_TYPE NAME(PARAM_1_TYPE p1) \
{ \
RET_TYPE ret; \
RET_TYPE ret = RET_DEF; \
GET_TYPE() \
QMetaObject::invokeMethod(s_instance, "_" #NAME, type, Q_RETURN_ARG(RET_TYPE, ret), Q_ARG(PARAM_1_TYPE, p1)); \
return ret; \
}
#define DEFINE_FUNC_TWO_PARAM(NAME, RET_TYPE, PARAM_1_TYPE, PARAM_2_TYPE) \
#define DEFINE_FUNC_TWO_PARAM(NAME, RET_TYPE, RET_DEF, PARAM_1_TYPE, PARAM_2_TYPE) \
static RET_TYPE NAME(PARAM_1_TYPE p1, PARAM_2_TYPE p2) \
{ \
RET_TYPE ret; \
RET_TYPE ret = RET_DEF; \
GET_TYPE() \
QMetaObject::invokeMethod(s_instance, "_" #NAME, type, Q_RETURN_ARG(RET_TYPE, ret), Q_ARG(PARAM_1_TYPE, p1), \
Q_ARG(PARAM_2_TYPE, p2)); \
@ -53,18 +53,18 @@ class PixmapCache final : public QObject {
static void setInstance(PixmapCache* i) { s_instance = i; }
public:
DEFINE_FUNC_NO_PARAM(cacheLimit, int)
DEFINE_FUNC_NO_PARAM(clear, bool)
DEFINE_FUNC_TWO_PARAM(find, bool, const QString&, QPixmap*)
DEFINE_FUNC_TWO_PARAM(find, bool, const QPixmapCache::Key&, QPixmap*)
DEFINE_FUNC_TWO_PARAM(insert, bool, const QString&, const QPixmap&)
DEFINE_FUNC_ONE_PARAM(insert, QPixmapCache::Key, const QPixmap&)
DEFINE_FUNC_ONE_PARAM(remove, bool, const QString&)
DEFINE_FUNC_ONE_PARAM(remove, bool, const QPixmapCache::Key&)
DEFINE_FUNC_TWO_PARAM(replace, bool, const QPixmapCache::Key&, const QPixmap&)
DEFINE_FUNC_ONE_PARAM(setCacheLimit, bool, int)
DEFINE_FUNC_NO_PARAM(markCacheMissByEviciton, bool)
DEFINE_FUNC_ONE_PARAM(setFastEvictionThreshold, bool, int)
DEFINE_FUNC_NO_PARAM(cacheLimit, int, -1)
DEFINE_FUNC_NO_PARAM(clear, bool, false)
DEFINE_FUNC_TWO_PARAM(find, bool, false, const QString&, QPixmap*)
DEFINE_FUNC_TWO_PARAM(find, bool, false, const QPixmapCache::Key&, QPixmap*)
DEFINE_FUNC_TWO_PARAM(insert, bool, false, const QString&, const QPixmap&)
DEFINE_FUNC_ONE_PARAM(insert, QPixmapCache::Key, {}, const QPixmap&)
DEFINE_FUNC_ONE_PARAM(remove, bool, false, const QString&)
DEFINE_FUNC_ONE_PARAM(remove, bool, false, const QPixmapCache::Key&)
DEFINE_FUNC_TWO_PARAM(replace, bool, false, const QPixmapCache::Key&, const QPixmap&)
DEFINE_FUNC_ONE_PARAM(setCacheLimit, bool, false, int)
DEFINE_FUNC_NO_PARAM(markCacheMissByEviciton, bool, false)
DEFINE_FUNC_ONE_PARAM(setFastEvictionThreshold, bool, false, int)
// NOTE: Every function returns something non-void to simplify the macros.
private slots:

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

@ -19,23 +19,52 @@
#include "ResourceDownloadTask.h"
#include <utility>
#include "Application.h"
#include "FileSystem.h"
#include "minecraft/MinecraftInstance.h"
#include "minecraft/PackProfile.h"
#include "minecraft/mod/ResourceFolderModel.h"
#include "minecraft/mod/ShaderPackFolderModel.h"
#include "modplatform/ModIndex.h"
#include "modplatform/helpers/HashUtils.h"
#include "net/ApiDownload.h"
#include "net/ChecksumValidator.h"
namespace {
Net::ModrinthDownloadMeta createModrinthMeta(BaseInstance* instance, QString reason)
{
auto* mcInstance = dynamic_cast<MinecraftInstance*>(instance);
if (!mcInstance) {
return {};
}
auto* profile = mcInstance->getPackProfile();
if (!profile) {
return {};
}
auto loaders = profile->getModLoadersList();
return {
.reason = std::move(reason),
.gameVersion = profile->getComponentVersion("net.minecraft"),
.loader = !loaders.isEmpty() ? ModPlatform::getModLoaderAsString(loaders.first()) : "",
};
}
} // namespace
ResourceDownloadTask::ResourceDownloadTask(ModPlatform::IndexedPack::Ptr pack,
ModPlatform::IndexedVersion version,
const std::shared_ptr<ResourceFolderModel> packs,
bool is_indexed)
ResourceFolderModel* packs,
bool isIndexed,
QString downloadReason)
: m_pack(std::move(pack)), m_pack_version(std::move(version)), m_pack_model(packs)
{
if (is_indexed) {
if (isIndexed) {
m_update_task.reset(new LocalResourceUpdateTask(m_pack_model->indexDir(), *m_pack, m_pack_version));
connect(m_update_task.get(), &LocalResourceUpdateTask::hasOldResource, this, &ResourceDownloadTask::hasOldResource);
@ -45,7 +74,9 @@ ResourceDownloadTask::ResourceDownloadTask(ModPlatform::IndexedPack::Ptr pack,
m_filesNetJob.reset(new NetJob(tr("Resource download"), APPLICATION->network()));
m_filesNetJob->setStatus(tr("Downloading resource:\n%1").arg(m_pack_version.downloadUrl));
auto action = Net::ApiDownload::makeFile(m_pack_version.downloadUrl, m_pack_model->dir().absoluteFilePath(getFilename()));
auto action = Net::ApiDownload::makeFile(m_pack_version.downloadUrl, m_pack_model->dir().absoluteFilePath(getFilename()),
Net::Download::Option::NoOptions,
createModrinthMeta(m_pack_model->instance(), std::move(downloadReason)));
if (!m_pack_version.hash_type.isEmpty() && !m_pack_version.hash.isEmpty()) {
switch (Hashing::algorithmFromString(m_pack_version.hash_type)) {
case Hashing::Algorithm::Md4:
@ -82,29 +113,31 @@ void ResourceDownloadTask::downloadSucceeded()
auto oldName = std::get<0>(to_delete);
auto oldFilename = std::get<1>(to_delete);
if (oldName.isEmpty() || oldFilename == m_pack_version.fileName)
if (oldName.isEmpty() || oldFilename == m_pack_version.fileName) {
return;
}
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");
if (oldConfig.exists() && !newConfig.exists()) {
bool success = FS::move(oldConfig.filePath(), newConfig.filePath());
if (!success)
if (!success) {
emit logWarning(tr("Failed to rename shader config from '%1' to '%2'").arg(oldConfig.fileName(), newConfig.fileName()));
}
}
}
}
void ResourceDownloadTask::downloadFailed(QString reason)
{
emitFailed(reason);
m_filesNetJob.reset();
emitFailed(std::move(reason));
}
void ResourceDownloadTask::downloadProgressChanged(qint64 current, qint64 total)
@ -114,7 +147,7 @@ void ResourceDownloadTask::downloadProgressChanged(qint64 current, qint64 total)
// This indirection is done so that we don't delete a mod before being sure it was
// downloaded successfully!
void ResourceDownloadTask::hasOldResource(QString name, QString filename)
void ResourceDownloadTask::hasOldResource(const QString& name, const QString& filename)
{
to_delete = { name, filename };
}

View file

@ -32,8 +32,9 @@ class ResourceDownloadTask : public SequentialTask {
public:
explicit ResourceDownloadTask(ModPlatform::IndexedPack::Ptr pack,
ModPlatform::IndexedVersion version,
std::shared_ptr<ResourceFolderModel> packs,
bool is_indexed = true);
ResourceFolderModel* packs,
bool isIndexed = true,
QString downloadReason = "standalone");
const QString& getFilename() const { return m_pack_version.fileName; }
const QVariant& getVersionID() const { return m_pack_version.fileId; }
const ModPlatform::IndexedVersion& getVersion() const { return m_pack_version; }
@ -44,7 +45,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;
@ -56,5 +57,5 @@ class ResourceDownloadTask : public SequentialTask {
std::tuple<QString, QString> to_delete{ "", "" };
private slots:
void hasOldResource(QString name, QString filename);
void hasOldResource(const QString& name, const QString& filename);
};

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();

View file

@ -35,7 +35,6 @@
*/
#include "StringUtils.h"
#include <qpair.h>
#include <QRegularExpression>
#include <QUuid>
@ -232,4 +231,4 @@ QString StringUtils::htmlListPatch(QString htmlStr)
pos = htmlStr.indexOf(s_ulMatcher, pos);
}
return htmlStr;
}
}

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