Compare commits

...

804 Commits
9.0 ... develop

Author SHA1 Message Date
Seth Flynn
f086233186
chore(nix): update lockfile (#3693) 2025-04-29 04:23:53 -04:00
Seth Flynn
e9afa16aa1
chore: format some of the project files (#3677) 2025-04-29 04:23:25 -04:00
Trial97
8bb79cefac
chore: add format commits to the git-blame-ignore
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2025-04-29 10:47:00 +03:00
Trial97
5c8481a118
chore: reformat
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2025-04-29 10:46:41 +03:00
Alexandru Ionut Tripon
57d3d4815b
fix: build error introduced in #3516 (#3708) 2025-04-29 10:46:19 +03:00
Seth Flynn
e1fce47eb3
ci(nix): remove addtional > (#3709) 2025-04-29 03:43:32 -04:00
Trial97
7da32af1b2
ci(nix): remove addtional >
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2025-04-29 10:42:42 +03:00
Alexandru Ionut Tripon
c54f420c23
ci(nix): fix the PR number (#3703) 2025-04-29 10:33:43 +03:00
Trial97
93552277fe
fix: build error introduced in #3516
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2025-04-29 10:20:28 +03:00
Alexandru Ionut Tripon
6b4f07e976
Add checkboxes to resource downloader (#3516) 2025-04-29 08:32:30 +03:00
Alexandru Ionut Tripon
0d15699b26
change java on modpack update (#3379) 2025-04-29 08:31:59 +03:00
Alexandru Ionut Tripon
aa6324c920
chore(deps): update hendrikmuhs/ccache-action action to v1.2.18 (#3704) 2025-04-29 08:31:46 +03:00
Alexandru Ionut Tripon
a6006c3a33
chore: make all the regexes static const (#3647) 2025-04-29 00:33:49 +03:00
renovate[bot]
1c223997db
chore(deps): update hendrikmuhs/ccache-action action to v1.2.18 2025-04-28 21:33:12 +00:00
Alexandru Ionut Tripon
d6bba50d86
replace qvector with qlist (#3519) 2025-04-29 00:32:40 +03:00
Alexandru Ionut Tripon
5f20d98643
chore: update submodules (#3701) 2025-04-28 23:24:23 +03:00
Trial97
71da130fe4
ci(nix): fix the PR number
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2025-04-28 23:11:52 +03:00
Alexandru Ionut Tripon
25b1d79080
ci(nix): add github token for gh cli (#3700) 2025-04-28 22:49:38 +03:00
Trial97
c5fd5e6ac1
chore: make all the regexes static const
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2025-04-28 22:37:29 +03:00
Alexandru Ionut Tripon
21c90527d2
Parse log4j xml events in logs (#3642) 2025-04-28 18:33:17 +03:00
Alexandru Ionut Tripon
2ceb8a4986
Fix: Use after free collecting tasks from ResourceDownloadDialogs (#3670) 2025-04-28 18:32:39 +03:00
Trial97
0ccb4059a0
chore: update submodules
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2025-04-28 17:57:31 +03:00
Trial97
bcdbe79c59
fix: add github token for gh cli
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2025-04-28 17:38:01 +03:00
Rachel Powers
07a6606c9c
fix: cover both usages of the download dialog
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2025-04-28 04:49:30 -07:00
Rachel Powers
d0ccd110a1
fix: use after free begone!
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2025-04-28 04:49:23 -07:00
Rachel Powers
2031859731
Merge remote-tracking branch 'upstream/develop' into xml-logs 2025-04-28 04:11:53 -07:00
Rachel Powers
2c943a003d
feat(xml-logs): preserve whitespace lines in logs
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2025-04-28 03:54:47 -07:00
Rachel Powers
da30904630
fix: nullptr access (#3690) 2025-04-28 03:39:01 -07:00
TheKodeToad
63e30352e6
Fix catastrophic regex mistake (#3669) 2025-04-28 11:07:01 +01:00
TheKodeToad
51cd4c2174
Shallow search and lazy loading for Other Logs page (#3664) 2025-04-28 10:57:37 +01:00
TheKodeToad
1e3c197222
Merge remote-tracking branch 'upstream/develop' into shallow-lazy-otherlogs
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2025-04-28 10:31:48 +01:00
TheKodeToad
20626e6606
Fix log sorting
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2025-04-28 10:28:57 +01:00
TheKodeToad
0f7cb916cc
Pass mainclass and gameargs to the main game via system properties (#3692) 2025-04-28 09:47:25 +01:00
Alexandru Ionut Tripon
f58ee6af7a
ci(nix): fix get-merge-commit action call (#3697) 2025-04-27 23:48:49 +03:00
Rachel Powers
abba91c6fa
chore(deps): update determinatesystems/nix-installer-action action to v17 (#3686) 2025-04-27 13:46:57 -07:00
Seth Flynn
cdb4247323
Improve CI path filtering (#3696) 2025-04-27 14:48:09 -04:00
Seth Flynn
57a2ef1aed
ci: fix improper paths-ignore usage
Signed-off-by: Seth Flynn <getchoo@tuta.io>
2025-04-27 07:47:36 -04:00
Seth Flynn
3b7b9fa03c
ci: better filter workflow runs
Signed-off-by: Seth Flynn <getchoo@tuta.io>
2025-04-27 07:30:26 -04:00
Seth Flynn
47cb58d326
ci(nix): fix get-merge-commit action call
Signed-off-by: Seth Flynn <getchoo@tuta.io>
2025-04-27 07:28:25 -04:00
Seth Flynn
440f7ea9a5
Use nix-shell over nix develop in .envrc (#3634) 2025-04-27 06:46:13 -04:00
Seth Flynn
816752e4e9
Ensure Nix workflows are actually running on PRs (#3678) 2025-04-27 03:21:58 -04:00
github-actions[bot]
facc48d0f8 chore(nix): update lockfile
Flake lock file updates:

• Updated input 'nixpkgs':
    'github:NixOS/nixpkgs/b024ced1aac25639f8ca8fdfc2f8c4fbd66c48ef?narHash=sha256-fusHbZCyv126cyArUwwKrLdCkgVAIaa/fQJYFlCEqiU%3D' (2025-04-17)
  → 'github:NixOS/nixpkgs/f771eb401a46846c1aebd20552521b233dd7e18b?narHash=sha256-ITSpPDwvLBZBnPRS2bUcHY3gZSwis/uTe255QgMtTLA%3D' (2025-04-24)
2025-04-27 00:28:07 +00:00
Xander
02106ab29a
comment on property about delimeter
Signed-off-by: Xander <xander@isxander.dev>
2025-04-26 23:42:22 +01:00
Xander
a92e114236
Use \u001F instead of a space as a delimeter for game args
Signed-off-by: Xander <xander@isxander.dev>
2025-04-26 21:57:28 +01:00
Xander
a702d06cd8
Pass mainclass and gameargs to the main game via system properties
Signed-off-by: Xander <xander@isxander.dev>
2025-04-26 21:41:14 +01:00
Seth Flynn
abe18fb144
ci(nix): checkout merge commit of pull request
Signed-off-by: Seth Flynn <getchoo@tuta.io>
2025-04-26 15:02:39 -04:00
Rachel Powers
83ebb5984b
fix: nullptr access
style can't always be created

Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2025-04-25 19:18:28 -07:00
renovate[bot]
f2a601f815
chore(deps): update determinatesystems/nix-installer-action action to v17 2025-04-24 16:58:13 +00:00
Seth Flynn
e03870d3f2
ci(get-merge-commit): init
Signed-off-by: Seth Flynn <getchoo@tuta.io>
2025-04-20 16:52:14 -04:00
Alexandru Ionut Tripon
60e279bf39
chore(nix): update lockfile (#3672) 2025-04-20 08:29:12 +03:00
github-actions[bot]
3fd5557f89 chore(nix): update lockfile
Flake lock file updates:

• Updated input 'libnbtplusplus':
    'github:PrismLauncher/libnbtplusplus/23b955121b8217c1c348a9ed2483167a6f3ff4ad?narHash=sha256-yy0q%2Bbky80LtK1GWzz7qpM%2BaAGrOqLuewbid8WT1ilk%3D' (2023-11-06)
  → 'github:PrismLauncher/libnbtplusplus/531449ba1c930c98e0bcf5d332b237a8566f9d78?narHash=sha256-qhmjaRkt%2BO7A%2Bgu6HjUkl7QzOEb4r8y8vWZMG2R/C6o%3D' (2025-04-16)
• Updated input 'nixpkgs':
    'github:NixOS/nixpkgs/2631b0b7abcea6e640ce31cd78ea58910d31e650?narHash=sha256-LWqduOgLHCFxiTNYi3Uj5Lgz0SR%2BXhw3kr/3Xd0GPTM%3D' (2025-04-12)
  → 'github:NixOS/nixpkgs/b024ced1aac25639f8ca8fdfc2f8c4fbd66c48ef?narHash=sha256-fusHbZCyv126cyArUwwKrLdCkgVAIaa/fQJYFlCEqiU%3D' (2025-04-17)
• Updated input 'qt-qrcodegenerator':
    'github:nayuki/QR-Code-generator/f40366c40d8d1956081f7ec643d240c02a81df52?narHash=sha256-5%2BiYwsbX8wjKZPCy7ENj5HCYgOqzeSNLs/YrX2Vc7CQ%3D' (2024-11-18)
  → 'github:nayuki/QR-Code-generator/2c9044de6b049ca25cb3cd1649ed7e27aa055138?narHash=sha256-6SugPt0lp1Gz7nV23FLmsmpfzgFItkSw7jpGftsDPWc%3D' (2025-01-23)
2025-04-20 00:28:02 +00:00
Rachel Powers
1bd1245d86
feat(xml-logs): Case insisitive xml parseing + cleaner switch
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2025-04-19 13:48:18 -07:00
TheKodeToad
11015a22d2
Remove commented out code
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2025-04-19 13:02:40 -07:00
TheKodeToad
266031df81
Fix compilation on Qt 6.4.2
Is this an EOL version lol

Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2025-04-19 13:02:40 -07:00
Rachel Powers
21570a03fb
feat(xml-logs): finish tests
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2025-04-19 13:02:30 -07:00
Rachel Powers
bfdc77665d
feat(xml-logs): add tests
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2025-04-19 12:54:45 -07:00
Rachel Powers
47295da390
feat(logs): parse log4j xml events in logs
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2025-04-19 12:54:40 -07:00
Rachel Powers
15a981b3f8
fix: gzip file parsing as a stream (#3667) 2025-04-19 05:33:56 -07:00
TheKodeToad
feec7bf249
chore: update submodules (#3643) 2025-04-19 11:08:34 +01:00
TheKodeToad
111cdc240e
Disable auto-reload of files
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2025-04-19 09:34:12 +01:00
Rachel Powers
2ce1fdcee0
chore(deps): update cachix/install-nix-action digest to 754537a (#3666) 2025-04-18 20:39:40 -07:00
Rachel Powers
16b0447dc9
blocked-prs workflow fixes (#3665) 2025-04-18 20:39:22 -07:00
Rachel Powers
0e00c28450
Console colors and log invocation location (#3654) 2025-04-18 20:38:55 -07:00
TheKodeToad
92ba13cfdb
Fix catastrophic regex mistake
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2025-04-19 00:12:38 +01:00
TheKodeToad
0aa3341d58
Fix other weird import
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2025-04-19 00:07:13 +01:00
TheKodeToad
19b241fd31
Include txt too
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2025-04-19 00:07:12 +01:00
TheKodeToad
8ea5eac29c
Make requested changes
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2025-04-18 23:50:02 +01:00
TheKodeToad
96a4b78e2e
Remove accidental return
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2025-04-18 23:46:55 +01:00
Trial97
49f0e8ef6b
replace qvector with qlist
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2025-04-19 00:59:48 +03:00
Trial97
d1c7107575
fix: gzip file parsing as a stream
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2025-04-19 00:41:24 +03:00
renovate[bot]
95492cdeef
chore(deps): update cachix/install-nix-action digest to 754537a 2025-04-18 20:57:31 +00:00
Seth Flynn
b6e48ac641
ci(blocked-prs): allow workflow_dispatch on blocking prs
Signed-off-by: Seth Flynn <getchoo@tuta.io>
2025-04-18 16:56:19 -04:00
Seth Flynn
e9f7ba188b
ci(blocked-prs): use object filter to check pr label
https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/evaluate-expressions-in-workflows-and-actions#example-using-an-object-filter

Signed-off-by: Seth Flynn <getchoo@tuta.io>
2025-04-18 16:53:16 -04:00
Seth Flynn
7f2f62afa8
ci(blocked-prs): use pull_request_target
This needs to run in the context of our repo to have access to it's
secrets

Signed-off-by: Seth Flynn <getchoo@tuta.io>
2025-04-18 16:50:25 -04:00
Seth Flynn
3df98dd5e7
Remove support for Qt 5 (#2174) 2025-04-18 16:26:55 -04:00
TheKodeToad
01efd5b5d8
Fix double load (again lol)
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2025-04-18 21:24:25 +01:00
TheKodeToad
d5db974008
Shallow search and lazy loading for Other Logs page
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2025-04-18 20:14:33 +01:00
TheKodeToad
a39edb3b59
Optimise log colourisation (#3641) 2025-04-18 20:14:17 +01:00
TheKodeToad
0f847d6682
Fix mistakes
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2025-04-18 19:40:19 +01:00
TheKodeToad
f307340690 Fix formatting
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2025-04-18 11:32:50 -07:00
TheKodeToad
166b2cb286 Tweak log formatting
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2025-04-18 11:32:50 -07:00
Alexandru Ionut Tripon
5cab302ce4
chore: improve log display (#3658) 2025-04-18 21:31:41 +03:00
Alexandru Ionut Tripon
8373fa81f1
chore: add getOrRegisterSetting function (#3660) 2025-04-18 21:31:22 +03:00
Trial97
0948d3598b
chore: improve log display
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2025-04-18 20:38:37 +03:00
Trial97
5af06dec85
chore: add getOrRegisterSetting function
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2025-04-18 20:02:52 +03:00
Alexandru Ionut Tripon
5eb8561157
add qr code support for login (#3257) 2025-04-18 18:48:26 +03:00
Alexandru Ionut Tripon
c622c83930
Add Popup for metacache clear failures (#3586) 2025-04-18 18:47:12 +03:00
Alexandru Ionut Tripon
e9245716f7
fix: load world size async (#3651) 2025-04-18 18:47:05 +03:00
Alexandru Ionut Tripon
6f38ab3fb0
fix: beginResetModel called before endResetModel (#3657) 2025-04-18 18:46:59 +03:00
Trial97
cb591ba52e
chore:add qr code support for login
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2025-04-18 18:46:10 +03:00
Trial97
cddf00c61b
fix: beginResetModel called before endResetModel
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2025-04-18 14:10:00 +03:00
Trial97
2271a05b19
chore: add back deprecation warnings and disable all API deprecated before 6.0
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2025-04-18 12:37:54 +03:00
Rachel Powers
45b6454222
feat(ansi-console): Format console with ansi excapes
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2025-04-18 00:39:19 -07:00
Rachel Powers
4a2b5c72dc
feat(color-console): support ansi colors in console
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2025-04-17 14:54:44 -07:00
Trial97
5fee4e3f8b
chore: remove qt5 from release and copyright
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2025-04-18 00:17:29 +03:00
Trial97
442aae88ce
chore: remove qt version checks from code
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2025-04-17 23:46:55 +03:00
Trial97
59bd6a915b
chore: remove qt5 from cmake files
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2025-04-17 23:38:49 +03:00
Trial97
8a3aafc274
chore: remove qt5 from github actions
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2025-04-17 23:38:48 +03:00
Trial97
efeaefbf2e
fix: load world size async
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2025-04-17 23:31:25 +03:00
Trial97
6e00f94a57
chore: rename varibales to match code standards
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2025-04-17 22:43:32 +03:00
Rachel Powers
564f120c22
chore: sync cmake version with the one used in the launcher (#3644) 2025-04-16 19:35:30 -07:00
Alexandru Ionut Tripon
202095c466
fix: compile warning regarding duplicate object name (#3645) 2025-04-16 21:30:48 +03:00
Trial97
b70d9d6537
chore: update submodules
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2025-04-16 17:56:01 +03:00
Trial97
c3f4735808
fix: compile warning regarding duplicate object name
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2025-04-16 17:02:22 +03:00
Trial97
5ce6ad604b
chore: sync cmake version with the one used in the launcher
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2025-04-16 16:54:08 +03:00
Alexandru Ionut Tripon
8285993f38
fix: crash when the instance window is closed before download dialog is open (#3614) 2025-04-16 16:28:11 +03:00
TheKodeToad
df15aacfbb
Harmonizing "Other Log" page with "Minecraft Log" (#3638) 2025-04-15 21:49:13 +01:00
Yihe Li
29b81e7163
Set parent for LogModel
Signed-off-by: Yihe Li <winmikedows@hotmail.com>
2025-04-15 23:11:54 +08:00
TheKodeToad
ce76320b23
Remove unnecessary import
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2025-04-15 15:58:11 +01:00
TheKodeToad
be803b3279
Optimise guessLevel
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2025-04-15 15:39:27 +01:00
Alexandru Ionut Tripon
8f54a8c8dc
Fix icon removal in icon picker (#3410) 2025-04-15 16:58:13 +03:00
Yihe Li
521302a962
Move delete buttons to the same line & set model to nullptr before adding lines
Signed-off-by: Yihe Li <winmikedows@hotmail.com>
2025-04-15 20:35:05 +08:00
Yihe Li
de66fe4eda
Apparently removeLast() only comes in Qt 6.5+
Signed-off-by: Yihe Li <winmikedows@hotmail.com>
2025-04-15 06:16:47 +08:00
Yihe Li
5634723ecd
Harmonizing other log controls with minecraft log
Signed-off-by: Yihe Li <winmikedows@hotmail.com>
2025-04-15 06:00:49 +08:00
Yihe Li
1ee1bab067
Add color lines button
Signed-off-by: Yihe Li <winmikedows@hotmail.com>
2025-04-15 05:07:56 +08:00
Yihe Li
4ac6a0629b
Use LogView to implement level highlighting for other logs
Signed-off-by: Yihe Li <winmikedows@hotmail.com>
2025-04-15 03:42:51 +08:00
timoreo
41a790d258
Shorten LocalPeer socket names to fix CLI not working if an instance of the launcher is already running (#3630) 2025-04-14 11:40:38 +02:00
Rachel Powers
bd304eee94
chore: use nix-shell over nix develop in .envrc (brakes less things)
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2025-04-13 12:16:07 -07:00
Alexandru Ionut Tripon
42007290a0
Start using patch versioning for launcher (#3605) 2025-04-13 20:27:14 +03:00
Kenneth Chew
7d4034cfa5
Shorten LocalPeer socket names
On most systems supporting Unix sockets, the maximum length of a socket name is quite low (e.g. on macOS 104 characters and on Linux 108). If the name is too long, the sockets will not work and thus sending messages to a running instance of the launcher will not work.

Signed-off-by: Kenneth Chew <79120643+kthchew@users.noreply.github.com>
2025-04-13 02:33:22 -04:00
Alexandru Ionut Tripon
edd88b9603
chore(nix): update lockfile (#3628) 2025-04-13 08:15:13 +03:00
github-actions[bot]
6812d137e6 chore(nix): update lockfile
Flake lock file updates:

• Updated input 'nixpkgs':
    'github:NixOS/nixpkgs/2c8d3f48d33929642c1c12cd243df4cc7d2ce434?narHash=sha256-F7n4%2BKOIfWrwoQjXrL2wD9RhFYLs2/GGe/MQY1sSdlE%3D' (2025-04-02)
  → 'github:NixOS/nixpkgs/2631b0b7abcea6e640ce31cd78ea58910d31e650?narHash=sha256-LWqduOgLHCFxiTNYi3Uj5Lgz0SR%2BXhw3kr/3Xd0GPTM%3D' (2025-04-12)
2025-04-13 00:51:01 +00:00
Rachel Powers
a8e5e8dcfc
Fix compatibility with Qt 6.9 (#3622) 2025-04-11 11:44:41 -07:00
Yihe Li
8bb9b168fb
Use explicit construction for QFile from QString
Signed-off-by: Yihe Li <winmikedows@hotmail.com>
2025-04-12 01:59:07 +08:00
timoreo
a601a7cb06
chore: remove release macos Legacy reference (#3619) 2025-04-11 08:32:45 +02:00
Trial97
cc69a59f36
fix: crash when the instance window is closed before download dialog is open
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2025-04-11 08:38:05 +03:00
Trial97
d1eebbceff
chore: remove release macos Legacy reference
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2025-04-11 08:33:27 +03:00
Alexandru Ionut Tripon
c430b66657
Drop ghc_filesystem (#3608) 2025-04-10 22:39:10 +03:00
Trial97
4361aaa094
remove ghc_filesystem
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2025-04-10 22:38:55 +03:00
Alexandru Ionut Tripon
2ec0457854
Remove macOS Legacy build (#3607) 2025-04-10 22:38:24 +03:00
Seth Flynn
9364753d51
[Linux] Update to Qt 6.8.1 (#3610) 2025-04-09 17:22:06 -04:00
Alexandru Ionut Tripon
a6f00330a6
Improvements to modlist export (#3512) 2025-04-10 00:16:32 +03:00
Seth Flynn
a3b8846465
[Linux] Bump Ubuntu requirement to 22.04 (#3612) 2025-04-08 21:14:06 -04:00
Trial97
1a3cc00438
deprecate ubuntu 20.04 runner
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2025-04-08 21:37:34 +03:00
Trial97
5ba25a1476
remove mac legacy build
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2025-04-08 21:36:13 +03:00
Trial97
c89a8a676e
increment linux qt version
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2025-04-08 20:43:41 +03:00
Rachel Powers
b579cae5c2
feat(server): start using semver for launcher
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2025-04-08 04:27:06 -07:00
Seth Flynn
734db2bedc
Use ninja with MSVC on x64 (#3587) 2025-04-07 09:25:31 -04:00
Seth Flynn
4995bdcad6
Fix Nix release CI (#3594) 2025-04-07 09:13:23 -04:00
Seth Flynn
d92f7b3c97
ci: use ninja with msvc on x64
Signed-off-by: Seth Flynn <getchoo@tuta.io>
2025-04-07 09:01:32 -04:00
Seth Flynn
6386d044e3
revert: "feat: publish on flakehub"
Flakehub requires semver. We don't use that (yet)

Refs: 86cc6d3
Signed-off-by: Seth Flynn <getchoo@tuta.io>
2025-04-07 08:40:15 -04:00
Seth Flynn
180292098d
ci(nix): pin release packages in cachix
Signed-off-by: Seth Flynn <getchoo@tuta.io>
2025-04-07 08:40:15 -04:00
Seth Flynn
76bec385d6
ci(nix): correctly parse action env vars as bools
Signed-off-by: Seth Flynn <getchoo@tuta.io>
2025-04-07 08:40:15 -04:00
Seth Flynn
1a5a162727
ci(nix): ignore more paths
Signed-off-by: Seth Flynn <getchoo@tuta.io>
2025-04-07 08:40:14 -04:00
Seth Flynn
da3a498490
ci(nix): run on tags
Signed-off-by: Seth Flynn <getchoo@tuta.io>
2025-04-07 08:40:14 -04:00
Seth Flynn
3f1b91c611
chore(nix): update lockfile (#3581) 2025-04-07 08:13:04 -04:00
Soup of the tomato kind
9b3fa591d3
Update launcher/net/HttpMetaCache.h
Co-authored-by: Alexandru Ionut Tripon <alexandru.tripon97@gmail.com>
Signed-off-by: Soup of the tomato kind <43444191+Soup-64@users.noreply.github.com>
2025-04-06 16:24:09 -04:00
Soup of the tomato kind
25d7db207d
Update FileSystem.cpp
fix oopsie

Signed-off-by: Soup of the tomato kind <43444191+Soup-64@users.noreply.github.com>
2025-04-06 16:15:02 -04:00
Soup
0c90530f88
cleanup
Fix formatting and fix a typo in the return code check

Signed-off-by: Soup <43444191+Soup-64@users.noreply.github.com>
2025-04-06 16:09:49 -04:00
Soup
b9a1fa3645
Implement popup for metacache
someone in the Discord ran into an issue somewhat related to the metacache button not working (folder in use err), so this warning makes it more obvious when this happens, though it would be better to find out why it ran into a process conflict

Signed-off-by: Soup <43444191+Soup-64@users.noreply.github.com>
2025-04-06 16:09:42 -04:00
Seth Flynn
6dd8bd0708
Use default palette on all system themes (#3584) 2025-04-06 15:55:02 -04:00
Seth Flynn
e5861129ad
fix(SystemTheme): use default palette on all system themes
Signed-off-by: Seth Flynn <getchoo@tuta.io>
2025-04-06 06:41:37 -04:00
github-actions[bot]
aec410cb28 chore(nix): update lockfile
Flake lock file updates:

• Updated input 'nixpkgs':
    'github:NixOS/nixpkgs/5e5402ecbcb27af32284d4a62553c019a3a49ea6?narHash=sha256-gWd4urRoLRe8GLVC/3rYRae1h%2BxfQzt09xOfb0PaHSk%3D' (2025-03-27)
  → 'github:NixOS/nixpkgs/2c8d3f48d33929642c1c12cd243df4cc7d2ce434?narHash=sha256-F7n4%2BKOIfWrwoQjXrL2wD9RhFYLs2/GGe/MQY1sSdlE%3D' (2025-04-02)
2025-04-06 00:27:19 +00:00
Seth Flynn
c1b460fa05
Nix Flake spring cleaning (#3560) 2025-04-04 05:01:40 -04:00
Alexandru Ionut Tripon
1bed9536f3
Add checkbox for LiteLoader in mod filter (#3572) 2025-04-04 08:12:52 +03:00
Alexandru Ionut Tripon
5ad6e7b50d
chore(deps): update actions/create-github-app-token action to v2 (#3575) 2025-04-04 08:11:15 +03:00
hanlie
12c266f8bd Update ExportToModListDialog.ui
Signed-off-by: hanlie <48323966+HanlieChina@users.noreply.github.com>
2025-04-04 11:22:00 +08:00
renovate[bot]
dc4cb8b9d5
chore(deps): update actions/create-github-app-token action to v2 2025-04-03 22:22:42 +00:00
Yihe Li
3ae68114f6
Remove extra argument from ModFilterWidget::create
Signed-off-by: Yihe Li <winmikedows@hotmail.com>
2025-04-02 16:28:49 +08:00
Yihe Li
b0c85fd539
Hide checkbox for CurseForge
Signed-off-by: Yihe Li <winmikedows@hotmail.com>
2025-04-02 16:22:52 +08:00
Yihe Li
0518c50958
Add checkbox for LiteLoader in mod filter
Signed-off-by: Yihe Li <winmikedows@hotmail.com>
2025-04-02 16:01:45 +08:00
Rachel Powers
e883e9f359
(blocked-pr): push json expansion into env (#3571) 2025-04-01 23:53:34 -07:00
Rachel Powers
8fd86e065e
push json expansion into env
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2025-04-01 23:46:49 -07:00
Rachel Powers
f82b050bca
Fix blocked pr comment body (#3570)
* Add newline to seperate header from comment body

Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>

* Apply suggestions from code review

Co-authored-by: Seth Flynn <getchoo@tuta.io>
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>

---------

Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
Co-authored-by: Seth Flynn <getchoo@tuta.io>
2025-04-02 02:33:17 -04:00
Alexandru Ionut Tripon
3042e051c7
ci: add a workflow to detect and check dependencies for blocked pull requests (#3497) 2025-04-02 09:08:21 +03:00
Alexandru Ionut Tripon
40ff0321f6
Rename instance's physical dir when renaming instances (#3550) 2025-04-02 09:03:08 +03:00
TheKodeToad
1e5d21be61
feat: add updater dialogues (#3454) 2025-04-01 16:09:40 +01:00
Seth Flynn
1d45850b6d
chore(deps): update cachix/install-nix-action digest to d1ca217 (#3563) 2025-03-31 21:41:17 -04:00
renovate[bot]
b1c4e85806
chore(deps): update cachix/install-nix-action digest to d1ca217 2025-03-31 19:53:22 +00:00
Seth Flynn
de08d7c364
chore(gitignore): add more nix-related files
Signed-off-by: Seth Flynn <getchoo@tuta.io>
2025-03-31 01:28:43 -04:00
Seth Flynn
e9cac2e0e3
refactor(nix): use date for version
Helps avoid needless rebuilds where only the revision changed. Also
better conforms to Nixpkgs' version standards

Signed-off-by: Seth Flynn <getchoo@tuta.io>
2025-03-31 01:28:43 -04:00
Seth Flynn
9b38226f8c
chore(nix): clone git submodules automatically
Signed-off-by: Seth Flynn <getchoo@tuta.io>
2025-03-31 01:28:43 -04:00
Seth Flynn
38ec7def32
chore(nix): add nice welcome message to dev shell
Signed-off-by: Seth Flynn <getchoo@tuta.io>
2025-03-31 01:28:43 -04:00
Seth Flynn
51bbd02a08
Fix typo in NetRequest.cpp (#3561) 2025-03-31 01:12:48 -04:00
Seth Flynn
de923a07d8
refactor(nix): rely more on setup hooks in dev shell
Signed-off-by: Seth Flynn <getchoo@tuta.io>
2025-03-30 19:25:48 -04:00
Seth Flynn
2d4bc09cb9
build(nix): properly wrap development shell
Allows actually running the executables built in the development shell

Signed-off-by: Seth Flynn <getchoo@tuta.io>
2025-03-30 19:25:48 -04:00
Seth Flynn
58579539d0
fix(nix): only create compile_commands.json if it doesn't exist
Signed-off-by: Seth Flynn <getchoo@tuta.io>
2025-03-30 19:25:48 -04:00
Seth Flynn
32b49ecb84
refactor(nix): cleanup flake
Signed-off-by: Seth Flynn <getchoo@tuta.io>
2025-03-30 19:25:48 -04:00
Seth Flynn
c367f48ec9
refactor(nix): pin flake-compat in default.nix
Avoids polluting downstream flake.locks

Signed-off-by: Seth Flynn <getchoo@tuta.io>
2025-03-30 19:25:47 -04:00
Seth Flynn
99852c972c
Reapply "refactor(nix): nix-filter -> lib.fileset"
After extensive (5 minutes) of testing, it seems we don't actually come
across any Nix bugs with lib.fileset! (aside from those inherit to
it...but 🤷)

This reverts commit a49a58bc4571f87f42f45bb9eeb1a957d5d12331.

Signed-off-by: Seth Flynn <getchoo@tuta.io>
2025-03-30 19:25:47 -04:00
Yihe Li
da007d6212
Use CustomMessageBox::selectable
Signed-off-by: Yihe Li <winmikedows@hotmail.com>
2025-03-31 07:14:09 +08:00
Alexandru Ionut Tripon
0709479110
chore(nix): update lockfile (#3557) 2025-03-30 10:53:02 +03:00
github-actions[bot]
0487ab3754 chore(nix): update lockfile
Flake lock file updates:

• Updated input 'nixpkgs':
    'github:NixOS/nixpkgs/a84ebe20c6bc2ecbcfb000a50776219f48d134cc?narHash=sha256-mNqIplmEohk5jRkqYqG19GA8MbQ/D4gQSK0Mu4LvfRQ%3D' (2025-03-19)
  → 'github:NixOS/nixpkgs/5e5402ecbcb27af32284d4a62553c019a3a49ea6?narHash=sha256-gWd4urRoLRe8GLVC/3rYRae1h%2BxfQzt09xOfb0PaHSk%3D' (2025-03-27)
2025-03-30 00:27:40 +00:00
Alexandru Ionut Tripon
6b93e7aa62
fix themes leak (#3555) 2025-03-30 01:54:33 +02:00
Trial97
5b12d3cfff
fix themes leak
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2025-03-30 00:46:59 +02:00
LAHarbottle
66c6399ade
Fix typo in NetRequest.cpp
Signed-off-by: LAHarbottle <87842870+LAHarbottle@users.noreply.github.com>
2025-03-29 17:17:57 +00:00
Yihe Li
02ca6bea8c
Sync group after updating instance
Signed-off-by: Yihe Li <winmikedows@hotmail.com>
2025-03-29 14:11:09 +08:00
Yihe Li
694959ef7f
Remove names from header comments
Signed-off-by: Yihe Li <winmikedows@hotmail.com>
2025-03-27 20:25:30 +08:00
Yihe Li
a2e44c0ef7
Use custom signals to record previous name
Signed-off-by: Yihe Li <winmikedows@hotmail.com>
2025-03-27 17:13:52 +08:00
Yihe Li
11a0dbf810
Make deleting a verb
Signed-off-by: Yihe Li <winmikedows@hotmail.com>
2025-03-27 16:11:54 +08:00
Yihe Li
45368fbf2f
Get rid of unused includes
Signed-off-by: Yihe Li <winmikedows@hotmail.com>
2025-03-27 08:36:07 +08:00
Yihe Li
a7af120cf0
Fix interaction with invalid chars
Signed-off-by: Yihe Li <winmikedows@hotmail.com>
2025-03-27 07:22:05 +08:00
Yihe Li
294448a01e
Filter out invalid chars
Signed-off-by: Yihe Li <winmikedows@hotmail.com>
2025-03-27 06:54:10 +08:00
Yihe Li
8fea37b8b7
Only call on interactive uses
Signed-off-by: Yihe Li <winmikedows@hotmail.com>
2025-03-27 06:53:57 +08:00
Yihe Li
ea44c2465c
Add link instance detection
Signed-off-by: Yihe Li <winmikedows@hotmail.com>
2025-03-27 05:48:05 +08:00
Yihe Li
7b511f4c67
Refactor into InstanceDirUpdate.h
Signed-off-by: Yihe Li <winmikedows@hotmail.com>
2025-03-27 05:47:29 +08:00
Yihe Li
b550a6c5c4
Revert the radio button changes
Signed-off-by: Yihe Li <winmikedows@hotmail.com>
2025-03-27 05:20:58 +08:00
Yihe Li
7ea5b6173c
Refactor updateInstanceRoot() to BaseInstance
Signed-off-by: Yihe Li <winmikedows@hotmail.com>
2025-03-27 04:51:13 +08:00
Yihe Li
abac3db125
Make remember checkbox off by default
Signed-off-by: Yihe Li <winmikedows@hotmail.com>
2025-03-27 04:11:29 +08:00
Yihe Li
4b20e3bc39
Implement instance renaming
Signed-off-by: Yihe Li <winmikedows@hotmail.com>
2025-03-27 03:26:13 +08:00
Yihe Li
0da645594f
Adjust instance view sorting mode to QComboBox and add renaming behavior
Signed-off-by: Yihe Li <winmikedows@hotmail.com>
2025-03-27 01:20:07 +08:00
Alexandru Ionut Tripon
1c0c247631
chore:fixed some codeql warnings (#1679) 2025-03-26 08:05:57 +02:00
Rachel Powers
064383b8fa
Pin AppImage tooling in CI, drop libfuse2 (#3543) 2025-03-24 16:09:51 -07:00
Seth Flynn
671aad88f5
ci: don't install libfuse2
Signed-off-by: Seth Flynn <getchoo@tuta.io>
2025-03-24 18:17:39 -04:00
Seth Flynn
5d5155bb22
ci: pin appimage tooling
Signed-off-by: Seth Flynn <getchoo@tuta.io>
2025-03-24 18:17:39 -04:00
Seth Flynn
6ef59fe984
ci: use bundled linuxdeploy appimage plugin
Signed-off-by: Seth Flynn <getchoo@tuta.io>
2025-03-24 18:17:39 -04:00
Alexandru Ionut Tripon
ad8e0a9f7f
chore(deps): update actions/cache action to v4.2.3 (#3517) 2025-03-24 22:27:02 +02:00
Trial97
f7fd6f566f
chore:fixed some codeql warnings
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2025-03-24 22:25:35 +02:00
TheKodeToad
9a57fddaaf
Refactor ResourcePack (#2616) 2025-03-24 20:12:41 +00:00
Alexandru Ionut Tripon
e27f602b7c
chore(nix): update lockfile (#3525) 2025-03-24 18:59:26 +02:00
Alexandru Ionut Tripon
7d0e3fb792
Fix crash with low disk space (#3528) 2025-03-24 18:59:09 +02:00
Alexandru Ionut Tripon
aa4c0a4dcc
fix account help link (#3529) 2025-03-24 18:58:36 +02:00
Alexandru Ionut Tripon
80b4a4427c
Use correct colours for all system themes (#3530) 2025-03-24 18:58:27 +02:00
Seth Flynn
9fe78fa86a
Improve clangd support (in Nix development shell) (#3526) 2025-03-23 17:15:23 -04:00
TheKodeToad
513959750f
Try best to avoid regression
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2025-03-23 14:29:58 +00:00
TheKodeToad
f08478c7ec
Use correct colours for all system themes
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2025-03-23 14:17:43 +00:00
Trial97
a4472406b9
fix account help link
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2025-03-23 14:02:09 +02:00
Trial97
9ce5587f60
fix crash on accessing reseted output
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2025-03-23 08:52:30 +02:00
Trial97
269938dfd8
rename variable
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2025-03-23 08:52:08 +02:00
Seth Flynn
e3f93295f0
build(nix): add clangd to dev shell
Signed-off-by: Seth Flynn <getchoo@tuta.io>
2025-03-22 22:36:16 -04:00
Seth Flynn
d6103c2a06
build(nix): copy compile_commands.json when entering dev shell
Signed-off-by: Seth Flynn <getchoo@tuta.io>
2025-03-22 22:36:11 -04:00
Seth Flynn
8a21b07915
build: export compile commands for debug builds
Signed-off-by: Seth Flynn <getchoo@tuta.io>
2025-03-22 22:16:18 -04:00
Seth Flynn
9fa397a299
chore(gitignore): add compile_commands.json
Signed-off-by: Seth Flynn <getchoo@tuta.io>
2025-03-22 22:15:36 -04:00
github-actions[bot]
9ee357dcf1 chore(nix): update lockfile
Flake lock file updates:

• Updated input 'nixpkgs':
    'github:NixOS/nixpkgs/6607cf789e541e7873d40d3a8f7815ea92204f32?narHash=sha256-cPfs8qMccim2RBgtKGF%2Bx9IBCduRvd/N5F4nYpU0TVE%3D' (2025-03-13)
  → 'github:NixOS/nixpkgs/a84ebe20c6bc2ecbcfb000a50776219f48d134cc?narHash=sha256-mNqIplmEohk5jRkqYqG19GA8MbQ/D4gQSK0Mu4LvfRQ%3D' (2025-03-19)
2025-03-23 00:27:03 +00:00
Rachel Powers
815306f1d0
Use group redirections for multiple outputs, prevent glob expansion of PR_NUMBER
Co-authored-by: Seth Flynn <getchoo@tuta.io>
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2025-03-21 12:16:44 -07:00
TheKodeToad
216034c283
refactor FlameCheckUpdate to remove qEventLoop (#3046) 2025-03-20 09:34:26 +00:00
Rachel Powers
436896d365
ci(blocked-pr): use gh issue comment --create-if-none --edit-last with app token, not composit action
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2025-03-19 15:46:04 -07:00
Rachel Powers
187728c1f2
ci(blocked-pr): use app token
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2025-03-19 15:19:13 -07:00
Alexandru Ionut Tripon
71e0c62fee
fix no cape select (#3511) 2025-03-19 22:56:37 +02:00
renovate[bot]
4c2182e086
chore(deps): update actions/cache action to v4.2.3 2025-03-19 18:59:33 +00:00
TheKodeToad
947ca67952
Fix windows 9x and possibly other styles
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2025-03-19 13:32:14 +00:00
TheKodeToad
a108b5e9eb
Correctly set objectName for HintOverrideProxyStyle
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2025-03-19 12:35:24 +00:00
TheKodeToad
e89f96e9e9
Hack for broken windowsvista
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2025-03-19 11:48:31 +00:00
TheKodeToad
5832fb8b95
Implement middle click
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2025-03-19 11:09:25 +00:00
TheKodeToad
9f768f76bb
Translate installed indicator
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2025-03-19 11:00:51 +00:00
TheKodeToad
6dc16c48a2
Append [installed] to installed mods
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2025-03-19 10:56:07 +00:00
TheKodeToad
6c44a3f6df
onToggle -> onResourceToggle
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2025-03-19 10:46:32 +00:00
TheKodeToad
0f3ac57fdd
Trigger onToggle instead of onResourceSelected when pressing enter
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2025-03-19 10:42:38 +00:00
TheKodeToad
7532172233
Clear enableQueue on model reset
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2025-03-19 10:31:55 +00:00
hanlie
6bda537633 Improvements to modlist export
Added .replace("{mod_id}", modID)

Signed-off-by: hanlie <48323966+HanlieChina@users.noreply.github.com>
2025-03-19 12:35:22 +08:00
TheKodeToad
a5c62e657a
Snek case
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2025-03-19 01:43:43 +00:00
TheKodeToad
c6066fe6ec
Add warning dialog if there are no versions available
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2025-03-19 01:41:56 +00:00
TheKodeToad
900579eea6
Handle checkbox toggle
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2025-03-19 01:17:25 +00:00
TheKodeToad
8577f58fe3
Remove UserDataTypes::SELECTED
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2025-03-18 20:44:49 +00:00
TheKodeToad
5f70335a07
Render checkbox in project items
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2025-03-18 19:52:59 +00:00
Trial97
d5d83bf55c
fix no cape select
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2025-03-18 16:48:18 +02:00
TheKodeToad
a501441e6e
Paint project item backgrounds with native style
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2025-03-17 21:34:03 +00:00
Alexandru Ionut Tripon
d0b9073f60
Show online players on servers screen (#3112) 2025-03-16 08:30:12 +02:00
Alexandru Ionut Tripon
52a53a3b75
Make account checks more on-par with MultiMC (#3466) 2025-03-16 08:29:31 +02:00
Alexandru Ionut Tripon
41e2a486e0
chore(nix): update lockfile (#3484) 2025-03-16 08:28:22 +02:00
Alexandru Ionut Tripon
da508da1ab
chore(deps): update cachix/install-nix-action digest to 02a151a (#3507) 2025-03-16 08:28:12 +02:00
github-actions[bot]
6cf96d8fe7 chore(nix): update lockfile
Flake lock file updates:

• Updated input 'nixpkgs':
    'github:NixOS/nixpkgs/6313551cd05425cd5b3e63fe47dbc324eabb15e4?narHash=sha256-D%2BR%2BkFxy1KsheiIzkkx/6L63wEHBYX21OIwlFV8JvDs%3D' (2025-02-27)
  → 'github:NixOS/nixpkgs/6607cf789e541e7873d40d3a8f7815ea92204f32?narHash=sha256-cPfs8qMccim2RBgtKGF%2Bx9IBCduRvd/N5F4nYpU0TVE%3D' (2025-03-13)
2025-03-16 00:27:01 +00:00
renovate[bot]
a469f6b114
chore(deps): update cachix/install-nix-action digest to 02a151a 2025-03-15 21:14:57 +00:00
Rachel Powers
e28dd30d87
ci(blocked_pr): merge env setup for dispatch and pull_request events
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2025-03-14 19:26:27 -07:00
Rachel Powers
72aee5c9f6
ci(blocked-pr): go back to single labels use gh cli actions directly insead of api where possible
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2025-03-14 16:07:14 -07:00
Alexandru Ionut Tripon
1a1bc14a73
Fix crash with invalid quilt mod info (#3496) 2025-03-15 00:00:46 +02:00
Alexandru Ionut Tripon
577cae3e00
chore(deps): update cachix/cachix-action action to v16 (#3493) 2025-03-15 00:00:30 +02:00
Alexandru Ionut Tripon
998de93ee5
chore(deps): update cachix/install-nix-action action to v31 (#3492) 2025-03-15 00:00:19 +02:00
Rachel Powers
e8e81a7627
use basename and dirname to split owner/repo
Co-authored-by: Seth Flynn <getchoo@tuta.io>
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2025-03-14 14:56:46 -07:00
Rachel Powers
b42b453f76
ci(blocking-lables): cleanup lables with a pr closes
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2025-03-14 12:58:42 -07:00
Rachel Powers
da3f378d5d
ci(label-actions): actions can't directly access secrets
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2025-03-14 11:04:44 -07:00
Rachel Powers
7cbdb80f6b
ci(label-actions): composit actions to add and delete labels in bulk
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2025-03-14 10:26:19 -07:00
Rachel Powers
0818e7068a
ci(blocked_pres): ensure merge workflow has actions permission
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2025-03-12 21:01:58 -07:00
Rachel Powers
c75ae4170f
ci(blocked_prs): fix merge workflow
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2025-03-12 20:44:07 -07:00
Rachel Powers
c2b7b4c82a
ci(blocked_prs): fix multiline comment body in comment action
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2025-03-12 20:44:07 -07:00
Rachel Powers
05356eff69
ci(blocking_prs): fix generated comment
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2025-03-12 20:44:06 -07:00
Rachel Powers
0474b03626
ci(blocked_pr): fix comment action
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2025-03-12 20:44:06 -07:00
Rachel Powers
79283fd744
ci(blocked_prs): checkout default branch for action access
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2025-03-12 20:44:06 -07:00
Rachel Powers
e00d93135f
ci(blocked_prs): fix blocking_data refrences, add synchronize and
reopend events

Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2025-03-12 20:44:06 -07:00
Rachel Powers
6fd70ad095
ci(blocked_prs): correct condition to use JOB_DATA from env
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2025-03-12 20:44:05 -07:00
Rachel Powers
1c6ab1f054
ci(blocked_prs): unnest array of blocking prs
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2025-03-12 20:44:05 -07:00
Rachel Powers
14f042540c
ci(blocking_pr): pass json expressions as env not direct.
use internal compost comment action

Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2025-03-12 20:44:05 -07:00
Rachel Powers
eb11cde0f4
ci(blocked_prs): use compact jq output when outputting to ENV or step
ouput

Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2025-03-12 20:44:05 -07:00
Rachel Powers
0bbf529afb
ci(blocked_prs): quote json in env file
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2025-03-12 20:44:04 -07:00
Rachel Powers
a6a172a136
ci: ensure block pr scan always returns valid json
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2025-03-12 20:44:04 -07:00
Rachel Powers
a2907dcaa3
ci: fix blocked PR workflow to preserve JSON in ENV
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2025-03-12 20:44:04 -07:00
Rachel Powers
cbd1fc6f43
ci: fix repo URL in blocked pr workflow
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2025-03-12 20:44:04 -07:00
Rachel Powers
cfc3c76779
ci: fix labels detected as sequence
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2025-03-12 20:44:03 -07:00
Rachel Powers
be1ce8dd9d
ci: add workflow to trigger refresh of dependants when a blocking pr is merged
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2025-03-12 20:44:03 -07:00
Rachel Powers
a65ced1598
ci: add a workflow to detect and check dependencies for blocked pull requests
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2025-03-12 20:44:03 -07:00
Alexandru Ionut Tripon
88bdb6541e
Update launcher/minecraft/mod/tasks/LocalModParseTask.cpp
Signed-off-by: Alexandru Ionut Tripon <alexandru.tripon97@gmail.com>
2025-03-12 00:14:53 +02:00
Trial97
0626e354a0
Fix crash with invalid quilt mod info
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2025-03-12 00:01:45 +02:00
renovate[bot]
de13d55c7c
chore(deps): update cachix/cachix-action action to v16 2025-03-10 21:53:14 +00:00
renovate[bot]
d41c54b6b2
chore(deps): update cachix/install-nix-action action to v31 2025-03-10 18:24:28 +00:00
TheKodeToad
fde2f4afe9
Fix mistakes
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2025-03-10 12:44:44 +00:00
Alexandru Ionut Tripon
1e1730e5a9
fix mod load with empty gameversions (#3455) 2025-03-10 14:40:35 +02:00
Alexandru Ionut Tripon
bb9e19eec6
Qt app ID fix (#3480) 2025-03-09 15:03:38 +02:00
Echo J
14ab4055ff Reduce app ID hardcoding
And rename the relevant build variable to make more sense

Signed-off-by: Echo J <tcg96nougat@gmail.com>
2025-03-09 14:16:48 +02:00
Echo J
ffdf1f746e Remove .desktop suffix from application ID
Signed-off-by: Echo J <tcg96nougat@gmail.com>
2025-03-09 14:15:45 +02:00
Alexandru Ionut Tripon
91ef9f4998
fix duplicate optional mods dialog appearing when updating a modpack (#3475) 2025-03-09 14:05:09 +02:00
Alexandru Ionut Tripon
0716e49065
fix beginResetModel called before endResetModel (#3470) 2025-03-09 14:04:58 +02:00
Alexandru Ionut Tripon
43385f22be
fix null mainwindow in case of login on setup (#3464) 2025-03-09 14:04:48 +02:00
Trial97
59a816c696
fix duplicate optional mods dialog appearing when updating a modpack
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>

tmp
2025-03-06 10:19:38 +02:00
Trial97
c441ae05df
fix beginResetModel called before endResetModel
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2025-03-05 13:06:29 +02:00
Sticks
d4e1851e67
fix: remove qWarning for unknown state
Co-authored-by: TheKodeToad <TheKodeToad@proton.me>
Signed-off-by: Sticks <sticks@teamhydra.dev>
2025-03-04 22:20:40 -06:00
Trial97
7db717ee7c
fix null mainwindow in case of login on setup
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2025-03-03 23:55:44 +02:00
Trial97
162bbcfe19
rename some variables
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2025-03-03 23:55:43 +02:00
TheKodeToad
cb77cc1219
Use refresh instead of requestRefresh on LaunchController::login
There should be no reason to queue it and it could cause problems with the launcher's rate limiting

Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2025-03-03 20:24:07 +00:00
Trial97
4dd026d1ae
QList to QVector
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2025-03-03 08:31:39 +02:00
Trial97
8e33608ddb
refactor FlameCheckUpdate to remove qEventLoop
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2025-03-03 08:31:39 +02:00
Trial97
22e0659a5f
removed unused BaseInstance argument from some API functions
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2025-03-03 08:31:39 +02:00
Trial97
3da94eeea2
removed some unused QNetworkAccessManager references
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2025-03-03 08:31:39 +02:00
Alexandru Ionut Tripon
f9ab75868a
remove some QEventLoops (#3044) 2025-03-03 08:27:06 +02:00
Alexandru Ionut Tripon
5d268a3ded
chore: Update year range (#3461) 2025-03-03 08:26:56 +02:00
txtsd
f99b7e9ebd
chore: Update year range
Signed-off-by: txtsd <code@ihavea.quest>
2025-03-03 10:14:06 +05:30
Trial97
8f8c8394dc
remove some QEventLoops
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2025-03-02 08:36:48 +02:00
Alexandru Ionut Tripon
02b6afe3d5
Default to Fusion based Dark/Bright themes on Windows (#3452) 2025-03-02 08:21:20 +02:00
Alexandru Ionut Tripon
67d385fed2
chore(deps): update actions/cache action to v4.2.2 (#3451) 2025-03-02 08:19:27 +02:00
Alexandru Ionut Tripon
758b6cb756
chore(deps): update korthout/backport-action action to v3.2.0 (#3448) 2025-03-02 08:19:18 +02:00
Alexandru Ionut Tripon
74dd9ff43a
chore(nix): update lockfile (#3439) 2025-03-02 08:19:10 +02:00
Alexandru Ionut Tripon
ecf770d4ae
implement packignore for curseforge/modrinth export (#3295) 2025-03-02 08:19:03 +02:00
Alexandru Ionut Tripon
bf01d42c83
Add skin preview (#3283) 2025-03-02 08:18:51 +02:00
Alexandru Ionut Tripon
74ed1f3b5d
Improve profile setup error messages (#3256) 2025-03-02 08:18:40 +02:00
github-actions[bot]
d75f1e3032 chore(nix): update lockfile
Flake lock file updates:

• Updated input 'nixpkgs':
    'github:NixOS/nixpkgs/2ff53fe64443980e139eaa286017f53f88336dd0?narHash=sha256-%2B/bYK3DbPxMIvSL4zArkMX0LQvS7rzBKXnDXLfKyRVc%3D' (2025-02-13)
  → 'github:NixOS/nixpkgs/6313551cd05425cd5b3e63fe47dbc324eabb15e4?narHash=sha256-D%2BR%2BkFxy1KsheiIzkkx/6L63wEHBYX21OIwlFV8JvDs%3D' (2025-02-27)
2025-03-02 00:26:09 +00:00
Trial97
29b3eb5cc6
fix mod load with empty gameversions
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2025-03-01 22:45:36 +02:00
iTrooz
93286789c5
fix typo
Signed-off-by: iTrooz <hey@itrooz.fr>
2025-03-01 20:12:31 +01:00
Sticks
ea5458ed22
fix: Grammar correction in failed message for update dialogues
Co-authored-by: TheKodeToad <TheKodeToad@proton.me>
Signed-off-by: Sticks <sticks@teamhydra.dev>
2025-02-28 21:06:34 -06:00
sticks
998bc660fa feat: add updater dialogues
Signed-off-by: sticks <tanner@teamhydra.dev>
2025-02-28 15:09:46 -06:00
TheKodeToad
5261b615d7 Default to Fusion based Dark/Bright themes on Windows
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2025-02-28 21:07:58 +00:00
renovate[bot]
8cb999c479
chore(deps): update actions/cache action to v4.2.2 2025-02-27 19:24:06 +00:00
renovate[bot]
3cb44ba105
chore(deps): update korthout/backport-action action to v3.2.0 2025-02-23 22:35:16 +00:00
Alexandru Ionut Tripon
12a4915420
Apply suggestions from code review
Co-authored-by: TheKodeToad <TheKodeToad@proton.me>
Signed-off-by: Alexandru Ionut Tripon <alexandru.tripon97@gmail.com>
2025-02-21 11:32:30 +02:00
Trial97
6a2f5f071c
improve chessboard contrast
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2025-02-21 11:12:27 +02:00
Trial97
47af33ff6f
Merge branch 'develop' of https://github.com/PrismLauncher/PrismLauncher into skin 2025-02-21 08:40:33 +02:00
Trial97
5810032861
Fix icon removal in icon picker
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2025-02-19 09:29:05 +02:00
Trial97
c9471d083b
change java on modpack update
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2025-02-19 09:28:06 +02:00
Seth Flynn
0af021fef2
ci: always run nix workflow on push (#3433) 2025-02-19 02:17:41 -05:00
Alexandru Ionut Tripon
d24066c965
chore(deps): update actions/cache action to v4.2.1 (#3432) 2025-02-19 08:20:04 +02:00
Seth Flynn
46385e671d
ci: always run nix workflow on push
Signed-off-by: Seth Flynn <getchoo@tuta.io>
2025-02-18 22:55:51 -05:00
renovate[bot]
73bb740bbb
chore(deps): update actions/cache action to v4.2.1 2025-02-18 18:14:21 +00:00
Alexandru Ionut Tripon
50ab1b2c40
Recognize riscv64 as a 64-bit platform (#3425) 2025-02-17 20:33:17 +02:00
Alexandru Ionut Tripon
d472b966dc
chore(nix): update lockfile (#3401) 2025-02-17 18:04:45 +02:00
Alexandru Ionut Tripon
beee93e199
Update hendrikmuhs/ccache-action action to v1.2.17 (#3388) 2025-02-17 18:04:33 +02:00
thonkdifferent
8f1750df51
Recognize riscv64 as a 64-bit platform
Currently PrismLauncher complains about the installed JDK being a 32-bit version, despite it being compiled for 64-bit RISC-V `riscv64`. 

This PR fixes this issue.

Signed-off-by: thonkdifferent <41342923+thonkdifferent@users.noreply.github.com>
2025-02-16 19:30:31 +02:00
github-actions[bot]
bdf87fa02f chore(nix): update lockfile
Flake lock file updates:

• Updated input 'nixpkgs':
    'github:NixOS/nixpkgs/3a228057f5b619feb3186e986dbe76278d707b6e?narHash=sha256-xvTo0Aw0%2Bveek7hvEVLzErmJyQkEcRk6PSR4zsRQFEc%3D' (2025-02-01)
  → 'github:NixOS/nixpkgs/2ff53fe64443980e139eaa286017f53f88336dd0?narHash=sha256-%2B/bYK3DbPxMIvSL4zArkMX0LQvS7rzBKXnDXLfKyRVc%3D' (2025-02-13)
2025-02-16 00:25:49 +00:00
Rachel Powers
3295b0717a
add libMangoHud_shim.so to mangohub preloadlist (#3413) 2025-02-13 14:41:01 -07:00
Rachel Powers
7b97863685
make sure if user changes java path also disable java management (#3414) 2025-02-13 14:40:40 -07:00
TheKodeToad
3840d8a37a
Always check Microsoft account for offline account
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2025-02-13 19:12:50 +00:00
Alexandru Ionut Tripon
3e4fc2ff3b
Increase the stale operations (#3393) 2025-02-13 13:44:01 +02:00
Alexandru Ionut Tripon
d22a20ffa6
Update .github/workflows/stale.yml
Co-authored-by: TheKodeToad <TheKodeToad@proton.me>
Signed-off-by: Alexandru Ionut Tripon <alexandru.tripon97@gmail.com>
2025-02-13 08:14:20 +02:00
TheKodeToad
de86e63611
Update .github/workflows/stale.yml
Co-authored-by: Alexandru Ionut Tripon <alexandru.tripon97@gmail.com>
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2025-02-13 00:05:14 +00:00
TheKodeToad
e41a60e57e
remove some unused files (#3412) 2025-02-13 00:04:45 +00:00
iTrooz
34233a93a2
MinecraftTarget::parse() to parse IP
Signed-off-by: iTrooz <hey@itrooz.fr>
2025-02-13 00:55:35 +01:00
Trial97
174cddcf42
make sure if user changes java path also disable java management
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2025-02-12 20:40:09 +02:00
Trial97
9e954548dd
add libMangoHud_shim.so to mangohub preloadlist
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2025-02-12 20:21:45 +02:00
Trial97
14b653e08d
remove some unused files
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2025-02-12 20:16:00 +02:00
TheKodeToad
79180db663
Fix some undefined behaviour (#3407) 2025-02-11 19:04:56 +00:00
Alexandru Ionut Tripon
22b59e760c
Update launcher/ui/widgets/CheckComboBox.cpp
Signed-off-by: Alexandru Ionut Tripon <alexandru.tripon97@gmail.com>
2025-02-11 21:03:04 +02:00
Alexandru Ionut Tripon
1d1a4f1b30
Apply suggestions from code review
Co-authored-by: TheKodeToad <TheKodeToad@proton.me>
Signed-off-by: Alexandru Ionut Tripon <alexandru.tripon97@gmail.com>
2025-02-11 21:02:27 +02:00
Trial97
bf1084d7fa
Fix some undefined behaviour
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2025-02-11 10:59:10 +02:00
Trial97
ef825a7bc5
update stale action
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2025-02-06 09:58:41 +02:00
Alexandru Ionut Tripon
8d143c7b95
Fixed when game crashes, it doesn't log any time played (#3392) 2025-02-06 09:35:23 +02:00
Riley Richard
9ea33e0651 DCO Remediation Commit for Riley Richard <bubbalou112@gmail.com>
I, Riley Richard <bubbalou112@gmail.com>, hereby add my Signed-off-by to this commit: cb83f8e52db1046173a8def2f216cfcf1518b91f

Signed-off-by: Riley Richard <bubbalou112@gmail.com>
2025-02-05 18:10:31 -05:00
Trial97
f1209c1279
Increase the stale operations
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2025-02-05 23:43:38 +02:00
Riley Richard
17e95c0d07 forgot to sign
Signed-off-by: Riley Richard <bubbalou112@gmail.com>
2025-02-05 16:33:15 -05:00
Riley Richard
cb83f8e52d fixed thing 2025-02-05 16:13:22 -05:00
Alexandru Ionut Tripon
7d202e348d
Use the same UI for instance and global settings (#3341) 2025-02-05 23:04:54 +02:00
Alexandru Ionut Tripon
364b5be856
Add stale workflow (#3389) 2025-02-05 23:04:38 +02:00
TheKodeToad
e1896d5b6b
Update launcher/ui/pages/global/MinecraftPage.h
Co-authored-by: Alexandru Ionut Tripon <alexandru.tripon97@gmail.com>
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2025-02-05 13:45:49 +00:00
TheKodeToad
6e3dd04a1f
Update launcher/ui/pages/global/MinecraftPage.h
Co-authored-by: Alexandru Ionut Tripon <alexandru.tripon97@gmail.com>
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2025-02-05 12:09:32 +00:00
TheKodeToad
f7a401ab22
Update launcher/ui/pages/instance/InstanceSettingsPage.h
Co-authored-by: Alexandru Ionut Tripon <alexandru.tripon97@gmail.com>
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2025-02-05 12:09:26 +00:00
TheKodeToad
9ed6801b15
Update launcher/ui/pages/global/JavaPage.h
Co-authored-by: Alexandru Ionut Tripon <alexandru.tripon97@gmail.com>
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2025-02-05 12:09:12 +00:00
TheKodeToad
06b50dfd33
Fix more header mistakes
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2025-02-05 11:11:45 +00:00
TheKodeToad
5a76d9b7e1
Make requested changes
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2025-02-05 10:58:06 +00:00
Alexandru Ionut Tripon
34438824c1
Update .github/workflows/stale.yml
Co-authored-by: Seth Flynn <getchoo@tuta.io>
Signed-off-by: Alexandru Ionut Tripon <alexandru.tripon97@gmail.com>
2025-02-04 23:15:18 +02:00
Alexandru Ionut Tripon
ac598740b3
Update .github/workflows/stale.yml
Signed-off-by: Alexandru Ionut Tripon <alexandru.tripon97@gmail.com>
2025-02-04 22:08:46 +02:00
Alexandru Ionut Tripon
85c2710e33
Apply suggestions from code review
Co-authored-by: Seth Flynn <getchoo@tuta.io>
Signed-off-by: Alexandru Ionut Tripon <alexandru.tripon97@gmail.com>
2025-02-04 22:08:16 +02:00
Alexandru Ionut Tripon
afe6d4836d
Update .github/workflows/stale.yml
Signed-off-by: Alexandru Ionut Tripon <alexandru.tripon97@gmail.com>
2025-02-04 17:41:36 +02:00
Trial97
9c26ba5932
add stale workflow
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2025-02-04 16:13:55 +02:00
renovate[bot]
2a987b5a4a
chore(deps): update hendrikmuhs/ccache-action action to v1.2.17 2025-02-03 22:11:56 +00:00
Alexandru Ionut Tripon
1a375dc243
Merge pull request #3382 from PrismLauncher/update_flake_lock_action
chore(nix): update lockfile
2025-02-03 00:28:59 +02:00
Alexandru Ionut Tripon
ab3792b080
Merge pull request #3381 from razzeee/patch-1
Add PackageManager category
2025-02-03 00:28:42 +02:00
Seth Flynn
f9dcc31843
Merge pull request #3374 from getchoo-contrib/ci/fix-nix-out-paths
Fix Nix workflow
2025-02-02 17:18:03 -05:00
Seth Flynn
989e6c6cb6
ci: directly print nix out paths to step summary
Signed-off-by: Seth Flynn <getchoo@tuta.io>
2025-02-01 22:55:39 -05:00
Seth Flynn
138684a84f
Revert "ci: add nix out paths to job summary"
This reverts commit 588e0d6305e673fc4e5eceebfe2692d30b8e876a.

Signed-off-by: Seth Flynn <getchoo@tuta.io>
2025-02-01 22:54:26 -05:00
github-actions[bot]
faf7e6b06e chore(nix): update lockfile
Flake lock file updates:

• Updated input 'nixpkgs':
    'github:NixOS/nixpkgs/825479c345a7f806485b7f00dbe3abb50641b083?narHash=sha256-nU6AezEX4EuahTO1YopzueAXfjFfmCHylYEFCagduHU%3D' (2025-01-24)
  → 'github:NixOS/nixpkgs/3a228057f5b619feb3186e986dbe76278d707b6e?narHash=sha256-xvTo0Aw0%2Bveek7hvEVLzErmJyQkEcRk6PSR4zsRQFEc%3D' (2025-02-01)
2025-02-02 00:24:39 +00:00
Kolja
f1671e3ded
Add PackageManager category
Signed-off-by: Kolja <razzeee@gmail.com>
2025-02-01 20:25:01 +01:00
Alexandru Ionut Tripon
6404d81ada
Merge pull request #3373 from Trial97/fix_crash2
Show warning when adding new resources with no instances
2025-01-31 23:03:55 +02:00
Alexandru Ionut Tripon
d6eb96df5c
Merge pull request #3260 from Trial97/fix_modrinth_shapshot
Map Minecraft snapshots to Modrinth
2025-01-31 23:02:55 +02:00
Trial97
c5efe081b4
fix add resource with no instance
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2025-01-31 22:03:57 +02:00
Seth Flynn
a639bc019e
Merge pull request #3368 from getchoo-contrib/ci/print-nix-out-paths 2025-01-31 07:00:37 -05:00
Seth Flynn
588e0d6305
ci: add nix out paths to job summary
Signed-off-by: Seth Flynn <getchoo@tuta.io>
2025-01-30 13:34:34 -05:00
Sefa Eyeoglu
d7eddedf41
Merge pull request #3359 from PrismLauncher/ci/flakehub 2025-01-30 16:06:58 +01:00
Alexandru Ionut Tripon
6ae9fa4df4
Merge pull request #3314 from Trial97/update_modules
update submodules
2025-01-29 23:35:08 +02:00
Seth Flynn
86cc6d3c5e
feat: publish on flakehub
Signed-off-by: Seth Flynn <getchoo@tuta.io>
2025-01-29 16:34:31 -05:00
Seth Flynn
61d7f08883
ci: use generic workflow for publishing
Signed-off-by: Seth Flynn <getchoo@tuta.io>
2025-01-29 16:34:27 -05:00
Seth Flynn
0deb5e20ae
Merge pull request #3362 from getchoo-contrib/ci/flakehub-cache 2025-01-29 16:34:02 -05:00
Alexandru Ionut Tripon
fcb3dd5e9d
Merge pull request #3346 from PrismLauncher/update_flake_lock_action
chore(nix): update lockfile
2025-01-29 23:33:01 +02:00
Seth Flynn
169f5728b1
ci: run nix workflow on pull_request_target
Signed-off-by: Seth Flynn <getchoo@tuta.io>
2025-01-29 16:22:44 -05:00
Seth Flynn
8816be1668
ci: use flakehub cache
Signed-off-by: Seth Flynn <getchoo@tuta.io>
2025-01-29 16:17:01 -05:00
Alexandru Ionut Tripon
bd752c025c
Merge pull request #3360 from getchoo-contrib/ci/split
Split Flatpak and Nix CI jobs from main build workflow
2025-01-29 22:51:07 +02:00
Seth Flynn
49d734f314
ci: separate flatpak job
Signed-off-by: Seth Flynn <getchoo@tuta.io>
2025-01-29 08:32:49 -05:00
Seth Flynn
417688089d
ci: separate nix job
Signed-off-by: Seth Flynn <getchoo@tuta.io>
2025-01-29 08:31:45 -05:00
Seth Flynn
de21b77ae1
Merge pull request #3334 from PrismLauncher/renovate/determinatesystems-magic-nix-cache-action-9.x
chore(deps): update determinatesystems/magic-nix-cache-action action to v9
2025-01-29 07:44:06 -05:00
TheKodeToad
68bf409a98
Fix formatting issues
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2025-01-27 19:14:57 +00:00
TheKodeToad
5d179671bf
Fix non-Linux build
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2025-01-27 18:55:24 +00:00
TheKodeToad
dc6f536843
Fix Qt 5 compilation
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2025-01-27 18:04:41 +00:00
TheKodeToad
cc504f4a6c
Merge remote-tracking branch 'upstream/develop' into unify-mc-settings
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2025-01-27 17:02:50 +00:00
TheKodeToad
a92c68adbd
Remove duplicate console section
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2025-01-27 16:54:45 +00:00
TheKodeToad
7aaa9fa93c
Finish off MinecraftSettingsWidget implementation
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2025-01-27 16:46:26 +00:00
TheKodeToad
81769b9047
Use MinecraftInstancePtr instance of InstancePtr
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2025-01-27 14:34:07 +00:00
TheKodeToad
147b315c14
Update thresholds when min. memory value is changed too
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2025-01-27 14:15:07 +00:00
TheKodeToad
9d0918a064
Remove outdated JavaWizardWidget comment
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2025-01-27 13:19:10 +00:00
TheKodeToad
98ab686348
Merge remote-tracking branch 'upstream/develop' into unify-mc-settings
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2025-01-27 13:18:19 +00:00
TheKodeToad
39ae2fbd4a
Fix tab inconsistencies
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2025-01-26 22:44:43 +00:00
TheKodeToad
36a35d7925
Fix tab order
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2025-01-26 22:36:48 +00:00
TheKodeToad
1b4b36df33
Unify Java page
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2025-01-26 22:25:26 +00:00
github-actions[bot]
3d9e073721 chore(nix): update lockfile
Flake lock file updates:

• Updated input 'nixpkgs':
    'github:NixOS/nixpkgs/5df43628fdf08d642be8ba5b3625a6c70731c19c?narHash=sha256-Tbk1MZbtV2s5aG%2BiM99U8FqwxU/YNArMcWAv6clcsBc%3D' (2025-01-16)
  → 'github:NixOS/nixpkgs/825479c345a7f806485b7f00dbe3abb50641b083?narHash=sha256-nU6AezEX4EuahTO1YopzueAXfjFfmCHylYEFCagduHU%3D' (2025-01-24)
2025-01-26 00:23:21 +00:00
iTrooz
bb20848449
use more sensible protocol version
Signed-off-by: iTrooz <hey@itrooz.fr>
2025-01-25 21:01:21 +01:00
iTrooz
0b9d4784d8
Show socket error in McClient
Signed-off-by: iTrooz <hey@itrooz.fr>
2025-01-25 20:26:52 +01:00
iTrooz
b06c4341d8
update documentation
Signed-off-by: iTrooz <hey@itrooz.fr>
2025-01-25 20:22:09 +01:00
iTrooz
7c82cd82d7
use m_responseReadState to avoid calling parseResponse() (as a failsafe for malicious/bad server responses)
Signed-off-by: iTrooz <hey@itrooz.fr>
2025-01-25 20:19:19 +01:00
iTrooz
439c565961
forward McResolver error as Task error
Signed-off-by: iTrooz <hey@itrooz.fr>
2025-01-25 20:14:15 +01:00
iTrooz
cf2b413f29
forward McClient error as Task error
Signed-off-by: iTrooz <hey@itrooz.fr>
2025-01-25 20:10:31 +01:00
iTrooz
fe8f755b43
remove waitForConnected() and waitForReadyRead() and use signals ineatd
Signed-off-by: iTrooz <hey@itrooz.fr>
2025-01-25 20:08:44 +01:00
iTrooz
43376b1c40
remove unused defines in McClient.h
Signed-off-by: iTrooz <hey@itrooz.fr>
2025-01-25 19:06:52 +01:00
Trial97
255f27d419
virtual constructor
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2025-01-22 16:11:54 +02:00
Trial97
aeeb6f6bb6
fix build final
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2025-01-22 00:16:20 +02:00
Trial97
49d82ab528
fix build
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2025-01-21 23:49:42 +02:00
Alexandru Ionut Tripon
fdb4159f2a
Merge pull request #3332 from eff3ry/modrinth-filter-tweak
Update Modrinth Client/Server Filters to match Modrinth website & launcher.
2025-01-21 23:42:37 +02:00
Alexandru Ionut Tripon
98be91c9d5
Merge pull request #3294 from Trial97/fix_flame_update
Fix updating Curseforge mods with missing mod loader
2025-01-21 23:40:21 +02:00
Trial97
7010b8acb6
fix the freeze with openglwidget
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2025-01-21 23:36:40 +02:00
renovate[bot]
705375c0df
chore(deps): update determinatesystems/magic-nix-cache-action action to v9 2025-01-21 21:35:18 +00:00
Alexandru Ionut Tripon
38d3f14f06
Apply suggestions from code review
Co-authored-by: TheKodeToad <TheKodeToad@proton.me>
Signed-off-by: Alexandru Ionut Tripon <alexandru.tripon97@gmail.com>
2025-01-21 16:45:40 +02:00
TheKodeToad
8d3684c484
Merge pull request #1413 from Trial97/fix_curse_import
feat: updated flame mod resolution
2025-01-21 13:53:00 +00:00
Alexandru Ionut Tripon
0d4eeb9965
Merge pull request #3330 from getchoo-contrib/mingw-cfg
Use better compile flags for MINGW
2025-01-21 15:18:43 +02:00
Jeffery Tolmie
caccaefb39
Change "none" to ""
Co-authored-by: Alexandru Ionut Tripon <alexandru.tripon97@gmail.com>
Signed-off-by: Jeffery Tolmie <jeffery.tolmie@gmail.com>
2025-01-22 02:06:49 +13:00
eff3ry
532fec7748 DCO Remediation Commit
DCO Remediation Commit for eff3ry <jeffery.tolmie@gmail.com>

I, eff3ry <jeffery.tolmie@gmail.com>, hereby add my Signed-off-by to this commit: 2a403b3bfe9f4c79c38c33e80515a232576f6018
I, eff3ry <jeffery.tolmie@gmail.com>, hereby add my Signed-off-by to this commit: 4ba3fd559d2664099524848825adb6f5a60650ab

Signed-off-by: eff3ry <jeffery.tolmie@gmail.com>
2025-01-22 01:48:04 +13:00
eff3ry
4ba3fd559d Update Filter Checks
Updates the filter checks so that options both and none can be differentiated.

Signed-off-by: Jeffery Tolmie Jeffery.tolmie@gmail.com
2025-01-22 01:40:59 +13:00
eff3ry
2a403b3bfe Edit Modrinth search faucets
Edit Modrinth search faucets to alter the client and server filters to be more in-line with the Modrinth website and Launcher, making it easier to find client-side only mods etc.

Signed-off-by: Jeffery Tolmie Jeffery.tolmie@gmail.com
2025-01-22 01:39:28 +13:00
Seth Flynn
f8a504e254
Merge pull request #3299 from Trial97/appimage2
Use Ubuntu 22.04 for Linux builds
2025-01-20 23:43:45 -05:00
Seth Flynn
e66f447ce5
feat: use better compile flags for mingw
Signed-off-by: Seth Flynn <getchoo@tuta.io>
2025-01-20 20:36:48 -05:00
Seth Flynn
67b218b1f3
Merge pull request #2895 from Edgars-Cirulis/qt-6.8
chore: update to qt 6.8.x
2025-01-20 18:53:05 -05:00
Alexandru Ionut Tripon
db766574a4
Update .github/workflows/build.yml
Co-authored-by: Seth Flynn <getchoo@tuta.io>
Signed-off-by: Alexandru Ionut Tripon <alexandru.tripon97@gmail.com>
2025-01-21 01:38:13 +02:00
timoreo
18da01c9a6
Merge pull request #3320 from PrismLauncher/update_flake_lock_action
chore(nix): update lockfile
2025-01-20 09:48:11 +01:00
Alexandru Ionut Tripon
c79ad73311
Merge pull request #3319 from getchoo-contrib/flatpak-arm
Build Flatpaks for ARM
2025-01-19 10:16:41 +02:00
Sefa Eyeoglu
fb3926a85d
Merge pull request #3318 from getchoo-contrib/nix-arm
Build Nix packages for aarch64-linux
2025-01-19 09:08:17 +01:00
github-actions[bot]
8d4f279539 chore(nix): update lockfile
Flake lock file updates:

• Updated input 'nixpkgs':
    'github:NixOS/nixpkgs/bffc22eb12172e6db3c5dde9e3e5628f8e3e7912?narHash=sha256-8YVQ9ZbSfuUk2bUf2KRj60NRraLPKPS0Q4QFTbc%2Bc2c%3D' (2025-01-08)
  → 'github:NixOS/nixpkgs/5df43628fdf08d642be8ba5b3625a6c70731c19c?narHash=sha256-Tbk1MZbtV2s5aG%2BiM99U8FqwxU/YNArMcWAv6clcsBc%3D' (2025-01-16)
2025-01-19 00:24:56 +00:00
Alexandru Ionut Tripon
1b5d3c2bf9
Update .github/workflows/build.yml
Co-authored-by: seth <getchoo@tuta.io>
Signed-off-by: Alexandru Ionut Tripon <alexandru.tripon97@gmail.com>
2025-01-19 02:03:21 +02:00
Trial97
be3eca8c97
remove specific step for qt6
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2025-01-19 01:05:06 +02:00
seth
66f0397087
ci: build flatpaks for arm
Signed-off-by: seth <getchoo@tuta.io>
2025-01-18 17:16:02 -05:00
seth
8e8538b506
ci: build nix packages for aarch64-linux
Signed-off-by: seth <getchoo@tuta.io>
2025-01-18 16:55:38 -05:00
Trial97
dc00c47f2e
update submodules
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2025-01-18 13:27:18 +02:00
Trial97
7d3238d234
rename variables
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2025-01-17 21:09:44 +02:00
Alexandru Ionut Tripon
f17599c8b8
Merge pull request #1689 from Trial97/progrss_bar_interaction
Added mouse interactions for labels in ProgressDialog
2025-01-17 20:59:52 +02:00
Trial97
8e5a7c6e33
ensure that the snapshot mapping is on all apis
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2025-01-17 10:35:13 +02:00
Trial97
1d8bf1d5a7
map modrinth snapshots
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2025-01-17 09:19:39 +02:00
Alexandru Ionut Tripon
0a71b19509
Apply suggestions from code review
Co-authored-by: seth <getchoo@tuta.io>
Signed-off-by: Alexandru Ionut Tripon <alexandru.tripon97@gmail.com>
2025-01-17 08:53:10 +02:00
Alexandru Ionut Tripon
c2f4389e5f
Merge pull request #3254 from Trial97/remove_multimc
remove EditAccountDialog
2025-01-17 08:51:44 +02:00
Alexandru Ionut Tripon
b7d117cc77
Merge pull request #2737 from maskersss/log-upload
Truncate logs for mclo.gs to fit 25k line limit
2025-01-17 08:49:49 +02:00
seth
1cce582d56
Merge pull request #3292 from Trial97/fix_modrinth_link
fix modrinth link
2025-01-16 20:42:00 -05:00
seth
867aaf881e
Merge pull request #3286 from PrismLauncher/update_flake_lock_action
chore(nix): update lockfile
2025-01-16 20:40:44 -05:00
seth
14b348ffe7
Merge pull request #3285 from PrismLauncher/renovate/hendrikmuhs-ccache-action-1.x
chore(deps): update hendrikmuhs/ccache-action action to v1.2.16
2025-01-16 20:40:17 -05:00
Edgars Cīrulis
181610a8c1
Merge branch 'PrismLauncher:develop' into qt-6.8 2025-01-17 03:04:43 +02:00
seth
b7f2175718
Merge pull request #3179 from sshcrack/fix-inst-java
Fix $INST_JAVA not being set for auto download java
2025-01-16 20:03:26 -05:00
seth
7a1dc0e9c9
Merge pull request #1555 from Trial97/env_vars
correctly expand env vars for pre/post launch commands
2025-01-16 19:45:31 -05:00
Trial97
9317a675ed
removed unused type
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2025-01-16 17:07:44 +02:00
Trial97
7cb8deeb90
feat: updated flame mod resolution
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2025-01-16 17:05:36 +02:00
Trial97
797cacf804
refactor to remove code duplication
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2025-01-16 17:04:53 +02:00
Trial97
d2516cbecc
use YCbCr for chesboard pattern
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2025-01-16 14:11:56 +02:00
Trial97
bca517b8d3
fix appimage
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2025-01-16 12:10:19 +02:00
Trial97
aa6518410e
fix build
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2025-01-15 23:04:47 +02:00
Trial97
9d25680587
remove defaults blocked list
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2025-01-15 22:35:47 +02:00
Trial97
82e59658d5
uniform ignoreFilesWithPath
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2025-01-15 21:59:31 +02:00
Trial97
a6f5858dac
Fix ignore for modrinth/flame export
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2025-01-15 21:54:02 +02:00
Trial97
c0525ebf4e
add wheel support for zoom
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2025-01-15 17:59:45 +02:00
Trial97
dbeb987978
improve skin preview
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2025-01-15 17:59:24 +02:00
Trial97
f6622a4cbb
implement packignore for curseforge/modrinth export
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2025-01-14 18:48:41 +02:00
Trial97
2292df16cc
some renames
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2025-01-14 18:48:20 +02:00
Trial97
e4ad4051c8
fix curseforge with empty loader as newest version
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2025-01-13 13:56:55 +02:00
Trial97
3ee73916ca
fix modrinth link
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2025-01-13 08:16:12 +02:00
github-actions[bot]
03834e1455 chore(nix): update lockfile
Flake lock file updates:

• Updated input 'nixpkgs':
    'github:NixOS/nixpkgs/6df24922a1400241dae323af55f30e4318a6ca65?narHash=sha256-dklw3AXr3OGO4/XT1Tu3Xz9n/we8GctZZ75ZWVqAVhk%3D' (2025-01-02)
  → 'github:NixOS/nixpkgs/bffc22eb12172e6db3c5dde9e3e5628f8e3e7912?narHash=sha256-8YVQ9ZbSfuUk2bUf2KRj60NRraLPKPS0Q4QFTbc%2Bc2c%3D' (2025-01-08)
2025-01-12 00:26:01 +00:00
renovate[bot]
54da41c625
chore(deps): update hendrikmuhs/ccache-action action to v1.2.16 2025-01-11 22:11:18 +00:00
Trial97
1b98c69948
generate skin preview
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2025-01-10 17:30:00 +02:00
Trial97
5ba4b3a32f
add licence header
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2025-01-10 15:31:57 +02:00
Trial97
059c03c655
fix qt5 build
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2025-01-10 15:03:53 +02:00
Trial97
87ec7cdd39
move background to vertex buffer
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2025-01-10 14:54:40 +02:00
Trial97
0219c11a73
Fix build CI
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2025-01-10 11:48:21 +02:00
Trial97
6fc386cfe9
Move shaders to separate files
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2025-01-10 11:40:38 +02:00
Trial97
cd0895b237
Add skin preview
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2025-01-10 00:54:14 +02:00
Alexandru Ionut Tripon
f4f1d5f0d7
Merge pull request #3228 from Trial97/delete_block
Add settings to control the if prism should move the downloaded mods
2025-01-09 00:12:12 +02:00
Alexandru Ionut Tripon
fbd886e9db
Merge pull request #3255 from Trial97/propagate_load
propagate load component error
2025-01-09 00:11:48 +02:00
Alexandru Ionut Tripon
0fb99d837f
Merge pull request #3230 from PrismLauncher/update_flake_lock_action
chore(nix): update lockfile
2025-01-09 00:11:24 +02:00
Alexandru Ionut Tripon
cb8320ca41
Merge pull request #3278 from Trial97/remove_drop
remove drop label
2025-01-09 00:10:50 +02:00
Alexandru Ionut Tripon
33981b9870
Merge pull request #3215 from Trial97/fix_custom_instance_icons
Fix curseforge/modrinth instance icons
2025-01-09 00:10:39 +02:00
Alexandru Ionut Tripon
07a0a15457
Merge pull request #3277 from Trial97/drop_file
fix drop file on resource page
2025-01-08 10:46:55 +02:00
Trial97
0f9ea5c949
remove drop label
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2025-01-08 01:55:45 +02:00
Trial97
d40c8b704c
fix drop file on resource page
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2025-01-08 01:52:11 +02:00
github-actions[bot]
82a500f4e8 chore(nix): update lockfile
Flake lock file updates:

• Updated input 'nixpkgs':
    'github:NixOS/nixpkgs/5d67ea6b4b63378b9c13be21e2ec9d1afc921713?narHash=sha256-Pj39hSoUA86ZePPF/UXiYHHM7hMIkios8TYG29kQT4g%3D' (2024-12-11)
  → 'github:NixOS/nixpkgs/6df24922a1400241dae323af55f30e4318a6ca65?narHash=sha256-dklw3AXr3OGO4/XT1Tu3Xz9n/we8GctZZ75ZWVqAVhk%3D' (2025-01-02)
2025-01-05 00:25:34 +00:00
Trial97
4358e28d7e
improve profile setup error message
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2024-12-31 14:33:36 +02:00
Trial97
6ebfcb91cf
propagate load component error
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2024-12-31 13:44:22 +02:00
Trial97
e01df73deb
remove EditAccountDialog
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2024-12-31 11:13:01 +02:00
Trial97
7dde35fef2
Add settings to control the if prism should move the downloaded mods
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2024-12-20 19:57:09 +02:00
Trial97
23ffc4d8b9
Refactor ResourcePack
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2024-12-19 10:42:42 +02:00
Alexandru Ionut Tripon
0b6ce5525d
Merge pull request #3216 from Trial97/fix_auto_mod_provider
Fix automatically choose mod provider option
2024-12-19 09:16:59 +02:00
timoreo
f17faadf8a
Merge pull request #3174 from PrismLauncher/update_flake_lock_action
chore(nix): update lockfile
2024-12-18 19:54:44 +01:00
timoreo
c7b6977692
Merge pull request #3043 from Trial97/fix_flame_loader_match
fix the flame loaders match
2024-12-18 19:53:22 +01:00
timoreo
423d72a6e8
Merge pull request #3197 from Trial97/fix_curseforge_import
Do not fail curseforge import if modrinth file check fails
2024-12-18 19:48:05 +01:00
timoreo
2a2ed9f8bd
Merge pull request #3214 from kthchew/fix/manifest-symlink
Correct symbolic link destination on manifest (Mojang) Java download
2024-12-18 19:42:25 +01:00
Trial97
0412ed3f78
Fix automatically choose mod provider option
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2024-12-16 14:51:59 +02:00
Trial97
f4d93a08ba
Fix curseforge/modrinth instance icons
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2024-12-16 13:27:44 +02:00
Kenneth Chew
8d53242952
Correct symbolic link destination on manifest Java download
Signed-off-by: Kenneth Chew <79120643+kthchew@users.noreply.github.com>
2024-12-16 03:30:09 -05:00
github-actions[bot]
706e263050 chore(nix): update lockfile
Flake lock file updates:

• Updated input 'flake-compat':
    'github:edolstra/flake-compat/9ed2ac151eada2306ca8c418ebd97807bb08f6ac?narHash=sha256-HRJ/18p%2BWoXpWJkcdsk9St5ZiukCqSDgbOGFa8Okehg%3D' (2024-11-27)
  → 'github:edolstra/flake-compat/ff81ac966bb2cae68946d5ed5fc4994f96d0ffec?narHash=sha256-NeCCThCEP3eCl2l/%2B27kNNK7QrwZB1IJCrXfrbv5oqU%3D' (2024-12-04)
• Updated input 'nixpkgs':
    'github:NixOS/nixpkgs/970e93b9f82e2a0f3675757eb0bfc73297cc6370?narHash=sha256-jNRNr49UiuIwaarqijgdTR2qLPifxsVhlJrKzQ8XUIE%3D' (2024-11-28)
  → 'github:NixOS/nixpkgs/5d67ea6b4b63378b9c13be21e2ec9d1afc921713?narHash=sha256-Pj39hSoUA86ZePPF/UXiYHHM7hMIkios8TYG29kQT4g%3D' (2024-12-11)
2024-12-15 00:27:47 +00:00
Alexandru Ionut Tripon
507faf9f00
Merge pull request #3150 from kthchew/fix/unneeded-hr-exceptions
Remove unnecessary hardened runtime exceptions on macOS
2024-12-14 19:30:11 +02:00
Alexandru Ionut Tripon
c0803365ef
Merge pull request #3202 from kthchew/chore/bump-sparkle
[macOS] Update Sparkle to v2.6.4
2024-12-14 18:18:04 +02:00
Alexandru Ionut Tripon
02e527c15b
Merge pull request #3199 from kthchew/fix/launcher-settings-tab
Fix tab order in launcher settings
2024-12-14 18:17:08 +02:00
Alexandru Ionut Tripon
5659dad23d
Merge pull request #3198 from kthchew/fix/local-net-use-desc
[macOS] Add local network usage description
2024-12-14 18:16:34 +02:00
Alexandru Ionut Tripon
647bb04a0d
Merge pull request #3181 from Trial97/fix_mrpack_crash
fix crash with invalid mrpack format
2024-12-14 18:15:50 +02:00
Kenneth Chew
b6cd46ad27
Update Sparkle to v2.6.4
Signed-off-by: Kenneth Chew <79120643+kthchew@users.noreply.github.com>
2024-12-14 00:42:08 -05:00
Kenneth Chew
c3712ba648
Fix tab order in launcher settings
Signed-off-by: Kenneth Chew <79120643+kthchew@users.noreply.github.com>
2024-12-12 14:53:39 -05:00
Kenneth Chew
c3e44554ab
Add local network usage description
Signed-off-by: Kenneth Chew <79120643+kthchew@users.noreply.github.com>
2024-12-12 14:43:28 -05:00
Trial97
a1c1c0b769
Do not fail curseforge import if modrinth file check fails
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2024-12-12 17:29:46 +02:00
Alexandru Ionut Tripon
15e58589d5
Merge pull request #3170 from leia-uwu/fix-icon-theme-path
[Linux] Don't use fallback icon search paths
2024-12-09 09:14:25 +02:00
Edgars Cirulis
eb8c375ec5
chore: update Qt to 6.8.1
Signed-off-by: Edgars Cirulis <edgarsciruliss@gmail.com>
2024-12-09 00:40:05 +02:00
Trial97
1dd0728a58
fix crash with invalid mrpack format
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2024-12-08 22:04:16 +02:00
sshcrack
cf2dcbd431
load meta first
Signed-off-by: sshcrack <34072808+sshcrack@users.noreply.github.com>
2024-12-08 18:27:57 +01:00
sshcrack
dedb7a2343
change order of steps
Signed-off-by: sshcrack <34072808+sshcrack@users.noreply.github.com>
2024-12-08 14:39:06 +01:00
leia uwu
614574f15c
fix icon theme search paths
using fallback search paths breaks qadwaitadecorations

Signed-off-by: leia uwu <leia@tutamail.com>
2024-12-06 23:26:46 -03:00
Alexandru Ionut Tripon
28a471777a
Merge pull request #2800 from QazCetelic/advanced-icon-dialog
Add search and support for subdirectories to icon picker
2024-12-06 12:37:45 +02:00
Alexandru Ionut Tripon
93526637cb
Merge pull request #3166 from PrismLauncher/renovate/actions-cache-4.x
chore(deps): update actions/cache action to v4.2.0
2024-12-06 08:47:04 +02:00
renovate[bot]
94c893bd86
chore(deps): update actions/cache action to v4.2.0 2024-12-05 20:29:11 +00:00
iTrooz
f9e450ace2
do not destroy the ping ConcurrentTask directly at the end of the task
Signed-off-by: iTrooz <hey@itrooz.fr>
2024-12-05 20:43:40 +01:00
iTrooz
4e48015868
currentQueryTask -> m_currentQueryTask
Signed-off-by: iTrooz <hey@itrooz.fr>
2024-12-05 20:43:40 +01:00
Alexandru Ionut Tripon
c99876f3d7
Merge pull request #3154 from PrismLauncher/update_flake_lock_action
chore(nix): update lockfile
2024-12-03 16:17:50 +02:00
Alexandru Ionut Tripon
a3b2f1a931
Merge pull request #3119 from guihkx/flathub-manifest-sync
Sync Flatpak manifest with Flathub's
2024-12-02 17:30:19 +02:00
TheKodeToad
488dc7815c
Merge pull request #3135 from Trial97/italic
Make FTB Import note italic to match others
2024-12-02 14:07:42 +00:00
Tayou
dbee4bee14
Merge pull request #3152 from leia-uwu/fix-system-icons
Fix system icons on Linux
2024-12-02 15:00:43 +01:00
github-actions[bot]
2cfd116947 chore(nix): update lockfile
Flake lock file updates:

• Updated input 'flake-compat':
    'github:edolstra/flake-compat/0f9255e01c2351cc7d116c072cb317785dd33b33?narHash=sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U%3D' (2023-10-04)
  → 'github:edolstra/flake-compat/9ed2ac151eada2306ca8c418ebd97807bb08f6ac?narHash=sha256-HRJ/18p%2BWoXpWJkcdsk9St5ZiukCqSDgbOGFa8Okehg%3D' (2024-11-27)
• Updated input 'nixpkgs':
    'github:NixOS/nixpkgs/23e89b7da85c3640bbc2173fe04f4bd114342367?narHash=sha256-y/MEyuJ5oBWrWAic/14LaIr/u5E0wRVzyYsouYY3W6w%3D' (2024-11-19)
  → 'github:NixOS/nixpkgs/970e93b9f82e2a0f3675757eb0bfc73297cc6370?narHash=sha256-jNRNr49UiuIwaarqijgdTR2qLPifxsVhlJrKzQ8XUIE%3D' (2024-11-28)
2024-12-01 00:30:03 +00:00
leia uwu
3f67ef968b
fix: icon search paths memory leak
Signed-off-by: leia uwu <leia@tutamail.com>
2024-11-30 12:51:39 -03:00
leia uwu
fd9c80db62
fix: fix system icons
This sets the fallback icon theme to the current(system default) icon theme before
launcher specific themes are applied

And removes `Inherits` line of multimc/legacy icon theme because it can end up making it
inherit a default theme set from /usr/share/icons/default/index.theme
instead of the user configured theme (probably a qt bug?)

Signed-off-by: leia uwu <leia@tutamail.com>
2024-11-30 11:35:41 -03:00
Kenneth Chew
7e76638f2c
Only disable library validation if using ad-hoc signature
While not needed for regular releases, it is needed for CI when an Apple Developer account isn't available and you can only perform an ad-hoc signature.

Signed-off-by: Kenneth Chew <79120643+kthchew@users.noreply.github.com>
2024-11-29 21:18:07 -05:00
Kenneth Chew
884f15da1e
Remove unnecessary hardened runtime exceptions
These are cruft from an older time when the launcher was ad-hoc signed, and the OS couldn't tell the libraries and launcher were signed by the same party.

Additionally, add a workaround to send the necessary library injection to the game if Steam overlay is used despite library validation being on for the launcher.

Signed-off-by: Kenneth Chew <79120643+kthchew@users.noreply.github.com>
2024-11-29 21:18:06 -05:00
iTrooz
ba0bd5fd74
Use shared pointer to store server query task
Signed-off-by: iTrooz <hey@itrooz.fr>
2024-11-29 19:42:54 +01:00
iTrooz
1477d64400
add m_ prefix to class members
Signed-off-by: iTrooz <hey@itrooz.fr>
2024-11-29 19:42:52 +01:00
iTrooz
4aaf7b9b09
chore
Signed-off-by: iTrooz <hey@itrooz.fr>
2024-11-29 14:07:39 +01:00
iTrooz
fd1cb1b58b
DCO Remediation Commit for iTrooz <hey@itrooz.fr>
I, iTrooz <hey@itrooz.fr>, hereby add my Signed-off-by to this commit: fac521a312d1f6055b29d12da8b8773adaa24afb
I, iTrooz <hey@itrooz.fr>, hereby add my Signed-off-by to this commit: 43a54cafef95a3b4c2181f4d3d1e2d3876b8e7f9
I, iTrooz <hey@itrooz.fr>, hereby add my Signed-off-by to this commit: ee35ac5afdb2a6409b7ad52fde38c411d112f064
I, iTrooz <hey@itrooz.fr>, hereby add my Signed-off-by to this commit: 99ac11bc408b5102a7c9d6d0c003e854d5e7fdef
I, iTrooz <hey@itrooz.fr>, hereby add my Signed-off-by to this commit: 8fa1dff17dc4d7953fbf7f0961a33e751183b06b
I, iTrooz <hey@itrooz.fr>, hereby add my Signed-off-by to this commit: 2f70115be5555c7c9ad46765f61e6b1cc965e8b4
I, iTrooz <hey@itrooz.fr>, hereby add my Signed-off-by to this commit: ea2a2349f8ebd353ac4ba4296f9514c3f8419c58
I, iTrooz <hey@itrooz.fr>, hereby add my Signed-off-by to this commit: 87c9066a2b218aef5296ab8ad4dddfa483dcd9cb
I, iTrooz <hey@itrooz.fr>, hereby add my Signed-off-by to this commit: fe28a051d533bd34681c6306deab5b93b13dc5e9
I, iTrooz <hey@itrooz.fr>, hereby add my Signed-off-by to this commit: 0a379a05ff03b2c55fcc4342c84f90fff64bb9a9
I, iTrooz <hey@itrooz.fr>, hereby add my Signed-off-by to this commit: 6a7678a6e9548501b84ed3a2d81a9cabe6955703
I, iTrooz <hey@itrooz.fr>, hereby add my Signed-off-by to this commit: cba7e2dc362238cbfa9bcc680d164c828cd39836
I, iTrooz <hey@itrooz.fr>, hereby add my Signed-off-by to this commit: 8cf0c2029ccccf40cbf21fd122bea233732911bc
I, iTrooz <hey@itrooz.fr>, hereby add my Signed-off-by to this commit: 0d830e56e9c888b860e03ee4a9e44239d67a4d4a
I, iTrooz <hey@itrooz.fr>, hereby add my Signed-off-by to this commit: b35cffb3477b997a4dc779696aeb0acb79880d51
I, iTrooz <hey@itrooz.fr>, hereby add my Signed-off-by to this commit: 1f094b98039b4f8c79bc402246babd4f821116db
I, iTrooz <hey@itrooz.fr>, hereby add my Signed-off-by to this commit: 2d06e0a11194a3a4c379ddd518b857c4c2b98f54
I, iTrooz <hey@itrooz.fr>, hereby add my Signed-off-by to this commit: c3543b104b5f13778677e2244ab93faf6850cb99
I, iTrooz <hey@itrooz.fr>, hereby add my Signed-off-by to this commit: 8b7040d416b46d8011b97b71505778026c2c5ece
I, iTrooz <hey@itrooz.fr>, hereby add my Signed-off-by to this commit: b8035ca0783ba42efbc7c11cf329c6f4372abbc5
I, iTrooz <hey@itrooz.fr>, hereby add my Signed-off-by to this commit: 9d5727e36b22d2a2eeb17f6faf0bf5b2c01421fd
I, iTrooz <hey@itrooz.fr>, hereby add my Signed-off-by to this commit: 7cf24586c2a9ff8e5dd33a390f83b7f098266881
I, iTrooz <hey@itrooz.fr>, hereby add my Signed-off-by to this commit: 7d04f0ee758cb3c0c9c4273de67424269d63507c
I, iTrooz <hey@itrooz.fr>, hereby add my Signed-off-by to this commit: 60fb922ba2ed56703e5d64626f015e57d5cb0de5
I, iTrooz <hey@itrooz.fr>, hereby add my Signed-off-by to this commit: a79a66c177194f1761f353e00bc53f1dc653eea3
I, iTrooz <hey@itrooz.fr>, hereby add my Signed-off-by to this commit: 1fb0fe0171fa2db09b296a62d636bab1ea026009
I, iTrooz <hey@itrooz.fr>, hereby add my Signed-off-by to this commit: 5cfb5a6f0db81e850ed3299759ffc131d049f289
I, iTrooz <hey@itrooz.fr>, hereby add my Signed-off-by to this commit: 9ce5eaaa0c8e8ca74dce42e2d287e865905efdf4
I, iTrooz <hey@itrooz.fr>, hereby add my Signed-off-by to this commit: 0c6f78dee2c16820624e2f55e12d903392baad75
I, iTrooz <hey@itrooz.fr>, hereby add my Signed-off-by to this commit: 7c8d2c9b55526db21a9656a65adbe4b2cfabd892
I, iTrooz <hey@itrooz.fr>, hereby add my Signed-off-by to this commit: 24b9815763ce1f81b30c4d422ee0d2dc5660dede
I, iTrooz <hey@itrooz.fr>, hereby add my Signed-off-by to this commit: 7d2da194184180846362af7c5d8e3726db190b88
I, iTrooz <hey@itrooz.fr>, hereby add my Signed-off-by to this commit: ca6d66970ea52ae95c064babf42f74a1d953717b
I, iTrooz <hey@itrooz.fr>, hereby add my Signed-off-by to this commit: 520d6b0b42eae5b7fb5757cc07d96b53d2f6e7e8
I, iTrooz <hey@itrooz.fr>, hereby add my Signed-off-by to this commit: 4fad298d675102df39fadd0837bc36450068a7dc
I, iTrooz <hey@itrooz.fr>, hereby add my Signed-off-by to this commit: 087ab70143c69de8e8b9c5006393137f42b41f1c
I, iTrooz <hey@itrooz.fr>, hereby add my Signed-off-by to this commit: 7c61fec8e0e753de1b7215e45b0a4272551ffac4
I, iTrooz <hey@itrooz.fr>, hereby add my Signed-off-by to this commit: fef8ee2d1b4f866437b30ec4ea8fd5cae2426e9c
I, iTrooz <hey@itrooz.fr>, hereby add my Signed-off-by to this commit: 3a9c03098267fd64a27b9bfe62dddccbdffc6cf0
I, iTrooz <hey@itrooz.fr>, hereby add my Signed-off-by to this commit: f05548f3a36c0badcedec86d6fc5dd7a973bd36e
I, iTrooz <hey@itrooz.fr>, hereby add my Signed-off-by to this commit: 66f36195d8d2d4c362e94dc56239feb42e31fd36
I, iTrooz <hey@itrooz.fr>, hereby add my Signed-off-by to this commit: ca52d00b8040e27860f931bdf5a6e7ce92c08413
I, iTrooz <hey@itrooz.fr>, hereby add my Signed-off-by to this commit: 26f50f9b818e68fc21c8ae06fc313bfc2e0da6e9
I, iTrooz <hey@itrooz.fr>, hereby add my Signed-off-by to this commit: 873232ebe3b3e41a97f908018dd5ff7fd14be10e
I, iTrooz <hey@itrooz.fr>, hereby add my Signed-off-by to this commit: 8b90a9f2b3e3d58b9725eda081cf209781c13aa6
I, iTrooz <hey@itrooz.fr>, hereby add my Signed-off-by to this commit: dbb88ca7df6594f65cba5c5e5bd821a0c2605c00
I, iTrooz <hey@itrooz.fr>, hereby add my Signed-off-by to this commit: 6f9be258dc87752c3d8d80cac44570575ecba7b0
I, iTrooz <hey@itrooz.fr>, hereby add my Signed-off-by to this commit: d124e2e0cba25e914bb885a4efd785294790227c
I, iTrooz <hey@itrooz.fr>, hereby add my Signed-off-by to this commit: cfb0c97262f2f6467f1f35460938a9160cb2484e
I, iTrooz <hey@itrooz.fr>, hereby add my Signed-off-by to this commit: 5eb417ff2be159330558999082ecb64e3ee8f003
I, iTrooz <hey@itrooz.fr>, hereby add my Signed-off-by to this commit: 3fb6764ea48e942a655aafbbce9fc4a226839eff
I, iTrooz <hey@itrooz.fr>, hereby add my Signed-off-by to this commit: ae7d3379e4ed2d8aee51026f37b7344026f97de7
I, iTrooz <hey@itrooz.fr>, hereby add my Signed-off-by to this commit: 09782745c6f1e1ad0edfd4222f432d679d10c17b
I, iTrooz <hey@itrooz.fr>, hereby add my Signed-off-by to this commit: b0778e7a1fcf62493638aa9caafcb17a8860a3a1
I, iTrooz <hey@itrooz.fr>, hereby add my Signed-off-by to this commit: 01db826ec92bd41164514518d25b1941b58e5180

Signed-off-by: iTrooz <hey@itrooz.fr>
2024-11-29 01:01:32 +01:00
iTrooz
01db826ec9
Reset online players UI component when refreshing 2024-11-29 00:58:08 +01:00
iTrooz
b0778e7a1f
chore 2024-11-29 00:44:31 +01:00
iTrooz
09782745c6
make writePacketToSocket() clear data automatically 2024-11-29 00:44:25 +01:00
iTrooz
ae7d3379e4
abort current query task if present when refreshing 2024-11-29 00:39:43 +01:00
iTrooz
3fb6764ea4
fix typo 2024-11-29 00:13:43 +01:00
iTrooz
5eb417ff2b
Always autodelete signal connections with this captured when the objet is deleted, just to be sure 2024-11-28 23:54:51 +01:00
TheKodeToad
616aa002e1
Merge pull request #2875 from Jan200101/PR/switcheroo
[Linux] Integrate switcheroo-control for discrete GPU support
2024-11-28 20:02:58 +00:00
iTrooz
cfb0c97262
use Json::requireInteger() 2024-11-28 18:09:38 +01:00
iTrooz
d124e2e0cb
cleanup 2024-11-28 17:50:55 +01:00
iTrooz
6f9be258dc
add documentation about task abortion 2024-11-28 17:49:35 +01:00
iTrooz
dbb88ca7df
move ServerPingTask in its own file 2024-11-28 17:46:42 +01:00
iTrooz
8b90a9f2b3
remove infinite loop from readVarInt() 2024-11-28 17:32:49 +01:00
iTrooz
873232ebe3
remove infinite loop in writeVarInt() 2024-11-28 17:29:35 +01:00
guihkx
e0faee7f26
ci(flatpak): update build artifact name
Just aligning the name of the Flatpak package with other build artifacts.

Signed-off-by: guihkx <626206+guihkx@users.noreply.github.com>
2024-11-27 14:35:15 -03:00
iTrooz
26f50f9b81
connect job to deletion task before starting it
This ensures the signal is not fired before we have connected it
2024-11-26 18:50:37 +01:00
iTrooz
ca52d00b80
replace std::string by QString in emitFail() 2024-11-26 18:47:13 +01:00
iTrooz
66f36195d8
simplify code 2024-11-26 18:44:21 +01:00
iTrooz
f05548f3a3
remove implicit captures 2024-11-26 18:43:14 +01:00
iTrooz
3a9c030982
Do not timeout after just 3000ms
Keep the network default timeout
2024-11-26 18:24:46 +01:00
iTrooz
fef8ee2d1b
Disconnect task finished signal when ServersModel is destroyed 2024-11-26 18:16:15 +01:00
iTrooz
7c61fec8e0
Make task output online players rather than updating Server itself
This doesn't really change anything
2024-11-26 18:03:35 +01:00
guihkx
f6770a847a
flatpak: update KDE runtime to 6.8
This also switches to the Docker image provided and maintained by
Flathub collaborators through the 'flathub-infra' organization on
GitHub, because it looks better maintained at the moment.

Signed-off-by: guihkx <626206+guihkx@users.noreply.github.com>
2024-11-26 13:51:09 -03:00
guihkx
4a50e94967
flatpak: update xrandr to 1.5.3
Signed-off-by: guihkx <626206+guihkx@users.noreply.github.com>
2024-11-26 13:51:09 -03:00
iTrooz
087ab70143
refresh UI when we got the players online 2024-11-26 14:33:02 +01:00
iTrooz
4fad298d67
put more McClient methods to private 2024-11-26 13:22:02 +01:00
iTrooz
520d6b0b42
run socket code in thread 2024-11-26 13:22:00 +01:00
iTrooz
ca6d66970e
add documentation for Task and ConcurrentTask 2024-11-25 23:49:03 +01:00
Jan200101
514ec99a03
Integrate switcheroo-control for discrete GPU support
Signed-off-by: Jan200101 <sentrycraft123@gmail.com>
2024-11-25 22:29:39 +01:00
TheKodeToad
6c062c48b4
Merge pull request #3130 from Kationor/trimversion
Improve MANIFEST.MF parsing
2024-11-25 10:05:02 +00:00
iTrooz
7d2da19418
make McResolver have the same signal name conventions as Task 2024-11-25 01:09:47 +01:00
iTrooz
24b9815763
cleanup 2024-11-25 00:16:46 +01:00
iTrooz
7c8d2c9b55
always delete McResolver object, even when it fails 2024-11-25 00:16:25 +01:00
iTrooz
0c6f78dee2
communicate when ServerPingTask succeeds/fails 2024-11-25 00:10:17 +01:00
iTrooz
9ce5eaaa0c
fix job being deleted before tasks are finished 2024-11-24 23:54:19 +01:00
Kationor
b40a1973bf
Improve MANIFEST.MF parsing
Previously, we would only properly parse LF-encoded manifests, and even
those only if they used the recommended casing.

This commit allows the parser to recognise CR and CRLF newlines, and
also makes the name comparison case insensitive to align with the
specification. (Though not completely: we still don't support multiline
values)

Signed-off-by: Kationor <n96211028@gmail.com>
2024-11-24 19:30:59 +01:00
Trial97
a09af619ce
Make FTB Import note italic to match others
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2024-11-24 20:29:07 +02:00
TheKodeToad
835944387b
Merge pull request #3128 from QazCetelic/naming-clang-tidy
Add naming check in `.clang-tidy` file
2024-11-24 16:10:41 +00:00
iTrooz
5cfb5a6f0d
do not capture things implicitely in lambdas 2024-11-24 16:37:42 +01:00
QazCetelic
d927c539b5 Update CONTRIBUTING.md conventions section
Signed-off-by: QazCetelic <qaz.cetelic@protonmail.com>
2024-11-23 19:55:40 +01:00
QazCetelic
14454faac8 Use old list style
Signed-off-by: QazCetelic <qaz.cetelic@protonmail.com>
2024-11-23 18:21:03 +01:00
QazCetelic
2351531e84 Add naming checks to clang-tidy
Signed-off-by: QazCetelic <qaz.cetelic@protonmail.com>
2024-11-23 18:15:07 +01:00
QazCetelic
33ff3b4f36 Fix naming
Signed-off-by: QazCetelic <qaz.cetelic@protonmail.com>
2024-11-23 18:10:33 +01:00
seth
11e7b218d4
Merge pull request #3113 from PrismLauncher/update_flake_lock_action
chore(nix): adopt new darwin SDK pattern
2024-11-22 18:25:21 -05:00
seth
fbbd64ddb7
chore(nix): sync with upstream nixpkgs
Signed-off-by: seth <getchoo@tuta.io>
2024-11-22 17:33:16 -05:00
github-actions[bot]
41db87c8cf chore(nix): update lockfile
Flake lock file updates:

• Updated input 'nix-filter':
    'github:numtide/nix-filter/776e68c1d014c3adde193a18db9d738458cd2ba4?narHash=sha256-SCHiL%2B1f7q9TAnxpasriP6fMarWE5H43t25F5/9e28I%3D' (2024-10-29)
  → 'github:numtide/nix-filter/f7653272fd234696ae94229839a99b73c9ab7de0?narHash=sha256-oRam5PS1vcrr5UPgALW0eo1m/5/pls27Z/pabHNy2Ms%3D' (2024-11-13)
• Updated input 'nixpkgs':
    'github:NixOS/nixpkgs/4aa36568d413aca0ea84a1684d2d46f55dbabad7?narHash=sha256-Zwl8YgTVJTEum%2BL%2B0zVAWvXAGbWAuXHax3KzuejaDyo%3D' (2024-11-05)
  → 'github:NixOS/nixpkgs/23e89b7da85c3640bbc2173fe04f4bd114342367?narHash=sha256-y/MEyuJ5oBWrWAic/14LaIr/u5E0wRVzyYsouYY3W6w%3D' (2024-11-19)
2024-11-22 22:26:01 +00:00
Alexandru Ionut Tripon
79dd912126
Merge pull request #3091 from Awqre/develop
Lossless image asset compression
2024-11-20 10:12:34 +02:00
Awqre
00fa65c18b
Merge branch 'PrismLauncher:develop' into develop 2024-11-20 02:08:31 +00:00
iTrooz
1fb0fe0171
ping servers when opening Servers page 2024-11-19 20:48:17 +01:00
iTrooz
a79a66c177
remove debug print 2024-11-19 20:43:04 +01:00
iTrooz
60fb922ba2
remove QObject parent argument from ServerPingTask constructor 2024-11-19 20:43:04 +01:00
seth
59db80cb0e
Merge pull request #3068 from Scrumplex/chore/update-nixos-readme
[Linux] Update Nix README
2024-11-19 10:09:11 -05:00
Alexandru Ionut Tripon
e5a4dfdf16
Merge pull request #2962 from AOSC-Tracking/upstream/detect-aosc-os-jdks
javautils: add a filter for detecting Java paths on AOSC OS
2024-11-19 13:44:57 +02:00
QazCetelic
6ca18c6266 Refactoring
Signed-off-by: QazCetelic <qaz.cetelic@protonmail.com>
2024-11-18 19:19:02 +01:00
QazCetelic
e74592fa09 Code style conventions (camelCase, m_ prefix)
Signed-off-by: QazCetelic <qaz.cetelic@protonmail.com>
2024-11-17 20:43:09 +01:00
QazCetelic
abbebff400 Removed bug when renaming icon file in nested folder while application is running
Signed-off-by: QazCetelic <qaz.cetelic@protonmail.com>
2024-11-17 20:35:24 +01:00
iTrooz
7d04f0ee75
remove useless code when reading response 2024-11-17 20:06:08 +01:00
iTrooz
7cf24586c2
.hpp -> .h 2024-11-17 19:58:30 +01:00
iTrooz
9d5727e36b
MCResolver -> McResolver 2024-11-17 19:51:15 +01:00
iTrooz
b8035ca078
refactor header and code into 2 files 2024-11-17 19:50:52 +01:00
iTrooz
8b7040d416
use Qt5-compatible writeString() impl 2024-11-17 19:37:15 +01:00
iTrooz
c3543b104b
fix qDebug() call with string << append 2024-11-17 19:26:21 +01:00
iTrooz
2d06e0a111
Fix after rebase 2024-11-17 19:21:09 +01:00
iTrooz
1f094b9803
avoid translating back to stf string without reason 2024-11-17 19:10:15 +01:00
iTrooz
b35cffb347
fix warning about unused jsonLength 2024-11-17 19:10:15 +01:00
iTrooz
0d830e56e9
replace std::runtime_exception with PrismLauncher Exception + add try/catch 2024-11-17 19:10:15 +01:00
iTrooz
8cf0c2029c
No need to close the socket, it is done automatically
https://doc.qt.io/qt-6/qtcpsocket.html#dtor.QTcpSocket
2024-11-17 19:10:15 +01:00
iTrooz
cba7e2dc36
use std::optional<> to signify when there is no value 2024-11-17 19:10:15 +01:00
iTrooz
6a7678a6e9
Actually show online players when clicking on the button 2024-11-17 19:10:15 +01:00
iTrooz
0a379a05ff
replace my printf calls with qDebug 2024-11-17 19:10:15 +01:00
iTrooz
fe28a051d5
make MCResolver a dynamic object so it doesnt get deleted before the callback
See https://discord.com/channels/1031648380885147709/1031823065937629267/1307471566166167696
2024-11-17 19:10:15 +01:00
iTrooz
87c9066a2b
run the code in tasks 2024-11-17 19:10:15 +01:00
iTrooz
ea2a2349f8
make splitAddress() const 2024-11-17 19:10:15 +01:00
iTrooz
2f70115be5
add debug print 2024-11-17 19:10:15 +01:00
iTrooz
8fa1dff17d
remove space 2024-11-17 19:10:15 +01:00
iTrooz
99ac11bc40
add my classes to CMakeLists 2024-11-17 19:10:15 +01:00
iTrooz
ee35ac5afd
add method queryStatus() to servers and use it on click 2024-11-17 19:10:15 +01:00
iTrooz
43a54cafef
add my classes 2024-11-17 19:10:15 +01:00
iTrooz
fac521a312
Add dummy UI button 2024-11-17 19:10:15 +01:00
Awqre
3c88eccf17
Merge branch 'PrismLauncher:develop' into develop 2024-11-17 08:19:35 +00:00
TheKodeToad
48235f5b71
Merge pull request #3083 from Trial97/fix_resource_search
Fix resource search
2024-11-15 23:09:28 +00:00
timoreo
736ecf266d
Merge pull request #3019 from Trial97/task_parent
fixed double deletion for tasks
2024-11-15 06:19:40 +01:00
timoreo
b2a37452be
Merge pull request #3024 from Trial97/leak
fix leak on resource search
2024-11-15 06:18:33 +01:00
timoreo
54f2e75b9d
Merge pull request #3070 from TheKodeToad/general-scrollbar
Add scrollbar to Settings -> Launcher -> Features
2024-11-15 06:16:54 +01:00
timoreo
f7620a43aa
Merge pull request #3094 from Trial97/remove_resource_warning
Fix warnings regarding Resource static cast
2024-11-15 06:15:55 +01:00
timoreo
bcbe5da87f
Merge pull request #3096 from Trial97/dangling_file
Fix file remaingin open after program closure
2024-11-15 06:14:25 +01:00
Alexandru Ionut Tripon
e735ea7e63
Merge pull request #3003 from PrismLauncher/update_flake_lock_action
chore(nix): update lockfile
2024-11-14 22:50:53 +02:00
Trial97
ce61ed2f86 Fix file remaingin open after program closure
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2024-11-14 13:27:16 +02:00
Trial97
172e43cd3f Fix warnings regarding Resource static cast
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2024-11-13 23:11:33 +02:00
Awqre
9f0b2bafd8 Further additional even better(er) compression
Truly unprecedented levels of optimization we're reaching here. (OxiPNG/ZopfliPNG/ECT/DeflOpt)

Signed-off-by: Awqre <32497511+Awqre@users.noreply.github.com>
2024-11-13 14:31:20 -05:00
txtsd
03b34e39f8
feat: Compression script with compressed images
Also modified genicons.sh

Signed-off-by: txtsd <code@ihavea.quest>
2024-11-13 19:04:31 +05:30
Awqre
885fc66c14 Lossless image compression
Applied lossless zopfli/ect/deflopt compression to PNG files including ones contained in ICO files.

Repacked ICO files with optidash icopack

Signed-off-by: Awqre <32497511+Awqre@users.noreply.github.com>
2024-11-12 20:17:17 -05:00
github-actions[bot]
f41380d91c chore(nix): update lockfile
Flake lock file updates:

• Updated input 'nix-filter':
    'github:numtide/nix-filter/3342559a24e85fc164b295c3444e8a139924675b?narHash=sha256-1Wvk8UP7PXdf8bCCaEoMnOT1qe5/Duqgj%2BrL8sRQsSM%3D' (2024-03-11)
  → 'github:numtide/nix-filter/776e68c1d014c3adde193a18db9d738458cd2ba4?narHash=sha256-SCHiL%2B1f7q9TAnxpasriP6fMarWE5H43t25F5/9e28I%3D' (2024-10-29)
• Updated input 'nixpkgs':
    'github:NixOS/nixpkgs/4c2fcb090b1f3e5b47eaa7bd33913b574a11e0a0?narHash=sha256-/uilDXvCIEs3C9l73JTACm4quuHUsIHcns1c%2BcHUJwA%3D' (2024-10-18)
  → 'github:NixOS/nixpkgs/4aa36568d413aca0ea84a1684d2d46f55dbabad7?narHash=sha256-Zwl8YgTVJTEum%2BL%2B0zVAWvXAGbWAuXHax3KzuejaDyo%3D' (2024-11-05)
2024-11-10 00:24:54 +00:00
Trial97
66883db645 Fix removed signal handler for filter resource
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2024-11-09 23:30:04 +02:00
Tayou
df45e5518f
Merge pull request #3081 from Trial97/fix_markdown
fix CONTRIBUTING.md formating
2024-11-09 22:19:41 +01:00
Trial97
4c8c6e543e fix contrributing
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2024-11-08 00:18:12 +02:00
Alexandru Ionut Tripon
1d9508c268
Merge pull request #3074 from Trial97/lock
Close the window using the invokeMethod to not block
2024-11-07 23:45:44 +02:00
Alexandru Ionut Tripon
7d03cb114d
Merge pull request #3031 from Trial97/lambda
do not capture by default all values in lambdas
2024-11-07 23:45:31 +02:00
Tayou
2fcf03ead3
Merge pull request #3036 from Trial97/typo4 2024-11-07 17:30:47 +01:00
TheKodeToad
012bbca197
JavaSettingsWidget -> JavaWizardWidget
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2024-11-07 14:51:43 +00:00
TheKodeToad
8132828ad7
Phrasing fix
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2024-11-07 13:36:33 +00:00
Trial97
9601fbf2d5
Close the window using the invokeMethod to not block
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2024-11-07 15:07:17 +02:00
TheKodeToad
6e55239cec
Merge pull request #3073 from TheKodeToad/fix-formatting-guidelines-oversight
Fix formatting oversight
2024-11-07 13:01:15 +00:00
TheKodeToad
900235642c
Fix formatting oversight
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2024-11-07 12:16:22 +00:00
TheKodeToad
f667f56fb7
Merge pull request #3067 from TheKodeToad/updated-formatting-guidelines
Updated formatting guidelines
2024-11-07 11:43:12 +00:00
TheKodeToad
e06b3e7a7a
Implement open global settings
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2024-11-07 00:47:32 +00:00
TheKodeToad
223b6b3b2b
Fix non-Linux build
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2024-11-07 00:22:22 +00:00
TheKodeToad
71e55f8829
Add scrollbar to Settings -> Launcher -> Features
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2024-11-07 00:11:27 +00:00
TheKodeToad
e6d4e5d78d
Unify instance and global settings pt.1
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2024-11-06 23:46:30 +00:00
TheKodeToad
8ecc21c093
Make Ryex's suggested change
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2024-11-06 22:12:22 +00:00
Sefa Eyeoglu
0a80da28fa
chore: update Nix readme
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2024-11-06 19:29:57 +01:00
TheKodeToad
b67d400f60
Update formatting guidelines
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2024-11-06 16:27:03 +00:00
timoreo
1ab10bdd84
Merge pull request #3060 from Ryex/ci/bump_linux_qt
ci: bump linux qt version
2024-11-05 11:25:27 +01:00
Rachel Powers
ba6743d134
ci: libxcb-curcsor_dev ?
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2024-11-05 01:30:55 -07:00
Rachel Powers
d63a336411
ci: bump linux qt version
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2024-11-05 01:10:38 -07:00
Alexandru Ionut Tripon
4a92573235
Merge pull request #3042 from Trial97/isportable
use isPortable to determine if the MSAStep should check for url handler
2024-11-03 11:55:55 +02:00
Alexandru Ionut Tripon
db3d796275
Merge pull request #3045 from Trial97/ask_retry3
disable retry for modrinth currentVersions API
2024-11-03 11:55:37 +02:00
Trial97
6f2f3c2d3b
disable retry for modrinth currentVersions API
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2024-11-01 17:34:29 +02:00
Trial97
f77f0207f7
fix the flame loaders match
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2024-11-01 14:30:47 +02:00
Trial97
99cfb62370
use isPortable to determine if the MSAStep should check for url handler
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2024-11-01 11:03:47 +02:00
Trial97
2b590f24ed
remove task parent from constuctor
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2024-11-01 00:11:45 +02:00
Trial97
670c932f32 Fix installed typo
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2024-10-31 14:51:18 +02:00
TheKodeToad
ba07a136dc
Merge pull request #3035 from PrismLauncher/remove-BasicFolderLoadTask
Remove BasicFolderLoadTask
2024-10-31 09:17:27 +00:00
TheKodeToad
9ae16921bc
Remove BasicFolderLoadTask
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2024-10-30 21:10:43 +00:00
Tayou
887e4a964a
Merge pull request #3010 from Trial97/lock3 2024-10-30 21:56:17 +01:00
seth
8faff9ac6a
Merge pull request #3030 from Trial97/sys 2024-10-30 15:16:38 -04:00
Trial97
0e80aae1b8
Merge branch 'develop' of https://github.com/PrismLauncher/PrismLauncher into lambda 2024-10-30 19:35:25 +02:00
TheKodeToad
c142d38f08
Merge pull request #1588 from TheKodeToad/resource-meta
Implement tracking and updates for files other than mods
2024-10-30 17:03:54 +00:00
Trial97
82bffabb69
do not capture by default all values in lambdas
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2024-10-30 18:16:43 +02:00
Trial97
14c95b9d37
fix macos system detection
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2024-10-30 17:15:42 +02:00
Alexandru Ionut Tripon
b7598c6a41
Merge pull request #2331 from michaeltyson/develop
Support for launching from command line in offline mode
2024-10-30 09:49:33 +02:00
Michael Tyson
ced2f9d1a0 Applied clang formatting
Signed-off-by: Michael Tyson <michael@atastypixel.com>
2024-10-30 12:51:34 +11:00
Michael Tyson
5661444414 Removed “--name” flag in favour of specifying offline player name via “--offline” flag
Signed-off-by: Michael Tyson <michael@atastypixel.com>
2024-10-30 12:37:14 +11:00
Michael Tyson
afa1e0599a Improved formatting
Signed-off-by: Michael Tyson <michael@atastypixel.com>
2024-10-30 12:34:33 +11:00
Michael Tyson
43e4481b70 Support for launching from command line in offline mode
This allows launching an offline instance with --offline --name=OfflineName. This is useful for playing split screen by creating two side-by-side instances, which is impossible online, unless one is using two separate paid accounts.

With this PR, it makes it possible to launch from a script - otherwise, one has to launch manually, which is a pain, or create offline profiles for each instance, which interferes with some functionality like skins (my autistic son takes great issue with his skin not being visible, when using offline profiles!).

Implementation is based on MultiMC, which supports this feature.

See also https://github.com/PrismLauncher/PrismLauncher/issues/1059 for discussion.

Signed-off-by: Michael Tyson <michael@atastypixel.com>
2024-10-30 12:30:20 +11:00
Tayou
65b0fdf08d
Merge pull request #3027 from benthetechguy/metadata 2024-10-29 23:06:01 +01:00
Ben Westover
f6511c601e
Fix some typos
Signed-off-by: Ben Westover <me@benthetechguy.net>
2024-10-29 20:45:10 +00:00
Ben Westover
fd109c4740
Shorten metainfo.xml app summary
Signed-off-by: Ben Westover <me@benthetechguy.net>
2024-10-29 20:45:06 +00:00
TheKodeToad
2368521a9a
Add missing semicolon
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2024-10-29 17:54:03 +00:00
TheKodeToad
d49e6187cd
Make requested changes
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2024-10-29 17:17:51 +00:00
TheKodeToad
c1c198b84b
Combine if statements
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2024-10-29 15:45:30 +00:00
TheKodeToad
e7ff3146fe
Merge pull request #1953 from Trial97/account2
Auto reauthenticate account if expired
2024-10-29 14:08:50 +00:00
Trial97
8e7d84d05b
fix leak on resource search
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2024-10-29 00:40:13 +02:00
TheKodeToad
d157159106
Fix license headers and formatting
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2024-10-28 22:29:43 +00:00
TheKodeToad
bd8b30c606
Implement link for InfoFrame::updateWithResource
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2024-10-28 22:17:16 +00:00
TheKodeToad
f56a8feade
Merge pull request #2986 from Trial97/bump_10.x
bump develop to 10
2024-10-28 21:12:53 +00:00
TheKodeToad
f3cae427f1
Fix tests (make them green)
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2024-10-28 21:09:45 +00:00
Alexandru Ionut Tripon
51b7abec24
Merge pull request #3005 from Trial97/installed
add installed text to version select
2024-10-28 22:55:40 +02:00
Alexandru Ionut Tripon
d90ed89a30
Merge pull request #2989 from Trial97/what
add extra protection against empty download link
2024-10-28 22:55:21 +02:00
TheKodeToad
ad1d5ddcdf
Revert unwise refactor
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2024-10-28 20:42:59 +00:00
Alexandru Ionut Tripon
2dee936246
Merge pull request #2837 from Trial97/translate_standeard_butons
translate standard buttons
2024-10-28 22:31:47 +02:00
Alexandru Ionut Tripon
a0a74612e1
Merge pull request #1894 from Trial97/maximize
Fixed the maximized option on the newer Minecraft versions
2024-10-28 22:30:09 +02:00
Alexandru Ionut Tripon
fbd3aa36c4
Merge pull request #3006 from Trial97/relase_type
add release_type filer for mod/modpacks
2024-10-28 22:29:38 +02:00
Trial97
94f65f8727
add qassert
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2024-10-28 22:27:40 +02:00
TheKodeToad
2b22a1aebe
Reimplement View Homepage
I removed it for some reason, but now it's back for all pages!

Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2024-10-28 20:14:56 +00:00
TheKodeToad
354a0ed46e
Fix column sizes
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2024-10-28 18:01:01 +00:00
Trial97
9cdda4377b
remove message box
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2024-10-28 19:19:06 +02:00
TheKodeToad
49044e23de
Fix Export List placement
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2024-10-28 16:21:00 +00:00
TheKodeToad
f57ca1e79e
Add Change Version action to all pages
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2024-10-28 16:07:41 +00:00
Trial97
0f42f3cc5c
Added warning regarding maximized option
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2024-10-28 17:19:18 +02:00
Trial97
81c5866fa9
Made sure that the qt version check is in place
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2024-10-28 17:19:18 +02:00
Trial97
1be29076ea
When java disappoints try C++
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2024-10-28 17:19:18 +02:00
Trial97
3c17f606ed
Patched the maximized option on the newer Minecraft versions
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2024-10-28 17:19:18 +02:00
Trial97
09a118e85e
expand env from wrapped cmd
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2024-10-28 16:23:33 +02:00
Trial97
c12beb43a0
correctly expand env vars
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2024-10-28 16:23:33 +02:00
Trial97
08f5148a9a
Added mouse interactions for labels in ProgressDialog
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2024-10-28 16:22:52 +02:00
Trial97
14ad720c58
fix conflict
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2024-10-28 16:21:40 +02:00
Trial97
0ee5665c95
Revert "Removed auto reauthenticate"
This reverts commit 400b518bc21b8a56131384fd4a56988d31bceb9f.

Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2024-10-28 16:21:39 +02:00
Trial97
bd82737efb
translate standard buttons
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2024-10-28 15:46:47 +02:00
Trial97
f75e049675
add release_type filer for mod/modpacks
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2024-10-28 15:36:47 +02:00
Tayou
1f8ce9eb92
Merge pull request #3002 from Trial97/typo2 2024-10-28 14:19:53 +01:00
Alexandru Ionut Tripon
d4bf61da50
Merge pull request #3007 from Trial97/open_source
add open source filter
2024-10-28 15:04:33 +02:00
Tayou
33754db9b9
Merge pull request #3009 from Trial97/order 2024-10-28 14:04:20 +01:00
TheKodeToad
1809858fc7
Ignore .index in ExportPackDialog
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2024-10-28 11:01:30 +00:00
Trial97
0cafac84ac
replace currentData with itemData on QComboBox::currentIndexChanged slots
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2024-10-28 12:54:21 +02:00
Trial97
9eb1ce3ad7
replace unzipping with unpacking
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2024-10-28 12:39:26 +02:00
TheKodeToad
6a6fe60a5b
Revert "Use non-mod metadata in ModrinthPackExportTask"
Out-of-scope

Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2024-10-28 10:29:49 +00:00
Alexandru Ionut Tripon
6338e2b362
Update launcher/ui/widgets/ModFilterWidget.ui
Co-authored-by: TheKodeToad <TheKodeToad@proton.me>
Signed-off-by: Alexandru Ionut Tripon <alexandru.tripon97@gmail.com>
2024-10-28 00:34:41 +02:00
txtsd
b1113f4293
Merge pull request #3008 from Trial97/about
change contributors name
2024-10-28 01:01:43 +05:30
Trial97
c4cd7cf6c1
change ZekeZ name
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2024-10-27 13:17:58 +02:00
Trial97
11d4d948aa
lock m_instanceExtras
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2024-10-27 12:36:14 +02:00
Trial97
61448a61ea
swap search with filter button for modpacks
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2024-10-27 12:06:45 +02:00
Trial97
f373a5cea0
change contributors name
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2024-10-27 11:58:34 +02:00
Trial97
935b2e8fb2
add open source filter
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2024-10-27 11:56:48 +02:00
Trial97
b1c8ab9350
add installed text to version select
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2024-10-27 10:56:14 +02:00
Trial97
b593ff09e9
fix #3001
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2024-10-27 03:05:56 +02:00
Trial97
44894a29b1
rename snake_case to camelCase
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2024-10-27 03:05:30 +02:00
Trial97
685d3c79ac
fix unzipping typo
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2024-10-27 03:02:13 +03:00
TheKodeToad
b66d6b2812
Unhardcode PREFIXES
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2024-10-26 13:24:03 +01:00
seth
5b8ea89092
Merge pull request #2992 from getchoo-contrib/nix/sync 2024-10-25 20:56:44 -04:00
TheKodeToad
13e13ea8fc
Use non-mod metadata in ModrinthPackExportTask
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2024-10-25 19:13:41 +01:00
seth
63b10738b2
chore(nix): use self for version
Signed-off-by: seth <getchoo@tuta.io>
2024-10-25 02:35:53 -04:00
seth
a5c554cf6e
chore(nix): sync with nixpkgs
Signed-off-by: seth <getchoo@tuta.io>
2024-10-25 02:35:53 -04:00
seth
6a2ed4a631
Merge pull request #2982 from TheKodeToad/launcher-level-autoinstalljava
Use Launcher log level in AutoInstallJava
2024-10-25 02:23:02 -04:00
seth
b7152e7010
Merge pull request #2963 from PrismLauncher/renovate/actions-cache-4.x
chore(deps): update actions/cache action to v4.1.2
2024-10-25 02:22:12 -04:00
seth
d766de5fbf
Merge pull request #2980 from Arcitec/flatpak-enhancements
fix: bring back Flathub manifest improvements to the repo
2024-10-25 02:19:09 -04:00
Trial97
8daa1219a5
add extra protection against empty download link
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2024-10-25 01:13:05 +03:00
Trial97
3bc40120cd
bump develop to 10
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2024-10-25 00:17:34 +03:00
Arcitec
4ce025c0a2 fix: bring back Flathub manifest improvements to the repo
- Brings back all manifest improvements, such as the incredibly important Mojang Java Downloader (without it, the Flatpak doesn't work), and important fixes for Wayland.

Signed-off-by: Arcitec <38923130+Arcitec@users.noreply.github.com>
2024-10-24 17:36:45 +02:00
TheKodeToad
d8702e1357
Use Launcher log level in AutoInstallJava
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2024-10-24 12:46:01 +01:00
TheKodeToad
9fe81ff564
Merge pull request #2975 from Ryex/fix/version-page-load-speed
fix: don't hang the ui for a full version load
2024-10-24 11:24:35 +01:00
TheKodeToad
5eff9b0934
Fix column crashes
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2024-10-24 01:23:11 +01:00
TheKodeToad
8e586c883c
Fix Modrinth update crashing
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2024-10-24 01:16:06 +01:00
Rachel Powers
7bd04ae928
fix don't hang the ui for a full version load
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2024-10-23 16:23:10 -07:00
TheKodeToad
4a7d624e9b
Merge pull request #2972 from TheKodeToad/fix-clean-env
Fix launching Minecraft in portable Linux
2024-10-23 22:30:42 +01:00
TheKodeToad
92a906e0d4
Move everything in CheckUpdateTask::Update
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2024-10-23 14:58:52 +01:00
TheKodeToad
24cecf7b63
Fix compile
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2024-10-23 14:42:54 +01:00
TheKodeToad
89a327d363
Merge remote-tracking branch 'upstream/develop' into resource-meta
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2024-10-23 14:19:07 +01:00
TheKodeToad
e7cd8fe078
Fix CleanEnviroment()'s usage of stripVariableEntries
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2024-10-23 13:44:39 +01:00
Kaiyang Wu
3d82bc37af
javautils: add a filter for detecting Java paths on AOSC OS
Signed-off-by: Kaiyang Wu <origincode@aosc.io>
2024-10-22 11:58:00 -07:00
TheKodeToad
f13e875f0d
Try to fix ModrinthCheckUpdate (not working)
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2024-10-22 18:46:10 +01:00
Alexandru Ionut Tripon
79439a0217
Merge pull request #2958 from Trial97/crash_QsaveFile
skip parsing open QSaveFile temprary files as resources
2024-10-22 17:38:32 +03:00
renovate[bot]
210d0d8aa2
chore(deps): update actions/cache action to v4.1.2 2024-10-22 13:48:29 +00:00
Trial97
836aebc0d9
fix small leak
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2024-10-22 13:43:16 +03:00
Trial97
73d33f93b3
Replaced QSet with QHash
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2024-10-22 09:41:00 +03:00
Trial97
562c301326
skip QSaveFile temprary files
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2024-10-22 01:22:31 +03:00
Alexandru Ionut Tripon
a43ebefc97
Merge pull request #2954 from Trial97/skin_warn
do not try to import skin if path is empty
2024-10-22 00:14:16 +03:00
Alexandru Ionut Tripon
69028969f1
Update launcher/ui/dialogs/skins/SkinManageDialog.cpp
Co-authored-by: TheKodeToad <TheKodeToad@proton.me>
Signed-off-by: Alexandru Ionut Tripon <alexandru.tripon97@gmail.com>
2024-10-21 22:59:51 +03:00
Alexandru Ionut Tripon
671d5270eb
Merge pull request #2953 from TheKodeToad/portable-fix
Fix removing portable.txt on Linux portable build
2024-10-21 22:44:44 +03:00
Trial97
9a5b773e69
do not try to import skin if path is empty
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2024-10-21 19:28:34 +03:00
TheKodeToad
f3f4c44620
Fix removing portable.txt on Linux portable build
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2024-10-21 16:30:08 +01:00
TheKodeToad
b049e92697
Merge pull request #2947 from Trial97/fix_initial_setup
do not require java if auto-download is enabled
2024-10-21 15:57:47 +01:00
Tayou
ea703ba26e
Merge pull request #2948 from TheKodeToad/vc-redist-norestart 2024-10-21 16:54:18 +02:00
TheKodeToad
78e24962f9
Fix /norestart
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2024-10-21 14:41:48 +01:00
Trial97
fcadbbb739
do not require java if auto-download is enabled
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2024-10-21 16:17:48 +03:00
Alexandru Ionut Tripon
a8c3a49cb9
Merge pull request #2938 from Trial97/fix_sparkle
fix sparkle signature
2024-10-21 00:05:57 +03:00
Trial97
0586d38e03
fix sparkle signature
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2024-10-20 23:53:23 +03:00
Edgars Cirulis
0beaa94311
ci: uprev qt install action to v4
Signed-off-by: Edgars Cirulis <edgarsciruliss@gmail.com>
2024-10-10 15:26:36 +03:00
Edgars Cirulis
b39098dbc5
ci: fix qt-6.8 workflow
Signed-off-by: Edgars Cirulis <edgarsciruliss@gmail.com>
2024-10-10 15:26:19 +03:00
Edgars Cirulis
5b6d551650
chore: update Qt to 6.8.0
Signed-off-by: Edgars Cirulis <edgarsciruliss@gmail.com>
2024-10-10 03:45:35 +03:00
TheKodeToad
4b66320f63
Move x-prism-launcher to unnamed table for consistency
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2024-10-08 22:51:03 +01:00
TheKodeToad
a76f37760c
Fix log spam when opening files from older versions
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2024-10-08 22:30:50 +01:00
TheKodeToad
538815e033
Merge remote-tracking branch 'upstream/develop' into resource-meta
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2024-10-08 17:16:10 +01:00
TheKodeToad
3fae659b30
Merge remote-tracking branch 'upstream/develop' into resource-meta
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2024-10-08 17:15:42 +01:00
QazCetelic
f641f3acda Refactoring
Signed-off-by: QazCetelic <qaz.cetelic@protonmail.com>
2024-09-24 12:32:49 +02:00
QazCetelic
b675406b1a Split set creation into a separate function for readability
Signed-off-by: QazCetelic <qaz.cetelic@protonmail.com>
2024-09-24 10:16:26 +02:00
QazCetelic
a58e81d744 snake_case to camelCase
Signed-off-by: QazCetelic <qaz.cetelic@protonmail.com>
2024-09-24 09:58:47 +02:00
QazCetelic
e35faa5522 Feedback I
Signed-off-by: QazCetelic <qaz.cetelic@protonmail.com>
2024-09-15 09:04:23 +02:00
QazCetelic
7b49fd6508 fixes for ci errors IV
Signed-off-by: QazCetelic <qaz.cetelic@protonmail.com>
2024-09-11 10:07:05 +02:00
QazCetelic
f7f7c4b43e fixes for ci errors III
Signed-off-by: QazCetelic <qaz.cetelic@protonmail.com>
2024-09-11 09:55:27 +02:00
QazCetelic
506ec64273 fixes for ci errors II
Signed-off-by: QazCetelic <qaz.cetelic@protonmail.com>
2024-09-11 09:43:45 +02:00
QazCetelic
0a576a0f67 fixes for ci errors
Signed-off-by: QazCetelic <qaz.cetelic@protonmail.com>
2024-09-11 09:31:16 +02:00
QazCetelic
40c3866f63 clang-tidy formatting
Signed-off-by: QazCetelic <qaz.cetelic@protonmail.com>
2024-09-11 09:22:28 +02:00
QazCetelic
6b0007291b Added search and support for subdirectories to icon picker
Signed-off-by: QazCetelic <qaz.cetelic@protonmail.com>
2024-09-10 22:30:29 +02:00
maskers
6a12c43c78 fix off by one error
Signed-off-by: maskers <97827489+mskrss@users.noreply.github.com>
2024-08-25 16:02:32 +03:00
TheKodeToad
43fc9ba932
Confirm Truncate -> Truncation
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2024-08-25 13:05:08 +01:00
maskers
762d24bd02 don't mention prism in the middle of the log
Signed-off-by: maskers <97827489+mskrss@users.noreply.github.com>
2024-08-22 21:44:53 +03:00
maskers
a910337e9d
apply suggestion from code review
Co-authored-by: TheKodeToad <TheKodeToad@proton.me>
Signed-off-by: maskers <97827489+maskersss@users.noreply.github.com>
2024-08-22 21:42:05 +03:00
maskers
6d017b5f0b fix formatting
Signed-off-by: maskers <97827489+mskrss@users.noreply.github.com>
2024-08-21 22:39:27 +03:00
maskers
65f8526152
add a Cancel option
Co-authored-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
Signed-off-by: maskers <97827489+maskersss@users.noreply.github.com>
2024-08-21 22:14:11 +03:00
maskers
99bd4a8937
Apply suggestions from code review
Co-authored-by: Alexandru Ionut Tripon <alexandru.tripon97@gmail.com>
Signed-off-by: maskers <97827489+maskersss@users.noreply.github.com>
2024-08-21 19:42:35 +03:00
maskers
cf914526bf add a warning about the log being too large
Signed-off-by: maskers <97827489+mskrss@users.noreply.github.com>
2024-08-21 15:59:51 +03:00
maskers
858f6aa9b8 fix formatting
Signed-off-by: maskers <97827489+mskrss@users.noreply.github.com>
2024-08-20 22:16:40 +03:00
maskers
e6f30c0ebe fix formatting
Signed-off-by: maskers <97827489+mskrss@users.noreply.github.com>
2024-08-20 22:14:40 +03:00
maskers
014fc14291 truncate logs for mclo.gs upload to fit 25k line limit
Signed-off-by: maskers <97827489+mskrss@users.noreply.github.com>
2024-08-20 21:53:05 +03:00
TheKodeToad
60bd8104c4
Merge remote-tracking branch 'upstream/develop' into resource-meta
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2024-04-26 01:53:51 +01:00
TheKodeToad
9ce10231ed
Remove redundant event handler
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2024-04-26 01:44:43 +01:00
TheKodeToad
803e26a401
Make actions more consistent
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2024-04-26 01:40:18 +01:00
TheKodeToad
27780cc7ae
Add update UI for all resource types
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2024-03-06 14:56:04 +00:00
TheKodeToad
82d0f204e2
De-OOP ProviderCapabilities
There was no reason for it to be a class, and imo it created quite a code-smell needing to initialise it everywhere.

Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2024-01-26 03:06:05 +00:00
TheKodeToad
97ee0a19b5
Refactor updating mechanisms to work with all resources
Summary:
- It compiles
- I need to go to bed

Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2024-01-26 02:53:57 +00:00
TheKodeToad
2c18d0f1a5
Store current version in packwiz metadata (temporarily using x-prismlauncher-version-number)
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2024-01-25 15:41:34 +00:00
TheKodeToad
35b5c8097c
Merge branch 'develop' into resource-meta
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2024-01-23 23:20:40 +00:00
TheKodeToad
f4940e26c6
Merge remote-tracking branch 'upstream/develop' into resource-meta
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2023-11-12 19:02:14 +00:00
TheKodeToad
179abfa03e
Resource provider column
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2023-09-01 22:05:44 +01:00
TheKodeToad
ad16d61208
Resource metadata writing
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2023-09-01 17:42:05 +01:00
TheKodeToad
6aecbfc38f
Fix crashes
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2023-09-01 12:50:20 +01:00
TheKodeToad
ee48766996
More generalistaion for ResourceFolderModels
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2023-09-01 00:27:05 +01:00
TheKodeToad
93876e27f8
Generalise resource metadata
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2023-08-31 17:54:22 +01:00
705 changed files with 18461 additions and 9561 deletions

View File

@ -1,5 +1,23 @@
Checks:
- modernize-use-using
- readability-avoid-const-params-in-decls
- misc-unused-parameters,
- readability-identifier-naming
SystemHeaders: false
# ^ Without unused-parameters the readability-identifier-naming check doesn't cause any warnings.
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 }

2
.envrc
View File

@ -1,2 +1,2 @@
use flake
use nix
watch_file nix/*.nix

View File

@ -5,3 +5,9 @@ bbb3b3e6f6e3c0f95873f22e6d0a4aaf350f49d9
# (nix) alejandra -> nixfmt
4c81d8c53d09196426568c4a31a4e752ed05397a
# reformat codebase
1d468ac35ad88d8c77cc83f25e3704d9bd7df01b
# format a part of codebase
5c8481a118c8fefbfe901001d7828eaf6866eac4

View File

@ -0,0 +1,103 @@
# This file incorporates work covered by the following copyright and
# permission notice
#
# Copyright (c) 2003-2025 Eelco Dolstra and the Nixpkgs/NixOS contributors
#
# 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.
name: Get merge commit
description: Get a merge commit of a given pull request
inputs:
repository:
description: Repository containing the pull request
required: false
pull-request-id:
description: ID of a pull request
required: true
outputs:
merge-commit-sha:
description: Git SHA of a merge commit
value: ${{ steps.query.outputs.merge-commit-sha }}
runs:
using: composite
steps:
- name: Wait for GitHub to report merge commit
id: query
shell: bash
env:
GITHUB_REPO: ${{ inputs.repository || github.repository }}
PR_ID: ${{ inputs.pull-request-id }}
# https://github.com/NixOS/nixpkgs/blob/8f77f3600f1ee775b85dc2c72fd842768e486ec9/ci/get-merge-commit.sh
run: |
set -euo pipefail
log() {
echo "$@" >&2
}
# Retry the API query this many times
retryCount=5
# Start with 5 seconds, but double every retry
retryInterval=5
while true; do
log "Checking whether the pull request can be merged"
prInfo=$(gh api \
-H "Accept: application/vnd.github+json" \
-H "X-GitHub-Api-Version: 2022-11-28" \
"/repos/$GITHUB_REPO/pulls/$PR_ID")
# Non-open PRs won't have their mergeability computed no matter what
state=$(jq -r .state <<<"$prInfo")
if [[ "$state" != open ]]; then
log "PR is not open anymore"
exit 1
fi
mergeable=$(jq -r .mergeable <<<"$prInfo")
if [[ "$mergeable" == "null" ]]; then
if ((retryCount == 0)); then
log "Not retrying anymore. It's likely that GitHub is having internal issues: check https://www.githubstatus.com/"
exit 3
else
((retryCount -= 1)) || true
# null indicates that GitHub is still computing whether it's mergeable
# Wait a couple seconds before trying again
log "GitHub is still computing whether this PR can be merged, waiting $retryInterval seconds before trying again ($retryCount retries left)"
sleep "$retryInterval"
((retryInterval *= 2)) || true
fi
else
break
fi
done
if [[ "$mergeable" == "true" ]]; then
echo "merge-commit-sha=$(jq -r .merge_commit_sha <<<"$prInfo")" >> "$GITHUB_OUTPUT"
else
echo "# 🚨 The PR has a merge conflict!" >> "$GITHUB_STEP_SUMMARY"
exit 2
fi

View File

@ -25,7 +25,7 @@ jobs:
with:
ref: ${{ github.event.pull_request.head.sha }}
- name: Create backport PRs
uses: korthout/backport-action@v3.1.0
uses: korthout/backport-action@v3.2.0
with:
# Config README: https://github.com/korthout/backport-action#backport-action
pull_description: |-

239
.github/workflows/blocked-prs.yml vendored Normal file
View File

@ -0,0 +1,239 @@
name: Blocked/Stacked Pull Requests Automation
on:
pull_request_target:
types:
- opened
- reopened
- edited
- synchronize
workflow_dispatch:
inputs:
pr_id:
description: Local Pull Request number to work on
required: true
type: number
jobs:
blocked_status:
name: Check Blocked Status
runs-on: ubuntu-latest
steps:
- name: Generate token
id: generate-token
uses: actions/create-github-app-token@v2
with:
app-id: ${{ vars.PULL_REQUEST_APP_ID }}
private-key: ${{ secrets.PULL_REQUEST_APP_PRIVATE_KEY }}
- name: Setup From Dispatch Event
if: github.event_name == 'workflow_dispatch'
id: dispatch_event_setup
env:
GH_TOKEN: ${{ steps.generate-token.outputs.token }}
PR_NUMBER: ${{ inputs.pr_id }}
run: |
# setup env for the rest of the workflow
OWNER=$(dirname "${{ github.repository }}")
REPO=$(basename "${{ github.repository }}")
PR_JSON=$(
gh api \
-H "Accept: application/vnd.github.raw+json" \
-H "X-GitHub-Api-Version: 2022-11-28" \
"/repos/$OWNER/$REPO/pulls/$PR_NUMBER"
)
echo "PR_JSON=$PR_JSON" >> "$GITHUB_ENV"
- name: Setup Environment
id: env_setup
env:
EVENT_PR_JSON: ${{ toJSON(github.event.pull_request) }}
run: |
# setup env for the rest of the workflow
PR_JSON=${PR_JSON:-"$EVENT_PR_JSON"}
{
echo "REPO=$(jq -r '.base.repo.name' <<< "$PR_JSON")"
echo "OWNER=$(jq -r '.base.repo.owner.login' <<< "$PR_JSON")"
echo "PR_NUMBER=$(jq -r '.number' <<< "$PR_JSON")"
echo "JOB_DATA=$(jq -c '
{
"repo": .base.repo.name,
"owner": .base.repo.owner.login,
"repoUrl": .base.repo.html_url,
"prNumber": .number,
"prHeadSha": .head.sha,
"prHeadLabel": .head.label,
"prBody": .body,
"prLabels": (reduce .labels[].name as $l ([]; . + [$l]))
}
' <<< "$PR_JSON")"
} >> "$GITHUB_ENV"
- name: Find Blocked/Stacked PRs in body
id: pr_ids
run: |
prs=$(
jq -c '
.prBody as $body
| (
$body |
reduce (
. | scan("blocked (?:by|on):? #([0-9]+)")
| map({
"type": "Blocked on",
"number": ( . | tonumber )
})
) as $i ([]; . + [$i[]])
) as $bprs
| (
$body |
reduce (
. | scan("stacked on:? #([0-9]+)")
| map({
"type": "Stacked on",
"number": ( . | tonumber )
})
) as $i ([]; . + [$i[]])
) as $sprs
| ($bprs + $sprs) as $prs
| {
"blocking": $prs,
"numBlocking": ( $prs | length),
}
' <<< "$JOB_DATA"
)
echo "prs=$prs" >> "$GITHUB_OUTPUT"
- name: Collect Blocked PR Data
id: blocking_data
if: fromJSON(steps.pr_ids.outputs.prs).numBlocking > 0
env:
GH_TOKEN: ${{ steps.generate-token.outputs.token }}
BLOCKING_PRS: ${{ steps.pr_ids.outputs.prs }}
run: |
blocked_pr_data=$(
while read -r pr_data ; do
gh api \
-H "Accept: application/vnd.github+json" \
-H "X-GitHub-Api-Version: 2022-11-28" \
"/repos/$OWNER/$REPO/pulls/$(jq -r '.number' <<< "$pr_data")" \
| jq -c --arg type "$(jq -r '.type' <<< "$pr_data")" \
'
. | {
"type": $type,
"number": .number,
"merged": .merged,
"labels": (reduce .labels[].name as $l ([]; . + [$l])),
"basePrUrl": .html_url,
"baseRepoName": .head.repo.name,
"baseRepoOwner": .head.repo.owner.login,
"baseRepoUrl": .head.repo.html_url,
"baseSha": .head.sha,
"baseRefName": .head.ref,
}
'
done < <(jq -c '.blocking[]' <<< "$BLOCKING_PRS") | jq -c -s
)
{
echo "data=$blocked_pr_data";
echo "all_merged=$(jq -r 'all(.[].merged; .)' <<< "$blocked_pr_data")";
echo "current_blocking=$(jq -c 'map( select( .merged | not ) | .number )' <<< "$blocked_pr_data" )";
} >> "$GITHUB_OUTPUT"
- name: Add 'blocked' Label is 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)
continue-on-error: true
env:
GH_TOKEN: ${{ steps.generate-token.outputs.token }}
run: |
gh -R ${{ github.repository }} issue edit --add-label 'blocked' "$PR_NUMBER"
- name: Remove 'blocked' Label if All Dependencies Are Merged
id: unlabel_blocked
if: fromJSON(steps.pr_ids.outputs.prs).numBlocking > 0 && 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 --remove-label 'blocked' "$PR_NUMBER"
- name: Apply 'blocking' Label to Unmerged Dependencies
id: label_blocking
if: fromJSON(steps.pr_ids.outputs.prs).numBlocking > 0
continue-on-error: true
env:
GH_TOKEN: ${{ steps.generate-token.outputs.token }}
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
done < <(jq -c '.[]' <<< "$BLOCKING_ISSUES")
- name: Apply Blocking PR Status Check
id: blocked_check
if: fromJSON(steps.pr_ids.outputs.prs).numBlocking > 0
continue-on-error: true
env:
GH_TOKEN: ${{ steps.generate-token.outputs.token }}
BLOCKING_DATA: ${{ steps.blocking_data.outputs.data }}
run: |
pr_head_sha=$(jq -r '.prHeadSha' <<< "$JOB_DATA")
# create commit Status, overwrites previous identical context
while read -r pr_data ; do
DESC=$(
jq -r ' "Blocking PR #" + (.number | tostring) + " is " + (if .merged then "" else "not yet " end) + "merged"' <<< "$pr_data"
)
gh api \
--method POST \
-H "Accept: application/vnd.github+json" \
-H "X-GitHub-Api-Version: 2022-11-28" \
"/repos/${OWNER}/${REPO}/statuses/${pr_head_sha}" \
-f "state=$(jq -r 'if .merged then "success" else "failure" end' <<< "$pr_data")" \
-f "target_url=$(jq -r '.basePrUrl' <<< "$pr_data" )" \
-f "description=$DESC" \
-f "context=ci/blocking-pr-check:$(jq '.number' <<< "$pr_data")"
done < <(jq -c '.[]' <<< "$BLOCKING_DATA")
- name: Context Comment
id: generate-comment
if: fromJSON(steps.pr_ids.outputs.prs).numBlocking > 0
continue-on-error: true
env:
BLOCKING_DATA: ${{ steps.blocking_data.outputs.data }}
run: |
COMMENT_PATH="$(pwd)/temp_comment_file.txt"
echo '<h3>PR Dependencies :pushpin:</h3>' > "$COMMENT_PATH"
echo >> "$COMMENT_PATH"
pr_head_label=$(jq -r '.prHeadLabel' <<< "$JOB_DATA")
while read -r pr_data ; do
base_pr=$(jq -r '.number' <<< "$pr_data")
base_ref_name=$(jq -r '.baseRefName' <<< "$pr_data")
base_repo_owner=$(jq -r '.baseRepoOwner' <<< "$pr_data")
base_repo_name=$(jq -r '.baseRepoName' <<< "$pr_data")
compare_url="https://github.com/$base_repo_owner/$base_repo_name/compare/$base_ref_name...$pr_head_label"
status=$(jq -r 'if .merged then ":heavy_check_mark: Merged" else ":x: Not Merged" end' <<< "$pr_data")
type=$(jq -r '.type' <<< "$pr_data")
echo " - $type #$base_pr $status [(compare)]($compare_url)" >> "$COMMENT_PATH"
done < <(jq -c '.[]' <<< "$BLOCKING_DATA")
{
echo 'body<<EOF';
cat "${COMMENT_PATH}";
echo 'EOF';
} >> "$GITHUB_OUTPUT"
- name: 💬 PR Comment
if: fromJSON(steps.pr_ids.outputs.prs).numBlocking > 0
continue-on-error: true
env:
GH_TOKEN: ${{ steps.generate-token.outputs.token }}
COMMENT_BODY: ${{ steps.generate-comment.outputs.body }}
run: |
gh -R ${{ github.repository }} issue comment "$PR_NUMBER" \
--body "$COMMENT_BODY" \
--create-if-none \
--edit-last

View File

@ -39,9 +39,6 @@ on:
APPLE_NOTARIZE_PASSWORD:
description: Password used for notarizing macOS builds
required: false
CACHIX_AUTH_TOKEN:
description: Private token for authenticating against Cachix cache
required: false
GPG_PRIVATE_KEY:
description: Private key for AppImage signing
required: false
@ -55,19 +52,15 @@ jobs:
fail-fast: false
matrix:
include:
- os: ubuntu-20.04
qt_ver: 5
qt_host: linux
qt_arch: ""
qt_version: "5.12.8"
qt_modules: "qtnetworkauth"
- os: ubuntu-20.04
- os: ubuntu-22.04
qt_ver: 6
qt_host: linux
qt_arch: ""
qt_version: "6.2.4"
qt_version: "6.8.1"
qt_modules: "qt5compat qtimageformats qtnetworkauth"
linuxdeploy_hash: "4648f278ab3ef31f819e67c30d50f462640e5365a77637d7e6f2ad9fd0b4522a linuxdeploy-x86_64.AppImage"
linuxdeploy_qt_hash: "15106be885c1c48a021198e7e1e9a48ce9d02a86dd0a1848f00bdbf3c1c92724 linuxdeploy-plugin-qt-x86_64.AppImage"
appimageupdate_hash: "f1747cf60058e99f1bb9099ee9787d16c10241313b7acec81810ea1b1e568c11 AppImageUpdate-x86_64.AppImage"
- os: windows-2022
name: "Windows-MinGW-w64"
@ -80,9 +73,9 @@ jobs:
architecture: "x64"
vcvars_arch: "amd64"
qt_ver: 6
qt_host: windows
qt_arch: ""
qt_version: "6.7.3"
qt_host: "windows"
qt_arch: "win64_msvc2022_64"
qt_version: "6.8.1"
qt_modules: "qt5compat qtimageformats qtnetworkauth"
nscurl_tag: "v24.9.26.122"
nscurl_sha256: "AEE6C4BE3CB6455858E9C1EE4B3AFE0DB9960FA03FE99CCDEDC28390D57CCBB0"
@ -93,9 +86,9 @@ jobs:
architecture: "arm64"
vcvars_arch: "amd64_arm64"
qt_ver: 6
qt_host: windows
qt_arch: "win64_msvc2019_arm64"
qt_version: "6.7.3"
qt_host: "windows"
qt_arch: "win64_msvc2022_arm64_cross_compiled"
qt_version: "6.8.1"
qt_modules: "qt5compat qtimageformats qtnetworkauth"
nscurl_tag: "v24.9.26.122"
nscurl_sha256: "AEE6C4BE3CB6455858E9C1EE4B3AFE0DB9960FA03FE99CCDEDC28390D57CCBB0"
@ -106,17 +99,9 @@ jobs:
qt_ver: 6
qt_host: mac
qt_arch: ""
qt_version: "6.7.3"
qt_version: "6.8.1"
qt_modules: "qt5compat qtimageformats qtnetworkauth"
- os: macos-14
name: macOS-Legacy
macosx_deployment_target: 10.13
qt_ver: 5
qt_host: mac
qt_version: "5.15.2"
qt_modules: "qtnetworkauth"
runs-on: ${{ matrix.os }}
env:
@ -167,13 +152,19 @@ jobs:
- name: Setup ccache
if: (runner.os != 'Windows' || matrix.msystem == '') && inputs.build_type == 'Debug'
uses: hendrikmuhs/ccache-action@v1.2.14
uses: hendrikmuhs/ccache-action@v1.2.18
with:
key: ${{ matrix.os }}-qt${{ matrix.qt_ver }}-${{ matrix.architecture }}
- name: Use ccache on Debug builds only
if: inputs.build_type == 'Debug'
shell: bash
run: |
echo "CCACHE_VAR=ccache" >> $GITHUB_ENV
- name: Retrieve ccache cache (Windows MinGW-w64)
if: runner.os == 'Windows' && matrix.msystem != '' && inputs.build_type == 'Debug'
uses: actions/cache@v4.1.1
uses: actions/cache@v4.2.3
with:
path: '${{ github.workspace }}\.ccache'
key: ${{ matrix.os }}-mingw-w64-ccache-${{ github.run_id }}
@ -190,11 +181,16 @@ jobs:
ccache -p # Show config
ccache -z # Zero stats
- name: Use ccache on Debug builds only
if: inputs.build_type == 'Debug'
shell: bash
- name: Configure ccache (Windows MSVC)
if: ${{ runner.os == 'Windows' && matrix.msystem == '' && inputs.build_type == 'Debug' }}
run: |
echo "CCACHE_VAR=ccache" >> $GITHUB_ENV
# https://github.com/ccache/ccache/wiki/MS-Visual-Studio (I coudn't figure out the compiler prefix)
Copy-Item C:/ProgramData/chocolatey/lib/ccache/tools/ccache-4.7.1-windows-x86_64/ccache.exe -Destination C:/ProgramData/chocolatey/lib/ccache/tools/ccache-4.7.1-windows-x86_64/cl.exe
echo "CLToolExe=cl.exe" >> $env:GITHUB_ENV
echo "CLToolPath=C:/ProgramData/chocolatey/lib/ccache/tools/ccache-4.7.1-windows-x86_64/" >> $env:GITHUB_ENV
echo "TrackFileAccess=false" >> $env:GITHUB_ENV
# Needed for ccache, but also speeds up compile
echo "UseMultiToolTask=true" >> $env:GITHUB_ENV
- name: Set short version
shell: bash
@ -206,7 +202,7 @@ jobs:
if: runner.os == 'Linux'
run: |
sudo apt-get -y update
sudo apt-get -y install ninja-build extra-cmake-modules scdoc appstream
sudo apt-get -y install ninja-build extra-cmake-modules scdoc appstream libxcb-cursor-dev
- name: Install Dependencies (macOS)
if: runner.os == 'macOS'
@ -216,14 +212,14 @@ jobs:
- name: Install host Qt (Windows MSVC arm64)
if: runner.os == 'Windows' && matrix.architecture == 'arm64'
uses: jurplel/install-qt-action@v3
uses: jurplel/install-qt-action@v4
with:
aqtversion: "==3.1.*"
py7zrversion: ">=0.20.2"
version: ${{ matrix.qt_version }}
host: "windows"
target: "desktop"
arch: ""
arch: ${{ matrix.qt_arch }}
modules: ${{ matrix.qt_modules }}
cache: ${{ inputs.is_qt_cached }}
cache-key-prefix: host-qt-arm64-windows
@ -232,7 +228,7 @@ jobs:
- name: Install Qt (macOS, Linux & Windows MSVC)
if: matrix.msystem == ''
uses: jurplel/install-qt-action@v3
uses: jurplel/install-qt-action@v4
with:
aqtversion: "==3.1.*"
py7zrversion: ">=0.20.2"
@ -251,20 +247,27 @@ jobs:
arch: ${{ matrix.vcvars_arch }}
- name: Prepare AppImage (Linux)
if: runner.os == 'Linux' && matrix.qt_ver != 5
if: runner.os == 'Linux'
env:
APPIMAGEUPDATE_HASH: ${{ matrix.appimageupdate_hash }}
LINUXDEPLOY_HASH: ${{ matrix.linuxdeploy_hash }}
LINUXDEPLOY_QT_HASH: ${{ matrix.linuxdeploy_qt_hash }}
run: |
wget "https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-x86_64.AppImage"
wget "https://github.com/linuxdeploy/linuxdeploy-plugin-appimage/releases/download/continuous/linuxdeploy-plugin-appimage-x86_64.AppImage"
wget "https://github.com/linuxdeploy/linuxdeploy-plugin-qt/releases/download/continuous/linuxdeploy-plugin-qt-x86_64.AppImage"
wget "https://github.com/linuxdeploy/linuxdeploy/releases/download/1-alpha-20250213-2/linuxdeploy-x86_64.AppImage"
wget "https://github.com/linuxdeploy/linuxdeploy-plugin-qt/releases/download/1-alpha-20250213-1/linuxdeploy-plugin-qt-x86_64.AppImage"
wget "https://github.com/AppImageCommunity/AppImageUpdate/releases/download/continuous/AppImageUpdate-x86_64.AppImage"
wget "https://github.com/AppImageCommunity/AppImageUpdate/releases/download/2.0.0-alpha-1-20241225/AppImageUpdate-x86_64.AppImage"
sha256sum -c - <<< "$LINUXDEPLOY_HASH"
sha256sum -c - <<< "$LINUXDEPLOY_QT_HASH"
sha256sum -c - <<< "$APPIMAGEUPDATE_HASH"
sudo apt install libopengl0
- name: Add QT_HOST_PATH var (Windows MSVC arm64)
if: runner.os == 'Windows' && matrix.architecture == 'arm64'
run: |
echo "QT_HOST_PATH=${{ github.workspace }}\HostQt\Qt\${{ matrix.qt_version }}\msvc2019_64" >> $env:GITHUB_ENV
echo "QT_HOST_PATH=${{ github.workspace }}\HostQt\Qt\${{ matrix.qt_version }}\msvc2022_64" >> $env:GITHUB_ENV
- name: Setup java (macOS)
if: runner.os == 'macOS'
@ -277,15 +280,10 @@ jobs:
##
- name: Configure CMake (macOS)
if: runner.os == 'macOS' && matrix.qt_ver == 6
if: runner.os == 'macOS'
run: |
cmake -S . -B ${{ env.BUILD_DIR }} -DCMAKE_INSTALL_PREFIX=${{ env.INSTALL_DIR }} -DCMAKE_BUILD_TYPE=${{ inputs.build_type }} -DENABLE_LTO=ON -DLauncher_ENABLE_JAVA_DOWNLOADER=ON -DLauncher_BUILD_PLATFORM=official -DCMAKE_C_COMPILER_LAUNCHER=${{ env.CCACHE_VAR }} -DCMAKE_CXX_COMPILER_LAUNCHER=${{ env.CCACHE_VAR }} -DLauncher_QT_VERSION_MAJOR=${{ matrix.qt_ver }} -DCMAKE_OSX_ARCHITECTURES="x86_64;arm64" -G Ninja
- name: Configure CMake (macOS-Legacy)
if: runner.os == 'macOS' && matrix.qt_ver == 5
run: |
cmake -S . -B ${{ env.BUILD_DIR }} -DCMAKE_INSTALL_PREFIX=${{ env.INSTALL_DIR }} -DCMAKE_BUILD_TYPE=${{ inputs.build_type }} -DENABLE_LTO=ON -DLauncher_ENABLE_JAVA_DOWNLOADER=ON -DLauncher_BUILD_PLATFORM=official -DCMAKE_C_COMPILER_LAUNCHER=${{ env.CCACHE_VAR }} -DCMAKE_CXX_COMPILER_LAUNCHER=${{ env.CCACHE_VAR }} -DLauncher_QT_VERSION_MAJOR=${{ matrix.qt_ver }} -DMACOSX_SPARKLE_UPDATE_PUBLIC_KEY="" -DMACOSX_SPARKLE_UPDATE_FEED_URL="" -DCMAKE_OSX_ARCHITECTURES="x86_64" -G Ninja
- name: Configure CMake (Windows MinGW-w64)
if: runner.os == 'Windows' && matrix.msystem != ''
shell: msys2 {0}
@ -293,19 +291,14 @@ jobs:
cmake -S . -B ${{ env.BUILD_DIR }} -DCMAKE_INSTALL_PREFIX=${{ env.INSTALL_DIR }} -DCMAKE_BUILD_TYPE=${{ inputs.build_type }} -DENABLE_LTO=ON -DLauncher_ENABLE_JAVA_DOWNLOADER=ON -DLauncher_BUILD_PLATFORM=official -DCMAKE_C_COMPILER_LAUNCHER=${{ env.CCACHE_VAR }} -DCMAKE_CXX_COMPILER_LAUNCHER=${{ env.CCACHE_VAR }} -DLauncher_QT_VERSION_MAJOR=6 -DCMAKE_OBJDUMP=/mingw64/bin/objdump.exe -DLauncher_BUILD_ARTIFACT=${{ matrix.name }}-Qt${{ matrix.qt_ver }} -G Ninja
- name: Configure CMake (Windows MSVC)
if: runner.os == 'Windows' && matrix.msystem == ''
if: runner.os == 'Windows' && matrix.msystem == '' && matrix.architecture != 'arm64'
run: |
cmake -S . -B ${{ env.BUILD_DIR }} -DCMAKE_INSTALL_PREFIX=${{ env.INSTALL_DIR }} -DCMAKE_BUILD_TYPE=${{ inputs.build_type }} -DENABLE_LTO=ON -DLauncher_ENABLE_JAVA_DOWNLOADER=ON -DLauncher_BUILD_PLATFORM=official -DLauncher_QT_VERSION_MAJOR=${{ matrix.qt_ver }} -DCMAKE_MSVC_RUNTIME_LIBRARY="MultiThreadedDLL" -DLauncher_FORCE_BUNDLED_LIBS=ON -DLauncher_BUILD_ARTIFACT=${{ matrix.name }}-Qt${{ matrix.qt_ver }} -G Ninja
- name: Configure CMake (Windows MSVC arm64)
if: runner.os == 'Windows' && matrix.msystem == '' && matrix.architecture == 'arm64'
run: |
cmake -S . -B ${{ env.BUILD_DIR }} -DCMAKE_INSTALL_PREFIX=${{ env.INSTALL_DIR }} -DCMAKE_BUILD_TYPE=${{ inputs.build_type }} -DENABLE_LTO=ON -DLauncher_ENABLE_JAVA_DOWNLOADER=ON -DLauncher_BUILD_PLATFORM=official -DLauncher_QT_VERSION_MAJOR=${{ matrix.qt_ver }} -DCMAKE_MSVC_RUNTIME_LIBRARY="MultiThreadedDLL" -A${{ matrix.architecture}} -DLauncher_FORCE_BUNDLED_LIBS=ON -DLauncher_BUILD_ARTIFACT=${{ matrix.name }}-Qt${{ matrix.qt_ver }}
# https://github.com/ccache/ccache/wiki/MS-Visual-Studio (I coudn't figure out the compiler prefix)
if ("${{ env.CCACHE_VAR }}")
{
Copy-Item C:/ProgramData/chocolatey/lib/ccache/tools/ccache-4.7.1-windows-x86_64/ccache.exe -Destination C:/ProgramData/chocolatey/lib/ccache/tools/ccache-4.7.1-windows-x86_64/cl.exe
echo "CLToolExe=cl.exe" >> $env:GITHUB_ENV
echo "CLToolPath=C:/ProgramData/chocolatey/lib/ccache/tools/ccache-4.7.1-windows-x86_64/" >> $env:GITHUB_ENV
echo "TrackFileAccess=false" >> $env:GITHUB_ENV
}
# Needed for ccache, but also speeds up compile
echo "UseMultiToolTask=true" >> $env:GITHUB_ENV
- name: Configure CMake (Linux)
if: runner.os == 'Linux'
@ -380,11 +373,13 @@ jobs:
if [ -n '${{ secrets.APPLE_CODESIGN_ID }}' ]; then
APPLE_CODESIGN_ID='${{ secrets.APPLE_CODESIGN_ID }}'
ENTITLEMENTS_FILE='../program_info/App.entitlements'
else
APPLE_CODESIGN_ID='-'
ENTITLEMENTS_FILE='../program_info/AdhocSignedApp.entitlements'
fi
sudo codesign --sign "$APPLE_CODESIGN_ID" --deep --force --entitlements "../program_info/App.entitlements" --options runtime "PrismLauncher.app/Contents/MacOS/prismlauncher"
sudo codesign --sign "$APPLE_CODESIGN_ID" --deep --force --entitlements "$ENTITLEMENTS_FILE" --options runtime "PrismLauncher.app/Contents/MacOS/prismlauncher"
mv "PrismLauncher.app" "Prism Launcher.app"
- name: Notarize (macOS)
@ -410,9 +405,8 @@ jobs:
if: matrix.name == 'macOS'
run: |
if [ '${{ secrets.SPARKLE_ED25519_KEY }}' != '' ]; then
brew install openssl@3
echo '${{ secrets.SPARKLE_ED25519_KEY }}' > ed25519-priv.pem
signature=$(/usr/local/opt/openssl@3/bin/openssl pkeyutl -sign -rawin -in ${{ github.workspace }}/PrismLauncher.zip -inkey ed25519-priv.pem | openssl base64 | tr -d \\n)
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)
rm ed25519-priv.pem
cat >> $GITHUB_STEP_SUMMARY << EOF
### Artifact Information :information_source:
@ -501,7 +495,7 @@ jobs:
}
- name: Package AppImage (Linux)
if: runner.os == 'Linux' && matrix.qt_ver != 5
if: runner.os == 'Linux'
shell: bash
env:
GPG_PRIVATE_KEY: ${{ secrets.GPG_PRIVATE_KEY }}
@ -520,8 +514,8 @@ jobs:
cp -r ${{ runner.workspace }}/Qt/${{ matrix.qt_version }}/gcc_64/plugins/iconengines/* ${{ env.INSTALL_APPIMAGE_DIR }}/usr/plugins/iconengines
cp /usr/lib/x86_64-linux-gnu/libcrypto.so.1.1 ${{ env.INSTALL_APPIMAGE_DIR }}/usr/lib/
cp /usr/lib/x86_64-linux-gnu/libssl.so.1.1 ${{ env.INSTALL_APPIMAGE_DIR }}/usr/lib/
cp /usr/lib/x86_64-linux-gnu/libcrypto.so.* ${{ env.INSTALL_APPIMAGE_DIR }}/usr/lib/
cp /usr/lib/x86_64-linux-gnu/libssl.so.* ${{ env.INSTALL_APPIMAGE_DIR }}/usr/lib/
cp /usr/lib/x86_64-linux-gnu/libOpenGL.so.0* ${{ env.INSTALL_APPIMAGE_DIR }}/usr/lib/
LD_LIBRARY_PATH="${LD_LIBRARY_PATH}:${{ env.INSTALL_APPIMAGE_DIR }}/usr/lib"
@ -556,9 +550,9 @@ jobs:
mkdir ${{ env.INSTALL_PORTABLE_DIR }}/lib
cp /lib/x86_64-linux-gnu/libbz2.so.1.0 ${{ env.INSTALL_PORTABLE_DIR }}/lib
cp /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0 ${{ env.INSTALL_PORTABLE_DIR }}/lib
cp /usr/lib/x86_64-linux-gnu/libcrypto.so.1.1 ${{ env.INSTALL_PORTABLE_DIR }}/lib
cp /usr/lib/x86_64-linux-gnu/libssl.so.1.1 ${{ env.INSTALL_PORTABLE_DIR }}/lib
cp /usr/lib/x86_64-linux-gnu/libffi.so.7 ${{ env.INSTALL_PORTABLE_DIR }}/lib
cp /usr/lib/x86_64-linux-gnu/libcrypto.so.* ${{ env.INSTALL_PORTABLE_DIR }}/lib
cp /usr/lib/x86_64-linux-gnu/libssl.so.* ${{ env.INSTALL_PORTABLE_DIR }}/lib
cp /usr/lib/x86_64-linux-gnu/libffi.so.*.* ${{ env.INSTALL_PORTABLE_DIR }}/lib
mv ${{ env.INSTALL_PORTABLE_DIR }}/bin/*.so* ${{ env.INSTALL_PORTABLE_DIR }}/lib
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
@ -597,29 +591,22 @@ jobs:
name: PrismLauncher-${{ matrix.name }}-Setup-${{ env.VERSION }}-${{ inputs.build_type }}
path: PrismLauncher-Setup.exe
- name: Upload binary tarball (Linux, portable, Qt 5)
if: runner.os == 'Linux' && matrix.qt_ver != 6
uses: actions/upload-artifact@v4
with:
name: PrismLauncher-${{ runner.os }}-Qt5-Portable-${{ env.VERSION }}-${{ inputs.build_type }}
path: PrismLauncher-portable.tar.gz
- name: Upload binary tarball (Linux, portable, Qt 6)
if: runner.os == 'Linux' && matrix.qt_ver != 5
- name: Upload binary tarball (Linux, portable)
if: runner.os == 'Linux'
uses: actions/upload-artifact@v4
with:
name: PrismLauncher-${{ runner.os }}-Qt6-Portable-${{ env.VERSION }}-${{ inputs.build_type }}
path: PrismLauncher-portable.tar.gz
- name: Upload AppImage (Linux)
if: runner.os == 'Linux' && matrix.qt_ver != 5
if: runner.os == 'Linux'
uses: actions/upload-artifact@v4
with:
name: PrismLauncher-${{ runner.os }}-${{ env.VERSION }}-${{ inputs.build_type }}-x86_64.AppImage
path: PrismLauncher-${{ runner.os }}-${{ env.VERSION }}-${{ inputs.build_type }}-x86_64.AppImage
- name: Upload AppImage Zsync (Linux)
if: runner.os == 'Linux' && matrix.qt_ver != 5
if: runner.os == 'Linux'
uses: actions/upload-artifact@v4
with:
name: PrismLauncher-${{ runner.os }}-${{ env.VERSION }}-${{ inputs.build_type }}-x86_64.AppImage.zsync
@ -630,71 +617,3 @@ jobs:
shell: msys2 {0}
run: |
ccache -s
flatpak:
runs-on: ubuntu-latest
container:
image: bilelmoussaoui/flatpak-github-actions:kde-6.7
options: --privileged
steps:
- name: Checkout
uses: actions/checkout@v4
if: inputs.build_type == 'Debug'
with:
submodules: "true"
- name: Build Flatpak (Linux)
if: inputs.build_type == 'Debug'
uses: flatpak/flatpak-github-actions/flatpak-builder@v6
with:
bundle: "Prism Launcher.flatpak"
manifest-path: flatpak/org.prismlauncher.PrismLauncher.yml
nix:
name: Nix (${{ matrix.system }})
strategy:
fail-fast: false
matrix:
include:
- os: ubuntu-22.04
system: x86_64-linux
- os: macos-13
system: x86_64-darwin
- os: macos-14
system: aarch64-darwin
runs-on: ${{ matrix.os }}
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Install Nix
uses: cachix/install-nix-action@v30
# For PRs
- name: Setup Nix Magic Cache
uses: DeterminateSystems/magic-nix-cache-action@v8
# For in-tree builds
- name: Setup Cachix
uses: cachix/cachix-action@v15
with:
name: prismlauncher
authToken: ${{ secrets.CACHIX_AUTH_TOKEN }}
- name: Run flake checks
run: |
nix flake check --print-build-logs --show-trace
- name: Build debug package
if: ${{ inputs.build_type == 'Debug' }}
run: |
nix build --print-build-logs .#prismlauncher-debug
- name: Build release package
if: ${{ inputs.build_type != 'Debug' }}
run: |
nix build --print-build-logs .#prismlauncher

View File

@ -1,16 +1,49 @@
name: "CodeQL Code Scanning"
on: [ push, pull_request, workflow_dispatch ]
on:
push:
# NOTE: `!` doesn't work with `paths-ignore` :(
# So we a catch-all glob instead
# https://github.com/orgs/community/discussions/25369#discussioncomment-3247674
paths:
- "**"
- "!.github/**"
- ".github/workflows/codeql.yml"
- "!flatpak/"
- "!nix/"
- "!scripts/"
- "!.git*"
- "!.envrc"
- "!**.md"
- "COPYING.md"
- "!renovate.json"
pull_request:
# See above
paths:
- "**"
- "!.github/**"
- ".github/workflows/codeql.yml"
- "!flatpak/"
- "!nix/"
- "!scripts/"
- "!.git*"
- "!.envrc"
- "!**.md"
- "COPYING.md"
- "!renovate.json"
workflow_dispatch:
jobs:
CodeQL:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
submodules: 'true'
submodules: "true"
- name: Initialize CodeQL
uses: github/codeql-action/init@v3
@ -20,14 +53,25 @@ jobs:
languages: cpp, java
- name: Install Dependencies
run:
sudo apt-get -y update
run: sudo apt-get -y update
sudo apt-get -y install ninja-build extra-cmake-modules scdoc qtbase5-dev qtchooser qt5-qmake qtbase5-dev-tools libqt5core5a libqt5network5 libqt5gui5 libqt5networkauth5 libqt5networkauth5-dev
sudo apt-get -y install ninja-build extra-cmake-modules scdoc
- name: Install Qt
uses: jurplel/install-qt-action@v3
with:
aqtversion: "==3.1.*"
py7zrversion: ">=0.20.2"
version: "6.8.1"
host: "linux"
target: "desktop"
arch: ""
modules: "qt5compat qtimageformats qtnetworkauth"
tools: ""
- name: Configure and Build
run: |
cmake -S . -B build -DCMAKE_INSTALL_PREFIX=/usr -DLauncher_QT_VERSION_MAJOR=5 -G Ninja
cmake -S . -B build -DCMAKE_INSTALL_PREFIX=/usr -G Ninja
cmake --build build

78
.github/workflows/flatpak.yml vendored Normal file
View File

@ -0,0 +1,78 @@
name: Flatpak
on:
push:
# We don't do anything with these artifacts on releases. They go to Flathub
tags-ignore:
- "*"
# NOTE: `!` doesn't work with `paths-ignore` :(
# So we a catch-all glob instead
# https://github.com/orgs/community/discussions/25369#discussioncomment-3247674
paths:
- "**"
- "!.github/**"
- ".github/workflows/flatpak.yml"
- "!nix/"
- "!scripts/"
- "!.git*"
- "!.envrc"
- "!**.md"
- "COPYING.md"
- "!renovate.json"
pull_request:
# See above
paths:
- "**"
- "!.github/**"
- ".github/workflows/flatpak.yml"
- "!nix/"
- "!scripts/"
- "!.git*"
- "!.envrc"
- "!**.md"
- "COPYING.md"
- "!renovate.json"
workflow_dispatch:
permissions:
contents: read
jobs:
build:
name: Build (${{ matrix.arch }})
strategy:
fail-fast: false
matrix:
include:
- os: ubuntu-22.04
arch: x86_64
- os: ubuntu-22.04-arm
arch: aarch64
runs-on: ${{ matrix.os }}
container:
image: ghcr.io/flathub-infra/flatpak-github-actions:kde-6.8
options: --privileged
steps:
- name: Checkout repository
uses: actions/checkout@v4
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 }}

62
.github/workflows/merge-blocking-pr.yml vendored Normal file
View File

@ -0,0 +1,62 @@
name: Merged Blocking Pull Request Automation
on:
pull_request_target:
types:
- closed
workflow_dispatch:
inputs:
pr_id:
description: Local Pull Request number to work on
required: true
type: number
jobs:
update-blocked-status:
name: Update Blocked Status
runs-on: ubuntu-latest
# 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') }}
steps:
- name: Generate token
id: generate-token
uses: actions/create-github-app-token@v2
with:
app-id: ${{ vars.PULL_REQUEST_APP_ID }}
private-key: ${{ secrets.PULL_REQUEST_APP_PRIVATE_KEY }}
- name: Gather Dependent PRs
id: gather_deps
env:
GH_TOKEN: ${{ steps.generate-token.outputs.token }}
PR_NUMBER: ${{ inputs.pr_id || github.event.pull_request.number }}
run: |
blocked_prs=$(
gh -R ${{ github.repository }} pr list --label 'blocked' --json 'number,body' \
| jq -c --argjson pr "$PR_NUMBER" '
reduce ( .[] | select(
.body |
scan("(?:blocked (?:by|on)|stacked on):? #([0-9]+)") |
map(tonumber) |
any(.[]; . == $pr)
)) as $i ([]; . + [$i])
'
)
{
echo "deps=$blocked_prs"
echo "numdeps=$(jq -r '. | length' <<< "$blocked_prs")"
} >> "$GITHUB_OUTPUT"
- name: Trigger Blocked PR Workflows for Dependants
if: fromJSON(steps.gather_deps.outputs.numdeps) > 0
env:
GH_TOKEN: ${{ steps.generate-token.outputs.token }}
DEPS: ${{ steps.gather_deps.outputs.deps }}
run: |
while read -r pr ; do
gh -R ${{ github.repository }} workflow run 'blocked-prs.yml' -r "${{ github.ref_name }}" -f pr_id="$pr"
done < <(jq -c '.[].number' <<< "$DEPS")

121
.github/workflows/nix.yml vendored Normal file
View File

@ -0,0 +1,121 @@
name: Nix
on:
push:
tags:
- "*"
# NOTE: `!` doesn't work with `paths-ignore` :(
# So we a catch-all glob instead
# https://github.com/orgs/community/discussions/25369#discussioncomment-3247674
paths:
- "**"
- "!.github/**"
- ".github/workflows/nix.yml"
- "!flatpak/"
- "!scripts/"
- "!.git*"
- "!.envrc"
- "!**.md"
- "COPYING.md"
- "!renovate.json"
pull_request_target:
paths:
- "**"
- "!.github/**"
- ".github/workflows/nix.yml"
- "!flatpak/"
- "!scripts/"
- "!.git*"
- "!.envrc"
- "!**.md"
- "COPYING.md"
- "!renovate.json"
workflow_dispatch:
permissions:
contents: read
env:
DEBUG: ${{ github.ref_type != 'tag' }}
USE_DETERMINATE: ${{ github.event_name == 'pull_request' }}
jobs:
build:
name: Build (${{ matrix.system }})
strategy:
fail-fast: false
matrix:
include:
- os: ubuntu-22.04
system: x86_64-linux
- os: ubuntu-22.04-arm
system: aarch64-linux
- os: macos-13
system: x86_64-darwin
- os: macos-14
system: aarch64-darwin
runs-on: ${{ matrix.os }}
permissions:
id-token: write
steps:
- name: Get merge commit
if: ${{ github.event_name == 'pull_request_target' }}
id: merge-commit
uses: PrismLauncher/PrismLauncher/.github/actions/get-merge-commit@develop
with:
pull-request-id: ${{ github.event.number }}
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Checkout repository
uses: actions/checkout@v4
with:
ref: ${{ steps.merge-commit.outputs.merge-commit-sha || github.sha }}
- name: Install Nix
uses: DeterminateSystems/nix-installer-action@v17
with:
determinate: ${{ env.USE_DETERMINATE }}
# For PRs
- name: Setup Nix Magic Cache
if: ${{ env.USE_DETERMINATE == 'true' }}
uses: DeterminateSystems/flakehub-cache-action@v1
# For in-tree builds
- name: Setup Cachix
if: ${{ github.event_name == 'push' || github.event_name == 'workflow_dispatch' }}
uses: cachix/cachix-action@v16
with:
name: prismlauncher
authToken: ${{ secrets.CACHIX_AUTH_TOKEN }}
- name: Run Flake checks
run: |
nix flake check --print-build-logs --show-trace
- name: Build debug package
if: ${{ env.DEBUG == 'true' }}
run: |
nix build \
--no-link --print-build-logs --print-out-paths \
.#prismlauncher-debug >> "$GITHUB_STEP_SUMMARY"
- name: Build release package
if: ${{ env.DEBUG == 'false' }}
env:
TAG: ${{ github.ref_name }}
SYSTEM: ${{ matrix.system }}
run: |
nix build --no-link --print-out-paths .#prismlauncher \
| tee -a "$GITHUB_STEP_SUMMARY" \
| xargs cachix pin prismlauncher "$TAG"-"$SYSTEM"

View File

@ -1,13 +1,21 @@
name: Publish to WinGet
name: Publish
on:
release:
types: [released]
types: [ released ]
permissions:
contents: read
jobs:
publish:
winget:
name: Winget
runs-on: windows-latest
steps:
- uses: vedantmgoyal2009/winget-releaser@v2
- name: Publish on Winget
uses: vedantmgoyal2009/winget-releaser@v2
with:
identifier: PrismLauncher.PrismLauncher
version: ${{ github.event.release.tag_name }}

29
.github/workflows/stale.yml vendored Normal file
View File

@ -0,0 +1,29 @@
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@v9
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

@ -4,21 +4,39 @@ on:
push:
branches-ignore:
- "renovate/**"
paths-ignore:
- "**.md"
- "**/LICENSE"
- "flake.lock"
- "packages/**"
- ".github/ISSUE_TEMPLATE/**"
- ".markdownlint**"
# NOTE: `!` doesn't work with `paths-ignore` :(
# So we a catch-all glob instead
# https://github.com/orgs/community/discussions/25369#discussioncomment-3247674
paths:
- "**"
- "!.github/**"
- ".github/workflows/build.yml"
- ".github/workflows/trigger_builds.yml"
- "!flatpak/"
- "!nix/"
- "!scripts/"
- "!.git*"
- "!.envrc"
- "!**.md"
- "COPYING.md"
- "!renovate.json"
pull_request:
paths-ignore:
- "**.md"
- "**/LICENSE"
- "flake.lock"
- "packages/**"
- ".github/ISSUE_TEMPLATE/**"
- ".markdownlint**"
# See above
paths:
- "**"
- "!.github/**"
- ".github/workflows/build.yml"
- ".github/workflows/trigger_builds.yml"
- "!flatpak/"
- "!nix/"
- "!scripts/"
- "!.git*"
- "!.envrc"
- "!**.md"
- "COPYING.md"
- "!renovate.json"
workflow_dispatch:
jobs:
@ -38,6 +56,5 @@ jobs:
APPLE_NOTARIZE_APPLE_ID: ${{ secrets.APPLE_NOTARIZE_APPLE_ID }}
APPLE_NOTARIZE_TEAM_ID: ${{ secrets.APPLE_NOTARIZE_TEAM_ID }}
APPLE_NOTARIZE_PASSWORD: ${{ secrets.APPLE_NOTARIZE_PASSWORD }}
CACHIX_AUTH_TOKEN: ${{ secrets.CACHIX_AUTH_TOKEN }}
GPG_PRIVATE_KEY: ${{ secrets.GPG_PRIVATE_KEY }}
GPG_PRIVATE_KEY_ID: ${{ secrets.GPG_PRIVATE_KEY_ID }}

View File

@ -22,7 +22,6 @@ jobs:
APPLE_NOTARIZE_APPLE_ID: ${{ secrets.APPLE_NOTARIZE_APPLE_ID }}
APPLE_NOTARIZE_TEAM_ID: ${{ secrets.APPLE_NOTARIZE_TEAM_ID }}
APPLE_NOTARIZE_PASSWORD: ${{ secrets.APPLE_NOTARIZE_PASSWORD }}
CACHIX_AUTH_TOKEN: ${{ secrets.CACHIX_AUTH_TOKEN }}
GPG_PRIVATE_KEY: ${{ secrets.GPG_PRIVATE_KEY }}
GPG_PRIVATE_KEY_ID: ${{ secrets.GPG_PRIVATE_KEY_ID }}
@ -47,10 +46,8 @@ jobs:
run: |
mv ${{ github.workspace }}/PrismLauncher-source PrismLauncher-${{ env.VERSION }}
mv PrismLauncher-Linux-Qt6-Portable*/PrismLauncher-portable.tar.gz PrismLauncher-Linux-Qt6-Portable-${{ env.VERSION }}.tar.gz
mv PrismLauncher-Linux-Qt5-Portable*/PrismLauncher-portable.tar.gz PrismLauncher-Linux-Qt5-Portable-${{ env.VERSION }}.tar.gz
mv PrismLauncher-*.AppImage/PrismLauncher-*.AppImage PrismLauncher-Linux-x86_64.AppImage
mv PrismLauncher-*.AppImage.zsync/PrismLauncher-*.AppImage.zsync PrismLauncher-Linux-x86_64.AppImage.zsync
mv PrismLauncher-macOS-Legacy*/PrismLauncher.zip PrismLauncher-macOS-Legacy-${{ env.VERSION }}.zip
mv PrismLauncher-macOS*/PrismLauncher.zip PrismLauncher-macOS-${{ env.VERSION }}.zip
tar --exclude='.git' -czf PrismLauncher-${{ env.VERSION }}.tar.gz PrismLauncher-${{ env.VERSION }}
@ -91,7 +88,6 @@ jobs:
draft: true
prerelease: false
files: |
PrismLauncher-Linux-Qt5-Portable-${{ env.VERSION }}.tar.gz
PrismLauncher-Linux-x86_64.AppImage
PrismLauncher-Linux-x86_64.AppImage.zsync
PrismLauncher-Linux-Qt6-Portable-${{ env.VERSION }}.tar.gz
@ -105,5 +101,4 @@ jobs:
PrismLauncher-Windows-MSVC-Portable-${{ env.VERSION }}.zip
PrismLauncher-Windows-MSVC-Setup-${{ env.VERSION }}.exe
PrismLauncher-macOS-${{ env.VERSION }}.zip
PrismLauncher-macOS-Legacy-${{ env.VERSION }}.zip
PrismLauncher-${{ env.VERSION }}.tar.gz

View File

@ -17,7 +17,7 @@ jobs:
steps:
- uses: actions/checkout@v4
- uses: cachix/install-nix-action@08dcb3a5e62fa31e2da3d490afc4176ef55ecd72 # v30
- uses: cachix/install-nix-action@754537aaedb35f72ab11a60cc162c49ef3016495 # v31
- uses: DeterminateSystems/update-flake-lock@v24
with:

7
.gitignore vendored
View File

@ -21,6 +21,7 @@ CMakeCache.txt
/.vs
cmake-build-*/
Debug
compile_commands.json
# Build dirs
build
@ -47,8 +48,12 @@ run/
# Nix/NixOS
.direnv/
.pre-commit-config.yaml
## Used when manually invoking stdenv phases
outputs/
## Regular artifacts
result
result-*
repl-result-*
# Flatpak
.flatpak-builder

6
.gitmodules vendored
View File

@ -4,9 +4,6 @@
[submodule "libraries/tomlplusplus"]
path = libraries/tomlplusplus
url = https://github.com/marzer/tomlplusplus.git
[submodule "libraries/filesystem"]
path = libraries/filesystem
url = https://github.com/gulrak/filesystem
[submodule "libraries/libnbtplusplus"]
path = libraries/libnbtplusplus
url = https://github.com/PrismLauncher/libnbtplusplus.git
@ -22,3 +19,6 @@
[submodule "flatpak/shared-modules"]
path = flatpak/shared-modules
url = https://github.com/flathub/shared-modules.git
[submodule "libraries/qt-qrcodegenerator/QR-Code-generator"]
path = libraries/qt-qrcodegenerator/QR-Code-generator
url = https://github.com/nayuki/QR-Code-generator

View File

@ -78,13 +78,18 @@ else()
# 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}")
# -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()
endif()
endif()
# Fix build with Qt 5.13
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DQT_NO_DEPRECATED_WARNINGS=Y")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DQT_DISABLE_DEPRECATED_BEFORE=0x050C00")
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")
# Fix aarch64 build for toml++
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DTOML_ENABLE_FLOAT16=0")
@ -92,6 +97,12 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DTOML_ENABLE_FLOAT16=0")
# 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 STREQUAL "Ninja" AND CMAKE_BUILD_TYPE STREQUAL "Debug")
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
endif()
option(DEBUG_ADDRESS_SANITIZER "Enable Address Sanitizer in Debug builds" OFF)
# If this is a Debug build turn on address sanitiser
@ -106,14 +117,14 @@ if ((CMAKE_BUILD_TYPE STREQUAL "Debug" OR CMAKE_BUILD_TYPE STREQUAL "RelWithDebI
else()
# AppleClang and Clang
message(STATUS "Address Sanitizer available on Clang")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address -fno-omit-frame-pointer")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address -fno-omit-frame-pointer")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address -fno-omit-frame-pointer -fsanitize=undefined -fno-sanitize-recover=null")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address -fno-omit-frame-pointer -fsanitize=undefined -fno-sanitize-recover=null")
endif()
elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
# GCC
message(STATUS "Address Sanitizer available on GCC")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address -fno-omit-frame-pointer")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address -fno-omit-frame-pointer")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address -fno-omit-frame-pointer -fsanitize=undefined -fno-sanitize-recover")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address -fno-omit-frame-pointer -fsanitize=undefined -fno-sanitize-recover")
link_libraries("asan")
elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
message(STATUS "Address Sanitizer available on MSVC")
@ -180,12 +191,13 @@ set(Launcher_LOGIN_CALLBACK_URL "https://prismlauncher.org/successful-login" CAC
set(Launcher_FMLLIBS_BASE_URL "https://files.prismlauncher.org/fmllibs/" CACHE STRING "URL for FML Libraries.")
######## Set version numbers ########
set(Launcher_VERSION_MAJOR 9)
set(Launcher_VERSION_MAJOR 10)
set(Launcher_VERSION_MINOR 0)
set(Launcher_VERSION_PATCH 0)
set(Launcher_VERSION_NAME "${Launcher_VERSION_MAJOR}.${Launcher_VERSION_MINOR}")
set(Launcher_VERSION_NAME4 "${Launcher_VERSION_MAJOR}.${Launcher_VERSION_MINOR}.0.0")
set(Launcher_VERSION_NAME4_COMMA "${Launcher_VERSION_MAJOR},${Launcher_VERSION_MINOR},0,0")
set(Launcher_VERSION_NAME "${Launcher_VERSION_MAJOR}.${Launcher_VERSION_MINOR}.${Launcher_VERSION_PATCH}")
set(Launcher_VERSION_NAME4 "${Launcher_VERSION_MAJOR}.${Launcher_VERSION_MINOR}.${Launcher_VERSION_PATCH}.0")
set(Launcher_VERSION_NAME4_COMMA "${Launcher_VERSION_MAJOR},${Launcher_VERSION_MINOR},${Launcher_VERSION_PATCH},0")
# Build platform.
set(Launcher_BUILD_PLATFORM "unknown" CACHE STRING "A short string identifying the platform that this build was built for. Only used to display in the about dialog.")
@ -229,7 +241,7 @@ set(Launcher_ENABLE_JAVA_DOWNLOADER_DEFAULT ON)
# differing Linux/BSD/etc distributions. Downstream packagers should be explicitly opt-ing into this
# feature if they know it will work with their distribution.
if(UNIX AND NOT APPLE)
set(Launcher_ENABLE_JAVA_DOWNLOADER_DEFAULT OFF)
set(Launcher_ENABLE_JAVA_DOWNLOADER_DEFAULT OFF)
endif()
# Java downloader
@ -296,23 +308,11 @@ endif()
# Find the required Qt parts
include(QtVersionlessBackport)
if(Launcher_QT_VERSION_MAJOR EQUAL 5)
set(QT_VERSION_MAJOR 5)
find_package(Qt5 REQUIRED COMPONENTS Core Widgets Concurrent Network Test Xml NetworkAuth)
if(NOT Launcher_FORCE_BUNDLED_LIBS)
find_package(QuaZip-Qt5 1.3 QUIET)
endif()
if (NOT QuaZip-Qt5_FOUND)
set(QUAZIP_QT_MAJOR_VERSION ${QT_VERSION_MAJOR} CACHE STRING "Qt version to use (4, 5 or 6), defaults to ${QT_VERSION_MAJOR}" FORCE)
set(FORCE_BUNDLED_QUAZIP 1)
endif()
# Qt 6 sets these by default. Notably causes Windows APIs to use UNICODE strings.
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DUNICODE -D_UNICODE")
elseif(Launcher_QT_VERSION_MAJOR EQUAL 6)
if(Launcher_QT_VERSION_MAJOR EQUAL 6)
set(QT_VERSION_MAJOR 6)
find_package(Qt6 REQUIRED COMPONENTS Core CoreTools Widgets Concurrent Network Test Xml Core5Compat NetworkAuth)
find_package(Qt6 REQUIRED COMPONENTS Core CoreTools Widgets Concurrent Network Test Xml Core5Compat NetworkAuth OpenGL)
find_package(Qt6 COMPONENTS DBus)
list(APPEND Launcher_QT_DBUS Qt6::DBus)
list(APPEND Launcher_QT_LIBS Qt6::Core5Compat)
if(NOT Launcher_FORCE_BUNDLED_LIBS)
@ -326,29 +326,16 @@ else()
message(FATAL_ERROR "Qt version ${Launcher_QT_VERSION_MAJOR} is not supported")
endif()
if(Launcher_QT_VERSION_MAJOR EQUAL 5)
include(ECMQueryQt)
ecm_query_qt(QT_PLUGINS_DIR QT_INSTALL_PLUGINS)
ecm_query_qt(QT_LIBS_DIR QT_INSTALL_LIBS)
ecm_query_qt(QT_LIBEXECS_DIR QT_INSTALL_LIBEXECS)
else()
if(Launcher_QT_VERSION_MAJOR EQUAL 6)
set(QT_PLUGINS_DIR ${QT${QT_VERSION_MAJOR}_INSTALL_PREFIX}/${QT${QT_VERSION_MAJOR}_INSTALL_PLUGINS})
set(QT_LIBS_DIR ${QT${QT_VERSION_MAJOR}_INSTALL_PREFIX}/${QT${QT_VERSION_MAJOR}_INSTALL_LIBS})
set(QT_LIBEXECS_DIR ${QT${QT_VERSION_MAJOR}_INSTALL_PREFIX}/${QT${QT_VERSION_MAJOR}_INSTALL_LIBEXECS})
endif()
# NOTE: Qt 6 already sets this by default
if (Qt5_POSITION_INDEPENDENT_CODE)
SET(CMAKE_POSITION_INDEPENDENT_CODE ON)
endif()
if(NOT Launcher_FORCE_BUNDLED_LIBS)
# Find toml++
find_package(tomlplusplus 3.2.0 QUIET)
# Find ghc_filesystem
find_package(ghc_filesystem QUIET)
# Find cmark
find_package(cmark QUIET)
endif()
@ -366,7 +353,7 @@ set(Launcher_ENABLE_UPDATER NO)
set(Launcher_BUILD_UPDATER NO)
if (NOT APPLE AND (NOT Launcher_UPDATER_GITHUB_REPO STREQUAL "" AND NOT Launcher_BUILD_ARTIFACT STREQUAL ""))
set(Launcher_BUILD_UPDATER YES)
set(Launcher_BUILD_UPDATER YES)
endif()
if(NOT (UNIX AND APPLE))
@ -397,8 +384,8 @@ if(UNIX AND APPLE)
set(MACOSX_SPARKLE_UPDATE_PUBLIC_KEY "v55ZWWD6QlPoXGV6VLzOTZxZUggWeE51X8cRQyQh6vA=" CACHE STRING "Public key for Sparkle update feed")
set(MACOSX_SPARKLE_UPDATE_FEED_URL "https://prismlauncher.org/feed/appcast.xml" CACHE STRING "URL for Sparkle update feed")
set(MACOSX_SPARKLE_DOWNLOAD_URL "https://github.com/sparkle-project/Sparkle/releases/download/2.5.2/Sparkle-2.5.2.tar.xz" CACHE STRING "URL to Sparkle release archive")
set(MACOSX_SPARKLE_SHA256 "572dd67ae398a466f19f343a449e1890bac1ef74885b4739f68f979a8a89884b" CACHE STRING "SHA256 checksum for Sparkle release archive")
set(MACOSX_SPARKLE_DOWNLOAD_URL "https://github.com/sparkle-project/Sparkle/releases/download/2.6.4/Sparkle-2.6.4.tar.xz" CACHE STRING "URL to Sparkle release archive")
set(MACOSX_SPARKLE_SHA256 "50612a06038abc931f16011d7903b8326a362c1074dabccb718404ce8e585f0b" CACHE STRING "SHA256 checksum for Sparkle release archive")
set(MACOSX_SPARKLE_DIR "${CMAKE_BINARY_DIR}/frameworks/Sparkle")
# directories to look for dependencies
@ -488,6 +475,7 @@ 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
add_subdirectory(libraries/qt-qrcodegenerator) # qr code generator
if(FORCE_BUNDLED_ZLIB)
message(STATUS "Using bundled zlib")
@ -543,12 +531,6 @@ else()
endif()
add_subdirectory(libraries/gamemode)
add_subdirectory(libraries/murmur2) # Hash for usage with the CurseForge API
if (NOT ghc_filesystem_FOUND)
message(STATUS "Using bundled ghc_filesystem")
add_subdirectory(libraries/filesystem) # Implementation of std::filesystem for old C++, for usage in old macOS
else()
message(STATUS "Using system ghc_filesystem")
endif()
add_subdirectory(libraries/qdcss) # css parser
############################### Built Artifacts ###############################

View File

@ -2,16 +2,59 @@
## Code formatting
Try to follow the existing formatting.
If there is no existing formatting, you may use `clang-format` with our included `.clang-format` configuration.
All files are formatted with `clang-format` using the configuration in `.clang-format`. Ensure it is run on changed files before committing!
In general, in order of importance:
Please also follow the project's conventions for C++:
- Make sure your IDE is not messing up line endings or whitespace and avoid using linters.
- Prefer readability over dogma.
- Keep to the existing formatting.
- Indent with 4 space unless it's in a submodule.
- Keep lists (of arguments, parameters, initializers...) as lists, not paragraphs. It should either read from top to bottom, or left to right. Not both.
- Class and type names should be formatted as `PascalCase`: `MyClass`.
- Private or protected class data members should be formatted as `camelCase` prefixed with `m_`: `m_myCounter`.
- Private or protected `static` class data members should be formatted as `camelCase` prefixed with `s_`: `s_instance`.
- Public class data members should be formatted as `camelCase` without the prefix: `dateOfBirth`.
- 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`.
- Avoid inventing acronyms or abbreviations especially for a name of multiple words - like `tp` for `texturePack`.
Most of these rules are included in the `.clang-tidy` file, so you can run `clang-tidy` to check for any violations.
Here is what these conventions with the formatting configuration look like:
```c++
#define AWESOMENESS 10
constexpr double PI = 3.14159;
enum class PizzaToppings { HAM_AND_PINEAPPLE, OREO_AND_KETCHUP };
struct Person {
QString name;
QDateTime dateOfBirth;
long daysOld() const { return dateOfBirth.daysTo(QDateTime::currentDateTime()); }
};
class ImportantClass {
public:
void incrementCounter()
{
if (m_counter + 1 > MAX_COUNTER_VALUE)
throw std::runtime_error("Counter has reached limit!");
++m_counter;
}
int counter() const { return m_counter; }
private:
static constexpr int MAX_COUNTER_VALUE = 100;
int m_counter;
};
ImportantClass importantClassInstance;
```
If you see any names which do not follow these conventions, it is preferred that you leave them be - renames increase the number of changes therefore make reviewing harder and make your PR more prone to conflicts. However, if you're refactoring a whole class anyway, it's fine.
## Signing your work

View File

@ -1,7 +1,7 @@
## Prism Launcher
Prism Launcher - Minecraft Launcher
Copyright (C) 2022-2024 Prism Launcher Contributors
Copyright (C) 2022-2025 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
@ -108,7 +108,7 @@
Information on third party licenses used in MinGW-w64 can be found in its COPYING.MinGW-w64-runtime.txt.
## Qt 5/6
## Qt 6
Copyright (C) 2022 The Qt Company Ltd and other contributors.
Contact: https://www.qt.io/licensing
@ -362,28 +362,6 @@
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
## gulrak/filesystem
Copyright (c) 2018, Steffen Schümann <s.schuemann@pobox.com>
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.
## Breeze icons
Copyright (C) 2014 Uri Herrera <uri_herrera@nitrux.in> and others
@ -425,3 +403,12 @@
You should have received a copy of the GNU Lesser General Public
License along with this library. If not, see <http://www.gnu.org/licenses/>.
## qt-qrcodegenerator (`libraries/qt-qrcodegenerator`)
Copyright © 2024 Project Nayuki. (MIT License)
https://www.nayuki.io/page/qr-code-generator-library
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.

View File

@ -34,8 +34,8 @@
*/
#include <qstringliteral.h>
#include "BuildConfig.h"
#include <QObject>
#include "BuildConfig.h"
const Config BuildConfig;
@ -49,7 +49,7 @@ Config::Config()
LAUNCHER_DOMAIN = "@Launcher_Domain@";
LAUNCHER_CONFIGFILE = "@Launcher_ConfigFile@";
LAUNCHER_GIT = "@Launcher_Git@";
LAUNCHER_DESKTOPFILENAME = "@Launcher_DesktopFileName@";
LAUNCHER_APPID = "@Launcher_AppID@";
LAUNCHER_SVGFILENAME = "@Launcher_SVGFileName@";
USER_AGENT = "@Launcher_UserAgent@";
@ -58,6 +58,7 @@ Config::Config()
// Version information
VERSION_MAJOR = @Launcher_VERSION_MAJOR@;
VERSION_MINOR = @Launcher_VERSION_MINOR@;
VERSION_PATCH = @Launcher_VERSION_PATCH@;
BUILD_PLATFORM = "@Launcher_BUILD_PLATFORM@";
BUILD_ARTIFACT = "@Launcher_BUILD_ARTIFACT@";
@ -74,14 +75,13 @@ Config::Config()
MAC_SPARKLE_PUB_KEY = "@MACOSX_SPARKLE_UPDATE_PUBLIC_KEY@";
MAC_SPARKLE_APPCAST_URL = "@MACOSX_SPARKLE_UPDATE_FEED_URL@";
if (!MAC_SPARKLE_PUB_KEY.isEmpty() && !MAC_SPARKLE_APPCAST_URL.isEmpty())
{
if (!MAC_SPARKLE_PUB_KEY.isEmpty() && !MAC_SPARKLE_APPCAST_URL.isEmpty()) {
UPDATER_ENABLED = true;
} else if(!UPDATER_GITHUB_REPO.isEmpty() && !BUILD_ARTIFACT.isEmpty()) {
} else if (!UPDATER_GITHUB_REPO.isEmpty() && !BUILD_ARTIFACT.isEmpty()) {
UPDATER_ENABLED = true;
}
#cmakedefine01 Launcher_ENABLE_JAVA_DOWNLOADER
#cmakedefine01 Launcher_ENABLE_JAVA_DOWNLOADER
JAVA_DOWNLOADER_ENABLED = Launcher_ENABLE_JAVA_DOWNLOADER;
GIT_COMMIT = "@Launcher_GIT_COMMIT@";
@ -89,27 +89,19 @@ Config::Config()
GIT_REFSPEC = "@Launcher_GIT_REFSPEC@";
// Assume that builds outside of Git repos are "stable"
if (GIT_REFSPEC == QStringLiteral("GITDIR-NOTFOUND")
|| GIT_TAG == QStringLiteral("GITDIR-NOTFOUND")
|| GIT_REFSPEC == QStringLiteral("")
|| GIT_TAG == QStringLiteral("GIT-NOTFOUND"))
{
if (GIT_REFSPEC == QStringLiteral("GITDIR-NOTFOUND") || GIT_TAG == QStringLiteral("GITDIR-NOTFOUND") ||
GIT_REFSPEC == QStringLiteral("") || GIT_TAG == QStringLiteral("GIT-NOTFOUND")) {
GIT_REFSPEC = "refs/heads/stable";
GIT_TAG = versionString();
GIT_COMMIT = "";
}
if (GIT_REFSPEC.startsWith("refs/heads/"))
{
if (GIT_REFSPEC.startsWith("refs/heads/")) {
VERSION_CHANNEL = GIT_REFSPEC;
VERSION_CHANNEL.remove("refs/heads/");
}
else if (!GIT_COMMIT.isEmpty())
{
VERSION_CHANNEL.remove("refs/heads/");
} else if (!GIT_COMMIT.isEmpty()) {
VERSION_CHANNEL = GIT_COMMIT.mid(0, 8);
}
else
{
} else {
VERSION_CHANNEL = "unknown";
}
@ -136,7 +128,7 @@ Config::Config()
QString Config::versionString() const
{
return QString("%1.%2").arg(VERSION_MAJOR).arg(VERSION_MINOR);
return QString("%1.%2.%3").arg(VERSION_MAJOR).arg(VERSION_MINOR).arg(VERSION_PATCH);
}
QString Config::printableVersionString() const
@ -144,8 +136,7 @@ QString Config::printableVersionString() const
QString vstr = versionString();
// If the build is not a main release, append the channel
if(VERSION_CHANNEL != "stable" && GIT_TAG != vstr)
{
if (VERSION_CHANNEL != "stable" && GIT_TAG != vstr) {
vstr += "-" + VERSION_CHANNEL;
}
return vstr;
@ -162,4 +153,3 @@ QString Config::systemID() const
{
return QStringLiteral("%1 %2 %3").arg(COMPILER_TARGET_SYSTEM, COMPILER_TARGET_SYSTEM_VERSION, COMPILER_TARGET_SYSTEM_PROCESSOR);
}

View File

@ -52,13 +52,15 @@ class Config {
QString LAUNCHER_DOMAIN;
QString LAUNCHER_CONFIGFILE;
QString LAUNCHER_GIT;
QString LAUNCHER_DESKTOPFILENAME;
QString LAUNCHER_APPID;
QString LAUNCHER_SVGFILENAME;
/// The major version number.
int VERSION_MAJOR;
/// The minor version number.
int VERSION_MINOR;
/// The patch version number.
int VERSION_PATCH;
/**
* The version channel

View File

@ -8,6 +8,8 @@
<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>
<key>NSLocalNetworkUsageDescription</key>
<string>Minecraft uses the local network to find and connect to LAN servers.</string>
<key>NSPrincipalClass</key>
<string>NSApplication</string>
<key>NSHighResolutionCapable</key>

View File

@ -1,9 +1,4 @@
(import (
let
lock = builtins.fromJSON (builtins.readFile ./flake.lock);
in
fetchTarball {
url = "https://github.com/edolstra/flake-compat/archive/${lock.nodes.flake-compat.locked.rev}.tar.gz";
sha256 = lock.nodes.flake-compat.locked.narHash;
}
) { src = ./.; }).defaultNix
(import (fetchTarball {
url = "https://github.com/edolstra/flake-compat/archive/ff81ac966bb2cae68946d5ed5fc4994f96d0ffec.tar.gz";
sha256 = "sha256-NeCCThCEP3eCl2l/+27kNNK7QrwZB1IJCrXfrbv5oqU=";
}) { src = ./.; }).defaultNix

64
flake.lock generated
View File

@ -1,29 +1,13 @@
{
"nodes": {
"flake-compat": {
"flake": false,
"locked": {
"lastModified": 1696426674,
"narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=",
"owner": "edolstra",
"repo": "flake-compat",
"rev": "0f9255e01c2351cc7d116c072cb317785dd33b33",
"type": "github"
},
"original": {
"owner": "edolstra",
"repo": "flake-compat",
"type": "github"
}
},
"libnbtplusplus": {
"flake": false,
"locked": {
"lastModified": 1699286814,
"narHash": "sha256-yy0q+bky80LtK1GWzz7qpM+aAGrOqLuewbid8WT1ilk=",
"lastModified": 1744811532,
"narHash": "sha256-qhmjaRkt+O7A+gu6HjUkl7QzOEb4r8y8vWZMG2R/C6o=",
"owner": "PrismLauncher",
"repo": "libnbtplusplus",
"rev": "23b955121b8217c1c348a9ed2483167a6f3ff4ad",
"rev": "531449ba1c930c98e0bcf5d332b237a8566f9d78",
"type": "github"
},
"original": {
@ -32,28 +16,13 @@
"type": "github"
}
},
"nix-filter": {
"locked": {
"lastModified": 1710156097,
"narHash": "sha256-1Wvk8UP7PXdf8bCCaEoMnOT1qe5/Duqgj+rL8sRQsSM=",
"owner": "numtide",
"repo": "nix-filter",
"rev": "3342559a24e85fc164b295c3444e8a139924675b",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "nix-filter",
"type": "github"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1729256560,
"narHash": "sha256-/uilDXvCIEs3C9l73JTACm4quuHUsIHcns1c+cHUJwA=",
"lastModified": 1745526057,
"narHash": "sha256-ITSpPDwvLBZBnPRS2bUcHY3gZSwis/uTe255QgMtTLA=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "4c2fcb090b1f3e5b47eaa7bd33913b574a11e0a0",
"rev": "f771eb401a46846c1aebd20552521b233dd7e18b",
"type": "github"
},
"original": {
@ -63,12 +32,27 @@
"type": "github"
}
},
"qt-qrcodegenerator": {
"flake": false,
"locked": {
"lastModified": 1737616857,
"narHash": "sha256-6SugPt0lp1Gz7nV23FLmsmpfzgFItkSw7jpGftsDPWc=",
"owner": "nayuki",
"repo": "QR-Code-generator",
"rev": "2c9044de6b049ca25cb3cd1649ed7e27aa055138",
"type": "github"
},
"original": {
"owner": "nayuki",
"repo": "QR-Code-generator",
"type": "github"
}
},
"root": {
"inputs": {
"flake-compat": "flake-compat",
"libnbtplusplus": "libnbtplusplus",
"nix-filter": "nix-filter",
"nixpkgs": "nixpkgs"
"nixpkgs": "nixpkgs",
"qt-qrcodegenerator": "qt-qrcodegenerator"
}
}
},

178
flake.nix
View File

@ -16,25 +16,8 @@
flake = false;
};
nix-filter.url = "github:numtide/nix-filter";
/*
Inputs below this are optional and can be removed
```
{
inputs.prismlauncher = {
url = "github:PrismLauncher/PrismLauncher";
inputs = {
flake-compat.follows = "";
};
};
}
```
*/
flake-compat = {
url = "github:edolstra/flake-compat";
qt-qrcodegenerator = {
url = "github:nayuki/QR-Code-generator";
flake = false;
};
};
@ -44,9 +27,9 @@
self,
nixpkgs,
libnbtplusplus,
nix-filter,
...
qt-qrcodegenerator,
}:
let
inherit (nixpkgs) lib;
@ -58,53 +41,151 @@
forAllSystems = lib.genAttrs systems;
nixpkgsFor = forAllSystems (system: nixpkgs.legacyPackages.${system});
in
{
checks = forAllSystems (
system:
let
checks' = nixpkgsFor.${system}.callPackage ./nix/checks.nix { inherit self; };
pkgs = nixpkgsFor.${system};
llvm = pkgs.llvmPackages_19;
in
lib.filterAttrs (_: lib.isDerivation) checks'
{
formatting =
pkgs.runCommand "check-formatting"
{
nativeBuildInputs = with pkgs; [
deadnix
llvm.clang-tools
markdownlint-cli
nixfmt-rfc-style
statix
];
}
''
cd ${self}
echo "Running clang-format...."
clang-format --dry-run --style='file' --Werror */**.{c,cc,cpp,h,hh,hpp}
echo "Running deadnix..."
deadnix --fail
echo "Running markdownlint..."
markdownlint --dot .
echo "Running nixfmt..."
find -type f -name '*.nix' -exec nixfmt --check {} +
echo "Running statix"
statix check .
touch $out
'';
}
);
devShells = forAllSystems (
system:
let
pkgs = nixpkgsFor.${system};
llvm = pkgs.llvmPackages_19;
packages' = self.packages.${system};
welcomeMessage = ''
Welcome to the Prism Launcher repository! 🌈
We just set some things up for you. To get building, you can run:
```
$ cd "$cmakeBuildDir"
$ ninjaBuildPhase
$ ninjaInstallPhase
```
Feel free to ask any questions in our Discord server or Matrix space:
- https://prismlauncher.org/discord
- https://matrix.to/#/#prismlauncher:matrix.org
And thanks for helping out :)
'';
# Re-use our package wrapper to wrap our development environment
qt-wrapper-env = packages'.prismlauncher.overrideAttrs (old: {
name = "qt-wrapper-env";
# Required to use script-based makeWrapper below
strictDeps = true;
# We don't need/want the unwrapped Prism package
paths = [ ];
nativeBuildInputs = old.nativeBuildInputs or [ ] ++ [
# Ensure the wrapper is script based so it can be sourced
pkgs.makeWrapper
];
# Inspired by https://discourse.nixos.org/t/python-qt-woes/11808/10
buildCommand = ''
makeQtWrapper ${lib.getExe pkgs.runtimeShellPackage} "$out"
sed -i '/^exec/d' "$out"
'';
});
in
{
default = pkgs.mkShell {
inputsFrom = [ self.packages.${system}.prismlauncher-unwrapped ];
buildInputs = with pkgs; [
name = "prism-launcher";
inputsFrom = [ packages'.prismlauncher-unwrapped ];
packages = with pkgs; [
ccache
ninja
llvm.clang-tools
];
cmakeBuildType = "Debug";
cmakeFlags = [ "-GNinja" ] ++ packages'.prismlauncher.cmakeFlags;
dontFixCmake = true;
shellHook = ''
echo "Sourcing ${qt-wrapper-env}"
source ${qt-wrapper-env}
git submodule update --init --force
if [ ! -f compile_commands.json ]; then
cmakeConfigurePhase
cd ..
ln -s "$cmakeBuildDir"/compile_commands.json compile_commands.json
fi
echo ${lib.escapeShellArg welcomeMessage}
'';
};
}
);
formatter = forAllSystems (system: nixpkgsFor.${system}.nixfmt-rfc-style);
overlays.default =
final: prev:
let
version = builtins.substring 0 8 self.lastModifiedDate or "dirty";
in
{
prismlauncher-unwrapped = prev.callPackage ./nix/unwrapped.nix {
inherit
libnbtplusplus
nix-filter
self
version
;
};
prismlauncher = final.callPackage ./nix/wrapper.nix { };
overlays.default = final: prev: {
prismlauncher-unwrapped = prev.callPackage ./nix/unwrapped.nix {
inherit
libnbtplusplus
qt-qrcodegenerator
self
;
};
prismlauncher = final.callPackage ./nix/wrapper.nix { };
};
packages = forAllSystems (
system:
let
pkgs = nixpkgsFor.${system};
@ -117,6 +198,7 @@
default = prismPackages.prismlauncher;
};
in
# Only output them if they're available on the current system
lib.filterAttrs (_: lib.meta.availableOn pkgs.stdenv.hostPlatform) packages
);
@ -124,16 +206,18 @@
# We put these under legacyPackages as they are meant for CI, not end user consumption
legacyPackages = forAllSystems (
system:
let
prismPackages = self.packages.${system};
legacyPackages = self.legacyPackages.${system};
packages' = self.packages.${system};
legacyPackages' = self.legacyPackages.${system};
in
{
prismlauncher-debug = prismPackages.prismlauncher.override {
prismlauncher-unwrapped = legacyPackages.prismlauncher-unwrapped-debug;
prismlauncher-debug = packages'.prismlauncher.override {
prismlauncher-unwrapped = legacyPackages'.prismlauncher-unwrapped-debug;
};
prismlauncher-unwrapped-debug = prismPackages.prismlauncher-unwrapped.overrideAttrs {
prismlauncher-unwrapped-debug = packages'.prismlauncher-unwrapped.overrideAttrs {
cmakeBuildType = "Debug";
dontStrip = true;
};

20
flatpak/flite.json Normal file
View File

@ -0,0 +1,20 @@
{
"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,22 +1,18 @@
{
"name": "libdecor",
"buildsystem": "meson",
"config-opts": [
"-Ddemo=false"
],
"sources": [
{
"type": "git",
"url": "https://gitlab.freedesktop.org/libdecor/libdecor.git",
"commit": "73260393a97291c887e1074ab7f318e031be0ac6"
},
{
"type": "patch",
"path": "patches/weird_libdecor.patch"
}
],
"cleanup": [
"/include",
"/lib/pkgconfig"
]
"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,6 +1,6 @@
id: org.prismlauncher.PrismLauncher
runtime: org.kde.Platform
runtime-version: 6.7
runtime-version: '6.8'
sdk: org.kde.Sdk
sdk-extensions:
- org.freedesktop.Sdk.Extension.openjdk17
@ -19,6 +19,12 @@ finish-args:
- --filesystem=xdg-download:ro
# FTBApp import
- --filesystem=~/.ftba:ro
# Userspace visibility for manual hugepages configuration
# Required for -XX:+UseLargePages
- --filesystem=/sys/kernel/mm/hugepages:ro
# Userspace visibility for transparent hugepages configuration
# Required for -XX:+UseTransparentHugePages
- --filesystem=/sys/kernel/mm/transparent_hugepage:ro
modules:
# Might be needed by some Controller mods (see https://github.com/isXander/Controlify/issues/31)
@ -27,11 +33,16 @@ modules:
# 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:
@ -47,18 +58,14 @@ modules:
config-opts:
- -DCMAKE_BUILD_TYPE=RelWithDebInfo
- -DBUILD_SHARED_LIBS:BOOL=ON
- -DGLFW_USE_WAYLAND:BOOL=ON
- -DGLFW_BUILD_WAYLAND:BOOL=ON
- -DGLFW_BUILD_DOCS:BOOL=OFF
sources:
- type: git
url: https://github.com/glfw/glfw.git
commit: 3fa2360720eeba1964df3c0ecf4b5df8648a8e52
commit: 7b6aead9fb88b3623e3b3725ebb42670cbe4c579 # 3.4
- type: patch
path: patches/0003-Don-t-crash-on-calls-to-focus-or-icon.patch
- type: patch
path: patches/0005-Add-warning-about-being-an-unofficial-patch.patch
- type: patch
path: patches/0007-Platform-Prefer-Wayland-over-X11.patch
path: patches/0009-Defer-setting-cursor-position-until-the-cursor-is-lo.patch
cleanup:
- /include
- /lib/cmake
@ -68,8 +75,8 @@ modules:
buildsystem: autotools
sources:
- type: archive
url: https://xorg.freedesktop.org/archive/individual/app/xrandr-1.5.2.tar.xz
sha256: c8bee4790d9058bacc4b6246456c58021db58a87ddda1a9d0139bf5f18f1f240
url: https://xorg.freedesktop.org/archive/individual/app/xrandr-1.5.3.tar.xz
sha256: f8dd7566adb74147fab9964680b6bbadee87cf406a7fcff51718a5e6949b841c
x-checker-data:
type: anitya
project-id: 14957
@ -91,8 +98,8 @@ modules:
sources:
- type: archive
dest-filename: gamemode.tar.gz
url: https://api.github.com/repos/FeralInteractive/gamemode/tarball/1.8.1
sha256: 969cf85b5ca3944f3e315cd73a0ee9bea4f9c968cd7d485e9f4745bc1e679c4e
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

View File

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

View File

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

View File

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

View File

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

@ -1 +1 @@
Subproject commit f2b0c16a2a217a1822ce5a6538ba8f755ed1dd32
Subproject commit 73f08ed2c3187f6648ca04ebef030930a6c9f0be

View File

@ -48,6 +48,7 @@
#include "net/PasteUpload.h"
#include "pathmatcher/MultiMatcher.h"
#include "pathmatcher/SimplePrefixMatcher.h"
#include "tasks/Task.h"
#include "tools/GenericProfiler.h"
#include "ui/InstanceWindow.h"
#include "ui/MainWindow.h"
@ -58,8 +59,6 @@
#include "ui/pages/BasePageProvider.h"
#include "ui/pages/global/APIPage.h"
#include "ui/pages/global/AccountListPage.h"
#include "ui/pages/global/CustomCommandsPage.h"
#include "ui/pages/global/EnvironmentVariablesPage.h"
#include "ui/pages/global/ExternalToolsPage.h"
#include "ui/pages/global/JavaPage.h"
#include "ui/pages/global/LanguagePage.h"
@ -97,6 +96,7 @@
#include <QList>
#include <QNetworkAccessManager>
#include <QStringList>
#include <QStringLiteral>
#include <QStyleFactory>
#include <QTranslator>
#include <QWindow>
@ -128,6 +128,7 @@
#include <stdlib.h>
#include <sys.h>
#include <QStringLiteral>
#include "SysInfo.h"
#ifdef Q_OS_LINUX
@ -154,9 +155,15 @@
#endif
#if defined Q_OS_WIN32
#include <windows.h>
#include "WindowsConsole.h"
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <windows.h>
#include <QStyleHints>
#include "console/WindowsConsole.h"
#endif
#include "console/Console.h"
#define STRINGIFY(x) #x
#define TOSTRING(x) STRINGIFY(x)
@ -165,6 +172,63 @@ static const QLatin1String liveCheckFile("live.check");
PixmapCache* PixmapCache::s_instance = nullptr;
static bool isANSIColorConsole;
static QString defaultLogFormat = QStringLiteral(
"%{time process}"
" "
"%{if-debug}Debug:%{endif}"
"%{if-info}Info:%{endif}"
"%{if-warning}Warning:%{endif}"
"%{if-critical}Critical:%{endif}"
"%{if-fatal}Fatal:%{endif}"
" "
"%{if-category}[%{category}] %{endif}"
"%{message}"
" "
"(%{function}:%{line})");
#define ansi_reset "\x1b[0m"
#define ansi_bold "\x1b[1m"
#define ansi_reset_bold "\x1b[22m"
#define ansi_faint "\x1b[2m"
#define ansi_italic "\x1b[3m"
#define ansi_red_fg "\x1b[31m"
#define ansi_green_fg "\x1b[32m"
#define ansi_yellow_fg "\x1b[33m"
#define ansi_blue_fg "\x1b[34m"
#define ansi_purple_fg "\x1b[35m"
#define ansi_inverse "\x1b[7m"
// clang-format off
static QString ansiLogFormat = QStringLiteral(
ansi_faint "%{time process}" ansi_reset
" "
"%{if-debug}" ansi_bold ansi_green_fg "D:" ansi_reset "%{endif}"
"%{if-info}" ansi_bold ansi_blue_fg "I:" ansi_reset "%{endif}"
"%{if-warning}" ansi_bold ansi_yellow_fg "W:" ansi_reset_bold "%{endif}"
"%{if-critical}" ansi_bold ansi_red_fg "C:" ansi_reset_bold "%{endif}"
"%{if-fatal}" ansi_bold ansi_inverse ansi_red_fg "F:" ansi_reset_bold "%{endif}"
" "
"%{if-category}" ansi_bold "[%{category}]" ansi_reset_bold " %{endif}"
"%{message}"
" "
ansi_reset ansi_faint "(%{function}:%{line})" ansi_reset
);
// clang-format on
#undef ansi_inverse
#undef ansi_purple_fg
#undef ansi_blue_fg
#undef ansi_yellow_fg
#undef ansi_green_fg
#undef ansi_red_fg
#undef ansi_italic
#undef ansi_faint
#undef ansi_bold
#undef ansi_reset_bold
#undef ansi_reset
namespace {
/** This is used so that we can output to the log file in addition to the CLI. */
@ -173,11 +237,24 @@ void appDebugOutput(QtMsgType type, const QMessageLogContext& context, const QSt
static std::mutex loggerMutex;
const std::lock_guard<std::mutex> lock(loggerMutex); // synchronized, QFile logFile is not thread-safe
if (isANSIColorConsole) {
// ensure default is set for log file
qSetMessagePattern(defaultLogFormat);
}
QString out = qFormatLogMessage(type, context, msg);
out += QChar::LineFeed;
APPLICATION->logFile->write(out.toUtf8());
APPLICATION->logFile->flush();
if (isANSIColorConsole) {
// format ansi for console;
qSetMessagePattern(ansiLogFormat);
out = qFormatLogMessage(type, context, msg);
out += QChar::LineFeed;
}
QTextStream(stderr) << out.toLocal8Bit();
fflush(stderr);
}
@ -218,15 +295,25 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv)
// 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);
setApplicationName(BuildConfig.LAUNCHER_NAME);
setApplicationDisplayName(QString("%1 %2").arg(BuildConfig.LAUNCHER_DISPLAYNAME, BuildConfig.printableVersionString()));
setApplicationVersion(BuildConfig.printableVersionString() + "\n" + BuildConfig.GIT_COMMIT);
setDesktopFileName(BuildConfig.LAUNCHER_DESKTOPFILENAME);
startTime = QDateTime::currentDateTime();
setDesktopFileName(BuildConfig.LAUNCHER_APPID);
m_startTime = QDateTime::currentDateTime();
// Don't quit on hiding the last window
this->setQuitOnLastWindowClosed(false);
@ -242,6 +329,7 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv)
{ { "s", "server" }, "Join the specified server on launch (only valid in combination with --launch)", "address" },
{ { "w", "world" }, "Join the specified world on launch (only valid in combination with --launch)", "world" },
{ { "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" },
{ { "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" } });
@ -257,6 +345,10 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv)
m_serverToJoin = parser.value("server");
m_worldToJoin = parser.value("world");
m_profileToUse = parser.value("profile");
if (parser.isSet("offline")) {
m_offline = true;
m_offlineName = parser.value("offline");
}
m_liveCheck = parser.isSet("alive");
m_instanceIdToShowWindowOf = parser.value("show");
@ -271,8 +363,9 @@ 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_instanceIdToLaunch.isEmpty()) {
std::cerr << "--server and --profile can only be used in combination with --launch!" << std::endl;
if ((!m_serverToJoin.isEmpty() || !m_worldToJoin.isEmpty() || !m_profileToUse.isEmpty() || m_offline) &&
m_instanceIdToLaunch.isEmpty()) {
std::cerr << "--server, --profile and --offline can only be used in combination with --launch!" << std::endl;
m_status = Application::Failed;
return;
}
@ -369,19 +462,20 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv)
m_peerInstance = new LocalPeer(this, appID);
connect(m_peerInstance, &LocalPeer::messageReceived, this, &Application::messageReceived);
if (m_peerInstance->isClient()) {
bool sentMessage = false;
int timeout = 2000;
if (m_instanceIdToLaunch.isEmpty()) {
ApplicationMessage activate;
activate.command = "activate";
m_peerInstance->sendMessage(activate.serialize(), timeout);
sentMessage = m_peerInstance->sendMessage(activate.serialize(), timeout);
if (!m_urlsToImport.isEmpty()) {
for (auto url : m_urlsToImport) {
ApplicationMessage import;
import.command = "import";
import.args.insert("url", url.toString());
m_peerInstance->sendMessage(import.serialize(), timeout);
sentMessage = m_peerInstance->sendMessage(import.serialize(), timeout);
}
}
} else {
@ -397,10 +491,20 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv)
if (!m_profileToUse.isEmpty()) {
launch.args["profile"] = m_profileToUse;
}
m_peerInstance->sendMessage(launch.serialize(), timeout);
if (m_offline) {
launch.args["offline_enabled"] = "true";
launch.args["offline_name"] = m_offlineName;
}
sentMessage = m_peerInstance->sendMessage(launch.serialize(), timeout);
}
if (sentMessage) {
m_status = Application::Succeeded;
return;
} else {
std::cerr << "Unable to redirect command to already running instance\n";
// C function not Qt function - event loop not started yet
::exit(1);
}
m_status = Application::Succeeded;
return;
}
}
@ -431,27 +535,14 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv)
return;
}
qInstallMessageHandler(appDebugOutput);
qSetMessagePattern(
"%{time process}"
" "
"%{if-debug}D%{endif}"
"%{if-info}I%{endif}"
"%{if-warning}W%{endif}"
"%{if-critical}C%{endif}"
"%{if-fatal}F%{endif}"
" "
"|"
" "
"%{if-category}[%{category}]: %{endif}"
"%{message}");
qSetMessagePattern(defaultLogFormat);
bool foundLoggingRules = false;
auto logRulesFile = QStringLiteral("qtlogging.ini");
auto logRulesPath = FS::PathCombine(dataPath, logRulesFile);
qDebug() << "Testing" << logRulesPath << "...";
qInfo() << "Testing" << logRulesPath << "...";
foundLoggingRules = QFile::exists(logRulesPath);
// search the dataPath()
@ -459,7 +550,7 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv)
if (!foundLoggingRules && !isPortable() && dirParam.isEmpty() && dataDirEnv.isEmpty()) {
logRulesPath = QStandardPaths::locate(QStandardPaths::AppDataLocation, FS::PathCombine("..", logRulesFile));
if (!logRulesPath.isEmpty()) {
qDebug() << "Found" << logRulesPath << "...";
qInfo() << "Found" << logRulesPath << "...";
foundLoggingRules = true;
}
}
@ -470,28 +561,28 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv)
#else
logRulesPath = FS::PathCombine(m_rootPath, logRulesFile);
#endif
qDebug() << "Testing" << logRulesPath << "...";
qInfo() << "Testing" << logRulesPath << "...";
foundLoggingRules = QFile::exists(logRulesPath);
}
if (foundLoggingRules) {
// load and set logging rules
qDebug() << "Loading logging rules from:" << logRulesPath;
qInfo() << "Loading logging rules from:" << logRulesPath;
QSettings loggingRules(logRulesPath, QSettings::IniFormat);
loggingRules.beginGroup("Rules");
QStringList rule_names = loggingRules.childKeys();
QStringList rules;
qDebug() << "Setting log rules:";
qInfo() << "Setting log rules:";
for (auto rule_name : rule_names) {
auto rule = QString("%1=%2").arg(rule_name).arg(loggingRules.value(rule_name).toString());
rules.append(rule);
qDebug() << " " << rule;
qInfo() << " " << rule;
}
auto rules_str = rules.join("\n");
QLoggingCategory::setFilterRules(rules_str);
}
qDebug() << "<> Log initialized.";
qInfo() << "<> Log initialized.";
}
{
@ -508,33 +599,33 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv)
}
{
qDebug() << qPrintable(BuildConfig.LAUNCHER_DISPLAYNAME + ", " + QString(BuildConfig.LAUNCHER_COPYRIGHT).replace("\n", ", "));
qDebug() << "Version : " << BuildConfig.printableVersionString();
qDebug() << "Platform : " << BuildConfig.BUILD_PLATFORM;
qDebug() << "Git commit : " << BuildConfig.GIT_COMMIT;
qDebug() << "Git refspec : " << BuildConfig.GIT_REFSPEC;
qDebug() << "Compiled for : " << BuildConfig.systemID();
qDebug() << "Compiled by : " << BuildConfig.compilerID();
qDebug() << "Build Artifact : " << BuildConfig.BUILD_ARTIFACT;
qDebug() << "Updates Enabled : " << (updaterEnabled() ? "Yes" : "No");
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");
if (adjustedBy.size()) {
qDebug() << "Work dir before adjustment : " << origcwdPath;
qDebug() << "Work dir after adjustment : " << QDir::currentPath();
qDebug() << "Adjusted by : " << adjustedBy;
qInfo() << "Work dir before adjustment : " << origcwdPath;
qInfo() << "Work dir after adjustment : " << QDir::currentPath();
qInfo() << "Adjusted by : " << adjustedBy;
} else {
qDebug() << "Work dir : " << QDir::currentPath();
qInfo() << "Work dir : " << QDir::currentPath();
}
qDebug() << "Binary path : " << binPath;
qDebug() << "Application root path : " << m_rootPath;
qInfo() << "Binary path : " << binPath;
qInfo() << "Application root path : " << m_rootPath;
if (!m_instanceIdToLaunch.isEmpty()) {
qDebug() << "ID of instance to launch : " << m_instanceIdToLaunch;
qInfo() << "ID of instance to launch : " << m_instanceIdToLaunch;
}
if (!m_serverToJoin.isEmpty()) {
qDebug() << "Address of server to join :" << m_serverToJoin;
qInfo() << "Address of server to join :" << m_serverToJoin;
} else if (!m_worldToJoin.isEmpty()) {
qDebug() << "Name of the world to join :" << m_worldToJoin;
qInfo() << "Name of the world to join :" << m_worldToJoin;
}
qDebug() << "<> Paths set.";
qInfo() << "<> Paths set.";
}
if (m_liveCheck) {
@ -605,6 +696,7 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv)
m_settings->registerSetting("IconsDir", "icons");
m_settings->registerSetting("DownloadsDir", QStandardPaths::writableLocation(QStandardPaths::DownloadLocation));
m_settings->registerSetting("DownloadsDirWatchRecursive", false);
m_settings->registerSetting("MoveModsFromDownloadsDir", false);
m_settings->registerSetting("SkinsDir", "skins");
m_settings->registerSetting("JavaDir", "java");
@ -698,7 +790,9 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv)
m_settings->registerSetting("ToolbarsLocked", false);
// Instance
m_settings->registerSetting("InstSortMode", "Name");
m_settings->registerSetting("InstRenamingMode", "AskEverytime");
m_settings->registerSetting("SelectedInstance", QString());
// Window state and geometry
@ -790,8 +884,6 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv)
m_globalSettingsProvider->addPage<MinecraftPage>();
m_globalSettingsProvider->addPage<JavaPage>();
m_globalSettingsProvider->addPage<LanguagePage>();
m_globalSettingsProvider->addPage<CustomCommandsPage>();
m_globalSettingsProvider->addPage<EnvironmentVariablesPage>();
m_globalSettingsProvider->addPage<ProxyPage>();
m_globalSettingsProvider->addPage<ExternalToolsPage>();
m_globalSettingsProvider->addPage<AccountListPage>();
@ -800,7 +892,7 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv)
PixmapCache::setInstance(new PixmapCache(this));
qDebug() << "<> Settings loaded.";
qInfo() << "<> Settings loaded.";
}
#ifndef QT_NO_ACCESSIBILITY
@ -816,7 +908,7 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv)
QString user = settings()->get("ProxyUser").toString();
QString pass = settings()->get("ProxyPass").toString();
updateProxySettings(proxyTypeStr, addr, port, user, pass);
qDebug() << "<> Network done.";
qInfo() << "<> Network done.";
}
// load translations
@ -824,8 +916,8 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv)
m_translations.reset(new TranslationsModel("translations"));
auto bcp47Name = m_settings->get("Language").toString();
m_translations->selectLanguage(bcp47Name);
qDebug() << "Your language is" << bcp47Name;
qDebug() << "<> Translations loaded.";
qInfo() << "Your language is" << bcp47Name;
qInfo() << "<> Translations loaded.";
}
// Instance icons
@ -835,8 +927,8 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv)
":/icons/multimc/128x128/instances/", ":/icons/multimc/scalable/instances/" };
m_icons.reset(new IconList(instFolders, setting->get().toString()));
connect(setting.get(), &Setting::SettingChanged,
[&](const Setting&, QVariant value) { m_icons->directoryChanged(value.toString()); });
qDebug() << "<> Instance icons initialized.";
[this](const Setting&, QVariant value) { m_icons->directoryChanged(value.toString()); });
qInfo() << "<> Instance icons initialized.";
}
// Themes
@ -848,25 +940,25 @@ 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 = InstDirSetting->get().toString();
qDebug() << "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));
connect(InstDirSetting.get(), &Setting::SettingChanged, m_instances.get(), &InstanceList::on_InstFolderChanged);
qDebug() << "Loading Instances...";
qInfo() << "Loading Instances...";
m_instances->loadList();
qDebug() << "<> Instances loaded.";
qInfo() << "<> Instances loaded.";
}
// and accounts
{
m_accounts.reset(new AccountList(this));
qDebug() << "Loading accounts...";
qInfo() << "Loading accounts...";
m_accounts->setListFilePath("accounts.json", true);
m_accounts->loadList();
m_accounts->fillQueue();
qDebug() << "<> Accounts loaded.";
qInfo() << "<> Accounts loaded.";
}
// init the http meta cache
@ -887,7 +979,7 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv)
m_metacache->addBase("meta", QDir("meta").absolutePath());
m_metacache->addBase("java", QDir("cache/java").absolutePath());
m_metacache->Load();
qDebug() << "<> Cache initialized.";
qInfo() << "<> Cache initialized.";
}
// now we have network, download translation updates
@ -1070,8 +1162,11 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv)
bool Application::createSetupWizard()
{
bool javaRequired = [&]() {
bool ignoreJavaWizard = m_settings->get("IgnoreJavaWizard").toBool();
bool javaRequired = [this]() {
if (BuildConfig.JAVA_DOWNLOADER_ENABLED && settings()->get("AutomaticJavaDownload").toBool()) {
return false;
}
bool ignoreJavaWizard = settings()->get("IgnoreJavaWizard").toBool();
if (ignoreJavaWizard) {
return false;
}
@ -1083,13 +1178,10 @@ bool Application::createSetupWizard()
}
QString currentJavaPath = settings()->get("JavaPath").toString();
QString actualPath = FS::ResolveExecutable(currentJavaPath);
if (actualPath.isNull()) {
return true;
}
return false;
return actualPath.isNull();
}();
bool askjava = BuildConfig.JAVA_DOWNLOADER_ENABLED && !javaRequired && !m_settings->get("AutomaticJavaDownload").toBool() &&
!m_settings->get("AutomaticJavaSwitch").toBool() && !m_settings->get("UserAskedAboutAutomaticJavaDownload").toBool();
bool askjava = BuildConfig.JAVA_DOWNLOADER_ENABLED && !javaRequired && !settings()->get("AutomaticJavaDownload").toBool() &&
!settings()->get("AutomaticJavaSwitch").toBool() && !settings()->get("UserAskedAboutAutomaticJavaDownload").toBool();
bool languageRequired = settings()->get("Language").toString().isEmpty();
bool pasteInterventionRequired = settings()->get("PastebinURL") != "";
bool validWidgets = m_themeManager->isValidApplicationTheme(settings()->get("ApplicationTheme").toString());
@ -1101,8 +1193,16 @@ bool Application::createSetupWizard()
// set default theme after going into theme wizard
if (!validIcons)
settings()->set("IconTheme", QString("pe_colored"));
if (!validWidgets)
settings()->set("ApplicationTheme", QString("system"));
if (!validWidgets) {
#if defined(Q_OS_WIN32) && QT_VERSION >= QT_VERSION_CHECK(6, 5, 0)
const QString style =
QGuiApplication::styleHints()->colorScheme() == Qt::ColorScheme::Dark ? QStringLiteral("dark") : QStringLiteral("bright");
#else
const QString style = QStringLiteral("system");
#endif
settings()->set("ApplicationTheme", style);
}
m_themeManager->applyCurrentlySelectedTheme(true);
@ -1169,6 +1269,9 @@ bool Application::event(QEvent* event)
#endif
if (event->type() == QEvent::FileOpen) {
if (!m_mainWindow) {
showMainWindow(false);
}
auto ev = static_cast<QFileOpenEvent*>(event);
m_mainWindow->processURLs({ ev->url() });
}
@ -1209,7 +1312,7 @@ void Application::performMainStartupAction()
qDebug() << " Launching with account" << m_profileToUse;
}
launch(inst, true, false, targetToJoin, accountToUse);
launch(inst, !m_offline, false, targetToJoin, accountToUse, m_offlineName);
return;
}
}
@ -1302,12 +1405,17 @@ void Application::messageReceived(const QByteArray& message)
qWarning() << "Received" << command << "message without a zip path/URL.";
return;
}
if (!m_mainWindow) {
showMainWindow(false);
}
m_mainWindow->processURLs({ normalizeImportUrl(url) });
} else if (command == "launch") {
QString id = received.args["id"];
QString server = received.args["server"];
QString world = received.args["world"];
QString profile = received.args["profile"];
bool offline = received.args["offline_enabled"] == "true";
QString offlineName = received.args["offline_name"];
InstancePtr instance;
if (!id.isEmpty()) {
@ -1337,7 +1445,7 @@ void Application::messageReceived(const QByteArray& message)
}
}
launch(instance, true, false, serverObject, accountObject);
launch(instance, !offline, false, serverObject, accountObject, offlineName);
} else {
qWarning() << "Received invalid message" << message;
}
@ -1375,11 +1483,17 @@ bool Application::openJsonEditor(const QString& filename)
}
}
bool Application::launch(InstancePtr instance, bool online, bool demo, MinecraftTarget::Ptr targetToJoin, MinecraftAccountPtr accountToUse)
bool Application::launch(InstancePtr instance,
bool online,
bool demo,
MinecraftTarget::Ptr targetToJoin,
MinecraftAccountPtr accountToUse,
const QString& offlineName)
{
if (m_updateRunning) {
qDebug() << "Cannot launch instances while an update is running. Please try again when updates are completed.";
} else if (instance->canLaunch()) {
QMutexLocker locker(&m_instanceExtrasMutex);
auto& extras = m_instanceExtras[instance->id()];
auto window = extras.window;
if (window) {
@ -1395,6 +1509,7 @@ bool Application::launch(InstancePtr instance, bool online, bool demo, Minecraft
controller->setProfiler(profilers().value(instance->settings()->get("Profiler").toString(), nullptr).get());
controller->setTargetToJoin(targetToJoin);
controller->setAccountToUse(accountToUse);
controller->setOfflineName(offlineName);
if (window) {
controller->setParentWidget(window);
} else if (m_mainWindow) {
@ -1404,7 +1519,7 @@ bool Application::launch(InstancePtr instance, bool online, bool demo, Minecraft
connect(controller.get(), &LaunchController::failed, this, &Application::controllerFailed);
connect(controller.get(), &LaunchController::aborted, this, [this] { controllerFailed(tr("Aborted")); });
addRunningInstance();
controller->start();
QMetaObject::invokeMethod(controller.get(), &Task::start, Qt::QueuedConnection);
return true;
} else if (instance->isRunning()) {
showInstanceWindow(instance, "console");
@ -1422,9 +1537,11 @@ bool Application::kill(InstancePtr instance)
qWarning() << "Attempted to kill instance" << instance->id() << ", which isn't running.";
return false;
}
QMutexLocker locker(&m_instanceExtrasMutex);
auto& extras = m_instanceExtras[instance->id()];
// NOTE: copy of the shared pointer keeps it alive
auto controller = extras.controller;
locker.unlock();
if (controller) {
return controller->abort();
}
@ -1478,12 +1595,14 @@ void Application::controllerSucceeded()
if (!controller)
return;
auto id = controller->id();
QMutexLocker locker(&m_instanceExtrasMutex);
auto& extras = m_instanceExtras[id];
// on success, do...
if (controller->instance()->settings()->get("AutoCloseConsole").toBool()) {
if (extras.window) {
extras.window->close();
QMetaObject::invokeMethod(extras.window, &QWidget::close, Qt::QueuedConnection);
}
}
extras.controller.reset();
@ -1503,6 +1622,7 @@ void Application::controllerFailed(const QString& error)
if (!controller)
return;
auto id = controller->id();
QMutexLocker locker(&m_instanceExtrasMutex);
auto& extras = m_instanceExtras[id];
// on failure, do... nothing
@ -1560,6 +1680,7 @@ InstanceWindow* Application::showInstanceWindow(InstancePtr instance, QString pa
if (!instance)
return nullptr;
auto id = instance->id();
QMutexLocker locker(&m_instanceExtrasMutex);
auto& extras = m_instanceExtras[id];
auto& window = extras.window;
@ -1597,6 +1718,7 @@ void Application::on_windowClose()
m_openWindows--;
auto instWindow = qobject_cast<InstanceWindow*>(QObject::sender());
if (instWindow) {
QMutexLocker locker(&m_instanceExtrasMutex);
auto& extras = m_instanceExtras[instWindow->instanceId()];
extras.window = nullptr;
if (extras.controller) {
@ -1844,7 +1966,7 @@ bool Application::handleDataMigration(const QString& currentData,
matcher->add(std::make_shared<SimplePrefixMatcher>("themes/"));
ProgressDialog diag;
DataMigrationTask task(nullptr, oldData, currentData, matcher);
DataMigrationTask task(oldData, currentData, matcher);
if (diag.execWithTask(&task)) {
qDebug() << "<> Migration succeeded";
setDoNotMigrate();
@ -1883,3 +2005,31 @@ const QString Application::javaPath()
{
return m_settings->get("JavaDir").toString();
}
void Application::addQSavePath(QString path)
{
QMutexLocker locker(&m_qsaveResourcesMutex);
m_qsaveResources[path] = m_qsaveResources.value(path, 0) + 1;
}
void Application::removeQSavePath(QString path)
{
QMutexLocker locker(&m_qsaveResourcesMutex);
auto count = m_qsaveResources.value(path, 0) - 1;
if (count <= 0) {
m_qsaveResources.remove(path);
} else {
m_qsaveResources[path] = count;
}
}
bool Application::checkQSavePath(QString path)
{
QMutexLocker locker(&m_qsaveResourcesMutex);
for (auto partialPath : m_qsaveResources.keys()) {
if (path.startsWith(partialPath) && m_qsaveResources.value(partialPath, 0) > 0) {
return true;
}
}
return false;
}

View File

@ -42,6 +42,7 @@
#include <QDebug>
#include <QFlag>
#include <QIcon>
#include <QMutex>
#include <QUrl>
#include <memory>
@ -111,7 +112,7 @@ class Application : public QApplication {
std::shared_ptr<SettingsObject> settings() const { return m_settings; }
qint64 timeSinceStart() const { return startTime.msecsTo(QDateTime::currentDateTime()); }
qint64 timeSinceStart() const { return m_startTime.msecsTo(QDateTime::currentDateTime()); }
QIcon getThemedIcon(const QString& name);
@ -210,7 +211,8 @@ class Application : public QApplication {
bool online = true,
bool demo = false,
MinecraftTarget::Ptr targetToJoin = nullptr,
MinecraftAccountPtr accountToUse = nullptr);
MinecraftAccountPtr accountToUse = nullptr,
const QString& offlineName = QString());
bool kill(InstancePtr instance);
void closeCurrentWindow();
@ -235,7 +237,7 @@ class Application : public QApplication {
bool shouldExitNow() const;
private:
QDateTime startTime;
QDateTime m_startTime;
shared_qobject_ptr<QNetworkAccessManager> m_network;
@ -278,6 +280,7 @@ class Application : public QApplication {
shared_qobject_ptr<LaunchController> controller;
};
std::map<QString, InstanceXtras> m_instanceExtras;
mutable QMutex m_instanceExtrasMutex;
// main state variables
size_t m_openWindows = 0;
@ -299,8 +302,19 @@ class Application : public QApplication {
QString m_serverToJoin;
QString m_worldToJoin;
QString m_profileToUse;
bool m_offline = false;
QString m_offlineName;
bool m_liveCheck = false;
QList<QUrl> m_urlsToImport;
QString m_instanceIdToShowWindowOf;
std::unique_ptr<QFile> logFile;
public:
void addQSavePath(QString);
void removeQSavePath(QString);
bool checkQSavePath(QString);
private:
QHash<QString, int> m_qsaveResources;
mutable QMutex m_qsaveResourcesMutex;
};

View File

@ -42,8 +42,8 @@
#include <QFileInfo>
#include <QJsonDocument>
#include <QJsonObject>
#include <QRegularExpression>
#include "Application.h"
#include "settings/INISettingsObject.h"
#include "settings/OverrideSetting.h"
#include "settings/Setting.h"
@ -174,6 +174,12 @@ void BaseInstance::copyManagedPack(BaseInstance& other)
m_settings->set("ManagedPackName", other.getManagedPackName());
m_settings->set("ManagedPackVersionID", other.getManagedPackVersionID());
m_settings->set("ManagedPackVersionName", other.getManagedPackVersionName());
if (APPLICATION->settings()->get("AutomaticJavaSwitch").toBool() && m_settings->get("AutomaticJava").toBool() &&
m_settings->get("OverrideJavaLocation").toBool()) {
m_settings->set("OverrideJavaLocation", false);
m_settings->set("JavaPath", "");
}
}
int BaseInstance::getConsoleMaxLines() const
@ -386,6 +392,12 @@ void BaseInstance::setName(QString val)
emit propertiesChanged(this);
}
bool BaseInstance::syncInstanceDirName(const QString& newRoot) const
{
auto oldRoot = instanceRoot();
return oldRoot == newRoot || QFile::rename(oldRoot, newRoot);
}
QString BaseInstance::name() const
{
return m_settings->get("name").toString();
@ -411,3 +423,8 @@ void BaseInstance::updateRuntimeContext()
{
// NOOP
}
bool BaseInstance::isLegacy()
{
return traits().contains("legacyLaunch") || traits().contains("alphaLaunch");
}

View File

@ -126,6 +126,9 @@ class BaseInstance : public QObject, public std::enable_shared_from_this<BaseIns
QString name() const;
void setName(QString val);
/// Sync name and rename instance dir accordingly; returns true if successful
bool syncInstanceDirName(const QString& newRoot) const;
/// Value used for instance window titles
QString windowTitle() const;
@ -148,9 +151,6 @@ class BaseInstance : public QObject, public std::enable_shared_from_this<BaseIns
void setManagedPack(const QString& type, const QString& id, const QString& name, const QString& versionId, const QString& version);
void copyManagedPack(BaseInstance& other);
/// guess log level from a line of game log
virtual MessageLevel::Enum guessLevel([[maybe_unused]] const QString& line, MessageLevel::Enum level) { return level; }
virtual QStringList extraArguments();
/// Traits. Normally inside the version, depends on instance implementation.
@ -195,15 +195,10 @@ class BaseInstance : public QObject, public std::enable_shared_from_this<BaseIns
virtual QProcessEnvironment createEnvironment() = 0;
virtual QProcessEnvironment createLaunchEnvironment() = 0;
/*!
* Returns a matcher that can maps relative paths within the instance to whether they are 'log files'
*/
virtual IPathMatcher::Ptr getLogFileMatcher() = 0;
/*!
* Returns the root folder to use for looking up log files
*/
virtual QString getLogFileRoot() = 0;
virtual QStringList getLogFileSearchPaths() = 0;
virtual QString getStatusbarDescription() = 0;
@ -269,6 +264,8 @@ class BaseInstance : public QObject, public std::enable_shared_from_this<BaseIns
bool removeLinkedInstanceId(const QString& id);
bool isLinkedToInstanceId(const QString& id) const;
bool isLegacy();
protected:
void changeStatus(Status newStatus);

View File

@ -21,6 +21,8 @@ set(CORE_SOURCES
BaseVersion.h
BaseInstance.h
BaseInstance.cpp
InstanceDirUpdate.h
InstanceDirUpdate.cpp
NullInstance.h
MMCZip.h
MMCZip.cpp
@ -30,6 +32,7 @@ set(CORE_SOURCES
StringUtils.cpp
QVariantUtils.h
RuntimeContext.h
PSaveFile.h
# Basic instance manipulation tasks (derived from InstanceTask)
InstanceCreationTask.h
@ -96,7 +99,7 @@ set(CORE_SOURCES
MTPixmapCache.h
)
if (UNIX AND NOT CYGWIN AND NOT APPLE)
set(CORE_SOURCES
set(CORE_SOURCES
${CORE_SOURCES}
# MangoHud
@ -172,6 +175,8 @@ set(LAUNCH_SOURCES
launch/LogModel.h
launch/TaskStepWrapper.cpp
launch/TaskStepWrapper.h
logs/LogParser.cpp
logs/LogParser.h
)
# Old update system
@ -344,13 +349,12 @@ set(MINECRAFT_SOURCES
minecraft/mod/TexturePackFolderModel.h
minecraft/mod/TexturePackFolderModel.cpp
minecraft/mod/ShaderPackFolderModel.h
minecraft/mod/tasks/BasicFolderLoadTask.h
minecraft/mod/tasks/ModFolderLoadTask.h
minecraft/mod/tasks/ModFolderLoadTask.cpp
minecraft/mod/tasks/ResourceFolderLoadTask.h
minecraft/mod/tasks/ResourceFolderLoadTask.cpp
minecraft/mod/tasks/LocalModParseTask.h
minecraft/mod/tasks/LocalModParseTask.cpp
minecraft/mod/tasks/LocalModUpdateTask.h
minecraft/mod/tasks/LocalModUpdateTask.cpp
minecraft/mod/tasks/LocalResourceUpdateTask.h
minecraft/mod/tasks/LocalResourceUpdateTask.cpp
minecraft/mod/tasks/LocalDataPackParseTask.h
minecraft/mod/tasks/LocalDataPackParseTask.cpp
minecraft/mod/tasks/LocalResourcePackParseTask.h
@ -587,8 +591,8 @@ set(ATLAUNCHER_SOURCES
)
set(LINKEXE_SOURCES
WindowsConsole.cpp
WindowsConsole.h
console/WindowsConsole.h
console/WindowsConsole.cpp
filelink/FileLink.h
filelink/FileLink.cpp
@ -657,6 +661,14 @@ set(PRISMUPDATER_SOURCES
)
if(WIN32)
set(PRISMUPDATER_SOURCES
console/WindowsConsole.h
console/WindowsConsole.cpp
${PRISMUPDATER_SOURCES}
)
endif()
######## Logging categories ########
ecm_qt_declare_logging_category(CORE_SOURCES
@ -784,6 +796,9 @@ SET(LAUNCHER_SOURCES
SysInfo.h
SysInfo.cpp
# console utils
console/Console.h
# GUI - general utilities
DesktopServices.h
DesktopServices.cpp
@ -810,7 +825,8 @@ SET(LAUNCHER_SOURCES
resources/flat/flat.qrc
resources/flat_white/flat_white.qrc
resources/documents/documents.qrc
../${Launcher_Branding_LogoQRC}
resources/shaders/shaders.qrc
"${CMAKE_CURRENT_BINARY_DIR}/../${Launcher_Branding_LogoQRC}"
# Icons
icons/MMCIcon.h
@ -908,7 +924,6 @@ SET(LAUNCHER_SOURCES
ui/pages/instance/NotesPage.h
ui/pages/instance/LogPage.cpp
ui/pages/instance/LogPage.h
ui/pages/instance/InstanceSettingsPage.cpp
ui/pages/instance/InstanceSettingsPage.h
ui/pages/instance/ScreenshotsPage.cpp
ui/pages/instance/ScreenshotsPage.h
@ -918,21 +933,22 @@ SET(LAUNCHER_SOURCES
ui/pages/instance/ServersPage.h
ui/pages/instance/WorldListPage.cpp
ui/pages/instance/WorldListPage.h
ui/pages/instance/McClient.cpp
ui/pages/instance/McClient.h
ui/pages/instance/McResolver.cpp
ui/pages/instance/McResolver.h
ui/pages/instance/ServerPingTask.cpp
ui/pages/instance/ServerPingTask.h
# GUI - global settings pages
ui/pages/global/AccountListPage.cpp
ui/pages/global/AccountListPage.h
ui/pages/global/CustomCommandsPage.cpp
ui/pages/global/CustomCommandsPage.h
ui/pages/global/EnvironmentVariablesPage.cpp
ui/pages/global/EnvironmentVariablesPage.h
ui/pages/global/ExternalToolsPage.cpp
ui/pages/global/ExternalToolsPage.h
ui/pages/global/JavaPage.cpp
ui/pages/global/JavaPage.h
ui/pages/global/LanguagePage.cpp
ui/pages/global/LanguagePage.h
ui/pages/global/MinecraftPage.cpp
ui/pages/global/MinecraftPage.h
ui/pages/global/LauncherPage.cpp
ui/pages/global/LauncherPage.h
@ -1030,8 +1046,6 @@ SET(LAUNCHER_SOURCES
ui/dialogs/CopyInstanceDialog.h
ui/dialogs/CustomMessageBox.cpp
ui/dialogs/CustomMessageBox.h
ui/dialogs/EditAccountDialog.cpp
ui/dialogs/EditAccountDialog.h
ui/dialogs/ExportInstanceDialog.cpp
ui/dialogs/ExportInstanceDialog.h
ui/dialogs/ExportPackDialog.cpp
@ -1068,14 +1082,21 @@ SET(LAUNCHER_SOURCES
ui/dialogs/BlockedModsDialog.h
ui/dialogs/ChooseProviderDialog.h
ui/dialogs/ChooseProviderDialog.cpp
ui/dialogs/ModUpdateDialog.cpp
ui/dialogs/ModUpdateDialog.h
ui/dialogs/ResourceUpdateDialog.cpp
ui/dialogs/ResourceUpdateDialog.h
ui/dialogs/InstallLoaderDialog.cpp
ui/dialogs/InstallLoaderDialog.h
ui/dialogs/skins/SkinManageDialog.cpp
ui/dialogs/skins/SkinManageDialog.h
ui/dialogs/skins/draw/SkinOpenGLWindow.h
ui/dialogs/skins/draw/SkinOpenGLWindow.cpp
ui/dialogs/skins/draw/Scene.h
ui/dialogs/skins/draw/Scene.cpp
ui/dialogs/skins/draw/BoxGeometry.h
ui/dialogs/skins/draw/BoxGeometry.cpp
# GUI - widgets
ui/widgets/CheckComboBox.cpp
ui/widgets/CheckComboBox.h
@ -1085,14 +1106,12 @@ SET(LAUNCHER_SOURCES
ui/widgets/CustomCommands.h
ui/widgets/EnvironmentVariables.cpp
ui/widgets/EnvironmentVariables.h
ui/widgets/DropLabel.cpp
ui/widgets/DropLabel.h
ui/widgets/FocusLineEdit.cpp
ui/widgets/FocusLineEdit.h
ui/widgets/IconLabel.cpp
ui/widgets/IconLabel.h
ui/widgets/JavaSettingsWidget.cpp
ui/widgets/JavaSettingsWidget.h
ui/widgets/JavaWizardWidget.cpp
ui/widgets/JavaWizardWidget.h
ui/widgets/LabeledToolButton.cpp
ui/widgets/LabeledToolButton.h
ui/widgets/LanguageSelectionWidget.cpp
@ -1128,6 +1147,10 @@ SET(LAUNCHER_SOURCES
ui/widgets/WideBar.cpp
ui/widgets/ThemeCustomizationWidget.h
ui/widgets/ThemeCustomizationWidget.cpp
ui/widgets/MinecraftSettingsWidget.h
ui/widgets/MinecraftSettingsWidget.cpp
ui/widgets/JavaSettingsWidget.h
ui/widgets/JavaSettingsWidget.cpp
# GUI - instance group view
ui/instanceview/InstanceProxyModel.cpp
@ -1144,7 +1167,7 @@ SET(LAUNCHER_SOURCES
)
if (NOT Apple)
set(LAUNCHER_SOURCES
set(LAUNCHER_SOURCES
${LAUNCHER_SOURCES}
ui/dialogs/UpdateAvailableDialog.h
@ -1154,8 +1177,8 @@ endif()
if(WIN32)
set(LAUNCHER_SOURCES
WindowsConsole.cpp
WindowsConsole.h
console/WindowsConsole.h
console/WindowsConsole.cpp
${LAUNCHER_SOURCES}
)
endif()
@ -1171,7 +1194,6 @@ qt_wrap_ui(LAUNCHER_UI
ui/pages/global/LauncherPage.ui
ui/pages/global/APIPage.ui
ui/pages/global/ProxyPage.ui
ui/pages/global/MinecraftPage.ui
ui/pages/global/ExternalToolsPage.ui
ui/pages/instance/ExternalResourcesPage.ui
ui/pages/instance/NotesPage.ui
@ -1179,7 +1201,6 @@ qt_wrap_ui(LAUNCHER_UI
ui/pages/instance/ServersPage.ui
ui/pages/instance/GameOptionsPage.ui
ui/pages/instance/OtherLogsPage.ui
ui/pages/instance/InstanceSettingsPage.ui
ui/pages/instance/VersionPage.ui
ui/pages/instance/ManagedPackPage.ui
ui/pages/instance/WorldListPage.ui
@ -1202,6 +1223,8 @@ qt_wrap_ui(LAUNCHER_UI
ui/widgets/ModFilterWidget.ui
ui/widgets/SubTaskProgressBar.ui
ui/widgets/ThemeCustomizationWidget.ui
ui/widgets/MinecraftSettingsWidget.ui
ui/widgets/JavaSettingsWidget.ui
ui/dialogs/CopyInstanceDialog.ui
ui/dialogs/ProfileSetupDialog.ui
ui/dialogs/ProgressDialog.ui
@ -1217,12 +1240,10 @@ qt_wrap_ui(LAUNCHER_UI
ui/dialogs/MSALoginDialog.ui
ui/dialogs/OfflineLoginDialog.ui
ui/dialogs/AboutDialog.ui
ui/dialogs/EditAccountDialog.ui
ui/dialogs/ReviewMessageBox.ui
ui/dialogs/ScrollMessageBox.ui
ui/dialogs/BlockedModsDialog.ui
ui/dialogs/ChooseProviderDialog.ui
ui/dialogs/skins/SkinManageDialog.ui
)
@ -1247,7 +1268,8 @@ qt_add_resources(LAUNCHER_RESOURCES
resources/iOS/iOS.qrc
resources/flat/flat.qrc
resources/documents/documents.qrc
../${Launcher_Branding_LogoQRC}
resources/shaders/shaders.qrc
"${CMAKE_CURRENT_BINARY_DIR}/../${Launcher_Branding_LogoQRC}"
)
qt_wrap_ui(PRISMUPDATER_UI
@ -1280,7 +1302,7 @@ target_link_libraries(Launcher_logic
qdcss
BuildConfig
Qt${QT_VERSION_MAJOR}::Widgets
ghcFilesystem::ghc_filesystem
qrcode
)
if (UNIX AND NOT CYGWIN AND NOT APPLE)
@ -1297,6 +1319,8 @@ target_link_libraries(Launcher_logic
Qt${QT_VERSION_MAJOR}::Gui
Qt${QT_VERSION_MAJOR}::Widgets
Qt${QT_VERSION_MAJOR}::NetworkAuth
Qt${QT_VERSION_MAJOR}::OpenGL
${Launcher_QT_DBUS}
${Launcher_QT_LIBS}
)
target_link_libraries(Launcher_logic
@ -1305,16 +1329,20 @@ target_link_libraries(Launcher_logic
LocalPeer
Launcher_rainbow
)
if (TARGET ${Launcher_QT_DBUS})
add_compile_definitions(WITH_QTDBUS)
endif()
if(APPLE)
set(CMAKE_MACOSX_RPATH 1)
set(CMAKE_INSTALL_RPATH "@loader_path/../Frameworks/")
if(Launcher_ENABLE_UPDATER)
file(DOWNLOAD ${MACOSX_SPARKLE_DOWNLOAD_URL} ${CMAKE_BINARY_DIR}/Sparkle.tar.xz EXPECTED_HASH SHA256=${MACOSX_SPARKLE_SHA256})
file(ARCHIVE_EXTRACT INPUT ${CMAKE_BINARY_DIR}/Sparkle.tar.xz DESTINATION ${CMAKE_BINARY_DIR}/frameworks/Sparkle)
file(DOWNLOAD ${MACOSX_SPARKLE_DOWNLOAD_URL} ${CMAKE_BINARY_DIR}/Sparkle.tar.xz EXPECTED_HASH SHA256=${MACOSX_SPARKLE_SHA256})
file(ARCHIVE_EXTRACT INPUT ${CMAKE_BINARY_DIR}/Sparkle.tar.xz DESTINATION ${CMAKE_BINARY_DIR}/frameworks/Sparkle)
find_library(SPARKLE_FRAMEWORK Sparkle "${CMAKE_BINARY_DIR}/frameworks/Sparkle")
add_compile_definitions(SPARKLE_ENABLED)
find_library(SPARKLE_FRAMEWORK Sparkle "${CMAKE_BINARY_DIR}/frameworks/Sparkle")
add_compile_definitions(SPARKLE_ENABLED)
endif()
target_link_libraries(Launcher_logic
@ -1324,7 +1352,7 @@ if(APPLE)
"-framework ApplicationServices"
)
if(Launcher_ENABLE_UPDATER)
target_link_libraries(Launcher_logic ${SPARKLE_FRAMEWORK})
target_link_libraries(Launcher_logic ${SPARKLE_FRAMEWORK})
endif()
endif()
@ -1361,7 +1389,6 @@ if(Launcher_BUILD_UPDATER)
${ZLIB_LIBRARIES}
systeminfo
BuildConfig
ghcFilesystem::ghc_filesystem
Qt${QT_VERSION_MAJOR}::Widgets
Qt${QT_VERSION_MAJOR}::Core
Qt${QT_VERSION_MAJOR}::Network
@ -1400,7 +1427,6 @@ if(WIN32 OR (DEFINED Launcher_BUILD_FILELINKER AND Launcher_BUILD_FILELINKER))
target_link_libraries(filelink_logic
systeminfo
BuildConfig
ghcFilesystem::ghc_filesystem
Qt${QT_VERSION_MAJOR}::Widgets
Qt${QT_VERSION_MAJOR}::Core
Qt${QT_VERSION_MAJOR}::Network

View File

@ -12,13 +12,10 @@
#include <QtConcurrent>
DataMigrationTask::DataMigrationTask(QObject* parent,
const QString& sourcePath,
const QString& targetPath,
const IPathMatcher::Ptr pathMatcher)
: Task(parent), m_sourcePath(sourcePath), m_targetPath(targetPath), m_pathMatcher(pathMatcher), m_copy(sourcePath, targetPath)
DataMigrationTask::DataMigrationTask(const QString& sourcePath, const QString& targetPath, const IPathMatcher::Ptr pathMatcher)
: Task(), m_sourcePath(sourcePath), m_targetPath(targetPath), m_pathMatcher(pathMatcher), m_copy(sourcePath, targetPath)
{
m_copy.matcher(m_pathMatcher.get()).whitelist(true);
m_copy.matcher(m_pathMatcher).whitelist(true);
}
void DataMigrationTask::executeTask()
@ -27,7 +24,7 @@ void DataMigrationTask::executeTask()
// 1. Scan
// Check how many files we gotta copy
m_copyFuture = QtConcurrent::run(QThreadPool::globalInstance(), [&] {
m_copyFuture = QtConcurrent::run(QThreadPool::globalInstance(), [this] {
return m_copy(true); // dry run to collect amount of files
});
connect(&m_copyFutureWatcher, &QFutureWatcher<bool>::finished, this, &DataMigrationTask::dryRunFinished);
@ -40,11 +37,7 @@ void DataMigrationTask::dryRunFinished()
disconnect(&m_copyFutureWatcher, &QFutureWatcher<bool>::finished, this, &DataMigrationTask::dryRunFinished);
disconnect(&m_copyFutureWatcher, &QFutureWatcher<bool>::canceled, this, &DataMigrationTask::dryRunAborted);
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
if (!m_copyFuture.isValid() || !m_copyFuture.result()) {
#else
if (!m_copyFuture.result()) {
#endif
emitFailed(tr("Failed to scan source path."));
return;
}
@ -60,7 +53,7 @@ void DataMigrationTask::dryRunFinished()
setProgress(m_copy.totalCopied(), m_toCopy);
setStatus(tr("Copying %1…").arg(shortenedName));
});
m_copyFuture = QtConcurrent::run(QThreadPool::globalInstance(), [&] {
m_copyFuture = QtConcurrent::run(QThreadPool::globalInstance(), [this] {
return m_copy(false); // actually copy now
});
connect(&m_copyFutureWatcher, &QFutureWatcher<bool>::finished, this, &DataMigrationTask::copyFinished);
@ -78,11 +71,7 @@ void DataMigrationTask::copyFinished()
disconnect(&m_copyFutureWatcher, &QFutureWatcher<bool>::finished, this, &DataMigrationTask::copyFinished);
disconnect(&m_copyFutureWatcher, &QFutureWatcher<bool>::canceled, this, &DataMigrationTask::copyAborted);
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
if (!m_copyFuture.isValid() || !m_copyFuture.result()) {
#else
if (!m_copyFuture.result()) {
#endif
emitFailed(tr("Some paths could not be copied!"));
return;
}

View File

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

View File

@ -40,12 +40,11 @@
#include <QFileSystemModel>
#include <QSortFilterProxyModel>
#include <QStack>
#include <algorithm>
#include "FileSystem.h"
#include "SeparatorPrefixTree.h"
#include "StringUtils.h"
FileIgnoreProxy::FileIgnoreProxy(QString root, QObject* parent) : QSortFilterProxyModel(parent), root(root) {}
FileIgnoreProxy::FileIgnoreProxy(QString root, QObject* parent) : QSortFilterProxyModel(parent), m_root(root) {}
// NOTE: Sadly, we have to do sorting ourselves.
bool FileIgnoreProxy::lessThan(const QModelIndex& left, const QModelIndex& right) const
{
@ -104,10 +103,10 @@ QVariant FileIgnoreProxy::data(const QModelIndex& index, int role) const
if (index.column() == 0 && role == Qt::CheckStateRole) {
QFileSystemModel* fsm = qobject_cast<QFileSystemModel*>(sourceModel());
auto blockedPath = relPath(fsm->filePath(sourceIndex));
auto cover = blocked.cover(blockedPath);
auto cover = m_blocked.cover(blockedPath);
if (!cover.isNull()) {
return QVariant(Qt::Unchecked);
} else if (blocked.exists(blockedPath)) {
} else if (m_blocked.exists(blockedPath)) {
return QVariant(Qt::PartiallyChecked);
} else {
return QVariant(Qt::Checked);
@ -130,7 +129,7 @@ bool FileIgnoreProxy::setData(const QModelIndex& index, const QVariant& value, i
QString FileIgnoreProxy::relPath(const QString& path) const
{
return QDir(root).relativeFilePath(path);
return QDir(m_root).relativeFilePath(path);
}
bool FileIgnoreProxy::setFilterState(QModelIndex index, Qt::CheckState state)
@ -146,18 +145,18 @@ bool FileIgnoreProxy::setFilterState(QModelIndex index, Qt::CheckState state)
bool changed = false;
if (state == Qt::Unchecked) {
// blocking a path
auto& node = blocked.insert(blockedPath);
auto& node = m_blocked.insert(blockedPath);
// get rid of all blocked nodes below
node.clear();
changed = true;
} else if (state == Qt::Checked || state == Qt::PartiallyChecked) {
if (!blocked.remove(blockedPath)) {
auto cover = blocked.cover(blockedPath);
if (!m_blocked.remove(blockedPath)) {
auto cover = m_blocked.cover(blockedPath);
qDebug() << "Blocked by cover" << cover;
// uncover
blocked.remove(cover);
m_blocked.remove(cover);
// block all contents, except for any cover
QModelIndex rootIndex = fsm->index(FS::PathCombine(root, cover));
QModelIndex rootIndex = fsm->index(FS::PathCombine(m_root, cover));
QModelIndex doing = rootIndex;
int row = 0;
QStack<QModelIndex> todo;
@ -179,7 +178,7 @@ bool FileIgnoreProxy::setFilterState(QModelIndex index, Qt::CheckState state)
todo.push(node);
} else {
// or just block this one.
blocked.insert(relpath);
m_blocked.insert(relpath);
}
row++;
}
@ -229,7 +228,7 @@ bool FileIgnoreProxy::shouldExpand(QModelIndex index)
return false;
}
auto blockedPath = relPath(fsm->filePath(sourceIndex));
auto found = blocked.find(blockedPath);
auto found = m_blocked.find(blockedPath);
if (found) {
return !found->leaf();
}
@ -239,8 +238,8 @@ bool FileIgnoreProxy::shouldExpand(QModelIndex index)
void FileIgnoreProxy::setBlockedPaths(QStringList paths)
{
beginResetModel();
blocked.clear();
blocked.insert(paths);
m_blocked.clear();
m_blocked.insert(paths);
endResetModel();
}
@ -272,5 +271,26 @@ bool FileIgnoreProxy::ignoreFile(QFileInfo fileInfo) const
bool FileIgnoreProxy::filterFile(const QString& fileName) const
{
return blocked.covers(fileName) || ignoreFile(QFileInfo(QDir(root), fileName));
return m_blocked.covers(fileName) || ignoreFile(QFileInfo(QDir(m_root), fileName));
}
void FileIgnoreProxy::loadBlockedPathsFromFile(const QString& fileName)
{
QFile ignoreFile(fileName);
if (!ignoreFile.open(QIODevice::ReadOnly)) {
return;
}
auto ignoreData = ignoreFile.readAll();
auto string = QString::fromUtf8(ignoreData);
setBlockedPaths(string.split('\n', Qt::SkipEmptyParts));
}
void FileIgnoreProxy::saveBlockedPathsToFile(const QString& fileName)
{
auto ignoreData = blockedPaths().toStringList().join('\n').toUtf8();
try {
FS::write(fileName, ignoreData);
} catch (const Exception& e) {
qWarning() << e.cause();
}
}

View File

@ -61,8 +61,8 @@ class FileIgnoreProxy : public QSortFilterProxyModel {
void setBlockedPaths(QStringList paths);
inline const SeparatorPrefixTree<'/'>& blockedPaths() const { return blocked; }
inline SeparatorPrefixTree<'/'>& blockedPaths() { return blocked; }
inline const SeparatorPrefixTree<'/'>& blockedPaths() const { return m_blocked; }
inline SeparatorPrefixTree<'/'>& blockedPaths() { return m_blocked; }
// list of file names that need to be removed completely from model
inline QStringList& ignoreFilesWithName() { return m_ignoreFiles; }
@ -71,6 +71,10 @@ class FileIgnoreProxy : public QSortFilterProxyModel {
bool filterFile(const QString& fileName) const;
void loadBlockedPathsFromFile(const QString& fileName);
void saveBlockedPathsToFile(const QString& fileName);
protected:
bool filterAcceptsColumn(int source_column, const QModelIndex& source_parent) const;
bool filterAcceptsRow(int source_row, const QModelIndex& source_parent) const;
@ -78,8 +82,8 @@ class FileIgnoreProxy : public QSortFilterProxyModel {
bool ignoreFile(QFileInfo file) const;
private:
const QString root;
SeparatorPrefixTree<'/'> blocked;
const QString m_root;
SeparatorPrefixTree<'/'> m_blocked;
QStringList m_ignoreFiles;
SeparatorPrefixTree<'/'> m_ignoreFilePaths;
};

View File

@ -45,7 +45,6 @@
#include <QDirIterator>
#include <QFile>
#include <QFileInfo>
#include <QSaveFile>
#include <QStandardPaths>
#include <QStorageInfo>
#include <QTextStream>
@ -54,6 +53,7 @@
#include <system_error>
#include "DesktopServices.h"
#include "PSaveFile.h"
#include "StringUtils.h"
#if defined Q_OS_WIN32
@ -77,24 +77,8 @@
#include <utime.h>
#endif
// Snippet from https://github.com/gulrak/filesystem#using-it-as-single-file-header
#ifdef __APPLE__
#include <Availability.h> // for deployment target to support pre-catalina targets without std::fs
#endif // __APPLE__
#if ((defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) || (defined(__cplusplus) && __cplusplus >= 201703L)) && defined(__has_include)
#if __has_include(<filesystem>) && (!defined(__MAC_OS_X_VERSION_MIN_REQUIRED) || __MAC_OS_X_VERSION_MIN_REQUIRED >= 101500)
#define GHC_USE_STD_FS
#include <filesystem>
namespace fs = std::filesystem;
#endif // MacOS min version check
#endif // Other OSes version check
#ifndef GHC_USE_STD_FS
#include <ghc/filesystem.hpp>
namespace fs = ghc::filesystem;
#endif
// clone
#if defined(Q_OS_LINUX)
@ -191,8 +175,8 @@ void ensureExists(const QDir& dir)
void write(const QString& filename, const QByteArray& data)
{
ensureExists(QFileInfo(filename).dir());
QSaveFile file(filename);
if (!file.open(QSaveFile::WriteOnly)) {
PSaveFile file(filename);
if (!file.open(PSaveFile::WriteOnly)) {
throw FileSystemException("Couldn't open " + filename + " for writing: " + file.errorString());
}
if (data.size() != file.write(data)) {
@ -213,8 +197,8 @@ void appendSafe(const QString& filename, const QByteArray& data)
buffer = QByteArray();
}
buffer.append(data);
QSaveFile file(filename);
if (!file.open(QSaveFile::WriteOnly)) {
PSaveFile file(filename);
if (!file.open(PSaveFile::WriteOnly)) {
throw FileSystemException("Couldn't open " + filename + " for writing: " + file.errorString());
}
if (buffer.size() != file.write(buffer)) {
@ -341,7 +325,7 @@ bool copy::operator()(const QString& offset, bool dryRun)
opt |= copy_opts::overwrite_existing;
// Function that'll do the actual copying
auto copy_file = [&](QString src_path, QString relative_dst_path) {
auto copy_file = [this, dryRun, src, dst, opt, &err](QString src_path, QString relative_dst_path) {
if (m_matcher && (m_matcher->matches(relative_dst_path) != m_whitelist))
return;
@ -428,7 +412,7 @@ void create_link::make_link_list(const QString& offset)
m_recursive = true;
// Function that'll do the actual linking
auto link_file = [&](QString src_path, QString relative_dst_path) {
auto link_file = [this, dst](QString src_path, QString relative_dst_path) {
if (m_matcher && (m_matcher->matches(relative_dst_path) != m_whitelist)) {
qDebug() << "path" << relative_dst_path << "in black list or not in whitelist";
return;
@ -523,7 +507,7 @@ void create_link::runPrivileged(const QString& offset)
QString serverName = BuildConfig.LAUNCHER_APP_BINARY_NAME + "_filelink_server" + StringUtils::getRandomAlphaNumeric();
connect(&m_linkServer, &QLocalServer::newConnection, this, [&]() {
connect(&m_linkServer, &QLocalServer::newConnection, this, [this, &gotResults]() {
qDebug() << "Client connected, sending out pairs";
// construct block of data to send
QByteArray block;
@ -605,7 +589,7 @@ void create_link::runPrivileged(const QString& offset)
}
ExternalLinkFileProcess* linkFileProcess = new ExternalLinkFileProcess(serverName, m_useHardLinks, this);
connect(linkFileProcess, &ExternalLinkFileProcess::processExited, this, [&]() { emit finishedPrivileged(gotResults); });
connect(linkFileProcess, &ExternalLinkFileProcess::processExited, this, [this, gotResults]() { emit finishedPrivileged(gotResults); });
connect(linkFileProcess, &ExternalLinkFileProcess::finished, linkFileProcess, &QObject::deleteLater);
linkFileProcess->start();
@ -695,9 +679,6 @@ bool deletePath(QString path)
bool trash(QString path, QString* pathInTrash)
{
#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
return false;
#else
// FIXME: Figure out trash in Flatpak. Qt seemingly doesn't use the Trash portal
if (DesktopServices::isFlatpak())
return false;
@ -706,7 +687,6 @@ bool trash(QString path, QString* pathInTrash)
return false;
#endif
return QFile::moveToTrash(path, pathInTrash);
#endif
}
QString PathCombine(const QString& path1, const QString& path2)
@ -740,11 +720,7 @@ int pathDepth(const QString& path)
QFileInfo info(path);
#if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
auto parts = QDir::toNativeSeparators(info.path()).split(QDir::separator(), QString::SkipEmptyParts);
#else
auto parts = QDir::toNativeSeparators(info.path()).split(QDir::separator(), Qt::SkipEmptyParts);
#endif
int numParts = parts.length();
numParts -= parts.count(".");
@ -764,11 +740,7 @@ QString pathTruncate(const QString& path, int depth)
return pathTruncate(trunc, depth);
}
#if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
auto parts = QDir::toNativeSeparators(trunc).split(QDir::separator(), QString::SkipEmptyParts);
#else
auto parts = QDir::toNativeSeparators(trunc).split(QDir::separator(), Qt::SkipEmptyParts);
#endif
if (parts.startsWith(".") && !path.startsWith(".")) {
parts.removeFirst();
@ -950,7 +922,7 @@ bool createShortcut(QString destination, QString target, QStringList args, QStri
QDir content = application.path() + "/Contents/";
QDir resources = content.path() + "/Resources/";
QDir binaryDir = content.path() + "/MacOS/";
QFile info = content.path() + "/Info.plist";
QFile info(content.path() + "/Info.plist");
if (!(content.mkpath(".") && resources.mkpath(".") && binaryDir.mkpath("."))) {
qWarning() << "Couldn't create directories within application";
@ -971,8 +943,7 @@ bool createShortcut(QString destination, QString target, QStringList args, QStri
if (!args.empty())
argstring = " \"" + args.join("\" \"") + "\"";
stream << "#!/bin/bash"
<< "\n";
stream << "#!/bin/bash" << "\n";
stream << "\"" << target << "\" " << argstring << "\n";
stream.flush();
@ -1016,12 +987,9 @@ bool createShortcut(QString destination, QString target, QStringList args, QStri
if (!args.empty())
argstring = " '" + args.join("' '") + "'";
stream << "[Desktop Entry]"
<< "\n";
stream << "Type=Application"
<< "\n";
stream << "Categories=Game;ActionGame;AdventureGame;Simulation"
<< "\n";
stream << "[Desktop Entry]" << "\n";
stream << "Type=Application" << "\n";
stream << "Categories=Game;ActionGame;AdventureGame;Simulation" << "\n";
stream << "Exec=\"" << target.toLocal8Bit() << "\"" << argstring.toLocal8Bit() << "\n";
stream << "Name=" << name.toLocal8Bit() << "\n";
if (!icon.isEmpty()) {
@ -1299,7 +1267,7 @@ bool clone::operator()(const QString& offset, bool dryRun)
std::error_code err;
// Function that'll do the actual cloneing
auto cloneFile = [&](QString src_path, QString relative_dst_path) {
auto cloneFile = [this, dryRun, dst, &err](QString src_path, QString relative_dst_path) {
if (m_matcher && (m_matcher->matches(relative_dst_path) != m_whitelist))
return;

View File

@ -115,7 +115,7 @@ class copy : public QObject {
m_followSymlinks = follow;
return *this;
}
copy& matcher(const IPathMatcher* filter)
copy& matcher(IPathMatcher::Ptr filter)
{
m_matcher = filter;
return *this;
@ -147,7 +147,7 @@ class copy : public QObject {
private:
bool m_followSymlinks = true;
const IPathMatcher* m_matcher = nullptr;
IPathMatcher::Ptr m_matcher = nullptr;
bool m_whitelist = false;
bool m_overwrite = false;
QDir m_src;
@ -209,7 +209,7 @@ class create_link : public QObject {
m_useHardLinks = useHard;
return *this;
}
create_link& matcher(const IPathMatcher* filter)
create_link& matcher(IPathMatcher::Ptr filter)
{
m_matcher = filter;
return *this;
@ -260,7 +260,7 @@ class create_link : public QObject {
private:
bool m_useHardLinks = false;
const IPathMatcher* m_matcher = nullptr;
IPathMatcher::Ptr m_matcher = nullptr;
bool m_whitelist = false;
bool m_recursive = true;
@ -488,7 +488,7 @@ class clone : public QObject {
m_src.setPath(src);
m_dst.setPath(dst);
}
clone& matcher(const IPathMatcher* filter)
clone& matcher(IPathMatcher::Ptr filter)
{
m_matcher = filter;
return *this;
@ -514,7 +514,7 @@ class clone : public QObject {
bool operator()(const QString& offset, bool dryRun = false);
private:
const IPathMatcher* m_matcher = nullptr;
IPathMatcher::Ptr m_matcher = nullptr;
bool m_whitelist = false;
QDir m_src;
QDir m_dst;

View File

@ -36,6 +36,8 @@
#include "GZip.h"
#include <zlib.h>
#include <QByteArray>
#include <QDebug>
#include <QFile>
bool GZip::unzip(const QByteArray& compressedBytes, QByteArray& uncompressedBytes)
{
@ -136,3 +138,81 @@ bool GZip::zip(const QByteArray& uncompressedBytes, QByteArray& compressedBytes)
}
return true;
}
int inf(QFile* source, std::function<bool(const QByteArray&)> handleBlock)
{
constexpr auto CHUNK = 16384;
int ret;
unsigned have;
z_stream strm;
memset(&strm, 0, sizeof(strm));
char in[CHUNK];
unsigned char out[CHUNK];
ret = inflateInit2(&strm, (16 + MAX_WBITS));
if (ret != Z_OK)
return ret;
/* decompress until deflate stream ends or end of file */
do {
strm.avail_in = source->read(in, CHUNK);
if (source->error()) {
(void)inflateEnd(&strm);
return Z_ERRNO;
}
if (strm.avail_in == 0)
break;
strm.next_in = reinterpret_cast<Bytef*>(in);
/* run inflate() on input until output buffer not full */
do {
strm.avail_out = CHUNK;
strm.next_out = out;
ret = inflate(&strm, Z_NO_FLUSH);
assert(ret != Z_STREAM_ERROR); /* state not clobbered */
switch (ret) {
case Z_NEED_DICT:
ret = Z_DATA_ERROR; /* and fall through */
case Z_DATA_ERROR:
case Z_MEM_ERROR:
(void)inflateEnd(&strm);
return ret;
}
have = CHUNK - strm.avail_out;
if (!handleBlock(QByteArray(reinterpret_cast<const char*>(out), have))) {
(void)inflateEnd(&strm);
return Z_OK;
}
} while (strm.avail_out == 0);
/* done when inflate() says it's done */
} while (ret != Z_STREAM_END);
/* clean up and return */
(void)inflateEnd(&strm);
return ret == Z_STREAM_END ? Z_OK : Z_DATA_ERROR;
}
QString zerr(int ret)
{
switch (ret) {
case Z_ERRNO:
return QObject::tr("error handling file");
case Z_STREAM_ERROR:
return QObject::tr("invalid compression level");
case Z_DATA_ERROR:
return QObject::tr("invalid or incomplete deflate data");
case Z_MEM_ERROR:
return QObject::tr("out of memory");
case Z_VERSION_ERROR:
return QObject::tr("zlib version mismatch!");
}
return {};
}
QString GZip::readGzFileByBlocks(QFile* source, std::function<bool(const QByteArray&)> handleBlock)
{
auto ret = inf(source, handleBlock);
return zerr(ret);
}

View File

@ -1,8 +1,11 @@
#pragma once
#include <QByteArray>
#include <QFile>
class GZip {
public:
static bool unzip(const QByteArray& compressedBytes, QByteArray& uncompressedBytes);
static bool zip(const QByteArray& uncompressedBytes, QByteArray& compressedBytes);
};
namespace GZip {
bool unzip(const QByteArray& compressedBytes, QByteArray& uncompressedBytes);
bool zip(const QByteArray& uncompressedBytes, QByteArray& compressedBytes);
QString readGzFileByBlocks(QFile* source, std::function<bool(const QByteArray&)> handleBlock);
} // namespace GZip

View File

@ -43,7 +43,7 @@ void InstanceCopyTask::executeTask()
m_copyFuture = QtConcurrent::run(QThreadPool::globalInstance(), [this] {
if (m_useClone) {
FS::clone folderClone(m_origInstance->instanceRoot(), m_stagingPath);
folderClone.matcher(m_matcher.get());
folderClone.matcher(m_matcher);
folderClone(true);
setProgress(0, folderClone.totalCloned());
@ -72,7 +72,7 @@ void InstanceCopyTask::executeTask()
}
FS::create_link folderLink(m_origInstance->instanceRoot(), m_stagingPath);
int depth = m_linkRecursively ? -1 : 0; // we need to at least link the top level instead of the instance folder
folderLink.linkRecursively(true).setMaxDepth(depth).useHardLinks(m_useHardLinks).matcher(m_matcher.get());
folderLink.linkRecursively(true).setMaxDepth(depth).useHardLinks(m_useHardLinks).matcher(m_matcher);
folderLink(true);
setProgress(0, m_progressTotal + folderLink.totalToLink());
@ -91,7 +91,7 @@ void InstanceCopyTask::executeTask()
QEventLoop loop;
bool got_priv_results = false;
connect(&folderLink, &FS::create_link::finishedPrivileged, this, [&](bool gotResults) {
connect(&folderLink, &FS::create_link::finishedPrivileged, this, [&got_priv_results, &loop](bool gotResults) {
if (!gotResults) {
qDebug() << "Privileged run exited without results!";
}
@ -127,7 +127,7 @@ void InstanceCopyTask::executeTask()
return !there_were_errors;
}
FS::copy folderCopy(m_origInstance->instanceRoot(), m_stagingPath);
folderCopy.followSymlinks(false).matcher(m_matcher.get());
folderCopy.followSymlinks(false).matcher(m_matcher);
folderCopy(true);
setProgress(0, folderCopy.totalCopied());

View File

@ -28,7 +28,7 @@ class InstanceCopyTask : public InstanceTask {
InstancePtr m_origInstance;
QFuture<bool> m_copyFuture;
QFutureWatcher<bool> m_copyFutureWatcher;
std::unique_ptr<IPathMatcher> m_matcher;
IPathMatcher::Ptr m_matcher;
bool m_keepPlaytime;
bool m_useLinks = false;
bool m_useHardLinks = false;

View File

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

View File

@ -0,0 +1,126 @@
// SPDX-License-Identifier: GPL-3.0-only
/*
* Prism Launcher - Minecraft Launcher
*
* 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/>.
*
* This file incorporates work covered by the following copyright and
* permission notice:
*
* Copyright 2013-2021 MultiMC Contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "InstanceDirUpdate.h"
#include <QCheckBox>
#include "Application.h"
#include "FileSystem.h"
#include "InstanceList.h"
#include "ui/dialogs/CustomMessageBox.h"
QString askToUpdateInstanceDirName(InstancePtr instance, const QString& oldName, const QString& newName, QWidget* parent)
{
if (oldName == newName)
return QString();
QString renamingMode = APPLICATION->settings()->get("InstRenamingMode").toString();
if (renamingMode == "MetadataOnly")
return QString();
auto oldRoot = instance->instanceRoot();
auto newDirName = FS::DirNameFromString(newName, QFileInfo(oldRoot).dir().absolutePath());
auto newRoot = FS::PathCombine(QFileInfo(oldRoot).dir().absolutePath(), newDirName);
if (oldRoot == newRoot)
return QString();
if (oldRoot == FS::PathCombine(QFileInfo(oldRoot).dir().absolutePath(), newName))
return QString();
// Check for conflict
if (QDir(newRoot).exists()) {
QMessageBox::warning(parent, QObject::tr("Cannot rename instance"),
QObject::tr("New instance root (%1) already exists. <br />Only the metadata will be renamed.").arg(newRoot));
return QString();
}
// Ask if we should rename
if (renamingMode == "AskEverytime") {
auto checkBox = new QCheckBox(QObject::tr("&Remember my choice"), parent);
auto dialog =
CustomMessageBox::selectable(parent, QObject::tr("Rename instance folder"),
QObject::tr("Would you also like to rename the instance folder?\n\n"
"Old name: %1\n"
"New name: %2")
.arg(oldName, newName),
QMessageBox::Question, QMessageBox::No | QMessageBox::Yes, QMessageBox::NoButton, checkBox);
auto res = dialog->exec();
if (checkBox->isChecked()) {
if (res == QMessageBox::Yes)
APPLICATION->settings()->set("InstRenamingMode", "PhysicalDir");
else
APPLICATION->settings()->set("InstRenamingMode", "MetadataOnly");
}
if (res == QMessageBox::No)
return QString();
}
// Check for linked instances
if (!checkLinkedInstances(instance->id(), parent, QObject::tr("Renaming")))
return QString();
// Now we can confirm that a renaming is happening
if (!instance->syncInstanceDirName(newRoot)) {
QMessageBox::warning(parent, QObject::tr("Cannot rename instance"),
QObject::tr("An error occurred when performing the following renaming operation: <br/>"
" - Old instance root: %1<br/>"
" - New instance root: %2<br/>"
"Only the metadata is renamed.")
.arg(oldRoot, newRoot));
return QString();
}
return newRoot;
}
bool checkLinkedInstances(const QString& id, QWidget* parent, const QString& verb)
{
auto linkedInstances = APPLICATION->instances()->getLinkedInstancesById(id);
if (!linkedInstances.empty()) {
auto response = CustomMessageBox::selectable(parent, QObject::tr("There are linked instances"),
QObject::tr("The following instance(s) might reference files in this instance:\n\n"
"%1\n\n"
"%2 it could break the other instance(s), \n\n"
"Do you wish to proceed?",
nullptr, linkedInstances.count())
.arg(linkedInstances.join("\n"))
.arg(verb),
QMessageBox::Warning, QMessageBox::Yes | QMessageBox::No, QMessageBox::No)
->exec();
if (response != QMessageBox::Yes)
return false;
}
return true;
}

View File

@ -0,0 +1,43 @@
// SPDX-License-Identifier: GPL-3.0-only
/*
* Prism Launcher - Minecraft Launcher
*
* 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/>.
*
* This file incorporates work covered by the following copyright and
* permission notice:
*
* Copyright 2013-2021 MultiMC Contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#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);
/// 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

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

View File

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

View File

@ -428,7 +428,7 @@ static QMap<InstanceId, InstanceLocator> getIdMapping(const QList<InstancePtr>&
QList<InstanceId> InstanceList::discoverInstances()
{
qDebug() << "Discovering instances in" << m_instDir;
qInfo() << "Discovering instances in" << m_instDir;
QList<InstanceId> out;
QDirIterator iter(m_instDir, QDir::Dirs | QDir::NoDot | QDir::NoDotDot | QDir::Readable | QDir::Hidden, QDirIterator::FollowSymlinks);
while (iter.hasNext()) {
@ -447,13 +447,9 @@ QList<InstanceId> InstanceList::discoverInstances()
}
auto id = dirInfo.fileName();
out.append(id);
qDebug() << "Found instance ID" << id;
qInfo() << "Found instance ID" << id;
}
#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)
instanceSet = QSet<QString>(out.begin(), out.end());
#else
instanceSet = out.toSet();
#endif
m_instancesProbed = true;
return out;
}
@ -468,7 +464,7 @@ InstanceList::InstListError InstanceList::loadList()
if (existingIds.contains(id)) {
auto instPair = existingIds[id];
existingIds.remove(id);
qDebug() << "Should keep and soft-reload" << id;
qInfo() << "Should keep and soft-reload" << id;
} else {
InstancePtr instPtr = loadInstance(id);
if (instPtr) {
@ -487,7 +483,7 @@ InstanceList::InstListError InstanceList::loadList()
int front_bookmark = -1;
int back_bookmark = -1;
int currentItem = -1;
auto removeNow = [&]() {
auto removeNow = [this, &front_bookmark, &back_bookmark, &currentItem]() {
beginRemoveRows(QModelIndex(), front_bookmark, back_bookmark);
m_instances.erase(m_instances.begin() + front_bookmark, m_instances.begin() + back_bookmark + 1);
endRemoveRows();

View File

@ -43,11 +43,8 @@ class InstancePageProvider : protected QObject, public BasePageProvider {
values.append(new ServersPage(onesix));
// values.append(new GameOptionsPage(onesix.get()));
values.append(new ScreenshotsPage(FS::PathCombine(onesix->gameRoot(), "screenshots")));
values.append(new InstanceSettingsPage(onesix.get()));
auto logMatcher = inst->getLogFileMatcher();
if (logMatcher) {
values.append(new OtherLogsPage(inst->getLogFileRoot(), logMatcher));
}
values.append(new InstanceSettingsPage(onesix));
values.append(new OtherLogsPage(inst));
return values;
}

View File

@ -41,7 +41,9 @@
bool JavaCommon::checkJVMArgs(QString jvmargs, QWidget* parent)
{
if (jvmargs.contains("-XX:PermSize=") || jvmargs.contains(QRegularExpression("-Xm[sx]")) || jvmargs.contains("-XX-MaxHeapSize") ||
static const QRegularExpression s_memRegex("-Xm[sx]");
static const QRegularExpression s_versionRegex("-version:.*");
if (jvmargs.contains("-XX:PermSize=") || jvmargs.contains(s_memRegex) || jvmargs.contains("-XX-MaxHeapSize") ||
jvmargs.contains("-XX:InitialHeapSize")) {
auto warnStr = QObject::tr(
"You tried to manually set a JVM memory option (using \"-XX:PermSize\", \"-XX-MaxHeapSize\", \"-XX:InitialHeapSize\", \"-Xmx\" "
@ -52,7 +54,7 @@ bool JavaCommon::checkJVMArgs(QString jvmargs, QWidget* parent)
return false;
}
// block lunacy with passing required version to the JVM
if (jvmargs.contains(QRegularExpression("-version:.*"))) {
if (jvmargs.contains(s_versionRegex)) {
auto warnStr = QObject::tr(
"You tried to pass required Java version argument to the JVM (using \"-version:xxx\"). This is not safe and will not be "
"allowed.\n"
@ -116,7 +118,7 @@ void JavaCommon::TestCheck::run()
emit finished();
return;
}
checker.reset(new JavaChecker(m_path, "", 0, 0, 0, 0, this));
checker.reset(new JavaChecker(m_path, "", 0, 0, 0, 0));
connect(checker.get(), &JavaChecker::checkFinished, this, &JavaCommon::TestCheck::checkFinished);
checker->start();
}
@ -128,7 +130,7 @@ void JavaCommon::TestCheck::checkFinished(const JavaChecker::Result& result)
emit finished();
return;
}
checker.reset(new JavaChecker(m_path, m_args, m_maxMem, m_maxMem, result.javaVersion.requiresPermGen() ? m_permGen : 0, 0, this));
checker.reset(new JavaChecker(m_path, m_args, m_maxMem, m_maxMem, result.javaVersion.requiresPermGen() ? m_permGen : 0, 0));
connect(checker.get(), &JavaChecker::checkFinished, this, &JavaCommon::TestCheck::checkFinishedWithArgs);
checker->start();
}

View File

@ -24,7 +24,7 @@ class TestCheck : public QObject {
TestCheck(QWidget* parent, QString path, QString args, int minMem, int maxMem, int permGen)
: m_parent(parent), m_path(path), m_args(args), m_minMem(minMem), m_maxMem(maxMem), m_permGen(permGen)
{}
virtual ~TestCheck() {};
virtual ~TestCheck() = default;
void run();

View File

@ -188,10 +188,10 @@ T ensureIsType(const QJsonObject& parent, const QString& key, const T default_ =
}
template <typename T>
QVector<T> requireIsArrayOf(const QJsonDocument& doc)
QList<T> requireIsArrayOf(const QJsonDocument& doc)
{
const QJsonArray array = requireArray(doc);
QVector<T> out;
QList<T> out;
for (const QJsonValue val : array) {
out.append(requireIsType<T>(val, "Document"));
}
@ -199,10 +199,10 @@ QVector<T> requireIsArrayOf(const QJsonDocument& doc)
}
template <typename T>
QVector<T> ensureIsArrayOf(const QJsonValue& value, const QString& what = "Value")
QList<T> ensureIsArrayOf(const QJsonValue& value, const QString& what = "Value")
{
const QJsonArray array = ensureIsType<QJsonArray>(value, QJsonArray(), what);
QVector<T> out;
QList<T> out;
for (const QJsonValue val : array) {
out.append(requireIsType<T>(val, what));
}
@ -210,7 +210,7 @@ QVector<T> ensureIsArrayOf(const QJsonValue& value, const QString& what = "Value
}
template <typename T>
QVector<T> ensureIsArrayOf(const QJsonValue& value, const QVector<T> default_, const QString& what = "Value")
QList<T> ensureIsArrayOf(const QJsonValue& value, const QList<T> default_, const QString& what = "Value")
{
if (value.isUndefined()) {
return default_;
@ -220,7 +220,7 @@ QVector<T> ensureIsArrayOf(const QJsonValue& value, const QVector<T> default_, c
/// @throw JsonException
template <typename T>
QVector<T> requireIsArrayOf(const QJsonObject& parent, const QString& key, const QString& what = "__placeholder__")
QList<T> requireIsArrayOf(const QJsonObject& parent, const QString& key, const QString& what = "__placeholder__")
{
const QString localWhat = QString(what).replace("__placeholder__", '\'' + key + '\'');
if (!parent.contains(key)) {
@ -230,10 +230,10 @@ QVector<T> requireIsArrayOf(const QJsonObject& parent, const QString& key, const
}
template <typename T>
QVector<T> ensureIsArrayOf(const QJsonObject& parent,
const QString& key,
const QVector<T>& default_ = QVector<T>(),
const QString& what = "__placeholder__")
QList<T> ensureIsArrayOf(const QJsonObject& parent,
const QString& key,
const QList<T>& default_ = QList<T>(),
const QString& what = "__placeholder__")
{
const QString localWhat = QString(what).replace("__placeholder__", '\'' + key + '\'');
if (!parent.contains(key)) {

View File

@ -43,6 +43,7 @@
#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"
@ -61,7 +62,7 @@
#include "launch/steps/TextPrint.h"
#include "tasks/Task.h"
LaunchController::LaunchController(QObject* parent) : Task(parent) {}
LaunchController::LaunchController() : Task() {}
void LaunchController::executeTask()
{
@ -181,7 +182,8 @@ void LaunchController::login()
auto name = askOfflineName("Player", m_demo, ok);
if (ok) {
m_session = std::make_shared<AuthSession>();
m_session->MakeDemo(name, MinecraftAccount::uuidFromUsername(name).toString().remove(QRegularExpression("[{}-]")));
static const QRegularExpression s_removeChars("[{}-]");
m_session->MakeDemo(name, MinecraftAccount::uuidFromUsername(name).toString().remove(s_removeChars));
launchInstance();
return;
}
@ -199,8 +201,7 @@ void LaunchController::login()
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
auto accounts = APPLICATION->accounts();
accounts->requestRefresh(m_accountToUse->internalId());
m_accountToUse->refresh();
}
while (tryagain) {
if (tries > 0 && tries % 3 == 0) {
@ -219,13 +220,34 @@ void LaunchController::login()
m_session->demo = m_demo;
m_accountToUse->fillSession(m_session);
// Launch immediately in true offline mode
if (m_accountToUse->accountType() == AccountType::Offline) {
launchInstance();
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 (m_accountToUse->accountState()) {
switch (accountToCheck->accountState()) {
case AccountState::Offline: {
m_session->wants_online = false;
}
@ -234,46 +256,41 @@ void LaunchController::login()
if (!m_session->wants_online) {
// we ask the user for a player name
bool ok = false;
auto name = askOfflineName(m_session->player_name, m_session->demo, ok);
if (!ok) {
tryagain = false;
break;
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
}
if (m_accountToUse->ownsMinecraft()) {
if (!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;
}
}
// we own Minecraft, there is a profile, it's all ready to go!
launchInstance();
return;
} else {
// play demo ?
if (!m_session->demo) {
m_session->demo = askPlayDemo();
}
if (m_session->demo) { // play demo here
launchInstance();
} 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("Launch cancelled - account does not own Minecraft."));
emitFailed(tr("Received undetermined session status during login."));
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: {
m_accountToUse->refresh();
accountToCheck->refresh();
}
/* fallthrough */
case AccountState::Working: {
@ -282,19 +299,19 @@ void LaunchController::login()
if (m_online) {
progDialog.setSkipButton(true, tr("Play Offline"));
}
auto task = m_accountToUse->currentTask();
auto task = accountToCheck->currentTask();
progDialog.execWithTask(task.get());
continue;
}
case AccountState::Expired: {
auto errorString = tr("The account has expired and needs to be logged into manually again.");
QMessageBox::warning(m_parentWidget, tr("Account refresh failed"), errorString, QMessageBox::StandardButton::Ok,
QMessageBox::StandardButton::Ok);
emitFailed(errorString);
if (reauthenticateAccount(accountToCheck))
continue;
return;
}
case AccountState::Disabled: {
auto errorString = tr("The launcher's client identification has changed. Please remove this account and add it again.");
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);
@ -302,8 +319,9 @@ void LaunchController::login()
}
case AccountState::Gone: {
auto errorString =
tr("The account no longer exists on the servers. It may have been migrated, in which case please add the new account "
"you migrated this one to.");
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);
@ -314,6 +332,38 @@ void LaunchController::login()
emitFailed(tr("Failed to launch."));
}
bool LaunchController::reauthenticateAccount(MinecraftAccountPtr account)
{
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()),
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())));
if (account->accountType() == AccountType::MSA) {
auto newAccount = MSALoginDialog::newAccount(m_parentWidget);
if (newAccount != nullptr) {
accounts->addAccount(newAccount);
if (isDefault)
accounts->setDefaultAccount(newAccount);
if (m_accountToUse == account) {
m_accountToUse = nullptr;
decideAccount();
}
return true;
}
}
}
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");

View File

@ -47,7 +47,7 @@ class LaunchController : public Task {
public:
void executeTask() override;
LaunchController(QObject* parent = nullptr);
LaunchController();
virtual ~LaunchController() = default;
void setInstance(InstancePtr instance) { m_instance = instance; }
@ -56,6 +56,8 @@ class LaunchController : public Task {
void setOnline(bool online) { m_online = online; }
void setOfflineName(const QString& offlineName) { m_offlineName = offlineName; }
void setDemo(bool demo) { m_demo = demo; }
void setProfiler(BaseProfilerFactory* profiler) { m_profiler = profiler; }
@ -76,6 +78,7 @@ class LaunchController : public Task {
void decideAccount();
bool askPlayDemo();
QString askOfflineName(QString playerName, bool demo, bool& ok);
bool reauthenticateAccount(MinecraftAccountPtr account);
private slots:
void readyForLaunch();
@ -87,6 +90,7 @@ class LaunchController : public Task {
private:
BaseProfilerFactory* m_profiler = nullptr;
bool m_online = true;
QString m_offlineName;
bool m_demo = false;
InstancePtr m_instance;
QWidget* m_parentWidget = nullptr;

View File

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

View File

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

View File

@ -2,19 +2,22 @@
MessageLevel::Enum MessageLevel::getLevel(const QString& levelName)
{
if (levelName == "Launcher")
QString name = levelName.toUpper();
if (name == "LAUNCHER")
return MessageLevel::Launcher;
else if (levelName == "Debug")
else if (name == "TRACE")
return MessageLevel::Trace;
else if (name == "DEBUG")
return MessageLevel::Debug;
else if (levelName == "Info")
else if (name == "INFO")
return MessageLevel::Info;
else if (levelName == "Message")
else if (name == "MESSAGE")
return MessageLevel::Message;
else if (levelName == "Warning")
else if (name == "WARNING" || name == "WARN")
return MessageLevel::Warning;
else if (levelName == "Error")
else if (name == "ERROR")
return MessageLevel::Error;
else if (levelName == "Fatal")
else if (name == "FATAL")
return MessageLevel::Fatal;
// Skip PrePost, it's not exposed to !![]!
// Also skip StdErr and StdOut

View File

@ -12,6 +12,7 @@ enum Enum {
StdOut, /**< Undetermined stderr messages */
StdErr, /**< Undetermined stdout messages */
Launcher, /**< Launcher Messages */
Trace, /**< Trace Messages */
Debug, /**< Debug Messages */
Info, /**< Info Messages */
Message, /**< Standard Messages */

View File

@ -57,8 +57,7 @@ class NullInstance : public BaseInstance {
QProcessEnvironment createEnvironment() override { return QProcessEnvironment(); }
QProcessEnvironment createLaunchEnvironment() override { return QProcessEnvironment(); }
QMap<QString, QString> getVariables() override { return QMap<QString, QString>(); }
IPathMatcher::Ptr getLogFileMatcher() override { return nullptr; }
QString getLogFileRoot() override { return instanceRoot(); }
QStringList getLogFileSearchPaths() override { return {}; }
QString typeName() const override { return "Null"; }
bool canExport() const override { return false; }
bool canEdit() const override { return false; }

71
launcher/PSaveFile.h Normal file
View File

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

View File

@ -33,7 +33,7 @@ class shared_qobject_ptr : public QSharedPointer<T> {
{}
void reset() { QSharedPointer<T>::reset(); }
void reset(T*&& other)
void reset(T* other)
{
shared_qobject_ptr<T> t(other);
this->swap(t);

View File

@ -1,7 +1,6 @@
#include "RecursiveFileSystemWatcher.h"
#include <QDebug>
#include <QRegularExpression>
RecursiveFileSystemWatcher::RecursiveFileSystemWatcher(QObject* parent) : QObject(parent), m_watcher(new QFileSystemWatcher(this))
{

View File

@ -35,9 +35,9 @@ ResourceDownloadTask::ResourceDownloadTask(ModPlatform::IndexedPack::Ptr pack,
QString custom_target_folder)
: m_pack(std::move(pack)), m_pack_version(std::move(version)), m_pack_model(packs), m_custom_target_folder(custom_target_folder)
{
if (auto model = dynamic_cast<ModFolderModel*>(m_pack_model.get()); model && is_indexed) {
m_update_task.reset(new LocalModUpdateTask(model->indexDir(), *m_pack, m_pack_version));
connect(m_update_task.get(), &LocalModUpdateTask::hasOldMod, this, &ResourceDownloadTask::hasOldResource);
if (is_indexed) {
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);
addTask(m_update_task);
}
@ -91,12 +91,8 @@ void ResourceDownloadTask::downloadSucceeded()
m_filesNetJob.reset();
auto name = std::get<0>(to_delete);
auto filename = std::get<1>(to_delete);
if (!name.isEmpty() && filename != m_pack_version.fileName) {
if (auto model = dynamic_cast<ModFolderModel*>(m_pack_model.get()); model)
model->uninstallMod(filename, true);
else
m_pack_model->uninstallResource(filename);
}
if (!name.isEmpty() && filename != m_pack_version.fileName)
m_pack_model->uninstallResource(filename, true);
}
void ResourceDownloadTask::downloadFailed(QString reason)

View File

@ -22,7 +22,7 @@
#include "net/NetJob.h"
#include "tasks/SequentialTask.h"
#include "minecraft/mod/tasks/LocalModUpdateTask.h"
#include "minecraft/mod/tasks/LocalResourceUpdateTask.h"
#include "modplatform/ModIndex.h"
class ResourceFolderModel;
@ -50,7 +50,7 @@ class ResourceDownloadTask : public SequentialTask {
QString m_custom_target_folder;
NetJob::Ptr m_filesNetJob;
LocalModUpdateTask::Ptr m_update_task;
LocalResourceUpdateTask::Ptr m_update_task;
void downloadProgressChanged(qint64 current, qint64 total);
void downloadFailed(QString reason);

View File

@ -53,7 +53,7 @@ static inline QChar getNextChar(const QString& s, int location)
int StringUtils::naturalCompare(const QString& s1, const QString& s2, Qt::CaseSensitivity cs)
{
int l1 = 0, l2 = 0;
while (l1 <= s1.count() && l2 <= s2.count()) {
while (l1 <= s1.size() && l2 <= s2.size()) {
// skip spaces, tabs and 0's
QChar c1 = getNextChar(s1, l1);
while (c1.isSpace())
@ -213,11 +213,10 @@ QPair<QString, QString> StringUtils::splitFirst(const QString& s, const QRegular
return qMakePair(left, right);
}
static const QRegularExpression ulMatcher("<\\s*/\\s*ul\\s*>");
QString StringUtils::htmlListPatch(QString htmlStr)
{
int pos = htmlStr.indexOf(ulMatcher);
static const QRegularExpression s_ulMatcher("<\\s*/\\s*ul\\s*>");
int pos = htmlStr.indexOf(s_ulMatcher);
int imgPos;
while (pos != -1) {
pos = htmlStr.indexOf(">", pos) + 1; // Get the size of the </ul> tag. Add one for zeroeth index
@ -230,7 +229,7 @@ QString StringUtils::htmlListPatch(QString htmlStr)
if (textBetween.isEmpty())
htmlStr.insert(pos, "<br>");
pos = htmlStr.indexOf(ulMatcher, pos);
pos = htmlStr.indexOf(s_ulMatcher, pos);
}
return htmlStr;
}

View File

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

View File

@ -1,7 +1,6 @@
#include "Version.h"
#include <QDebug>
#include <QRegularExpression>
#include <QRegularExpressionMatch>
#include <QUrl>
@ -79,7 +78,7 @@ void Version::parse()
if (m_string.isEmpty())
return;
auto classChange = [&](QChar lastChar, QChar currentChar) {
auto classChange = [&currentSection](QChar lastChar, QChar currentChar) {
if (lastChar.isNull())
return false;
if (lastChar.isDigit() != currentChar.isDigit())

View File

@ -72,22 +72,14 @@ class Version {
}
}
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
auto numPart = QStringView{ m_fullString }.left(cutoff);
#else
auto numPart = m_fullString.leftRef(cutoff);
#endif
if (!numPart.isEmpty()) {
m_isNull = false;
m_numPart = numPart.toInt();
}
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
auto stringPart = QStringView{ m_fullString }.mid(cutoff);
#else
auto stringPart = m_fullString.midRef(cutoff);
#endif
if (!stringPart.isEmpty()) {
m_isNull = false;

View File

@ -193,8 +193,8 @@ QVariant VersionProxyModel::data(const QModelIndex& index, int role) const
if (value.toBool()) {
return tr("Recommended");
} else if (hasLatest) {
auto value = sourceModel()->data(parentIndex, BaseVersionList::LatestRole);
if (value.toBool()) {
auto latest = sourceModel()->data(parentIndex, BaseVersionList::LatestRole);
if (latest.toBool()) {
return tr("Latest");
}
}
@ -203,33 +203,27 @@ QVariant VersionProxyModel::data(const QModelIndex& index, int role) const
}
}
case Qt::DecorationRole: {
switch (column) {
case Name: {
if (hasRecommended) {
auto recommenced = sourceModel()->data(parentIndex, BaseVersionList::RecommendedRole);
if (recommenced.toBool()) {
return APPLICATION->getThemedIcon("star");
} else if (hasLatest) {
auto latest = sourceModel()->data(parentIndex, BaseVersionList::LatestRole);
if (latest.toBool()) {
return APPLICATION->getThemedIcon("bug");
}
}
QPixmap pixmap;
QPixmapCache::find("placeholder", &pixmap);
if (!pixmap) {
QPixmap px(16, 16);
px.fill(Qt::transparent);
QPixmapCache::insert("placeholder", px);
return px;
}
return pixmap;
if (column == Name && hasRecommended) {
auto recommenced = sourceModel()->data(parentIndex, BaseVersionList::RecommendedRole);
if (recommenced.toBool()) {
return APPLICATION->getThemedIcon("star");
} else if (hasLatest) {
auto latest = sourceModel()->data(parentIndex, BaseVersionList::LatestRole);
if (latest.toBool()) {
return APPLICATION->getThemedIcon("bug");
}
}
default: {
return QVariant();
QPixmap pixmap;
QPixmapCache::find("placeholder", &pixmap);
if (!pixmap) {
QPixmap px(16, 16);
px.fill(Qt::transparent);
QPixmapCache::insert("placeholder", px);
return px;
}
return pixmap;
}
return QVariant();
}
default: {
if (roles.contains((BaseVersionList::ModelRoles)role)) {
@ -301,7 +295,6 @@ void VersionProxyModel::sourceDataChanged(const QModelIndex& source_top_left, co
void VersionProxyModel::setSourceModel(QAbstractItemModel* replacingRaw)
{
auto replacing = dynamic_cast<BaseVersionList*>(replacingRaw);
beginResetModel();
m_columns.clear();
if (!replacing) {
@ -348,8 +341,6 @@ void VersionProxyModel::setSourceModel(QAbstractItemModel* replacingRaw)
hasLatest = true;
}
filterModel->setSourceModel(replacing);
endResetModel();
}
QModelIndex VersionProxyModel::getRecommended() const

View File

@ -0,0 +1,33 @@
#pragma once
#include <QString>
#include <ostream>
#if defined Q_OS_WIN32
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <windows.h>
#else
#include <unistd.h>
#include <cstdio>
#endif
namespace console {
inline bool isConsole()
{
#if defined Q_OS_WIN32
DWORD procIDs[2];
DWORD maxCount = 2;
DWORD result = GetConsoleProcessList((LPDWORD)procIDs, maxCount);
return result > 1;
#else
if (isatty(fileno(stdout))) {
return true;
}
return false;
#endif
}
} // namespace console

View File

@ -16,13 +16,18 @@
*
*/
#include "WindowsConsole.h"
#include <system_error>
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <windows.h>
#include <fcntl.h>
#include <io.h>
#include <stdio.h>
#include <windows.h>
#include <cstddef>
#include <iostream>
void RedirectHandle(DWORD handle, FILE* stream, const char* mode)
@ -126,3 +131,29 @@ bool AttachWindowsConsole()
return false;
}
std::error_code EnableAnsiSupport()
{
// ref: https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilew
// Using `CreateFileW("CONOUT$", ...)` to retrieve the console handle works correctly even if STDOUT and/or STDERR are redirected
HANDLE console_handle = CreateFileW(L"CONOUT$", FILE_GENERIC_READ | FILE_GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0);
if (console_handle == INVALID_HANDLE_VALUE) {
return std::error_code(GetLastError(), std::system_category());
}
// ref: https://docs.microsoft.com/en-us/windows/console/getconsolemode
DWORD console_mode;
if (0 == GetConsoleMode(console_handle, &console_mode)) {
return std::error_code(GetLastError(), std::system_category());
}
// VT processing not already enabled?
if ((console_mode & ENABLE_VIRTUAL_TERMINAL_PROCESSING) == 0) {
// https://docs.microsoft.com/en-us/windows/console/setconsolemode
if (0 == SetConsoleMode(console_handle, console_mode | ENABLE_VIRTUAL_TERMINAL_PROCESSING)) {
return std::error_code(GetLastError(), std::system_category());
}
}
return {};
}

View File

@ -21,5 +21,8 @@
#pragma once
#include <system_error>
void BindCrtHandlesToStdHandles(bool bindStdIn, bool bindStdOut, bool bindStdErr);
bool AttachWindowsConsole();
std::error_code EnableAnsiSupport();

View File

@ -37,27 +37,14 @@
#include <sys.h>
#if defined Q_OS_WIN32
#include "WindowsConsole.h"
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include "console/WindowsConsole.h"
#endif
// Snippet from https://github.com/gulrak/filesystem#using-it-as-single-file-header
#ifdef __APPLE__
#include <Availability.h> // for deployment target to support pre-catalina targets without std::fs
#endif // __APPLE__
#if ((defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) || (defined(__cplusplus) && __cplusplus >= 201703L)) && defined(__has_include)
#if __has_include(<filesystem>) && (!defined(__MAC_OS_X_VERSION_MIN_REQUIRED) || __MAC_OS_X_VERSION_MIN_REQUIRED >= 101500)
#define GHC_USE_STD_FS
#include <filesystem>
namespace fs = std::filesystem;
#endif // MacOS min version check
#endif // Other OSes version check
#ifndef GHC_USE_STD_FS
#include <ghc/filesystem.hpp>
namespace fs = ghc::filesystem;
#endif
FileLinkApp::FileLinkApp(int& argc, char** argv) : QCoreApplication(argc, argv), socket(new QLocalSocket(this))
{
@ -104,11 +91,11 @@ void FileLinkApp::joinServer(QString server)
in.setDevice(&socket);
connect(&socket, &QLocalSocket::connected, this, [&]() { qDebug() << "connected to server"; });
connect(&socket, &QLocalSocket::connected, this, []() { qDebug() << "connected to server"; });
connect(&socket, &QLocalSocket::readyRead, this, &FileLinkApp::readPathPairs);
connect(&socket, &QLocalSocket::errorOccurred, this, [&](QLocalSocket::LocalSocketError socketError) {
connect(&socket, &QLocalSocket::errorOccurred, this, [this](QLocalSocket::LocalSocketError socketError) {
m_status = Failed;
switch (socketError) {
case QLocalSocket::ServerNotFoundError:
@ -132,7 +119,7 @@ void FileLinkApp::joinServer(QString server)
}
});
connect(&socket, &QLocalSocket::disconnected, this, [&]() {
connect(&socket, &QLocalSocket::disconnected, this, [this]() {
qDebug() << "disconnected from server, should exit";
m_status = Succeeded;
exit();

View File

@ -37,7 +37,6 @@
#include "IconList.h"
#include <FileSystem.h>
#include <QDebug>
#include <QEventLoop>
#include <QFileSystemWatcher>
#include <QMap>
#include <QMimeData>
@ -47,24 +46,24 @@
#define MAX_SIZE 1024
IconList::IconList(const QStringList& builtinPaths, QString path, QObject* parent) : QAbstractListModel(parent)
IconList::IconList(const QStringList& builtinPaths, const QString& path, QObject* parent) : QAbstractListModel(parent)
{
QSet<QString> builtinNames;
// add builtin icons
for (auto& builtinPath : builtinPaths) {
QDir instance_icons(builtinPath);
auto file_info_list = instance_icons.entryInfoList(QDir::Files, QDir::Name);
for (auto file_info : file_info_list) {
builtinNames.insert(file_info.completeBaseName());
for (const auto& builtinPath : builtinPaths) {
QDir instanceIcons(builtinPath);
auto fileInfoList = instanceIcons.entryInfoList(QDir::Files, QDir::Name);
for (const auto& fileInfo : fileInfoList) {
builtinNames.insert(fileInfo.baseName());
}
}
for (auto& builtinName : builtinNames) {
for (const auto& builtinName : builtinNames) {
addThemeIcon(builtinName);
}
m_watcher.reset(new QFileSystemWatcher());
is_watching = false;
m_isWatching = false;
connect(m_watcher.get(), &QFileSystemWatcher::directoryChanged, this, &IconList::directoryChanged);
connect(m_watcher.get(), &QFileSystemWatcher::fileChanged, this, &IconList::fileChanged);
@ -77,91 +76,129 @@ IconList::IconList(const QStringList& builtinPaths, QString path, QObject* paren
void IconList::sortIconList()
{
qDebug() << "Sorting icon list...";
std::sort(icons.begin(), icons.end(), [](const MMCIcon& a, const MMCIcon& b) { return a.m_key.localeAwareCompare(b.m_key) < 0; });
std::sort(m_icons.begin(), m_icons.end(), [](const MMCIcon& a, const MMCIcon& b) {
bool aIsSubdir = a.m_key.contains(QDir::separator());
bool bIsSubdir = b.m_key.contains(QDir::separator());
if (aIsSubdir != bIsSubdir) {
return !aIsSubdir; // root-level icons come first
}
return a.m_key.localeAwareCompare(b.m_key) < 0;
});
reindex();
}
// Helper function to add directories recursively
bool IconList::addPathRecursively(const QString& path)
{
QDir dir(path);
if (!dir.exists())
return false;
// Add the directory itself
bool watching = m_watcher->addPath(path);
// Add all subdirectories
QFileInfoList entries = dir.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot);
for (const QFileInfo& entry : entries) {
if (addPathRecursively(entry.absoluteFilePath())) {
watching = true;
}
}
return watching;
}
QStringList IconList::getIconFilePaths() const
{
QStringList iconFiles{};
QStringList directories{ m_dir.absolutePath() };
while (!directories.isEmpty()) {
QString first = directories.takeFirst();
QDir dir(first);
for (QFileInfo& fileInfo : dir.entryInfoList(QDir::AllDirs | QDir::Files | QDir::NoDotAndDotDot, QDir::Name)) {
if (fileInfo.isDir())
directories.push_back(fileInfo.absoluteFilePath());
else
iconFiles.push_back(fileInfo.absoluteFilePath());
}
}
return iconFiles;
}
QString formatName(const QDir& iconsDir, const QFileInfo& iconFile)
{
if (iconFile.dir() == iconsDir)
return iconFile.baseName();
constexpr auto delimiter = " » ";
QString relativePathWithoutExtension = iconsDir.relativeFilePath(iconFile.dir().path()) + QDir::separator() + iconFile.baseName();
return relativePathWithoutExtension.replace(QDir::separator(), delimiter);
}
/// Split into a separate function because the preprocessing impedes readability
QSet<QString> toStringSet(const QList<QString>& list)
{
QSet<QString> set(list.begin(), list.end());
return set;
}
void IconList::directoryChanged(const QString& path)
{
QDir new_dir(path);
if (m_dir.absolutePath() != new_dir.absolutePath()) {
m_dir.setPath(path);
QDir newDir(path);
if (m_dir.absolutePath() != newDir.absolutePath()) {
if (!path.startsWith(m_dir.absolutePath()))
m_dir.setPath(path);
m_dir.refresh();
if (is_watching)
if (m_isWatching)
stopWatching();
startWatching();
}
if (!m_dir.exists())
if (!FS::ensureFolderPathExists(m_dir.absolutePath()))
return;
if (!m_dir.exists() && !FS::ensureFolderPathExists(m_dir.absolutePath()))
return;
m_dir.refresh();
auto new_list = m_dir.entryList(QDir::Files, QDir::Name);
for (auto it = new_list.begin(); it != new_list.end(); it++) {
QString& foo = (*it);
foo = m_dir.filePath(foo);
}
#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)
QSet<QString> new_set(new_list.begin(), new_list.end());
#else
auto new_set = new_list.toSet();
#endif
QList<QString> current_list;
for (auto& it : icons) {
const QStringList newFileNamesList = getIconFilePaths();
const QSet<QString> newSet = toStringSet(newFileNamesList);
QSet<QString> currentSet;
for (const MMCIcon& it : m_icons) {
if (!it.has(IconType::FileBased))
continue;
current_list.push_back(it.m_images[IconType::FileBased].filename);
QFileInfo icon(it.getFilePath());
currentSet.insert(icon.absoluteFilePath());
}
#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)
QSet<QString> current_set(current_list.begin(), current_list.end());
#else
QSet<QString> current_set = current_list.toSet();
#endif
QSet<QString> toRemove = currentSet - newSet;
QSet<QString> toAdd = newSet - currentSet;
QSet<QString> to_remove = current_set;
to_remove -= new_set;
QSet<QString> to_add = new_set;
to_add -= current_set;
for (auto remove : to_remove) {
qDebug() << "Removing " << remove;
QFileInfo rmfile(remove);
QString key = rmfile.completeBaseName();
QString suffix = rmfile.suffix();
// The icon doesnt have a suffix, but it can have other .s in the name, so we account for those as well
if (!IconUtils::isIconSuffix(suffix))
key = rmfile.fileName();
for (const QString& removedPath : toRemove) {
qDebug() << "Removing icon " << removedPath;
QFileInfo removedFile(removedPath);
QString relativePath = m_dir.relativeFilePath(removedFile.absoluteFilePath());
QString key = QFileInfo(relativePath).completeBaseName();
int idx = getIconIndex(key);
if (idx == -1)
continue;
icons[idx].remove(IconType::FileBased);
if (icons[idx].type() == IconType::ToBeDeleted) {
m_icons[idx].remove(FileBased);
if (m_icons[idx].type() == ToBeDeleted) {
beginRemoveRows(QModelIndex(), idx, idx);
icons.remove(idx);
m_icons.remove(idx);
reindex();
endRemoveRows();
} else {
dataChanged(index(idx), index(idx));
}
m_watcher->removePath(remove);
m_watcher->removePath(removedPath);
emit iconUpdated(key);
}
for (auto add : to_add) {
qDebug() << "Adding " << add;
for (const QString& addedPath : toAdd) {
qDebug() << "Adding icon " << addedPath;
QFileInfo addfile(add);
QString key = addfile.completeBaseName();
QFileInfo addfile(addedPath);
QString relativePath = m_dir.relativeFilePath(addfile.absoluteFilePath());
QString key = QFileInfo(relativePath).completeBaseName();
QString name = formatName(m_dir, addfile);
QString suffix = addfile.suffix();
// The icon doesnt have a suffix, but it can have other .s in the name, so we account for those as well
if (!IconUtils::isIconSuffix(suffix))
key = addfile.fileName();
if (addIcon(key, QString(), addfile.filePath(), IconType::FileBased)) {
m_watcher->addPath(add);
if (addIcon(key, name, addfile.filePath(), IconType::FileBased)) {
m_watcher->addPath(addedPath);
emit iconUpdated(key);
}
}
@ -171,24 +208,24 @@ void IconList::directoryChanged(const QString& path)
void IconList::fileChanged(const QString& path)
{
qDebug() << "Checking " << path;
qDebug() << "Checking icon " << path;
QFileInfo checkfile(path);
if (!checkfile.exists())
return;
QString key = checkfile.completeBaseName();
QString key = m_dir.relativeFilePath(checkfile.absoluteFilePath());
int idx = getIconIndex(key);
if (idx == -1)
return;
QIcon icon(path);
if (!icon.availableSizes().size())
if (icon.availableSizes().empty())
return;
icons[idx].m_images[IconType::FileBased].icon = icon;
m_icons[idx].m_images[IconType::FileBased].icon = icon;
dataChanged(index(idx), index(idx));
emit iconUpdated(key);
}
void IconList::SettingChanged(const Setting& setting, QVariant value)
void IconList::SettingChanged(const Setting& setting, const QVariant& value)
{
if (setting.id() != "IconsDir")
return;
@ -200,8 +237,8 @@ void IconList::startWatching()
{
auto abs_path = m_dir.absolutePath();
FS::ensureFolderPathExists(abs_path);
is_watching = m_watcher->addPath(abs_path);
if (is_watching) {
m_isWatching = addPathRecursively(abs_path);
if (m_isWatching) {
qDebug() << "Started watching " << abs_path;
} else {
qDebug() << "Failed to start watching " << abs_path;
@ -212,7 +249,7 @@ void IconList::stopWatching()
{
m_watcher->removePaths(m_watcher->files());
m_watcher->removePaths(m_watcher->directories());
is_watching = false;
m_isWatching = false;
}
QStringList IconList::mimeTypes() const
@ -242,7 +279,7 @@ bool IconList::dropMimeData(const QMimeData* data,
if (data->hasUrls()) {
auto urls = data->urls();
QStringList iconFiles;
for (auto url : urls) {
for (const auto& url : urls) {
// only local files may be dropped...
if (!url.isLocalFile())
continue;
@ -263,33 +300,33 @@ Qt::ItemFlags IconList::flags(const QModelIndex& index) const
QVariant IconList::data(const QModelIndex& index, int role) const
{
if (!index.isValid())
return QVariant();
return {};
int row = index.row();
if (row < 0 || row >= icons.size())
return QVariant();
if (row < 0 || row >= m_icons.size())
return {};
switch (role) {
case Qt::DecorationRole:
return icons[row].icon();
return m_icons[row].icon();
case Qt::DisplayRole:
return icons[row].name();
return m_icons[row].name();
case Qt::UserRole:
return icons[row].m_key;
return m_icons[row].m_key;
default:
return QVariant();
return {};
}
}
int IconList::rowCount(const QModelIndex& parent) const
{
return parent.isValid() ? 0 : icons.size();
return parent.isValid() ? 0 : m_icons.size();
}
void IconList::installIcons(const QStringList& iconFiles)
{
for (QString file : iconFiles)
for (const QString& file : iconFiles)
installIcon(file, {});
}
@ -312,12 +349,13 @@ bool IconList::iconFileExists(const QString& key) const
return iconEntry && iconEntry->has(IconType::FileBased);
}
/// Returns the icon with the given key or nullptr if it doesn't exist.
const MMCIcon* IconList::icon(const QString& key) const
{
int iconIdx = getIconIndex(key);
if (iconIdx == -1)
return nullptr;
return &icons[iconIdx];
return &m_icons[iconIdx];
}
bool IconList::deleteIcon(const QString& key)
@ -332,22 +370,22 @@ bool IconList::trashIcon(const QString& key)
bool IconList::addThemeIcon(const QString& key)
{
auto iter = name_index.find(key);
if (iter != name_index.end()) {
auto& oldOne = icons[*iter];
auto iter = m_nameIndex.find(key);
if (iter != m_nameIndex.end()) {
auto& oldOne = m_icons[*iter];
oldOne.replace(Builtin, key);
dataChanged(index(*iter), index(*iter));
return true;
}
// add a new icon
beginInsertRows(QModelIndex(), icons.size(), icons.size());
beginInsertRows(QModelIndex(), m_icons.size(), m_icons.size());
{
MMCIcon mmc_icon;
mmc_icon.m_name = key;
mmc_icon.m_key = key;
mmc_icon.replace(Builtin, key);
icons.push_back(mmc_icon);
name_index[key] = icons.size() - 1;
m_icons.push_back(mmc_icon);
m_nameIndex[key] = m_icons.size() - 1;
}
endInsertRows();
return true;
@ -359,22 +397,22 @@ bool IconList::addIcon(const QString& key, const QString& name, const QString& p
QIcon icon(path);
if (icon.isNull())
return false;
auto iter = name_index.find(key);
if (iter != name_index.end()) {
auto& oldOne = icons[*iter];
auto iter = m_nameIndex.find(key);
if (iter != m_nameIndex.end()) {
auto& oldOne = m_icons[*iter];
oldOne.replace(type, icon, path);
dataChanged(index(*iter), index(*iter));
return true;
}
// add a new icon
beginInsertRows(QModelIndex(), icons.size(), icons.size());
beginInsertRows(QModelIndex(), m_icons.size(), m_icons.size());
{
MMCIcon mmc_icon;
mmc_icon.m_name = name;
mmc_icon.m_key = key;
mmc_icon.replace(type, icon, path);
icons.push_back(mmc_icon);
name_index[key] = icons.size() - 1;
m_icons.push_back(mmc_icon);
m_nameIndex[key] = m_icons.size() - 1;
}
endInsertRows();
return true;
@ -389,33 +427,32 @@ void IconList::saveIcon(const QString& key, const QString& path, const char* for
void IconList::reindex()
{
name_index.clear();
int i = 0;
for (auto& iter : icons) {
name_index[iter.m_key] = i;
i++;
m_nameIndex.clear();
for (int i = 0; i < m_icons.size(); i++) {
m_nameIndex[m_icons[i].m_key] = i;
emit iconUpdated(m_icons[i].m_key); // prevents incorrect indices with proxy model
}
}
QIcon IconList::getIcon(const QString& key) const
{
int icon_index = getIconIndex(key);
int iconIndex = getIconIndex(key);
if (icon_index != -1)
return icons[icon_index].icon();
if (iconIndex != -1)
return m_icons[iconIndex].icon();
// Fallback for icons that don't exist.
icon_index = getIconIndex("grass");
// Fallback for icons that don't exist.b
iconIndex = getIconIndex("grass");
if (icon_index != -1)
return icons[icon_index].icon();
return QIcon();
if (iconIndex != -1)
return m_icons[iconIndex].icon();
return {};
}
int IconList::getIconIndex(const QString& key) const
{
auto iter = name_index.find(key == "default" ? "grass" : key);
if (iter != name_index.end())
auto iter = m_nameIndex.find(key == "default" ? "grass" : key);
if (iter != m_nameIndex.end())
return *iter;
return -1;
@ -425,3 +462,15 @@ QString IconList::getDirectory() const
{
return m_dir.absolutePath();
}
/// Returns the directory of the icon with the given key or the default directory if it's a builtin icon.
QString IconList::iconDirectory(const QString& key) const
{
for (const auto& mmcIcon : m_icons) {
if (mmcIcon.m_key == key && mmcIcon.has(IconType::FileBased)) {
QFileInfo iconFile(mmcIcon.getFilePath());
return iconFile.dir().path();
}
}
return getDirectory();
}

View File

@ -51,7 +51,7 @@ class QFileSystemWatcher;
class IconList : public QAbstractListModel {
Q_OBJECT
public:
explicit IconList(const QStringList& builtinPaths, QString path, QObject* parent = 0);
explicit IconList(const QStringList& builtinPaths, const QString& path, QObject* parent = 0);
virtual ~IconList() {};
QIcon getIcon(const QString& key) const;
@ -72,6 +72,7 @@ class IconList : public QAbstractListModel {
bool deleteIcon(const QString& key);
bool trashIcon(const QString& key);
bool iconFileExists(const QString& key) const;
QString iconDirectory(const QString& key) const;
void installIcons(const QStringList& iconFiles);
void installIcon(const QString& file, const QString& name);
@ -91,18 +92,20 @@ class IconList : public QAbstractListModel {
IconList& operator=(const IconList&) = delete;
void reindex();
void sortIconList();
bool addPathRecursively(const QString& path);
QStringList getIconFilePaths() const;
public slots:
void directoryChanged(const QString& path);
protected slots:
void fileChanged(const QString& path);
void SettingChanged(const Setting& setting, QVariant value);
void SettingChanged(const Setting& setting, const QVariant& value);
private:
shared_qobject_ptr<QFileSystemWatcher> m_watcher;
bool is_watching;
QMap<QString, int> name_index;
QVector<MMCIcon> icons;
bool m_isWatching;
QMap<QString, int> m_nameIndex;
QList<MMCIcon> m_icons;
QDir m_dir;
};

View File

@ -44,8 +44,8 @@
#include "FileSystem.h"
#include "java/JavaUtils.h"
JavaChecker::JavaChecker(QString path, QString args, int minMem, int maxMem, int permGen, int id, QObject* parent)
: Task(parent), m_path(path), m_args(args), m_minMem(minMem), m_maxMem(maxMem), m_permGen(permGen), m_id(id)
JavaChecker::JavaChecker(QString path, QString args, int minMem, int maxMem, int permGen, int id)
: Task(), m_path(path), m_args(args), m_minMem(minMem), m_maxMem(maxMem), m_permGen(permGen), m_id(id)
{}
void JavaChecker::executeTask()
@ -137,11 +137,7 @@ void JavaChecker::finished(int exitcode, QProcess::ExitStatus status)
QMap<QString, QString> results;
#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)
QStringList lines = m_stdout.split("\n", Qt::SkipEmptyParts);
#else
QStringList lines = m_stdout.split("\n", QString::SkipEmptyParts);
#endif
for (QString line : lines) {
line = line.trimmed();
// NOTE: workaround for GH-4125, where garbage is getting printed into stdout on bedrock linux
@ -149,11 +145,7 @@ void JavaChecker::finished(int exitcode, QProcess::ExitStatus status)
continue;
}
#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)
auto parts = line.split('=', Qt::SkipEmptyParts);
#else
auto parts = line.split('=', QString::SkipEmptyParts);
#endif
if (parts.size() != 2 || parts[0].isEmpty() || parts[1].isEmpty()) {
continue;
} else {
@ -171,7 +163,7 @@ void JavaChecker::finished(int exitcode, QProcess::ExitStatus status)
auto os_arch = results["os.arch"];
auto java_version = results["java.version"];
auto java_vendor = results["java.vendor"];
bool is_64 = os_arch == "x86_64" || os_arch == "amd64" || os_arch == "aarch64" || os_arch == "arm64";
bool is_64 = os_arch == "x86_64" || os_arch == "amd64" || os_arch == "aarch64" || os_arch == "arm64" || os_arch == "riscv64";
result.validity = Result::Validity::Valid;
result.is_64bit = is_64;

View File

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

View File

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

View File

@ -102,6 +102,8 @@ QProcessEnvironment CleanEnviroment()
QString newValue = stripVariableEntries(key, value, rawenv.value("LAUNCHER_" + key));
qDebug() << "Env: stripped" << key << value << "to" << newValue;
value = newValue;
}
#if defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD) || defined(Q_OS_OPENBSD)
// Strip IBus
@ -403,7 +405,7 @@ QList<QString> JavaUtils::FindJavaPaths()
{
QList<QString> javas;
javas.append(this->GetDefaultJava()->path);
auto scanJavaDir = [&](
auto scanJavaDir = [&javas](
const QString& dirPath,
const std::function<bool(const QFileInfo&)>& filter = [](const QFileInfo&) { return true; }) {
QDir dir(dirPath);
@ -422,7 +424,7 @@ QList<QString> JavaUtils::FindJavaPaths()
};
// java installed in a snap is installed in the standard directory, but underneath $SNAP
auto snap = qEnvironmentVariable("SNAP");
auto scanJavaDirs = [&](const QString& dirPath) {
auto scanJavaDirs = [scanJavaDir, snap](const QString& dirPath) {
scanJavaDir(dirPath);
if (!snap.isNull()) {
scanJavaDir(snap + dirPath);
@ -440,9 +442,15 @@ QList<QString> JavaUtils::FindJavaPaths()
QString fileName = info.fileName();
return fileName.startsWith("openjdk-") || fileName.startsWith("openj9-");
};
// AOSC OS's locations for openjdk
auto aoscFilter = [](const QFileInfo& info) {
QString fileName = info.fileName();
return fileName == "java" || fileName.startsWith("java-");
};
scanJavaDir("/usr/lib64", gentooFilter);
scanJavaDir("/usr/lib", gentooFilter);
scanJavaDir("/opt", gentooFilter);
scanJavaDir("/usr/lib", aoscFilter);
// javas stored in Prism Launcher's folder
scanJavaDirs("java");
// manually installed JDKs in /opt
@ -544,12 +552,12 @@ QStringList getPrismJavaBundle()
{
QList<QString> javas;
auto scanDir = [&](QString prefix) {
auto scanDir = [&javas](QString prefix) {
javas.append(FS::PathCombine(prefix, "jre", "bin", JavaUtils::javaExecutable));
javas.append(FS::PathCombine(prefix, "bin", JavaUtils::javaExecutable));
javas.append(FS::PathCombine(prefix, JavaUtils::javaExecutable));
};
auto scanJavaDir = [&](const QString& dirPath) {
auto scanJavaDir = [scanDir](const QString& dirPath) {
QDir dir(dirPath);
if (!dir.exists())
return;

View File

@ -19,9 +19,13 @@ JavaVersion& JavaVersion::operator=(const QString& javaVersionString)
QRegularExpression pattern;
if (javaVersionString.startsWith("1.")) {
pattern = QRegularExpression("1[.](?<major>[0-9]+)([.](?<minor>[0-9]+))?(_(?<security>[0-9]+)?)?(-(?<prerelease>[a-zA-Z0-9]+))?");
static const QRegularExpression s_withOne(
"1[.](?<major>[0-9]+)([.](?<minor>[0-9]+))?(_(?<security>[0-9]+)?)?(-(?<prerelease>[a-zA-Z0-9]+))?");
pattern = s_withOne;
} else {
pattern = QRegularExpression("(?<major>[0-9]+)([.](?<minor>[0-9]+))?([.](?<security>[0-9]+))?(-(?<prerelease>[a-zA-Z0-9]+))?");
static const QRegularExpression s_withoutOne(
"(?<major>[0-9]+)([.](?<minor>[0-9]+))?([.](?<security>[0-9]+))?(-(?<prerelease>[a-zA-Z0-9]+))?");
pattern = s_withoutOne;
}
auto match = pattern.match(m_string);

View File

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

View File

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

View File

@ -37,12 +37,12 @@
#include "launch/LaunchTask.h"
#include <assert.h>
#include <QAnyStringView>
#include <QCoreApplication>
#include <QDebug>
#include <QDir>
#include <QEventLoop>
#include <QRegularExpression>
#include <QStandardPaths>
#include <variant>
#include "MessageLevel.h"
#include "tasks/Task.h"
@ -214,6 +214,52 @@ shared_qobject_ptr<LogModel> LaunchTask::getLogModel()
return m_logModel;
}
bool LaunchTask::parseXmlLogs(QString const& line, MessageLevel::Enum level)
{
LogParser* parser;
switch (level) {
case MessageLevel::StdErr:
parser = &m_stderrParser;
break;
case MessageLevel::StdOut:
parser = &m_stdoutParser;
break;
default:
return false;
}
parser->appendLine(line);
auto items = parser->parseAvailable();
if (auto err = parser->getError(); err.has_value()) {
auto& model = *getLogModel();
model.append(MessageLevel::Error, tr("[Log4j Parse Error] Failed to parse log4j log event: %1").arg(err.value().errMessage));
return false;
} else {
if (!items.isEmpty()) {
auto& model = *getLogModel();
for (auto const& item : items) {
if (std::holds_alternative<LogParser::LogEntry>(item)) {
auto entry = std::get<LogParser::LogEntry>(item);
auto msg = QString("[%1] [%2/%3] [%4]: %5")
.arg(entry.timestamp.toString("HH:mm:ss"))
.arg(entry.thread)
.arg(entry.levelText)
.arg(entry.logger)
.arg(entry.message);
msg = censorPrivateInfo(msg);
model.append(entry.level, msg);
} else if (std::holds_alternative<LogParser::PlainText>(item)) {
auto msg = std::get<LogParser::PlainText>(item).message;
level = LogParser::guessLevel(msg, model.previousLevel());
msg = censorPrivateInfo(msg);
model.append(level, msg);
}
}
}
}
return true;
}
void LaunchTask::onLogLines(const QStringList& lines, MessageLevel::Enum defaultLevel)
{
for (auto& line : lines) {
@ -223,21 +269,26 @@ void LaunchTask::onLogLines(const QStringList& lines, MessageLevel::Enum default
void LaunchTask::onLogLine(QString line, MessageLevel::Enum level)
{
if (parseXmlLogs(line, level)) {
return;
}
// if the launcher part set a log level, use it
auto innerLevel = MessageLevel::fromLine(line);
if (innerLevel != MessageLevel::Unknown) {
level = innerLevel;
}
auto& model = *getLogModel();
// If the level is still undetermined, guess level
if (level == MessageLevel::StdErr || level == MessageLevel::StdOut || level == MessageLevel::Unknown) {
level = m_instance->guessLevel(line, level);
if (level == MessageLevel::Unknown) {
level = LogParser::guessLevel(line, model.previousLevel());
}
// censor private user info
line = censorPrivateInfo(line);
auto& model = *getLogModel();
model.append(level, line);
}
@ -254,20 +305,60 @@ void LaunchTask::emitFailed(QString reason)
Task::emitFailed(reason);
}
void LaunchTask::substituteVariables(QStringList& args) const
QString expandVariables(const QString& input, QProcessEnvironment dict)
{
auto env = m_instance->createEnvironment();
QString result = input;
for (auto key : env.keys()) {
args.replaceInStrings("$" + key, env.value(key));
enum { base, maybeBrace, variable, brace } state = base;
int startIdx = -1;
for (int i = 0; i < result.length();) {
QChar c = result.at(i++);
switch (state) {
case base:
if (c == '$')
state = maybeBrace;
break;
case maybeBrace:
if (c == '{') {
state = brace;
startIdx = i;
} else if (c.isLetterOrNumber() || c == '_') {
state = variable;
startIdx = i - 1;
} else {
state = base;
}
break;
case brace:
if (c == '}') {
const auto res = dict.value(result.mid(startIdx, i - 1 - startIdx), "");
if (!res.isEmpty()) {
result.replace(startIdx - 2, i - startIdx + 2, res);
i = startIdx - 2 + res.length();
}
state = base;
}
break;
case variable:
if (!c.isLetterOrNumber() && c != '_') {
const auto res = dict.value(result.mid(startIdx, i - startIdx - 1), "");
if (!res.isEmpty()) {
result.replace(startIdx - 1, i - startIdx, res);
i = startIdx - 1 + res.length();
}
state = base;
}
break;
}
}
if (state == variable) {
if (const auto res = dict.value(result.mid(startIdx), ""); !res.isEmpty())
result.replace(startIdx - 1, result.length() - startIdx + 1, res);
}
return result;
}
void LaunchTask::substituteVariables(QString& cmd) const
QString LaunchTask::substituteVariables(QString& cmd, bool isLaunch) const
{
auto env = m_instance->createEnvironment();
for (auto key : env.keys()) {
cmd.replace("$" + key, env.value(key));
}
return expandVariables(cmd, isLaunch ? m_instance->createLaunchEnvironment() : m_instance->createEnvironment());
}

View File

@ -43,6 +43,7 @@
#include "LaunchStep.h"
#include "LogModel.h"
#include "MessageLevel.h"
#include "logs/LogParser.h"
class LaunchTask : public Task {
Q_OBJECT
@ -87,8 +88,7 @@ class LaunchTask : public Task {
shared_qobject_ptr<LogModel> getLogModel();
public:
void substituteVariables(QStringList& args) const;
void substituteVariables(QString& cmd) const;
QString substituteVariables(QString& cmd, bool isLaunch = false) const;
QString censorPrivateInfo(QString in);
protected: /* methods */
@ -115,6 +115,9 @@ class LaunchTask : public Task {
private: /*methods */
void finalizeSteps(bool successful, const QString& error);
protected:
bool parseXmlLogs(QString const& line, MessageLevel::Enum level);
protected: /* data */
MinecraftInstancePtr m_instance;
shared_qobject_ptr<LogModel> m_logModel;
@ -123,4 +126,6 @@ class LaunchTask : public Task {
int currentStep = -1;
State state = NotStarted;
qint64 m_pid = -1;
LogParser m_stdoutParser;
LogParser m_stderrParser;
};

View File

@ -100,7 +100,7 @@ void LogModel::setMaxLines(int maxLines)
return;
}
// otherwise, we need to reorganize the data because it crosses the wrap boundary
QVector<entry> newContent;
QList<entry> newContent;
newContent.resize(maxLines);
if (m_numLines <= maxLines) {
// if it all fits in the new buffer, just copy it over
@ -149,3 +149,28 @@ bool LogModel::wrapLines() const
{
return m_lineWrap;
}
void LogModel::setColorLines(bool state)
{
if (m_colorLines != state) {
m_colorLines = state;
}
}
bool LogModel::colorLines() const
{
return m_colorLines;
}
bool LogModel::isOverFlow()
{
return m_numLines >= m_maxLines && m_stopOnOverflow;
}
MessageLevel::Enum LogModel::previousLevel()
{
if (!m_content.isEmpty()) {
return m_content.last().level;
}
return MessageLevel::Unknown;
}

View File

@ -24,20 +24,25 @@ class LogModel : public QAbstractListModel {
void setMaxLines(int maxLines);
void setStopOnOverflow(bool stop);
void setOverflowMessage(const QString& overflowMessage);
bool isOverFlow();
void setLineWrap(bool state);
bool wrapLines() const;
void setColorLines(bool state);
bool colorLines() const;
MessageLevel::Enum previousLevel();
enum Roles { LevelRole = Qt::UserRole };
private /* types */:
struct entry {
MessageLevel::Enum level;
MessageLevel::Enum level = MessageLevel::Enum::Unknown;
QString line;
};
private: /* data */
QVector<entry> m_content;
QList<entry> m_content;
int m_maxLines = 1000;
// first line in the circular buffer
int m_firstLine = 0;
@ -47,6 +52,7 @@ class LogModel : public QAbstractListModel {
QString m_overflowMessage = "OVERFLOW";
bool m_suspended = false;
bool m_lineWrap = true;
bool m_colorLines = true;
private:
Q_DISABLE_COPY(LogModel)

View File

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

View File

@ -47,25 +47,17 @@ PostLaunchCommand::PostLaunchCommand(LaunchTask* parent) : LaunchStep(parent)
void PostLaunchCommand::executeTask()
{
// FIXME: where to put this?
#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)
auto args = QProcess::splitCommand(m_command);
m_parent->substituteVariables(args);
auto cmd = m_parent->substituteVariables(m_command);
emit logLine(tr("Running Post-Launch command: %1").arg(cmd), MessageLevel::Launcher);
auto args = QProcess::splitCommand(cmd);
emit logLine(tr("Running Post-Launch command: %1").arg(args.join(' ')), MessageLevel::Launcher);
const QString program = args.takeFirst();
m_process.start(program, args);
#else
m_parent->substituteVariables(m_command);
emit logLine(tr("Running Post-Launch command: %1").arg(m_command), MessageLevel::Launcher);
m_process.start(m_command);
#endif
}
void PostLaunchCommand::on_state(LoggedProcess::State state)
{
auto getError = [&]() { return tr("Post-Launch command failed with code %1.\n\n").arg(m_process.exitCode()); };
auto getError = [this]() { return tr("Post-Launch command failed with code %1.\n\n").arg(m_process.exitCode()); };
switch (state) {
case LoggedProcess::Aborted:
case LoggedProcess::Crashed:

View File

@ -47,25 +47,16 @@ PreLaunchCommand::PreLaunchCommand(LaunchTask* parent) : LaunchStep(parent)
void PreLaunchCommand::executeTask()
{
// FIXME: where to put this?
#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)
auto args = QProcess::splitCommand(m_command);
m_parent->substituteVariables(args);
emit logLine(tr("Running Pre-Launch command: %1").arg(args.join(' ')), MessageLevel::Launcher);
auto cmd = m_parent->substituteVariables(m_command);
emit logLine(tr("Running Pre-Launch command: %1").arg(cmd), MessageLevel::Launcher);
auto args = QProcess::splitCommand(cmd);
const QString program = args.takeFirst();
m_process.start(program, args);
#else
m_parent->substituteVariables(m_command);
emit logLine(tr("Running Pre-Launch command: %1").arg(m_command), MessageLevel::Launcher);
m_process.start(m_command);
#endif
}
void PreLaunchCommand::on_state(LoggedProcess::State state)
{
auto getError = [&]() { return tr("Pre-Launch command failed with code %1.\n\n").arg(m_process.exitCode()); };
auto getError = [this]() { return tr("Pre-Launch command failed with code %1.\n\n").arg(m_process.exitCode()); };
switch (state) {
case LoggedProcess::Aborted:
case LoggedProcess::Crashed:

351
launcher/logs/LogParser.cpp Normal file
View File

@ -0,0 +1,351 @@
// SPDX-License-Identifier: GPL-3.0-only
/*
* Prism Launcher - Minecraft Launcher
* Copyright (C) 2025 Rachel Powers <508861+Ryex@users.noreply.github.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 "LogParser.h"
#include <QRegularExpression>
#include "MessageLevel.h"
using namespace Qt::Literals::StringLiterals;
void LogParser::appendLine(QAnyStringView data)
{
if (!m_partialData.isEmpty()) {
m_buffer = QString(m_partialData);
m_buffer.append("\n");
m_partialData.clear();
}
m_buffer.append(data.toString());
}
std::optional<LogParser::Error> LogParser::getError()
{
return m_error;
}
std::optional<LogParser::LogEntry> LogParser::parseAttributes()
{
LogParser::LogEntry entry{
"",
MessageLevel::Info,
};
auto attributes = m_parser.attributes();
for (const auto& attr : attributes) {
auto name = attr.name();
auto value = attr.value();
if (name == "logger"_L1) {
entry.logger = value.trimmed().toString();
} else if (name == "timestamp"_L1) {
if (value.trimmed().isEmpty()) {
m_parser.raiseError("log4j:Event Missing required attribute: timestamp");
return {};
}
entry.timestamp = QDateTime::fromSecsSinceEpoch(value.trimmed().toLongLong());
} else if (name == "level"_L1) {
entry.levelText = value.trimmed().toString();
entry.level = MessageLevel::getLevel(entry.levelText);
} else if (name == "thread"_L1) {
entry.thread = value.trimmed().toString();
}
}
if (entry.logger.isEmpty()) {
m_parser.raiseError("log4j:Event Missing required attribute: logger");
return {};
}
return entry;
}
void LogParser::setError()
{
m_error = {
m_parser.errorString(),
m_parser.error(),
};
}
void LogParser::clearError()
{
m_error = {}; // clear previous error
}
bool isPotentialLog4JStart(QStringView buffer)
{
static QString target = QStringLiteral("<log4j:event");
if (buffer.isEmpty() || buffer[0] != '<') {
return false;
}
auto bufLower = buffer.toString().toLower();
return target.startsWith(bufLower) || bufLower.startsWith(target);
}
std::optional<LogParser::ParsedItem> LogParser::parseNext()
{
clearError();
if (m_buffer.isEmpty()) {
return {};
}
if (m_buffer.trimmed().isEmpty()) {
auto text = QString(m_buffer);
m_buffer.clear();
return LogParser::PlainText{ text };
}
// check if we have a full xml log4j event
bool isCompleteLog4j = false;
m_parser.clear();
m_parser.setNamespaceProcessing(false);
m_parser.addData(m_buffer);
if (m_parser.readNextStartElement()) {
if (m_parser.qualifiedName().compare("log4j:Event"_L1, Qt::CaseInsensitive) == 0) {
int depth = 1;
bool eod = false;
while (depth > 0 && !eod) {
auto tok = m_parser.readNext();
switch (tok) {
case QXmlStreamReader::TokenType::StartElement: {
depth += 1;
} break;
case QXmlStreamReader::TokenType::EndElement: {
depth -= 1;
} break;
case QXmlStreamReader::TokenType::EndDocument: {
eod = true; // break outer while loop
} break;
default: {
// no op
}
}
if (m_parser.hasError()) {
break;
}
}
isCompleteLog4j = depth == 0;
}
}
if (isCompleteLog4j) {
return parseLog4J();
} else {
if (isPotentialLog4JStart(m_buffer)) {
m_partialData = QString(m_buffer);
return LogParser::Partial{ QString(m_buffer) };
}
int start = 0;
auto bufView = QStringView(m_buffer);
while (start < bufView.length()) {
if (qsizetype pos = bufView.right(bufView.length() - start).indexOf('<'); pos != -1) {
auto slicestart = start + pos;
auto slice = bufView.right(bufView.length() - slicestart);
if (isPotentialLog4JStart(slice)) {
if (slicestart > 0) {
auto text = m_buffer.left(slicestart);
m_buffer = m_buffer.right(m_buffer.length() - slicestart);
if (!text.trimmed().isEmpty()) {
return LogParser::PlainText{ text };
}
}
m_partialData = QString(m_buffer);
return LogParser::Partial{ QString(m_buffer) };
}
start = slicestart + 1;
} else {
break;
}
}
// no log4j found, all plain text
auto text = QString(m_buffer);
m_buffer.clear();
return LogParser::PlainText{ text };
}
}
QList<LogParser::ParsedItem> LogParser::parseAvailable()
{
QList<LogParser::ParsedItem> items;
bool doNext = true;
while (doNext) {
auto item_ = parseNext();
if (m_error.has_value()) {
return {};
}
if (item_.has_value()) {
auto item = item_.value();
if (std::holds_alternative<LogParser::Partial>(item)) {
break;
} else {
items.push_back(item);
}
} else {
doNext = false;
}
}
return items;
}
std::optional<LogParser::ParsedItem> LogParser::parseLog4J()
{
m_parser.clear();
m_parser.setNamespaceProcessing(false);
m_parser.addData(m_buffer);
m_parser.readNextStartElement();
if (m_parser.qualifiedName().compare("log4j:Event"_L1, Qt::CaseInsensitive) == 0) {
auto entry_ = parseAttributes();
if (!entry_.has_value()) {
setError();
return {};
}
auto entry = entry_.value();
bool foundMessage = false;
int depth = 1;
enum parseOp { noOp, entryReady, parseError };
auto foundStart = [&]() -> parseOp {
depth += 1;
if (m_parser.qualifiedName().compare("log4j:Message"_L1, Qt::CaseInsensitive) == 0) {
QString message;
bool messageComplete = false;
while (!messageComplete) {
auto tok = m_parser.readNext();
switch (tok) {
case QXmlStreamReader::TokenType::Characters: {
message.append(m_parser.text());
} break;
case QXmlStreamReader::TokenType::EndElement: {
if (m_parser.qualifiedName().compare("log4j:Message"_L1, Qt::CaseInsensitive) == 0) {
messageComplete = true;
}
} break;
case QXmlStreamReader::TokenType::EndDocument: {
return parseError; // parse fail
} break;
default: {
// no op
}
}
if (m_parser.hasError()) {
return parseError;
}
}
entry.message = message;
foundMessage = true;
depth -= 1;
}
return noOp;
};
auto foundEnd = [&]() -> parseOp {
depth -= 1;
if (depth == 0 && m_parser.qualifiedName().compare("log4j:Event"_L1, Qt::CaseInsensitive) == 0) {
if (foundMessage) {
auto consumed = m_parser.characterOffset();
if (consumed > 0 && consumed <= m_buffer.length()) {
m_buffer = m_buffer.right(m_buffer.length() - consumed);
// potential whitespace preserved for next item
}
clearError();
return entryReady;
}
m_parser.raiseError("log4j:Event Missing required attribute: message");
setError();
return parseError;
}
return noOp;
};
while (!m_parser.atEnd()) {
auto tok = m_parser.readNext();
parseOp op = noOp;
switch (tok) {
case QXmlStreamReader::TokenType::StartElement: {
op = foundStart();
} break;
case QXmlStreamReader::TokenType::EndElement: {
op = foundEnd();
} break;
case QXmlStreamReader::TokenType::EndDocument: {
return {};
} break;
default: {
// no op
}
}
switch (op) {
case parseError:
return {}; // parse fail or error
case entryReady:
return entry;
case noOp:
default: {
// no op
}
}
if (m_parser.hasError()) {
return {};
}
}
}
throw std::runtime_error("unreachable: already verified this was a complete log4j:Event");
}
MessageLevel::Enum LogParser::guessLevel(const QString& line, MessageLevel::Enum level)
{
static const QRegularExpression LINE_WITH_LEVEL("^\\[(?<timestamp>[0-9:]+)\\] \\[[^/]+/(?<level>[^\\]]+)\\]");
auto match = LINE_WITH_LEVEL.match(line);
if (match.hasMatch()) {
// New style logs from log4j
QString timestamp = match.captured("timestamp");
QString levelStr = match.captured("level");
level = MessageLevel::getLevel(levelStr);
} else {
// Old style forge logs
if (line.contains("[INFO]") || line.contains("[CONFIG]") || line.contains("[FINE]") || line.contains("[FINER]") ||
line.contains("[FINEST]"))
level = MessageLevel::Info;
if (line.contains("[SEVERE]") || line.contains("[STDERR]"))
level = MessageLevel::Error;
if (line.contains("[WARNING]"))
level = MessageLevel::Warning;
if (line.contains("[DEBUG]"))
level = MessageLevel::Debug;
}
if (level != MessageLevel::Unknown)
return level;
if (line.contains("overwriting existing"))
return MessageLevel::Fatal;
return MessageLevel::Info;
}

76
launcher/logs/LogParser.h Normal file
View File

@ -0,0 +1,76 @@
// SPDX-License-Identifier: GPL-3.0-only
/*
* Prism Launcher - Minecraft Launcher
* Copyright (C) 2025 Rachel Powers <508861+Ryex@users.noreply.github.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 <QAnyStringView>
#include <QDateTime>
#include <QList>
#include <QString>
#include <QStringView>
#include <QXmlStreamReader>
#include <optional>
#include <variant>
#include "MessageLevel.h"
class LogParser {
public:
struct LogEntry {
QString logger;
MessageLevel::Enum level;
QString levelText;
QDateTime timestamp;
QString thread;
QString message;
};
struct Partial {
QString data;
};
struct PlainText {
QString message;
};
struct Error {
QString errMessage;
QXmlStreamReader::Error error;
};
using ParsedItem = std::variant<LogEntry, PlainText, Partial>;
public:
LogParser() = default;
void appendLine(QAnyStringView data);
std::optional<ParsedItem> parseNext();
QList<ParsedItem> parseAvailable();
std::optional<Error> getError();
/// guess log level from a line of game log
static MessageLevel::Enum guessLevel(const QString& line, MessageLevel::Enum level);
protected:
std::optional<LogEntry> parseAttributes();
void setError();
void clearError();
std::optional<ParsedItem> parseLog4J();
private:
QString m_buffer;
QString m_partialData;
QXmlStreamReader m_parser;
std::optional<Error> m_error;
};

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