Compare commits

...

1609 Commits
1.4.1 ... 7.0

Author SHA1 Message Date
bfe7e3afed Merge pull request #1133 from DioEgizio/bump-mac-11.0 2023-06-08 18:11:59 +02:00
75b1eaed0c chore: bump macOS requirement to 11.0
Noticed only now that Qt 6.5 bumps the macOS requirement to macOS 11.
This was basically already effective in prism since with the Qt 6.5 bump pr macOS 10.15 user's wouldn't be able to run this, but updating the requirement here makes it more clear for the end user trying to run prism on macOS 10.15

Signed-off-by: DioEgizio <83089242+DioEgizio@users.noreply.github.com>
2023-06-08 17:12:49 +02:00
7fb4c8358b Merge pull request #1131 from DioEgizio/revert-to-qt650 2023-06-08 16:20:22 +02:00
5b3431b268 chore: revert macOS Qt version back to 6.5.0
Qt 6.5.1 seems to cause issues with Rectangle

Signed-off-by: DioEgizio <83089242+DioEgizio@users.noreply.github.com>
2023-06-08 14:55:09 +02:00
9b9d439fce Merge pull request #1111 from Trial97/requires 2023-06-07 18:57:46 +02:00
62d1bc87ae Merge pull request #1117 from leo78913/update-pack-formats 2023-06-07 17:49:52 +02:00
51ed39804f Merge pull request #1125 from Ryex/fix/link-crash-1118 2023-06-07 16:14:53 +02:00
d12110b47b fix #1118 : use filePath not path on QFileInfo
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2023-06-07 06:26:58 -07:00
accf0cd40e Merge pull request #1115 from leo78913/fix-resource-downloader-crash 2023-06-07 08:47:19 +02:00
a9302468e7 update resource and data pack pack_format_versions
Signed-off-by: leo78913 <leo3758@riseup.net>
2023-06-06 16:10:15 -03:00
3b9d822d72 Merge pull request #1073 from leo78913/accounts-menus-fixes 2023-06-06 20:34:41 +02:00
f3a7de6b76 fix: save meta custom url as string, not QUrl (#1114) 2023-06-06 20:25:29 +02:00
a807b231a7 fix: fix crash when selecting resource/texture/shader packs
Signed-off-by: leo78913 <leo3758@riseup.net>
2023-06-06 15:17:13 -03:00
d59a06344a fix main toolbar accounts toolbutton name
previously it was not using the selected account name when opening the launcher

and i also added an action group to the menu items so it uses radio buttons instead of checkboxes :p

Signed-off-by: leo78913 <leo3758@riseup.net>
2023-06-06 14:21:41 -03:00
e884341795 save meta custom url as string, not QUrl
Signed-off-by: Tayou <tayou@gmx.net>
2023-06-06 18:15:26 +02:00
3a068970f9 Packaging: file manifest in portable install (#1101) 2023-06-06 16:03:13 +02:00
1043d29dd5 Merge branch 'develop' of https://github.com/PrismLauncher/PrismLauncher into requires 2023-06-06 10:34:36 +03:00
6505a62801 Renamed requires fields
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2023-06-06 10:34:05 +03:00
7e016c44c1 Merge pull request #1093 from getchoo/use-flake-parts
Refactor Nix Flake
2023-06-06 08:10:39 +02:00
e1b37f3cd3 Merge pull request #1108 from Ryex/fix/memory-leak-translation 2023-06-05 20:34:56 +02:00
0c24827a52 Merge pull request #1103 from Ryex/fix/1.120-allowed_symlinks.txt 2023-06-05 20:32:30 +02:00
e6eee82fb9 Merge pull request #1100 from Ryex/packaging/windows-installer-uninstall-previous 2023-06-05 20:30:57 +02:00
c5cf78205a Merge pull request #1109 from TheKodeToad/mrpack-export-validate 2023-06-05 19:44:45 +02:00
37b4f606c8 Validate input lengths on mrpack export
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2023-06-05 17:54:24 +01:00
5824047ffa fix(memory leak): cyclic refrence in translations model dl task
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2023-06-05 01:12:16 -07:00
3dccc38f42 Merge pull request #904 from TheKodeToad/mrpack-export
mrpack export
2023-06-04 19:01:50 -07:00
f613b03efd Typo fix
Co-authored-by: Sefa Eyeoglu <contact@scrumplex.net>
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2023-06-03 08:28:49 -07:00
3c87e5d31e Make mcInstance mutable
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2023-06-03 13:48:15 +01:00
e26827b849 Optimised icons
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2023-06-03 13:39:42 +01:00
8eb10e991f fix: use isSymLink (i've made this mistake before but I've made it again)
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2023-06-02 16:14:38 -07:00
f6f32914de fix: add origonal instance path to allowed_symlinks.txt when copying via symlinks
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2023-06-02 16:04:27 -07:00
1840505a0f Fix crash when selecting same mod from different providers (#1029) 2023-06-02 18:04:06 -03:00
29e532c096 fix(nix): fix prismlauncher-qt5
Signed-off-by: seth <getchoo@tuta.io>
2023-06-02 11:53:09 -04:00
0f0cbd4c1f refactor(nix): introduce unwrapped packages
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2023-06-02 12:41:18 +02:00
0ece0b5b27 Merge pull request #1086 from TayouVR/fix-qt6_5-brown-system-theme 2023-06-02 12:18:37 +02:00
6a4fb6a271 packaging: remove redundant "do you want to uninstall previous version"
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2023-06-01 12:40:08 -07:00
4593538fc8 fix: typo - space before comment
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2023-05-31 14:36:24 -07:00
03b66ba7a5 packaging: make windows nsis installer run the uninstaller for previous install before installing
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2023-05-31 13:25:14 -07:00
954d4d701a Merge pull request #1034 from kerichdev/patch-1 2023-05-28 10:56:44 -03:00
ce2d58bb7d Merge pull request #1083 from Ryex/fix/memory-leaks-develop 2023-05-28 10:11:43 -03:00
7af116fb00 refactor: function scope statics
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2023-05-28 05:06:28 -07:00
0357921284 cleanup: move qstyle getInstance decl inline
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2023-05-28 04:37:09 -07:00
86974b046e Clarify comment
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2023-05-28 11:48:09 +01:00
a04a6f1e0d fix(memory leak): don't give shared pointers out to foldermodels (causes cyclic refrence)
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2023-05-28 02:15:39 -07:00
37420405c7 fix(memory leak): refactor NoBigComboStyle -> singleton
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2023-05-27 23:22:40 -07:00
acf1946dac chore(nix): update sources
Signed-off-by: seth <getchoo@tuta.io>
2023-05-27 19:25:58 -04:00
a52574b026 chore(nix): add nil
Signed-off-by: seth <getchoo@tuta.io>
2023-05-27 19:25:49 -04:00
5d14724e66 chore(deps): enable nix lockfile maintenance for renovate
Signed-off-by: seth <getchoo@tuta.io>
2023-05-27 19:17:44 -04:00
d582bf7f1f feat(nix): flake-utils -> flake-parts
Signed-off-by: seth <getchoo@tuta.io>
2023-05-27 19:14:50 -04:00
c81cb59b4b fix(memory leak): don't capture job and create cyclic refrence
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2023-05-26 21:21:10 -07:00
ff03dd22fe fix(memory leak): don't override default deconstructor + reset shared_ptr + ensure modal get's cleaned up
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2023-05-26 21:10:49 -07:00
aae892dfd1 fix(memory leak): IndexedPack too large to live inside a qlist without pointers ()
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2023-05-26 19:21:07 -07:00
f24211e8b5 Merge pull request #1088 from DioEgizio/update-qt651
chore: update to Qt 6.5.1
2023-05-26 07:31:18 +02:00
e61d8e4dc8 fix: katabasis and QStyle leaks
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2023-05-25 16:16:58 -07:00
403279e926 Merge pull request #1087 from PrismLauncher/renovate/cachix-install-nix-action-21.x 2023-05-25 19:08:16 -03:00
70983c7269 chore: update to Qt 6.5.1
Signed-off-by: DioEgizio <83089242+DioEgizio@users.noreply.github.com>
2023-05-25 16:38:24 +02:00
42f9eccb17 chore(deps): update cachix/install-nix-action action to v21 2023-05-24 14:21:39 +00:00
3c937532f2 fix System theme colors on windows
Signed-off-by: Tayou <tayou@gmx.net>
2023-05-24 15:18:08 +02:00
863027cbe8 Enable size grip
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2023-05-22 11:56:54 +01:00
6b8fe283f0 fix: memory leak, set parent so it's in tree to get cleaned up.
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2023-05-21 01:49:13 -07:00
7983977156 feat: Qt 5.15 adds transfer timeouts. at least use it for downloads
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2023-05-21 01:48:34 -07:00
21cb459899 fix: memory leak NetJob wans't getting cleaned up. ensure lambda capture of job doens;t increase refcount or it will be cyclic
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2023-05-21 01:47:54 -07:00
1b3ff96ffd fix: memory leak with NetJob and responce not getting cleaned up
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2023-05-21 01:46:28 -07:00
42ceaa0015 Merge pull request #1080 from Scrumplex/update-social-links 2023-05-19 16:37:03 -03:00
90b330d4ba chore: update social links
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2023-05-19 18:34:54 +02:00
3be18b58bb Better variable name :p
Signed-off-by: Kode <TheKodeToad@proton.me>
2023-05-15 19:15:56 +01:00
22aaf56855 De-hardcode .index
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2023-05-15 18:48:49 +01:00
7537ea1ef5 make instance settings account selector a comboBox
Signed-off-by: leo78913 <leo3758@riseup.net>
2023-05-14 16:33:41 -03:00
2078133493 fix: remove unnecessary keywords from desktop file
this messes with apps that use tag search like rofi

Signed-off-by: Keri <kerichuudev@gmail.com>
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2023-05-14 14:38:19 +02:00
f60562c5a2 Merge branch 'develop' into mrpack-export
Signed-off-by: Kode <TheKodeToad@proton.me>
2023-05-13 19:07:03 +01:00
18cfe219fe Hopefully This Works™
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2023-05-13 18:58:05 +01:00
129e959a3b Move setAbortable(true)
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2023-05-13 18:28:51 +01:00
e1b6020b76 Make some changes
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2023-05-13 18:24:01 +01:00
d5c6a1b4d1 Merge pull request #1007 from Ryex/fix/network_and_signals 2023-05-13 19:06:47 +02:00
5b8d025440 ty!
Co-authored-by: flow <flowlnlnln@gmail.com>
Signed-off-by: Kode <TheKodeToad@proton.me>
2023-05-12 14:43:55 +01:00
6b6d6a01dc Merge branch 'develop' into fix/network_and_signals
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2023-05-12 01:13:17 -07:00
c5aff7cc1e Merge pull request #961 from Ryex/better-tasks 2023-05-12 09:47:19 +02:00
b16829b0f9 Gib -> GiB
Co-authored-by: Sefa Eyeoglu <contact@scrumplex.net>
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2023-05-12 00:21:37 -07:00
f27716656c fix: remove qt < 5.6 support process error signal
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2023-05-11 16:32:00 -07:00
30cf73a22f typo fix
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2023-05-07 13:23:59 -07:00
884ac73078 Merge remote-tracking branch 'upstream/develop' into better-tasks
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2023-05-07 13:21:21 -07:00
718abaae0e doc fixes
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2023-05-06 19:18:39 -07:00
62a402d05a refactor: move functions to utils + code-review fixes
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2023-05-06 19:10:58 -07:00
ce5bb29c44 Merge pull request #1054 from Ryex/more-lax-block-mods-filename-check 2023-05-06 09:54:59 +02:00
d535f73a58 Merge pull request #950 from DioEgizio/resize-settings
fix: divide minecraftpage into tabs
2023-05-06 08:28:46 +02:00
d38696f411 Update launcher/ui/pages/global/MinecraftPage.ui
Co-authored-by: Sefa Eyeoglu <contact@scrumplex.net>
Signed-off-by: DioEgizio <83089242+DioEgizio@users.noreply.github.com>
2023-05-06 07:15:14 +02:00
d0b6f0124b change: don't search appdata locaiton for logging rules if using custom data dir
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2023-05-05 14:13:34 -07:00
b266068644 Apply suggestions from code review
Co-authored-by: flow <flowlnlnln@gmail.com>
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2023-05-05 14:07:10 -07:00
e0635955df fix: super lax compare
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2023-05-04 13:30:39 -07:00
5ec4cbf1cb fix add an addtion lax file name match with replaced with +
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2023-05-03 20:31:15 -07:00
e0380960fd Change to use future
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2023-05-02 14:23:31 +01:00
64ba5e4ed1 Merge pull request #833 from Ryex/advanced_copy_instance 2023-05-02 12:11:41 +02:00
733619ca74 feat: estimate remining time on downloads
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2023-05-01 10:48:00 -07:00
9f9c829bc5 fix: prevent logspam, fix MacOS theme artifacts
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2023-05-01 10:48:00 -07:00
236764adf6 refactor: Qt can handle const& in signals and slots
While most Qt types cna use implicit data sharing
pasing our own structs means copies. const& ensure
it's only copied as needed by Qt.

Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2023-05-01 10:48:00 -07:00
a80b425551 fix: no need for const bool
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2023-05-01 10:48:00 -07:00
d7032d975c fix: no need to loop all sub tasks
pathc by flowin

Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
Signed-off-by: flow <flowlnlnln@gmail.com>
2023-05-01 10:48:00 -07:00
96decbac27 feat: default qtlogging.ini file
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2023-05-01 10:48:00 -07:00
0fb6a2836b refactor: propogate only only one StepProgress at a time
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2023-05-01 10:48:00 -07:00
fe36471b8d refactor: logging.h -> Logging.h
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2023-05-01 10:48:00 -07:00
6b28af6cc5 fix: clean up license headers for Tasks
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2023-05-01 10:48:00 -07:00
6306fb564b feat: add UID to debug lines of upload tasks
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2023-05-01 10:48:00 -07:00
cdccb25fe3 feat: add download size to download details alongside speed
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2023-05-01 10:48:00 -07:00
b6452215c1 feat: add details signal to Task
feat: add details to mod pack downloading
feat: add logging rule sloading form `ligging.ini at data path root
feat: add `launcher.task` `launcher.task.net` and `launcher.task.net.[down|up]load` logging categories
fix: add new subtask progress to the end of the lay out not the beginning (cuts down on flickering)

Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2023-05-01 10:47:50 -07:00
f1028fa66d fix: properly map progress range
- doument PCRE used for URL compacting

Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2023-05-01 10:47:31 -07:00
9d2f0e4dc8 feat: Propogated subtask progress
Oh boy this is big.

> TaskStepProgress struct is now QMetaObject compatabile and can be sent through signals
> Task now has a method to propogates sub task progress it must be signal bound by each task containing a task wishing to report progress of it's children.
> Downloads report speed
> Tasks now have UUIDS to track them
  - use when reporting
  - use when logging
  - use when storeing them or objects related to them

Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2023-05-01 10:47:20 -07:00
f997529cd4 feat: better task tracking
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2023-05-01 10:45:34 -07:00
495103f72e fix: set x-xbl-contract-version header during xbox auth step
Refrencing GDlauncher and ATLauncher code for auth as well as https://learn.microsoft.com/en-us/gaming/gdk/_content/gc/reference/live/rest/additional/httpstandardheaders
it is possible some of microsoft's server's are rejecting our request because of this missing header?

Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2023-05-01 10:43:31 -07:00
d80dee2a54 refactor: pass instance ptr to resource models. use it to find instance root.
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2023-04-29 19:55:37 -07:00
788fa40c2a refactor: Move ini to use QSettings && drop get/setList functions
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2023-04-29 19:55:24 -07:00
ae75585b52 Merge pull request #1040 from Scrumplex/remove-modpacksch
Remove FTB modpack support
2023-04-29 08:04:53 +02:00
ff07714e8c chore: remove FTB modpack support
We have been contacted by Feed the Beast to drop support for the FTB
modpack browser from Prism Launcher.

Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2023-04-28 11:35:20 +02:00
f54fc16718 Merge pull request #1025 from japa4551/lastLaunchTimeDate 2023-04-27 10:09:53 +02:00
7298f9c273 Fixed typo
Signed-off-by: Japa <japa4551@protonmail.com>
2023-04-26 16:06:17 -03:00
672f5cf160 Update launcher/minecraft/MinecraftInstance.cpp
Co-authored-by: Sefa Eyeoglu <contact@scrumplex.net>
Signed-off-by: Japa <japa4551@protonmail.com>
2023-04-21 19:46:33 -03:00
92cda68480 Update launcher/minecraft/MinecraftInstance.cpp
Co-authored-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
Signed-off-by: Japa <japa4551@protonmail.com>
2023-04-21 11:18:17 -03:00
f41426f394 Instance Description displays the last launch date
Initial Draft using the Standard C++ Library, still requires testing.

Signed-off-by: Japa <japa4551@protonmail.com>
2023-04-21 00:30:38 -03:00
8dc3267925 Merge pull request #994 from PrismLauncher/renovate/hendrikmuhs-ccache-action-1.x 2023-04-18 18:54:11 +02:00
709736d3f9 Make response const
I don't think the segfault fix was ideal :P
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2023-04-18 09:28:10 +01:00
12f0d51c0c Fix: signal/slot macro -> func pointer & network fixes
- convert qt connect calls to use function pointers instead of the signal/slot macros wherever practical (UI classes were mostly left alone, target was tasks and processes)
- give signals an explicit receivers to use the static method over the instance method wherever practical
- ensure networks tasks are using the `errorOccured` signal added in Qt5.15 over the deprecated `error` signal
- ensure all networks tasks have an sslErrors signal connected
- add seemingly missing `MinecraftAccount::authSucceeded` connection for `MSAInteractive` login flow

Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2023-04-17 18:23:18 -07:00
2e9403a324 This was moved
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2023-04-17 13:19:59 +01:00
ba17efa381 Smol fixes
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2023-04-17 13:18:25 +01:00
b8e0c8ebc6 Boring changes
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2023-04-17 10:16:03 +01:00
1b05303250 Merge pull request #946 from Ryex/subfolder-watch 2023-04-14 17:10:25 +02:00
51095c5a27 chore(deps): update hendrikmuhs/ccache-action action to v1.2.9 2023-04-14 06:31:06 +00:00
a02f67ed0e refactor: rename watch_subdirectories -> watch_recurisve (prevent confusion of behavior)
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2023-04-12 11:30:02 -07:00
3a7961834a Remove seek
Don't need it if the data is already in a byte array.

Signed-off-by: Kode <TheKodeToad@proton.me>
2023-04-09 21:28:40 +01:00
95842ee25f Merge pull request #983 from DioEgizio/update-qt650-win 2023-04-08 22:14:26 +02:00
371c839573 chore: update Qt to 6.5.0 on Windows
Signed-off-by: DioEgizio <83089242+DioEgizio@users.noreply.github.com>
2023-04-08 19:38:46 +02:00
1b8b044b52 Merge pull request #982 from Scrumplex/fix-theming-style 2023-04-08 19:26:43 +02:00
a988111507 fix: do not apply system theme on launch
Closes PrismLauncher/PrismLauncher#490

Regression introduced by PrismLauncher/PrismLauncher#249

Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2023-04-08 18:48:05 +02:00
c56db0408b fix: load setting state with page. don't translate "..."
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2023-04-08 07:26:56 -07:00
2321d9c065 fix: canonical*File*Path()
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2023-04-07 18:36:35 -07:00
ed085630db Merge pull request #968 from Scrumplex/nix/sync-2023-04-02 2023-04-07 06:51:14 -07:00
74d5c7c1a4 Merge pull request #972 from DioEgizio/update-qt650 2023-04-07 06:50:02 -07:00
813ccc1381 How did i-
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2023-04-07 11:03:11 +01:00
b65f4c9536 Better collectFileListRecursively error
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2023-04-06 19:59:24 +01:00
012d8bb468 Revert concurrent syntax
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2023-04-06 19:58:09 +01:00
d7a137ad13 Remove more prototype not good code
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2023-04-06 19:24:19 +01:00
073aaf9b3b Remove "prototype" field
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2023-04-06 19:19:41 +01:00
871d647c93 Use local metadata
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2023-04-06 19:18:36 +01:00
0ce3049579 fix: sysinfo libs needed too
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2023-04-03 18:48:28 -07:00
de20258aa7 fix: filelink needs network for local socket
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2023-04-03 18:30:28 -07:00
41c5e523b2 fix: add back QT::Widgets link
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2023-04-03 18:09:01 -07:00
197be9cfd0 fix: remove fixed datastream version
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2023-04-03 18:00:56 -07:00
5b50b806ec refactor: remove data duplication in statis FS Names
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2023-04-03 17:14:06 -07:00
62c59820cf fix: harden watchPath. NO DUPLICATES! >:(
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2023-04-03 15:26:26 -07:00
0cf1fc72a3 chore: update to qt 6.5.0 on macos
Signed-off-by: DioEgizio <83089242+DioEgizio@users.noreply.github.com>
2023-04-03 18:01:23 +02:00
5ce7874280 fix: no loops in watch paths! >:(
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2023-04-02 18:55:21 -07:00
ba2b5c3a65 fix: Apply suggestions from code review
-expand columspan on new UI element
-improve tooltip

Co-authored-by: flow <flowlnlnln@gmail.com>
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2023-04-02 16:39:13 -07:00
0a9081cb87 Merge pull request #965 from getchoo/update-manoghud-detection 2023-04-02 17:55:19 +02:00
eea1e3b800 Merge pull request #967 from PrismLauncher/renovate/flatpak-flatpak-github-actions-6.x 2023-04-02 08:03:02 -07:00
70364884a9 feat(nix): add support for GameMode
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2023-04-02 11:35:35 +02:00
ea7f03770c refactor(nix): use qtWrapperArgs
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2023-04-02 11:33:04 +02:00
bc1a7d2890 Merge pull request #966 from getchoo/use-ninja
use ninja in nix builds
2023-04-02 14:06:35 +05:30
732bc53692 chore(deps): update flatpak/flatpak-github-actions action to v6 2023-04-02 03:14:42 +00:00
4055e34320 chore: use system architecture to detect vulkan layers
Signed-off-by: seth <getchoo@tuta.io>
2023-04-01 13:09:09 -04:00
81b1406290 feat(nix): use ninja for builds
Signed-off-by: seth <getchoo@tuta.io>
2023-04-01 13:06:53 -04:00
538092b727 fix: typos, CamelCase to camelCase the new names
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2023-03-31 20:31:27 -07:00
4df4b43900 fix: Apply suggestions from code review (string changes)
Co-authored-by: flow <flowlnlnln@gmail.com>
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2023-03-31 18:25:29 -07:00
3e3b92d4c1 chore: improve detection of newer vulkan layers
i've been scrump'd

Co-authored-by: Sefa Eyeoglu <contact@scrumplex.net>
Signed-off-by: seth <getchoo@tuta.io>
2023-03-31 20:09:26 +00:00
c7dc115365 fix: search for newer mangohud vulkan layers
Signed-off-by: seth <getchoo@tuta.io>
2023-03-31 15:49:09 -04:00
e42050cc8a Skip lookup if no files and fail if zipping fails
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2023-03-28 14:22:28 +01:00
df17f5e899 fix: use QDir::Filter::NoDotAndDotDot
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2023-03-27 19:11:26 -07:00
a0045ece07 feat: add setting to watch recursively
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2023-03-27 19:01:53 -07:00
4c013e59f0 divide minecraftpage into tabs
this way small screen users can use the launcher settings without having window a bigger than their actual screens
Signed-off-by: DioEgizio <83089242+DioEgizio@users.noreply.github.com>
2023-03-25 13:12:50 +01:00
09d607f39c Merge pull request #945 from Scrumplex/fix-logging-newlines 2023-03-25 10:37:02 +01:00
9418c62d95 refactor: reprocess log lines per instance
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2023-03-22 10:32:17 +01:00
ef50e5595e fix: don't try to watch the entier filesystem by watching parent links
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2023-03-21 12:17:01 -07:00
02bf086c09 feat: watch sub directories for mods
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2023-03-21 11:07:20 -07:00
77932061bc chore: update ignores for Nix
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2023-03-21 18:33:41 +01:00
44bf32e729 fix: handle partial lines in LoggedProcess
Fixes PrismLauncher/PrismLauncher#930

Co-authored-by: flow <flowlnlnln@gmail.com>
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2023-03-21 18:30:46 +01:00
0c986ba4d0 spelling and formatting
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2023-03-20 16:38:40 -07:00
a28193430c fix: adjust geometry and add missing tooltip
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2023-03-20 14:56:33 -07:00
0bec0046bb format: clang-format to fix windows fallout
it looked fine over in vscod on windows but
as soon as I opened it on linux via Helix
the chaos was clear

Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2023-03-20 14:56:33 -07:00
a96519cbdc workflow: add filelink.exe to SignTool call
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2023-03-20 14:56:33 -07:00
458c2f38bc cleanup: code review sugestions
clean up translation strings

Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2023-03-20 14:56:33 -07:00
dc5402349e refactor: use UUID toString mode
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2023-03-20 14:56:33 -07:00
ae289c923c fix: clean up initial review comments (flowin)
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2023-03-20 14:56:33 -07:00
e0ef86340f feat: connect new help button help-pages/instance-copy
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2023-03-20 14:56:33 -07:00
1ca2c59f2e feat: track instance copies that use links
confirm deleations when other instances link to it

Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2023-03-20 14:56:32 -07:00
3ec92acfe7 fix: use noexcept overload of std::filesystem::hard_link_count
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2023-03-20 14:56:32 -07:00
656bfd36f6 fix: ensure filelink.exe is included in setup.exe
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2023-03-20 14:56:32 -07:00
562ae676a5 fix: mingw still missing typedefs
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2023-03-20 14:56:32 -07:00
72292f4e03 fix: windows compile broke
move winapi defs into #ifndef blocks don't check explicitly for __mingw__ define
function name win_ioctl_clone didn't get updated in teh last commit

Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2023-03-20 14:56:32 -07:00
536da704fc refactor: cleanupFilesystem.cpp
* remove now redundant reflink/clone code for windows
* remove unnessacery debug code that could slow things down

Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2023-03-20 14:56:32 -07:00
a0e03c41c0 fix: typos
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2023-03-20 14:56:32 -07:00
a1053a4c5a feat: warnings when instance resources are linked
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2023-03-20 14:56:32 -07:00
9f441a9678 feat: Add UAC icon when symlinking on windows.
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2023-03-20 14:56:32 -07:00
7870cf28e5 fix: add missing mingw defs
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2023-03-20 14:56:32 -07:00
9939367db7 feat(reflink): ioctl_clone for winbtrfs & ReFS
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2023-03-20 14:56:32 -07:00
1210c3256d fix: macos compat after refactor of clonefile
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2023-03-20 14:56:32 -07:00
2e8d04aad0 feat: support reflink on windows via winbtrfs!
https://github.com/maharmstone/btrfs

Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2023-03-20 14:56:32 -07:00
3a0e4546c2 fix: windows test compat
fix: compiler warning on int qint32 compare

Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2023-03-20 14:56:32 -07:00
cd2419137d fix: better test compareison (also qt5 compat)
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2023-03-20 14:56:32 -07:00
34ac8b3ec3 fix: Qt < 5.14.0 compat
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2023-03-20 14:56:32 -07:00
2837236d81 fix: intelegent recursive links & symlink follow on export
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2023-03-20 14:56:32 -07:00
bc8336a4b1 fix: cleanup UI, detect FAT and turn off links
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2023-03-20 14:56:32 -07:00
397e7f0363 feat(reflink): hook up relink / clone on the copy dialog
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2023-03-20 14:56:32 -07:00
c5bbe42b57 feat: reflink / Clone support!
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2023-03-20 14:56:32 -07:00
c9105e525e fix: follow symlinks when exporting
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2023-03-20 14:56:32 -07:00
1bed7754e0 feat(symlinks): make recursive links explicit
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2023-03-20 14:56:32 -07:00
5978882378 feat(symlinks&hardlinks): linkup copy dialog
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2023-03-20 14:56:32 -07:00
8ba51c7900 refactor: make complete list of links to make and send that.
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2023-03-20 14:56:32 -07:00
6d160a7b7e feat: successful process elevation and comunication!
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2023-03-20 14:56:32 -07:00
32409a361b fix CMakeLits.txt for non MSVC windows builds
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2023-03-20 14:56:32 -07:00
2ceefea5f3 qt5 compatability
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2023-03-20 14:56:32 -07:00
485f156e57 working outside windows
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2023-03-20 14:56:32 -07:00
f794e49bb6 we want to make links!
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2023-03-20 14:56:27 -07:00
46f448dfba Improve invokeMethod syntax
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2023-03-19 21:26:25 +00:00
710156b9f1 Replace native file separator - this was accidentally brought to my attention on Modrinth's guild
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2023-03-19 21:25:12 +00:00
6dcf34acdc Merge pull request #937 from DioEgizio/update-qt6 2023-03-19 22:17:26 +05:30
d2f674e08f chore: update qt6 to 6.4.3 on windows and macos
Signed-off-by: DioEgizio <83089242+DioEgizio@users.noreply.github.com>
2023-03-19 17:11:16 +01:00
ec8cb056bf QRegExp -> QRegularExpression :P
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2023-03-19 11:49:24 +00:00
1893871a99 Merge branch 'PrismLauncher:develop' into mrpack-export 2023-03-18 14:02:05 +00:00
8837f06e4e Only add summary if not empty
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2023-03-18 14:01:41 +00:00
5346dfc782 Use first line of notes for summary
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2023-03-18 12:57:44 +00:00
ddca838e46 Info and error dialogs
TODO: is there a better approach?

Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2023-03-18 12:24:18 +00:00
45b0367d14 Merge pull request #931 from Janrupf/feature/custom-downloads-dir 2023-03-14 13:53:51 +01:00
dce86edff0 Merge pull request #934 from heftymouse/develop 2023-03-14 13:52:44 +01:00
84e91ec3b5 Merge pull request #888 from Scrumplex/nix-stuff 2023-03-14 13:52:31 +01:00
05b6969ee5 fix: add mnemonic to downloads directory setting
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2023-03-14 13:35:16 +01:00
af949f5cdd Add visual studio files to gitignore
Signed-off-by: Nikhil B <59918974+heftymouse@users.noreply.github.com>
2023-03-14 16:52:06 +05:30
7707af08e3 chore(nix): update sources
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2023-03-14 11:19:23 +01:00
5db4fabcad chore(nix): add deadnix
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2023-03-14 10:59:43 +01:00
cfca82ceb3 chore(nix)!: use overlays.default
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2023-03-14 10:58:41 +01:00
a1130dace0 chore: format markdown files
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2023-03-14 10:54:50 +01:00
95a0bd61a9 feat(nix): add pre-commit-hooks.nix
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2023-03-14 10:53:51 +01:00
b324778be7 feat(nix): add devShell
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2023-03-14 10:51:47 +01:00
950f921c09 refactor(nix): use flake-utils
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2023-03-14 10:50:07 +01:00
9dff1bac83 chore(nix): format code using alejandra
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2023-03-14 10:48:19 +01:00
c17f6e37e5 feat: Add setting for downloads directory
Closes #641

Signed-off-by: Janrupf <business.janrupf@gmail.com>
2023-03-13 21:58:22 +01:00
e0e26a37b5 Merge pull request #927 from kthchew/fix/mingw-build 2023-03-13 21:24:48 +01:00
15a0c03664 Merge pull request #928 from PrismLauncher/renovate/actions-cache-3.x
chore(deps): update actions/cache action to v3.3.1
2023-03-13 18:14:35 +01:00
7642e75b28 Merge pull request #929 from Scrumplex/drop-snap 2023-03-13 22:37:16 +05:30
4b36d1e3ea chore: drop Snap packaging
We do not have a lot of expertise dealing with Snap and as it is
currently breaking our CI, it might be good to drop support for it.

This does not mean that it won't come back in the future, but as it
stands, it was effectively unmaintained and was only used for nightly
builds anyway.

Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2023-03-13 15:33:23 +01:00
20525bec29 chore(deps): update actions/cache action to v3.3.1 2023-03-13 10:50:27 +00:00
430369feb8 fix: explicit conversion to C string to fix MinGW g++ 10 build
Signed-off-by: Kenneth Chew <kenneth.c0@protonmail.com>
2023-03-12 18:33:48 -04:00
5ac3e5c958 Update tomlplusplus library
Fix build on MinGW g++ 10

Signed-off-by: Kenneth Chew <kenneth.c0@protonmail.com>
2023-03-12 18:33:48 -04:00
abc2a529fb Merge pull request #919 from PrismLauncher/renovate/actions-cache-3.x 2023-03-09 20:54:31 +05:30
c638fd9056 chore(deps): update actions/cache action to v3.3.0 2023-03-09 14:41:24 +00:00
1dd96898e1 Merge pull request #896 from TheKodeToad/modrinth-token 2023-03-09 15:10:40 +01:00
2cc9b0df06 Only select some paths by default - again!
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2023-03-08 18:10:52 +00:00
3bd4ad7c93 Merge pull request #918 from Scrumplex/qt6-default 2023-03-08 21:18:53 +05:30
a8ffdeca2b chore!: switch to Qt 6 by default
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2023-03-08 11:22:30 +01:00
59b15c5f08 Fix another duplicate name 🤦
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2023-03-07 21:03:09 +00:00
59cf8f678f (hopefully) Fix duplicates names
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2023-03-07 20:50:19 +00:00
088be050b2 Apply flowln's suggestion :)
Co-authored-by: flow <flowlnlnln@gmail.com>
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2023-03-07 20:46:27 +00:00
5d5fcae501 Further reduce buggy behaviour
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2023-03-06 17:24:04 +00:00
970ec8187c More refactoring
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2023-03-05 18:25:57 +00:00
76f66148db Apply flowln's suggestion
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2023-03-05 18:21:24 +00:00
6bdd6ce571 Merge pull request #912 from Scrumplex/bump-ghc-filesystem
Bump ghc-filesystem
2023-03-05 17:25:38 +01:00
dd96e1819d fix: remove unneeded alias for ghc_filesystem
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2023-03-05 14:24:40 +01:00
07702d3be7 fix: drop unneeded GHC_FILESYSTEM_WITH_INSTALL
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2023-03-05 14:23:40 +01:00
b9dfcf6d2f chore: bump ghc-filesystem
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2023-03-05 14:21:07 +01:00
f3f0652d2b Merge pull request #853 from kumquat-ir/nil
NilLoader mod metadata support
2023-03-05 13:39:00 +01:00
aae60334d1 Merge pull request #911 from flowln/fix_zip_extract_windows 2023-03-05 13:09:25 +01:00
b38af948b9 Merge pull request #857 from Ryex/fix_windows_default_apps 2023-03-05 13:09:11 +01:00
06de728aa7 fix: use toLocalFile() instead of path()
QUrl::path() adds a '/' at the beginning of the path on Windows, causing
the world to explode every once in a while.

Signed-off-by: flow <flowlnlnln@gmail.com>
2023-03-05 08:24:56 -03:00
87384182a1 Fix abort?
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2023-03-04 11:07:07 +00:00
f583e617ec Implement abort (possible broken?) and therefore make it work without crashing!
The shared pointer was going out of scope 🤦.

Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2023-03-04 10:37:56 +00:00
a2716f5cf6 Improve code
Even more broken now (it is stuck loading forever)!

Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2023-03-04 10:24:25 +00:00
55f928f845 More consistent naming
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2023-03-03 15:06:29 +00:00
2343aad088 Make it work! (TODO make it not crash)
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2023-03-03 15:00:07 +00:00
dcaa907fed Mod loader support
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2023-03-03 11:25:11 +00:00
adcdf28d64 Move task to another thread
I don't know whether this is the prefered method.

Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2023-03-03 11:24:36 +00:00
f28a7b9d08 Add PackIgnoreProxy.h to cmake
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2023-03-02 19:50:42 +00:00
6505b0c065 Move logic to task
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2023-03-02 19:48:41 +00:00
88ef02474f Minify index JSON
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2023-03-02 17:36:44 +00:00
9ec32b2561 Fix QuaZipFile usage
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2023-03-02 17:36:28 +00:00
a5dd6b6cd7 Export without file urls
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2023-03-02 16:41:09 +00:00
46cc325f7c Add file tree
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2023-03-02 11:25:36 +00:00
0fadb5a2be Add *basic* interaction
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2023-03-02 10:31:53 +00:00
8b897ac714 Fix menu being set as central widget
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2023-03-02 10:31:53 +00:00
a80b820e94 UI for mrpack export (broken)
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2023-03-02 10:31:53 +00:00
4efbf22089 Prism-ify more license headers
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2023-03-02 10:19:42 +00:00
5c913149c8 Merge branch 'PrismLauncher:develop' into modrinth-token 2023-03-02 10:10:46 +00:00
9265c319a9 Merge pull request #788 from flowln/other_resource_downloaders_two
Add resource pack, texture pack and shader pack downloaders
2023-03-02 10:08:45 +00:00
cbe6eff2fa Move Modrinth before CurseForge for consistency
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2023-03-02 09:28:14 +00:00
1f3d18ec12 Replace with exact match and add TODO to improve
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2023-03-02 09:26:00 +00:00
89255e34bd fix: change wording of TP/RP download buttons
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2023-03-02 09:42:28 +01:00
a7b8092296 Add link
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2023-03-01 14:41:16 +00:00
1feb630520 Allow custom Modrinth API token
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2023-03-01 14:24:56 +00:00
9f202caf93 Merge pull request #895 from Scrumplex/fix-component-creation
Use makeShared for importing components
2023-03-01 12:08:46 +00:00
651e511ff0 fix: use makeShared for importing components
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2023-03-01 12:33:00 +01:00
b46aca52ee Merge pull request #894 from PrismLauncher/renovate/cachix-install-nix-action-20.x
chore(deps): update cachix/install-nix-action action to v20
2023-03-01 11:22:59 +00:00
0eae9355e6 Merge pull request #889 from flowln/fix_zip_extract 2023-03-01 09:51:08 +01:00
4878f1a438 Merge pull request #735 from Scrumplex/import-component 2023-03-01 09:49:47 +01:00
f986b4cd56 chore(deps): update cachix/install-nix-action action to v20 2023-03-01 07:20:11 +00:00
d5c6704475 fix: prevent crash when aborting import task while extracting pack
Signed-off-by: flow <flowlnlnln@gmail.com>
2023-02-24 20:34:43 -03:00
fda9ca1e34 fix+refactor: fix fail to import modpacks and clean up a bit
QDir::cleanPath called by FS::PathCombine removes the trailing '/'...

Signed-off-by: flow <flowlnlnln@gmail.com>
2023-02-24 20:09:02 -03:00
01c4ed232e license stuff
Signed-off-by: kumquat-ir <66188216+kumquat-ir@users.noreply.github.com>
2023-02-24 15:01:59 -05:00
dc8109658c review fixes
Signed-off-by: kumquat-ir <66188216+kumquat-ir@users.noreply.github.com>
2023-02-22 13:20:13 -05:00
8ce8055aeb Merge pull request #846 from PrismLauncher/renovate/vedantmgoyal2009-winget-releaser-2.x 2023-02-22 16:19:11 +01:00
a71b743ee3 Merge pull request #881 from PrismLauncher/renovate/actions-cache-3.x 2023-02-22 07:07:55 -08:00
c50e9ac418 chore(deps): update actions/cache action to v3.2.6 2023-02-21 12:33:23 +00:00
7973b01e81 fix metadata for mods with .nilmod extension
Signed-off-by: kumquat-ir <66188216+kumquat-ir@users.noreply.github.com>
2023-02-19 17:21:53 -05:00
b977ac6df5 Merge pull request #865 from Scrumplex/codesign-windows 2023-02-17 17:56:55 +01:00
256fc322a8 minor cleanup
Signed-off-by: kumquat-ir <66188216+kumquat-ir@users.noreply.github.com>
2023-02-16 12:57:35 -05:00
33bf85a387 fix(actions): don't fail if code signing certificate is missing
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2023-02-16 16:41:40 +01:00
1f0fc61b53 Merge pull request from GHSA-gq28-qx55-mh2r
Don't extract files outside of target path
2023-02-15 21:48:06 +01:00
89c945ecc8 feat(ci): add Windows codesigning
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2023-02-15 20:43:33 +01:00
c15962c6c1 Merge pull request #859 from Ryex/fix-KISS-Linux-build
Add missing header to Application.cpp: Fix build failure on KISS Linux
2023-02-13 08:37:39 +01:00
9c2a3231c5 do not create nilmods folder
"it cant be that easy" - me, clueless

Signed-off-by: kumquat-ir <66188216+kumquat-ir@users.noreply.github.com>
2023-02-13 01:45:23 -05:00
80840f1fdb fix: add missing header to Application.cpp
fails to compile on KISS Linux without

Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2023-02-12 22:32:34 -07:00
7d02e1f866 feat: make shell association an optional section
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2023-02-12 17:34:37 -07:00
d93cb751b0 fix: oversight caused prism to be .zip windows default
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2023-02-12 16:23:33 -07:00
c07fff7503 switch to qdcss for parsing
make it not horrible to look at

Signed-off-by: kumquat-ir <66188216+kumquat-ir@users.noreply.github.com>
2023-02-12 17:23:15 -05:00
7896dd19c1 nilmods instance page
mostly copied from the coremod page impl

Signed-off-by: kumquat-ir <66188216+kumquat-ir@users.noreply.github.com>
2023-02-11 17:46:17 -05:00
f5f2d33f93 parse nil metadata
Signed-off-by: kumquat-ir <66188216+kumquat-ir@users.noreply.github.com>
2023-02-11 17:46:17 -05:00
4331eaae2e chore(deps): update vedantmgoyal2009/winget-releaser action to v2 2023-02-11 15:48:00 +00:00
d5d4f87236 Merge pull request #831 from PrismLauncher/renovate/cachix-install-nix-action-19.x 2023-02-11 16:47:30 +01:00
5d49433326 Merge pull request #841 from RaptaG/patch-1 2023-02-11 08:45:42 +01:00
381d7413c8 Link license in the shield badge
So that no trash URL shows when hovering!

Signed-off-by: RaptaG <77157639+RaptaG@users.noreply.github.com>
2023-02-10 19:47:08 +02:00
e70a5a47ee fix: ignore absolute paths when extracting
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2023-02-10 10:46:21 +01:00
6be7eed878 fix: don't extract files outside of target path
This should fix a security issue regarding path traversal in zip files.

Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2023-02-10 09:17:48 +01:00
a6ac832f8f Merge pull request #839 from PrismLauncher/renovate/actions-cache-3.x
chore(deps): update actions/cache action to v3.2.5
2023-02-10 08:27:00 +01:00
104863846b chore(deps): update actions/cache action to v3.2.5 2023-02-10 06:24:45 +00:00
5883c30b84 Merge pull request #834 from pandaninjas/patch-2 2023-02-09 09:29:13 +01:00
cebaae76b4 Merge pull request #832 from ktheticdev/develop
Fix README COPR typo
2023-02-08 14:32:16 -08:00
d886d32bd8 Replace potentially ReDOSable regex
Signed-off-by: PandaNinjas <admin@malwarefight.gq>
2023-02-07 17:21:00 +00:00
8440c2819b Fix README.md typo
Signed-off-by: ktheticdev <64607352+ktheticdev@users.noreply.github.com>
2023-02-07 11:10:43 +04:00
8114d8778f chore(deps): update cachix/install-nix-action action to v19 2023-02-06 15:31:42 +00:00
f36c3a3f6c Merge pull request #819 from Scrumplex/fix-launch-script 2023-02-06 16:26:54 +01:00
46c6cc2d2b chore: add my copyright headers
.-.

Signed-off-by: flow <flowlnlnln@gmail.com>
2023-02-05 17:02:56 -03:00
ada5e88eb9 feat(RD): add texture pack downloader
This extends the resource pack downloader, with the custom behavior of
filtering the versions that shows up, to those <= 1.6. As always, Flame
is funky and requires a bit more workarounds than average.

This will also get a nice improvement when the Version parsing and
comparison PR gets merged! :D

Signed-off-by: flow <flowlnlnln@gmail.com>
2023-02-05 17:02:56 -03:00
b724607e31 feat(RD): add shader pack downloader
Signed-off-by: flow <flowlnlnln@gmail.com>
2023-02-05 17:02:56 -03:00
c3ea303a37 feat(RD): add resource pack downloader
Signed-off-by: flow <flowlnlnln@gmail.com>
2023-02-05 17:02:52 -03:00
e89a10945c Merge pull request #823 from BalkanMadman/linux-java
Fix https://github.com/PrismLauncher/PrismLauncher/issues/790
2023-02-05 19:09:48 +01:00
8ddc89fa01 Merge pull request #825 from Ryex/cmd_env_native_sep
fix https://github.com/PrismLauncher/PrismLauncher/issues/824
2023-02-05 18:42:19 +01:00
a47bf72b07 Merge pull request #751 from Edgars-Cirulis/develop 2023-02-05 17:48:26 +01:00
34460dd77a ensure command env vars use native path seperators
fix #824

Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2023-02-04 12:28:52 -07:00
c125c96e88 Java installations detection fix for Linux
Signed-off-by: BalkanMadman <zurabid2016@gmail.com>
2023-02-04 16:48:06 +02:00
d2fd0fd8e8 Merge pull request #802 from KosmX/develop 2023-02-04 14:43:28 +01:00
74a875bdce Merge pull request #803 from TheLastRar/msys2-ccache 2023-02-04 05:37:23 -08:00
edaa66f622 fix: use /usr/bin/env bash in launch script
This should make it possible to run these scripts on any system, as
/bin/bash is not standard! Notably this fixes the script on NixOS.

Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2023-02-04 01:06:16 +01:00
c392db7e0d Merge pull request #815 from Scrumplex/fix-funny 2023-02-03 18:44:07 +01:00
6ac073e779 fix: fix component uid regex
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2023-02-03 18:32:57 +01:00
58d9ceda4b Merge pull request #804 from flowln/improve_big_concurrent_task_test 2023-02-02 13:47:51 -08:00
3781c64d41 Merge pull request #810 from flowln/error_on_bad_file_paths_as_we_should_catquake 2023-02-02 13:47:36 -08:00
4166d9ab7b fix: give error when components have bad uids
This allows other code to reject proceeding when the UID is bad, which
is generally a good idea. :p

Co-authored-by: Sefa Eyeoglu <contact@scrumplex.net>
Signed-off-by: flow <flowlnlnln@gmail.com>
2023-02-02 17:11:24 -03:00
435273e08a fix(Inst.Import): don't allow bad file path in mrpack import
This checks the URL of the path of the file to be downloaded,
ensuring that it always contains the root .minecraft target folder,
following the warning in the mrpack documentation.

Signed-off-by: flow <flowlnlnln@gmail.com>
2023-02-02 17:11:24 -03:00
35a62d9787 commit requested change, make the lock static
Signed-off-by: KosmX <kosmx.mc@gmail.com>
2023-02-01 23:31:12 +01:00
75683039c5 CI: Always update windows ccache
Also change name to avoid pulling the stale cache

Signed-off-by: TheLastRar <TheLastRar@users.noreply.github.com>
2023-02-01 20:13:26 +00:00
1a609612f2 CI: Move mingw restore cache before setup ccache
Signed-off-by: TheLastRar <TheLastRar@users.noreply.github.com>
2023-02-01 20:13:26 +00:00
121a7a9e23 CI: Log ccache stats for msys2
Signed-off-by: TheLastRar <TheLastRar@users.noreply.github.com>
2023-02-01 20:13:26 +00:00
e593faf245 fix(tests): improve the reliability of the Task's stack test
This actually takes into account the amount of stuff put into the stack
in each iteration, and thus avoids having to change the stack size of
the thread, and using ad-hoc values for the other stuff. It also reduces
the time the test takes to run.

Signed-off-by: flow <flowlnlnln@gmail.com>
2023-02-01 16:58:33 -03:00
ec5bb944b2 thread-safe logger
Signed-off-by: KosmX <kosmx.mc@gmail.com>
2023-02-01 14:59:11 +01:00
deed49574a Merge pull request #798 from PrismLauncher/renovate/actions-cache-3.x 2023-01-30 07:02:51 -08:00
7cc39cd357 chore(deps): update actions/cache action to v3.2.4 2023-01-30 13:29:47 +00:00
a714d5966e Merge pull request #795 from leo78913/mainwindow-fixes
closes https://github.com/PrismLauncher/PrismLauncher/issues/792
2023-01-29 10:35:26 -08:00
2b0252d4ae Fix: fix some regressions in the main window
this removes the update action from the help button
and fixes the add to path action not showing on macos

Signed-off-by: leo78913 <leo3758@riseup.net>
2023-01-28 15:09:26 -03:00
c78db5459e Merge pull request #724 from leo78913/dot-ui-mainwindow
Closes https://github.com/PrismLauncher/PrismLauncher/issues/594
Closes https://github.com/PrismLauncher/PrismLauncher/issues/69
Closes https://github.com/PrismLauncher/PrismLauncher/issues/473
2023-01-27 10:55:49 -08:00
a27564ed70 better fix for WideBar::insertSeparator
Signed-off-by: leo78913 <leo3758@riseup.net>
2023-01-27 13:48:12 -03:00
df8df41621 Remove unused BarEntry variable
Signed-off-by: leo78913 <leo3758@riseup.net>
2023-01-27 12:40:27 -03:00
d5a0d4b452 Update launcher/ui/MainWindow.ui
Co-authored-by: flow <flowlnlnln@gmail.com>
Signed-off-by: leo78913 <leo3758@riseup.net>
2023-01-27 12:35:53 -03:00
357b6ee991 Update launcher/ui/MainWindow.ui
Co-authored-by: flow <flowlnlnln@gmail.com>
Signed-off-by: leo78913 <leo3758@riseup.net>
2023-01-27 12:35:41 -03:00
4d2b5c2f42 refactor: clean up some MainWindow stuff
this makes the accounts button and menubar item share the same QMenu
and also refactors some code

Signed-off-by: leo78913 <leo3758@riseup.net>
2023-01-26 19:48:21 -03:00
f705cf09bc Merge pull request #787 from flowln/make_shared_ptrs_explicit 2023-01-26 10:15:28 -08:00
29f7ea752f refactor: make shared_qobject_ptr ctor explicit
This turns issues like creating two shared ptrs from a single raw ptr
from popping up at runtime, instead making them a compile error.

Signed-off-by: flow <flowlnlnln@gmail.com>
2023-01-25 16:57:51 -03:00
9b7c8ea22d Merge pull request #779 from TheLastRar/zlib-undo-rename 2023-01-25 11:53:51 -08:00
199a7df807 refactor: add error handling to component import
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2023-01-25 10:43:23 +01:00
5186ad95d3 Merge pull request #784 from flowln/fix_resource_folder_double_smart_ptrs 2023-01-25 10:33:01 +01:00
0546345182 Merge pull request #458 from Scrumplex/remove-updater 2023-01-25 10:32:49 +01:00
90feaaf2df fix(Tasks): don't try to start more tasks than necessary
Signed-off-by: flow <flowlnlnln@gmail.com>
2023-01-24 17:04:05 -03:00
6d27ef5eea fix(ResourceFolder): don't create two smart ptrs for the same raw ptr
Signed-off-by: flow <flowlnlnln@gmail.com>
2023-01-24 17:04:01 -03:00
e4e8a51e5c Merge pull request #781 from Ryex/patch-1 2023-01-24 11:15:33 -08:00
3ddf413332 Update launcher/Application.cpp
Co-authored-by: Sefa Eyeoglu <contact@scrumplex.net>
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2023-01-24 09:24:12 -07:00
6eb36fb053 Merge pull request #783 from DioEgizio/update-cmark-fix-cve 2023-01-24 07:25:26 -08:00
58239ff98f fix: update cmark to fix a CVE
Signed-off-by: DioEgizio <83089242+DioEgizio@users.noreply.github.com>
2023-01-24 15:05:13 +01:00
6e841a3b7e Merge branch 'develop' into remove-updater
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2023-01-24 14:40:17 +01:00
085e067fc1 remove NDEBUG check per Scrumplex's orders
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2023-01-24 02:26:21 -07:00
c45fa016c0 fix: let jars be found from inside build dir for debug builds
debug bug builds run form inside the build dir before they are bundled can't find the jars

Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2023-01-23 18:36:58 -07:00
16477a8f6c Merge pull request #675 from flowln/generalize_mod_model 2023-01-23 23:58:52 +01:00
04e4900415 Merge pull request #758 from flowln/fix_process_events_backstab 2023-01-23 23:58:41 +01:00
322f317a5b fix: Undo zlibs file rename when using bundled zlib
Signed-off-by: TheLastRar <TheLastRar@users.noreply.github.com>
2023-01-23 22:36:26 +00:00
ea5020e188 fix(license): add/fix my copyright/license headers
*sobbing in messy legal stuff i know nothing about*

Signed-off-by: flow <flowlnlnln@gmail.com>
2023-01-23 11:12:43 -03:00
cefa1662ef Merge pull request #772 from TheLastRar/zlib-fallback-bundled-fix
Fix: zlib fallback not working
2023-01-23 00:07:34 +01:00
2a949fcb86 fix: zlib fallback
Signed-off-by: TheLastRar <TheLastRar@users.noreply.github.com>
2023-01-22 15:04:15 +00:00
445f9e5f71 feat+fix(Version): make comparsion FlexVer-compatible
... and fixes a minor issue in the parsing.

This changes the expected behavior of Versions in one significant way:
Now, Versions like 1.2 or 1.5 evaluate to LESS THAN 1.2.0 and 1.5.0
respectively. This makes sense for sorting versions, since one expects
the versions without patch release to 'contain' the ones with, so the
ones without should be evaluated uniformily with the ones with the
patch.

Signed-off-by: flow <flowlnlnln@gmail.com>
2023-01-21 18:47:47 -03:00
5a25ce8c1b Fix main window icon and stuff
i forgor 💀

Signed-off-by: leo78913 <leo3758@riseup.net>
2023-01-20 19:45:43 -03:00
670cf8ee07 Fix: make the newsLabel toolbutton fullwidth again
this reverts it to how it was before the MainWindow .ui port

Signed-off-by: leo78913 <leo3758@riseup.net>
2023-01-20 19:45:43 -03:00
6c5f6e8900 Fix status bar name
Signed-off-by: leo78913 <leo3758@riseup.net>
2023-01-20 19:45:43 -03:00
4ed4fb2314 remove useless setEnabled calls
Signed-off-by: leo78913 <leo3758@riseup.net>
2023-01-20 19:45:43 -03:00
f16989bea9 feat(WideBar): custom context menu actions
Signed-off-by: leo78913 <leo3758@riseup.net>
2023-01-20 19:45:43 -03:00
55d4064335 Fix: translate actionNoDefaultAcount text
Co-authored-by: flow <flowlnlnln@gmail.com>
Signed-off-by: leo78913 <leo3758@riseup.net>
2023-01-20 19:45:43 -03:00
3b38a4c690 Fix: translate NoAccountsAdded text
Co-authored-by: flow <flowlnlnln@gmail.com>
Signed-off-by: leo78913 <leo3758@riseup.net>
2023-01-20 19:45:43 -03:00
ada595663d fix(widebar): fix insertSeparator
WideBar::insertSeparator was adding the separator to the end of the toolbar

Signed-off-by: leo78913 <leo3758@riseup.net>
2023-01-20 19:45:43 -03:00
b2de01b076 feat(WideBar): Allow disabling alt shortcuts
Signed-off-by: leo78913 <leo3758@riseup.net>
2023-01-20 19:45:43 -03:00
f3acf35aea refactor: Port the main window to a .ui file
some stuff still needs to be done in the c++ side because qt designer is dumb >:(

the instance toolbar icon and instance name buttons are still added manually inside MainWindow.cpp

looks almost identical, with some minor tweaks:
- the instance toolbar is now a WideBar, so you can customize what actions you want :D
- the instance toolbar buttons are now fullwidth
- the close window button is now at the end of the file menu
- the help menu has some layout changes

this also fixes some stuff:
- menus not having tooltips
- the top toolbar not connecting to the title bar in kde
- the instance toolbar separators looking weird after you move the toolbar

Signed-off-by: leo78913 <leo3758@riseup.net>
2023-01-20 19:45:43 -03:00
3da1d6a464 feat: add Widebar::InsertWidgetBefore method
Signed-off-by: leo78913 <leo3758@riseup.net>
2023-01-20 19:44:39 -03:00
b9df10c8bd Merge pull request #766 from TayouVR/change-cat-on-settings-change
closes https://github.com/PrismLauncher/PrismLauncher/issues/763
2023-01-20 08:36:08 -08:00
ec1f73c827 fix(tests): add some comments on the stack overflow Task test
Signed-off-by: flow <flowlnlnln@gmail.com>
2023-01-20 12:55:38 -03:00
cdc9f93f71 make MainWindow cat update instantly
Signed-off-by: Tayou <tayou@gmx.net>
2023-01-20 15:16:25 +01:00
bcebb1920f refactor: clean up Section struct
Signed-off-by: flow <flowlnlnln@gmail.com>
2023-01-20 11:15:26 -03:00
81848e05f1 refactor: simplify Version operators
Signed-off-by: flow <flowlnlnln@gmail.com>
2023-01-20 11:15:26 -03:00
5ae69c079a feat(tests): add FlexVer test vector to the Version tests
Signed-off-by: flow <flowlnlnln@gmail.com>
2023-01-20 11:15:26 -03:00
0199d8a74f Version.cpp: Add new line
Signed-off-by: Edgars Cīrulis <edgarsscirulis@gmail.com>
2023-01-19 14:12:59 +02:00
f49ad2ee03 Version.h: Fix comparison of null version in Version class
Co-authored-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
Signed-off-by: Edgars Cīrulis <edgarsscirulis@gmail.com>
2023-01-19 10:40:30 +02:00
7ed993b54e fix: proper null padded version comparison
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2023-01-19 09:51:11 +02:00
9934537e19 feat: add debug printing for Version
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2023-01-19 09:50:45 +02:00
00d42d296e fix: call processEvents() before adding new tasks to the task queue
This allows the ongoing task to go off the stack before the next one is
started.

Signed-off-by: flow <flowlnlnln@gmail.com>
2023-01-18 16:23:30 -03:00
ad74fedfba feat(tests): add test for stack overflow in ConcurrentTask
Signed-off-by: flow <flowlnlnln@gmail.com>
2023-01-18 16:23:30 -03:00
730f714e97 Version.cpp: Remove unnecessary QStringList include
Signed-off-by: Edgars Cīrulis <edgarsscirulis@gmail.com>
2023-01-17 22:39:19 +02:00
3bec4a80b3 Version.cpp: Decompose version strings according to flexver
Co-authored-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
Signed-off-by: Edgars Cīrulis <edgarsscirulis@gmail.com>
2023-01-17 22:39:12 +02:00
a84e4b0e07 Version.cpp: Format parse function code using clang-format
Signed-off-by: Edgars Cīrulis <edgarsscirulis@gmail.com>
2023-01-17 07:14:49 +02:00
198139feb4 Version.cpp: Simplify Version::parse by using const auto& current_char
Signed-off-by: Edgars Cīrulis <edgarsscirulis@gmail.com>
2023-01-17 07:14:37 +02:00
de11017552 Version.cpp: Use anonymous function to eliminate code duplication
Signed-off-by: Edgars Cīrulis <edgarsscirulis@gmail.com>
2023-01-17 07:14:29 +02:00
6fb837c529 Version.cpp: Add version string parser to split on '.' character
Signed-off-by: Edgars Cīrulis <edgarsscirulis@gmail.com>
2023-01-17 07:14:05 +02:00
c0c3892064 Version.cpp: Improve version parsing to handle mixed numeric and alphabetic characters
Signed-off-by: Edgars Cīrulis <edgarsscirulis@gmail.com>
2023-01-17 07:13:24 +02:00
1a35fec134 Merge pull request #696 from Ryex/import-all-the-things
Fixes https://github.com/PrismLauncher/PrismLauncher/issues/581
Fixes https://github.com/PrismLauncher/PrismLauncher/issues/700
2023-01-16 10:04:09 +01:00
f1247d2224 Merge pull request #753 from PrismLauncher/renovate/hendrikmuhs-ccache-action-1.x 2023-01-15 11:39:50 -03:00
7992b7eb89 chore(deps): update hendrikmuhs/ccache-action action to v1.2.8 2023-01-15 13:40:16 +00:00
cd893e18d2 chore: update license headers
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2023-01-14 17:21:52 +01:00
a5c8b166fe Merge pull request #746 from RaptaG/patch-1 2023-01-14 17:17:49 +01:00
72a9b98ef0 We're in 2023 :)
Signed-off-by: RaptaG <77157639+RaptaG@users.noreply.github.com>
2023-01-14 17:55:56 +02:00
cf022524d1 Merge pull request #743 from flowln/fix_mods_with_wrong_modListVersion 2023-01-14 12:19:12 -03:00
ebb0596c1a fix: don't fail mod parsing when encountering invalid modListVersion
The spec (admitely a very old one) states that this entry should always
have the value "2". However, some mods do not follow this convention,
causing issues.

One notable example is the 1.6 version of Aether II for 1.7.10, that has
this value set at "5" for whatever reason.

Signed-off-by: flow <flowlnlnln@gmail.com>
2023-01-13 21:15:10 -03:00
3de681d2d6 Merge pull request #685 from byteduck/instance-accounts 2023-01-13 17:21:12 -03:00
f7b0ba88da Apply suggestions from code review
Co-authored-by: Sefa Eyeoglu <contact@scrumplex.net>
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2023-01-13 13:15:13 -07:00
c95c81d42f fix(ModUpdater): ensure instead of require icon_url
The spec says that this can be null, and indeed some mods have it set to
null, and should still be considered as valid.

Signed-off-by: flow <flowlnlnln@gmail.com>
2023-01-13 16:59:37 -03:00
9407596b12 fix(ModUpdater): fail mods individually when there's errors in the JSON
Prevents a single problematic mod from invalidating all the API
response.

Signed-off-by: flow <flowlnlnln@gmail.com>
2023-01-13 16:49:21 -03:00
c294c2d1df refactor(RD): allow setting custom folder target for downloaded resources
Signed-off-by: flow <flowlnlnln@gmail.com>
2023-01-13 16:23:09 -03:00
bd36f8e220 fix(RD): set resource strings for ReviewMessageBox too
Signed-off-by: flow <flowlnlnln@gmail.com>
2023-01-13 16:23:09 -03:00
3a168ba6dd feat(tests): add very basic ResourceModel test
______very_____ basic indeed, creating tests is super boring :c

Signed-off-by: flow <flowlnlnln@gmail.com>
2023-01-13 16:23:09 -03:00
1919069b12 fix(RD): don't assert search offset on fetchMore() in ResourceModel
This allows the standard QAbstractItemModelTester to work without
shenanigans!

Signed-off-by: flow <flowlnlnln@gmail.com>
2023-01-13 16:23:09 -03:00
ba677a8cb7 refactor: change some ResourceAPI from NetJob to Task
This makes it easier to create resource apis that aren't network-based.

Signed-off-by: flow <flowlnlnln@gmail.com>
2023-01-13 16:23:09 -03:00
e62e1d9701 refactor(RD): move BaseInstance dep. to subclasses of ResourceModel
Signed-off-by: flow <flowlnlnln@gmail.com>
2023-01-13 16:23:08 -03:00
b3330cb0da fix(RD): correctly set the strings for the specific resource names
Signed-off-by: flow <flowlnlnln@gmail.com>
2023-01-13 16:23:08 -03:00
7d128c79a3 fix: CodeQL warnings about the rule of two
shush

Signed-off-by: flow <flowlnlnln@gmail.com>
2023-01-13 16:23:08 -03:00
3cff23dae2 refactor(RD): move success callbacks from ModModel to ResourceModel
While implementing the resource pack downloader in another branch, I
noticed that most of the code in the success callback was identical in
both cases, safe for a few minute differences in strings. So, this tries
to make it easier to share this piece of code.

However, it still leaves the possibility of extending the methods in
ResourceModel to accomodate for cases where this similarity may not
hold.

Signed-off-by: flow <flowlnlnln@gmail.com>
2023-01-13 16:23:08 -03:00
c3f0139f76 refactor(RD): add helper in ResourceModel to find current sorting
Signed-off-by: flow <flowlnlnln@gmail.com>
2023-01-13 16:23:08 -03:00
563fe8d515 fix(RD): separate search and versions/info tasks
This allows us to check whether a search request is already on-going, in
which case we don't need to make another one (and shouldn't).

Signed-off-by: flow <flowlnlnln@gmail.com>
2023-01-13 16:23:08 -03:00
38e20eb148 fix(RD): pass copy of IndexedPack to callbacks instead of ref.
This prevents a crash in which the pack list gets updated in a search
request meanwhile a versions / extra info request is being processed.
Previously, this situation would cause the reference in the latter
callbacks to be invalidated by an internal relocation of the pack list.

Signed-off-by: flow <flowlnlnln@gmail.com>
2023-01-13 16:23:07 -03:00
36571c5e22 refactor(RD): clear up sorting methods
This refactors the sorting methods to join every bit of it into a single
list, easing maintanance. It also removes the weird index contraint on
the list of methods by adding an index field to the DS that holds the
method.

Lastly, it puts the available methods on their respective API, so other
resources on the same API can re-use them later on.

Signed-off-by: flow <flowlnlnln@gmail.com>
2023-01-13 16:23:07 -03:00
c8eca4fb85 fix: build with qt5.12 on Linux and pedantic flag
Signed-off-by: flow <flowlnlnln@gmail.com>
2023-01-13 16:23:07 -03:00
0e207aba6c feat(RD): add roleNames and Q_PROPERTY to ResourceModel
in preparation for QML interop.

Signed-off-by: flow <flowlnlnln@gmail.com>
2023-01-13 16:23:07 -03:00
45d1319891 refactor(RD): decouple ResourceModels from ResourcePages
This makes it so that we don't need a reference to the parent page in
the model. It will be useful once we change the page from a widget-based
one to a QML page.

It also makes tasks be created in the dialog instead of the page, so
that the dialog can also have the necessary information to mark versions
as selected / deselected easily. It also makes the task pointers into
smart pointers.

Signed-off-by: flow <flowlnlnln@gmail.com>
2023-01-13 16:23:07 -03:00
39b7ac90d4 refactor(RD): unify download dialogs into a single file
No need for multiple files since the subclasses are so small now

Signed-off-by: flow <flowlnlnln@gmail.com>
2023-01-13 16:23:06 -03:00
ef87bdf18a fix(RD): prevent weird behavior of progress widget
when i.e. clicking on links or just using the downloader at all, this
prevents some flickering and the widget never getting hidden in some
cases.

Signed-off-by: flow <flowlnlnln@gmail.com>
2023-01-13 16:23:06 -03:00
433a802c6e refactor: put resource downloading classes in common namespace
Puts them all inside the 'ResourceDownload' namespace, so that it's a
bit clearer from the outside that those belong to the same 'module'.

Signed-off-by: flow <flowlnlnln@gmail.com>
2023-01-13 16:23:06 -03:00
6a18079953 refactor: generalize mod models and APIs to resources
Firstly, this abstract away behavior in the mod download models that can
also be applied to other types of resources into a superclass, allowing
other resource types to be implemented without so much code duplication.

For that, this also generalizes the APIs used (currently, ModrinthAPI
and FlameAPI) to be able to make requests to other types of resources.

It also does a general cleanup of both of those. In particular, this
makes use of std::optional instead of invalid values for errors and,
well, optional values :p

This is a squash of some commits that were becoming too interlaced
together to be cleanly separated.

Signed-off-by: flow <flowlnlnln@gmail.com>
2023-01-13 16:23:00 -03:00
b937d33436 Merge pull request #714 from redstrate/cmark 2023-01-13 16:16:00 -03:00
f7244fbf68 Merge pull request #737 from PrismLauncher/renovate/hendrikmuhs-ccache-action-1.x
chore(deps): update hendrikmuhs/ccache-action action to v1.2.7
2023-01-13 08:17:59 +01:00
4e80d1fc79 DCO Remediation Commit for Aaron <10217842+byteduck@users.noreply.github.com>
I, Aaron <10217842+byteduck@users.noreply.github.com>, hereby add my Signed-off-by to this commit: 160dd09fc2788fea17c8e9e332c2877586640971

Signed-off-by: Aaron <10217842+byteduck@users.noreply.github.com>
2023-01-12 20:16:48 -08:00
b2f48eaeb8 Merge branch 'PrismLauncher:develop' into instance-accounts 2023-01-12 20:11:46 -08:00
160dd09fc2 Fix instance account selector face for offline accounts 2023-01-12 20:03:31 -08:00
80eea05deb chore(deps): update hendrikmuhs/ccache-action action to v1.2.7 2023-01-12 22:06:50 +00:00
5e89ba7079 Merge pull request #732 from DioEgizio/actually-fix-openssl3-mac-failures 2023-01-12 16:31:03 +01:00
ff7878217d fix: add cmark:p to mingw build
this way we can just dynamically link it on that build instead of building it ourselves and statically linking it

Signed-off-by: DioEgizio <83089242+DioEgizio@users.noreply.github.com>
2023-01-12 10:08:52 -05:00
807da6a035 fix: Remove extra line breaks for modrinth descriptions
Signed-off-by: Joshua Goins <josh@redstrate.com>
2023-01-12 10:08:52 -05:00
4e2a958896 fix(flatpak): enable builddir
Signed-off-by: Joshua Goins <josh@redstrate.com>
2023-01-12 10:08:52 -05:00
3ee0ec7cd0 fix(nix): add cmark dependency
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2023-01-12 10:08:52 -05:00
22a2b7ac46 refactor: support system and bundled cmark
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2023-01-12 10:08:52 -05:00
aa7c910e26 build: remove hoedown vendored source
Signed-off-by: Joshua Goins <josh@redstrate.com>
2023-01-12 10:08:52 -05:00
24a4bd3a1c refactor: replace hoedown markdown parser with cmark
Signed-off-by: Joshua Goins <josh@redstrate.com>
2023-01-12 10:08:52 -05:00
fff52cb247 feat: add button to import component JSONs
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2023-01-11 13:50:57 +01:00
219c5b323d Merge pull request #731 from flowln/windows_server_trash 2023-01-11 09:49:20 +01:00
14278a9e35 fix: set HOMEBREW_NO_INSTALLED_DEPENDENTS_CHECK to 1
should fix some random failures

Signed-off-by: DioEgizio <83089242+DioEgizio@users.noreply.github.com>
2023-01-10 20:02:20 +01:00
dd013209e8 Merge pull request #730 from DioEgizio/aaaaaaaa-revert
Revert "Merge pull request #729 from DioEgizio/fix-mac-openssl3-failing"
2023-01-10 17:44:23 +01:00
96d5438633 Merge pull request #249 from TayouVR/theme-selector-first-time-wizard 2023-01-10 13:28:57 -03:00
391ef64c22 fix(FileSystem): don't attempt to trash items on Windows Server
For some reason this makes some of our CI test runs super slow, and
sometimes fail miserably.

Signed-off-by: flow <flowlnlnln@gmail.com>
2023-01-10 12:50:56 -03:00
d45a62b3a6 Revert "Merge pull request #729 from DioEgizio/fix-mac-openssl3-failing"
it was necessary :/

This reverts commit 976e550aa7291f22f5011178ab824a937f89d11a, reversing
changes made to 61144f7a219995fa29531683ed36e8e4002848b5.

Signed-off-by: DioEgizio <83089242+DioEgizio@users.noreply.github.com>
2023-01-10 16:47:28 +01:00
976e550aa7 Merge pull request #729 from DioEgizio/fix-mac-openssl3-failing
fix: just use github runner's openssl 1.1 instead of installing 3 on …
2023-01-10 16:28:02 +01:00
668b19d119 Add hint about Cat
Signed-off-by: Tayou <tayou@gmx.net>
2023-01-10 16:09:57 +01:00
5c48f0b458 fix: set minimum size for setup wizard
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2023-01-10 16:06:50 +01:00
689fe1e2c7 CRLF -> LF
damn you visual studio for creating CRLF files everywhere...
Signed-off-by: Tayou <tayou@gmx.net>
2023-01-10 16:06:50 +01:00
7d440402ad Update launcher/Application.cpp with suggestion from scrumplex
Co-authored-by: Sefa Eyeoglu <contact@scrumplex.net>
Signed-off-by: Tayou <tayou@gmx.net>
2023-01-10 16:06:42 +01:00
6daa457838 Implement Suggestions from flow & Scrumplex
Signed-off-by: Tayou <tayou@gmx.net>
2023-01-10 16:06:42 +01:00
49d317b19a UX tweak + formatting + added cat to wizard
Signed-off-by: Tayou <tayou@gmx.net>
2023-01-10 16:06:24 +01:00
1b80ae0fca add theme setup wizard
Signed-off-by: Tayou <tayou@gmx.net>
2023-01-10 16:06:01 +01:00
a113ecca8b fix: just use github runner's openssl 1.1 instead of installing 3 on macos signing
Signed-off-by: DioEgizio <83089242+DioEgizio@users.noreply.github.com>
2023-01-10 15:03:28 +01:00
61144f7a21 Merge pull request #726 from TheLastRar/qt6-win-darkmode
Closes https://github.com/PrismLauncher/PrismLauncher/issues/158
2023-01-10 08:48:17 +01:00
574af2c795 chore: cleanup review suggestions
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2023-01-09 17:18:08 -07:00
a4870d4834 fix: fix #700
fixed by properly converting from a file path and converting to native seperators.
should have known naive handling of file path as a URL would come back to bite us cross platform.

Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2023-01-09 17:00:12 -07:00
78bbcac0ea ui: Let Qt 6.4.2 handle dark mode titlebar
Signed-off-by: TheLastRar <TheLastRar@users.noreply.github.com>
2023-01-09 19:44:11 +00:00
ca9b2525c8 Merge pull request #715 from getchoo/add-teawie 2023-01-09 09:46:31 +01:00
bb1c387a98 Merge pull request #722 from PrismLauncher/renovate/actions-cache-3.x 2023-01-09 09:41:32 +01:00
38ce37b6fd Merge pull request #720 from PrismLauncher/renovate/hendrikmuhs-ccache-action-1.x 2023-01-09 09:41:03 +01:00
7fdc81236e chore(deps): update actions/cache action to v3.2.3 2023-01-09 07:54:22 +00:00
fca40c1c6b chore(deps): update hendrikmuhs/ccache-action action to v1.2.6 2023-01-08 22:40:41 +00:00
d5d5d66e03 Merge pull request #716 from DioEgizio/qt6.4.2-winmsvc
closes https://github.com/PrismLauncher/PrismLauncher/issues/288
2023-01-08 11:33:13 -03:00
0481ae187a chore: update windows msvc to qt 6.4.2
Signed-off-by: DioEgizio <83089242+DioEgizio@users.noreply.github.com>
2023-01-08 10:34:45 +01:00
9de6927c3f feat: add CC BY-SA 4.0 info for teawie images
Signed-off-by: seth <getchoo@tuta.io>
2023-01-07 19:18:22 -05:00
30b01ef053 fix: *sigh* no implicit QString->QFileInfo conversion in Qt6, again...
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2023-01-07 15:04:23 -07:00
03b75bf2a9 feat: Import all the things!
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2023-01-07 15:04:22 -07:00
f3f628410d Merge pull request #576 from Ryex/identify-zip-packs
fix https://github.com/PrismLauncher/PrismLauncher/issues/349
2023-01-07 17:33:34 +01:00
9901ecda49 Merge pull request #710 from byquanton/develop
Fixes https://github.com/PrismLauncher/PrismLauncher/issues/708
2023-01-07 17:18:10 +01:00
39becf607e Merge pull request #713 from redstrate/fix-html-rendering 2023-01-07 12:57:35 -03:00
f5955a4738 feat: add bday teawie
Signed-off-by: seth <getchoo@tuta.io>
2023-01-07 04:47:53 -05:00
e018b30875 fix: make spooky teawie load
gimp fail

Signed-off-by: seth <getchoo@tuta.io>
2023-01-07 04:38:26 -05:00
2dbd775cf3 feat: add xmas teawie
Signed-off-by: seth <getchoo@tuta.io>
2023-01-07 04:37:41 -05:00
a5051327db feat: add spooky teawie
Signed-off-by: seth <getchoo@tuta.io>
2023-01-07 03:42:53 -05:00
8140f5136d feat: add teawie
drawn by sympathytea (https://github.com/SympathyTea)

Signed-off-by: seth <getchoo@tuta.io>
2023-01-06 22:28:15 -05:00
f04703f09b Strip certain HTML tags when rendering mod pages
Some mod pages use certain tags for centering purposes, but trips up
hoedown.

Signed-off-by: Joshua Goins <josh@redstrate.com>
2023-01-06 15:05:19 -05:00
2faf8332ee fix: Add 1.16+ Forge library prefix in TechnicPackProcessor.cpp
Signed-off-by: byquanton <32410361+byquanton@users.noreply.github.com>
2023-01-06 02:44:10 +01:00
e0e3d4d8fe Merge branch 'PrismLauncher:develop' into instance-accounts 2023-01-02 11:59:29 -07:00
ba81ad1ac3 Reword instance-specific account settings, apply clang-format
Signed-off-by: Aaron <10217842+byteduck@users.noreply.github.com>
2023-01-02 11:17:19 -07:00
eefb259ddf Remove unecessary delete in InstanceSettingsPage destructor
Co-authored-by: flow <flowlnlnln@gmail.com>
Signed-off-by: Aaron Sonin <10217842+byteduck@users.noreply.github.com>
Signed-off-by: Aaron <10217842+byteduck@users.noreply.github.com>
2023-01-02 11:17:19 -07:00
9b8add1961 Properly connect signal in instance settings for account selector
Co-authored-by: flow <flowlnlnln@gmail.com>
Signed-off-by: Aaron Sonin <10217842+byteduck@users.noreply.github.com>
Signed-off-by: Aaron <10217842+byteduck@users.noreply.github.com>
2023-01-02 11:17:19 -07:00
e186523878 Add null check for face in instance account settings selector
Co-authored-by: flow <flowlnlnln@gmail.com>
Signed-off-by: Aaron Sonin <10217842+byteduck@users.noreply.github.com>
Signed-off-by: Aaron <10217842+byteduck@users.noreply.github.com>
2023-01-02 11:17:19 -07:00
021e6c02d7 Replace unecessary type check with assertion in InstanceSettingsPage
Co-authored-by: flow <flowlnlnln@gmail.com>
Signed-off-by: Aaron Sonin <10217842+byteduck@users.noreply.github.com>
Signed-off-by: Aaron <10217842+byteduck@users.noreply.github.com>
2023-01-02 11:17:19 -07:00
cba3d68063 Fix conflicting layout name in InstanceSettingsPage
Signed-off-by: Aaron <10217842+byteduck@users.noreply.github.com>
2023-01-02 11:17:19 -07:00
7e2d78bab5 Allow selecting a default account to use with an instance
Signed-off-by: Aaron <10217842+byteduck@users.noreply.github.com>
2023-01-02 11:17:19 -07:00
4b12c85d91 Merge pull request #673 from PrismLauncher/renovate/flatpak-flatpak-github-actions-5.x
chore(deps): update flatpak/flatpak-github-actions action to v5
2022-12-30 19:23:10 +01:00
0ebf04a021 fix newlines
Co-authored-by: flow <flowlnlnln@gmail.com>
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2022-12-30 10:21:49 -07:00
d55f47077a Merge pull request #626 from leo78913/mods-provider-column
closes https://github.com/PrismLauncher/PrismLauncher/issues/402
2022-12-30 11:39:03 -03:00
11df4845b7 fix: remove Flatpak cache key workaround
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2022-12-30 15:36:35 +01:00
7f438425aa refactor: add an identify function to make easy to reuse
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2022-12-29 19:47:19 -07:00
c470f05abf refactor: use std::filesystem::rename insted of copy and then moving.
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2022-12-29 17:21:54 -07:00
141e94369e feat(Mods): hide 'Provider' column when no mods have providers
This makes the mod list look a bit less polluted in the common case of
mods having no provider whatsoever.

Signed-off-by: flow <flowlnlnln@gmail.com>
2022-12-29 13:21:49 -03:00
257970c27d refactor(Mods): make provider() return a std::optional
This makes it easier to check if a mod has a provider or not, without
having to do a string comparison.

Signed-off-by: flow <flowlnlnln@gmail.com>
2022-12-29 13:21:49 -03:00
67ac3da8a0 Merge pull request #684 from Scrumplex/logging-categories
Prevents private credentials from leaking in the logs of general users
2022-12-28 09:54:23 -08:00
c1e5179b5f Merge pull request #680 from AshtakaOOf/flathub-screenshots 2022-12-28 13:48:39 +01:00
7a651bdc53 feat: install launcher logging categories
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2022-12-27 18:10:01 +01:00
f33f596584 refactor: use ECM logging categories instead
Co-authored-by: flow <flowlnlnln@gmail.com>
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2022-12-27 17:34:21 +01:00
c8d8046412 refactor: add logging category for credentials
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2022-12-27 17:04:42 +01:00
4d334b645d Merge pull request #681 from PrismLauncher/renovate/actions-cache-3.x 2022-12-27 13:54:00 +01:00
58d3779efb chore(deps): update actions/cache action to v3.2.2 2022-12-27 12:20:21 +00:00
3691f3a296 fix: cleanup and suggested changes
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2022-12-26 14:50:15 -07:00
463b4fbe0c Fix
Me when me when me when

Signed-off-by: Adrien <66513643+AshtakaOOf@users.noreply.github.com>
2022-12-26 20:09:47 +01:00
9f1c79a5ec Update org.prismlauncher.PrismLauncher.metainfo.xml.in
Add ModpackUpdate and change some lines

Signed-off-by: Adrien <66513643+AshtakaOOf@users.noreply.github.com>
2022-12-26 19:59:46 +01:00
70573b6f31 Update org.prismlauncher.PrismLauncher.metainfo.xml.in
Should be the right properties (I hope)

Signed-off-by: Adrien <66513643+AshtakaOOf@users.noreply.github.com>
2022-12-26 19:24:17 +01:00
6ea1234a3b Merge pull request #618 from TheKodeToad/safer-destructive-actions
Fixes https://github.com/PolyMC/PolyMC/issues/948
2022-12-26 17:48:43 +01:00
434f639b0c Use optional instead of hardcoded cancelled string
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2022-12-26 14:58:37 +00:00
bf04becc9e About to -> you are about to
You're is used in some other places but im lazy

Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2022-12-26 14:45:04 +00:00
b2082bfde7 fix: explicit QFileInfo converison for qt6
fix: validatePath in validateZIPResouces

Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2022-12-25 17:16:26 -07:00
78984eea3a feat: support installing worlds during flame pack import.
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2022-12-25 16:49:56 -07:00
8422e3ac01 feat: zip resource validation check for flame
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2022-12-24 20:43:17 -07:00
cfce54fe46 fix: update parse tests
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2022-12-24 20:43:17 -07:00
a7c9b2f172 feat: validate world saves
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2022-12-24 20:43:17 -07:00
eb31a951a1 feat: worldSave parsing and validation
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2022-12-24 20:43:01 -07:00
ccfe605920 feat: add shaderpack validation
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2022-12-24 15:55:10 -07:00
878614ff68 feat: add a ModUtils::validate
moves the reading of mod files into `ModUtils` namespace

Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2022-12-24 09:42:02 -07:00
25e23e50ca fix: force add of ignored testdata files
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2022-12-24 09:42:02 -07:00
64c51a70a3 feat: add initial support for parseing datapacks
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2022-12-24 09:42:02 -07:00
e4296c48c8 chore(deps): update flatpak/flatpak-github-actions action to v5 2022-12-24 16:20:44 +00:00
dd3848d7b1 Merge pull request #666 from getchoo/pls-scrump
scrump heard your pleads, rejoice!
2022-12-24 06:38:49 -08:00
56ac1a0813 Merge pull request #665 from flowln/logging_categories 2022-12-24 03:58:49 -08:00
cbe5af235c Make requested changes
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2022-12-24 08:59:55 +00:00
f932ffcc5b fix: check if GIT_REFSPEC is empty
Signed-off-by: seth <getchoo@tuta.io>
2022-12-23 20:50:08 -05:00
0a50c5bf40 Merge pull request #644 from RaptaG/new-readme 2022-12-23 04:39:57 -08:00
e416e5d301 Merge pull request #667 from PrismLauncher/renovate/actions-cache-3.x 2022-12-23 04:00:43 -08:00
3227859992 chore(deps): update actions/cache action to v3.2.1 2022-12-23 08:18:30 +00:00
01139c3b50 fix: assume builds are stable when git isn't installed
Signed-off-by: seth <getchoo@tuta.io>
2022-12-22 19:25:04 -05:00
ee3e65d759 feat(docs): add note about logging env variables in man page
Signed-off-by: flow <flowlnlnln@gmail.com>
2022-12-22 19:18:16 -03:00
c85867395d feat: use Qt logging facilities instead of our own
This system allows us to globally define categories, and control whether
they are shown or not at runtime. It also does some things by it's own,
so we can remove some (uhhh) code.

Lastly, this allows changing the behavior of the logger at runtime via
environment variables that Qt takes care of for us.

Signed-off-by: flow <flowlnlnln@gmail.com>
2022-12-22 19:15:50 -03:00
bf2ce54076 Merge pull request #656 from PrismLauncher/renovate/actions-cache-3.x 2022-12-21 07:30:23 -08:00
07de285299 chore(deps): update actions/cache action to v3.2.0 2022-12-21 14:46:35 +00:00
8c194cd245 Merge pull request #649 from Scrumplex/fix-winget-release-no9999999 2022-12-19 16:36:42 +01:00
8cbec3d5a0 fix: update installers-regex for winget releaser again
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2022-12-19 16:31:50 +01:00
cdf05e74c8 Merge pull request #647 from Scrumplex/update-flake 2022-12-19 16:09:55 +01:00
b98b4f1027 chore(nix): update flakes
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2022-12-19 15:54:10 +01:00
fc11dfd6b4 refactor(nix): use tomlplusplus from nixpkgs
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2022-12-19 15:54:09 +01:00
483a5b6cae fix(nix): use jdk17 instead of jdk
See NixOS/nixpkgs#206806

Co-authored-by: Infinidoge <infinidoge@doge-inc.net>
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2022-12-19 15:44:05 +01:00
df1b7f1656 Merge pull request #628 from flowln/fix_multiple_resource_packs_crash
Fixes https://github.com/PrismLauncher/PrismLauncher/issues/624
2022-12-19 15:35:34 +01:00
a566d1c5de Change numbered list to bullet list
Signed-off-by: RaptaG <77157639+RaptaG@users.noreply.github.com>
2022-12-18 18:01:44 +02:00
11c8237d8b Merge pull request #642 from DioEgizio/dont-ship-unnecessary-tlsbackends
fix: exclude unused tls backends
2022-12-18 16:27:48 +01:00
6dc19c85a8 Improve the README
Not very serious changes, just some enhancements to make it look better!

Signed-off-by: RaptaG <77157639+RaptaG@users.noreply.github.com>
2022-12-18 15:23:22 +02:00
6e07c11f65 fix: exclude unused tls backends
makes bundles slightly smaller on windows and macos:

- qopensslbackend will not be used neither on macos nor on qt6 windows, so let's just not copy it
- qcertonlybackend won't be used and wouldn't work for prism anyways as it doesn't support some features we use

Signed-off-by: DioEgizio <83089242+DioEgizio@users.noreply.github.com>
2022-12-18 11:03:48 +01:00
8da6667816 Merge pull request #636 from flowln/fix_component_version_when_updating
Correctly set component versions in Modrinth pack updating
2022-12-17 17:26:34 +01:00
81fedbf03c refactor(Tasks): remove 'm_total_size' from ConcurrentTask
We can use the queues directly instead.

Signed-off-by: flow <flowlnlnln@gmail.com>
2022-12-17 13:10:19 -03:00
0516055b31 Merge pull request #630 from leo78913/yeet-scrollbars 2022-12-17 08:02:41 -08:00
e3f8d99087 refactor(Inst. Import): use m_* for member variables in MR components
Makes it clearer what is being changed when.

Signed-off-by: flow <flowlnlnln@gmail.com>
2022-12-17 12:41:10 -03:00
22aebc2215 fix(Inst. Import): correctly set component versions when updating
This makes it so that the later call to parse the old manifest doesn't
change the class data, so that the new data con continue there and be
reflected on the component list later.

Co-authored-by: Sefa Eyeoglu <contact@scrumplex.net>
Signed-off-by: flow <flowlnlnln@gmail.com>
2022-12-17 12:38:58 -03:00
3653e9d5e3 let the theme decide the notes page right margin
Signed-off-by: leo78913 <leo3758@riseup.net>
2022-12-17 12:05:20 -03:00
40f16b6d62 Merge pull request #631 from getchoo/better-msvc-flags 2022-12-17 05:53:17 -08:00
a61daa40dc fix: re-enable /GS and only use some flags on release builds
Signed-off-by: seth <getchoo@tuta.io>
2022-12-16 16:05:12 -05:00
ee67b5f1ad Merge pull request #607 from flowln/dont_crash_on_zip_import
Fixes https://github.com/PrismLauncher/PrismLauncher/issues/609
2022-12-16 07:22:22 -08:00
aa3633d2d7 fix: translate unknown mod provider
Co-authored-by: flow <flowlnlnln@gmail.com>
Signed-off-by: leo78913 <leo3758@riseup.net>
2022-12-16 11:13:54 -03:00
7b805a38b9 feat: improve msvc build flags
- adds /GL, /Gy, and /LTCG for better optimizations
- adds /Gw for a smaller binary size
- adds /guard:cf for added security at runtime
- removes unneeded /GS flag as that's already enabled by default

Signed-off-by: seth <getchoo@tuta.io>
2022-12-15 18:50:35 -05:00
c8d8dda79a fix: only show scrollbars when needed
Signed-off-by: leo78913 <leo3758@riseup.net>
2022-12-15 16:34:52 -03:00
c440f33122 fix(ResourceModel): use a single ConcurrentTask for parsing tasks
This avoids creating a bunch of threads that fills up the maximum amount
allowed by QThreadPool, and causes a deadlock between the helper threads
and the main thread (main thread tries to create threads in painting
code, but isn't able to, so it keeps waiting for a thread to free up,
but all the threads are waiting on the main thread to process some
events).

Signed-off-by: flow <flowlnlnln@gmail.com>
2022-12-15 13:51:07 -03:00
b0c866bfaa feat(Tasks): allow adding subtasks while running in ConcurrentTask
Signed-off-by: flow <flowlnlnln@gmail.com>
2022-12-15 13:48:53 -03:00
dd578354c4 feat(Tasks): add ConcurrentTask::clear to allow re-using tasks
This way old runs won't pile up in the internal DSs

Signed-off-by: flow <flowlnlnln@gmail.com>
2022-12-15 13:45:50 -03:00
fdac978c84 Merge pull request #625 from Edgars-Cirulis/develop 2022-12-15 07:55:28 -08:00
3b81ada1c3 Merge pull request #593 from Scrumplex/fix-winget-release-no999999 2022-12-15 16:35:15 +01:00
4ee29b388d feat: add a provider column to the mods page
Signed-off-by: leo78913 <leo3758@riseup.net>
2022-12-15 12:02:08 -03:00
52dc9068e5 ApplicationMessage: Use QHash instead of QMap
QHash provides faster lookup times than QMap because it uses a hash table to store the elements, while QMap uses a self-balancing binary tree.

Signed-off-by: Edgars Cīrulis <edgarsscirulis@gmail.com>
2022-12-15 16:17:19 +02:00
4f1ea712da Merge pull request #605 from flowln/fix_crash_in_downloader_image
Fixes https://github.com/PrismLauncher/PrismLauncher/issues/590
2022-12-15 04:47:56 -08:00
849b92665e Merge branch 'develop' into remove-updater 2022-12-14 23:22:27 +01:00
d193ed9eeb Merge pull request #561 from leo78913/iconpicker-stuff
closes https://github.com/PrismLauncher/PrismLauncher/issues/494
2022-12-14 23:15:21 +01:00
ee003cd9ee Add confirmation on customised components
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2022-12-14 15:40:20 +00:00
127b094c41 Improve handling of destructive actions
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2022-12-14 15:20:42 +00:00
b2285be5bc Merge pull request #612 from DioEgizio/move-cat-right
closes https://github.com/PrismLauncher/PrismLauncher/issues/611
2022-12-14 13:04:41 +01:00
6ede02bb84 Merge pull request #608 from Scrumplex/bump-7.0 2022-12-14 11:33:46 +01:00
821c424b66 move cat to bottom right
Signed-off-by: DioEgizio <83089242+DioEgizio@users.noreply.github.com>
2022-12-14 08:36:35 +01:00
5450e0edf3 fix(Inst.Import): don't set managed pack info from imported ZIPs
This prevents the Managed Pack page from showing up even though there's
no way for it to work correctly.

Signed-off-by: flow <flowlnlnln@gmail.com>
2022-12-13 13:43:27 -03:00
e05ccc0e55 Merge pull request #601 from Scrumplex/fix-translations-3 2022-12-13 07:01:23 -08:00
4f3786c2e1 chore: bump to 7.0
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2022-12-13 11:10:05 +01:00
107977f3d1 fix: update source strings
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2022-12-13 10:40:35 +01:00
813663485d Merge pull request #604 from flowln/fix_crash_with_gtk2
fix: crash with GTK2 theme due to QProxyStyle in ManagedPackPage
2022-12-13 08:31:52 +01:00
64585d8f78 fix(Inst.Import): don't assert extra data when importing from ZIP
ZIPs don't have the necessary data in those cases.

Signed-off-by: flow <flowlnlnln@gmail.com>
2022-12-13 00:31:41 -03:00
756d933d1a fix: bind image fetch callback lambda to the parent object
Fixes a possible crash with the callback being called after the image
object was already deleted.

Signed-off-by: flow <flowlnlnln@gmail.com>
2022-12-12 23:51:22 -03:00
83deccf266 fix(ManagedPackPage): crash with GTK2 theme due to QProxyStyle
Seemingly related issue: https://bugreports.qt.io/browse/QTBUG-49940

Signed-off-by: flow <flowlnlnln@gmail.com>
2022-12-12 23:31:10 -03:00
aaef448959 Merge pull request #600 from TheLastRar/reset-stylesheet
Resolves https://github.com/PrismLauncher/PrismLauncher/issues/510
2022-12-12 13:28:24 -08:00
7e96077ed7 Fix: Reset stylesheet before setting style
Resolves #510

Signed-off-by: TheLastRar <TheLastRar@users.noreply.github.com>
2022-12-12 20:22:08 +00:00
c44f931059 fix: update installers-regex for winget releaser
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2022-12-12 19:03:32 +01:00
15084c8d6d Merge pull request #587 from unascribed/patch/libraries-wording 2022-12-11 16:57:45 -08:00
Una
822c5a530e Not all libraries are from Mojang
Signed-off-by: Una <me@unascribed.com>
2022-12-11 16:11:32 -08:00
6eb641ae56 Merge pull request #585 from DioEgizio/remove-leftover-todo 2022-12-11 13:02:08 -08:00
9eb14e6b9b fix: remove leftover TODO
Signed-off-by: DioEgizio <83089242+DioEgizio@users.noreply.github.com>
2022-12-11 20:35:39 +01:00
7cc42269a9 Merge pull request #569 from Jan200101/PR/fix-mangohud 2022-12-11 18:31:05 +01:00
c45442760c Merge pull request #584 from TayouVR/fix-breeze-colors-and-matrix-icon 2022-12-11 09:24:53 -08:00
83f0611200 fix breeze icon colors and matrix icon
Signed-off-by: Tayou <tayou@gmx.net>
2022-12-11 17:36:05 +01:00
d95625ed88 Merge pull request #486 from flowln/wide_bar_customization 2022-12-11 04:16:45 -08:00
5622bcc563 Merge pull request #461 from flowln/fix_big_resource_pack_imgs
Fixes https://github.com/PrismLauncher/PrismLauncher/issues/360
2022-12-11 04:16:21 -08:00
deb9c98630 chore: replace naive mangohud preload with vklayer detection
Signed-off-by: Jan200101 <sentrycraft123@gmail.com>
2022-12-11 11:01:34 +01:00
2c1e887c8d chore: replace naive mangohud detection with vulkan layer detection
Signed-off-by: Jan200101 <sentrycraft123@gmail.com>
2022-12-11 11:01:33 +01:00
4a13d72997 Merge pull request #32 from flowln/modpack_update_page
Closes https://github.com/PrismLauncher/PrismLauncher/issues/180
Closes https://github.com/PrismLauncher/PrismLauncher/issues/170
2022-12-10 06:34:18 -08:00
2d5820e910 Update launcher/icons/IconList.cpp
Co-authored-by: flow <flowlnlnln@gmail.com>
Signed-off-by: leo78913 <leo3758@riseup.net>
2022-12-10 10:31:44 -03:00
6cb857b895 Update launcher/icons/IconList.cpp
Co-authored-by: flow <flowlnlnln@gmail.com>
Signed-off-by: leo78913 <leo3758@riseup.net>
2022-12-10 10:31:30 -03:00
590875d022 Merge pull request #575 from Ryex/blockedmods-only-drop-local
Prevent potental crash if droping non local files in BlockedModsDialog
2022-12-10 02:46:55 +01:00
8f30237765 fix: prevent potental crash if droping non local files
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2022-12-09 17:21:40 -07:00
cb0339b492 Merge pull request #572 from DioEgizio/breeze-icons-improvements 2022-12-09 04:14:36 -08:00
e427174ff0 Merge pull request #571 from Ryex/blocked-targetFolder
fix(blockedmods): Track and use targetFolder for blocked files
2022-12-09 08:33:10 +01:00
fc4c57f0d9 feat: improve new.svg in breeze icon packs
makes it better and more similar to the one in legacy

Signed-off-by: DioEgizio <83089242+DioEgizio@users.noreply.github.com>
2022-12-09 07:49:16 +01:00
9ad4ae5340 Merge pull request #568 from leo78913/flatpak-shortcuts 2022-12-08 17:53:33 -08:00
0f48e0fc06 fix(blockedmods): Track and use targetFolder for blocked files
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2022-12-08 18:42:51 -07:00
37ad1b40d8 fix: fix creating instance shortcuts in flatpak
Signed-off-by: leo78913 <leo3758@riseup.net>
2022-12-08 20:18:07 -03:00
514e7ae6a0 fix: re-add LD_LIBARY_PATH to mangohud
Upstream officially supports the use of $LIB/mangohud/

Signed-off-by: Jan200101 <sentrycraft123@gmail.com>
2022-12-08 23:09:14 +01:00
ab2f3bb5bc make removeButton a member of IconPickerDialog
Signed-off-by: leo78913 <leo3758@riseup.net>
2022-12-08 11:13:53 -03:00
34230bfcf4 fix: don't try updating Flame instance names when updating versions
Since the exact version string is only available in the manifest,
there's no easy way of getting it before commiting to the update, so
there's not much of a good way of showing the updated name in the UI,
and using the displayName is weird and gives some buggy behavior.

We may want to re-enable it in the future if we find a reliable way of
showing the correct info on the UI before starting the update.

Signed-off-by: flow <flowlnlnln@gmail.com>
2022-12-07 18:05:46 -03:00
c390e211ee Merge pull request #565 from DioEgizio/shortcut-menu-bar 2022-12-07 12:57:46 -08:00
b0d69db878 fix: add instance shortcut creation action to menubar
also moves deleteinstance to the same place as the instance toolbar

Signed-off-by: DioEgizio <83089242+DioEgizio@users.noreply.github.com>
2022-12-07 16:52:06 +01:00
b373beee21 Merge pull request #511 from Scrumplex/fix-blocked-mods-usability 2022-12-07 06:12:09 -08:00
8c99edd3c5 feat+refactor: trash instance icons
also refactor IconList::deleteIcon

Signed-off-by: leo78913 <leo3758@riseup.net>
2022-12-06 20:25:42 -03:00
8036272e87 fix: disable remove icon button for default icons
pressing this button in the icon picker dialog when a default icon is selected does nothing so why not disable it

Signed-off-by: leo78913 <leo3758@riseup.net>
2022-12-06 20:10:30 -03:00
6f50809457 fix(FlamePage): don't assert / suggest blocked modpacks
Signed-off-by: flow <flowlnlnln@gmail.com>
2022-12-06 17:00:35 -03:00
bb386a1162 fix(ManagedPackPage): only update the current instance exactly
Also carry on the original ID to avoid updating the wrong instance.

Signed-off-by: flow <flowlnlnln@gmail.com>
2022-12-06 17:00:34 -03:00
80054e4db2 fix(ManagedPackPage): preserve pack ID from Modrinth update
Signed-off-by: flow <flowlnlnln@gmail.com>
2022-12-06 17:00:34 -03:00
1630a23fb0 refactor(InstanceImport): require rvalue from 'extra_info' mappings
Signed-off-by: flow <flowlnlnln@gmail.com>
2022-12-06 17:00:34 -03:00
4e75419e08 fix(ManagedPagePage): don't reload pack info when not needed
Signed-off-by: flow <flowlnlnln@gmail.com>
2022-12-06 17:00:34 -03:00
089018015a refactor(ManagedPackPage): use smart pointers instead of raw ones
Signed-off-by: flow <flowlnlnln@gmail.com>
2022-12-06 17:00:34 -03:00
feb6f285ce feat(ManagedPackPage): add reload button when in a fail state
Signed-off-by: flow <flowlnlnln@gmail.com>
2022-12-06 17:00:34 -03:00
cb12c51afc fix(ManagedPackPage): check app capabilities for creating the CF page
Signed-off-by: flow <flowlnlnln@gmail.com>
2022-12-06 17:00:34 -03:00
c5c426ecbc chore(ManagedPackPage): format and add headers
Signed-off-by: flow <flowlnlnln@gmail.com>
2022-12-06 17:00:33 -03:00
74f7039abf fix(ManagedPackPage): clear combo boxes when adding new versions
Prevents versions to undergo mitosis.

Signed-off-by: flow <flowlnlnln@gmail.com>
2022-12-06 17:00:33 -03:00
57b905be24 feat(ManagedPackPage): implement Flame modpack updating button
Signed-off-by: flow <flowlnlnln@gmail.com>
2022-12-06 17:00:33 -03:00
34794cc4af fix(ManagedPackPage): give extra_info to InstanceImportTask in MR packs
Signed-off-by: flow <flowlnlnln@gmail.com>
2022-12-06 17:00:33 -03:00
38f59fdf39 fix(ManagedPackPage): add warning about old bug with pack IDs
Signed-off-by: flow <flowlnlnln@gmail.com>
2022-12-06 17:00:33 -03:00
527c1113f1 feat(ManagedPackPage): add Flame UI
Signed-off-by: flow <flowlnlnln@gmail.com>
2022-12-06 17:00:33 -03:00
04dbe28793 fix(ManagedPackPage): better changelog text when fetching / no changelog
Signed-off-by: flow <flowlnlnln@gmail.com>
2022-12-06 17:00:33 -03:00
968366c2ae feat+fix: allow forwarding extra info to InstanceImportTask
This allows us to pass to the creation instances their actual pack ID
and version ID, that in Flame's case, are only available before starting
to create an instance.

Signed-off-by: flow <flowlnlnln@gmail.com>
2022-12-06 17:00:32 -03:00
7f5dea28bb feat(ManagedPackPage): add link to the Modrinth's pack page
Signed-off-by: flow <flowlnlnln@gmail.com>
2022-12-06 17:00:32 -03:00
d4979974b4 fix(ManagedPackPage): better UX for when network requests fail / are pending
Signed-off-by: flow <flowlnlnln@gmail.com>
2022-12-06 17:00:32 -03:00
9539230915 fix: do not display managed pack page for providers without an impl. yet
Signed-off-by: flow <flowlnlnln@gmail.com>
2022-12-06 17:00:32 -03:00
25cfa26e7b fix: use rich text in changelog for modrinth modpacks
Signed-off-by: flow <flowlnlnln@gmail.com>
2022-12-06 17:00:32 -03:00
0ff8891c66 feat: add ManagedPackPage to the instance pages
Signed-off-by: flow <flowlnlnln@gmail.com>
2022-12-06 17:00:32 -03:00
58d2c15ffa feat: add functionality to MR modpack update in the page :D
Signed-off-by: flow <flowlnlnln@gmail.com>
2022-12-06 17:00:32 -03:00
82699cc297 feat: allow skipping the update confirmation dialog
Signed-off-by: flow <flowlnlnln@gmail.com>
2022-12-06 17:00:32 -03:00
08d008a5aa refactor: abstract away update confirmation dialog
... so that we can avoid code duplication.

Signed-off-by: flow <flowlnlnln@gmail.com>
2022-12-06 17:00:29 -03:00
9e17ff884f feat: add PageContainer::getPage
This allows us to directly access a page from outside. This will be
useful for telling the ManagedPackPage who is the window it's on, so
that we can close it when updating :^)

Signed-off-by: flow <flowlnlnln@gmail.com>
2022-12-06 16:54:54 -03:00
1c567232e3 feat: add (current) indicator to the currently installed version in MR
Signed-off-by: flow <flowlnlnln@gmail.com>
2022-12-06 16:54:54 -03:00
cba2608c1c feat: add logic for the modrinth instance modpack page
Signed-off-by: flow <flowlnlnln@gmail.com>
2022-12-06 16:54:54 -03:00
e5c42f68c2 feat: add basic ManagedPackPage classes
The idea is to have a base class that defines common behavior, and
subclasses for each modpack provider, adding specific behavior.

Signed-off-by: flow <flowlnlnln@gmail.com>
2022-12-06 16:54:54 -03:00
02b4468bcd feat(ui): add ManagedPackPage ui
Signed-off-by: flow <flowlnlnln@gmail.com>
2022-12-06 16:54:50 -03:00
746f6945da fix: remove rogue notr
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2022-12-06 20:52:32 +01:00
5cab4d8864 chore: reformat code
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2022-12-06 20:52:31 +01:00
5cedfcbfaf chore: add license headers
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2022-12-06 20:52:14 +01:00
c06abd9b6b refactor: replace Open All with Open Missing
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2022-12-06 20:52:13 +01:00
e08d97825d feat: implement lax filename match in BlockedModsDialog
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2022-12-06 20:51:18 +01:00
d61323aa6d fix: improve resize behavior of BlockedModsDialog
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2022-12-06 20:51:18 +01:00
5ae044db93 Merge pull request #556 from DioEgizio/modrinth-icon-larger 2022-12-06 11:50:35 -08:00
c6e4fdac7e Merge pull request #557 from Scrumplex/fix-fswatcher-segfault
Closes https://github.com/PrismLauncher/PrismLauncher/issues/555
2022-12-06 11:50:03 -08:00
9669377b06 Merge pull request #560 from edgarogh/fix-minutes-unit
Closes https://github.com/PrismLauncher/PrismLauncher/issues/553
2022-12-06 14:45:46 +01:00
c8c3fe1023 chore: add license headers
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2022-12-06 13:18:50 +01:00
85bddbed86 chore: reformat code
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2022-12-06 13:16:27 +01:00
318a2a429c Fix minutes unit
Replaced "m" with "min" in `Time::prettifyDuration`

Signed-off-by: Edgar Onghena <dev@edgar.bzh>
2022-12-06 13:01:43 +01:00
07359865c6 fix: don't allocate BlockedsModsDialog
Fixes temporary memory leak!

Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2022-12-05 21:39:26 +01:00
2fd7338cd3 dix: disable FS watcher after closing BlockedModsDialog
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2022-12-05 21:39:24 +01:00
ce3cfa212c fix: make modrinth icon larger
before it was considerably smaller than the other modpack platform icons which looked weird

Signed-off-by: DioEgizio <83089242+DioEgizio@users.noreply.github.com>
2022-12-05 20:27:29 +01:00
b29c99656e Merge pull request #546 from DioEgizio/add-server-icon
feat: add a proper server icon
2022-12-05 07:49:55 +01:00
45b0762096 Merge pull request #547 from flowln/fix_copying_instance
Fixes https://github.com/PrismLauncher/PrismLauncher/issues/545
2022-12-04 23:47:09 +01:00
aceafb28f6 feat: add server icon to simple colored icons too
Signed-off-by: DioEgizio <83089242+DioEgizio@users.noreply.github.com>
Co-Authored-By: leo78913 <leo3758@riseup.net>
2022-12-04 21:29:00 +01:00
928939cbe3 fix(Inst.Copy): create FS::copy object inside the secundary thread
Signed-off-by: flow <flowlnlnln@gmail.com>
2022-12-04 12:29:38 -03:00
2462b8e524 feat+fix: better flat icon
Signed-off-by: DioEgizio <83089242+DioEgizio@users.noreply.github.com>
2022-12-04 13:30:24 +01:00
263a72879d fix: oyxgen is lgpl3!
Signed-off-by: DioEgizio <83089242+DioEgizio@users.noreply.github.com>
2022-12-04 12:50:40 +01:00
70620d5137 feat: add a proper server icon
Signed-off-by: DioEgizio <83089242+DioEgizio@users.noreply.github.com>
2022-12-04 12:45:39 +01:00
79d5beff8d Merge pull request #541 from ryanccn/warn-before-trash-instance
Closes https://github.com/PrismLauncher/PrismLauncher/issues/192
closes https://github.com/PrismLauncher/PrismLauncher/issues/462
2022-12-03 15:20:49 +01:00
fa3caf091a fix: warn before trashing instances
Signed-off-by: Ryan Cao <70191398+ryanccn@users.noreply.github.com>
2022-12-03 21:54:41 +08:00
93707560cb Merge pull request #506 from Protrikk/develop 2022-12-02 22:04:33 +01:00
5c6f325071 Remove blue-ish tint from remaining flat white icons
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2022-12-02 20:47:11 +01:00
b9a17f5999 Merge branch 'upstream/develop' into develop
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2022-12-02 20:46:04 +01:00
ab23f542c6 Merge pull request #423 from TheKodeToad/addagent
Fixes https://github.com/PrismLauncher/PrismLauncher/issues/414
2022-12-02 06:40:18 -08:00
fa98bf1ee7 Merge pull request #481 from ryanccn/import-resource-pack-dialog-uwu 2022-12-02 06:39:54 -08:00
3cc987a5b4 fix: explicitly set scheme for local file in -I argument
Otherwise isLocalFile() will return false for local files without the
file:// thingy.

Signed-off-by: flow <flowlnlnln@gmail.com>
2022-12-01 22:54:03 -03:00
d1a1b8b6e8 Merge pull request #524 from DioEgizio/woa
add windows on arm builds
2022-12-01 23:09:37 +01:00
0d08e082be Merge pull request #538 from flowln/fix_some_cf_imports
A couple fixes for CF instance imports
2022-12-01 23:06:35 +01:00
386fb28a35 fix(FileResolvingTask): Fail instead of crash when there's API errors
Also remove non-used variable (rip).

Signed-off-by: flow <flowlnlnln@gmail.com>
2022-12-01 15:33:35 -03:00
79b79b752c fix(Inst.Import): Show error reason in fail dialog
Signed-off-by: flow <flowlnlnln@gmail.com>
2022-12-01 15:32:26 -03:00
a116778402 fix(Inst.Import): don't search inside 'overrides/' for the manifest
It will never be there anyways, and saves a **bunch** of time when the
overrides folder is big and we traverse all the tree when searching for
the MMC 'instance.cfg' file.

Signed-off-by: flow <flowlnlnln@gmail.com>
2022-12-01 15:15:15 -03:00
4c1c26a0e6 chore: drop Windows-MinGW-w64-Legacy
this brings back the number of builds as the same as before the pr

this is one of the slowest builds + windows 7/8.1 users can just use Windows-MSVC-Legacy

Signed-off-by: DioEgizio <83089242+DioEgizio@users.noreply.github.com>
2022-11-30 18:45:34 +01:00
9e1653ebb4 Merge pull request #436 from Scrumplex/feat-change-maxmem
Closes https://github.com/PrismLauncher/PrismLauncher/issues/426
2022-11-30 18:22:55 +01:00
99dd9874df refactor+fix: refactor the windows part of the release workflow and add arm to it
Signed-off-by: DioEgizio <83089242+DioEgizio@users.noreply.github.com>
2022-11-30 13:46:55 +01:00
24193163e1 Maybe fix ResourceFolderModel Clang64 test failure
Previously this test would fail sometimes without including ECMQueryQt

Signed-off-by: TheLastRar <TheLastRar@users.noreply.github.com>
2022-11-30 13:46:55 +01:00
94d164c0f2 Remove unused QT_DATA_DIR/QT_MKSPECS_DIR
Signed-off-by: TheLastRar <TheLastRar@users.noreply.github.com>
2022-11-30 13:46:55 +01:00
efef2e95ab Use ECMQueryQt Only with Qt5
Qt6 provides CMake variables for the paths we need

Signed-off-by: TheLastRar <TheLastRar@users.noreply.github.com>
2022-11-30 13:46:55 +01:00
5efa725e92 feat(actions) add arm64 build
Signed-off-by: DioEgizio <83089242+DioEgizio@users.noreply.github.com>
2022-11-30 13:46:55 +01:00
42c00213ce Merge pull request #238 from santiagocezar/new-icons 2022-11-29 14:30:29 -08:00
b7d1b9ac61 Merge pull request #527 from DioEgizio/revert-6.4.1-winmsvc 2022-11-29 14:27:29 -08:00
52d06ed814 chore: move instance_icons.svg
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2022-11-29 20:07:00 +01:00
46a1c855a9 Merge pull request #528 from Scrumplex/fix-resourcepages-runningstate 2022-11-29 19:50:00 +01:00
31dc82b1a6 Make requested changes
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2022-11-29 09:43:08 +00:00
4e27e132a0 fix: don't disable interaction on non-mod models when inst. is running
It is still useful for mods though, since we don't wnt to allow
disabling mods when the instance is running, as that wouldn't affect the
running instance, possibly causing confusion

Signed-off-by: flow <flowlnlnln@gmail.com>
2022-11-28 12:02:38 -03:00
a5b0b4800a fix: make resource buttons work when instance is running
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2022-11-27 23:10:32 +01:00
e6244c937a Merge branch 'develop' into new-icons
Signed-off-by: Santiago Cézar <48573316+santiagocezar@users.noreply.github.com>
2022-11-27 16:28:42 -03:00
3cbf8d4993 resolving reviews
Signed-off-by: Santiago Cézar <santiagocezar2013@gmail.com>
2022-11-27 16:24:45 -03:00
f3279a0697 Merge remote-tracking branch 'upstream/develop' into import-resource-pack-dialog-uwu 2022-11-27 20:05:21 +01:00
8cac61f0be fix: check resource pack validity solely using pack format
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2022-11-27 18:41:52 +01:00
236c196e68 fix: improve code readability
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2022-11-27 18:38:56 +01:00
6c09efd630 fix: use qt 6.4.0 on windows msvc for now
qt 6.4.1 has a very bad scaling regression

Signed-off-by: DioEgizio <83089242+DioEgizio@users.noreply.github.com>
2022-11-27 15:24:15 +01:00
cc92e1b0b6 Merge pull request #521 from Scrumplex/missing-icons 2022-11-26 19:02:03 +01:00
c90f2c3ac6 fix: use monochrome icon for breeze
Signed-off-by: DioEgizio <83089242+DioEgizio@users.noreply.github.com>
2022-11-26 15:05:08 +01:00
6bdd27a08e Merge pull request #493 from Scrumplex/cachix
Closes https://github.com/PrismLauncher/PrismLauncher/issues/491
2022-11-26 14:24:06 +01:00
80ff0b1418 Merge pull request #492 from Scrumplex/update-nix 2022-11-26 14:03:51 +01:00
a8943ce1ee remove unused ftb icon
Signed-off-by: Santiago Cézar <santiagocezar2013@gmail.com>
2022-11-25 15:15:08 -03:00
71d35dc70b meat is now round
Signed-off-by: Santiago Cézar <santiagocezar2013@gmail.com>
2022-11-25 15:15:08 -03:00
9daf2a2996 resize to 24x24
Signed-off-by: Santiago Cézar <santiagocezar2013@gmail.com>
2022-11-25 15:15:07 -03:00
f5d6aea942 forgot ftb
Signed-off-by: Santiago Cézar <santiagocezar2013@gmail.com>
2022-11-25 15:15:07 -03:00
5850447fd0 merge with upstream
Signed-off-by: Santiago Cézar <santiagocezar2013@gmail.com>
2022-11-25 15:14:52 -03:00
e12a7a4415 gradients!
Signed-off-by: Santiago Cézar <santiagocezar2013@gmail.com>
2022-11-25 14:22:49 -03:00
81d84b8d02 initial icons
Signed-off-by: Santiago Cézar <santiagocezar2013@gmail.com>
2022-11-25 14:22:49 -03:00
bae0a0530b fix(RPImportDialog): allow changing item size to accomodate wrapped text
Signed-off-by: flow <flowlnlnln@gmail.com>
2022-11-25 11:51:08 -03:00
cbf4159c7e fix: add missing shortcut icons
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2022-11-25 14:03:10 +01:00
4a1d082614 reafctor(WideBar): connect to signal instead of overriding menu method
This makes stuff more standard and closer to what we do in other places
in the codebase.

Signed-off-by: flow <flowlnlnln@gmail.com>
2022-11-25 09:33:05 -03:00
fd8b4c5368 Merge pull request #227 from Leo40Git/feature/instance-shortcuts
Closes https://github.com/PrismLauncher/PrismLauncher/issues/210
2022-11-25 13:11:00 +01:00
5872c34315 Merge pull request #412 from leo78913/legacy-icons
add the missing icons to the legacy icon theme
2022-11-25 08:36:42 +01:00
b60fe08d44 Merge pull request #514 from DioEgizio/force-bundled-libs-win 2022-11-23 15:11:45 -08:00
6a51eda361 fix: force bundled libs on win msvc
Signed-off-by: DioEgizio <83089242+DioEgizio@users.noreply.github.com>
2022-11-23 19:53:55 +01:00
96e8217b00 Button to add agent
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2022-11-23 09:46:55 +00:00
e6cb6cae11 Merge pull request #508 from TheLastRar/ForceBundledLibs 2022-11-23 09:49:24 +01:00
980f03dd20 Fix: Launcher_FORCE_BUNDLED_LIBS Failing to find bundled zlib
Signed-off-by: TheLastRar <TheLastRar@users.noreply.github.com>
2022-11-22 19:23:09 +00:00
20c281d6f8 fix: reset wide bar settings when the list of actions changes
This prevents changes to the actions to cause non-intuitive issues in
the Wide bar, hiding items that previously weren't hidden.

Signed-off-by: flow <flowlnlnln@gmail.com>
2022-11-22 14:30:54 -03:00
66f9fed2f2 Remove blue-ish tint from flat white icons
Signed-off-by: Trisave <42098407+Protrikk@users.noreply.github.com>
2022-11-22 18:30:21 +01:00
68b7aa0a4d Merge pull request #498 from Scrumplex/fix-copy-signal 2022-11-21 13:44:43 -08:00
f916ce8752 Merge branch 'develop' of https://github.com/PrismLauncher/PrismLauncher into import-resource-pack-dialog-uwu 2022-11-21 23:19:50 +08:00
fdbd8d9d2b refactor: remove old updater
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2022-11-21 16:18:05 +01:00
4208c2c72a fix: actually emit fileCopied
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2022-11-21 15:47:15 +01:00
5cc91965d0 Merge pull request #487 from TayouVR/breeze-icon-themes 2022-11-21 14:43:58 +01:00
c74f852364 Merge pull request #243 from Scrumplex/migration-dialog
Closes https://github.com/PrismLauncher/PrismLauncher/issues/46
Closes https://github.com/PrismLauncher/PrismLauncher/issues/204
2022-11-21 12:14:49 +01:00
c1b3a3adb4 fix(actions): don't ignore nix files
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2022-11-21 11:43:46 +01:00
7096f02b88 fix: text wrapping
Signed-off-by: Ryan Cao <70191398+ryanccn@users.noreply.github.com>
2022-11-21 18:15:03 +08:00
70a11935a8 feat(actions): add Nix build
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2022-11-21 00:22:25 +01:00
f601135cc0 refactor(nix): synchronize changes from nixpkgs
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2022-11-20 23:49:11 +01:00
884fe0d574 feat: validate maximum memory allocation in wizard
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2022-11-20 18:16:19 +01:00
ffcbf97dcc fix: add Breeze copyright notice to COPYING
Signed-off-by: DioEgizio <83089242+DioEgizio@users.noreply.github.com>
2022-11-20 17:48:44 +01:00
f55fc51e9b fix: remove commented-out assertions
They may not hold true at all times, and that's fine.

Signed-off-by: flow <flowlnlnln@gmail.com>
2022-11-20 11:11:08 -03:00
df0f9259c0 refactor: move RP/TP validation to their respective utils
This makes it easier to validate individual resources, and allows the
logic to be used in other places in the future, if we need to.

Signed-off-by: flow <flowlnlnln@gmail.com>
2022-11-20 11:10:26 -03:00
bb7a321c6e add breeze themes
Signed-off-by: Tayou <tayou@gmx.net>
2022-11-20 05:24:10 +01:00
2d69d63efe feat(InstancePages): save/load wide bar visibility settings
Signed-off-by: flow <flowlnlnln@gmail.com>
2022-11-19 18:41:31 -03:00
479843f56b feat(WideBar): allow loading/unloading visibility via a byte array
I really wanted to use a QBitArray :c

Signed-off-by: flow <flowlnlnln@gmail.com>
2022-11-19 18:41:31 -03:00
6e1639551b feat(WideBar): allow hiding buttons with right-click
Signed-off-by: flow <flowlnlnln@gmail.com>
2022-11-19 18:41:30 -03:00
2367903ac6 refactor: clean up WideBar a bit
Signed-off-by: flow <flowlnlnln@gmail.com>
2022-11-19 18:41:30 -03:00
30607c34a1 Merge pull request #291 from TheKodeToad/betterjavalauncher 2022-11-19 18:45:15 +01:00
817947c928 Merge pull request #483 from jopejoe1/patch-1 2022-11-19 18:44:09 +01:00
29926a59bb Merge pull request #482 from DioEgizio/fix-cache-flatpak 2022-11-19 18:10:03 +01:00
d92ae530d7 fix: stray include
Signed-off-by: Ryan Cao <70191398+ryanccn@users.noreply.github.com>
2022-11-20 00:34:44 +08:00
e0e428ce38 fix: add support for CLI and drag and drop
Signed-off-by: Ryan Cao <70191398+ryanccn@users.noreply.github.com>
2022-11-20 00:28:35 +08:00
d1db7a0e23 Fix New Zealand English display
Signed-off-by: jopejoe1 <34899572+jopejoe1@users.noreply.github.com>
2022-11-19 16:28:27 +00:00
c27ebde575 fix(actions): fix cache on flatpak
currently there's a [bug](https://github.com/flatpak/flatpak-github-actions/issues/80) on the stable version of the flatpak action which causes the cache key to be wrong. this commit work arounds it

Signed-off-by: DioEgizio <83089242+DioEgizio@users.noreply.github.com>
2022-11-19 17:14:19 +01:00
a99cd16422 fix: resource pack import dialog icons and add message
Signed-off-by: Ryan Cao <70191398+ryanccn@users.noreply.github.com>
2022-11-20 00:14:16 +08:00
1f6b8f9d2b fix instance IDs and resource pack imports
Signed-off-by: Ryan Cao <70191398+ryanccn@users.noreply.github.com>
2022-11-19 23:59:30 +08:00
a33b804923 fix: add resource pack format for 1.19.3
Co-authored-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
Signed-off-by: Ryan Cao <70191398+ryanccn@users.noreply.github.com>
2022-11-19 23:47:47 +08:00
f527958cb3 fix: check if packFormat is valid for resourcepack parsing
Signed-off-by: Ryan Cao <70191398+ryanccn@users.noreply.github.com>
2022-11-19 23:42:56 +08:00
b1bdc6f745 fix resource packs and add support for texture packs
Signed-off-by: Ryan Cao <70191398+ryanccn@users.noreply.github.com>
2022-11-19 23:38:05 +08:00
8dacbafc8b feat: initial support for smart resource pack parsing on file handler
Signed-off-by: Ryan Cao <70191398+ryanccn@users.noreply.github.com>
2022-11-19 23:14:57 +08:00
70fa92f22c Remove dirty printStackTrace hacks
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2022-11-19 13:59:22 +00:00
3482076a20 Merge pull request #476 from Scrumplex/matrix 2022-11-19 05:07:33 -08:00
f7239f7f8a chore: update community links
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2022-11-19 13:34:02 +01:00
20ba787c00 Merge pull request #474 from Scrumplex/translations-maybe2 2022-11-19 03:41:54 -08:00
669eef92eb Make requested changes and utilise AssertionError
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2022-11-19 08:54:17 +00:00
c6d9edb78f chore: improve display names of more languages
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2022-11-18 22:21:55 +01:00
347ae0a9ad Merge pull request #456 from DioEgizio/flatpak-build
closes https://github.com/PrismLauncher/PrismLauncher/issues/62
2022-11-18 21:37:14 +01:00
dbd01d35e6 Merge pull request #455 from leo78913/menubar-stuff 2022-11-18 17:20:50 +01:00
b24c09665f Merge pull request #439 from Ryex/better-blocked-mods 2022-11-17 11:29:28 -08:00
fa96ebd382 Merge pull request #471 from IDeletedSystem64/develop 2022-11-17 20:28:42 +01:00
52d43f843b feat(BlockModsDialog): remove redundant Ui info
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2022-11-17 11:46:14 -07:00
90376749f0 Fix AUR qt5-git and git having the wrong AUR links
Signed-off-by: Sophie Marie <twilightsparkle@duck.com>
2022-11-17 12:42:34 -06:00
5cf2a8b5fc Merge pull request #454 from RedsonBr140/menu-themes 2022-11-17 09:47:55 -08:00
f72ac94c11 fix: Fix usage below
Signed-off-by: Redson <redson@riseup.net>
2022-11-17 06:39:05 -03:00
bd3a693e70 chore: Change var name
Co-authored-by: Sefa Eyeoglu <contact@scrumplex.net>
Signed-off-by: RedsonBr140 <redson@riseup.net>
2022-11-17 06:20:53 -03:00
298871e207 Merge pull request #467 from Scrumplex/fix-meta-extensions-json
Fix serialization of components with custom metadata
2022-11-16 23:54:26 +01:00
ce958f4ffd refactor: use isEmpty instead of size for lists
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2022-11-16 23:20:47 +01:00
2de150bfc8 Merge pull request #431 from FayneAldan/version 2022-11-16 18:20:32 +01:00
40970a1a87 fix: serialize metadata extensions
Prism has introduced a few extensions to the meta component version
format, which were not exported as JSON in the launcher. This caused the
`Customize` button on the version page to not write these new properties
to the custom component file.

Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2022-11-16 18:11:18 +01:00
8aae652be1 fix: remove unnecessary condition
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2022-11-16 18:10:54 +01:00
37a117d2ef chore: Var definition inside the for loop
Co-authored-by: flow <flowlnlnln@gmail.com>
Signed-off-by: RedsonBr140 <redson@riseup.net>
2022-11-16 12:24:28 -03:00
debc1659e1 Merge pull request #464 from DioEgizio/qt-6.4.1 2022-11-16 15:23:52 +05:30
23e411c42b Merge pull request #459 from Scrumplex/bump-tomlplusplus 2022-11-16 01:34:15 -08:00
88feebe499 chore: use qt 6.4.1 on Windows-MSVC
Signed-off-by: DioEgizio <83089242+DioEgizio@users.noreply.github.com>
2022-11-16 09:55:46 +01:00
e8b871ac72 Merge branch 'PrismLauncher:develop' into version 2022-11-15 18:34:24 -07:00
9f30c6d94b Add commit hash to --version
Signed-off-by: Fayne Aldan <FayneAldan@gmail.com>
2022-11-15 18:33:51 -07:00
c4c1e75de8 fix: use QPixmapCache only from the main thread
It's a required condition.

Signed-off-by: flow <flowlnlnln@gmail.com>
2022-11-15 18:14:03 -03:00
c1763cc4b0 fix: disable FLOAT16 in toml++
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2022-11-15 21:23:20 +01:00
ee096edfff chore: bump tomlplusplus
Should fix issues with builds on aarch64

Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2022-11-15 20:58:07 +01:00
464b9ebc95 feat: add flatpak builds to the ci for testing
Signed-off-by: DioEgizio <83089242+DioEgizio@users.noreply.github.com>
2022-11-15 17:45:12 +01:00
7705f290ca fix: don't retry to load RP images that can't fit in the cache
Avoids an infinite loop when the image is too big.

Signed-off-by: flow <flowlnlnln@gmail.com>
2022-11-15 12:07:11 -03:00
7439fd6bcb fix: Fix some stuff in the menu bar
- Remove duplicated launch actions
 - Enable the add instance action icon in menus
 - Remove ugly separator at the end of the help menu if the updater is disabled
 - Add icons to the help and news menu items

Signed-off-by: leo78913 <leo3758@riseup.net>
2022-11-15 10:56:41 -03:00
6fe626ab9a feat: Make the changes persistent.
Signed-off-by: Redson <redson@riseup.net>
2022-11-15 06:09:13 -03:00
a12f892841 fix: Check the box when the theme is changed via settings
Signed-off-by: Redson <redson@riseup.net>
2022-11-15 05:46:24 -03:00
aa3ea79f94 fix: Check the current theme box on startup.
Signed-off-by: Redson <redson@riseup.net>
2022-11-15 05:38:31 -03:00
ef53455b66 fix: Build on QT6
Signed-off-by: Redson <redson@riseup.net>
2022-11-15 05:19:46 -03:00
ba46ff6692 Merge remote-tracking branch 'upstream/develop' into feature/instance-shortcuts 2022-11-15 10:05:04 +02:00
0e916244f0 feat: Add themes and their logic.
Signed-off-by: leo78913 <leo3758@riseup.net>
2022-11-14 21:10:48 -03:00
1e4ee02cbc Merge branch 'PrismLauncher:develop' into menu-themes 2022-11-14 21:09:37 -03:00
cedc7754d9 Merge pull request #428 from DioEgizio/fixes-to-CI 2022-11-14 14:16:01 -08:00
fece9e207b Merge pull request #448 from TheLastRar/fixup-warnings 2022-11-14 14:15:46 -08:00
cca052ccc9 Restore QRC headers
Signed-off-by: ADudeCalledLeo <7997354+Leo40Git@users.noreply.github.com>
2022-11-14 22:46:41 +02:00
5be9472912 fix: fix potentially uninitialized variable
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2022-11-14 21:20:38 +01:00
f60b09568c Merge pull request #112 from ryanccn/macos-add-to-path 2022-11-14 21:12:36 +01:00
be765f8d88 feat: Add empty menu
Signed-off-by: Redson <redson@riseup.net>
2022-11-14 16:33:25 -03:00
8d6aecd944 add the missing icons to the legacy icon theme
Signed-off-by: leo78913 <leo3758@riseup.net>
2022-11-14 16:16:52 -03:00
aef5349aee Pass index.parent() as parent parameter for rowCount
Signed-off-by: TheLastRar <TheLastRar@users.noreply.github.com>
2022-11-14 19:05:57 +00:00
ac993aa31f Use Q_UNUSED instead of [[maybe_unused]] in onParseFailed
Qt5 on Ubuntu cannot handle [[maybe_unused]] in this function

Signed-off-by: TheLastRar <TheLastRar@users.noreply.github.com>
2022-11-14 19:05:57 +00:00
fce323b945 Check parent in rowCount/columnCount/canFetchMore
Signed-off-by: TheLastRar <TheLastRar@users.noreply.github.com>
2022-11-14 19:05:57 +00:00
5558f3d2cc Mark paramaters of dropMimeData as unused
Signed-off-by: TheLastRar <TheLastRar@users.noreply.github.com>
2022-11-14 19:05:57 +00:00
08f8623cb7 Mark paramaters of onParseFailed as unused
Signed-off-by: TheLastRar <TheLastRar@users.noreply.github.com>
2022-11-14 19:05:56 +00:00
f8a137a26e Mark loadExtraPackInfo abstract
All classes that inherit from ModModel override this method

Signed-off-by: TheLastRar <TheLastRar@users.noreply.github.com>
2022-11-14 19:05:56 +00:00
3cba359d38 Mark paramater runtimeContext as unused
Base class uses variable, but ImplicitRule does not

Signed-off-by: TheLastRar <TheLastRar@users.noreply.github.com>
2022-11-14 19:05:56 +00:00
b8d7aedb2c Mark paramater line as unused in guessLevel()
The base method doesn't use this variable, but classes overriding this method do

Signed-off-by: TheLastRar <TheLastRar@users.noreply.github.com>
2022-11-14 19:05:56 +00:00
55c7b291e1 Remove unused qhash function
Signed-off-by: TheLastRar <TheLastRar@users.noreply.github.com>
2022-11-14 19:05:56 +00:00
472d931b4b Prefix member variables in HttpMetaCache
MSVC warns about shadowing variables

Signed-off-by: TheLastRar <TheLastRar@users.noreply.github.com>
2022-11-14 19:05:56 +00:00
ce892c9e77 Add icon
NOTE: Currently missing on Legacy, Flat and Flat (White)
Signed-off-by: ADudeCalledLeo <7997354+Leo40Git@users.noreply.github.com>
2022-11-14 21:02:31 +02:00
e14b998da3 refactor: improve readability
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2022-11-14 18:38:12 +01:00
2c9452efaf Merge branch 'develop' into macos-add-to-path 2022-11-14 19:26:31 +08:00
97a7af855f slight reword: "install to PATH"
Signed-off-by: Ryan Cao <70191398+ryanccn@users.noreply.github.com>
2022-11-14 19:21:47 +08:00
5be8545edc Windows, Linux: prevent segfault on missing icon
Signed-off-by: ADudeCalledLeo <7997354+Leo40Git@users.noreply.github.com>
2022-11-13 20:18:51 +02:00
0a04c3a2a7 fix: Fix the error that CodeQL caught
Signed-off-by: txtsd <code@ihavea.quest>
2022-11-13 18:54:55 +01:00
dcfc15a0a1 feat+fix: move codeql to its own workflow
i think it's better practice, it should slightly improve linux qt6 build times and i noticed ccache? is messing up with it because alerts get randomly fixed

Signed-off-by: DioEgizio <83089242+DioEgizio@users.noreply.github.com>
2022-11-13 18:54:55 +01:00
841c2e9166 fix: disable caching Qt on release
it's good practice to not cache on release builds

Signed-off-by: DioEgizio <83089242+DioEgizio@users.noreply.github.com>
2022-11-13 18:54:55 +01:00
07392d493c fix: disable building snaps on release
the snap infra should already be able to deal with it, i think

Signed-off-by: DioEgizio <83089242+DioEgizio@users.noreply.github.com>
2022-11-13 18:54:55 +01:00
acd50969e0 Linux: remove TryExec entry from .desktop files
Signed-off-by: ADudeCalledLeo <7997354+Leo40Git@users.noreply.github.com>
2022-11-13 19:50:27 +02:00
074b53eb6b Merge pull request #445 from flowln/optimize_edit_instance 2022-11-13 17:18:06 +01:00
c4cfec1e94 Undo accidental tomlplusplus downgrade
Signed-off-by: ADudeCalledLeo <7997354+Leo40Git@users.noreply.github.com>
2022-11-13 18:00:18 +02:00
b0269e6dfc Linux: fixes
- Fix shortcut icons
- Possibly fix shortcut creation on AppImages
- Fix shortcut not working if path to launcher contains spaces

Signed-off-by: ADudeCalledLeo <7997354+Leo40Git@users.noreply.github.com>
2022-11-13 17:51:29 +02:00
43b9d9484d tabs -> spaces
Signed-off-by: ADudeCalledLeo <7997354+Leo40Git@users.noreply.github.com>
2022-11-13 15:49:28 +02:00
69bbb29328 Mac: attempt 2
- create .command files instead of .sh
- fix shortcuts not working if path to Prism Launcher contains spaces
- fix path to executable in shortcutss
- add check for running from extracted folder (prevents creating shortcuts)

Signed-off-by: ADudeCalledLeo <7997354+Leo40Git@users.noreply.github.com>
2022-11-13 15:47:37 +02:00
577069cfb4 fix: don't have the clear button on instance page filters
This thing is otherworldly unoptimized. o.O

Signed-off-by: flow <flowlnlnln@gmail.com>
2022-11-12 19:23:57 -03:00
fe94c3609e fix: implement code review suggestions
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2022-11-12 20:28:30 +01:00
173aed7fd8 chore: add REUSE headers
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2022-11-12 20:28:30 +01:00
335bec68fb fix: prevent abort for un-abortable tasks
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2022-11-12 20:28:30 +01:00
bbb7e9f5c7 feat: show current copy operation in migration dialog
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2022-11-12 20:28:30 +01:00
086304f7f2 feat: add initial Migration dialog
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2022-11-12 20:28:30 +01:00
bd7065eece feat: add SimplePrefixMatcher
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2022-11-12 20:28:30 +01:00
15aaff7c1c feat: add dryRun to copy operation
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2022-11-12 20:28:29 +01:00
e048bce13e refactor: allow copy operation with whitelist
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2022-11-12 20:27:13 +01:00
ddfb449b28 fix: remove PolyMC data paths
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2022-11-12 20:27:13 +01:00
5322155b19 Mac: fix build
Signed-off-by: ADudeCalledLeo <7997354+Leo40Git@users.noreply.github.com>
2022-11-12 20:48:21 +02:00
45ce72593a Windows: remove icon if shortcut creation fails
Signed-off-by: ADudeCalledLeo <7997354+Leo40Git@users.noreply.github.com>
2022-11-12 20:43:58 +02:00
b813c867b5 refactor #if checks
Signed-off-by: ADudeCalledLeo <7997354+Leo40Git@users.noreply.github.com>
2022-11-12 20:41:52 +02:00
f7d7d76ee8 Mac: now supported! [UNTESTED]
Signed-off-by: ADudeCalledLeo <7997354+Leo40Git@users.noreply.github.com>
2022-11-12 20:36:49 +02:00
7e5076b068 Linux: fix path shortcut is written to
Co-authored-by: flow <flowlnlnln@gmail.com>
Signed-off-by: ADudeCalledLeo <7997354+Leo40Git@users.noreply.github.com>
2022-11-12 20:19:32 +02:00
dbe0553b4a Move addAction call above left-align loop
Signed-off-by: ADudeCalledLeo <7997354+Leo40Git@users.noreply.github.com>
2022-11-12 20:19:31 +02:00
9be48f1dc4 this ain't static, falco
Signed-off-by: ADudeCalledLeo <7997354+Leo40Git@users.noreply.github.com>
2022-11-12 20:19:31 +02:00
6043444e4e Apply suggestions from code review
Co-authored-by: Sefa Eyeoglu <contact@scrumplex.net>
Signed-off-by: ADudeCalledLeo <7997354+Leo40Git@users.noreply.github.com>
2022-11-12 20:19:30 +02:00
487e352642 Fix nested #if directive
Signed-off-by: ADudeCalledLeo <7997354+Leo40Git@users.noreply.github.com>
2022-11-12 20:19:29 +02:00
cc5f82bfac Windows: fix window icon being replaced
Dunno why it happens but the fix was literally 2 lines, so whatever I guess

Signed-off-by: ADudeCalledLeo <7997354+Leo40Git@users.noreply.github.com>
2022-11-12 20:19:28 +02:00
4d4dfab388 Windows: add instance icon to shortcut
Signed-off-by: ADudeCalledLeo <7997354+Leo40Git@users.noreply.github.com>
2022-11-12 20:19:28 +02:00
b83f9be1bd Add missing fail check for CoInitialize
Add a few comments

Signed-off-by: ADudeCalledLeo <7997354+Leo40Git@users.noreply.github.com>
2022-11-12 20:19:27 +02:00
6ae3b183fd Remove unnessecary "is defined" check
Signed-off-by: ADudeCalledLeo <7997354+Leo40Git@users.noreply.github.com>
2022-11-12 20:19:27 +02:00
f12117c532 [UNTESTED] Linux: add icons to shortcuts
Signed-off-by: ADudeCalledLeo <7997354+Leo40Git@users.noreply.github.com>
2022-11-12 20:19:26 +02:00
70768189ba Windows: implement FS::createShortcut
Signed-off-by: ADudeCalledLeo <7997354+Leo40Git@users.noreply.github.com>
2022-11-12 20:19:25 +02:00
30b266622c Add 'Create shortcut' button to instance toolbar
Implemented on Windows only rn!

Signed-off-by: ADudeCalledLeo <7997354+Leo40Git@users.noreply.github.com>
2022-11-12 20:18:49 +02:00
25b306b7e1 feat: mark folder paths as links
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2022-11-11 18:32:11 -07:00
9af1b00df5 feat: add list of watched folders
move explanation text into dialog class and it's own label

Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2022-11-11 18:05:19 -07:00
51c27e2748 always use the pending path set to avoid task duplication.
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2022-11-11 16:33:52 -07:00
b9e2c3524c chore: clang format & cleanup
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2022-11-11 16:07:57 -07:00
3f6cc17818 properly handle a currently running hashing task
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2022-11-11 15:45:40 -07:00
5909af9878 drag&drop + add folder to watch
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2022-11-11 14:17:33 -07:00
64576f4c4c Merge pull request #304 from Ryex/move-downloads
Fixes https://github.com/PrismLauncher/PrismLauncher/issues/222
2022-11-11 12:48:53 -08:00
21dbd28a2f Merge pull request #266 from Ryex/windows-file-association 2022-11-11 15:46:03 +01:00
b57fee1a44 fix: swap spin box and state icon
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2022-11-11 15:24:14 +01:00
cabd887866 feat: use icons to show memory allocation state
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2022-11-11 15:22:16 +01:00
863a168cb5 feat: raise memory limits to 1TiB
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2022-11-11 15:05:00 +01:00
5ee4fb3522 feat: validate maximum memory allocation
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2022-11-11 15:04:05 +01:00
bb8ac9b99a changed name of file type association
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2022-11-11 05:46:41 -07:00
2f10fa8b61 add some extra debug logs for CF blocked mods
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2022-11-11 05:41:32 -07:00
46a8e18841 Merge pull request #367 from TheKodeToad/linkjumping
fix https://github.com/PrismLauncher/PrismLauncher/issues/363
2022-11-10 08:08:44 -08:00
6c53e68a52 Merge pull request #406 from Scrumplex/fix-clear-metadata 2022-11-10 07:50:14 -08:00
392452d422 Merge pull request #397 from flowln/windows_mod_updater_fixes_maybe
Fixes https://github.com/PrismLauncher/PrismLauncher/issues/226
2022-11-10 14:34:15 +01:00
99ed0b6c2c Implement flowln's suggestions
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2022-11-10 11:14:58 +00:00
e6d057fe6d Merge pull request #415 from TayouVR/fix-main-warning 2022-11-09 18:27:40 +01:00
9ad6eb11a3 refactor: fix CodeQL warnings in StringUtils::naturalCompare
I have no idea why this function exists, so better to just let it exist.
=D

Signed-off-by: flow <flowlnlnln@gmail.com>
2022-11-09 14:14:25 -03:00
32c2ad2bbd A lot more cleanup
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2022-11-08 17:51:18 +00:00
f2ca9a6b31 Revert switch to JUL for better colours
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2022-11-08 17:38:23 +00:00
50d40257fe Always use this for consistency
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2022-11-08 17:38:23 +00:00
d90eff64d0 Add StringUtils to CMakeLists.txt
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2022-11-08 16:37:27 +00:00
e6dc34fe10 More license fixing
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2022-11-08 16:37:27 +00:00
745c331311 Remove last case of printStackTrace
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2022-11-08 16:37:27 +00:00
1ea2e85415 Implicit is generally prefered
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2022-11-08 16:37:27 +00:00
4a2df30f92 Try to use more standard exit codes
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2022-11-08 16:37:27 +00:00
922220c11e More consistent logging text
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2022-11-08 16:37:27 +00:00
56d5035c63 Fix the warnings properly
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2022-11-08 16:37:27 +00:00
4abf3a20c6 More standard code formatting profile
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2022-11-08 16:37:25 +00:00
5912ef3b45 Just ignore empty lines
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2022-11-08 16:37:00 +00:00
9931c9a286 Remove arguments being passed twice
Passing the classpath into stdin has no effect. Java is already provided the classpath with -cp, which pretty much takes up the largest part of the arguments anyway, which leads me to wonder, what's the point of stdin arguments at all?

Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2022-11-08 16:37:00 +00:00
1da834f650 *opinionated change* Remove LauncherFactory
Factories in OOP are a classic example of over-enginneering. When you only have two launchers I personally think that it's not very useful.

Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2022-11-08 16:37:00 +00:00
fb677a7489 So turns out we can have nice things
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2022-11-08 16:36:55 +00:00
404796d4b2 Sorry for reverting a lot but copying a list just hurts me
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2022-11-08 16:36:35 +00:00
5b9bfe8891 Attempt to mimic clang-format
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2022-11-08 16:36:33 +00:00
779bc2c63d Fix WrongMethodTypeException. Invoke exact don't work like that
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2022-11-08 16:35:46 +00:00
cae1ba7cd8 Less needless verbosity, and return fallback
Needlessly verbose commit message ik.

Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2022-11-08 16:35:46 +00:00
8ce78dcc54 Try to improve consistency
- Makes code formatting more consistent with the C++ codebase. Probably removes some trailing whitespace. Maybe it would be best to commit an Eclipse or IntelliJ code format preferences file?
- Removes obscure suppressions. I personally think it's better to only suppress warnings that javac complains about. Suppressing a lot of non-standardised warnings (many of them turned off by default even in IntelliJ) just creates needless clutter.
- Fixes some trivial warnings instead of suppressing them. serialVersionUID is sort of stupid, but I'd rather mentally ignore it or just fix it if it's really that annoying.

Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2022-11-08 16:35:43 +00:00
afe088dba1 Fix license headers
- Update license headers in several files to remove multimc apache reference, when unneeded
  - LauncherFactory: we've entirely rewritten this class at this point, so it's fully under GPL code
  - Launcher: this interface contains zero logic, and only a single method named `launch`, so I doubt you can actually copyright that
  - LauncherProvider: same as above
  - ParseException, ParameterNotFoundException: same as above; this class contains almost no logic (And the logic that was added is under GPL)
  - ReflectionUtils, StringUtils: add license header
  - Everything else: modify the program name in the license header from "PolyMC - Minecraft Launcher" to "Prism Launcher"

Signed-off-by: solonovamax <solonovamax@12oclockpoint.com>
2022-11-08 16:25:09 +00:00
e899e31745 More informative exceptions in entrypoint
Signed-off-by: solonovamax <solonovamax@12oclockpoint.com>
2022-11-08 16:25:09 +00:00
dabb84f62a Cleanup launcher classes
Cleanup a bunch of the code in launcher classes
- Migrate the majority of the reflection to ReflectionUtils
- Decrease logic in AbstractLauncher
- Add logging to launcher classes at FINE level
- make mcParams in AbstractLauncher an immutable list to prevent runtime manipulation
  - StandardLauncher instead copies the list to modify it

Signed-off-by: solonovamax <solonovamax@12oclockpoint.com>
2022-11-08 16:25:09 +00:00
9b8096c699 Get rid of gross HashMap being used by LauncherFactory and instead use *fancy* enum
Signed-off-by: solonovamax <solonovamax@12oclockpoint.com>
2022-11-08 16:25:09 +00:00
ac5b74301e Cleanup splitting string into a pair
Signed-off-by: solonovamax <solonovamax@12oclockpoint.com>
2022-11-08 16:25:09 +00:00
609b30110b Make main static
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>

Inline local variable

Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2022-11-08 16:25:09 +00:00
35d200356f Create launcher.impl.legacy
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2022-11-08 16:25:09 +00:00
0cd1d7aa7e Excessive safety
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2022-11-08 16:25:09 +00:00
ade7526f5f Remove the need for LegacyUtils
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2022-11-08 16:25:09 +00:00
a7b1700d42 Better variable naming
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2022-11-08 16:25:09 +00:00
c0b8c53e69 Attempt to sort out copyright headers
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2022-11-08 16:25:09 +00:00
e86fbc697f Fix formatting
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2022-11-08 16:25:09 +00:00
e5622ce824 Code cleanup to net.minecraft.Launcher
No code logic has been changed, only:
- add @Override annotatons
- change setVisible(boolean b) -> setVisible(boolean visible)
- Change block commend on class -> javadoc comment

Signed-off-by: solonovamax <solonovamax@12oclockpoint.com>
2022-11-08 16:25:09 +00:00
99d9868116 Cleanup EntryPoint code
- Don't return an int from listen(). An enum is preferred.
- Make parseLine() static, and pass Parameters to it.

Signed-off-by: solonovamax <solonovamax@12oclockpoint.com>
2022-11-08 16:25:09 +00:00
107fa6b4f7 Code refactors
- Refactor LauncherFactory.LauncherProvider to LauncherFactory
- Refactor all launcher related components to launcher package
- some basic code cleanup
- Rename all, allSafe -> getList and first, firstSafe -> getString
- Rename Utils -> LegacyUtils

Signed-off-by: solonovamax <solonovamax@12oclockpoint.com>
2022-11-08 16:25:09 +00:00
9062d28704 Get rid of singleton, and refactor LauncherFactory to be a static class
Signed-off-by: solonovamax <solonovamax@12oclockpoint.com>
2022-11-08 16:25:09 +00:00
e68dcea6bc Various tweaks to the Java component of the launcher
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2022-11-08 16:24:55 +00:00
787c5a515f Merge pull request #407 from AshtakaOOf/readme 2022-11-08 17:25:19 +05:30
ce2df4b36f chore(readme): Specify openSUSE Tumbleweed
Signed-off-by: txtsd <code@ihavea.quest>
2022-11-08 17:24:00 +05:30
fcb9733df0 Merge pull request #392 from PrismLauncher/max_ram_logic 2022-11-08 12:23:24 +05:30
245928a064 Update README.md
Signed-off-by: Adrien <66513643+AshtakaOOf@users.noreply.github.com>
2022-11-07 20:33:09 +01:00
589d160515 fix: use cross-platform toStdString in FlameHasher
Almost the same issue from toml++ :p

Signed-off-by: flow <flowlnlnln@gmail.com>
2022-11-07 14:04:48 -03:00
380e76a2e3 Add Tumbleweed
Signed-off-by: Adrien <66513643+AshtakaOOf@users.noreply.github.com>
2022-11-07 17:14:16 +01:00
9ac6114b63 Fix warning in main function
main could according to the compiler end up not returning. of course it will always return, but I satisfied the compiler by adding a default case.

Signed-off-by: Tayou <tayou@gmx.net>
2022-11-07 14:33:37 +01:00
d558ff305a Merge pull request #411 from TheLastRar/configurationless-install
Fix: Configuration-less config for Qt Install
2022-11-07 13:30:39 +01:00
89aaac3a70 Update README.md
Signed-off-by: Adrien <66513643+AshtakaOOf@users.noreply.github.com>
2022-11-06 21:56:02 +01:00
456999eee6 Fix: Configuration-less config for Qt Install
Signed-off-by: TheLastRar <TheLastRar@users.noreply.github.com>
2022-11-06 14:25:38 +00:00
16e3b786fc Implement Scrumplex's suggestions
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2022-11-06 10:09:06 +00:00
126bbd67f7 Merge pull request #405 from AshtakaOOf/spooky 2022-11-06 07:27:39 +01:00
38e1d44dbb Update README.md
Add copr

Signed-off-by: Adrien <66513643+AshtakaOOf@users.noreply.github.com>
2022-11-06 03:42:51 +01:00
9fb80a2687 Merge pull request #242 from marcelohdez/more-copy-options 2022-11-06 01:10:24 +01:00
d5d224d89a fix: save metacache after clearing
If the user closes the launcher right after clearing, it probably
didn't actually clear the cache yet.

Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2022-11-06 01:05:13 +01:00
4708ce4226 refactor: rename halloween cats to -spooky
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2022-11-06 00:47:33 +01:00
a0580946dc fix: allow -ween variants for all cats
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2022-11-06 00:04:43 +01:00
e68fd7c1e3 Merge pull request #383 from leo78913/toolbar-lock 2022-11-06 00:00:47 +01:00
369419870e add: Spooky Rory
Signed-off-by: Adrien <66513643+AshtakaOOf@users.noreply.github.com>
2022-11-05 23:55:43 +01:00
0938f80b41 Update launcher/ui/MainWindow.cpp
Co-authored-by: flow <flowlnlnln@gmail.com>
Signed-off-by: leo78913 <leo3758@riseup.net>
2022-11-05 18:10:36 -03:00
9f462dcc27 fix: update tomlplusplus submodule
This fixes an issue with Windows TOML file parsing with non-latin
characters.

Signed-off-by: flow <flowlnlnln@gmail.com>
2022-11-05 16:28:54 -03:00
96008d3bb2 add -I import flag & don't clobber .zip assoc
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2022-11-05 08:07:58 -07:00
c05f744ec2 windows file association is *hard*
new macros!

Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2022-11-05 08:07:58 -07:00
3df31579a1 fix: @timoreo22
Signed-off-by: Ryan Cao <70191398+ryanccn@users.noreply.github.com>
2022-11-05 22:31:38 +08:00
f1d3481a29 fix: remove dumb FS::symlink function
Signed-off-by: Ryan Cao <70191398+ryanccn@users.noreply.github.com>
2022-11-05 22:25:22 +08:00
cf3aad9c41 fix: use osascript to get admin privileges
inspired from VSCode's approach

Signed-off-by: Ryan Cao <70191398+ryanccn@users.noreply.github.com>
2022-11-05 22:18:05 +08:00
7b1e68bfa8 initial support for add to PATH action
Signed-off-by: Ryan Cao <70191398+ryanccn@users.noreply.github.com>
2022-11-05 22:17:59 +08:00
82256a2fe8 Merge pull request #400 from DioEgizio/bump-6.0 2022-11-05 14:35:21 +01:00
016b3448e8 chore: bump to 6.0
Signed-off-by: DioEgizio <83089242+DioEgizio@users.noreply.github.com>
2022-11-05 13:34:02 +01:00
2dde26e485 Merge pull request #399 from ryanccn/readme-adaptive-logo-fix 2022-11-05 13:07:53 +01:00
2999afe781 fix: width="50%"
Signed-off-by: Ryan Cao <70191398+ryanccn@users.noreply.github.com>
2022-11-05 19:20:08 +08:00
bfc5a6488b fix(docs): use new format for adaptive images in README
Signed-off-by: Ryan Cao <70191398+ryanccn@users.noreply.github.com>
2022-11-05 19:16:56 +08:00
4af22d663a Merge pull request #229 from ryanccn/macos-drag-n-drop 2022-11-05 11:17:21 +01:00
ba8322aa5c Merge pull request #396 from leozamboni/develop 2022-11-05 11:17:13 +01:00
e4bd82190a Merge pull request #149 from TayouVR/better-custom-themes 2022-11-05 11:16:41 +01:00
695734636f Merge pull request #294 from piperswe/add-snapcraft-yml 2022-11-05 11:09:51 +01:00
bdac2a5f4d fix: add missing newline
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2022-11-05 11:09:35 +01:00
f8ea6212c7 fix: fix icon install path
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2022-11-05 10:42:44 +01:00
5e9b26dbef Merge pull request #366 from TheLastRar/MSVC-Build 2022-11-04 23:49:54 +01:00
67c99369ab fix: use KDEInstallDirs for manpage
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2022-11-04 23:43:18 +01:00
d35c2db41e fix: separate types of std::string in Packwiz
Signed-off-by: flow <flowlnlnln@gmail.com>
2022-11-04 16:53:25 -03:00
dff5fea976 feat: add more separation between types of std::string in StringUtils
Signed-off-by: flow <flowlnlnln@gmail.com>
2022-11-04 16:53:25 -03:00
ab6c7244fc refactor: move FS's toStdString to StringUtils
This is so that anyone can use it :)

Signed-off-by: flow <flowlnlnln@gmail.com>
2022-11-04 16:53:25 -03:00
353b51f11e refactor: move MMCStrings -> StringUtils
General utilities can go in here >:)

Signed-off-by: flow <flowlnlnln@gmail.com>
2022-11-04 16:53:24 -03:00
76050880f1 fix: use unicode variant for marking '.index' hidden
Signed-off-by: flow <flowlnlnln@gmail.com>
2022-11-04 16:53:21 -03:00
396a7994f9 Workflow: Add MSVC Builds to release workflow
Signed-off-by: TheLastRar <TheLastRar@users.noreply.github.com>
2022-11-04 18:11:39 +00:00
e29259cd55 Fix: Resolve ambiguous overload errors
Clang-cl fails to select the correct function and instead errors

Signed-off-by: TheLastRar <TheLastRar@users.noreply.github.com>
2022-11-04 18:11:39 +00:00
79a728d7d2 Fix: Conflicting types for hoedown functions
Signed-off-by: TheLastRar <TheLastRar@users.noreply.github.com>
2022-11-04 18:11:39 +00:00
98444bd865 CI: Add VC variables before packaging on Windows
Signed-off-by: TheLastRar <TheLastRar@users.noreply.github.com>
2022-11-04 18:11:39 +00:00
3f75e1cb1d CI: Build MSVC Legacy as 32bit
Signed-off-by: TheLastRar <TheLastRar@users.noreply.github.com>
2022-11-04 18:11:39 +00:00
4f327120ac CI: Link to release libraries even in debug
Signed-off-by: TheLastRar <TheLastRar@users.noreply.github.com>
2022-11-04 18:11:39 +00:00
cc8456ec6b CI: Use msbuild generator for msvc builds
Signed-off-by: TheLastRar <TheLastRar@users.noreply.github.com>
2022-11-04 18:11:38 +00:00
f8ad1a052f CMake: Support multi-configuration generators
Signed-off-by: TheLastRar <TheLastRar@users.noreply.github.com>
2022-11-04 18:11:38 +00:00
372ce588cd CI: Add MSVC Builds
Signed-off-by: TheLastRar <TheLastRar@users.noreply.github.com>
2022-11-04 18:11:38 +00:00
12632ec404 CMake: Build flags for MSVC
Signed-off-by: TheLastRar <TheLastRar@users.noreply.github.com>
2022-11-04 18:11:37 +00:00
e777c26a14 CMake: Add fallback to bundled ECM
Signed-off-by: TheLastRar <TheLastRar@users.noreply.github.com>
2022-11-04 18:11:37 +00:00
1d38248194 Libraries: Add ECM
Signed-off-by: TheLastRar <TheLastRar@users.noreply.github.com>
2022-11-04 18:11:36 +00:00
d52868c6c5 CI: Exclude zlib tests
Signed-off-by: TheLastRar <TheLastRar@users.noreply.github.com>
2022-11-04 18:11:36 +00:00
29c1639b1d CMake: Force bundled zlib to take our IPO settings
Signed-off-by: TheLastRar <TheLastRar@users.noreply.github.com>
2022-11-04 18:11:36 +00:00
653a953d2f CMake: Add zlib
Signed-off-by: TheLastRar <TheLastRar@users.noreply.github.com>
2022-11-04 18:11:35 +00:00
9f5537d936 feat: spooky cat for halloween
Signed-off-by: leozamboni <leonardonunes169@gmail.com>
2022-11-04 15:09:57 -03:00
21a7af535c Merge branch 'develop' into macos-drag-n-drop 2022-11-04 18:30:42 +01:00
a241d3f187 refactor(cmake): use KDEInstallDirs for Linux install paths
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2022-11-04 18:29:19 +01:00
8f045af867 Merge pull request #374 from flowln/fix_lto 2022-11-04 15:39:41 +05:30
6d4efc0443 Libraries: Add zlib
Signed-off-by: TheLastRar <TheLastRar@users.noreply.github.com>
2022-11-03 21:35:28 +00:00
e2e6d00064 CMake: Remove CMP0020 OLD
Signed-off-by: TheLastRar <TheLastRar@users.noreply.github.com>
2022-11-03 21:35:28 +00:00
e682c3e9b8 Fix: Correct exclusions for debug QT plugins
Signed-off-by: TheLastRar <TheLastRar@users.noreply.github.com>
2022-11-03 21:35:28 +00:00
fe347262e9 Fix: Using uint8_t in std::uniform_int_distribution is undefined
Signed-off-by: TheLastRar <TheLastRar@users.noreply.github.com>
2022-11-03 21:35:27 +00:00
c993209b76 Fix: Explicitly specify Version.h path
MSVC uses a different search mechanism that ends up picking the mete Version.h

Signed-off-by: TheLastRar <TheLastRar@users.noreply.github.com>
2022-11-03 21:35:27 +00:00
2cf4d5f8ec Merge pull request #389 from PrismLauncher/renovate/hendrikmuhs-ccache-action-1.x 2022-11-03 21:58:29 +01:00
c6ab9718ae chore(deps): update hendrikmuhs/ccache-action action to v1.2.5 2022-11-03 19:50:27 +00:00
3e3ef03855 Merge pull request #379 from TheLastRar/win-stacksize 2022-11-03 10:52:36 +05:30
c2f37716e5 clang_format for PR files
I'm getting a rendezvous... I thought I did this already

Signed-off-by: Tayou <tayou@gmx.net>
2022-11-03 05:05:07 +01:00
e9bfd43ff7 added requested changes
Signed-off-by: Tayou <tayou@gmx.net>
2022-11-03 05:04:36 +01:00
2958ffa73f Merge pull request #382 from PrismLauncher/renovate/hendrikmuhs-ccache-action-1.x 2022-11-02 16:50:47 -07:00
3d11d044d2 add an option to lock the toolbars
Signed-off-by: leo78913 <leo3758@riseup.net>
2022-11-02 20:33:02 -03:00
7eb0b1c69a chore(deps): update hendrikmuhs/ccache-action action to v1.2.4 2022-11-02 23:02:32 +00:00
8d39a9ea61 Fix: Increase stack size on Windows to 8MiB
Signed-off-by: TheLastRar <TheLastRar@users.noreply.github.com>
2022-11-02 20:13:44 +00:00
cb796dbdfb Remove unnecessary block
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2022-11-02 16:38:32 +00:00
4254c20eda experimental: install mime info in CMake
Signed-off-by: Ryan Cao <70191398+ryanccn@users.noreply.github.com>
2022-11-02 23:28:42 +08:00
094b57bb23 Merge pull request #372 from santiagocezar/rory 2022-11-02 12:06:08 +01:00
9ca4f19aea remove logcat
Signed-off-by: Santiago Cézar <santiagocezar2013@gmail.com>
2022-11-02 07:45:43 -03:00
a29d88c313 Even more fixes
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2022-11-02 09:59:58 +00:00
a1ed8154f7 Another fix
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2022-11-02 09:31:39 +00:00
6c45a990ef A good use of auto
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2022-11-02 09:13:44 +00:00
8dfa3393dc Formatting and forward-declaration
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2022-11-02 08:43:46 +00:00
d12323396f Merge pull request #346 from ryanccn/more-user-friendly-java-warning-text-ahaha 2022-11-02 10:38:26 +05:30
48d34741f3 keyboard navigation is important
Signed-off-by: Santiago Cézar <santiagocezar2013@gmail.com>
2022-11-01 22:53:45 -03:00
76203018e9 forgot the qrc
Signed-off-by: Santiago Cézar <santiagocezar2013@gmail.com>
2022-11-01 20:21:34 -03:00
7956e6f04e fix: don't use forward-declared Ptr types in meta/
This would cause ODR violations when those headers were included in
other places that also included stuff like "Version.h" (note the
"meta/Version.h"), which can cause problems, especially in LTO.

Signed-off-by: flow <flowlnlnln@gmail.com>
2022-11-01 19:48:26 -03:00
668342b470 add rory flat too (and holiday variants)
Signed-off-by: Santiago Cézar <santiagocezar2013@gmail.com>
Co-authored-by: Ashtaka <66513643+AshtakaOOf@users.noreply.github.com>
2022-11-01 19:31:37 -03:00
0a0ce74105 add rory
Signed-off-by: Santiago Cézar <santiagocezar2013@gmail.com>
Co-authored-by: Ashtaka <66513643+AshtakaOOf@users.noreply.github.com>
2022-11-01 19:06:27 -03:00
f6a3fa55b1 Merge pull request #368 from PrismLauncher/credits 2022-11-01 21:56:26 +01:00
718a9a3559 change: Update credits
Replaces txtsd's GitHub link with their website
Moves DioEgizio and flowln from contributors to dev team

Signed-off-by: txtsd <code@ihavea.quest>
2022-11-02 01:20:58 +05:30
5485c5aaed Merge pull request #365 from Scrumplex/fix-logo 2022-11-01 20:34:23 +01:00
afcdf4b9cf condensed icon theme code
Signed-off-by: Tayou <tayou@gmx.net>
2022-11-01 20:18:07 +01:00
a3f5ea3598 added suggested changes
Signed-off-by: Tayou <tayou@gmx.net>
2022-11-01 20:17:53 +01:00
fef60a9da0 add support for multiple custom themes
also moved theme related code from Application.cpp to new ui/themes/ThemeManager.cpp, this class should cleanly isolate theme related functions and help avoid code duplication in future theme related additions.
Themes can now be just qss or css files, they won't have color pallette information with them in that case

Signed-off-by: Tayou <tayou@gmx.net>
2022-11-01 20:10:12 +01:00
576867605d Add another fallback
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2022-11-01 18:40:12 +00:00
d1626d20bd Slight cleanup
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2022-11-01 18:30:11 +00:00
c890aa18f7 Only select correct mod
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2022-11-01 18:25:54 +00:00
6c7d040439 Hacky tweaks
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2022-11-01 18:12:27 +00:00
d03ae34b61 Auto-select first result
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2022-11-01 17:19:54 +00:00
b9547adce7 Add more license headers
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2022-11-01 17:02:24 +00:00
7f32c6464d Initial better mod browser link implementation
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
2022-11-01 16:58:22 +00:00
209a1650e4 clang_format and code cleanup
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2022-11-01 07:06:36 -07:00
b142e2a7a7 fix: fix logo name
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2022-11-01 13:59:11 +01:00
6010ce0dc5 chore(remove FS::copyFile):
Now that #333 is merged and FS::copy works on non directory copyFile can be removed.

Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2022-11-01 04:28:57 -07:00
a7a331a26e ensure FS::copyFile is marked for removal
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2022-11-01 04:24:11 -07:00
fda2c116be code quality cleanup
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2022-11-01 04:24:11 -07:00
d2f3dbaa29 fix mispellings and wrap strings for translation
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2022-11-01 04:24:11 -07:00
e9d4793b1e minor clean up and add some docs
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2022-11-01 04:24:11 -07:00
13c7efa058 copy found mods to instance (FTB and Flame)
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2022-11-01 04:24:11 -07:00
1598d65824 watch filesystem, compute and match hashes
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2022-11-01 04:24:11 -07:00
028e086960 send blocked mod info to dialog & prototype UI
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
2022-11-01 04:24:11 -07:00
04b39294ba Merge pull request #333 from flowln/fix_atl_packs_post_modpack_update 2022-11-01 09:56:16 +01:00
3a446c410c Merge pull request #329 from flowln/only_safe_workarounds 2022-11-01 09:55:43 +01:00
35edea2141 Merge pull request #359 from Chrono-byte/develop 2022-11-01 08:17:14 +01:00
ce1a4857cc Merge branch 'PrismLauncher:develop' into develop 2022-10-31 20:06:59 -04:00
dfdf739282 remove one space
Signed-off-by: Chrono <me@disilla.org>
2022-10-31 19:44:55 -04:00
7086b1e65c Merge pull request #351 from Scrumplex/fix-trash 2022-10-31 22:56:07 +01:00
f2d445d27b fix: fix undo key sequence
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2022-10-31 11:34:48 +01:00
29d362a6e0 fix: do not trash instances in Flatpak
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2022-10-31 11:34:46 +01:00
c8adc4e356 Merge pull request #354 from Scrumplex/translations-maybe
Improve display names of certain languages
2022-10-31 08:43:43 +01:00
8467daa0ec oop
Signed-off-by: Ryan Cao <70191398+ryanccn@users.noreply.github.com>
2022-10-31 14:58:38 +08:00
13e14b712e Merge pull request #352 from TheLastRar/Win-setDarkWinTitlebar-10OrGreater 2022-10-31 07:51:13 +01:00
27dfe30fe6 Update VerifyJavaInstall.cpp
Signed-off-by: Ryan Cao <70191398+ryanccn@users.noreply.github.com>
2022-10-31 14:44:11 +08:00
d89a541a8d Merge pull request #353 from FayneAldan/accounts-consistency 2022-10-30 16:52:36 -07:00
42350e689d chore: improve display names of certain languages
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2022-10-30 23:50:57 +01:00
b7d5fee995 Change Profiles to Accounts for consistency
Signed-off-by: Fayne Aldan <FayneAldan@gmail.com>
2022-10-30 15:56:45 -06:00
fd099166c6 Fix: Check if Windows 10 before calling setDarkWinTitlebar()
Signed-off-by: TheLastRar <TheLastRar@users.noreply.github.com>
2022-10-30 20:49:56 +00:00
b4be28b9bb fix: fix disabled trash undo action
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2022-10-30 18:37:06 +01:00
19a8d51bf3 fix: more user friendly Java warning text
Signed-off-by: Ryan Cao <70191398+ryanccn@users.noreply.github.com>
2022-10-30 11:56:43 +08:00
5d1aac3c53 added option to not copy screenshots
+ moved select all checkbox to top row, centered.

Signed-off-by: Marcelo Hernandez <marcelohdez.inq@gmail.com>
2022-10-29 22:27:31 -04:00
87b0d3fe11 Merge pull request #342 from fn2006/prism-svg-fix 2022-10-30 01:51:14 +05:30
98891a036d use existing variables
Signed-off-by: fn2006 <usernamefn2006alreadyused@protonmail.com>
2022-10-29 17:35:37 +01:00
b142a6da5b fix hardcoded svg
Signed-off-by: fn2006 <usernamefn2006alreadyused@protonmail.com>
2022-10-29 16:42:37 +01:00
1c0139c5f4 Merge pull request #340 from PrismLauncher/repology 2022-10-29 16:16:12 +02:00
1b7ae4321d Merge pull request #338 from Scrumplex/fix-credits-1 2022-10-29 16:15:34 +02:00
7f991ed897 feat: Add Repology badge to README
Signed-off-by: txtsd <code@ihavea.quest>
2022-10-29 19:37:00 +05:30
5ed7eb9d53 chore: update credits
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2022-10-29 13:12:51 +02:00
c00f96c7ca create getters and setters for InstanceCopyPrefs
+ use pragma once like other .h files in this directory

Signed-off-by: Marcelo Hernandez <marcelohdez.inq@gmail.com>
2022-10-29 00:55:33 -04:00
81333515e0 feat(tests): add test for FS::copy with files
Signed-off-by: flow <flowlnlnln@gmail.com>
2022-10-28 20:55:25 -03:00
be3c9abcfe fix: copy single files too in FS::copy
eek

Signed-off-by: flow <flowlnlnln@gmail.com>
2022-10-28 20:54:58 -03:00
177f17450a Merge pull request #173 from Scrumplex/fix-icons 2022-10-29 00:35:48 +02:00
150a3adaaf Merge pull request #267 from leo78913/toolbar-icons 2022-10-28 21:28:44 +02:00
76146e0f17 add a flat white version of the launch icon
Signed-off-by: leo78913 <leo3758@riseup.net>
2022-10-28 15:51:20 -03:00
4500e345b3 Merge branch 'PrismLauncher:develop' into toolbar-icons 2022-10-28 15:46:02 -03:00
e885f3c26a Merge pull request #65 from he3als/develop 2022-10-28 18:43:30 +02:00
e6e92f2b0e fix: only allow workarounds for blocked mods from MR when 100% safe
If a version on Modrinth has more than a single mod loader associated,
it means that it's possible we might get the wrong file for download,
since individual files don't really have this kind of metadata in the
API response.

So, in such cases, it's best to let the user take care of it instead.

Signed-off-by: flow <flowlnlnln@gmail.com>
2022-10-28 13:31:21 -03:00
03b48554b1 fix(style): convert tabs to spaces
Signed-off-by: Ryan Cao <70191398+ryanccn@users.noreply.github.com>
2022-10-29 00:01:22 +08:00
f229574758 Merge pull request #322 from DioEgizio/64bit-it 2022-10-28 18:43:32 +05:30
7b446dd30f Merge pull request #319 from Scrumplex/fix-avoid-mr-segfault 2022-10-28 13:40:52 +02:00
a5be974f1a feat: use clang64 on qt6 builds
Signed-off-by: DioEgizio <83089242+DioEgizio@users.noreply.github.com>
2022-10-28 08:05:31 +02:00
952615eadb Merge pull request #301 from DioEgizio/clang-attempt
feat(actions): use clang32 for building on windows
2022-10-28 07:54:17 +02:00
93894f62ff fix: avoid segfault for unexpected API reponse
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2022-10-28 00:08:15 +02:00
2051de51b5 Merge pull request #318 from TheLastRar/manifest-platform
Fix: Don't specify x86 in manifest
2022-10-27 22:53:15 +02:00
2ba3de79d8 chore: add comment about copy bug
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2022-10-27 21:23:17 +02:00
d35c985d2e feat(actions): use clang32 for building on windows
*way* faster

Signed-off-by: DioEgizio <83089242+DioEgizio@users.noreply.github.com>
2022-10-27 21:23:17 +02:00
b18466da84 Fix: Don't specify x86 in manifest
Signed-off-by: TheLastRar <TheLastRar@users.noreply.github.com>
2022-10-27 18:37:08 +01:00
90714a93f3 Merge pull request #315 from AshtakaOOf/develop
Remove appveyor from README
2022-10-27 13:15:53 -03:00
990cfb7b33 Remove appveyor
I forgor 💀 
But seriously I forgor to remove the &logo=appveyor thing AAAAAH!!!

Signed-off-by: Adrien <66513643+AshtakaOOf@users.noreply.github.com>
2022-10-27 18:08:56 +02:00
aacf7938ae Add CI build for Snap
Signed-off-by: Piper McCorkle <contact@piperswe.me>
2022-10-26 09:25:58 -05:00
2e0f818905 Add a snapcraft.yml for building Snaps
The included snapcraft.yml can be used to build a Snap (the application
format used by Canonical's modern package manager) out of Prism. If the
project wants in the future, Prism can publish these Snaps to the Snap
Store so the Prism Launcher can be installed through the Ubuntu Software
app on vanilla Ubuntu.

I haven't registered the Snap name, so it's currently free for anyone to
reserve. I'd suggest that a Prism developer register the name
prismlauncher at https://snapcraft.io/register-snap to ensure the name
belongs to the project, even if there are no plans of setting up CI to
publish snaps in the short term.

I have also modified JavaUtils.cpp to be able to autodetect the Java
versions included in the Snap, and added "*.snap" to the .gitignore so
the compiled Snap isn't accidentally committed to the repository.

Signed-off-by: Piper McCorkle <contact@piperswe.me>
2022-10-26 09:25:54 -05:00
63b6c6685c Abstract away InstanceCopyPrefs' internals through new getSelectedFiltersAsRegex() function
+ fix typo in comment
+ remove unused import
+ add [[nodiscard]] to methods

Signed-off-by: Marcelo Hernandez <marcelohdez.inq@gmail.com>
2022-10-26 00:20:36 -04:00
610b971117 Improve a bit README.md (#305)
Add Open Collective and fix some stuff.
2022-10-25 21:09:45 -03:00
318f657c31 Merge pull request #231 from tobimori/patch-1 2022-10-25 20:15:31 +02:00
482d3a1d76 update macos copyright year
Signed-off-by: tobimori <tobias@moeritz.cc>
2022-10-25 15:24:41 +02:00
b516dd970f Merge pull request #206 from flowln/changelog_height_fix 2022-10-25 11:29:14 +02:00
d9463620e6 move .app rename to packaging process, update mac copyright string
Signed-off-by: tobimori <tobias@moeritz.cc>
2022-10-25 09:34:07 +02:00
385c452ddf remove checkBool function, add updateSelectAllCheckbox function
Signed-off-by: Marcelo Hernandez <marcelohdez.inq@gmail.com>
2022-10-24 20:49:40 -04:00
a89df42561 Simplify bool check in CopyInstanceDialog.cpp
Signed-off-by: Marcelo Hernandez <marcelohdez.inq@gmail.com>
2022-10-24 19:31:40 -04:00
08cd5d52fa Merge pull request #283 from flowln/fix_abort_on_autosearch 2022-10-24 23:00:02 +02:00
d0e668e1d8 Merge pull request #211 from Hibiii/show-instace-arg 2022-10-24 22:51:30 +02:00
eeb95f89e1 add .mrpack mime type
Signed-off-by: Ryan Cao <70191398+ryanccn@users.noreply.github.com>
2022-10-25 00:12:27 +08:00
e4e0c27e1c Merge pull request #281 from Scrumplex/fix-nsis-displayname 2022-10-24 11:09:23 -03:00
b638a6ae95 fix: retry mod search job after aborting it
This way, we don't get stuck with an aborted job in our way! :o

Signed-off-by: flow <flowlnlnln@gmail.com>
2022-10-24 09:09:24 -03:00
74b98af8e5 fix: use display name in NSIS
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2022-10-24 12:43:13 +02:00
6a474a0125 fix: update icon generate script
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2022-10-24 11:18:53 +02:00
224304813a Merge pull request #274 from Protrikk/patch-1 2022-10-24 11:13:42 +02:00
4caf06bc99 Check "Select all" checkbox if all options are already selected
+ code cleanup

Signed-off-by: Marcelo Hernandez <marcelohdez.inq@gmail.com>
2022-10-23 19:30:41 -04:00
15593b5c09 Add "Select all" checkbox + ui revamp + code cleanup
Signed-off-by: Marcelo Hernandez <marcelohdez.inq@gmail.com>
2022-10-23 19:30:41 -04:00
e7e56eb1e3 add more options to copy instance dialog
- Copy game options, copy resource packs, copy shaders,
copy servers, and copy mods
- Also made a new InstanceCopyPrefs struct to store those
options rather than passing 7 different booleans into
InstanceCopyTask's constructor

Signed-off-by: Marcelo Hernandez <marcelohdez.inq@gmail.com>
2022-10-23 19:30:28 -04:00
43bf601f12 add icons to the instance toolbar
Signed-off-by: leo78913 <leo3758@riseup.net>
2022-10-23 20:04:19 -03:00
d5109f024b Better dark theme selection contrast
Tweak background of the selection background in order to make text more readable

Signed-off-by: Trisave <42098407+Protrikk@users.noreply.github.com>
2022-10-23 20:32:04 +02:00
7f441f5b87 Merge pull request #228 from bensuperpc/change_cast 2022-10-23 14:28:33 -03:00
0aac85dda1 Replace tab with spaces in flat_white.qrc
Signed-off-by: he3als <65787561+he3als@users.noreply.github.com>
2022-10-23 14:35:33 +01:00
4777a45722 Fix new flat white icons
Signed-off-by: he3als <65787561+he3als@users.noreply.github.com>
2022-10-23 14:32:35 +01:00
29e6e170cc Merge pull request #240 from jn64/fix/version-label-width 2022-10-23 02:07:29 +02:00
01db80d19a Fix version labels width
Make labels fit to the contents, so Ibeam cursor doesn't appear
over empty space. Should have been done with 90025ed.

Signed-off-by: jn64 <23169302+jn64@users.noreply.github.com>
2022-10-23 03:35:23 +08:00
8b28ed67ae Merge pull request #234 from AliceDTRH/fix/dedupejava 2022-10-22 13:14:26 -03:00
f35a30d371 oops
Signed-off-by: Ryan Cao <70191398+ryanccn@users.noreply.github.com>
2022-10-22 23:47:53 +08:00
1a8de111a3 add linux support
Signed-off-by: Ryan Cao <70191398+ryanccn@users.noreply.github.com>
2022-10-22 23:46:53 +08:00
9bb62e1bba Merge pull request #233 from jamierocks/atl-fix-aborting-installs 2022-10-22 12:19:58 -03:00
b2789fef0f Use correct variable for Windows
Signed-off-by: AliceDTRH <57547425+AliceDTRH@users.noreply.github.com>
2022-10-22 17:19:34 +02:00
46fe7e77b3 DCO Remediation Commit for he3als <65787561+he3als@users.noreply.github.com>
I, he3als <65787561+he3als@users.noreply.github.com>, hereby add my Signed-off-by to this commit: d87f743a2bd2fac761b94de77ed7255d7a983f03
I, he3als <65787561+he3als@users.noreply.github.com>, hereby add my Signed-off-by to this commit: 92dfd659f1a3e11accdbf0ebbdc7cb91f74d9a21
I, he3als <65787561+he3als@users.noreply.github.com>, hereby add my Signed-off-by to this commit: a6e65dfc7a7e8080297b59ecf322b788d1c9bad2
I, he3als <65787561+he3als@users.noreply.github.com>, hereby add my Signed-off-by to this commit: 99e1c13e80d12764f57a993661656d9ed7de27bb

Signed-off-by: he3als <65787561+he3als@users.noreply.github.com>
2022-10-22 16:14:50 +01:00
99e1c13e80 fix: add flat_white to code 2022-10-22 15:50:06 +01:00
a6e65dfc7a Add new flat white icons 2022-10-22 15:40:39 +01:00
1471eddc7e Deduplicates java installs before passing it on
Signed-off-by: AliceDTRH <57547425+AliceDTRH@users.noreply.github.com>
2022-10-22 16:40:31 +02:00
89fd84d916 Merge branch 'PrismLauncher:develop' into develop 2022-10-22 15:30:40 +01:00
0e17eee096 ATLauncher: Fix pack installation always aborting
I made a mistake during when cherry picking a previous commit, this
applies the change - and fixes installing ATLauncher packs.
2022-10-22 15:22:30 +01:00
81f1305270 Merge pull request #215 from forkiesassds/develop 2022-10-22 10:48:00 -03:00
2ec4310104 Merge pull request #230 from Scrumplex/add-pr-template 2022-10-22 15:32:00 +02:00
24e4db676a Merge pull request #224 from jamierocks/atl-abort-close-optional-mods-dialog 2022-10-22 15:31:53 +02:00
6e21a9829d Merge pull request #225 from Scrumplex/fix-segfault-fileresolver 2022-10-22 15:31:46 +02:00
4e99e10cbd Merge pull request #218 from getchoo/change-jars-path 2022-10-22 10:18:58 -03:00
500a7eceab update macOS build process to work with new .app
Signed-off-by: Tobias Möritz <tobias@moeritz.cc>
2022-10-22 15:10:32 +02:00
1dad35ca76 update macos plist contents (fixes #132)
Signed-off-by: Tobias Möritz <tobias@moeritz.cc>
2022-10-22 15:00:52 +02:00
8b3093e758 chore: add PR template
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2022-10-22 14:59:57 +02:00
a406aeb3ea feat: register as zip/mrpack handler on macOS
Signed-off-by: Ryan Cao <70191398+ryanccn@users.noreply.github.com>
2022-10-22 20:51:46 +08:00
970e4b020e fix: fix segfault when resolving Flame resources
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2022-10-22 14:11:51 +02:00
a4f4f2891c DCO Remediation Commit for a6b13487
I, Jamie Mansfield <jmansfield@cadixdev.org>, hereby add my
Signed-off-by to this commit: a6b13487f0e27c8bea1917720a0c5c1eb1eb206c

Signed-off-by: Jamie Mansfield <jmansfield@cadixdev.org>
2022-10-22 12:58:56 +01:00
a6b13487f0 ATLauncher: Abort install if optional mods dialog is closed
This matches the behaviour of ATLauncher.
2022-10-22 12:35:34 +01:00
56ae4e5b6a Change old style cast to C++ cast
Change old style cast to C++ cast

Signed-off-by: Bensuperpc <bensuperpc@gmail.com>
2022-10-22 13:04:48 +02:00
54c26b05fa Merge pull request #185 from flowln/fix_blocked_mods_crash 2022-10-22 12:44:20 +02:00
bd376d5217 Merge pull request #203 from Scrumplex/fix-dont-build-renove-branches
Don't build renovate branches
2022-10-22 10:59:49 +02:00
2592c69021 semicolon fail
i was off by one key :(

Signed-off-by: seth <getchoo@tuta.io>
2022-10-21 21:40:21 -04:00
4a2b25e841 fix: use correct variable for jars path
Signed-off-by: seth <getchoo@tuta.io>
2022-10-21 21:40:21 -04:00
ba4af1a890 fix: make jars path specific to prism
Signed-off-by: seth <getchoo@tuta.io>
2022-10-21 21:40:20 -04:00
9b17cde019 CurseForge modpack page improvements
Signed-off-by: forkiesassds <icanttellyou@memeware.net>
2022-10-22 01:20:08 +03:00
7a8c963722 Merge pull request #147 from Minion3665/enhancement/update-nix-derivation 2022-10-21 19:04:35 -03:00
82d1dbf173 DCO Remediation Commit for Hibi <69405847+Hibiii@users.noreply.github.com>
I, Hibi <69405847+Hibiii@users.noreply.github.com>, hereby add my Signed-off-by to this commit: 1288b926153c86b7966727e60de4af8e7dcb4031
I, Hibi <69405847+Hibiii@users.noreply.github.com>, hereby add my Signed-off-by to this commit: 5b75869c0ba60e00147d723d5633c9f6a5d6304e

Signed-off-by: Hibi <69405847+Hibiii@users.noreply.github.com>
2022-10-21 17:59:35 -03:00
aefb8b353e Merge pull request #187 from leo78913/menu-icons 2022-10-21 22:39:35 +02:00
5b75869c0b Add --show to manual page 2022-10-21 16:10:03 -03:00
1288b92615 Add argument to show instance window 2022-10-21 15:40:28 -03:00
7eecf454e8 fix: remove max height logic for mod update changelogs
It's not worth it to keep this, it's just a heuristic that fails from
time to time.

Signed-off-by: flow <flowlnlnln@gmail.com>
2022-10-21 14:07:43 -03:00
ccf7d1e0c4 material design icons
Signed-off-by: leo78913 <leo3758@riseup.net>
2022-10-21 14:04:04 -03:00
e4b5cd23e6 the trashcan icons dont look like trash now
Signed-off-by: leo78913 <leo3758@riseup.net>
2022-10-21 13:49:31 -03:00
819296cc9c Merge pull request #198 from PrismLauncher/renovate/hendrikmuhs-ccache-action-1.x 2022-10-21 22:13:09 +05:30
67c7d80f41 Merge pull request #197 from PrismLauncher/renovate/actions-cache-3.x 2022-10-21 22:12:48 +05:30
919f8c54d7 fix: don't build renovate branches
They will be built using the pull_requests event anyway.

Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2022-10-21 17:42:39 +02:00
cbaf71f581 Merge pull request #201 from Scrumplex/add-netlify-sponsor 2022-10-21 17:37:18 +02:00
f118c602e6 Merge pull request #202 from Heath123/patch-1 2022-10-21 17:37:09 +02:00
ff2f40f5e1 Fix typo
Signed-off-by: circuit10 <heath.mitchell27@gmail.com>
2022-10-21 16:28:04 +01:00
9758c9b2a2 chore: add Netlify as sponsor
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2022-10-21 17:04:21 +02:00
09e4e100a2 chore(deps): update hendrikmuhs/ccache-action action to v1.2.3 2022-10-21 14:55:49 +00:00
bdd5c180d3 chore(deps): update actions/cache action to v3.0.11 2022-10-21 14:55:42 +00:00
749b085063 Merge pull request #196 from PrismLauncher/renovate/configure 2022-10-21 16:55:17 +02:00
c5a796ad8e chore(deps): add renovate.json 2022-10-21 14:43:02 +00:00
12d8409e65 Merge pull request #39 from Sebbl0508/mod_dialog_fontsize 2022-10-21 15:25:28 +02:00
8db89b4cfb Merge branch 'PrismLauncher:develop' into menu-icons 2022-10-20 17:54:43 -03:00
31dc92dafe add icons to the instance menu and 4 new icons:
delete
rename
tag
export

Signed-off-by: leo78913 <leo3758@riseup.net>
2022-10-20 17:48:57 -03:00
01b90809e8 fix: memory leak when finishing blocked mods job
Signed-off-by: flow <flowlnlnln@gmail.com>
2022-10-20 16:55:22 -03:00
0a7383a4e1 fix: hide ProgressDialog when failing/succeeding tasks
WHY IS QT LIKE THAT AAAAAAAA

Signed-off-by: flow <flowlnlnln@gmail.com>
2022-10-20 16:54:39 -03:00
5e86a34925 Merge pull request #184 from Chrono-byte/develop 2022-10-20 21:52:24 +02:00
ece206b81c Remove erroneous space
Signed-off-by: Chrono-byte <me@disilla.org>
2022-10-20 15:22:04 -04:00
88341b923a fix contributor notices in AboutDialog.cpp for license compliance
Signed-off-by: Chrono-byte <me@disilla.org>
2022-10-20 15:14:26 -04:00
5d27633821 fix: show a single line in ProjectItem's desc. when there's no more space
Signed-off-by: flow <flowlnlnln@gmail.com>
2022-10-20 15:03:46 -03:00
a9d4370ad4 Merge pull request #47 from TheOPtimal/develop 2022-10-20 10:01:46 +02:00
8a0318c779 Merge pull request #119 from Scrumplex/update-readme-sponsors 2022-10-20 09:59:00 +02:00
8e754d9a56 fix: update README
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2022-10-20 09:54:23 +02:00
0e209dcb02 Merge pull request #148 from ZombieNub/prismlauncher-rename 2022-10-20 09:44:25 +02:00
6f2d6425a2 update meta to not break flatpak
Signed-off-by: Zeke <ezekielsmith@protonmail.com>
2022-10-20 16:54:57 +10:00
b46c4a81e0 check space requirements of project description
if there isn't enough space for 2 lines of project description, only
draw one

Signed-off-by: Sebastian Rueth <sebastian.rueth@protonmail.com>
2022-10-20 08:02:05 +02:00
b6aa33f3a6 Add Matrix Room
Co-authored-by: Fayne Aldan <FayneAldan@gmail.com>
Signed-off-by: TheOPtimal <41379516+TheOPtimal@users.noreply.github.com>
Signed-off-by: Jacob Gogichaishvili <iakob.gogichaishvili@gmail.com>
2022-10-20 09:13:37 +04:00
ab68d9198d PrismLauncher → Prism Launcher (again)
Co-authored-by: DioEgizio <83089242+DioEgizio@users.noreply.github.com>
Signed-off-by: TheOPtimal <41379516+TheOPtimal@users.noreply.github.com>
Signed-off-by: Jacob Gogichaishvili <iakob.gogichaishvili@gmail.com>
2022-10-20 09:13:37 +04:00
32eebd3ca7 PrismLauncher → Prism Launcher
Co-authored-by: Fayne Aldan <FayneAldan@gmail.com>
Co-authored-by: DioEgizio <83089242+DioEgizio@users.noreply.github.com>
Signed-off-by: TheOPtimal <41379516+TheOPtimal@users.noreply.github.com>
Signed-off-by: Jacob Gogichaishvili <iakob.gogichaishvili@gmail.com>
2022-10-20 09:13:37 +04:00
3f2e5633b4 Add OpenCollective
Co-authored-by: Fayne Aldan <FayneAldan@gmail.com>
Signed-off-by: TheOPtimal <41379516+TheOPtimal@users.noreply.github.com>
Signed-off-by: Jacob Gogichaishvili <iakob.gogichaishvili@gmail.com>
2022-10-20 09:13:37 +04:00
a99b9e80b8 Remove PolyMC's OpenCollective
Signed-off-by: Jacob Gogichaishvili <iakob.gogichaishvili@gmail.com>
2022-10-20 09:13:37 +04:00
42ed7e4626 Remove Matrix room link until one is created
Signed-off-by: Jacob Gogichaishvili <iakob.gogichaishvili@gmail.com>
2022-10-20 09:13:37 +04:00
ae910eea62 Change issue templates to Prism branding
Signed-off-by: Jacob Gogichaishvili <iakob.gogichaishvili@gmail.com>
2022-10-20 09:13:37 +04:00
d35920f356 Merge pull request #123 from MMK21Hub/patch-1 2022-10-19 22:00:23 -03:00
c29e7477f0 Merge branch 'develop' into prismlauncher-rename
Signed-off-by: IroncladLandship <jack.huffstutler@gmail.com>
2022-10-19 19:21:08 -05:00
86bbc7939c Merge pull request #100 from TheEvilSkeleton/improve-approachability 2022-10-19 21:15:37 -03:00
dab091a7b7 Update NIX.md so it has more methods + is clearer
- Add proper headings
- Change flake codeblocks so that configuration stuff isn't in the same
  place as flake.nix stuff
- Add instructions for not using the overlay with flakes
- Add instructions for running ad-hoc with flakes

Signed-off-by: Skyler Grey <skyler3665@gmail.com>
2022-10-19 23:50:48 +01:00
513d93cfc7 Change the derivation to have parity with nixpkgs
- Symlink rather than copying libraries
- Update maintainers
- Reformat with nixpkgs-fmt

Signed-off-by: Skyler Grey <skyler3665@gmail.com>
2022-10-19 23:48:56 +01:00
d7478c14fd Renamed inappropriate instances of "PrismLauncher" to "Prism Launcher"
Signed-off-by: IroncladLandship <jack.huffstutler@gmail.com>
2022-10-19 16:03:18 -05:00
297c593edd Improve approachability
Signed-off-by: TheEvilSkeleton <theevilskeleton@riseup.net>
2022-10-19 15:10:35 -04:00
6439ef11aa Fix incorrect release titles
Signed-off-by: MMK21Hub <KAGfan2018@outlook.com>
2022-10-19 19:21:48 +01:00
d6479e133d fix: properly center project descriptions
In particular, this takes into account the space used by the title, so
(hopefully) there won't be problems with custom themes with that.

Signed-off-by: flow <flowlnlnln@gmail.com>
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
Signed-off-by: Sebastian Rüth <sebastian.rueth@protonmail.com>
2022-10-19 20:12:50 +02:00
50bbf2aacc fix text clipping
Signed-off-by: Sebastian Rüth <sebastian.rueth@protonmail.com>
2022-10-19 20:12:50 +02:00
41032aaac2 Merge pull request #110 from Scrumplex/fix-nsis-shortcut 2022-10-19 14:28:36 +02:00
4e08f28246 Merge pull request #31 from flowln/who_needs_webview 2022-10-19 14:28:29 +02:00
46c57e120f Merge pull request #27 from flowln/ftb_install_improve 2022-10-19 13:51:35 +02:00
6b52ee61ae Merge pull request #92 from Scrumplex/new-logo 2022-10-19 13:41:56 +02:00
61fbc5a791 refactor: replace with new logo
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2022-10-19 13:08:23 +02:00
22365205f9 fix: use display name for NSIS
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2022-10-19 12:17:06 +02:00
c6515c1dad Merge pull request #54 from Samisafool/develop 2022-10-19 12:13:13 +02:00
8201d1df02 Rename
Signed-off-by: Samisafool <thenerdiestguy@gmail.com>
2022-10-19 15:02:43 +05:30
ddf168c536 Merge pull request #75 from Gideon9212/develop 2022-10-19 06:27:09 +02:00
c9f81f56e9 Fix banner
Removed boosted URL for plain

Signed-off-by: Gideon9212 <gideon_gallagher@zoho.com>
2022-10-18 18:35:03 -07:00
570264e1e9 Merge branch 'develop' into develop
Signed-off-by: Gideon9212 <gideon_gallagher@zoho.com>
2022-10-18 17:28:42 -07:00
325e58d98c Merge pull request #88 from FayneAldan/multimc-fallback
go all the way up the fork chain!
2022-10-18 19:27:24 -03:00
23a2960aa3 Merge pull request #60 from jitterdev/develop 2022-10-18 18:53:30 -03:00
888a87463e Add fallback for multimc.cfg
Signed-off-by: Fayne Aldan <FayneAldan@gmail.com>
2022-10-18 14:40:34 -06:00
2ebaf46095 Merge pull request #82 from flowln/i_broke_something_again 2022-10-18 22:15:08 +02:00
3a95a3b7c1 fix: don't take item from a possibly empty list
The list gets destroyed when we take the last object, so things explode.
😔

Signed-off-by: flow <flowlnlnln@gmail.com>
2022-10-18 16:51:42 -03:00
c4edffb388 Update banner
Changed to Join instead of Support server.

Signed-off-by: Gideon9212 <gideon_gallagher@zoho.com>
2022-10-18 12:10:29 -07:00
5eec7cc788 Change discord invite to a banner
To help direct people to support with a big banner.

Signed-off-by: Gideon9212 <gideon_gallagher@zoho.com>
2022-10-18 11:40:23 -07:00
fb4cf0b75d Merge pull request #55 from flowln/config_add_fallback 2022-10-18 19:50:34 +02:00
5584884fe6 Merge pull request #68 from nightsnowlinouo/develop 2022-10-18 19:43:02 +02:00
3bb1068ef0 Merge pull request #59 from CutestNekoAqua/bug-35 2022-10-18 19:26:57 +02:00
b1b85313ae Fix hosted weblate translation website URL
Signed-off-by: 雪鈴 SnowLin <113241163+nightsnowlinouo@users.noreply.github.com>
2022-10-19 01:22:58 +08:00
92dfd659f1 Fix .QRC file for flat white icons 2022-10-18 17:54:26 +01:00
d87f743a2b Add flat white icons
This is mainly for dark mode users, as I think that the regular colour of the flat icons do not look good with dark mode.
2022-10-18 17:49:35 +01:00
aec3e7b0fc correct non-proper noun
Signed-off-by: Jitter <64605731+jitterdev@users.noreply.github.com>
2022-10-18 11:14:27 -05:00
243600b75b Merge pull request #61 from pog5/develop 2022-10-18 18:03:34 +02:00
3d89d126d0 PlaceholderMC => PrismLauncher
Small Correction

Signed-off-by: Nightly <62222436+pog5@users.noreply.github.com>
2022-10-18 15:52:32 +00:00
54281e53a1 Update README.md
Signed-off-by: Jitter <64605731+jitterdev@users.noreply.github.com>
2022-10-18 10:35:00 -05:00
6befd2be81 Update README.md
Signed-off-by: Jitter <64605731+jitterdev@users.noreply.github.com>
2022-10-18 10:34:27 -05:00
1f0ca9ed92 Update README.md
Signed-off-by: Jitter <64605731+jitterdev@users.noreply.github.com>
2022-10-18 10:34:11 -05:00
f3db9c3920 Merge pull request #48 from flowln/fix_nbt 2022-10-18 17:31:46 +02:00
83ceb26151 Streamline Button changes to improve source readability. 2022-10-18 17:28:23 +02:00
32cdfb871c fix: add fallback for polymc.cfg
Signed-off-by: flow <flowlnlnln@gmail.com>
2022-10-18 12:22:42 -03:00
801e7da5ee feat: allow specifying fallbacks to INI files
Signed-off-by: flow <flowlnlnln@gmail.com>
2022-10-18 12:22:42 -03:00
2cf1ab7ec5 Merge pull request #43 from SSUPII/develop 2022-10-18 11:31:38 -03:00
d049c1afaf chore: update flake
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2022-10-18 16:28:30 +02:00
9f45389bc1 Merge pull request #45 from NotNite/update-readme 2022-10-18 11:23:10 -03:00
d875481969 fix: update libnbtplusplus submodule's URL
Signed-off-by: flow <flowlnlnln@gmail.com>
2022-10-18 11:11:34 -03:00
17a1e1245c Updated HTML tags to Markdown
Signed-off-by: Sergio <42090377+SSUPII@users.noreply.github.com>
2022-10-18 16:04:28 +02:00
06d28c3eec Updated project naming
Signed-off-by: Sergio <42090377+SSUPII@users.noreply.github.com>
2022-10-18 15:57:43 +02:00
684982c25c README: PlaceholderMC -> Prism Launcher
Also cleaned it up a bit to make my Markdown linter happy.
2022-10-18 09:52:36 -04:00
421522a61a Added further clarifications
Signed-off-by: Sergio <42090377+SSUPII@users.noreply.github.com>
2022-10-18 15:52:00 +02:00
f3b29d67f4 Merge branch 'PrismLauncher:develop' into develop 2022-10-18 15:39:29 +02:00
2ee5c6b2a1 Totally skipped a typo
Signed-off-by: Sergio <42090377+SSUPII@users.noreply.github.com>
2022-10-18 15:38:32 +02:00
5083772c6f Fixed markdown errors
Signed-off-by: Sergio <42090377+SSUPII@users.noreply.github.com>
2022-10-18 15:37:11 +02:00
fd51e5df47 Added build instructions for Linux
Added build instructions in the main repository as a temporary reference

Signed-off-by: Sergio <42090377+SSUPII@users.noreply.github.com>
2022-10-18 15:35:40 +02:00
3405fd91c6 Merge pull request #33 from DioEgizio/remove-useless-actions 2022-10-18 15:31:32 +02:00
194822f11e Merge pull request #28 from flowln/fix_copy 2022-10-18 15:27:53 +02:00
98963d4cdf Merge pull request #29 from Scrumplex/feat-clear-metadata 2022-10-18 15:25:56 +02:00
804ef36b20 Merge pull request #26 from Scrumplex/armhf 2022-10-18 15:24:33 +02:00
3c6ff8fddf Merge pull request #36 from DioEgizio/fix-copying 2022-10-18 15:05:31 +02:00
511893d535 update COPYING
Signed-off-by: DioEgizio <83089242+DioEgizio@users.noreply.github.com>
2022-10-18 14:47:20 +02:00
e05fe77bfe feat: remove redundant actions from instance toolbar and redundant "instance"s
Signed-off-by: DioEgizio <83089242+DioEgizio@users.noreply.github.com>
2022-10-18 14:43:29 +02:00
2b7b9a2abb Merge pull request #25 from PlaceholderMC/fix-data-path
Fix Data path
2022-10-18 14:05:22 +02:00
6db3f68ae1 refactor: use correct data path
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2022-10-18 13:58:50 +02:00
3773f2e7a5 Merge pull request #23 from PlaceholderMC/new-cf-key 2022-10-18 13:29:36 +02:00
1f8bffc15a fix: new CurseForge key
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2022-10-18 13:24:57 +02:00
afaef4e83b Merge pull request #13 from PlaceholderMC/rebrand 2022-10-18 13:05:24 +02:00
b746f723cb fix: add Prism copyright header
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2022-10-18 13:01:32 +02:00
cfaf44f57b fix: add sparkle public key
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2022-10-18 12:49:08 +02:00
eed541201e fix: add new MSA client id
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2022-10-18 10:37:35 +02:00
a8bcb85f7b fix(actions): change to PrismLauncher
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2022-10-18 10:13:44 +02:00
981e9cf290 Merge pull request #14 from leumasme/develop 2022-10-18 13:27:10 +05:30
3ac398ac49 fix: use display name in code
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2022-10-18 09:50:27 +02:00
2d0728395f Update README.md discord vanity link 2022-10-18 09:44:50 +02:00
722194405a refactor: initial rebrand
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2022-10-18 09:37:59 +02:00
0868a5e534 Merge pull request #11 from AshtakaOOf/temp-readme
More readable README.md :)
2022-10-18 01:42:54 +02:00
a86b9c82ce Update README.md
Signed-off-by: Adrien <66513643+AshtakaOOf@users.noreply.github.com>
2022-10-18 01:38:49 +02:00
f8642548c8 Update README.md
Signed-off-by: Adrien <66513643+AshtakaOOf@users.noreply.github.com>
2022-10-18 01:35:30 +02:00
27873f7ed4 Update README.md
Signed-off-by: Adrien <66513643+AshtakaOOf@users.noreply.github.com>
2022-10-18 01:27:51 +02:00
b3eda6bcbb Merge pull request #5 from AshtakaOOf/AshtakaOOf-readme
Temporary README.md
2022-10-17 23:08:21 +02:00
1c7799e292 Update README.md
Change some stuff temporarily

Signed-off-by: Adrien <66513643+AshtakaOOf@users.noreply.github.com>
2022-10-17 22:53:02 +02:00
aecd158d3c Merge pull request #1208 from DioEgizio/fix-unused-libs
Removes `classparser` and `xz-embedded`
2022-10-16 10:41:43 -03:00
87d35f0d16 fix: remove some unused libs
Signed-off-by: DioEgizio <83089242+DioEgizio@users.noreply.github.com>
2022-10-15 20:16:15 +02:00
c089f9b59f Merge pull request #1203 from DioEgizio/macos-legacy 2022-10-15 15:24:30 +02:00
82d7f9f5a4 chore(tests): add test for FS copy with dot folders/files
Signed-off-by: flow <flowlnlnln@gmail.com>
2022-10-15 09:40:00 -03:00
8bc529be3d fix: include hidden files when copying instances
fixes instance ccopy on linux .-.

Signed-off-by: flow <flowlnlnln@gmail.com>
2022-10-15 09:20:31 -03:00
924c1634d3 Merge pull request #1194 from flowln/fix_opted_out_on_any_filter 2022-10-15 13:18:35 +02:00
03d077e915 fix(nix): add ghc_filesystem dependency
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2022-10-15 13:13:56 +02:00
303628bb05 refactor: support system ghc-filesystem
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2022-10-15 13:13:38 +02:00
3b92ec8e82 chore: clang-format RuntimeContext
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2022-10-15 12:43:15 +02:00
545944cb0d refactor: support armhf
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2022-10-15 12:41:16 +02:00
c90a88b6b6 fix: correct ftb legacy too
Signed-off-by: flow <flowlnlnln@gmail.com>
2022-10-14 12:18:06 -03:00
89e45a61b3 fix: workaround ghc::filesystem bug
Signed-off-by: DioEgizio <83089242+DioEgizio@users.noreply.github.com>
2022-10-14 16:45:13 +02:00
2aff7bac4a fix: disable updater on macOS-Legacy
Signed-off-by: DioEgizio <83089242+DioEgizio@users.noreply.github.com>
2022-10-14 15:58:16 +02:00
124097d3a5 feat!: use ghc/filesystem in place of std's one if needed
Signed-off-by: flow <flowlnlnln@gmail.com>
2022-10-14 14:08:48 +02:00
c520faed6d feat: add gulrak/filesystem submodule
... for old macs that don't have std::filesystem in their stdlib.

Signed-off-by: flow <flowlnlnln@gmail.com>
2022-10-14 14:08:42 +02:00
5bdb3703ed fix: stop forcing libc++ on macOS
Signed-off-by: DioEgizio <83089242+DioEgizio@users.noreply.github.com>
2022-10-14 14:08:05 +02:00
2901039a48 feat(actions): macOS-Legacy package
still no updater part though

Signed-off-by: DioEgizio <83089242+DioEgizio@users.noreply.github.com>
2022-10-14 14:08:05 +02:00
dfa220ef02 fix: issues with aborts (again)
i hate it

Signed-off-by: flow <flowlnlnln@gmail.com>
2022-10-13 15:10:35 -03:00
f26be00571 fix: abort search if we're already trying to download a pack
Meaning we don't have to wait for the searches to finish in the
background to finally start the modpack download, when we have already
selected it -_-

Signed-off-by: flow <flowlnlnln@gmail.com>
2022-10-13 13:49:06 -03:00
83654a193e refactor+fix: Make FTB install task similar to other install tasks
In particular, this changes the order so that the instance gets created
before downloading the mods (like other install tasks), and the mod download
directly puts the files in the staging folder (like the others), instead
of that weird makeCached and copy stuff.

This fixes some issues with modpack downloads from FTB, like creating an
instance with no mods in it.

Signed-off-by: flow <flowlnlnln@gmail.com>
2022-10-13 13:27:52 -03:00
b2a5d8daf4 fix: don't include opted out versions with the 'Any' filter on the MD
Signed-off-by: flow <flowlnlnln@gmail.com>
2022-10-12 10:26:14 -03:00
19ee736e1d Merge pull request #1190 from TayouVR/merged-launch-button1 2022-10-11 16:21:41 -03:00
fda3f1352e feat: add image support for the news reader :^)
Signed-off-by: flow <flowlnlnln@gmail.com>
2022-10-11 16:11:08 -03:00
d194b02e28 fix: prevent images overriding content when changing pages
Signed-off-by: flow <flowlnlnln@gmail.com>
2022-10-11 15:51:54 -03:00
aaba99dc10 Update launcher/ui/MainWindow.cpp
make " Offline" string for profilers translatable

Co-authored-by: Sefa Eyeoglu <contact@scrumplex.net>
Signed-off-by: Tayou <31988415+TayouVR@users.noreply.github.com>
2022-10-11 14:58:34 +02:00
93a2e0f777 Merge Launch Buttons
Signed-off-by: Tayou <tayou@gmx.net>
2022-10-10 23:23:06 +02:00
71f3c6b461 feat: add clear metadata action
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2022-10-10 12:48:25 +02:00
aabcca5059 Merge pull request #1175 from Ozynt/patch-1 2022-10-09 20:20:05 +02:00
7e67fd8c79 Update LaunchController.cpp
Signed-off-by: Ozynt <104643560+Ozynt@users.noreply.github.com>
2022-10-09 13:20:50 +02:00
fecf1ffcb9 Update LaunchController.cpp
Signed-off-by: Ozynt <104643560+Ozynt@users.noreply.github.com>
2022-10-09 13:19:38 +02:00
fafc9cf9ca Merge pull request #1033 from Scrumplex/multi-arch-support 2022-10-08 20:12:40 +02:00
3111e6a721 chore: add missing license headers
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2022-10-08 20:12:07 +02:00
e436f471a0 Merge pull request #1177 from DioEgizio/codeql
bye LGTM 👋
2022-10-08 15:04:23 -03:00
28f84902f6 Merge pull request #1185 from DioEgizio/fix-tooltip
Fix outdated 'Disable mod metadata' button's warning message.
2022-10-08 14:34:59 -03:00
ebee50eedc Improve default light and dark themes (#1174) 2022-10-08 14:33:24 -03:00
e0ef09dfe1 Merge pull request #1183 from Scrumplex/fix-capabilities-first-run 2022-10-08 14:29:14 -03:00
d7992ab29d feat: add image support for FTB packs
Signed-off-by: flow <flowlnlnln@gmail.com>
2022-10-08 14:12:05 -03:00
60f19f305e feat: add image support for modrinth modpack pages
Signed-off-by: flow <flowlnlnln@gmail.com>
2022-10-08 14:12:03 -03:00
d99976f5d7 fix: make mod and modpack caches separate for Modrinth
This makes it similar to CF mods / modpacks. The mods cache is
maintained with the same name because it most likely has more data it
in, so this commit will affect existing caches as minimally as possible.

Signed-off-by: flow <flowlnlnln@gmail.com>
2022-10-08 14:11:20 -03:00
db158a5735 feat: add image support for mod pages
Signed-off-by: flow <flowlnlnln@gmail.com>
2022-10-08 14:11:20 -03:00
ea3be17220 feat: add widget for a text browser with image support
Signed-off-by: flow <flowlnlnln@gmail.com>
2022-10-08 14:11:20 -03:00
f26049009e fix: mod updating isn't upcoming anymore :p
Signed-off-by: DioEgizio <83089242+DioEgizio@users.noreply.github.com>
2022-10-08 16:20:46 +02:00
787234a53a Merge pull request #1163 from flowln/fix_list_icons 2022-10-08 12:12:38 +02:00
fc3a64056c Merge pull request #1154 from Scrumplex/epic-formatting-codes 2022-10-08 12:12:26 +02:00
6ebc9abb80 fix: update capabilities before first-run wizard
On first run, the condition for the wizard would return, before running
updateCapabilities(). This moves that call up, as its only dependency is
the settings system.

Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2022-10-06 14:46:13 +02:00
80e9eed35a fix: remove old unused lgtm.yml, exclude cpp/fixme-comment
Signed-off-by: DioEgizio <83089242+DioEgizio@users.noreply.github.com>
2022-10-04 16:17:57 +02:00
23b3990f99 feat(code scanning): enable security-and-quality query
Signed-off-by: DioEgizio <83089242+DioEgizio@users.noreply.github.com>
2022-10-04 16:17:57 +02:00
41276403df feat(actions): add codeql code scanning
Signed-off-by: DioEgizio <83089242+DioEgizio@users.noreply.github.com>
2022-10-04 16:17:57 +02:00
e3e9e39498 Merge pull request #1171 from vedantmgoyal2009/patch-1 2022-10-02 15:08:59 +02:00
f315025a8d Merge pull request #1167 from Scrumplex/epic-commandline 2022-10-02 00:41:34 +05:30
8e43d97133 Microsoft account only
Signed-off-by: stoltsvensk <104643560+stoltsvensk@users.noreply.github.com>
2022-10-01 16:47:23 +02:00
c97a47dc62 Merge pull request #1172 from Scrumplex/fix-includes 2022-09-30 18:08:45 -03:00
7ccafdc993 fix: add missing includes to fix Qt 6.4 build
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2022-09-30 19:56:01 +02:00
0dca9cb6b8 Merge pull request #1162 from Trial97/feature/Replace-toml-library 2022-09-30 19:44:45 +02:00
be3d780720 Update winget.yml
Signed-off-by: Vedant <83997633+vedantmgoyal2009@users.noreply.github.com>
2022-09-30 22:51:47 +05:30
0f59a1dde1 fix(nix): add tomlplusplus
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2022-09-26 15:42:45 +02:00
7c6bb80cee fix: move toml++ find call
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2022-09-26 13:46:01 +02:00
62841c5b23 fix: pin tomlplusplus to latest release
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2022-09-26 13:44:28 +02:00
aad4f8d1f7 fix: update Git modules
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2022-09-26 13:44:28 +02:00
11c44c676c fix: remove unused MACOS_HINT
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2022-09-26 13:28:46 +02:00
370c3aa598 Merge pull request #894 from flowln/update_from_external_source
epic PR
2022-09-26 08:25:12 -03:00
1cdadafdf8 refactor: use QCommandLineParser instead
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2022-09-26 13:21:27 +02:00
dd6f670dec fix: Fixed memory leak
Signed-off-by: timoreo <contact@timoreo.fr>
2022-09-26 11:50:55 +02:00
9ff364b0d3 huge nit: added const refs, everywhere
Signed-off-by: timoreo <contact@timoreo.fr>
2022-09-26 11:50:31 +02:00
58a5331f7b Merge pull request #1164 from Scrumplex/fix-sort-languages 2022-09-25 19:50:55 +02:00
ed261f0af9 Update launcher/minecraft/mod/tasks/LocalModParseTask.cpp
Co-authored-by: flow <flowlnlnln@gmail.com>
Signed-off-by: Alexandru Ionut Tripon <alexandru.tripon97@gmail.com>
2022-09-25 20:38:55 +03:00
c01b475cbf Merge pull request #1165 from ErogigGit/develop 2022-09-25 09:33:29 -03:00
3d4feeec8d DCO Remediation Commit for ErogigGit <eric.hagerstrand@gmail.com>
I, ErogigGit <eric.hagerstrand@gmail.com>, hereby add my Signed-off-by to this commit: 8a4f1c66f83a339d33ab0ba0076d8c1141055067

Signed-off-by: ErogigGit <eric.hagerstrand@gmail.com>
2022-09-24 23:31:30 +02:00
a1800ec23f Prefer the system tomlplusplus
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2022-09-25 00:20:01 +03:00
8a4f1c66f8 Allow double clicking to mark for dowload
Signed-off-by: Erogig <erogigabyte@gmail.com>
2022-09-24 22:37:51 +02:00
b187231b0e fix: sort languages by their name instead of key
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2022-09-24 11:53:41 +02:00
60b38de69f fix: fallback for languages without a native name
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2022-09-24 11:48:33 +02:00
600c49f7f0 Replaced tomlc99 with tomlplusplus
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
2022-09-24 00:10:27 +03:00
e7380e70a3 fix: use placeholder icon when the project has no icon in MR
Projects with no icon return a null icon URL in Modrinth's API.

Signed-off-by: flow <flowlnlnln@gmail.com>
2022-09-23 18:05:58 -03:00
3df8594f19 feat: change project item delegate for modrinth modpacks
more info! \ ^-^/

Signed-off-by: flow <flowlnlnln@gmail.com>
2022-09-23 16:59:40 -03:00
ee4a829293 fix: remove manual icon resize in ModModel
THis fixes a FIXME, now that we fixed the issue :o

Signed-off-by: flow <flowlnlnln@gmail.com>
2022-09-23 16:59:40 -03:00
1862f3c124 fix: set icon sizes correctly in ProjectItemDelegate
no more dumb hacks with icons!!

Signed-off-by: flow <flowlnlnln@gmail.com>
2022-09-23 16:59:40 -03:00
777ab3416f feat: also format resource/texture pack names
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2022-09-21 15:00:28 +02:00
ecf5ab75e7 feat: support more formatting codes
also fix some crashes

Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2022-09-21 14:59:01 +02:00
4f6d964217 fix: don't change groups when updating an instance
Signed-off-by: flow <flowlnlnln@gmail.com>
2022-09-20 18:36:10 -03:00
06019f01e3 feat: add dialog to ask whether to chaneg instance's name
This prevents custom names from being lost when updating, by only
changing the name if the old instance name constains the old version,
so that we can update it if the user whishes to.

Signed-off-by: flow <flowlnlnln@gmail.com>
2022-09-20 18:36:10 -03:00
ddde885084 fix: show warning in case there's no old index when updating
Signed-off-by: flow <flowlnlnln@gmail.com>
2022-09-20 18:36:10 -03:00
be8c6f218c refactor: setAbortStatus -> setAbortable
Signed-off-by: flow <flowlnlnln@gmail.com>
2022-09-20 18:36:10 -03:00
9eb35ea7c8 fix: don't load specific settings for managed pack info
This avoids loading all settings for all instances when searching for
one with a specific managed pack name.

Signed-off-by: flow <flowlnlnln@gmail.com>
2022-09-20 18:36:10 -03:00
d2fdbec41d fix: move file deletion to the end of the instance update
This makes it harder for problems in the updating process to affect the
current instance. Network issues, for instance, will no longer put the
instance in an invalid state.

Still, a possible improvement to this would be passing that logic to
InstanceStaging instead, to be handled with the instance commiting
directly. However, as it is now, the code would become very spaguetti-y,
and given that the override operation in the commiting could also put
the instance into an invalid state, it seems to me that, in order to
fully error-proof this, we would need to do a copy operation on the
whole instance, in order to modify the copy, and only in the end
override everything an once with a rename. That also has the possibility
of corrupting the instance if done without super care, however, so I
think we may need to instead create an automatic backup system, with an
undo command of sorts, or something like that. This doesn't seem very
trivial though, so it'll probably need to wait until another PR. In the
meantime, the user is advised to always backup their instances before
doing this kind of action, as always.

What a long commit message o.O

Signed-off-by: flow <flowlnlnln@gmail.com>
2022-09-20 18:36:09 -03:00
2dd372600c fix: some abort-related issues
Signed-off-by: flow <flowlnlnln@gmail.com>
2022-09-20 18:36:09 -03:00
eda6cf11ef feat(ui): improve info dialog before updating an instance
Adds a 'Cancel' option, and add a note about doing a backup before
updating.

Signed-off-by: flow <flowlnlnln@gmail.com>
2022-09-20 18:36:09 -03:00
68facd6b93 fix(ui): hook up abort status signal in ProgressDialog
Now we have a visual indication on when tasks are abortable!

Signed-off-by: flow <flowlnlnln@gmail.com>
2022-09-20 18:36:09 -03:00
87002fb8f8 fix: hook up setAbortStatus in instance import tasks
Signed-off-by: flow <flowlnlnln@gmail.com>
2022-09-20 18:36:09 -03:00
6a50fa35ec feat: add canAbort() status change in Task
By now, it's a recurring pattern of wanting to restrict aborting in
certain situations. This avoids further code duplication, and adds a
signal that external users can hook up to to respond to such change.

Signed-off-by: flow <flowlnlnln@gmail.com>
2022-09-20 18:36:09 -03:00
6541570969 fix: simplify abort handling and add missing emits
Signed-off-by: flow <flowlnlnln@gmail.com>
2022-09-20 18:36:09 -03:00
4b0ceea894 fix: correctly set managed pack fields in CF pack
Signed-off-by: flow <flowlnlnln@gmail.com>
2022-09-20 18:36:09 -03:00
8c0816c166 feat: add override awareness to CF modpack updating
Signed-off-by: flow <flowlnlnln@gmail.com>
2022-09-20 18:36:08 -03:00
be769d07f1 fix: correctly set all managed pack fields in Modrinth pack
Signed-off-by: flow <flowlnlnln@gmail.com>
2022-09-20 18:36:08 -03:00
3a9d58e31c feat: add override handling in modrinth pack update
Signed-off-by: flow <flowlnlnln@gmail.com>
2022-09-20 18:36:08 -03:00
7024acac06 feat: add override helper functions
These help us keep track of relevant metadata information about
overrides, so that we know what they are when we update a pack.

Signed-off-by: flow <flowlnlnln@gmail.com>
2022-09-20 18:36:08 -03:00
6131346e2f refactor: change the way instance names are handled
While working on pack updating, instance naming always gets in the way,
since we need both way of respecting the user's name choice, and a
standarized way of getting the original pack name / version.

This tries to circunvent such problems by abstracting away the naming
schema into it's own struct, holding both the original name / version,
and the user-defined name, so that everyone can be happy and world peace
can be achieved! (at least that's what i'd hope :c).

Signed-off-by: flow <flowlnlnln@gmail.com>
2022-09-20 18:36:08 -03:00
eed73c9078 refactor: clean up InstanceImportTask a bit
Also removes a divide by two in the download progress
(why was it there???)

Signed-off-by: flow <flowlnlnln@gmail.com>
2022-09-20 18:36:08 -03:00
795d6f35ee feat: add curseforge modpack updating
Signed-off-by: flow <flowlnlnln@gmail.com>
2022-09-20 18:36:08 -03:00
ebd46705d5 refactor: move creation of CF file download task to a separate function
Signed-off-by: flow <flowlnlnln@gmail.com>
2022-09-20 18:36:08 -03:00
72d2ca234e refactor: move flame modpack import to separate file
Signed-off-by: flow <flowlnlnln@gmail.com>
2022-09-20 18:36:07 -03:00
2246c3359b refactor: add throw_on_blocked arg to Flame file parse
Signed-off-by: flow <flowlnlnln@gmail.com>
2022-09-20 18:36:07 -03:00
242fb156a2 feat: add 'getFiles' by fileIds route in Flame API
Signed-off-by: flow <flowlnlnln@gmail.com>
2022-09-20 18:36:07 -03:00
208ed73e59 feat: add early modrinth pack updating
Still some FIXMEs and TODOs to consider, but the general thing is here!

Signed-off-by: flow <flowlnlnln@gmail.com>
2022-09-20 18:36:06 -03:00
4441b37338 refactor: move modrinth modpack import to separate file
Signed-off-by: flow <flowlnlnln@gmail.com>
2022-09-20 18:32:36 -03:00
941d75824a refactor: add instance creation abstraction and move vanilla
This is so that 1. Code is more cleanly separated, and 2. Allows to more
easily add instance updating :)

Signed-off-by: flow <flowlnlnln@gmail.com>
2022-09-20 18:32:36 -03:00
ec9ddc4f22 chore: add helper function for copying managed pack data between insts.
Signed-off-by: flow <flowlnlnln@gmail.com>
2022-09-20 18:32:36 -03:00
98b6f90172 fix: add more legacy architectures
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2022-09-20 16:01:08 +02:00
7e280de361 refactor: drop 64-bit check
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2022-09-20 16:01:08 +02:00
7bd8bd13fe feat: support multiarch system classifiers
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2022-09-20 16:01:06 +02:00
09e85e948c refactor: introduce RuntimeContext
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2022-09-20 15:59:43 +02:00
9ec1c00887 fix: register JavaRealArchitecture for MinecraftInstance
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2022-09-20 15:58:56 +02:00
c6bcb6228b Merge pull request #1108 from Scrumplex/better_texture_packs 2022-09-20 13:28:33 +02:00
a24d589845 fix: ensure all resource folders exist
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2022-09-20 10:39:05 +02:00
ebbcc9f6da fix: actually render color codes for texture packs
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2022-09-20 10:26:15 +02:00
23fc453fae fix: comments and naming of texture pack stuff
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2022-09-20 10:26:15 +02:00
aad6f74db6 fix: tests
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2022-09-20 10:26:15 +02:00
07dcefabcb feat: add texture pack parsing
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2022-09-20 10:26:15 +02:00
40c68595d7 Merge pull request #1150 from flowln/fix_crash_on_game_quit 2022-09-20 09:41:59 +05:30
fe9a4fece4 Merge pull request #1142 from flowln/better_fs 2022-09-20 09:00:19 +05:30
098327f128 Merge pull request #903 from jopejoe1/demo-launch 2022-09-18 14:41:25 +02:00
0873b8d304 fix: prevent container detaching in ResourceFolderModel
and use const accessors whenever we can!

Signed-off-by: flow <flowlnlnln@gmail.com>
2022-09-16 20:12:31 -03:00
c9eb584ac8 fix: prevent deletes by shared pointer accidental creation
This fixes the launcher crashing when opening the game :iea:

Signed-off-by: flow <flowlnlnln@gmail.com>
2022-09-16 20:12:30 -03:00
10493bd44a fix: move newly allocated resources to the main thread
This avoids them getting deleted when the worker thread exits, due to
thread affinity on the created thread.

Signed-off-by: flow <flowlnlnln@gmail.com>
2022-09-16 20:12:30 -03:00
9e35230467 fix: memory leak when getting mods from the mods folder
friendly reminder to always delete your news.

Signed-off-by: flow <flowlnlnln@gmail.com>
2022-09-16 20:12:30 -03:00
81e326571b fix: enable demo launch only on supported instances
e.g. >= 1.3.1 instances

Signed-off-by: flow <flowlnlnln@gmail.com>
2022-09-15 19:27:42 -03:00
1b2a7de4e2 fix: show 'demo' instead of 'offline' in log when in demo mode
Signed-off-by: flow <flowlnlnln@gmail.com>
2022-09-15 18:44:18 -03:00
11216d200c change: move demo action to "Play offline" menu
Signed-off-by: flow <flowlnlnln@gmail.com>
2022-09-15 18:44:18 -03:00
777be6a48d Add 'Ctrl+Alt+O' Shortcut to launch demo instance.
Signed-off-by: jopejoe1 <johannes@joens.email>
2022-09-15 18:44:18 -03:00
5765a1fdf1 fix: allow demo for older versions
We were not propagating the '--demo' flag in the legacy launcher,
unconditionally setting the 'demo' parameter to false.

Signed-off-by: flow <flowlnlnln@gmail.com>
2022-09-15 18:44:18 -03:00
29dcb9d274 Added Launch Demo button.
Signed-off-by: jopejoe1 <johannes@joens.email>
2022-09-15 18:44:18 -03:00
8674ac4f68 Merge pull request #1146 from Scrumplex/fix-launch-rd 2022-09-15 17:55:08 -03:00
684b8f24f3 fix: allow starting rd- versions
Using `Collections.emptyList()` doesn't allow us to later append stuff
into that list. Use an empty `ArrayList` instead.

Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2022-09-15 09:29:48 +02:00
1ca2be0039 Merge pull request #982 from DavidoTek/windarkmode2 2022-09-14 13:17:17 +02:00
8c41ff68f7 chore(actions)!: bump macOS required version to 10.15
This is needed for std::filesystem support in macOS's libc.

Signed-off-by: flow <flowlnlnln@gmail.com>
2022-09-12 18:41:13 -03:00
931d6c280a chore(tests): add test for copy operation with blacklist
I almost 💀 because no tests used this x.x

Signed-off-by: flow <flowlnlnln@gmail.com>
2022-09-12 13:12:55 -03:00
ee0fb2d0e0 fix: use std::wstring for Windows filenames
Signed-off-by: flow <flowlnlnln@gmail.com>
2022-09-12 13:07:24 -03:00
c496ad1237 chore: make DirNameFromString add normal duplicate identifier
Wrap the number in parenthesis to be similar to other software.

Signed-off-by: flow <flowlnlnln@gmail.com>
2022-09-12 13:07:24 -03:00
277fa21f5f refactor: remove Win32 'crap' in FileSystem
We should use std::filesystem symlink and hardlink functions instead.

Signed-off-by: flow <flowlnlnln@gmail.com>
2022-09-12 13:07:23 -03:00
1cf949226e refactor: use std::filesystem for overrides
Signed-off-by: flow <flowlnlnln@gmail.com>
2022-09-12 13:07:23 -03:00
be3fae6511 refactor: use std::filesystem for path deletion
Signed-off-by: flow <flowlnlnln@gmail.com>
2022-09-12 13:07:23 -03:00
5932f36285 refactor: use std::filesystem for file copy
Signed-off-by: flow <flowlnlnln@gmail.com>
2022-09-12 13:07:23 -03:00
30abb65368 Merge pull request #1133 from Scrumplex/refactor-tests
Move tests to a separate folder, to fix issues and improve maintenance
2022-09-12 12:57:55 -03:00
64a06b5ed6 Merge pull request #1123 from flowln/fix_abort_inst 2022-09-12 17:11:19 +05:30
69d18f17a5 fix(actions, win): only copy openssl libs on qt5 builds (#1130) 2022-09-12 07:57:18 -03:00
4c7d3a103c refactor: restructure tests
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2022-09-11 22:29:01 +02:00
10320bdeb4 Merge pull request #1129 from dada513/metainfo_fix
Fixes FlatHub's image metadata for the 1.4.2 release
2022-09-11 09:39:21 -03:00
4261dcff39 fix meta
Signed-off-by: dada513 <dada513@protonmail.com>
2022-09-11 10:45:42 +02:00
a091245793 fix: emit signals when aborting NetJob
Signed-off-by: flow <flowlnlnln@gmail.com>
2022-09-10 09:10:16 -03:00
ca282f9fb3 Merge pull request #1117 from flowln/fix_updater
Fix the mod updater not working as intended
2022-09-08 09:28:05 +02:00
7cf2c3be0f fix: start at least one task in ConcurrentTask
This allows us to emit all the necessary stuff when we're finished in
the case of starting a task with no subtasks. In particular, this caused
the mod updater to not work properly :)

Signed-off-by: flow <flowlnlnln@gmail.com>
2022-09-07 12:11:42 -03:00
f65d506f26 Merge pull request #997 from flowln/fix_major_version_filter 2022-09-07 10:34:50 -03:00
333dbca01e Merge pull request #1105 from flowln/better_resource_packs
Add basic resource pack parsing and fix issues
2022-09-07 08:30:36 -03:00
42eb265624 refactor: create mod pages and filter widget by factory methods
This takes most expensive operations out of the constructors.

Signed-off-by: flow <flowlnlnln@gmail.com>
2022-09-07 08:29:58 -03:00
8a65726e9d fix: use more robust method of finding matches for major version
This uses the proper version list to find all MC versions matching the
major number (_don't say anything about SemVer_ 🔫).

Signed-off-by: flow <flowlnlnln@gmail.com>
2022-09-07 08:27:53 -03:00
1b0ca47682 Merge pull request #939 from flowln/mod_downloader_improve
Some more UI / UX improvements to the mod downloader!
2022-09-07 08:27:11 -03:00
8e3f5c3305 Merge pull request #966 from flowln/refactor_tasks
Reduce code duplication in tasks, fix some bugs and add some tests
2022-09-07 08:26:28 -03:00
3c0a6987cd Merge pull request #1113 from timoreo22/develop
Fix compilation warning due to uninitiated variables.
2022-09-06 18:50:46 -03:00
e37f70b9f7 Merge pull request #1114 from DioEgizio/bump-installqtaction-v3 2022-09-06 20:36:35 +05:30
03c148ce50 chore: update install-qt-action to v3
Signed-off-by: DioEgizio <83089242+DioEgizio@users.noreply.github.com>
2022-09-06 15:41:32 +02:00
4817f0312d Fixed up a warning
Signed-off-by: timoreo <contact@timoreo.fr>
2022-09-06 14:32:19 +02:00
b70a82c609 Merge pull request #1111 from PolyMC/revert-1067-classpath-epicness 2022-09-05 20:06:33 +02:00
25d1e0c4e6 Merge pull request #1107 from DioEgizio/smaller-about 2022-09-05 17:52:16 +02:00
8e3356f11a Merge pull request #1034 from Scrumplex/detect-performance-features 2022-09-05 17:45:17 +02:00
1b559c7776 Revert "Move classpath definition into NewLaunch itself"
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2022-09-05 17:37:10 +02:00
d5583f0f02 make the about dialog smaller
Signed-off-by: DioEgizio <83089242+DioEgizio@users.noreply.github.com>
2022-09-04 14:32:33 +02:00
bedd3c50b6 fix: improve handling of unrecognized pack formats
Signed-off-by: flow <flowlnlnln@gmail.com>
2022-09-03 15:05:23 -03:00
43a7af3f44 fix: removing mods with their metadata as well
Signed-off-by: flow <flowlnlnln@gmail.com>
2022-09-03 13:37:23 -03:00
9db27c6acc fix: crash when adding resource packs directly in the folder
This fixes an issue in which, when adding a new resource pack externally
to PolyMC, when the resource pack view was open, would crash poly.

Signed-off-by: flow <flowlnlnln@gmail.com>
2022-09-03 13:37:22 -03:00
42c81395b3 fix: race condition on ResourceFolderModel tests
This (hopefully) fixes the race contiditions that sometimes got
triggered in tests.

Signed-off-by: flow <flowlnlnln@gmail.com>
2022-09-03 13:37:22 -03:00
3b13e692d2 feat: move resource pack images to QPixmapCache
This takes care of evicting entries when the cache gets too big for us,
so we can add new entries without much worries.

Signed-off-by: flow <flowlnlnln@gmail.com>
2022-09-03 13:37:22 -03:00
0331f5a1eb feat(tests): add tests for resource pack parsing
Signed-off-by: flow <flowlnlnln@gmail.com>
2022-09-03 13:37:22 -03:00
8a7e117f6b refactor: move resource pack file parsing utilities to separate namespace
This makes it easier to use that logic in other contexts.

Signed-off-by: flow <flowlnlnln@gmail.com>
2022-09-03 13:37:22 -03:00
9b984cedac feat: add image from pack.png to resource packs
Signed-off-by: flow <flowlnlnln@gmail.com>
2022-09-03 13:37:22 -03:00
dd9e30b24a feat: add resource icon to InfoFrame
Signed-off-by: flow <flowlnlnln@gmail.com>
2022-09-03 13:37:21 -03:00
6a93688b2e fix: filtering in regex search in resource packs
Signed-off-by: flow <flowlnlnln@gmail.com>
2022-09-03 13:37:21 -03:00
3ab17a97a8 fix: sorting by pack format
Signed-off-by: flow <flowlnlnln@gmail.com>
2022-09-03 13:37:21 -03:00
f21ae66265 feat: add basic resource pack parsing of pack.mcmeta
This parses the pack format ID and the description from the local file,
from both a ZIP and a folder, and hooks it into the model.

Signed-off-by: flow <flowlnlnln@gmail.com>
2022-09-03 13:37:21 -03:00
afa1a5e932 feat: modify InfoFrame and ResourcePackPage to show ResourcePack info
Signed-off-by: flow <flowlnlnln@gmail.com>
2022-09-03 13:37:21 -03:00
050768c266 feat: add more resource pack info
Adds pack format id and description to ResourcePack, that'll be parsed
from pack.mcmeta.

Signed-off-by: flow <flowlnlnln@gmail.com>
2022-09-03 13:37:21 -03:00
cda2bfc240 feat: allow specifying factory for resources in BasicFolderLoadTask
This allows us to hook our own resource type, that possibly has more
content than the base Resource, to it.

Signed-off-by: flow <flowlnlnln@gmail.com>
2022-09-03 13:37:20 -03:00
2f167b1512 Merge pull request #1095 from flowln/ensure_file_path_in_override 2022-09-01 09:54:22 +02:00
ba3ac85356 Merge pull request #1067 from Scrumplex/classpath-epicness
Move classpath definition into NewLaunch itself
2022-08-31 18:28:29 -03:00
ec29cedeb7 Merge pull request #1080 from flowln/eternal_cache
Never invalidate libraries cache entries by time elapsed
2022-08-31 18:28:07 -03:00
064ae49d2b fix: make MultipleOptionsTask inherit directly from SequentialTask
It's not a good idea to have multiple concurrent tasks running on a
sequential thing like this one.

Signed-off-by: flow <flowlnlnln@gmail.com>
2022-08-28 16:29:02 -03:00
247f99ce2f feat(test): add more tests to Tasks
Signed-off-by: flow <flowlnlnln@gmail.com>
2022-08-28 16:29:01 -03:00
7b6d269904 refactor: make NetJob inherit from ConcurrentTask as well!
Avoids lots of code duplication

Signed-off-by: flow <flowlnlnln@gmail.com>
2022-08-28 16:29:01 -03:00
87a0482b8b refactor: make MultipleOptionsTask inherit from ConcurrentTask too
Signed-off-by: flow <flowlnlnln@gmail.com>
2022-08-28 16:29:01 -03:00
e899699918 refactor: make SequentialTask inherit from ConcurrentTask
In a way, sequential tasks are just concurrent tasks with only a single
task running concurrently, so we can remove LOTS of duplicated logic :)

Signed-off-by: flow <flowlnlnln@gmail.com>
2022-08-28 16:29:01 -03:00
bdf464e792 fix: abort logic running subsequent tasks anyways some times
Signed-off-by: flow <flowlnlnln@gmail.com>
2022-08-28 16:29:01 -03:00
c410bb4ecb fix: 'succeeded while not running' spam in ConcurrentTask
Signed-off-by: flow <flowlnlnln@gmail.com>
2022-08-28 16:29:01 -03:00
a720bcc637 fix: bogus progress update when the total step progress was zero
Signed-off-by: flow <flowlnlnln@gmail.com>
2022-08-28 16:29:01 -03:00
369a8cdc74 fix: only try to start tasks that are really there
This fixes an annoying issue where concurrent tasks would try to start
multiple tasks even when there was not that many tasks to run in the
first place, causing some amount of log spam.

Signed-off-by: flow <flowlnlnln@gmail.com>
2022-08-28 16:29:00 -03:00
3f4e55be4f fix: ensure destination file paths exist when overriding folders
Signed-off-by: flow <flowlnlnln@gmail.com>
2022-08-28 16:28:23 -03:00
9171f471ab Merge pull request #1094 from flowln/fix_the_thing
Fix build due to merge without rebase messing things up :p
2022-08-28 16:27:41 -03:00
2186b134a4 fix: Mod type enum -> Resource type enum
Signed-off-by: flow <flowlnlnln@gmail.com>
2022-08-28 14:47:52 -03:00
f371ec210c Merge pull request #1052 from flowln/resource_model 2022-08-28 16:52:53 +02:00
afcd669d2f Merge pull request #965 from flowln/fat_files_in_memory
Refactor a bit EnsureMetadataTask and calculate hashes in a incremental manner
2022-08-28 11:03:12 +02:00
fbf542d205 Merge pull request #1087 from DioEgizio/fix-ftblegacy-url
fix: fix urls on ftb legacy
2022-08-24 20:37:07 -03:00
13184eb8e9 fix: fix urls on ftb legacy
Signed-off-by: DioEgizio <83089242+DioEgizio@users.noreply.github.com>
2022-08-24 12:31:38 +02:00
ddf1e1ccee fix: make FML libraries cache eternal
Signed-off-by: flow <flowlnlnln@gmail.com>
2022-08-21 13:47:49 -03:00
5ac4e73697 fix: make libraries cache eternal
This restores the behavior prior to PR #920.

Signed-off-by: flow <flowlnlnln@gmail.com>
2022-08-21 13:47:49 -03:00
6be59b53f1 feat: add eternal cache entries
Those are entries that don't get stale over time, so we don't invalidate
them if they 'expire'.

Signed-off-by: flow <flowlnlnln@gmail.com>
2022-08-21 13:47:49 -03:00
bb54fec907 Merge pull request #1073 from DioEgizio/update-copying
fix(COPYING): fix COPYING.md by adding some missing copyright notices
2022-08-21 13:09:30 -03:00
0b81b283bf fix: LGTM warnings
Signed-off-by: flow <flowlnlnln@gmail.com>
2022-08-20 10:49:56 -03:00
e2ab2aea32 change: add enable/disable to resources
TIL that zip resource packs, when disabled, actually have the effect of
not showing up in the game at all. Since this can be useful to someone,
I moved the logic for it to the resources.

Signed-off-by: flow <flowlnlnln@gmail.com>
2022-08-20 10:49:54 -03:00
c3ceefbafb refactor+fix: add new tests for Resource models and fix issues
Signed-off-by: flow <flowlnlnln@gmail.com>
2022-08-20 10:49:23 -03:00
e7cf9932a9 refactor: simplify Mod structure
No need to keep track of pointers left and right. A single one already
gives enough headaches!

Signed-off-by: flow <flowlnlnln@gmail.com>
2022-08-20 10:48:51 -03:00
0c9d03f5df fix(tests): add timeout on ModFolderModel's tests
If the update never ends, the signal is not emitted and we become stuck
in the event loop forever. So a very lenient timer is added to prevent
that.

Signed-off-by: flow <flowlnlnln@gmail.com>
2022-08-20 10:48:01 -03:00
92aa24ae34 fix: don't give shared pointer to obj. external to the model
It causes some weird problems and adds refcounting overhead.

Signed-off-by: flow <flowlnlnln@gmail.com>
2022-08-20 10:48:00 -03:00
97a74d5c1f refactor: adapt rest of the codebase to the new resource model
In order to access the ModFolderModel from the ModFolderPage, i created
a new m_model for the correct type, shadowing the m_model of type
ResourceFolderModel. This creates two shared_ptr references to the same object,
but since they will have the same lifetime, it doesn't generate a memory
leak.

Signed-off-by: flow <flowlnlnln@gmail.com>
2022-08-20 10:47:58 -03:00
256f8094f5 refactor: make Resource Pack model inherit from ResourceFolderModel
Signed-off-by: flow <flowlnlnln@gmail.com>
2022-08-20 10:47:11 -03:00
1e2f0ab308 refactor: move more tied logic to model and move logic to the resources
This moves the QSortFilterProxyModel to the resource model files,
acessible via a factory method, and moves the sorting and filtering to
the objects themselves, decoupling the code a bit.

This also adds a basic implementation of methods in the
ResourceFolderModel, simplifying the process of constructing a new model
from it.

Signed-off-by: flow <flowlnlnln@gmail.com>
2022-08-20 10:47:08 -03:00
af2cf2734d refactor: move things around in the mod model
Makes the method order in the cpp file the same as in the header file.

Signed-off-by: flow <flowlnlnln@gmail.com>
2022-08-20 10:46:33 -03:00
ec62d8e973 refactor: move general code from mod model to its own model
This aims to continue decoupling other types of resources (e.g. resource
packs, shader packs, etc) from mods, so that we don't have to
continuously watch our backs for changes to one of them affecting the
others.

To do so, this creates a more general list model for resources, based on
the mods one, that allows you to extend it with functionality for other
resources.

I had to do some template and preprocessor stuff to get around the
QObject limitation of not allowing templated classes, so that's sadge :c

On the other hand, I tried cleaning up most general-purpose code in the
mod model, and added some documentation, because it looks nice :D

Signed-off-by: flow <flowlnlnln@gmail.com>
2022-08-20 10:45:01 -03:00
3225f514f6 refactor: move general info from Mod to Resource
This allows us to create other resources that are not Mods, but can
still share a significant portion of code.

Signed-off-by: flow <flowlnlnln@gmail.com>
2022-08-20 10:41:59 -03:00
2d63c86022 feat: make Task a QRunnable
This makes it possible to run a task in another thread.

I added a variable to toggle debug prints because they seem to trigger
an assertion on Qt internals when the task in on another thread. Of
course, this isn't awesome, but can wait until we improve our logging.

Signed-off-by: flow <flowlnlnln@gmail.com>
2022-08-20 10:41:59 -03:00
2dcff83be7 Merge pull request #1035 from Scrumplex/fix-coremods
Make Coremods / Mods seperation more clear
2022-08-20 10:15:50 -03:00
afb9ebcd99 fix: distinguish Coremods
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2022-08-20 12:53:13 +02:00
92d7e44525 Merge pull request #878 from flowln/lazy_settings 2022-08-20 12:50:56 +02:00
a517f442ea Merge pull request #1023 from flowln/better_shared_ptr 2022-08-20 12:50:50 +02:00
311758233b Merge pull request #1044 from flowln/better_orphan_fix 2022-08-20 12:50:43 +02:00
6e086eb808 Merge pull request #992 from Scrumplex/refactor-version 2022-08-20 12:50:25 +02:00
7e8644430c Merge pull request #1007 from Gingeh/disable-update-button 2022-08-20 12:50:19 +02:00
70a8f6743a Merge pull request #919 from kumquat-ir/download-all-blocked 2022-08-20 12:50:01 +02:00
69eafd0e11 Merge pull request #1058 from DioEgizio/fix-update-org.polymc.PolyMC.metainfo.xml.in 2022-08-19 20:34:11 +02:00
6b6a095b91 fix(COPYING): fix COPYING.md by adding some missing copyright notices
Signed-off-by: DioEgizio <83089242+DioEgizio@users.noreply.github.com>
2022-08-19 18:42:26 +02:00
d5a2185030 Merge pull request #1068 from TayouVR/improvedWindowsJavaCheck 2022-08-19 14:26:36 +02:00
26f31e9288 use qEnvironmentVariable instead of qgetenv in JavaUtils
Signed-off-by: Tayou <tayou@gmx.net>
2022-08-18 23:59:35 +02:00
e654e66839 Merge pull request #1049 from flowln/waiting_for_news_-_- 2022-08-18 22:53:41 +02:00
bb4861cf0d check for java installs in PATH on windows
this should find java installs from scoop as well as any other installer, that registers java in the PATH environment variable.

Signed-off-by: Tayou <tayou@gmx.net>
2022-08-18 18:24:32 +02:00
01505910f4 refactor: move classpath definition into NewLaunch itself
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2022-08-18 18:14:01 +02:00
ab766a0598 Merge pull request #968 from magneticflux-/utf8-logging
Decode process lines as UTF-8
2022-08-18 10:44:01 +02:00
51c664a678 fix: update org.polymc.PolyMC.metainfo.xml.in to not make flatpak break next release
Signed-off-by: DioEgizio <83089242+DioEgizio@users.noreply.github.com>
2022-08-15 20:34:56 +02:00
3c4b45c9e7 Use C locale codec for decoding
This should correctly decode multi-byte non-UTF-8 text, such as Windows-936 (Simplified Chinese)

Signed-off-by: Mitchell Skaggs <skaggsm333@gmail.com>
2022-08-13 10:39:05 -05:00
93507a263b fix: hide 'More news...' button if the news aren't loaded yet
Signed-off-by: flow <flowlnlnln@gmail.com>
2022-08-12 17:41:11 -03:00
1175461030 refactor: switch to new versioning scheme
The new versioning system is based on the versioning system used by the
GNOME Foundation for the GNOME desktop.

We are dropping the "major version" as defined by SemVer and move to a
version number with a most and least significant number.

The most significant number must be incremented, if there are new
features or significant changes since last major release.

Otherwise, the least significant number must be incremented, if there
are only minor changes since the last release. New features or
significant changes mustn't be introduced by a bump of the least
significant number.

If a minor change would introduce small user-facing changes (like a
message-box or slight UI changes), it could still be classified as a
minor change.
At the end of the day, a human shall decide, if a change is minor or
significant, as there is no clear line that would separate a "minor" and
a "significant" change in a GUI-application.

Definitions:

feature: New user-facing functionality
significant change: Something that changes user-facing behavior
minor change: Something that fixes unexpected behavior

Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2022-08-12 14:22:24 +02:00
2f5e55bea0 fix: only remove orphaned metadata on first opening
This avoids deleting the metadata while one is updating their mods.

Signed-off-by: flow <flowlnlnln@gmail.com>
2022-08-11 13:11:56 -03:00
c375e7b4df Merge pull request #897 from jamierocks/atl-updating-initial 2022-08-11 08:50:05 +02:00
5d188c69ed Merge pull request #1039 from budak7273/fix-world-safety-nag-title-text 2022-08-11 07:33:13 +02:00
6bff7751d0 Merge pull request #909 from txtsd/markdownlint 2022-08-11 07:33:04 +02:00
1a5986abe0 Merge pull request #920 from flowln/metacache_fix 2022-08-11 07:32:43 +02:00
cebac3c10e Make new title strings translatable
Signed-off-by: Robb <computerguy440+gh@gmail.com>
2022-08-10 12:07:24 -05:00
a5da3db966 Merge pull request #1018 from Scrumplex/fix-infinite-auth-loop 2022-08-10 18:14:26 +02:00
cd30f75173 fix: Make world safety nag title text match the action being performed instead of always saying 'Copy World'
Signed-off-by: Robb <computerguy440+gh@gmail.com>
2022-08-09 16:01:21 -05:00
94df4ceb36 Fix use of Qt 5.14 enum
Signed-off-by: Mitchell Skaggs <skaggsm333@gmail.com>
2022-08-09 00:17:53 -05:00
a14476c5fb Replace local 8-bit decoding with UTF-8 decoding
Handles incomplete byte sequences using `QTextDecoder`

Signed-off-by: Mitchell Skaggs <skaggsm333@gmail.com>
2022-08-08 23:54:01 -05:00
d82bb29919 fix: don't apply GameMode/MangoHud, if they aren't supported
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2022-08-08 21:19:46 +02:00
33af0c6a7c refactor: don't include mangohud's library path
This could cause issues on some environments. Users should just put
MangoHud libs into global LD_LIBRARY_PATH, just like with any other
library

Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2022-08-08 21:16:37 +02:00
68f3f98bc3 feat: detect GameMode and MangoHud's presence
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2022-08-08 21:16:37 +02:00
f873cd5b1a refactor: store current capabilities
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2022-08-08 21:16:37 +02:00
fa8df286d9 chore(ci): Add markdownlint config to ignored paths
Signed-off-by: txtsd <thexerothermicsclerodermoid@gmail.com>
2022-08-06 13:00:57 +05:30
76aa0c434a feat(markdown): Add markdownlint config
Signed-off-by: txtsd <thexerothermicsclerodermoid@gmail.com>
2022-08-06 13:00:57 +05:30
78dc0cfdf3 chore(markdown): MD001 Heading levels should only increment by one level at a time
Signed-off-by: txtsd <thexerothermicsclerodermoid@gmail.com>
2022-08-06 13:00:57 +05:30
9654728bfb chore(markdown): Align inline HTML correctly
Signed-off-by: txtsd <thexerothermicsclerodermoid@gmail.com>
2022-08-06 13:00:57 +05:30
123d1864f4 chore(markdown): MD037 Spaces inside emphasis markers
Signed-off-by: txtsd <thexerothermicsclerodermoid@gmail.com>
2022-08-06 13:00:57 +05:30
96a91e988d chore(markdown): MD010 Hard tabs
Signed-off-by: txtsd <thexerothermicsclerodermoid@gmail.com>
2022-08-06 13:00:56 +05:30
19ecb1701e chore(markdown): MD031 Fenced code blocks should be surrounded by blank lines
Signed-off-by: txtsd <thexerothermicsclerodermoid@gmail.com>
2022-08-06 13:00:56 +05:30
8085b2728d chore(markdown): MD032 Lists should be surrounded by blank lines
Signed-off-by: txtsd <thexerothermicsclerodermoid@gmail.com>
2022-08-06 13:00:56 +05:30
56cad31a36 chore(markdown): MD034 Bare URL used
Signed-off-by: txtsd <thexerothermicsclerodermoid@gmail.com>
2022-08-06 13:00:46 +05:30
3275bc4e93 chore(markdown): MD009 Trailing spaces
Signed-off-by: txtsd <thexerothermicsclerodermoid@gmail.com>
2022-08-06 12:57:30 +05:30
8963378039 chore(markdown): MD007 Unordered list indentation
Signed-off-by: txtsd <thexerothermicsclerodermoid@gmail.com>
2022-08-06 12:57:30 +05:30
c7d435bb7a chore(markdown): MD025 Multiple top-level headings in the same document
Signed-off-by: txtsd <thexerothermicsclerodermoid@gmail.com>
2022-08-06 12:57:11 +05:30
06cc7e4ea0 chore(markdown): MD046 Code block style
Signed-off-by: txtsd <thexerothermicsclerodermoid@gmail.com>
2022-08-06 12:55:11 +05:30
fba20e2cfb chore(markdown): MD040 Fenced code blocks should have a language specified
Signed-off-by: txtsd <thexerothermicsclerodermoid@gmail.com>
2022-08-06 12:55:11 +05:30
358f080c76 chore(markdown): MD012 Multiple consecutive blank lines
Signed-off-by: txtsd <thexerothermicsclerodermoid@gmail.com>
2022-08-06 12:55:11 +05:30
8cea57ff0f chore(markdown): MD022 Headings should be surrounded by blank lines
Signed-off-by: txtsd <thexerothermicsclerodermoid@gmail.com>
2022-08-06 12:53:50 +05:30
7b27f200b1 fix: don't mutate QHash while iterating over it
Even though it was using a QMutableHashIterator, sometimes it didn't
work quite well, so this is a bit better.

Signed-off-by: flow <flowlnlnln@gmail.com>
2022-08-05 16:30:12 -03:00
f4b207220c fix: add some more nullptr checks / protection
die sigsegv 🔫

Signed-off-by: flow <flowlnlnln@gmail.com>
2022-08-05 15:10:44 -03:00
d835e1d14e refactor: simplify smart pointers more
Signed-off-by: flow <flowlnlnln@gmail.com>
2022-08-05 11:38:46 -03:00
75f92de8f8 Merge pull request #1017 from flowln/kill_orphan_metadata
Remove orphaned metadata to avoid problems with auto-updating instances
2022-08-04 12:57:20 -07:00
293c1deee5 Merge pull request #1014 from DioEgizio/downgrade-qt-macos
chore: downgrade to Qt 6.3.0 on macos
2022-08-04 12:56:55 -07:00
4dee05a967 Merge pull request #1006 from DioEgizio/appimage-ubuntu-moment
fix: work around ubuntu 22.04 openssl appimage issues by copying openssl libs
2022-08-04 12:56:38 -07:00
8d6414d74a Merge pull request #1019 from Scrumplex/fix-openbsd-root
Add root path detection on OpenBSD
2022-08-04 21:47:35 +02:00
362ecdb583 refactor+fix: use QSharedPointer for shared_qobject_ptr
Signed-off-by: flow <flowlnlnln@gmail.com>
2022-08-04 15:33:51 -03:00
058b9f9272 Merge pull request #994 from Scrumplex/fix-winget-releaser
Fix WinGet releaser
2022-08-04 16:20:23 +01:00
355762aa30 fix: emit abort in LaunchController
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2022-08-04 10:07:36 +02:00
be4fb65470 fix: Add root path detection on OpenBSD
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2022-08-03 21:14:32 +02:00
4ed296bad4 fix: allow user to interrupt launch after 3 tries
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2022-08-03 20:38:40 +02:00
a8aa862919 Move large condition into a new lambda
Signed-off-by: Gingeh <39150378+Gingeh@users.noreply.github.com>
2022-08-03 16:39:30 +10:00
31ba1de53b fix: remove orphaned metadata to avoid problems with auto-updating insts
Just as my master has taught me. 🔫

Signed-off-by: flow <flowlnlnln@gmail.com>
2022-08-02 16:15:39 -03:00
bca1fef2b2 chore: downgrade to Qt 6.3.0 on macos
seems to fix some emoji-related issues

Signed-off-by: DioEgizio <83089242+DioEgizio@users.noreply.github.com>
2022-08-02 10:59:54 +02:00
f33b31e048 Check for running instance when re-opening the mod folder page and when selecting mods
Signed-off-by: Gingeh <39150378+Gingeh@users.noreply.github.com>
2022-08-02 14:14:45 +10:00
0d10ebb7ca Update launcher/ui/pages/instance/ModFolderPage.h
Co-authored-by: flow <flowlnlnln@gmail.com>
Signed-off-by: Gingeh <39150378+Gingeh@users.noreply.github.com>
2022-08-02 12:50:25 +10:00
4a8abc948e fix: prevent segfault due to callbacks into deleted objects
Since network requests are, for the most part, asynchronous, there's a
chance a request only comes through after the request sender has already
been deleted.

This adds a global (read static) hash table relating models for the mod
downloader to their status (true = alive, false = destroyed). It is a
bit of a hack, but I couldn't come up with a better way of doing this.

To reproduce the issue before this commit: scroll really quickly through
CF mods, to trigger network requests for their versions and description.
Then, in the middle of it close the mod downloader. Sometimes this will
create a crash.

Signed-off-by: flow <flowlnlnln@gmail.com>
2022-08-01 18:34:15 -03:00
6fd3672618 Merge pull request #1012 from DioEgizio/patch-10
fix: remove iconfix from libraries/README.MD
2022-08-01 20:31:11 +02:00
abd090bd48 fix: remove iconfix from libraries/README.MD
someone forgor (💀) to remove it

Signed-off-by: DioEgizio <83089242+DioEgizio@users.noreply.github.com>
2022-08-01 20:21:19 +02:00
bd9140f1f3 Merge pull request #1008 from DioEgizio/qt-version-issue-template
chore: update issue template to ask about Qt version
2022-08-01 18:40:11 +02:00
9d78b2d259 Update .github/ISSUE_TEMPLATE/bug_report.yml
Signed-off-by: DioEgizio <83089242+DioEgizio@users.noreply.github.com>
Co-authored-by: flow <flowlnlnln@gmail.com>
2022-08-01 14:51:19 +02:00
9c9528838a chore: update issue template to ask about Qt version
Signed-off-by: DioEgizio <83089242+DioEgizio@users.noreply.github.com>
2022-08-01 14:40:55 +02:00
77b640b76b Disable "Check for Updates" and "Download Mods" while the game is running
Signed-off-by: Gingeh <39150378+Gingeh@users.noreply.github.com>
2022-08-01 20:56:05 +10:00
a8dfe98b1a Disable "Check for Updates" if all mods are removed
Signed-off-by: Gingeh <39150378+Gingeh@users.noreply.github.com>
2022-08-01 20:56:05 +10:00
cee41b87f7 fix(ui): force redraw of mod list when (de)selecting a mod
Signed-off-by: flow <flowlnlnln@gmail.com>
2022-08-01 07:33:31 -03:00
7a95314e42 feat(ui): remember mod download dialog's geometry
Makes it consistent with other modal dialogs.

Signed-off-by: flow <flowlnlnln@gmail.com>
2022-08-01 07:33:31 -03:00
6aaf1f4f21 feat: lazy-load CF mod descriptions
Signed-off-by: flow <flowlnlnln@gmail.com>
2022-08-01 07:33:30 -03:00
368a0ddd44 feat: add mod descriptions to CF mods
Signed-off-by: flow <flowlnlnln@gmail.com>
2022-08-01 07:33:30 -03:00
0808a10b7b feat: cache mod versions
Signed-off-by: flow <flowlnlnln@gmail.com>
2022-08-01 07:33:30 -03:00
6f052baa94 refactor: use function cb instead of class cb in getVersions
I've discovered even more functional programming! :^)

Signed-off-by: flow <flowlnlnln@gmail.com>
2022-08-01 07:33:30 -03:00
5bc67d3f6b feat: cache extra mod info (like links and body)
Signed-off-by: flow <flowlnlnln@gmail.com>
2022-08-01 07:33:30 -03:00
74c6c5cfbc refactor: use function cb instead of class cb in getModInfo
I've discovered functional programming :^)
This makes this route more fit for general use.

Signed-off-by: flow <flowlnlnln@gmail.com>
2022-08-01 07:33:30 -03:00
158b7fd166 feat+refactor: clean up ProgressWidget and add progress indicatior to
mod downloader

Signed-off-by: flow <flowlnlnln@gmail.com>
2022-08-01 07:33:30 -03:00
c3f647dc96 feat: add (semi) instant searching in mod downloader
It has a delay of 350ms from the last typed character to search, in
order to cache small changes while typing.

Signed-off-by: flow <flowlnlnln@gmail.com>
2022-08-01 07:33:30 -03:00
5936c7b65c change: preserve search term across different mod providers
Signed-off-by: flow <flowlnlnln@gmail.com>
2022-08-01 07:33:29 -03:00
a8bcd85c93 feat+refactor: add shortcuts to mod downloader and clean up
Signed-off-by: flow <flowlnlnln@gmail.com>
2022-08-01 07:33:29 -03:00
127b558f95 change: change button names to be more user-friendly
Signed-off-by: flow <flowlnlnln@gmail.com>
2022-08-01 07:33:29 -03:00
6e9a27f40f feat: display the 'body' of a MR mod on the mod downloader
Signed-off-by: flow <flowlnlnln@gmail.com>
2022-08-01 07:33:29 -03:00
4a13dbe3bb feat: create delegate for project item views
This allows us to define custom painting for list view items. In
particular, this is applied to the mod downloader, in order to allow
displaying both the mod name and mod description, and settings their
effects (like bold or underline) independent of each other.

Signed-off-by: flow <flowlnlnln@gmail.com>
2022-08-01 07:33:29 -03:00
0f61f5ba03 fix(ui): missing tr() in mod download dialog's title
Signed-off-by: flow <flowlnlnln@gmail.com>
2022-08-01 07:33:29 -03:00
5f1efbeb67 fix: work around ubuntu 22.04 openssl appimage issues by copying openssl libs
terrible hack but it works™️

Signed-off-by: DioEgizio <83089242+DioEgizio@users.noreply.github.com>
2022-08-01 09:57:14 +02:00
9c105914f0 use BlockedModsDialog for ftb packs as well
Signed-off-by: kumquat-ir <66188216+kumquat-ir@users.noreply.github.com>
2022-07-31 15:05:47 -04:00
579582740e Merge remote-tracking branch 'origin/develop' into download-all-blocked
Signed-off-by: kumquat-ir <66188216+kumquat-ir@users.noreply.github.com>
2022-07-31 14:54:50 -04:00
b15544c163 Trash instances instead of deleting (when possible) (#549)
Squashed because of :pofat: commit history
2022-07-30 14:42:33 -03:00
94a63e3859 Merge pull request #941 from Scrumplex/bump-cxx-standard
Bump to C++17
2022-07-30 17:10:59 +01:00
842b7e6c39 use c11 instead
c17 dont work properly with lgtm's build system and c11 is already almost identical to c17 at least in gcc
2022-07-30 15:35:48 +01:00
22f5011451 fix(winget): strictly match non-Legacy setup
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2022-07-29 16:25:12 +02:00
b4e8abd0ad feat: win32 enable dark titlebar for dark theme
Signed-off-by: DavidoTek <54072917+DavidoTek@users.noreply.github.com>
2022-07-26 23:25:17 +02:00
a9e8ed5087 fix: pump events and do a queued start for concurrent tasks
Heavy workloads can consume a ton of time doing their stuff, and starve
the event loop out of events. This adds an event processing call after
every concurrent task has been completed, to decrease the event loop
stravation on such loads.

Signed-off-by: flow <flowlnlnln@gmail.com>
2022-07-24 17:46:54 -03:00
00520b6a0e feat: add hashing tasks to the sequential task in ModUpdateDialog
Signed-off-by: flow <flowlnlnln@gmail.com>
2022-07-24 17:46:54 -03:00
e6f2a3893a refactor+feat: improve code separation in ensure metadata
... and avoid calculating the same hash multiple times

Signed-off-by: flow <flowlnlnln@gmail.com>
2022-07-24 17:46:54 -03:00
24c034ff6a change(libs): use a 4MiB buffer by default in murmur2 hashing
Signed-off-by: flow <flowlnlnln@gmail.com>
2022-07-24 17:46:54 -03:00
631a93bcd8 refactor: add a HashUtils place for hashing stuff
Signed-off-by: flow <flowlnlnln@gmail.com>
2022-07-24 17:46:54 -03:00
b1763353ea feat: do incremental calculation of CF's hash
Signed-off-by: flow <flowlnlnln@gmail.com>
2022-07-24 17:46:53 -03:00
f95bcf45ad feat(libs): add incremental version of murmurhash2 calculation
This does two passes for a given file, which is kinda slow, but I don't
know how else to get the size excluding the filtered ones :<

Signed-off-by: flow <flowlnlnln@gmail.com>
2022-07-24 17:46:53 -03:00
15ec1abb6a feat: use QIODevice for calcuating the JAR hash on Modrinth
Signed-off-by: flow <flowlnlnln@gmail.com>
2022-07-24 17:46:53 -03:00
cfda8dbb2b refactor: use QIODevice instead of a whole QByteArray for hash calc.
This allows Qt to do its thing and optimize the data gathering from the
JAR.

Signed-off-by: flow <flowlnlnln@gmail.com>
2022-07-24 17:46:53 -03:00
ab6e1b112b change(cache): use cache-specific http headers for their lifetime
This uses the 'Age', 'Cache-Control' and 'Expires' HTTP headers to more
accurately set up the cache lifetime, falling back to a static 1-week
time if they're not present in the response.

Signed-off-by: flow <flowlnlnln@gmail.com>
2022-07-21 19:19:24 -03:00
c666c3e251 refactor!: bump to C++17 and C17
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2022-07-20 14:22:10 +02:00
20b1723e78 merge origin/develop
Signed-off-by: kumquat-ir <66188216+kumquat-ir@users.noreply.github.com>
2022-07-18 14:05:23 -04:00
be78afeee5 qtcreator moment
Signed-off-by: kumquat-ir <66188216+kumquat-ir@users.noreply.github.com>
2022-07-18 14:03:06 -04:00
6a1d611fd1 Restore ScrollMessageBox
Signed-off-by: kumquat-ir <66188216+kumquat-ir@users.noreply.github.com>
2022-07-17 02:40:27 -04:00
c8a72c876d fix: add missing HttpMetaCache entry for CF mods
Signed-off-by: flow <flowlnlnln@gmail.com>
2022-07-16 21:25:29 -03:00
ec87a8ddfc fix: add expiration time to cache entries
This is to prevent problems where the cache entry would still be used
way after the remote resource got updated. The limit is hardcoded for 1
week, which I think is a reasonable time, but this could be further
tweaked.

Signed-off-by: flow <flowlnlnln@gmail.com>
2022-07-16 21:25:28 -03:00
33e34ebb83 Add "Open All" button to blocked mods dialog
Signed-off-by: kumquat-ir <66188216+kumquat-ir@users.noreply.github.com>
2022-07-16 19:14:54 -04:00
509f7bd018 fix: move time record overrides to BaseInstance
This is needed so that we can show time stats in the UI without having
to load all type-specific settings, which would make all the previous
changes useless :c

This is apparently done with console settings too, so I don't think
there's a problem doing this too :>

Signed-off-by: flow <flowlnlnln@gmail.com>
2022-07-12 21:15:59 -03:00
10f27250ee DCO Remediation Commit for bf560f4
I, Jamie Mansfield <jmansfield@cadixdev.org>, hereby add my
Signed-off-by to this commit: bf560f4594e4c17b493725f1ac98f0becfff5c2e

Signed-off-by: Jamie Mansfield <jmansfield@cadixdev.org>
2022-07-10 19:14:05 +01:00
aed7963d11 DCO Remediation Commit for a7fc23d
I, Jamie Mansfield <jmansfield@cadixdev.org>, hereby add my
Signed-off-by to this commit: a7fc23dd96981b1bc2449b5bf32f1913b45ecbc8

Signed-off-by: Jamie Mansfield <jmansfield@cadixdev.org>
2022-07-10 19:13:34 +01:00
2810413112 DCO Remediation Commit for 9e69b8f
I, Jamie Mansfield <jmansfield@cadixdev.org>, hereby add my
Signed-off-by to this commit: 9e69b8fe1bf8b325f6c386b7578408da4b775177

Signed-off-by: Jamie Mansfield <jmansfield@cadixdev.org>
2022-07-10 19:12:57 +01:00
31fd92e071 DCO Remediation Commit for e0ae631
I, Jamie Mansfield <jmansfield@cadixdev.org>, hereby add my
Signed-off-by to this commit: e0ae631d59103cd32d758dec76e55b3a40b86be2

Signed-off-by: Jamie Mansfield <jmansfield@cadixdev.org>
2022-07-10 19:12:08 +01:00
bf560f4594 ATLauncher: Move the UI support implementation into it's own class
This will allow it to be used in multiple locations.
2022-07-10 11:27:42 +01:00
a7fc23dd96 ATLauncher: Reset existing directory if required 2022-07-10 11:15:48 +01:00
9e69b8fe1b ATLauncher: Parse keeps and deletes from pack manifests 2022-07-10 11:05:11 +01:00
e0ae631d59 ATLauncher: Add modes to install task and display appropriate message
This will display the update/reinstall message for the installation
method currently in use..
2022-07-10 10:55:05 +01:00
273cf3d565 feat: lazy-load MinecraftInstance settings
Makes the startup go fast!

vrum

Signed-off-by: flow <flowlnlnln@gmail.com>
2022-07-06 17:17:54 -03:00
f432cfd73a change: put settings initialization in a separate function
Signed-off-by: flow <flowlnlnln@gmail.com>
2022-07-06 16:18:09 -03:00
6961a39cd2 feat: Assign java max mem based on system RAM
If the system has <6GB RAM, it uses (system RAM / 1.5)
If the system has >=6GB, it uses 4GB

Signed-off-by: txtsd <code@ihavea.quest>
2022-01-23 02:12:03 +05:30
1045 changed files with 56861 additions and 32250 deletions

1
.envrc Normal file
View File

@ -0,0 +1 @@
use flake

2
.github/FUNDING.yml vendored
View File

@ -1 +1 @@
open_collective: polymc open_collective: prismlauncher

View File

@ -8,9 +8,9 @@ body:
If you need help with running Minecraft, please visit us on our Discord before making a bug report. If you need help with running Minecraft, please visit us on our Discord before making a bug report.
Before submitting a bug report, please make sure you have read this *entire* form, and that: Before submitting a bug report, please make sure you have read this *entire* form, and that:
* You have read the [PolyMC wiki](https://polymc.org/wiki/) and it has not answered your question. * You have read the [Prism Launcher wiki](https://prismlauncher.org/wiki/) and it has not answered your question.
* Your bug is not caused by Minecraft or any mods you have installed. * Your bug is not caused by Minecraft or any mods you have installed.
* Your issue has not been reported before, [make sure to use the search function!](https://github.com/PolyMC/PolyMC/issues) * Your issue has not been reported before, [make sure to use the search function!](https://github.com/PrismLauncher/PrismLauncher/issues)
**Do not forget to give your issue a descriptive title.** "Bug in the instance screen" makes it hard to distinguish issues at a glance. **Do not forget to give your issue a descriptive title.** "Bug in the instance screen" makes it hard to distinguish issues at a glance.
- type: dropdown - type: dropdown
@ -25,9 +25,16 @@ body:
- Other - Other
- type: textarea - type: textarea
attributes: attributes:
label: Version of PolyMC label: Version of Prism Launcher
description: The version of PolyMC used in the bug report. description: The version of Prism Launcher used in the bug report.
placeholder: PolyMC 1.3.2 placeholder: Prism Launcher 5.0
validations:
required: true
- type: textarea
attributes:
label: Version of Qt
description: The version of Qt used in the bug report. You can find it in Help -> About Prism Launcher -> About Qt.
placeholder: Qt 6.3.0
validations: validations:
required: true required: true
- type: textarea - type: textarea

View File

@ -1,5 +1,5 @@
blank_issues_enabled: true blank_issues_enabled: true
contact_links: contact_links:
- name: PolyMC Matrix Support Room - name: Prism Launcher Matrix Support Room
url: https://matrix.to/#/#support:polymc.org url: https://matrix.to/#/#prism-support:matrix.org
about: Please ask for support here before opening an issue. about: Please ask for support here before opening an issue.

View File

@ -6,7 +6,7 @@ body:
- type: markdown - type: markdown
attributes: attributes:
value: | value: |
### Use this form to suggest a larger change for PolyMC. ### Use this form to suggest a larger change for Prism Launcher.
- type: textarea - type: textarea
attributes: attributes:
label: Goal label: Goal
@ -18,7 +18,7 @@ body:
attributes: attributes:
label: Motivation label: Motivation
description: | description: |
Introduce the topic. If this is a not-well-known section of PolyMC, a detailed explanation of the background is recommended. Introduce the topic. If this is a not-well-known section of Prism Launcher, a detailed explanation of the background is recommended.
Some example points of discussion: Some example points of discussion:
- What specific problems are you facing right now that you're trying to address? - What specific problems are you facing right now that you're trying to address?
- Are there any previous discussions? Link to them and summarize them (don't force your readers to read them though!). - Are there any previous discussions? Link to them and summarize them (don't force your readers to read them though!).

View File

@ -5,25 +5,25 @@ body:
- type: markdown - type: markdown
attributes: attributes:
value: | value: |
### Use this form to suggest a feature for PolyMC. ### Use this form to suggest a feature for Prism Launcher.
- type: input - type: input
attributes: attributes:
label: Role label: Role
description: In what way do you use PolyMC that needs this feature? description: In what way do you use Prism Launcher that needs this feature?
placeholder: I play modded Minecraft. placeholder: I play modded Minecraft.
validations: validations:
required: true required: true
- type: input - type: input
attributes: attributes:
label: Suggestion label: Suggestion
description: What do you want PolyMC to do? description: What do you want Prism Launcher to do?
placeholder: I want the cat button to meow. placeholder: I want the cat button to meow.
validations: validations:
required: true required: true
- type: input - type: input
attributes: attributes:
label: Benefit label: Benefit
description: Why do you need PolyMC to do this? description: Why do you need Prism Launcher to do this?
placeholder: so that I can always hear a cat when I need to. placeholder: so that I can always hear a cat when I need to.
validations: validations:
required: true required: true

3
.github/codeql/codeql-config.yml vendored Normal file
View File

@ -0,0 +1,3 @@
query-filters:
- exclude:
id: cpp/fixme-comment

9
.github/pull_request_template.md vendored Normal file
View File

@ -0,0 +1,9 @@
<!--
Hey there! Thanks for your contribution.
Please make sure that your commits are signed off first.
If you don't know how that works, check out our contribution guidelines: https://github.com/PrismLauncher/PrismLauncher/blob/develop/CONTRIBUTING.md#signing-your-work
If you already created your commits, you can run `git rebase --signoff develop` to retroactively sign-off all your commits and `git push --force` to override what you have pushed already.
Note that signing and signing-off are two different things!
-->

View File

@ -7,10 +7,23 @@ on:
description: Type of build (Debug, Release, RelWithDebInfo, MinSizeRel) description: Type of build (Debug, Release, RelWithDebInfo, MinSizeRel)
type: string type: string
default: Debug default: Debug
is_qt_cached:
description: Enable Qt caching or not
type: string
default: true
secrets: secrets:
SPARKLE_ED25519_KEY: SPARKLE_ED25519_KEY:
description: Private key for signing Sparkle updates description: Private key for signing Sparkle updates
required: false required: false
WINDOWS_CODESIGN_CERT:
description: Certificate for signing Windows builds
required: false
WINDOWS_CODESIGN_PASSWORD:
description: Password for signing Windows builds
required: false
CACHIX_AUTH_TOKEN:
description: Private token for authenticating against Cachix cache
required: false
jobs: jobs:
build: build:
@ -25,27 +38,70 @@ jobs:
- os: ubuntu-20.04 - os: ubuntu-20.04
qt_ver: 6 qt_ver: 6
qt_host: linux qt_host: linux
qt_arch: ''
qt_version: '6.2.4' qt_version: '6.2.4'
qt_modules: 'qt5compat qtimageformats' qt_modules: 'qt5compat qtimageformats'
qt_path: /home/runner/work/PolyMC/Qt qt_tools: ''
- os: windows-2022 - os: windows-2022
name: "Windows-Legacy" name: "Windows-MinGW-w64"
msystem: mingw32 msystem: clang64
vcvars_arch: 'amd64_x86'
- os: windows-2022
name: "Windows-MSVC-Legacy"
msystem: ''
architecture: 'win32'
vcvars_arch: 'amd64_x86'
qt_ver: 5 qt_ver: 5
qt_host: windows
qt_arch: 'win32_msvc2019'
qt_version: '5.15.2'
qt_modules: ''
qt_tools: 'tools_openssl_x86'
- os: windows-2022 - os: windows-2022
name: "Windows" name: "Windows-MSVC"
msystem: mingw32 msystem: ''
architecture: 'x64'
vcvars_arch: 'amd64'
qt_ver: 6 qt_ver: 6
qt_host: windows
qt_arch: ''
qt_version: '6.5.1'
qt_modules: 'qt5compat qtimageformats'
qt_tools: ''
- os: windows-2022
name: "Windows-MSVC-arm64"
msystem: ''
architecture: 'arm64'
vcvars_arch: 'amd64_arm64'
qt_ver: 6
qt_host: windows
qt_arch: 'win64_msvc2019_arm64'
qt_version: '6.5.1'
qt_modules: 'qt5compat qtimageformats'
qt_tools: ''
- os: macos-12 - os: macos-12
macosx_deployment_target: 10.14 name: macOS
macosx_deployment_target: 11.0
qt_ver: 6 qt_ver: 6
qt_host: mac qt_host: mac
qt_version: '6.3.1' qt_arch: ''
qt_version: '6.5.0'
qt_modules: 'qt5compat qtimageformats' qt_modules: 'qt5compat qtimageformats'
qt_path: /Users/runner/work/PolyMC/Qt qt_tools: ''
- os: macos-12
name: macOS-Legacy
macosx_deployment_target: 10.13
qt_ver: 5
qt_host: mac
qt_version: '5.15.2'
qt_modules: ''
qt_tools: ''
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}
@ -56,6 +112,7 @@ jobs:
INSTALL_APPIMAGE_DIR: "install-appdir" INSTALL_APPIMAGE_DIR: "install-appdir"
BUILD_DIR: "build" BUILD_DIR: "build"
CCACHE_VAR: "" CCACHE_VAR: ""
HOMEBREW_NO_INSTALLED_DEPENDENTS_CHECK: 1
steps: steps:
## ##
@ -67,34 +124,49 @@ jobs:
submodules: 'true' submodules: 'true'
- name: 'Setup MSYS2' - name: 'Setup MSYS2'
if: runner.os == 'Windows' if: runner.os == 'Windows' && matrix.msystem != ''
uses: msys2/setup-msys2@v2 uses: msys2/setup-msys2@v2
with: with:
msystem: ${{ matrix.msystem }} msystem: ${{ matrix.msystem }}
update: true update: true
install: >- install: >-
git git
mingw-w64-x86_64-binutils
pacboy: >- pacboy: >-
toolchain:p toolchain:p
cmake:p cmake:p
extra-cmake-modules:p extra-cmake-modules:p
ninja:p ninja:p
qt${{ matrix.qt_ver }}-base:p qt6-base:p
qt${{ matrix.qt_ver }}-svg:p qt6-svg:p
qt${{ matrix.qt_ver }}-imageformats:p qt6-imageformats:p
quazip-qt${{ matrix.qt_ver }}:p quazip-qt6:p
ccache:p ccache:p
nsis:p qt6-5compat:p
${{ matrix.qt_ver == 6 && 'qt6-5compat:p' || '' }} cmark:p
- name: Force newer ccache
if: runner.os == 'Windows' && matrix.msystem == '' && inputs.build_type == 'Debug'
run: |
choco install ccache --version 4.7.1
- name: Setup ccache - name: Setup ccache
if: runner.os != 'Windows' && inputs.build_type == 'Debug' if: (runner.os != 'Windows' || matrix.msystem == '') && inputs.build_type == 'Debug'
uses: hendrikmuhs/ccache-action@v1.2.1 uses: hendrikmuhs/ccache-action@v1.2.9
with: with:
key: ${{ matrix.os }}-qt${{ matrix.qt_ver }} key: ${{ matrix.os }}-qt${{ matrix.qt_ver }}-${{ matrix.architecture }}
- name: Setup ccache (Windows) - name: Retrieve ccache cache (Windows MinGW-w64)
if: runner.os == 'Windows' && inputs.build_type == 'Debug' if: runner.os == 'Windows' && matrix.msystem != '' && inputs.build_type == 'Debug'
uses: actions/cache@v3.3.1
with:
path: '${{ github.workspace }}\.ccache'
key: ${{ matrix.os }}-mingw-w64-ccache-${{ github.run_id }}
restore-keys: |
${{ matrix.os }}-mingw-w64-ccache
- name: Setup ccache (Windows MinGW-w64)
if: runner.os == 'Windows' && matrix.msystem != '' && inputs.build_type == 'Debug'
shell: msys2 {0} shell: msys2 {0}
run: | run: |
ccache --set-config=cache_dir='${{ github.workspace }}\.ccache' ccache --set-config=cache_dir='${{ github.workspace }}\.ccache'
@ -109,15 +181,6 @@ jobs:
run: | run: |
echo "CCACHE_VAR=ccache" >> $GITHUB_ENV echo "CCACHE_VAR=ccache" >> $GITHUB_ENV
- name: Retrieve ccache cache (Windows)
if: runner.os == 'Windows' && inputs.build_type == 'Debug'
uses: actions/cache@v3.0.2
with:
path: '${{ github.workspace }}\.ccache'
key: ${{ matrix.os }}-qt${{ matrix.qt_ver }}
restore-keys: |
${{ matrix.os }}-qt${{ matrix.qt_ver }}
- name: Set short version - name: Set short version
shell: bash shell: bash
run: | run: |
@ -140,25 +203,44 @@ jobs:
if: runner.os == 'Linux' && matrix.qt_ver != 6 if: runner.os == 'Linux' && matrix.qt_ver != 6
run: | run: |
sudo apt-get -y install qtbase5-dev qtchooser qt5-qmake qtbase5-dev-tools libqt5core5a libqt5network5 libqt5gui5 sudo apt-get -y install qtbase5-dev qtchooser qt5-qmake qtbase5-dev-tools libqt5core5a libqt5network5 libqt5gui5
- name: Cache Qt (macOS and AppImage)
id: cache-qt
if: matrix.qt_ver == 6 && runner.os != 'Windows'
uses: actions/cache@v3
with:
path: '${{ matrix.qt_path }}/${{ matrix.qt_version }}'
key: ${{ matrix.qt_host }}-${{ matrix.qt_version }}-"${{ matrix.qt_modules }}"-qt_cache
- name: Install Qt (macOS and AppImage) - name: Install host Qt (Windows MSVC arm64)
if: matrix.qt_ver == 6 && runner.os != 'Windows' if: runner.os == 'Windows' && matrix.architecture == 'arm64'
uses: jurplel/install-qt-action@v2 uses: jurplel/install-qt-action@v3
with: with:
aqtversion: '==3.1.*'
py7zrversion: '>=0.20.2'
version: ${{ matrix.qt_version }}
host: 'windows'
target: 'desktop'
arch: ''
modules: ${{ matrix.qt_modules }}
tools: ${{ matrix.qt_tools }}
cache: ${{ inputs.is_qt_cached }}
cache-key-prefix: host-qt-arm64-windows
dir: ${{ github.workspace }}\HostQt
set-env: false
- name: Install Qt (macOS, Linux, Qt 6 & Windows MSVC)
if: runner.os == 'Linux' && matrix.qt_ver == 6 || runner.os == 'macOS' || (runner.os == 'Windows' && matrix.msystem == '')
uses: jurplel/install-qt-action@v3
with:
aqtversion: '==3.1.*'
py7zrversion: '>=0.20.2'
version: ${{ matrix.qt_version }} version: ${{ matrix.qt_version }}
host: ${{ matrix.qt_host }} host: ${{ matrix.qt_host }}
target: 'desktop' target: 'desktop'
arch: ${{ matrix.qt_arch }}
modules: ${{ matrix.qt_modules }} modules: ${{ matrix.qt_modules }}
cached: ${{ steps.cache-qt.outputs.cache-hit }} tools: ${{ matrix.qt_tools }}
aqtversion: ==2.1.* cache: ${{ inputs.is_qt_cached }}
- name: Install MSVC (Windows MSVC)
if: runner.os == 'Windows' # We want this for MinGW builds as well, as we need SignTool
uses: ilammy/msvc-dev-cmd@v1
with:
vsversion: 2022
arch: ${{ matrix.vcvars_arch }}
- name: Prepare AppImage (Linux) - name: Prepare AppImage (Linux)
if: runner.os == 'Linux' && matrix.qt_ver != 5 if: runner.os == 'Linux' && matrix.qt_ver != 5
@ -169,20 +251,45 @@ jobs:
${{ github.workspace }}/.github/scripts/prepare_JREs.sh ${{ github.workspace }}/.github/scripts/prepare_JREs.sh
- 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
## ##
# CONFIGURE # CONFIGURE
## ##
- name: Configure CMake (macOS) - name: Configure CMake (macOS)
if: runner.os == 'macOS' if: runner.os == 'macOS' && matrix.qt_ver == 6
run: | run: |
cmake -S . -B ${{ env.BUILD_DIR }} -DCMAKE_INSTALL_PREFIX=${{ env.INSTALL_DIR }} -DCMAKE_BUILD_TYPE=${{ inputs.build_type }} -DENABLE_LTO=ON -DCMAKE_OSX_ARCHITECTURES="x86_64;arm64" -DLauncher_BUILD_PLATFORM=macOS -DCMAKE_C_COMPILER_LAUNCHER=${{ env.CCACHE_VAR }} -DCMAKE_CXX_COMPILER_LAUNCHER=${{ env.CCACHE_VAR }} -DLauncher_QT_VERSION_MAJOR=${{ matrix.qt_ver }} -G Ninja cmake -S . -B ${{ env.BUILD_DIR }} -DCMAKE_INSTALL_PREFIX=${{ env.INSTALL_DIR }} -DCMAKE_BUILD_TYPE=${{ inputs.build_type }} -DENABLE_LTO=ON -DLauncher_BUILD_PLATFORM=${{ matrix.name }} -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 (Windows) - name: Configure CMake (macOS-Legacy)
if: runner.os == 'Windows' 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_BUILD_PLATFORM=${{ matrix.name }} -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="" -G Ninja
- name: Configure CMake (Windows MinGW-w64)
if: runner.os == 'Windows' && matrix.msystem != ''
shell: msys2 {0} shell: msys2 {0}
run: | run: |
cmake -S . -B ${{ env.BUILD_DIR }} -DCMAKE_INSTALL_PREFIX=${{ env.INSTALL_DIR }} -DCMAKE_BUILD_TYPE=${{ inputs.build_type }} -DENABLE_LTO=ON -DLauncher_BUILD_PLATFORM=${{ matrix.name }} -DCMAKE_C_COMPILER_LAUNCHER=${{ env.CCACHE_VAR }} -DCMAKE_CXX_COMPILER_LAUNCHER=${{ env.CCACHE_VAR }} -DLauncher_QT_VERSION_MAJOR=${{ matrix.qt_ver }} -G Ninja cmake -S . -B ${{ env.BUILD_DIR }} -DCMAKE_INSTALL_PREFIX=${{ env.INSTALL_DIR }} -DCMAKE_BUILD_TYPE=${{ inputs.build_type }} -DENABLE_LTO=ON -DLauncher_BUILD_PLATFORM=${{ matrix.name }} -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 -G Ninja
- name: Configure CMake (Windows MSVC)
if: runner.os == 'Windows' && matrix.msystem == ''
run: |
cmake -S . -B ${{ env.BUILD_DIR }} -DCMAKE_INSTALL_PREFIX=${{ env.INSTALL_DIR }} -DCMAKE_BUILD_TYPE=${{ inputs.build_type }} -DENABLE_LTO=ON -DLauncher_BUILD_PLATFORM=${{ matrix.name }} -DLauncher_QT_VERSION_MAJOR=${{ matrix.qt_ver }} -DCMAKE_MSVC_RUNTIME_LIBRARY="MultiThreadedDLL" -A${{ matrix.architecture}} -DLauncher_FORCE_BUNDLED_LIBS=ON
# 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) - name: Configure CMake (Linux)
if: runner.os == 'Linux' if: runner.os == 'Linux'
@ -198,12 +305,17 @@ jobs:
run: | run: |
cmake --build ${{ env.BUILD_DIR }} cmake --build ${{ env.BUILD_DIR }}
- name: Build (Windows) - name: Build (Windows MinGW-w64)
if: runner.os == 'Windows' if: runner.os == 'Windows' && matrix.msystem != ''
shell: msys2 {0} shell: msys2 {0}
run: | run: |
cmake --build ${{ env.BUILD_DIR }} cmake --build ${{ env.BUILD_DIR }}
- name: Build (Windows MSVC)
if: runner.os == 'Windows' && matrix.msystem == ''
run: |
cmake --build ${{ env.BUILD_DIR }} --config ${{ inputs.build_type }}
## ##
# TEST # TEST
## ##
@ -211,13 +323,18 @@ jobs:
- name: Test - name: Test
if: runner.os != 'Windows' if: runner.os != 'Windows'
run: | run: |
ctest --test-dir build --output-on-failure ctest -E "^example64|example$" --test-dir build --output-on-failure
- name: Test (Windows) - name: Test (Windows MinGW-w64)
if: runner.os == 'Windows' if: runner.os == 'Windows' && matrix.msystem != ''
shell: msys2 {0} shell: msys2 {0}
run: | run: |
ctest --test-dir build --output-on-failure ctest -E "^example64|example$" --test-dir build --output-on-failure
- name: Test (Windows MSVC)
if: runner.os == 'Windows' && matrix.msystem == '' && matrix.architecture != 'arm64'
run: |
ctest -E "^example64|example$" --test-dir build --output-on-failure -C ${{ inputs.build_type }}
## ##
# PACKAGE BUILDS # PACKAGE BUILDS
@ -229,17 +346,18 @@ jobs:
cmake --install ${{ env.BUILD_DIR }} cmake --install ${{ env.BUILD_DIR }}
cd ${{ env.INSTALL_DIR }} cd ${{ env.INSTALL_DIR }}
chmod +x "PolyMC.app/Contents/MacOS/polymc" chmod +x "PrismLauncher.app/Contents/MacOS/prismlauncher"
sudo codesign --sign - --deep --force --entitlements "../program_info/App.entitlements" --options runtime "PolyMC.app/Contents/MacOS/polymc" sudo codesign --sign - --deep --force --entitlements "../program_info/App.entitlements" --options runtime "PrismLauncher.app/Contents/MacOS/prismlauncher"
tar -czf ../PolyMC.tar.gz * mv "PrismLauncher.app" "Prism Launcher.app"
tar -czf ../PrismLauncher.tar.gz *
- name: Make Sparkle signature (macOS) - name: Make Sparkle signature (macOS)
if: runner.os == 'macOS' if: matrix.name == 'macOS'
run: | run: |
if [ '${{ secrets.SPARKLE_ED25519_KEY }}' != '' ]; then if [ '${{ secrets.SPARKLE_ED25519_KEY }}' != '' ]; then
brew install openssl@3 brew install openssl@3
echo '${{ secrets.SPARKLE_ED25519_KEY }}' > ed25519-priv.pem echo '${{ secrets.SPARKLE_ED25519_KEY }}' > ed25519-priv.pem
signature=$(/usr/local/opt/openssl@3/bin/openssl pkeyutl -sign -rawin -in ${{ github.workspace }}/PolyMC.tar.gz -inkey ed25519-priv.pem | openssl base64 | tr -d \\n) signature=$(/usr/local/opt/openssl@3/bin/openssl pkeyutl -sign -rawin -in ${{ github.workspace }}/PrismLauncher.tar.gz -inkey ed25519-priv.pem | openssl base64 | tr -d \\n)
rm ed25519-priv.pem rm ed25519-priv.pem
cat >> $GITHUB_STEP_SUMMARY << EOF cat >> $GITHUB_STEP_SUMMARY << EOF
### Artifact Information :information_source: ### Artifact Information :information_source:
@ -252,49 +370,97 @@ jobs:
EOF EOF
fi fi
- name: Package (Windows) - name: Package (Windows MinGW-w64)
if: runner.os == 'Windows' if: runner.os == 'Windows' && matrix.msystem != ''
shell: msys2 {0} shell: msys2 {0}
run: | run: |
cmake --install ${{ env.BUILD_DIR }} cmake --install ${{ env.BUILD_DIR }}
touch ${{ env.INSTALL_DIR }}/manifest.txt
for l in $(find ${{ env.INSTALL_DIR }} -type f); do l=$(cygpath -u $l); l=${l#$(pwd)/}; l=${l#${{ env.INSTALL_DIR }}/}; l=${l#./}; echo $l; done >> ${{ env.INSTALL_DIR }}/manifest.txt
- name: Package (Windows MSVC)
if: runner.os == 'Windows' && matrix.msystem == ''
run: |
cmake --install ${{ env.BUILD_DIR }} --config ${{ inputs.build_type }}
cd ${{ env.INSTALL_DIR }} cd ${{ env.INSTALL_DIR }}
if [ "${{ matrix.msystem }}" == "mingw32" ]; then if ("${{ matrix.qt_ver }}" -eq "5")
cp /mingw32/bin/libcrypto-1_1.dll /mingw32/bin/libssl-1_1.dll ./ {
elif [ "${{ matrix.msystem }}" == "mingw64" ]; then Copy-Item D:/a/PrismLauncher/Qt/Tools/OpenSSL/Win_x86/bin/libcrypto-1_1.dll -Destination libcrypto-1_1.dll
cp /mingw64/bin/libcrypto-1_1-x64.dll /mingw64/bin/libssl-1_1-x64.dll ./ Copy-Item D:/a/PrismLauncher/Qt/Tools/OpenSSL/Win_x86/bin/libssl-1_1.dll -Destination libssl-1_1.dll
fi }
cd ${{ github.workspace }}
- name: Package (Windows, portable) Get-ChildItem ${{ env.INSTALL_DIR }} -Recurse | ForEach FullName | Resolve-Path -Relative | %{ $_.TrimStart('.\') } | %{ $_.TrimStart('${{ env.INSTALL_DIR }}') } | %{ $_.TrimStart('\') } | Out-File -FilePath ${{ env.INSTALL_DIR }}/manifest.txt
- name: Fetch codesign certificate (Windows)
if: runner.os == 'Windows' if: runner.os == 'Windows'
shell: bash # yes, we are not using MSYS2 or PowerShell here
run: |
echo '${{ secrets.WINDOWS_CODESIGN_CERT }}' | base64 --decode > codesign.pfx
- name: Sign executable (Windows)
if: runner.os == 'Windows'
run: |
if (Get-Content ./codesign.pfx){
cd ${{ env.INSTALL_DIR }}
# We ship the exact same executable for portable and non-portable editions, so signing just once is fine
SignTool sign /fd sha256 /td sha256 /f ../codesign.pfx /p '${{ secrets.WINDOWS_CODESIGN_PASSWORD }}' /tr http://timestamp.digicert.com prismlauncher.exe prismlauncher_filelink.exe
} else {
":warning: Skipped code signing for Windows, as certificate was not present." >> $env:GITHUB_STEP_SUMMARY
}
- name: Package (Windows MinGW-w64, portable)
if: runner.os == 'Windows' && matrix.msystem != ''
shell: msys2 {0} shell: msys2 {0}
run: | run: |
cp -r ${{ env.INSTALL_DIR }} ${{ env.INSTALL_PORTABLE_DIR }} # cmake install on Windows is slow, let's just copy instead cp -r ${{ env.INSTALL_DIR }} ${{ env.INSTALL_PORTABLE_DIR }} # cmake install on Windows is slow, let's just copy instead
cmake --install ${{ env.BUILD_DIR }} --prefix ${{ env.INSTALL_PORTABLE_DIR }} --component portable cmake --install ${{ env.BUILD_DIR }} --prefix ${{ env.INSTALL_PORTABLE_DIR }} --component portable
for l in $(find ${{ env.INSTALL_PORTABLE_DIR }} -type f); do l=$(cygpath -u $l); l=${l#$(pwd)/}; l=${l#${{ env.INSTALL_PORTABLE_DIR }}/}; l=${l#./}; echo $l; done >> ${{ env.INSTALL_PORTABLE_DIR }}/manifest.txt
- name: Package (Windows MSVC, portable)
if: runner.os == 'Windows' && matrix.msystem == ''
run: |
cp -r ${{ env.INSTALL_DIR }} ${{ env.INSTALL_PORTABLE_DIR }} # cmake install on Windows is slow, let's just copy instead
cmake --install ${{ env.BUILD_DIR }} --prefix ${{ env.INSTALL_PORTABLE_DIR }} --component portable
Get-ChildItem ${{ env.INSTALL_PORTABLE_DIR }} -Recurse | ForEach FullName | Resolve-Path -Relative | %{ $_.TrimStart('.\') } | %{ $_.TrimStart('${{ env.INSTALL_PORTABLE_DIR }}') } | %{ $_.TrimStart('\') } | Out-File -FilePath ${{ env.INSTALL_DIR }}/manifest.txt
- name: Package (Windows, installer) - name: Package (Windows, installer)
if: runner.os == 'Windows' if: runner.os == 'Windows'
shell: msys2 {0}
run: | run: |
cd ${{ env.INSTALL_DIR }} cd ${{ env.INSTALL_DIR }}
makensis -NOCD "${{ github.workspace }}/${{ env.BUILD_DIR }}/program_info/win_install.nsi" makensis -NOCD "${{ github.workspace }}/${{ env.BUILD_DIR }}/program_info/win_install.nsi"
- name: Sign installer (Windows)
if: runner.os == 'Windows'
run: |
if (Get-Content ./codesign.pfx){
SignTool sign /fd sha256 /td sha256 /f codesign.pfx /p '${{ secrets.WINDOWS_CODESIGN_PASSWORD }}' /tr http://timestamp.digicert.com PrismLauncher-Setup.exe
} else {
":warning: Skipped code signing for Windows, as certificate was not present." >> $env:GITHUB_STEP_SUMMARY
}
- name: Package (Linux) - name: Package (Linux)
if: runner.os == 'Linux' if: runner.os == 'Linux'
run: | run: |
cmake --install ${{ env.BUILD_DIR }} --prefix ${{ env.INSTALL_DIR }} cmake --install ${{ env.BUILD_DIR }} --prefix ${{ env.INSTALL_DIR }}
for l in $(find ${{ env.INSTALL_DIR }} -type f); do l=${l#$(pwd)/}; l=${l#${{ env.INSTALL_DIR }}/}; l=${l#./}; echo $l; done > ${{ env.INSTALL_DIR }}/manifest.txt
cd ${{ env.INSTALL_DIR }} cd ${{ env.INSTALL_DIR }}
tar --owner root --group root -czf ../PolyMC.tar.gz * tar --owner root --group root -czf ../PrismLauncher.tar.gz *
- name: Package (Linux, portable) - name: Package (Linux, portable)
if: runner.os == 'Linux' if: runner.os == 'Linux'
run: | run: |
cmake --install ${{ env.BUILD_DIR }} --prefix ${{ env.INSTALL_PORTABLE_DIR }} cmake --install ${{ env.BUILD_DIR }} --prefix ${{ env.INSTALL_PORTABLE_DIR }}
cmake --install ${{ env.BUILD_DIR }} --prefix ${{ env.INSTALL_PORTABLE_DIR }} --component portable cmake --install ${{ env.BUILD_DIR }} --prefix ${{ env.INSTALL_PORTABLE_DIR }} --component portable
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
cd ${{ env.INSTALL_PORTABLE_DIR }} cd ${{ env.INSTALL_PORTABLE_DIR }}
tar -czf ../PolyMC-portable.tar.gz * tar -czf ../PrismLauncher-portable.tar.gz *
- name: Package AppImage (Linux) - name: Package AppImage (Linux)
if: runner.os == 'Linux' && matrix.qt_ver != 5 if: runner.os == 'Linux' && matrix.qt_ver != 5
@ -302,7 +468,7 @@ jobs:
run: | run: |
cmake --install ${{ env.BUILD_DIR }} --prefix ${{ env.INSTALL_APPIMAGE_DIR }}/usr cmake --install ${{ env.BUILD_DIR }} --prefix ${{ env.INSTALL_APPIMAGE_DIR }}/usr
export OUTPUT="PolyMC-${{ runner.os }}-${{ env.VERSION }}-${{ inputs.build_type }}-x86_64.AppImage" export OUTPUT="PrismLauncher-${{ runner.os }}-${{ env.VERSION }}-${{ inputs.build_type }}-x86_64.AppImage"
chmod +x linuxdeploy-*.AppImage chmod +x linuxdeploy-*.AppImage
@ -313,7 +479,10 @@ jobs:
cp -r ${{ github.workspace }}/JREs/jre17/* ${{ env.INSTALL_APPIMAGE_DIR }}/usr/lib/jvm/java-17-openjdk cp -r ${{ github.workspace }}/JREs/jre17/* ${{ env.INSTALL_APPIMAGE_DIR }}/usr/lib/jvm/java-17-openjdk
cp -r /home/runner/work/PolyMC/Qt/${{ matrix.qt_version }}/gcc_64/plugins/iconengines/* ${{ env.INSTALL_APPIMAGE_DIR }}/usr/plugins/iconengines cp -r /home/runner/work/PrismLauncher/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/
LD_LIBRARY_PATH="${LD_LIBRARY_PATH}:${{ env.INSTALL_APPIMAGE_DIR }}/usr/lib" LD_LIBRARY_PATH="${LD_LIBRARY_PATH}:${{ env.INSTALL_APPIMAGE_DIR }}/usr/lib"
LD_LIBRARY_PATH="${LD_LIBRARY_PATH}:${{ env.INSTALL_APPIMAGE_DIR }}/usr/lib/jvm/java-8-openjdk/lib/amd64/server" LD_LIBRARY_PATH="${LD_LIBRARY_PATH}:${{ env.INSTALL_APPIMAGE_DIR }}/usr/lib/jvm/java-8-openjdk/lib/amd64/server"
@ -322,7 +491,7 @@ jobs:
LD_LIBRARY_PATH="${LD_LIBRARY_PATH}:${{ env.INSTALL_APPIMAGE_DIR }}/usr/lib/jvm/java-17-openjdk/lib" LD_LIBRARY_PATH="${LD_LIBRARY_PATH}:${{ env.INSTALL_APPIMAGE_DIR }}/usr/lib/jvm/java-17-openjdk/lib"
export LD_LIBRARY_PATH export LD_LIBRARY_PATH
./linuxdeploy-x86_64.AppImage --appdir ${{ env.INSTALL_APPIMAGE_DIR }} --output appimage --plugin qt -i ${{ env.INSTALL_APPIMAGE_DIR }}/usr/share/icons/hicolor/scalable/apps/org.polymc.PolyMC.svg ./linuxdeploy-x86_64.AppImage --appdir ${{ env.INSTALL_APPIMAGE_DIR }} --output appimage --plugin qt -i ${{ env.INSTALL_APPIMAGE_DIR }}/usr/share/icons/hicolor/scalable/apps/org.prismlauncher.PrismLauncher.svg
## ##
# UPLOAD BUILDS # UPLOAD BUILDS
@ -332,63 +501,115 @@ jobs:
if: runner.os == 'macOS' if: runner.os == 'macOS'
uses: actions/upload-artifact@v3 uses: actions/upload-artifact@v3
with: with:
name: PolyMC-${{ runner.os }}-${{ env.VERSION }}-${{ inputs.build_type }} name: PrismLauncher-${{ matrix.name }}-${{ env.VERSION }}-${{ inputs.build_type }}
path: PolyMC.tar.gz path: PrismLauncher.tar.gz
- name: Upload binary zip (Windows) - name: Upload binary zip (Windows)
if: runner.os == 'Windows' if: runner.os == 'Windows'
uses: actions/upload-artifact@v3 uses: actions/upload-artifact@v3
with: with:
name: PolyMC-${{ matrix.name }}-${{ env.VERSION }}-${{ inputs.build_type }} name: PrismLauncher-${{ matrix.name }}-${{ env.VERSION }}-${{ inputs.build_type }}
path: ${{ env.INSTALL_DIR }}/** path: ${{ env.INSTALL_DIR }}/**
- name: Upload binary zip (Windows, portable) - name: Upload binary zip (Windows, portable)
if: runner.os == 'Windows' if: runner.os == 'Windows'
uses: actions/upload-artifact@v3 uses: actions/upload-artifact@v3
with: with:
name: PolyMC-${{ matrix.name }}-Portable-${{ env.VERSION }}-${{ inputs.build_type }} name: PrismLauncher-${{ matrix.name }}-Portable-${{ env.VERSION }}-${{ inputs.build_type }}
path: ${{ env.INSTALL_PORTABLE_DIR }}/** path: ${{ env.INSTALL_PORTABLE_DIR }}/**
- name: Upload installer (Windows) - name: Upload installer (Windows)
if: runner.os == 'Windows' if: runner.os == 'Windows'
uses: actions/upload-artifact@v3 uses: actions/upload-artifact@v3
with: with:
name: PolyMC-${{ matrix.name }}-Setup-${{ env.VERSION }}-${{ inputs.build_type }} name: PrismLauncher-${{ matrix.name }}-Setup-${{ env.VERSION }}-${{ inputs.build_type }}
path: PolyMC-Setup.exe path: PrismLauncher-Setup.exe
- name: Upload binary tarball (Linux, Qt 5) - name: Upload binary tarball (Linux, Qt 5)
if: runner.os == 'Linux' && matrix.qt_ver != 6 if: runner.os == 'Linux' && matrix.qt_ver != 6
uses: actions/upload-artifact@v3 uses: actions/upload-artifact@v3
with: with:
name: PolyMC-${{ runner.os }}-${{ env.VERSION }}-${{ inputs.build_type }} name: PrismLauncher-${{ runner.os }}-${{ env.VERSION }}-${{ inputs.build_type }}
path: PolyMC.tar.gz path: PrismLauncher.tar.gz
- name: Upload binary tarball (Linux, portable, Qt 5) - name: Upload binary tarball (Linux, portable, Qt 5)
if: runner.os == 'Linux' && matrix.qt_ver != 6 if: runner.os == 'Linux' && matrix.qt_ver != 6
uses: actions/upload-artifact@v3 uses: actions/upload-artifact@v3
with: with:
name: PolyMC-${{ runner.os }}-Portable-${{ env.VERSION }}-${{ inputs.build_type }} name: PrismLauncher-${{ runner.os }}-Portable-${{ env.VERSION }}-${{ inputs.build_type }}
path: PolyMC-portable.tar.gz path: PrismLauncher-portable.tar.gz
- name: Upload binary tarball (Linux, Qt 6) - name: Upload binary tarball (Linux, Qt 6)
if: runner.os == 'Linux' && matrix.qt_ver !=5 if: runner.os == 'Linux' && matrix.qt_ver !=5
uses: actions/upload-artifact@v3 uses: actions/upload-artifact@v3
with: with:
name: PolyMC-${{ runner.os }}-Qt6-${{ env.VERSION }}-${{ inputs.build_type }} name: PrismLauncher-${{ runner.os }}-Qt6-${{ env.VERSION }}-${{ inputs.build_type }}
path: PolyMC.tar.gz path: PrismLauncher.tar.gz
- name: Upload binary tarball (Linux, portable, Qt 6) - name: Upload binary tarball (Linux, portable, Qt 6)
if: runner.os == 'Linux' && matrix.qt_ver != 5 if: runner.os == 'Linux' && matrix.qt_ver != 5
uses: actions/upload-artifact@v3 uses: actions/upload-artifact@v3
with: with:
name: PolyMC-${{ runner.os }}-Qt6-Portable-${{ env.VERSION }}-${{ inputs.build_type }} name: PrismLauncher-${{ runner.os }}-Qt6-Portable-${{ env.VERSION }}-${{ inputs.build_type }}
path: PolyMC-portable.tar.gz path: PrismLauncher-portable.tar.gz
- name: Upload AppImage (Linux) - name: Upload AppImage (Linux)
if: runner.os == 'Linux' && matrix.qt_ver != 5 if: runner.os == 'Linux' && matrix.qt_ver != 5
uses: actions/upload-artifact@v3 uses: actions/upload-artifact@v3
with: with:
name: PolyMC-${{ runner.os }}-${{ env.VERSION }}-${{ inputs.build_type }}-x86_64.AppImage name: PrismLauncher-${{ runner.os }}-${{ env.VERSION }}-${{ inputs.build_type }}-x86_64.AppImage
path: PolyMC-${{ runner.os }}-${{ env.VERSION }}-${{ inputs.build_type }}-x86_64.AppImage path: PrismLauncher-${{ runner.os }}-${{ env.VERSION }}-${{ inputs.build_type }}-x86_64.AppImage
- name: ccache stats (Windows MinGW-w64)
if: runner.os == 'Windows' && matrix.msystem != ''
shell: msys2 {0}
run: |
ccache -s
flatpak:
runs-on: ubuntu-latest
container:
image: bilelmoussaoui/flatpak-github-actions:kde-5.15-22.08
options: --privileged
steps:
- name: Checkout
uses: actions/checkout@v3
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:
runs-on: ubuntu-latest
strategy:
matrix:
package:
- prismlauncher
- prismlauncher-qt5
steps:
- name: Clone repository
if: inputs.build_type == 'Debug'
uses: actions/checkout@v3
with:
submodules: 'true'
- name: Install nix
if: inputs.build_type == 'Debug'
uses: cachix/install-nix-action@v21
with:
install_url: https://nixos.org/nix/install
extra_nix_config: |
auto-optimise-store = true
experimental-features = nix-command flakes
- uses: cachix/cachix-action@v12
if: inputs.build_type == 'Debug'
with:
name: prismlauncher
authToken: '${{ secrets.CACHIX_AUTH_TOKEN }}'
- name: Build
if: inputs.build_type == 'Debug'
run: nix build .#${{ matrix.package }} --print-build-logs

35
.github/workflows/codeql.yml vendored Normal file
View File

@ -0,0 +1,35 @@
name: "CodeQL Code Scanning"
on: [ push, pull_request, workflow_dispatch ]
jobs:
CodeQL:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v3
with:
submodules: 'true'
- name: Initialize CodeQL
uses: github/codeql-action/init@v2
with:
config-file: ./.github/codeql/codeql-config.yml
queries: security-and-quality
languages: cpp, java
- name: Install Dependencies
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
- name: Configure and Build
run: |
cmake -S . -B build -DCMAKE_INSTALL_PREFIX=/usr -DLauncher_QT_VERSION_MAJOR=5 -G Ninja
cmake --build build
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v2

View File

@ -3,22 +3,22 @@ name: Build Application
on: on:
push: push:
branches-ignore: branches-ignore:
- 'stable' - 'renovate/**'
paths-ignore: paths-ignore:
- '**.md' - '**.md'
- '**/LICENSE' - '**/LICENSE'
- 'flake.lock' - 'flake.lock'
- '**.nix'
- 'packages/**' - 'packages/**'
- '.github/ISSUE_TEMPLATE/**' - '.github/ISSUE_TEMPLATE/**'
- '.markdownlint**'
pull_request: pull_request:
paths-ignore: paths-ignore:
- '**.md' - '**.md'
- '**/LICENSE' - '**/LICENSE'
- 'flake.lock' - 'flake.lock'
- '**.nix'
- 'packages/**' - 'packages/**'
- '.github/ISSUE_TEMPLATE/**' - '.github/ISSUE_TEMPLATE/**'
- '.markdownlint**'
workflow_dispatch: workflow_dispatch:
jobs: jobs:
@ -28,5 +28,9 @@ jobs:
uses: ./.github/workflows/build.yml uses: ./.github/workflows/build.yml
with: with:
build_type: Debug build_type: Debug
is_qt_cached: true
secrets: secrets:
SPARKLE_ED25519_KEY: ${{ secrets.SPARKLE_ED25519_KEY }} SPARKLE_ED25519_KEY: ${{ secrets.SPARKLE_ED25519_KEY }}
WINDOWS_CODESIGN_CERT: ${{ secrets.WINDOWS_CODESIGN_CERT }}
WINDOWS_CODESIGN_PASSWORD: ${{ secrets.WINDOWS_CODESIGN_PASSWORD }}
CACHIX_AUTH_TOKEN: ${{ secrets.CACHIX_AUTH_TOKEN }}

View File

@ -12,8 +12,12 @@ jobs:
uses: ./.github/workflows/build.yml uses: ./.github/workflows/build.yml
with: with:
build_type: Release build_type: Release
is_qt_cached: false
secrets: secrets:
SPARKLE_ED25519_KEY: ${{ secrets.SPARKLE_ED25519_KEY }} SPARKLE_ED25519_KEY: ${{ secrets.SPARKLE_ED25519_KEY }}
WINDOWS_CODESIGN_CERT: ${{ secrets.WINDOWS_CODESIGN_CERT }}
WINDOWS_CODESIGN_PASSWORD: ${{ secrets.WINDOWS_CODESIGN_PASSWORD }}
CACHIX_AUTH_TOKEN: ${{ secrets.CACHIX_AUTH_TOKEN }}
create_release: create_release:
needs: build_release needs: build_release
@ -25,7 +29,7 @@ jobs:
uses: actions/checkout@v3 uses: actions/checkout@v3
with: with:
submodules: 'true' submodules: 'true'
path: 'PolyMC-source' path: 'PrismLauncher-source'
- name: Download artifacts - name: Download artifacts
uses: actions/download-artifact@v3 uses: actions/download-artifact@v3
- name: Grab and store version - name: Grab and store version
@ -34,25 +38,39 @@ jobs:
echo "VERSION=$tag_name" >> $GITHUB_ENV echo "VERSION=$tag_name" >> $GITHUB_ENV
- name: Package artifacts properly - name: Package artifacts properly
run: | run: |
mv ${{ github.workspace }}/PolyMC-source PolyMC-${{ env.VERSION }} mv ${{ github.workspace }}/PrismLauncher-source PrismLauncher-${{ env.VERSION }}
mv PolyMC-Linux-Qt6-Portable*/PolyMC-portable.tar.gz PolyMC-Linux-Qt6-Portable-${{ env.VERSION }}.tar.gz mv PrismLauncher-Linux-Qt6-Portable*/PrismLauncher-portable.tar.gz PrismLauncher-Linux-Qt6-Portable-${{ env.VERSION }}.tar.gz
mv PolyMC-Linux-Qt6*/PolyMC.tar.gz PolyMC-Linux-Qt6-${{ env.VERSION }}.tar.gz mv PrismLauncher-Linux-Qt6*/PrismLauncher.tar.gz PrismLauncher-Linux-Qt6-${{ env.VERSION }}.tar.gz
mv PolyMC-Linux-Portable*/PolyMC-portable.tar.gz PolyMC-Linux-Portable-${{ env.VERSION }}.tar.gz mv PrismLauncher-Linux-Portable*/PrismLauncher-portable.tar.gz PrismLauncher-Linux-Portable-${{ env.VERSION }}.tar.gz
mv PolyMC-Linux*/PolyMC.tar.gz PolyMC-Linux-${{ env.VERSION }}.tar.gz mv PrismLauncher-Linux*/PrismLauncher.tar.gz PrismLauncher-Linux-${{ env.VERSION }}.tar.gz
mv PolyMC-*.AppImage/PolyMC-*.AppImage PolyMC-Linux-${{ env.VERSION }}-x86_64.AppImage mv PrismLauncher-*.AppImage/PrismLauncher-*.AppImage PrismLauncher-Linux-${{ env.VERSION }}-x86_64.AppImage
mv PolyMC-macOS*/PolyMC.tar.gz PolyMC-macOS-${{ env.VERSION }}.tar.gz mv PrismLauncher-macOS-Legacy*/PrismLauncher.tar.gz PrismLauncher-macOS-Legacy-${{ env.VERSION }}.tar.gz
mv PrismLauncher-macOS*/PrismLauncher.tar.gz PrismLauncher-macOS-${{ env.VERSION }}.tar.gz
tar -czf PolyMC-${{ env.VERSION }}.tar.gz PolyMC-${{ env.VERSION }} tar -czf PrismLauncher-${{ env.VERSION }}.tar.gz PrismLauncher-${{ env.VERSION }}
for d in PolyMC-Windows-*; do for d in PrismLauncher-Windows-MSVC*; do
cd "${d}" || continue cd "${d}" || continue
LEGACY="$(echo -n ${d} | grep -o Legacy || true)" LEGACY="$(echo -n ${d} | grep -o Legacy || true)"
ARM64="$(echo -n ${d} | grep -o arm64 || true)"
INST="$(echo -n ${d} | grep -o Setup || true)" INST="$(echo -n ${d} | grep -o Setup || true)"
PORT="$(echo -n ${d} | grep -o Portable || true)" PORT="$(echo -n ${d} | grep -o Portable || true)"
NAME="PolyMC-Windows" NAME="PrismLauncher-Windows-MSVC"
test -z "${LEGACY}" || NAME="${NAME}-Legacy" test -z "${LEGACY}" || NAME="${NAME}-Legacy"
test -z "${ARM64}" || NAME="${NAME}-arm64"
test -z "${PORT}" || NAME="${NAME}-Portable" test -z "${PORT}" || NAME="${NAME}-Portable"
test -z "${INST}" || mv PolyMC-*.exe ../${NAME}-Setup-${{ env.VERSION }}.exe test -z "${INST}" || mv PrismLauncher-*.exe ../${NAME}-Setup-${{ env.VERSION }}.exe
test -n "${INST}" || zip -r -9 "../${NAME}-${{ env.VERSION }}.zip" *
cd ..
done
for d in PrismLauncher-Windows-MinGW-w64*; do
cd "${d}" || continue
INST="$(echo -n ${d} | grep -o Setup || true)"
PORT="$(echo -n ${d} | grep -o Portable || true)"
NAME="PrismLauncher-Windows-MinGW-w64"
test -z "${PORT}" || NAME="${NAME}-Portable"
test -z "${INST}" || mv PrismLauncher-*.exe ../${NAME}-Setup-${{ env.VERSION }}.exe
test -n "${INST}" || zip -r -9 "../${NAME}-${{ env.VERSION }}.zip" * test -n "${INST}" || zip -r -9 "../${NAME}-${{ env.VERSION }}.zip" *
cd .. cd ..
done done
@ -64,20 +82,27 @@ jobs:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with: with:
tag_name: ${{ github.ref }} tag_name: ${{ github.ref }}
name: PolyMC ${{ env.VERSION }} name: Prism Launcher ${{ env.VERSION }}
draft: true draft: true
prerelease: false prerelease: false
files: | files: |
PolyMC-Linux-${{ env.VERSION }}.tar.gz PrismLauncher-Linux-${{ env.VERSION }}.tar.gz
PolyMC-Linux-Portable-${{ env.VERSION }}.tar.gz PrismLauncher-Linux-Portable-${{ env.VERSION }}.tar.gz
PolyMC-Linux-${{ env.VERSION }}-x86_64.AppImage PrismLauncher-Linux-${{ env.VERSION }}-x86_64.AppImage
PolyMC-Windows-Legacy-${{ env.VERSION }}.zip PrismLauncher-Linux-Qt6-${{ env.VERSION }}.tar.gz
PolyMC-Linux-Qt6-${{ env.VERSION }}.tar.gz PrismLauncher-Linux-Qt6-Portable-${{ env.VERSION }}.tar.gz
PolyMC-Linux-Qt6-Portable-${{ env.VERSION }}.tar.gz PrismLauncher-Windows-MinGW-w64-${{ env.VERSION }}.zip
PolyMC-Windows-Legacy-Portable-${{ env.VERSION }}.zip PrismLauncher-Windows-MinGW-w64-Portable-${{ env.VERSION }}.zip
PolyMC-Windows-Legacy-Setup-${{ env.VERSION }}.exe PrismLauncher-Windows-MinGW-w64-Setup-${{ env.VERSION }}.exe
PolyMC-Windows-${{ env.VERSION }}.zip PrismLauncher-Windows-MSVC-Legacy-${{ env.VERSION }}.zip
PolyMC-Windows-Portable-${{ env.VERSION }}.zip PrismLauncher-Windows-MSVC-Legacy-Portable-${{ env.VERSION }}.zip
PolyMC-Windows-Setup-${{ env.VERSION }}.exe PrismLauncher-Windows-MSVC-Legacy-Setup-${{ env.VERSION }}.exe
PolyMC-macOS-${{ env.VERSION }}.tar.gz PrismLauncher-Windows-MSVC-arm64-${{ env.VERSION }}.zip
PolyMC-${{ env.VERSION }}.tar.gz PrismLauncher-Windows-MSVC-arm64-Portable-${{ env.VERSION }}.zip
PrismLauncher-Windows-MSVC-arm64-Setup-${{ env.VERSION }}.exe
PrismLauncher-Windows-MSVC-${{ env.VERSION }}.zip
PrismLauncher-Windows-MSVC-Portable-${{ env.VERSION }}.zip
PrismLauncher-Windows-MSVC-Setup-${{ env.VERSION }}.exe
PrismLauncher-macOS-${{ env.VERSION }}.tar.gz
PrismLauncher-macOS-Legacy-${{ env.VERSION }}.tar.gz
PrismLauncher-${{ env.VERSION }}.tar.gz

View File

@ -7,8 +7,9 @@ jobs:
publish: publish:
runs-on: windows-latest runs-on: windows-latest
steps: steps:
- uses: vedantmgoyal2009/winget-releaser@latest - uses: vedantmgoyal2009/winget-releaser@v2
with: with:
identifier: PolyMC.PolyMC identifier: PrismLauncher.PrismLauncher
installers-regex: '\.exe$' version: ${{ github.event.release.tag_name }}
installers-regex: 'PrismLauncher-Windows-MSVC(:?-arm64|-Legacy)?-Setup-.+\.exe$'
token: ${{ secrets.WINGET_TOKEN }} token: ${{ secrets.WINGET_TOKEN }}

11
.gitignore vendored
View File

@ -11,10 +11,14 @@ html/
*.pro.user *.pro.user
CMakeLists.txt.user CMakeLists.txt.user
CMakeLists.txt.user.* CMakeLists.txt.user.*
CMakeSettings.json
/CMakeFiles
CMakeCache.txt
/.project /.project
/.settings /.settings
/.idea /.idea
/.vscode /.vscode
/.vs
cmake-build-*/ cmake-build-*/
Debug Debug
@ -42,8 +46,13 @@ run/
.cache/ .cache/
# Nix/NixOS # Nix/NixOS
result/ .direnv/
.pre-commit-config.yaml
result
# Flatpak # Flatpak
.flatpak-builder .flatpak-builder
flatbuild flatbuild
# Snap
*.snap

23
.gitmodules vendored
View File

@ -1,8 +1,21 @@
[submodule "depends/libnbtplusplus"]
path = libraries/libnbtplusplus
url = https://github.com/PolyMC/libnbtplusplus.git
pushurl = git@github.com:PolyMC/libnbtplusplus.git
[submodule "libraries/quazip"] [submodule "libraries/quazip"]
path = libraries/quazip path = libraries/quazip
url = https://github.com/stachenov/quazip.git url = https://github.com/stachenov/quazip.git
[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
[submodule "libraries/zlib"]
path = libraries/zlib
url = https://github.com/madler/zlib.git
[submodule "libraries/extra-cmake-modules"]
path = libraries/extra-cmake-modules
url = https://github.com/KDE/extra-cmake-modules
[submodule "libraries/cmark"]
path = libraries/cmark
url = https://github.com/commonmark/cmark.git

12
.markdownlint.yaml Normal file
View File

@ -0,0 +1,12 @@
# MD013/line-length - Line length
MD013: false
# MD024/no-duplicate-heading/no-duplicate-header - Multiple headings with the same content
MD024:
siblings-only: true
# MD033/no-inline-html Inline HTML
MD033: false
# MD041/first-line-heading/first-line-h1 First line in a file should be a top-level heading
MD041: false

2
.markdownlintignore Normal file
View File

@ -0,0 +1,2 @@
libraries/nbtplusplus
libraries/quazip

View File

@ -1,5 +1,3 @@
# Build Instructions # Build Instructions
Build instructions are available on [the website](https://polymc.org/wiki/development/build-instructions/). Full build instructions are available on [the website](https://prismlauncher.org/wiki/development/build-instructions/).
If you would like to contribute or fix an issue with the Build instructions you can do so [here](https://github.com/PolyMC/polymc.github.io/blob/master/src/wiki/development/build-instructions.md).

View File

@ -1,10 +1,5 @@
cmake_minimum_required(VERSION 3.15) # minimum version required by QuaZip cmake_minimum_required(VERSION 3.15) # minimum version required by QuaZip
if(WIN32)
# In Qt 5.1+ we have our own main() function, don't autolink to qtmain on Windows
cmake_policy(SET CMP0020 OLD)
endif()
project(Launcher) project(Launcher)
string(COMPARE EQUAL "${CMAKE_SOURCE_DIR}" "${CMAKE_BUILD_DIR}" IS_IN_SOURCE_BUILD) string(COMPARE EQUAL "${CMAKE_SOURCE_DIR}" "${CMAKE_BUILD_DIR}" IS_IN_SOURCE_BUILD)
@ -29,12 +24,54 @@ set(CMAKE_JAVA_TARGET_OUTPUT_DIR ${PROJECT_BINARY_DIR}/jars)
######## Set compiler flags ######## ######## Set compiler flags ########
set(CMAKE_CXX_STANDARD_REQUIRED true) set(CMAKE_CXX_STANDARD_REQUIRED true)
set(CMAKE_C_STANDARD_REQUIRED true) set(CMAKE_C_STANDARD_REQUIRED true)
set(CMAKE_CXX_STANDARD 11) set(CMAKE_CXX_STANDARD 17)
set(CMAKE_C_STANDARD 11) set(CMAKE_C_STANDARD 11)
include(GenerateExportHeader) include(GenerateExportHeader)
set(CMAKE_CXX_FLAGS "-Wall -pedantic -D_GLIBCXX_USE_CXX11_ABI=0 -fstack-protector-strong --param=ssp-buffer-size=4 ${CMAKE_CXX_FLAGS}") if(MSVC)
if(UNIX AND APPLE) # /GS Adds buffer security checks, default on but incuded anyway to mirror gcc's fstack-protector flag
set(CMAKE_CXX_FLAGS "-stdlib=libc++ ${CMAKE_CXX_FLAGS}") # /permissive- specify standards-conforming compiler behavior, also enabled by Qt6, default on with std:c++20
# Use /W4 as /Wall includes unnesserey warnings such as added padding to structs
set(CMAKE_CXX_FLAGS "/GS /permissive- /W4 ${CMAKE_CXX_FLAGS}")
# LINK accepts /SUBSYSTEM whics sets if we are a WINDOWS (gui) or a CONSOLE programs
# This implicitly selects an entrypoint specific to the subsystem selected
# qtmain/QtEntryPointLib provides the correct entrypoint (wWinMain) for gui programs
# Additinaly LINK autodetects we use a GUI so we can omit /SUBSYSTEM
# This allows tests to still use have console without using seperate linker flags
# /LTCG allows for linking wholy optimizated programs
# /MANIFEST:NO disables generating a manifest file, we instead provide our own
# /STACK sets the stack reserve size, ATL's pack list needs 3-4 MiB as of November 2022, provide 8 MiB
set(CMAKE_EXE_LINKER_FLAGS "/LTCG /MANIFEST:NO /STACK:8388608 ${CMAKE_EXE_LINKER_FLAGS}")
# /GL enables whole program optimizations
# /Gw helps reduce binary size
# /Gy allows the compiler to package individual functions
# /guard:cf enables control flow guard
foreach(lang C CXX)
set("CMAKE_${lang}_FLAGS_RELEASE" "/GL /Gw /Gy /guard:cf")
endforeach()
# See https://github.com/ccache/ccache/issues/1040
# Note, CMake 3.25 replaces this with CMAKE_MSVC_DEBUG_INFORMATION_FORMAT
# See https://cmake.org/cmake/help/v3.25/variable/CMAKE_MSVC_DEBUG_INFORMATION_FORMAT.html
foreach(config DEBUG RELWITHDEBINFO)
foreach(lang C CXX)
set(flags_var "CMAKE_${lang}_FLAGS_${config}")
string(REGEX REPLACE "/Z[Ii]" "/Z7" ${flags_var} "${${flags_var}}")
endforeach()
endforeach()
if(CMAKE_MSVC_RUNTIME_LIBRARY STREQUAL "MultiThreadedDLL")
set(CMAKE_MAP_IMPORTED_CONFIG_DEBUG Release "")
set(CMAKE_MAP_IMPORTED_CONFIG_RELWITHDEBINFO Release "")
endif()
else()
set(CMAKE_CXX_FLAGS "-Wall -pedantic -fstack-protector-strong --param=ssp-buffer-size=4 ${CMAKE_CXX_FLAGS}")
# 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}")
endif()
endif() endif()
# Fix build with Qt 5.13 # Fix build with Qt 5.13
@ -42,6 +79,9 @@ 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_DISABLE_DEPRECATED_BEFORE=0x050C00")
# Fix aarch64 build for toml++
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DTOML_ENABLE_FLOAT16=0")
# set CXXFLAGS for build targets # set CXXFLAGS for build targets
set(CMAKE_CXX_FLAGS_RELEASE "-O2 -D_FORTIFY_SOURCE=2 ${CMAKE_CXX_FLAGS_RELEASE}") set(CMAKE_CXX_FLAGS_RELEASE "-O2 -D_FORTIFY_SOURCE=2 ${CMAKE_CXX_FLAGS_RELEASE}")
@ -51,11 +91,18 @@ if(ENABLE_LTO)
include(CheckIPOSupported) include(CheckIPOSupported)
check_ipo_supported(RESULT ipo_supported OUTPUT ipo_error) check_ipo_supported(RESULT ipo_supported OUTPUT ipo_error)
if(ipo_supported AND (CMAKE_BUILD_TYPE STREQUAL "Release" OR CMAKE_BUILD_TYPE STREQUAL "MinSizeRel")) if(ipo_supported)
message(STATUS "IPO / LTO enabled") set(CMAKE_INTERPROCEDURAL_OPTIMIZATION_RELEASE TRUE)
set(CMAKE_INTERPROCEDURAL_OPTIMIZATION TRUE) set(CMAKE_INTERPROCEDURAL_OPTIMIZATION_MINSIZEREL TRUE)
elseif(ipo_supported) if(CMAKE_BUILD_TYPE)
message(STATUS "Not enabling IPO / LTO on debug builds") if(CMAKE_BUILD_TYPE STREQUAL "Release" OR CMAKE_BUILD_TYPE STREQUAL "MinSizeRel")
message(STATUS "IPO / LTO enabled")
else()
message(STATUS "Not enabling IPO / LTO on debug builds")
endif()
else()
message(STATUS "IPO / LTO will only be enabled for release builds")
endif()
else() else()
message(STATUS "IPO / LTO not supported: <${ipo_error}>") message(STATUS "IPO / LTO not supported: <${ipo_error}>")
endif() endif()
@ -63,28 +110,40 @@ endif()
option(BUILD_TESTING "Build the testing tree." ON) option(BUILD_TESTING "Build the testing tree." ON)
find_package(ECM REQUIRED NO_MODULE) find_package(ECM QUIET NO_MODULE)
set(CMAKE_MODULE_PATH "${ECM_MODULE_PATH};${CMAKE_MODULE_PATH}") if(NOT ECM_FOUND)
if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/libraries/extra-cmake-modules/CMakeLists.txt")
message(STATUS "Using bundled ECM")
set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/libraries/extra-cmake-modules/modules;${CMAKE_MODULE_PATH}")
else()
message(FATAL_ERROR
" Could not find ECM\n \n"
" Either install ECM using the system package manager or clone submodules\n"
" Submodules can be cloned with 'git submodule update --init --recursive'")
endif()
else()
set(CMAKE_MODULE_PATH "${ECM_MODULE_PATH};${CMAKE_MODULE_PATH}")
endif()
include(CTest) include(CTest)
include(ECMAddTests) include(ECMAddTests)
if (BUILD_TESTING) if(BUILD_TESTING)
enable_testing() enable_testing()
endif() endif()
##################################### Set Application options ##################################### ##################################### Set Application options #####################################
######## Set URLs ######## ######## Set URLs ########
set(Launcher_NEWS_RSS_URL "https://polymc.org/feed/feed.xml" CACHE STRING "URL to fetch PolyMC's news RSS feed from.") set(Launcher_NEWS_RSS_URL "https://prismlauncher.org/feed/feed.xml" CACHE STRING "URL to fetch Prism Launcher's news RSS feed from.")
set(Launcher_NEWS_OPEN_URL "https://polymc.org/news" CACHE STRING "URL that gets opened when the user clicks 'More News'") set(Launcher_NEWS_OPEN_URL "https://prismlauncher.org/news" CACHE STRING "URL that gets opened when the user clicks 'More News'")
set(Launcher_HELP_URL "https://polymc.org/wiki/help-pages/%1" CACHE STRING "URL (with arg %1 to be substituted with page-id) that gets opened when the user requests help") set(Launcher_HELP_URL "https://prismlauncher.org/wiki/help-pages/%1" CACHE STRING "URL (with arg %1 to be substituted with page-id) that gets opened when the user requests help")
######## Set version numbers ######## ######## Set version numbers ########
set(Launcher_VERSION_MAJOR 1) set(Launcher_VERSION_MAJOR 7)
set(Launcher_VERSION_MINOR 4) set(Launcher_VERSION_MINOR 0)
set(Launcher_VERSION_HOTFIX 0)
# Build number set(Launcher_VERSION_NAME "${Launcher_VERSION_MAJOR}.${Launcher_VERSION_MINOR}")
set(Launcher_VERSION_BUILD -1 CACHE STRING "Build number. -1 for no build number.") 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")
# Build platform. # Build platform.
set(Launcher_BUILD_PLATFORM "" CACHE STRING "A short string identifying the platform that this build was built for. Only used to display in the about dialog.") set(Launcher_BUILD_PLATFORM "" CACHE STRING "A short string identifying the platform that this build was built for. Only used to display in the about dialog.")
@ -93,29 +152,29 @@ set(Launcher_BUILD_PLATFORM "" CACHE STRING "A short string identifying the plat
set(Launcher_UPDATER_BASE "" CACHE STRING "Base URL for the updater.") set(Launcher_UPDATER_BASE "" CACHE STRING "Base URL for the updater.")
# The metadata server # The metadata server
set(Launcher_META_URL "https://meta.polymc.org/v1/" CACHE STRING "URL to fetch Launcher's meta files from.") set(Launcher_META_URL "https://meta.prismlauncher.org/v1/" CACHE STRING "URL to fetch Launcher's meta files from.")
# Imgur API Client ID # Imgur API Client ID
set(Launcher_IMGUR_CLIENT_ID "5b97b0713fba4a3" CACHE STRING "Client ID you can get from Imgur when you register an application") set(Launcher_IMGUR_CLIENT_ID "5b97b0713fba4a3" CACHE STRING "Client ID you can get from Imgur when you register an application")
# Bug tracker URL # Bug tracker URL
set(Launcher_BUG_TRACKER_URL "https://github.com/PolyMC/PolyMC/issues" CACHE STRING "URL for the bug tracker.") set(Launcher_BUG_TRACKER_URL "https://github.com/PrismLauncher/PrismLauncher/issues" CACHE STRING "URL for the bug tracker.")
# Translations Platform URL # Translations Platform URL
set(Launcher_TRANSLATIONS_URL "https://hosted.weblate.org/projects/polymc/polymc/" CACHE STRING "URL for the translations platform.") set(Launcher_TRANSLATIONS_URL "https://hosted.weblate.org/projects/prismlauncher/launcher/" CACHE STRING "URL for the translations platform.")
# Matrix Space # Matrix Space
set(Launcher_MATRIX_URL "https://matrix.to/#/#polymc:matrix.org" CACHE STRING "URL to the Matrix Space") set(Launcher_MATRIX_URL "https://prismlauncher.org/matrix" CACHE STRING "URL to the Matrix Space")
# Discord URL # Discord URL
set(Launcher_DISCORD_URL "https://discord.gg/Z52pwxWCHP" CACHE STRING "URL for the Discord guild.") set(Launcher_DISCORD_URL "https://prismlauncher.org/discord" CACHE STRING "URL for the Discord guild.")
# Subreddit URL # Subreddit URL
set(Launcher_SUBREDDIT_URL "https://www.reddit.com/r/PolyMCLauncher/" CACHE STRING "URL for the subreddit.") set(Launcher_SUBREDDIT_URL "https://prismlauncher.org/reddit" CACHE STRING "URL for the subreddit.")
# Builds # Builds
set(Launcher_FORCE_BUNDLED_LIBS OFF CACHE BOOL "Prevent using system libraries, if they are available as submodules") set(Launcher_FORCE_BUNDLED_LIBS OFF CACHE BOOL "Prevent using system libraries, if they are available as submodules")
set(Launcher_QT_VERSION_MAJOR "5" CACHE STRING "Major Qt version to build against") set(Launcher_QT_VERSION_MAJOR "6" CACHE STRING "Major Qt version to build against")
# API Keys # API Keys
# NOTE: These API keys are here for convenience. If you rebrand this software or intend to break the terms of service # NOTE: These API keys are here for convenience. If you rebrand this software or intend to break the terms of service
@ -126,12 +185,13 @@ set(Launcher_QT_VERSION_MAJOR "5" CACHE STRING "Major Qt version to build agains
# By using this key in your builds you accept the terms of use laid down in # By using this key in your builds you accept the terms of use laid down in
# https://docs.microsoft.com/en-us/legal/microsoft-identity-platform/terms-of-use # https://docs.microsoft.com/en-us/legal/microsoft-identity-platform/terms-of-use
set(Launcher_MSA_CLIENT_ID "549033b2-1532-4d4e-ae77-1bbaa46f9d74" CACHE STRING "Client ID you can get from Microsoft Identity Platform when you register an application") set(Launcher_MSA_CLIENT_ID "c36a9fb6-4f2a-41ff-90bd-ae7cc92031eb" CACHE STRING "Client ID you can get from Microsoft Identity Platform when you register an application")
# By using this key in your builds you accept the terms and conditions laid down in # By using this key in your builds you accept the terms and conditions laid down in
# https://support.curseforge.com/en/support/solutions/articles/9000207405-curse-forge-3rd-party-api-terms-and-conditions # https://support.curseforge.com/en/support/solutions/articles/9000207405-curse-forge-3rd-party-api-terms-and-conditions
# NOTE: CurseForge requires you to change this if you make any kind of derivative work. # NOTE: CurseForge requires you to change this if you make any kind of derivative work.
set(Launcher_CURSEFORGE_API_KEY "$2a$10$1Oqr2MX3O4n/ilhFGc597u8tfI3L2Hyr9/rtWDAMRjghSQV2QUuxq" CACHE STRING "API key for the CurseForge platform") # This key was issued specifically for Prism Launcher
set(Launcher_CURSEFORGE_API_KEY "$2a$10$wuAJuNZuted3NORVmpgUC.m8sI.pv1tOPKZyBgLFGjxFp/br0lZCC" CACHE STRING "API key for the CurseForge platform")
#### Check the current Git commit and branch #### Check the current Git commit and branch
@ -143,18 +203,21 @@ message(STATUS "Git commit: ${Launcher_GIT_COMMIT}")
message(STATUS "Git tag: ${Launcher_GIT_TAG}") message(STATUS "Git tag: ${Launcher_GIT_TAG}")
message(STATUS "Git refspec: ${Launcher_GIT_REFSPEC}") message(STATUS "Git refspec: ${Launcher_GIT_REFSPEC}")
set(Launcher_RELEASE_VERSION_NAME "${Launcher_VERSION_MAJOR}.${Launcher_VERSION_MINOR}.${Launcher_VERSION_HOTFIX}")
set(Launcher_RELEASE_VERSION_NAME4 "${Launcher_RELEASE_VERSION_NAME}.0")
set(Launcher_RELEASE_VERSION_NAME4_COMMA "${Launcher_VERSION_MAJOR},${Launcher_VERSION_MINOR},${Launcher_VERSION_HOTFIX},0")
string(TIMESTAMP TODAY "%Y-%m-%d") string(TIMESTAMP TODAY "%Y-%m-%d")
set(Launcher_RELEASE_TIMESTAMP "${TODAY}") set(Launcher_BUILD_TIMESTAMP "${TODAY}")
#### Custom target to just print the version.
add_custom_target(version echo "Version: ${Launcher_RELEASE_VERSION_NAME}")
add_custom_target(tcversion echo "\\#\\#teamcity[setParameter name=\\'env.LAUNCHER_VERSION\\' value=\\'${Launcher_RELEASE_VERSION_NAME}\\']")
################################ 3rd Party Libs ################################ ################################ 3rd Party Libs ################################
# Successive configurations of cmake without cleaning the build dir will cause zlib fallback to fail due to cached values
# Record when fallback triggered and skip this find_package
if(NOT Launcher_FORCE_BUNDLED_LIBS AND NOT FORCE_BUNDLED_ZLIB)
find_package(ZLIB QUIET)
endif()
if(NOT ZLIB_FOUND)
set(FORCE_BUNDLED_ZLIB TRUE CACHE BOOL "")
mark_as_advanced(FORCE_BUNDLED_ZLIB)
endif()
# Find the required Qt parts # Find the required Qt parts
include(QtVersionlessBackport) include(QtVersionlessBackport)
if(Launcher_QT_VERSION_MAJOR EQUAL 5) if(Launcher_QT_VERSION_MAJOR EQUAL 5)
@ -173,7 +236,7 @@ if(Launcher_QT_VERSION_MAJOR EQUAL 5)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DUNICODE -D_UNICODE") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DUNICODE -D_UNICODE")
elseif(Launcher_QT_VERSION_MAJOR EQUAL 6) elseif(Launcher_QT_VERSION_MAJOR EQUAL 6)
set(QT_VERSION_MAJOR 6) set(QT_VERSION_MAJOR 6)
find_package(Qt6 REQUIRED COMPONENTS Core Widgets Concurrent Network Test Xml Core5Compat) find_package(Qt6 REQUIRED COMPONENTS Core CoreTools Widgets Concurrent Network Test Xml Core5Compat)
list(APPEND Launcher_QT_LIBS Qt6::Core5Compat) list(APPEND Launcher_QT_LIBS Qt6::Core5Compat)
if(NOT Launcher_FORCE_BUNDLED_LIBS) if(NOT Launcher_FORCE_BUNDLED_LIBS)
@ -187,21 +250,38 @@ else()
message(FATAL_ERROR "Qt version ${Launcher_QT_VERSION_MAJOR} is not supported") message(FATAL_ERROR "Qt version ${Launcher_QT_VERSION_MAJOR} is not supported")
endif() endif()
include(ECMQueryQt) if(Launcher_QT_VERSION_MAJOR EQUAL 5)
ecm_query_qt(QT_PLUGINS_DIR QT_INSTALL_PLUGINS) include(ECMQueryQt)
ecm_query_qt(QT_LIBS_DIR QT_INSTALL_LIBS) ecm_query_qt(QT_PLUGINS_DIR QT_INSTALL_PLUGINS)
ecm_query_qt(QT_LIBEXECS_DIR QT_INSTALL_LIBEXECS) ecm_query_qt(QT_LIBS_DIR QT_INSTALL_LIBS)
ecm_query_qt(QT_DATA_DIR QT_HOST_DATA) ecm_query_qt(QT_LIBEXECS_DIR QT_INSTALL_LIBEXECS)
set(QT_MKSPECS_DIR ${QT_DATA_DIR}/mkspecs) else()
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 # NOTE: Qt 6 already sets this by default
if (Qt5_POSITION_INDEPENDENT_CODE) if (Qt5_POSITION_INDEPENDENT_CODE)
SET(CMAKE_POSITION_INDEPENDENT_CODE ON) SET(CMAKE_POSITION_INDEPENDENT_CODE ON)
endif() 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()
include(ECMQtDeclareLoggingCategory)
####################################### Program Info ####################################### ####################################### Program Info #######################################
set(Launcher_APP_BINARY_NAME "polymc" CACHE STRING "Name of the Launcher binary") set(Launcher_APP_BINARY_NAME "prismlauncher" CACHE STRING "Name of the Launcher binary")
add_subdirectory(program_info) add_subdirectory(program_info)
####################################### Install layout ####################################### ####################################### Install layout #######################################
@ -223,16 +303,16 @@ if(UNIX AND APPLE)
set(APPS "\${CMAKE_INSTALL_PREFIX}/${Launcher_Name}.app") set(APPS "\${CMAKE_INSTALL_PREFIX}/${Launcher_Name}.app")
# Mac bundle settings # Mac bundle settings
set(MACOSX_BUNDLE_BUNDLE_NAME "${Launcher_Name}") set(MACOSX_BUNDLE_BUNDLE_NAME "${Launcher_DisplayName}")
set(MACOSX_BUNDLE_INFO_STRING "${Launcher_Name}: A custom launcher for Minecraft that allows you to easily manage multiple installations of Minecraft at once.") set(MACOSX_BUNDLE_INFO_STRING "${Launcher_DisplayName}: A custom launcher for Minecraft that allows you to easily manage multiple installations of Minecraft at once.")
set(MACOSX_BUNDLE_GUI_IDENTIFIER "org.polymc.${Launcher_Name}") set(MACOSX_BUNDLE_GUI_IDENTIFIER "org.prismlauncher.${Launcher_Name}")
set(MACOSX_BUNDLE_BUNDLE_VERSION "${Launcher_VERSION_MAJOR}.${Launcher_VERSION_MINOR}.${Launcher_VERSION_HOTFIX}") set(MACOSX_BUNDLE_BUNDLE_VERSION "${Launcher_VERSION_NAME}")
set(MACOSX_BUNDLE_SHORT_VERSION_STRING "${Launcher_VERSION_MAJOR}.${Launcher_VERSION_MINOR}.${Launcher_VERSION_HOTFIX}") set(MACOSX_BUNDLE_SHORT_VERSION_STRING "${Launcher_VERSION_NAME}")
set(MACOSX_BUNDLE_LONG_VERSION_STRING "${Launcher_VERSION_MAJOR}.${Launcher_VERSION_MINOR}.${Launcher_VERSION_HOTFIX}") set(MACOSX_BUNDLE_LONG_VERSION_STRING "${Launcher_VERSION_NAME}")
set(MACOSX_BUNDLE_ICON_FILE ${Launcher_Name}.icns) set(MACOSX_BUNDLE_ICON_FILE ${Launcher_Name}.icns)
set(MACOSX_BUNDLE_COPYRIGHT "Copyright 2021-2022 ${Launcher_Copyright}") set(MACOSX_BUNDLE_COPYRIGHT "© 2022 ${Launcher_Copyright_Mac}")
set(MACOSX_SPARKLE_UPDATE_PUBLIC_KEY "idALcUIazingvKSSsEa9U7coDVxZVx/ORpOEE/QtJfg=") set(MACOSX_SPARKLE_UPDATE_PUBLIC_KEY "v55ZWWD6QlPoXGV6VLzOTZxZUggWeE51X8cRQyQh6vA=")
set(MACOSX_SPARKLE_UPDATE_FEED_URL "https://polymc.org/feed/appcast.xml") set(MACOSX_SPARKLE_UPDATE_FEED_URL "https://prismlauncher.org/feed/appcast.xml")
set(MACOSX_SPARKLE_DOWNLOAD_URL "https://github.com/sparkle-project/Sparkle/releases/download/2.1.0/Sparkle-2.1.0.tar.xz" CACHE STRING "URL to Sparkle release archive") set(MACOSX_SPARKLE_DOWNLOAD_URL "https://github.com/sparkle-project/Sparkle/releases/download/2.1.0/Sparkle-2.1.0.tar.xz" CACHE STRING "URL to Sparkle release archive")
set(MACOSX_SPARKLE_SHA256 "bf6ac1caa9f8d321d5784859c88da874f28412f37fb327bc21b7b14c5d61ef94" CACHE STRING "SHA256 checksum for Sparkle release archive") set(MACOSX_SPARKLE_SHA256 "bf6ac1caa9f8d321d5784859c88da874f28412f37fb327bc21b7b14c5d61ef94" CACHE STRING "SHA256 checksum for Sparkle release archive")
@ -248,13 +328,11 @@ if(UNIX AND APPLE)
install(FILES ${Launcher_Branding_ICNS} DESTINATION ${RESOURCES_DEST_DIR} RENAME ${Launcher_Name}.icns) install(FILES ${Launcher_Branding_ICNS} DESTINATION ${RESOURCES_DEST_DIR} RENAME ${Launcher_Name}.icns)
elseif(UNIX) elseif(UNIX)
include(KDEInstallDirs)
set(BINARY_DEST_DIR "bin") set(BINARY_DEST_DIR "bin")
set(LIBRARY_DEST_DIR "lib${LIB_SUFFIX}") set(LIBRARY_DEST_DIR "lib${LIB_SUFFIX}")
set(JARS_DEST_DIR "share/jars") set(JARS_DEST_DIR "share/${Launcher_APP_BINARY_NAME}")
set(LAUNCHER_DESKTOP_DEST_DIR "share/applications" CACHE STRING "Path to the desktop file directory")
set(LAUNCHER_METAINFO_DEST_DIR "share/metainfo" CACHE STRING "Path to the metainfo directory")
set(LAUNCHER_ICON_DEST_DIR "share/icons/hicolor/scalable/apps" CACHE STRING "Path to the scalable icon directory")
set(LAUNCHER_MAN_DEST_DIR "share/man/man6" CACHE STRING "Path to the man page directory")
# install as bundle with no dependencies included # install as bundle with no dependencies included
set(INSTALL_BUNDLE "nodeps") set(INSTALL_BUNDLE "nodeps")
@ -262,12 +340,15 @@ elseif(UNIX)
# Set RPATH # Set RPATH
SET(Launcher_BINARY_RPATH "$ORIGIN/") SET(Launcher_BINARY_RPATH "$ORIGIN/")
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${Launcher_Desktop} DESTINATION ${LAUNCHER_DESKTOP_DEST_DIR}) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${Launcher_Desktop} DESTINATION ${KDE_INSTALL_APPDIR})
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${Launcher_MetaInfo} DESTINATION ${LAUNCHER_METAINFO_DEST_DIR}) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${Launcher_MetaInfo} DESTINATION ${KDE_INSTALL_METAINFODIR})
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/${Launcher_SVG} DESTINATION ${LAUNCHER_ICON_DEST_DIR}) install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/${Launcher_SVG} DESTINATION "${KDE_INSTALL_ICONDIR}/hicolor/scalable/apps")
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/${Launcher_mrpack_MIMEInfo} DESTINATION ${KDE_INSTALL_MIMEDIR})
install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/launcher/qtlogging.ini" DESTINATION "${KDE_INSTALL_DATADIR}/${Launcher_Name}")
if(Launcher_ManPage) if(Launcher_ManPage)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${Launcher_ManPage} DESTINATION ${LAUNCHER_MAN_DEST_DIR}) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${Launcher_ManPage} DESTINATION "${KDE_INSTALL_MANDIR}/man6")
endif() endif()
# Install basic runner script if component "portable" is selected # Install basic runner script if component "portable" is selected
@ -293,6 +374,8 @@ else()
message(FATAL_ERROR "Platform not supported") message(FATAL_ERROR "Platform not supported")
endif() endif()
################################ Included Libs ################################ ################################ Included Libs ################################
include(ExternalProject) include(ExternalProject)
@ -304,10 +387,34 @@ option(NBT_BUILD_TESTS "Build NBT library tests" OFF) #FIXME: fix unit tests.
add_subdirectory(libraries/libnbtplusplus) add_subdirectory(libraries/libnbtplusplus)
add_subdirectory(libraries/systeminfo) # system information library add_subdirectory(libraries/systeminfo) # system information library
add_subdirectory(libraries/hoedown) # markdown parser
add_subdirectory(libraries/launcher) # java based launcher part for Minecraft add_subdirectory(libraries/launcher) # java based launcher part for Minecraft
add_subdirectory(libraries/javacheck) # java compatibility checker add_subdirectory(libraries/javacheck) # java compatibility checker
add_subdirectory(libraries/xz-embedded) # xz compression if(FORCE_BUNDLED_ZLIB)
message(STATUS "Using bundled zlib")
set(CMAKE_POLICY_DEFAULT_CMP0069 NEW) # Suppress cmake warnings and allow INTERPROCEDURAL_OPTIMIZATION for zlib
set(SKIP_INSTALL_ALL ON)
add_subdirectory(libraries/zlib EXCLUDE_FROM_ALL)
# On OS where unistd.h exists, zlib's generated header defines `Z_HAVE_UNISTD_H`, while the included header does not.
# We cannot safely undo the rename on those systems, and they generally have packages for zlib anyway.
check_include_file(unistd.h NEED_GENERATED_ZCONF)
if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/libraries/zlib/zconf.h.included" AND NOT NEED_GENERATED_ZCONF)
# zlib's cmake script renames a file, dirtying the submodule, see https://github.com/madler/zlib/issues/162
message(STATUS "Undoing Rename")
message(STATUS " ${CMAKE_CURRENT_SOURCE_DIR}/libraries/zlib/zconf.h")
file(RENAME "${CMAKE_CURRENT_SOURCE_DIR}/libraries/zlib/zconf.h.included" "${CMAKE_CURRENT_SOURCE_DIR}/libraries/zlib/zconf.h")
endif()
set(ZLIB_INCLUDE_DIR "${CMAKE_CURRENT_BINARY_DIR}/libraries/zlib" "${CMAKE_CURRENT_SOURCE_DIR}/libraries/zlib" CACHE STRING "" FORCE)
set_target_properties(zlibstatic PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${ZLIB_INCLUDE_DIR}")
add_library(ZLIB::ZLIB ALIAS zlibstatic)
set(ZLIB_LIBRARY ZLIB::ZLIB CACHE STRING "zlib library name")
find_package(ZLIB REQUIRED)
else()
message(STATUS "Using system zlib")
endif()
if (FORCE_BUNDLED_QUAZIP) if (FORCE_BUNDLED_QUAZIP)
message(STATUS "Using bundled QuaZip") message(STATUS "Using bundled QuaZip")
set(BUILD_SHARED_LIBS 0) # link statically to avoid conflicts. set(BUILD_SHARED_LIBS 0) # link statically to avoid conflicts.
@ -318,16 +425,39 @@ else()
endif() endif()
add_subdirectory(libraries/rainbow) # Qt extension for colors add_subdirectory(libraries/rainbow) # Qt extension for colors
add_subdirectory(libraries/LocalPeer) # fork of a library from Qt solutions add_subdirectory(libraries/LocalPeer) # fork of a library from Qt solutions
add_subdirectory(libraries/classparser) # class parser library if(NOT tomlplusplus_FOUND)
add_subdirectory(libraries/optional-bare) message(STATUS "Using bundled tomlplusplus")
add_subdirectory(libraries/tomlc99) # toml parser add_subdirectory(libraries/tomlplusplus) # toml parser
else()
message(STATUS "Using system tomlplusplus")
endif()
if(NOT cmark_FOUND)
message(STATUS "Using bundled cmark")
set(CMARK_STATIC ON CACHE BOOL "Build static libcmark library" FORCE)
set(CMARK_SHARED OFF CACHE BOOL "Build shared libcmark library" FORCE)
set(CMARK_TESTS OFF CACHE BOOL "Build cmark tests and enable testing" FORCE)
add_subdirectory(libraries/cmark EXCLUDE_FROM_ALL) # Markdown parser
add_library(cmark::cmark ALIAS cmark_static)
else()
message(STATUS "Using system cmark")
endif()
add_subdirectory(libraries/katabasis) # An OAuth2 library that tried to do too much add_subdirectory(libraries/katabasis) # An OAuth2 library that tried to do too much
add_subdirectory(libraries/gamemode) add_subdirectory(libraries/gamemode)
add_subdirectory(libraries/murmur2) # Hash for usage with the CurseForge API 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 ############################### ############################### Built Artifacts ###############################
add_subdirectory(buildconfig) add_subdirectory(buildconfig)
if(BUILD_TESTING)
add_subdirectory(tests)
endif()
# NOTE: this must always be last to appease the CMake deity of quirky install command evaluation order. # NOTE: this must always be last to appease the CMake deity of quirky install command evaluation order.
add_subdirectory(launcher) add_subdirectory(launcher)

View File

@ -1,4 +1,5 @@
# Contributor Covenant Code of Conduct # Contributor Covenant Code of Conduct
This is a modified version of the Contributor Covenant. This is a modified version of the Contributor Covenant.
See commit history to see our changes. See commit history to see our changes.
@ -62,7 +63,7 @@ representative at an online or offline event.
Instances of abusive, harassing, or otherwise unacceptable behavior may be Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported to the community leaders responsible for enforcement via email at reported to the community leaders responsible for enforcement via email at
[polymc-enforcement@scrumplex.net](mailto:polymc-enforcement@scrumplex.net) (Email [coc@scrumplex.net](mailto:coc@scrumplex.net) (Email
address subject to change). address subject to change).
All complaints will be reviewed and investigated promptly and fairly. All complaints will be reviewed and investigated promptly and fairly.
@ -133,4 +134,3 @@ For answers to common questions about this code of conduct, see the FAQ at
[Mozilla CoC]: https://github.com/mozilla/diversity [Mozilla CoC]: https://github.com/mozilla/diversity
[FAQ]: https://www.contributor-covenant.org/faq [FAQ]: https://www.contributor-covenant.org/faq
[translations]: https://www.contributor-covenant.org/translations [translations]: https://www.contributor-covenant.org/translations

View File

@ -6,6 +6,7 @@ Try to follow the existing formatting.
If there is no existing formatting, you may use `clang-format` with our included `.clang-format` configuration. If there is no existing formatting, you may use `clang-format` with our included `.clang-format` configuration.
In general, in order of importance: In general, in order of importance:
- Make sure your IDE is not messing up line endings or whitespace and avoid using linters. - Make sure your IDE is not messing up line endings or whitespace and avoid using linters.
- Prefer readability over dogma. - Prefer readability over dogma.
- Keep to the existing formatting. - Keep to the existing formatting.
@ -26,37 +27,37 @@ Signed-off-by: Author name <Author email>
By signing off your work, you agree to the terms below: By signing off your work, you agree to the terms below:
Developer's Certificate of Origin 1.1 ```
Developer's Certificate of Origin 1.1
By making a contribution to this project, I certify that: By making a contribution to this project, I certify that:
(a) The contribution was created in whole or in part by me and I (a) The contribution was created in whole or in part by me and I
have the right to submit it under the open source license have the right to submit it under the open source license
indicated in the file; or indicated in the file; or
(b) The contribution is based upon previous work that, to the best (b) The contribution is based upon previous work that, to the best
of my knowledge, is covered under an appropriate open source of my knowledge, is covered under an appropriate open source
license and I have the right under that license to submit that license and I have the right under that license to submit that
work with modifications, whether created in whole or in part work with modifications, whether created in whole or in part
by me, under the same open source license (unless I am by me, under the same open source license (unless I am
permitted to submit under a different license), as indicated permitted to submit under a different license), as indicated
in the file; or in the file; or
(c) The contribution was provided directly to me by some other (c) The contribution was provided directly to me by some other
person who certified (a), (b) or (c) and I have not modified person who certified (a), (b) or (c) and I have not modified
it. it.
(d) I understand and agree that this project and the contribution (d) I understand and agree that this project and the contribution
are public and that a record of the contribution (including all are public and that a record of the contribution (including all
personal information I submit with it, including my sign-off) is personal information I submit with it, including my sign-off) is
maintained indefinitely and may be redistributed consistent with maintained indefinitely and may be redistributed consistent with
this project or the open source license(s) involved. this project or the open source license(s) involved.
```
These terms will be enforced once you create a pull request, and you will be informed automatically if any of your commits aren't signed-off by you. These terms will be enforced once you create a pull request, and you will be informed automatically if any of your commits aren't signed-off by you.
As a bonus, you can also [cryptographically sign your commits][gh-signing-commits] and enable [vigilant mode][gh-vigilant-mode] on GitHub. As a bonus, you can also [cryptographically sign your commits][gh-signing-commits] and enable [vigilant mode][gh-vigilant-mode] on GitHub.
[gh-signing-commits]: https://docs.github.com/en/authentication/managing-commit-signature-verification/signing-commits [gh-signing-commits]: https://docs.github.com/en/authentication/managing-commit-signature-verification/signing-commits
[gh-vigilant-mode]: https://docs.github.com/en/authentication/managing-commit-signature-verification/displaying-verification-statuses-for-all-of-your-commits [gh-vigilant-mode]: https://docs.github.com/en/authentication/managing-commit-signature-verification/displaying-verification-statuses-for-all-of-your-commits

View File

@ -1,4 +1,38 @@
# PolyMC ## Prism Launcher
Prism Launcher - Minecraft Launcher
Copyright (C) 2022-2023 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
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.
## PolyMC
PolyMC - Minecraft Launcher PolyMC - Minecraft Launcher
Copyright (C) 2021-2022 PolyMC Contributors Copyright (C) 2021-2022 PolyMC Contributors
@ -32,36 +66,56 @@
See the License for the specific language governing permissions and See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
# MinGW runtime (Windows) ## MinGW-w64 runtime (Windows)
Copyright (c) 2012 MinGW.org project Copyright (c) 2009, 2010, 2011, 2012, 2013 by the mingw-w64 project
Permission is hereby granted, free of charge, to any person obtaining a This license has been certified as open source. It has also been designated
copy of this software and associated documentation files (the "Software"), as GPL compatible by the Free Software Foundation (FSF).
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, this permission notice and the below disclaimer Redistribution and use in source and binary forms, with or without
shall be included in all copies or substantial portions of the Software. modification, are permitted provided that the following conditions are met:
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 1. Redistributions in source code must retain the accompanying copyright
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, notice, this list of conditions, and the following disclaimer.
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 2. Redistributions in binary form must reproduce the accompanying
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER copyright notice, this list of conditions, and the following disclaimer
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING in the documentation and/or other materials provided with the
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER distribution.
DEALINGS IN THE SOFTWARE. 3. Names of the copyright holders must not be used to endorse or promote
products derived from this software without prior written permission
from the copyright holders.
4. The right to distribute this software or to use it for any purpose does
not give you the right to use Servicemarks (sm) or Trademarks (tm) of
the copyright holders. Use of them is covered by separate agreement
with the copyright holders.
5. If any files are modified, you must cause the modified files to carry
prominent notices stating that you changed the files and the date of
any change.
# Qt 5/6 Disclaimer
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY EXPRESSED
OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Information on third party licenses used in MinGW-w64 can be found in its COPYING.MinGW-w64-runtime.txt.
## Qt 5/6
Copyright (C) 2022 The Qt Company Ltd and other contributors. Copyright (C) 2022 The Qt Company Ltd and other contributors.
Contact: https://www.qt.io/licensing Contact: https://www.qt.io/licensing
Licensed under LGPL v3 Licensed under LGPL v3
# libnbt++ ## libnbt++
libnbt++ - A library for the Minecraft Named Binary Tag format. libnbt++ - A library for the Minecraft Named Binary Tag format.
Copyright (C) 2013, 2015 ljfa-ag Copyright (C) 2013, 2015 ljfa-ag
@ -79,7 +133,7 @@
You should have received a copy of the GNU Lesser General Public License You should have received a copy of the GNU Lesser General Public License
along with libnbt++. If not, see <http://www.gnu.org/licenses/>. along with libnbt++. If not, see <http://www.gnu.org/licenses/>.
# rainbow (KGuiAddons) ## rainbow (KGuiAddons)
Copyright (C) 2007 Matthew Woehlke <mw_triad@users.sourceforge.net> Copyright (C) 2007 Matthew Woehlke <mw_triad@users.sourceforge.net>
Copyright (C) 2007 Olaf Schmidt <ojschmidt@kde.org> Copyright (C) 2007 Olaf Schmidt <ojschmidt@kde.org>
@ -102,25 +156,36 @@
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA. Boston, MA 02110-1301, USA.
# Hoedown ## cmark
Copyright (c) 2008, Natacha Porté Copyright (c) 2014, John MacFarlane
Copyright (c) 2011, Vicent Martí
Copyright (c) 2014, Xavier Mendez, Devin Torres and the Hoedown authors
Permission to use, copy, modify, and distribute this software for any All rights reserved.
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES Redistribution and use in source and binary forms, with or without
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF modification, are permitted provided that the following conditions are met:
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
# Batch icon set * Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials provided
with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
## Batch icon set
You are free to use Batch (the "icon set") or any part thereof (the "icons") You are free to use Batch (the "icon set") or any part thereof (the "icons")
in any personal, open-source or commercial work without obligation of payment in any personal, open-source or commercial work without obligation of payment
@ -136,7 +201,7 @@
PUNITIVE OR EXEMPLARY DAMAGES ARISING OUT OF THE USE OF THE ICONS, PUNITIVE OR EXEMPLARY DAMAGES ARISING OUT OF THE USE OF THE ICONS,
EVEN IF LICENSOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. EVEN IF LICENSOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
# Material Design Icons ## Material Design Icons
Copyright (c) 2014, Austin Andrews (http://materialdesignicons.com/), Copyright (c) 2014, Austin Andrews (http://materialdesignicons.com/),
with Reserved Font Name Material Design Icons. with Reserved Font Name Material Design Icons.
@ -147,7 +212,7 @@
This license is copied below, and is also available with a FAQ at: This license is copied below, and is also available with a FAQ at:
http://scripts.sil.org/OFL http://scripts.sil.org/OFL
# Quazip ## Quazip
Copyright (C) 2005-2021 Sergey A. Tachenov Copyright (C) 2005-2021 Sergey A. Tachenov
@ -171,53 +236,7 @@
See COPYING file for the full LGPL text. See COPYING file for the full LGPL text.
# xz-minidec ## launcher (`libraries/launcher`)
XZ decompressor
Authors: Lasse Collin <lasse.collin@tukaani.org>
Igor Pavlov <http://7-zip.org/>
This file has been put into the public domain.
You can do whatever you want with this file.
# ColumnResizer
Copyright (c) 2011-2016 Aurélien Gâteau and contributors.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted (subject to the limitations in the
disclaimer below) provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the
distribution.
* The name of the contributors may not be used to endorse or
promote products derived from this software without specific prior
written permission.
NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE
GRANTED BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT
HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
# launcher (`libraries/launcher`)
PolyMC - Minecraft Launcher PolyMC - Minecraft Launcher
Copyright (C) 2021-2022 PolyMC Contributors Copyright (C) 2021-2022 PolyMC Contributors
@ -268,7 +287,7 @@
See the License for the specific language governing permissions and See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
# lionshead ## lionshead
Code has been taken from https://github.com/natefoo/lionshead and loosely Code has been taken from https://github.com/natefoo/lionshead and loosely
translated to C++ laced with Qt. translated to C++ laced with Qt.
@ -295,60 +314,26 @@
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE. SOFTWARE.
# optional-bare ## tomlplusplus
Code from https://github.com/martinmoene/optional-bare/
Boost Software License - Version 1.0 - August 17th, 2003
Permission is hereby granted, free of charge, to any person or organization
obtaining a copy of the software and accompanying documentation covered by
this license (the "Software") to use, reproduce, display, distribute,
execute, and transmit the Software, and to prepare derivative works of the
Software, and to permit third-parties to whom the Software is furnished to
do so, all subject to the following:
The copyright notices in the Software and this entire statement, including
the above license grant, this restriction and the following disclaimer,
must be included in all copies of the Software, in whole or in part, and
all derivative works of the Software, unless such copies or derivative
works are solely in the form of machine-executable object code generated by
a source language processor.
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, TITLE AND NON-INFRINGEMENT. IN NO EVENT
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
# tomlc99
MIT License MIT License
Copyright (c) 2017 CK Tan Copyright (c) Mark Gillard <mark.gillard@outlook.com.au>
https://github.com/cktan/tomlc99
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
of this software and associated documentation files (the "Software"), to deal documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
in the Software without restriction, including without limitation the rights rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell permit persons to whom the Software is furnished to do so, subject to the following conditions:
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 The above copyright notice and this permission notice shall be included in all copies or substantial portions of the
copies or substantial portions of the Software. Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
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.
# O2 (Katabasis fork) ## O2 (Katabasis fork)
Copyright (c) 2012, Akos Polster Copyright (c) 2012, Akos Polster
All rights reserved. All rights reserved.
@ -373,3 +358,96 @@
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
## Gamemode
Copyright (c) 2017-2022, Feral Interactive
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of Feral Interactive nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
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
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 3 of the License, or (at your option) any later version.
This library 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
Lesser General Public License for more details.
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/>.
## Oxygen Icons
The Oxygen Icon Theme
Copyright (C) 2007 Nuno Pinheiro <nuno@oxygen-icons.org>
Copyright (C) 2007 David Vignoni <david@icon-king.com>
Copyright (C) 2007 David Miller <miller@oxygen-icons.org>
Copyright (C) 2007 Johann Ollivier Lapeyre <johann@oxygen-icons.org>
Copyright (C) 2007 Kenneth Wimer <kwwii@bootsplash.org>
Copyright (C) 2007 Riccardo Iaconelli <riccardo@oxygen-icons.org>
and others
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 3 of the License, or (at your option) any later version.
This library 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
Lesser General Public License for more details.
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/>.

127
README.md
View File

@ -1,98 +1,103 @@
<p align="center"> <p align="center">
<img src="./program_info/polymc-header-black.svg#gh-light-mode-only" alt="PolyMC logo" width="50%"/> <picture>
<img src="./program_info/polymc-header.svg#gh-dark-mode-only" alt="PolyMC logo" width="50%"/> <source media="(prefers-color-scheme: dark)" srcset="/program_info/org.prismlauncher.PrismLauncher.logo-darkmode.svg">
<source media="(prefers-color-scheme: light)" srcset="/program_info/org.prismlauncher.PrismLauncher.logo.svg">
<img alt="Prism Launcher" src="/program_info/org.prismlauncher.PrismLauncher.logo.svg" width="40%">
</picture>
</p> </p>
PolyMC is a custom launcher for Minecraft that focuses on predictability, long term stability and simplicity. <p align="center">
Prism Launcher is a custom launcher for Minecraft that allows you to easily manage multiple installations of Minecraft at once.<br />
<br />This is a <b>fork</b> of the MultiMC Launcher and is <b>not</b> endorsed by it.
</p>
This is a **fork** of the MultiMC Launcher and not endorsed by MultiMC. ## Installation
If you want to read about why this fork was created, check out [our FAQ page](https://polymc.org/wiki/overview/faq/).
<br>
# Installation <a href="https://repology.org/project/prismlauncher/versions">
<img src="https://repology.org/badge/vertical-allrepos/prismlauncher.svg" alt="Packaging status" align="right">
</a>
- All downloads and instructions for PolyMC can be found [here](https://polymc.org/download/) - All downloads and instructions for Prism Launcher can be found on our [Website](https://prismlauncher.org/download).
- Last build status: https://github.com/PolyMC/PolyMC/actions - Last build status can be found in the [GitHub Actions](https://github.com/PrismLauncher/PrismLauncher/actions).
### Development Builds
## Development Builds There are development builds available [here](https://github.com/PrismLauncher/PrismLauncher/actions). These have debug information in the binaries, so their file sizes are relatively larger.
There are per-commit development builds available [here](https://github.com/PolyMC/PolyMC/actions). These have debug information in the binaries, so their file sizes are relatively larger. Prebuilt Development builds are provided for **Linux**, **Windows** and **macOS**.
Portable builds are provided for AppImage on Linux, Windows, and macOS.
For Debian and Arch, you can use these packages for the latest development versions: For **Arch**, **Debian**, **Fedora**, **OpenSUSE (Tumbleweed)** and **Gentoo**, respectively, you can use these packages for the latest development versions:
[![polymc-git](https://img.shields.io/badge/aur-polymc--git-blue)](https://aur.archlinux.org/packages/polymc-git/)
[![polymc-git](https://img.shields.io/badge/mpr-polymc--git-orange)](https://mpr.makedeb.org/packages/polymc-git)
For flatpak, you can use [flathub-beta](https://discourse.flathub.org/t/how-to-use-flathub-beta/2111)
# Help & Support [![prismlauncher-git](https://img.shields.io/badge/aur-prismlauncher--git-1793D1?label=AUR&logo=archlinux&logoColor=white)](https://aur.archlinux.org/packages/prismlauncher-git) [![prismlauncher-git](https://img.shields.io/badge/aur-prismlauncher--qt5--git-1793D1?label=AUR&logo=archlinux&logoColor=white)](https://aur.archlinux.org/packages/prismlauncher-qt5-git) [![prismlauncher-git](https://img.shields.io/badge/mpr-prismlauncher--git-A80030?label=MPR&logo=debian&logoColor=white)](https://mpr.makedeb.org/packages/prismlauncher-git)<br />[![prismlauncher-nightly](https://img.shields.io/badge/copr-prismlauncher--nightly-51A2DA?label=COPR&logo=fedora&logoColor=white)](https://copr.fedorainfracloud.org/coprs/g3tchoo/prismlauncher/) [![prismlauncher-nightly](https://img.shields.io/badge/OBS-prismlauncher--nightly-3AB6A9?logo=opensuse&logoColor=white)](https://build.opensuse.org/project/show/home:getchoo) [![prismlauncher-9999](https://img.shields.io/badge/gentoo-prismlauncher--9999-4D4270?label=Gentoo&logo=gentoo&logoColor=white)](https://packages.gentoo.org/packages/games-action/prismlauncher)
Feel free to create an issue if you need help. However, you might find it easier to ask in the Discord server. These packages are also availiable to all the distributions based on the ones mentioned above.
[![PolyMC Discord](https://img.shields.io/discord/923671181020766230?label=PolyMC%20Discord)](https://discord.gg/xq7fxrgtMP) ## Community & Support
For people who don't want to use Discord, we have a Matrix Space which is bridged to the Discord server: Feel free to create a GitHub issue if you find a bug or want to suggest a new feature. We have multiple community spaces where other community members can help you:
[![PolyMC Space](https://img.shields.io/matrix/polymc:matrix.org?label=PolyMC%20space)](https://matrix.to/#/#polymc:matrix.org) - **Our Discord server:**
If there are any issues with the space or you are using a client that does not support the feature here are the individual rooms: [![Prism Launcher Discord server](https://discordapp.com/api/guilds/1031648380885147709/widget.png?style=banner3)](https://prismlauncher.org/discord)
[![Development](https://img.shields.io/matrix/polymc-development:matrix.org?label=PolyMC%20Development)](https://matrix.to/#/#polymc-development:matrix.org) - **Our Matrix space:**
[![Discussion](https://img.shields.io/matrix/polymc-discussion:matrix.org?label=PolyMC%20Discussion)](https://matrix.to/#/#polymc-discussion:matrix.org)
[![Github](https://img.shields.io/matrix/polymc-github:matrix.org?label=PolyMC%20Github)](https://matrix.to/#/#polymc-github:matrix.org)
[![Maintainers](https://img.shields.io/matrix/polymc-maintainers:matrix.org?label=PolyMC%20Maintainers)](https://matrix.to/#/#polymc-maintainers:matrix.org)
[![News](https://img.shields.io/matrix/polymc-news:matrix.org?label=PolyMC%20News)](https://matrix.to/#/#polymc-news:matrix.org)
[![Offtopic](https://img.shields.io/matrix/polymc-offtopic:matrix.org?label=PolyMC%20Offtopic)](https://matrix.to/#/#polymc-offtopic:matrix.org)
[![Support](https://img.shields.io/matrix/polymc-support:matrix.org?label=PolyMC%20Support)](https://matrix.to/#/#polymc-support:matrix.org)
[![Voice](https://img.shields.io/matrix/polymc-voice:matrix.org?label=PolyMC%20Voice)](https://matrix.to/#/#polymc-voice:matrix.org)
We also have a subreddit you can post your issues and suggestions on: [![PrismLauncher Space](https://img.shields.io/matrix/prismlauncher:matrix.org?style=for-the-badge&label=Matrix%20Space&logo=matrix&color=purple)](https://prismlauncher.org/matrix)
[r/PolyMCLauncher](https://www.reddit.com/r/PolyMCLauncher/) - **Our Subreddit:**
# Development [![r/PrismLauncher](https://img.shields.io/reddit/subreddit-subscribers/prismlauncher?style=for-the-badge&logo=reddit)](https://prismlauncher.org/reddit)
If you want to contribute to PolyMC you might find it useful to join our Discord Server or Matrix Space.
## Building
If you want to build PolyMC yourself, check [Build Instructions](https://polymc.org/wiki/development/build-instructions/) for build instructions.
## Translations ## Translations
The translation effort for PolyMC is hosted on [Weblate](https://hosted.weblate.org/projects/polymc/polymc/) and information about translating PolyMC is available at https://github.com/PolyMC/Translations The translation effort for PrismLauncher is hosted on [Weblate](https://hosted.weblate.org/projects/prismlauncher/launcher/) and information about translating Prism Launcher is available at <https://github.com/PrismLauncher/Translations>
## Download information ## Building
To modify download information or change packaging information send a pull request or issue to the website [here](https://github.com/PolyMC/polymc.github.io/tree/master/src/download). If you want to build Prism Launcher yourself, check the [Build Instructions](https://prismlauncher.org/wiki/development/build-instructions/).
## Sponsors & Partners
We thank all the wonderful backers over at Open Collective! Support Prism Launcher by [becoming a backer](https://opencollective.com/prismlauncher).
[![OpenCollective Backers](https://opencollective.com/prismlauncher/backers.svg?width=890&limit=1000)](https://opencollective.com/prismlauncher#backers)
Thanks to JetBrains for providing us a few licenses for all their products, as part of their [Open Source program](https://www.jetbrains.com/opensource/).
[![JetBrains](https://resources.jetbrains.com/storage/products/company/brand/logos/jb_beam.svg)](https://www.jetbrains.com/opensource/)
Thanks to Weblate for hosting our translation efforts.
<a href="https://hosted.weblate.org/engage/prismlauncher/">
<img src="https://hosted.weblate.org/widgets/prismlauncher/-/open-graph.png" alt="Translation status" width="300" />
</a>
Thanks to Netlify for providing us their excellent web services, as part of their [Open Source program](https://www.netlify.com/open-source/).
<a href="https://www.netlify.com"> <img src="https://www.netlify.com/v3/img/components/netlify-color-accent.svg" alt="Deploys by Netlify" /> </a>
Thanks to the awesome people over at [MacStadium](https://www.macstadium.com/), for providing M1-Macs for development purposes!
<a href="https://www.macstadium.com"><img src="https://uploads-ssl.webflow.com/5ac3c046c82724970fc60918/5c019d917bba312af7553b49_MacStadium-developerlogo.png" alt="Powered by MacStadium" width="300"></a>
## Forking/Redistributing/Custom builds policy ## Forking/Redistributing/Custom builds policy
We don't care what you do with your fork/custom build as long as you follow the terms of the [license](LICENSE) (this is a legal responsibility), and if you made code changes rather than just packaging a custom build, please do the following as a basic courtesy: We don't care what you do with your fork/custom build as long as you follow the terms of the [license](LICENSE) (this is a legal responsibility), and if you made code changes rather than just packaging a custom build, please do the following as a basic courtesy:
- Make it clear that your fork is not PolyMC and is not endorsed by or affiliated with the PolyMC project (https://polymc.org).
- Go through [CMakeLists.txt](CMakeLists.txt) and change PolyMC's API keys to your own or set them to empty strings (`""`) to disable them (this way the program will still compile but the functionality requiring those keys will be disabled). - Make it clear that your fork is not PrismLauncher and is not endorsed by or affiliated with the PrismLauncher project (<https://prismlauncher.org>).
- Go through [CMakeLists.txt](CMakeLists.txt) and change PrismLauncher's API keys to your own or set them to empty strings (`""`) to disable them (this way the program will still compile but the functionality requiring those keys will be disabled).
If you have any questions or want any clarification on the above conditions please make an issue and ask us. If you have any questions or want any clarification on the above conditions please make an issue and ask us.
Be aware that if you build this software without removing the provided API keys in [CMakeLists.txt](CMakeLists.txt) you are accepting the following terms and conditions: Be aware that if you build this software without removing the provided API keys in [CMakeLists.txt](CMakeLists.txt) you are accepting the following terms and conditions:
- [Microsoft Identity Platform Terms of Use](https://docs.microsoft.com/en-us/legal/microsoft-identity-platform/terms-of-use)
- [CurseForge 3rd Party API Terms and Conditions](https://support.curseforge.com/en/support/solutions/articles/9000207405-curse-forge-3rd-party-api-terms-and-conditions) - [Microsoft Identity Platform Terms of Use](https://docs.microsoft.com/en-us/legal/microsoft-identity-platform/terms-of-use)
- [CurseForge 3rd Party API Terms and Conditions](https://support.curseforge.com/en/support/solutions/articles/9000207405-curse-forge-3rd-party-api-terms-and-conditions)
If you do not agree with these terms and conditions, then remove the associated API keys from the [CMakeLists.txt](CMakeLists.txt) file by setting them to an empty string (`""`). If you do not agree with these terms and conditions, then remove the associated API keys from the [CMakeLists.txt](CMakeLists.txt) file by setting them to an empty string (`""`).
## License [![https://github.com/PrismLauncher/PrismLauncher/blob/develop/LICENSE](https://img.shields.io/github/license/PrismLauncher/PrismLauncher?label=License&logo=gnu&color=C4282D)](LICENSE)
All launcher code is available under the GPL-3.0-only license. All launcher code is available under the GPL-3.0-only license.
The logo and related assets are under the CC BY-SA 4.0 license. The logo and related assets are under the CC BY-SA 4.0 license.
## Sponsors
Thank you to all our generous backers over at Open Collective! Support PolyMC by [becoming a backer](https://opencollective.com/polymc).
[![OpenCollective Backers](https://opencollective.com/polymc/backers.svg?width=890&limit=1000)](https://opencollective.com/polymc#backers)
Also, thanks to JetBrains for providing us a few licenses for all their products, as part of their [Open Source program](https://www.jetbrains.com/opensource/).
[![JetBrains](https://resources.jetbrains.com/storage/products/company/brand/logos/jb_beam.svg)](https://www.jetbrains.com/opensource/)
Additionally, thanks to the awesome people over at [MacStadium](https://www.macstadium.com/), for providing M1-Macs for development purposes!
<a href="https://www.macstadium.com"><img src="https://uploads-ssl.webflow.com/5ac3c046c82724970fc60918/5c019d917bba312af7553b49_MacStadium-developerlogo.png" alt="Powered by MacStadium" width="300"></a>

View File

@ -42,12 +42,14 @@ Config::Config()
{ {
// Name and copyright // Name and copyright
LAUNCHER_NAME = "@Launcher_Name@"; LAUNCHER_NAME = "@Launcher_Name@";
LAUNCHER_APP_BINARY_NAME = "@Launcher_APP_BINARY_NAME@";
LAUNCHER_DISPLAYNAME = "@Launcher_DisplayName@"; LAUNCHER_DISPLAYNAME = "@Launcher_DisplayName@";
LAUNCHER_COPYRIGHT = "@Launcher_Copyright@"; LAUNCHER_COPYRIGHT = "@Launcher_Copyright@";
LAUNCHER_DOMAIN = "@Launcher_Domain@"; LAUNCHER_DOMAIN = "@Launcher_Domain@";
LAUNCHER_CONFIGFILE = "@Launcher_ConfigFile@"; LAUNCHER_CONFIGFILE = "@Launcher_ConfigFile@";
LAUNCHER_GIT = "@Launcher_Git@"; LAUNCHER_GIT = "@Launcher_Git@";
LAUNCHER_DESKTOPFILENAME = "@Launcher_DesktopFileName@"; LAUNCHER_DESKTOPFILENAME = "@Launcher_DesktopFileName@";
LAUNCHER_SVGFILENAME = "@Launcher_SVGFileName@";
USER_AGENT = "@Launcher_UserAgent@"; USER_AGENT = "@Launcher_UserAgent@";
USER_AGENT_UNCACHED = USER_AGENT + " (Uncached)"; USER_AGENT_UNCACHED = USER_AGENT + " (Uncached)";
@ -55,10 +57,9 @@ Config::Config()
// Version information // Version information
VERSION_MAJOR = @Launcher_VERSION_MAJOR@; VERSION_MAJOR = @Launcher_VERSION_MAJOR@;
VERSION_MINOR = @Launcher_VERSION_MINOR@; VERSION_MINOR = @Launcher_VERSION_MINOR@;
VERSION_HOTFIX = @Launcher_VERSION_HOTFIX@;
VERSION_BUILD = @Launcher_VERSION_BUILD@;
BUILD_PLATFORM = "@Launcher_BUILD_PLATFORM@"; BUILD_PLATFORM = "@Launcher_BUILD_PLATFORM@";
BUILD_DATE = "@Launcher_BUILD_TIMESTAMP@";
UPDATER_BASE = "@Launcher_UPDATER_BASE@"; UPDATER_BASE = "@Launcher_UPDATER_BASE@";
MAC_SPARKLE_PUB_KEY = "@MACOSX_SPARKLE_UPDATE_PUBLIC_KEY@"; MAC_SPARKLE_PUB_KEY = "@MACOSX_SPARKLE_UPDATE_PUBLIC_KEY@";
@ -75,7 +76,9 @@ Config::Config()
// Assume that builds outside of Git repos are "stable" // Assume that builds outside of Git repos are "stable"
if (GIT_REFSPEC == QStringLiteral("GITDIR-NOTFOUND") if (GIT_REFSPEC == QStringLiteral("GITDIR-NOTFOUND")
|| GIT_TAG == QStringLiteral("GITDIR-NOTFOUND")) || GIT_TAG == QStringLiteral("GITDIR-NOTFOUND")
|| GIT_REFSPEC == QStringLiteral("")
|| GIT_TAG == QStringLiteral("GIT-NOTFOUND"))
{ {
GIT_REFSPEC = "refs/heads/stable"; GIT_REFSPEC = "refs/heads/stable";
GIT_TAG = versionString(); GIT_TAG = versionString();
@ -85,7 +88,7 @@ Config::Config()
{ {
VERSION_CHANNEL = GIT_REFSPEC; VERSION_CHANNEL = GIT_REFSPEC;
VERSION_CHANNEL.remove("refs/heads/"); VERSION_CHANNEL.remove("refs/heads/");
if(!UPDATER_BASE.isEmpty() && !BUILD_PLATFORM.isEmpty() && VERSION_BUILD >= 0) { if(!UPDATER_BASE.isEmpty() && !BUILD_PLATFORM.isEmpty()) {
UPDATER_ENABLED = true; UPDATER_ENABLED = true;
} }
} }
@ -98,7 +101,6 @@ Config::Config()
VERSION_CHANNEL = "unknown"; VERSION_CHANNEL = "unknown";
} }
VERSION_STR = "@Launcher_VERSION_STRING@";
NEWS_RSS_URL = "@Launcher_NEWS_RSS_URL@"; NEWS_RSS_URL = "@Launcher_NEWS_RSS_URL@";
NEWS_OPEN_URL = "@Launcher_NEWS_OPEN_URL@"; NEWS_OPEN_URL = "@Launcher_NEWS_OPEN_URL@";
HELP_URL = "@Launcher_HELP_URL@"; HELP_URL = "@Launcher_HELP_URL@";
@ -116,7 +118,7 @@ Config::Config()
QString Config::versionString() const QString Config::versionString() const
{ {
return QString("%1.%2.%3").arg(VERSION_MAJOR).arg(VERSION_MINOR).arg(VERSION_HOTFIX); return QString("%1.%2").arg(VERSION_MAJOR).arg(VERSION_MINOR);
} }
QString Config::printableVersionString() const QString Config::printableVersionString() const
@ -128,11 +130,5 @@ QString Config::printableVersionString() const
{ {
vstr += "-" + VERSION_CHANNEL; vstr += "-" + VERSION_CHANNEL;
} }
// if a build number is set, also add it to the end
if(VERSION_BUILD >= 0)
{
vstr += "+build." + QString::number(VERSION_BUILD);
}
return vstr; return vstr;
} }

View File

@ -1,8 +1,9 @@
// SPDX-License-Identifier: GPL-3.0-only // SPDX-License-Identifier: GPL-3.0-only
/* /*
* PolyMC - Minecraft Launcher * Prism Launcher - Minecraft Launcher
* Copyright (c) 2022 Jamie Mansfield <jmansfield@cadixdev.org> * Copyright (c) 2022 Jamie Mansfield <jmansfield@cadixdev.org>
* Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net> * Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net>
* Copyright (C) 2023 TheKodeToad <TheKodeToad@proton.me>
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -36,6 +37,7 @@
#pragma once #pragma once
#include <QString> #include <QString>
#include <QList>
/** /**
* \brief The Config class holds all the build-time information passed from the build system. * \brief The Config class holds all the build-time information passed from the build system.
@ -44,21 +46,19 @@ class Config {
public: public:
Config(); Config();
QString LAUNCHER_NAME; QString LAUNCHER_NAME;
QString LAUNCHER_APP_BINARY_NAME;
QString LAUNCHER_DISPLAYNAME; QString LAUNCHER_DISPLAYNAME;
QString LAUNCHER_COPYRIGHT; QString LAUNCHER_COPYRIGHT;
QString LAUNCHER_DOMAIN; QString LAUNCHER_DOMAIN;
QString LAUNCHER_CONFIGFILE; QString LAUNCHER_CONFIGFILE;
QString LAUNCHER_GIT; QString LAUNCHER_GIT;
QString LAUNCHER_DESKTOPFILENAME; QString LAUNCHER_DESKTOPFILENAME;
QString LAUNCHER_SVGFILENAME;
/// The major version number. /// The major version number.
int VERSION_MAJOR; int VERSION_MAJOR;
/// The minor version number. /// The minor version number.
int VERSION_MINOR; int VERSION_MINOR;
/// The hotfix number.
int VERSION_HOTFIX;
/// The build number.
int VERSION_BUILD;
/** /**
* The version channel * The version channel
@ -71,6 +71,9 @@ class Config {
/// A short string identifying this build's platform. For example, "lin64" or "win32". /// A short string identifying this build's platform. For example, "lin64" or "win32".
QString BUILD_PLATFORM; QString BUILD_PLATFORM;
/// A string containing the build timestamp
QString BUILD_DATE;
/// URL for the updater's channel /// URL for the updater's channel
QString UPDATER_BASE; QString UPDATER_BASE;
@ -95,9 +98,6 @@ class Config {
/// The git refspec of this build /// The git refspec of this build
QString GIT_REFSPEC; QString GIT_REFSPEC;
/// This is printed on start to standard output
QString VERSION_STR;
/** /**
* This is used to fetch the news RSS feed. * This is used to fetch the news RSS feed.
* It defaults in CMakeLists.txt to "https://multimc.org/rss.xml" * It defaults in CMakeLists.txt to "https://multimc.org/rss.xml"
@ -144,8 +144,8 @@ class Config {
QString LIBRARY_BASE = "https://libraries.minecraft.net/"; QString LIBRARY_BASE = "https://libraries.minecraft.net/";
QString AUTH_BASE = "https://authserver.mojang.com/"; QString AUTH_BASE = "https://authserver.mojang.com/";
QString IMGUR_BASE_URL = "https://api.imgur.com/3/"; QString IMGUR_BASE_URL = "https://api.imgur.com/3/";
QString FMLLIBS_BASE_URL = "https://files.polymc.org/fmllibs/"; QString FMLLIBS_BASE_URL = "https://files.prismlauncher.org/fmllibs/"; // FIXME: move into CMakeLists
QString TRANSLATIONS_BASE_URL = "https://i18n.polymc.org/"; QString TRANSLATIONS_BASE_URL = "https://i18n.prismlauncher.org/"; // FIXME: move into CMakeLists
QString MODPACKSCH_API_BASE_URL = "https://api.modpacks.ch/"; QString MODPACKSCH_API_BASE_URL = "https://api.modpacks.ch/";
@ -162,6 +162,9 @@ class Config {
QString MODRINTH_STAGING_URL = "https://staging-api.modrinth.com/v2"; QString MODRINTH_STAGING_URL = "https://staging-api.modrinth.com/v2";
QString MODRINTH_PROD_URL = "https://api.modrinth.com/v2"; QString MODRINTH_PROD_URL = "https://api.modrinth.com/v2";
QStringList MODRINTH_MRPACK_HOSTS{"cdn.modrinth.com", "github.com", "raw.githubusercontent.com", "gitlab.com"};
QString FLAME_BASE_URL = "https://api.curseforge.com/v1";
QString versionString() const; QString versionString() const;
/** /**

View File

@ -44,5 +44,28 @@
<string>${MACOSX_SPARKLE_UPDATE_PUBLIC_KEY}</string> <string>${MACOSX_SPARKLE_UPDATE_PUBLIC_KEY}</string>
<key>SUFeedURL</key> <key>SUFeedURL</key>
<string>${MACOSX_SPARKLE_UPDATE_FEED_URL}</string> <string>${MACOSX_SPARKLE_UPDATE_FEED_URL}</string>
<key>CFBundleDocumentTypes</key>
<array>
<dict>
<key>CFBundleTypeExtensions</key>
<array>
<string>zip</string>
<string>mrpack</string>
</array>
<key>CFBundleTypeName</key>
<string>Prism Launcher instance</string>
<key>CFBundleTypeOSTypes</key>
<array>
<string>TEXT</string>
<string>utxt</string>
<string>TUTX</string>
<string>****</string>
</array>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
<key>LSHandlerRank</key>
<string>Alternate</string>
</dict>
</array>
</dict> </dict>
</plist> </plist>

View File

@ -1 +1,14 @@
(import nix/flake-compat.nix).defaultNix (
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

120
flake.lock generated
View File

@ -3,11 +3,11 @@
"flake-compat": { "flake-compat": {
"flake": false, "flake": false,
"locked": { "locked": {
"lastModified": 1650374568, "lastModified": 1673956053,
"narHash": "sha256-Z+s0J8/r907g149rllvwhb4pKi8Wam5ij0st8PwAh+E=", "narHash": "sha256-4gtG9iQuiKITOjNQQeQIpoIB6b16fm+504Ch3sNKLd8=",
"owner": "edolstra", "owner": "edolstra",
"repo": "flake-compat", "repo": "flake-compat",
"rev": "b4a34015c698c7793d592d66adbab377907a2be8", "rev": "35bb57c0c8d8b62bbfd284272c928ceb64ddbde9",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -16,29 +16,83 @@
"type": "github" "type": "github"
} }
}, },
"flake-parts": {
"inputs": {
"nixpkgs-lib": "nixpkgs-lib"
},
"locked": {
"lastModified": 1683560683,
"narHash": "sha256-XAygPMN5Xnk/W2c1aW0jyEa6lfMDZWlQgiNtmHXytPc=",
"owner": "hercules-ci",
"repo": "flake-parts",
"rev": "006c75898cf814ef9497252b022e91c946ba8e17",
"type": "github"
},
"original": {
"owner": "hercules-ci",
"repo": "flake-parts",
"type": "github"
}
},
"flake-utils": {
"locked": {
"lastModified": 1667395993,
"narHash": "sha256-nuEHfE/LcWyuSWnS8t12N1wc105Qtau+/OdUAjtQ0rA=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "5aed5285a952e0b949eb3ba02c12fa4fcfef535f",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"gitignore": {
"inputs": {
"nixpkgs": [
"pre-commit-hooks",
"nixpkgs"
]
},
"locked": {
"lastModified": 1660459072,
"narHash": "sha256-8DFJjXG8zqoONA1vXtgeKXy68KdJL5UaXR8NtVMUbx8=",
"owner": "hercules-ci",
"repo": "gitignore.nix",
"rev": "a20de23b925fd8264fd7fad6454652e142fd7f73",
"type": "github"
},
"original": {
"owner": "hercules-ci",
"repo": "gitignore.nix",
"type": "github"
}
},
"libnbtplusplus": { "libnbtplusplus": {
"flake": false, "flake": false,
"locked": { "locked": {
"lastModified": 1650031308, "lastModified": 1650031308,
"narHash": "sha256-TvVOjkUobYJD9itQYueELJX3wmecvEdCbJ0FinW2mL4=", "narHash": "sha256-TvVOjkUobYJD9itQYueELJX3wmecvEdCbJ0FinW2mL4=",
"owner": "PolyMC", "owner": "PrismLauncher",
"repo": "libnbtplusplus", "repo": "libnbtplusplus",
"rev": "2203af7eeb48c45398139b583615134efd8d407f", "rev": "2203af7eeb48c45398139b583615134efd8d407f",
"type": "github" "type": "github"
}, },
"original": { "original": {
"owner": "PolyMC", "owner": "PrismLauncher",
"repo": "libnbtplusplus", "repo": "libnbtplusplus",
"type": "github" "type": "github"
} }
}, },
"nixpkgs": { "nixpkgs": {
"locked": { "locked": {
"lastModified": 1658119717, "lastModified": 1685012353,
"narHash": "sha256-4upOZIQQ7Bc4CprqnHsKnqYfw+arJeAuU+QcpjYBXW0=", "narHash": "sha256-U3oOge4cHnav8OLGdRVhL45xoRj4Ppd+It6nPC9nNIU=",
"owner": "nixos", "owner": "nixos",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "9eb60f25aff0d2218c848dd4574a0ab5e296cabe", "rev": "aeb75dba965e790de427b73315d5addf91a54955",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -48,11 +102,59 @@
"type": "github" "type": "github"
} }
}, },
"nixpkgs-lib": {
"locked": {
"dir": "lib",
"lastModified": 1682879489,
"narHash": "sha256-sASwo8gBt7JDnOOstnps90K1wxmVfyhsTPPNTGBPjjg=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "da45bf6ec7bbcc5d1e14d3795c025199f28e0de0",
"type": "github"
},
"original": {
"dir": "lib",
"owner": "NixOS",
"ref": "nixos-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"pre-commit-hooks": {
"inputs": {
"flake-compat": [
"flake-compat"
],
"flake-utils": "flake-utils",
"gitignore": "gitignore",
"nixpkgs": [
"nixpkgs"
],
"nixpkgs-stable": [
"nixpkgs"
]
},
"locked": {
"lastModified": 1684842236,
"narHash": "sha256-rYWsIXHvNhVQ15RQlBUv67W3YnM+Pd+DuXGMvCBq2IE=",
"owner": "cachix",
"repo": "pre-commit-hooks.nix",
"rev": "61e567d6497bc9556f391faebe5e410e6623217f",
"type": "github"
},
"original": {
"owner": "cachix",
"repo": "pre-commit-hooks.nix",
"type": "github"
}
},
"root": { "root": {
"inputs": { "inputs": {
"flake-compat": "flake-compat", "flake-compat": "flake-compat",
"flake-parts": "flake-parts",
"libnbtplusplus": "libnbtplusplus", "libnbtplusplus": "libnbtplusplus",
"nixpkgs": "nixpkgs" "nixpkgs": "nixpkgs",
"pre-commit-hooks": "pre-commit-hooks"
} }
} }
}, },

View File

@ -3,35 +3,25 @@
inputs = { inputs = {
nixpkgs.url = "github:nixos/nixpkgs/nixpkgs-unstable"; nixpkgs.url = "github:nixos/nixpkgs/nixpkgs-unstable";
flake-compat = { url = "github:edolstra/flake-compat"; flake = false; }; flake-parts.url = "github:hercules-ci/flake-parts";
libnbtplusplus = { url = "github:PolyMC/libnbtplusplus"; flake = false; }; pre-commit-hooks = {
url = "github:cachix/pre-commit-hooks.nix";
inputs.nixpkgs.follows = "nixpkgs";
inputs.nixpkgs-stable.follows = "nixpkgs";
inputs.flake-compat.follows = "flake-compat";
};
flake-compat = {
url = "github:edolstra/flake-compat";
flake = false;
};
libnbtplusplus = {
url = "github:PrismLauncher/libnbtplusplus";
flake = false;
};
}; };
outputs = { self, nixpkgs, libnbtplusplus, ... }: outputs = inputs:
let inputs.flake-parts.lib.mkFlake
# User-friendly version number. {inherit inputs;}
version = builtins.substring 0 8 self.lastModifiedDate; {imports = [./nix];};
# Supported systems (qtbase is currently broken for "aarch64-darwin")
supportedSystems = [ "x86_64-linux" "x86_64-darwin" "aarch64-linux" ];
# Helper function to generate an attrset '{ x86_64-linux = f "x86_64-linux"; ... }'.
forAllSystems = nixpkgs.lib.genAttrs supportedSystems;
# Nixpkgs instantiated for supported systems.
pkgs = forAllSystems (system: nixpkgs.legacyPackages.${system});
packagesFn = pkgs: rec {
polymc = pkgs.libsForQt5.callPackage ./nix { inherit version self libnbtplusplus; };
polymc-qt6 = pkgs.qt6Packages.callPackage ./nix { inherit version self libnbtplusplus; };
};
in
{
packages = forAllSystems (system:
let packages = packagesFn pkgs.${system}; in
packages // { default = packages.polymc; }
);
overlay = final: packagesFn;
};
} }

View File

@ -0,0 +1,85 @@
id: org.prismlauncher.PrismLauncher
runtime: org.kde.Platform
runtime-version: "5.15-22.08"
sdk: org.kde.Sdk
sdk-extensions:
- org.freedesktop.Sdk.Extension.openjdk17
- org.freedesktop.Sdk.Extension.openjdk8
add-extensions:
com.valvesoftware.Steam.Utility.gamescope:
version: stable
add-ld-path: lib
no-autodownload: true
autodelete: false
directory: utils/gamescope
command: prismlauncher
finish-args:
- --share=ipc
- --socket=x11
- --socket=wayland
- --device=all
- --share=network
- --socket=pulseaudio
# for Discord RPC mods
- --filesystem=xdg-run/app/com.discordapp.Discord:create
# Mod drag&drop
- --filesystem=xdg-download:ro
modules:
- name: prismlauncher
buildsystem: cmake-ninja
config-opts:
- -DLauncher_BUILD_PLATFORM=flatpak
- -DCMAKE_BUILD_TYPE=Debug
- -DLauncher_QT_VERSION_MAJOR=5
build-options:
env:
JAVA_HOME: /usr/lib/sdk/openjdk17/jvm/openjdk-17
JAVA_COMPILER: /usr/lib/sdk/openjdk17/jvm/openjdk-17/bin/javac
sources:
- type: dir
path: ../
builddir: true
- name: openjdk
buildsystem: simple
build-commands:
- mkdir -p /app/jdk/
- /usr/lib/sdk/openjdk17/install.sh
- mv /app/jre /app/jdk/17
- /usr/lib/sdk/openjdk8/install.sh
- mv /app/jre /app/jdk/8
cleanup: [/jre]
- name: xrandr
buildsystem: autotools
sources:
- type: archive
url: https://xorg.freedesktop.org/archive/individual/app/xrandr-1.5.1.tar.xz
sha256: 7bc76daf9d72f8aff885efad04ce06b90488a1a169d118dea8a2b661832e8762
cleanup: [/share/man, /bin/xkeystone]
- name: gamemode
buildsystem: meson
config-opts:
- -Dwith-sd-bus-provider=no-daemon
- -Dwith-examples=false
post-install:
# gamemoderun is installed for users who want to use wrapper commands
# post-install is running inside the build dir, we need it from the source though
- install -Dm755 ../data/gamemoderun -t /app/bin
sources:
- type: git
url: https://github.com/FeralInteractive/gamemode
tag: "1.7"
commit: 4dc99dff76218718763a6b07fc1900fa6d1dafd9
- name: enhance
buildsystem: simple
build-commands:
- mkdir -p /app/utils/gamescope
- install -Dm755 prime-run /app/bin/prime-run
- mv /app/bin/prismlauncher /app/bin/prismrun
- install -Dm755 prismlauncher /app/bin/prismlauncher
sources:
- type: file
path: ../flatpak/prime-run
- type: file
path: ../flatpak/prismlauncher

4
flatpak/prime-run Normal file
View File

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

11
flatpak/prismlauncher Normal file
View File

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

View File

@ -1,8 +1,14 @@
// SPDX-License-Identifier: GPL-3.0-only // SPDX-FileCopyrightText: 2022 Sefa Eyeoglu <contact@scrumplex.net>
//
// SPDX-License-Identifier: GPL-3.0-only AND Apache-2.0
/* /*
* PolyMC - Minecraft Launcher * Prism Launcher - Minecraft Launcher
* Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net> * Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net>
* Copyright (C) 2022 Lenny McLennington <lenny@sneed.church> * Copyright (C) 2022 Lenny McLennington <lenny@sneed.church>
* Copyright (C) 2022 Tayou <tayou@gmx.net>
* Copyright (C) 2023 TheKodeToad <TheKodeToad@proton.me>
* Copyright (C) 2023 Rachel Powers <508861+Ryex@users.noreply.github.com>
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -37,10 +43,15 @@
#include "Application.h" #include "Application.h"
#include "BuildConfig.h" #include "BuildConfig.h"
#include "DataMigrationTask.h"
#include "net/PasteUpload.h" #include "net/PasteUpload.h"
#include "pathmatcher/MultiMatcher.h"
#include "pathmatcher/SimplePrefixMatcher.h"
#include "settings/INIFile.h"
#include "ui/MainWindow.h" #include "ui/MainWindow.h"
#include "ui/InstanceWindow.h" #include "ui/InstanceWindow.h"
#include "ui/dialogs/ProgressDialog.h"
#include "ui/instanceview/AccessibleInstanceView.h" #include "ui/instanceview/AccessibleInstanceView.h"
#include "ui/pages/BasePageProvider.h" #include "ui/pages/BasePageProvider.h"
@ -54,26 +65,26 @@
#include "ui/pages/global/APIPage.h" #include "ui/pages/global/APIPage.h"
#include "ui/pages/global/CustomCommandsPage.h" #include "ui/pages/global/CustomCommandsPage.h"
#include "ui/themes/ITheme.h"
#include "ui/themes/SystemTheme.h"
#include "ui/themes/DarkTheme.h"
#include "ui/themes/BrightTheme.h"
#include "ui/themes/CustomTheme.h"
#include "ui/setupwizard/SetupWizard.h" #include "ui/setupwizard/SetupWizard.h"
#include "ui/setupwizard/LanguageWizardPage.h" #include "ui/setupwizard/LanguageWizardPage.h"
#include "ui/setupwizard/JavaWizardPage.h" #include "ui/setupwizard/JavaWizardPage.h"
#include "ui/setupwizard/PasteWizardPage.h" #include "ui/setupwizard/PasteWizardPage.h"
#include "ui/setupwizard/ThemeWizardPage.h"
#include "ui/dialogs/CustomMessageBox.h" #include "ui/dialogs/CustomMessageBox.h"
#include "ui/pagedialog/PageDialog.h" #include "ui/pagedialog/PageDialog.h"
#include "ui/themes/ThemeManager.h"
#include "ApplicationMessage.h" #include "ApplicationMessage.h"
#include <iostream> #include <iostream>
#include <mutex>
#include <QFileOpenEvent>
#include <QAccessible> #include <QAccessible>
#include <QCommandLineParser>
#include <QDir> #include <QDir>
#include <QFileInfo> #include <QFileInfo>
#include <QNetworkAccessManager> #include <QNetworkAccessManager>
@ -87,6 +98,7 @@
#include <QIcon> #include <QIcon>
#include "InstanceList.h" #include "InstanceList.h"
#include "MTPixmapCache.h"
#include <minecraft/auth/AccountList.h> #include <minecraft/auth/AccountList.h>
#include "icons/IconList.h" #include "icons/IconList.h"
@ -94,7 +106,7 @@
#include "java/JavaUtils.h" #include "java/JavaUtils.h"
#include "updater/UpdateChecker.h" #include "updater/ExternalUpdater.h"
#include "tools/JProfiler.h" #include "tools/JProfiler.h"
#include "tools/JVisualVM.h" #include "tools/JVisualVM.h"
@ -106,13 +118,22 @@
#include "translations/TranslationsModel.h" #include "translations/TranslationsModel.h"
#include "meta/Index.h" #include "meta/Index.h"
#include <Commandline.h>
#include <FileSystem.h> #include <FileSystem.h>
#include <DesktopServices.h> #include <DesktopServices.h>
#include <LocalPeer.h> #include <LocalPeer.h>
#include <sys.h> #include <sys.h>
#ifdef Q_OS_LINUX
#include <dlfcn.h>
#include "gamemode_client.h"
#include "MangoHud.h"
#endif
#ifdef Q_OS_MAC
#include "updater/MacSparkleUpdater.h"
#endif
#if defined Q_OS_WIN32 #if defined Q_OS_WIN32
#ifndef WIN32_LEAN_AND_MEAN #ifndef WIN32_LEAN_AND_MEAN
@ -127,26 +148,18 @@
static const QLatin1String liveCheckFile("live.check"); static const QLatin1String liveCheckFile("live.check");
using namespace Commandline; PixmapCache* PixmapCache::s_instance = nullptr;
#define MACOS_HINT "If you are on macOS Sierra, you might have to move the app to your /Applications or ~/Applications folder. "\
"This usually fixes the problem and you can move the application elsewhere afterwards.\n"\
"\n"
namespace { namespace {
/** This is used so that we can output to the log file in addition to the CLI. */
void appDebugOutput(QtMsgType type, const QMessageLogContext &context, const QString &msg) void appDebugOutput(QtMsgType type, const QMessageLogContext &context, const QString &msg)
{ {
const char *levels = "DWCFIS"; static std::mutex loggerMutex;
const QString format("%1 %2 %3\n"); const std::lock_guard<std::mutex> lock(loggerMutex); // synchronized, QFile logFile is not thread-safe
qint64 msecstotal = APPLICATION->timeSinceStart(); QString out = qFormatLogMessage(type, context, msg);
qint64 seconds = msecstotal / 1000; out += QChar::LineFeed;
qint64 msecs = msecstotal % 1000;
QString foo;
char buf[1025] = {0};
::snprintf(buf, 1024, "%5lld.%03lld", seconds, msecs);
QString out = format.arg(buf).arg(levels[type]).arg(msg);
APPLICATION->logFile->write(out.toUtf8()); APPLICATION->logFile->write(out.toUtf8());
APPLICATION->logFile->flush(); APPLICATION->logFile->flush();
@ -154,45 +167,6 @@ void appDebugOutput(QtMsgType type, const QMessageLogContext &context, const QSt
fflush(stderr); fflush(stderr);
} }
QString getIdealPlatform(QString currentPlatform) {
auto info = Sys::getKernelInfo();
switch(info.kernelType) {
case Sys::KernelType::Darwin: {
if(info.kernelMajor >= 17) {
// macOS 10.13 or newer
return "osx64-5.15.2";
}
else {
// macOS 10.12 or older
return "osx64";
}
}
case Sys::KernelType::Windows: {
// FIXME: 5.15.2 is not stable on Windows, due to a large number of completely unpredictable and hard to reproduce issues
break;
/*
if(info.kernelMajor == 6 && info.kernelMinor >= 1) {
// Windows 7
return "win32-5.15.2";
}
else if (info.kernelMajor > 6) {
// Above Windows 7
return "win32-5.15.2";
}
else {
// Below Windows 7
return "win32";
}
*/
}
case Sys::KernelType::Undetermined:
case Sys::KernelType::Linux: {
break;
}
}
return currentPlatform;
}
} }
Application::Application(int &argc, char **argv) : QApplication(argc, argv) Application::Application(int &argc, char **argv) : QApplication(argc, argv)
@ -225,7 +199,7 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv)
setOrganizationDomain(BuildConfig.LAUNCHER_DOMAIN); setOrganizationDomain(BuildConfig.LAUNCHER_DOMAIN);
setApplicationName(BuildConfig.LAUNCHER_NAME); setApplicationName(BuildConfig.LAUNCHER_NAME);
setApplicationDisplayName(QString("%1 %2").arg(BuildConfig.LAUNCHER_DISPLAYNAME, BuildConfig.printableVersionString())); setApplicationDisplayName(QString("%1 %2").arg(BuildConfig.LAUNCHER_DISPLAYNAME, BuildConfig.printableVersionString()));
setApplicationVersion(BuildConfig.printableVersionString()); setApplicationVersion(BuildConfig.printableVersionString() + "\n" + BuildConfig.GIT_COMMIT);
setDesktopFileName(BuildConfig.LAUNCHER_DESKTOPFILENAME); setDesktopFileName(BuildConfig.LAUNCHER_DESKTOPFILENAME);
startTime = QDateTime::currentDateTime(); startTime = QDateTime::currentDateTime();
@ -233,80 +207,39 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv)
this->setQuitOnLastWindowClosed(false); this->setQuitOnLastWindowClosed(false);
// Commandline parsing // Commandline parsing
QHash<QString, QVariant> args; QCommandLineParser parser;
{ parser.setApplicationDescription(BuildConfig.LAUNCHER_DISPLAYNAME);
Parser parser(FlagStyle::GNU, ArgumentStyle::SpaceAndEquals);
// --help parser.addOptions({
parser.addSwitch("help"); {{"d", "dir"}, "Use a custom path as application root (use '.' for current directory)", "directory"},
parser.addShortOpt("help", 'h'); {{"l", "launch"}, "Launch the specified instance (by instance ID)", "instance"},
parser.addDocumentation("help", "Display this help and exit."); {{"s", "server"}, "Join the specified server on launch (only valid in combination with --launch)", "address"},
// --version {{"a", "profile"}, "Use the account specified by its profile name (only valid in combination with --launch)", "profile"},
parser.addSwitch("version"); {"alive", "Write a small '" + liveCheckFile + "' file after the launcher starts"},
parser.addShortOpt("version", 'V'); {{"I", "import"}, "Import instance from specified zip (local path or URL)", "file"},
parser.addDocumentation("version", "Display program version and exit."); {"show", "Opens the window for the specified instance (by instance ID)", "show"}
// --dir });
parser.addOption("dir"); parser.addHelpOption();
parser.addShortOpt("dir", 'd'); parser.addVersionOption();
parser.addDocumentation("dir", "Use the supplied folder as application root instead of the binary location (use '.' for current)");
// --launch
parser.addOption("launch");
parser.addShortOpt("launch", 'l');
parser.addDocumentation("launch", "Launch the specified instance (by instance ID)");
// --server
parser.addOption("server");
parser.addShortOpt("server", 's');
parser.addDocumentation("server", "Join the specified server on launch (only valid in combination with --launch)");
// --profile
parser.addOption("profile");
parser.addShortOpt("profile", 'a');
parser.addDocumentation("profile", "Use the account specified by its profile name (only valid in combination with --launch)");
// --alive
parser.addSwitch("alive");
parser.addDocumentation("alive", "Write a small '" + liveCheckFile + "' file after the launcher starts");
// --import
parser.addOption("import");
parser.addShortOpt("import", 'I');
parser.addDocumentation("import", "Import instance from specified zip (local path or URL)");
// parse the arguments parser.process(arguments());
try
{
args = parser.parse(arguments());
}
catch (const ParsingError &e)
{
std::cerr << "CommandLineError: " << e.what() << std::endl;
if(argc > 0)
std::cerr << "Try '" << argv[0] << " -h' to get help on command line parameters."
<< std::endl;
m_status = Application::Failed;
return;
}
// display help and exit m_instanceIdToLaunch = parser.value("launch");
if (args["help"].toBool()) m_serverToJoin = parser.value("server");
{ m_profileToUse = parser.value("profile");
std::cout << qPrintable(parser.compileHelp(arguments()[0])); m_liveCheck = parser.isSet("alive");
m_status = Application::Succeeded;
return;
}
// display version and exit m_instanceIdToShowWindowOf = parser.value("show");
if (args["version"].toBool())
{ for (auto zip_path : parser.values("import")){
std::cout << "Version " << BuildConfig.printableVersionString().toStdString() << std::endl; m_zipsToImport.append(QUrl::fromLocalFile(QFileInfo(zip_path).absoluteFilePath()));
std::cout << "Git " << BuildConfig.GIT_COMMIT.toStdString() << std::endl; }
m_status = Application::Succeeded;
return; // treat unspecified positional arguments as import urls
} for (auto zip_path : parser.positionalArguments()) {
m_zipsToImport.append(QUrl::fromLocalFile(QFileInfo(zip_path).absoluteFilePath()));
} }
m_instanceIdToLaunch = args["launch"].toString();
m_serverToJoin = args["server"].toString();
m_profileToUse = args["profile"].toString();
m_liveCheck = args["alive"].toBool();
m_zipToImport = args["import"].toUrl();
// error if --launch is missing with --server or --profile // error if --launch is missing with --server or --profile
if((!m_serverToJoin.isEmpty() || !m_profileToUse.isEmpty()) && m_instanceIdToLaunch.isEmpty()) if((!m_serverToJoin.isEmpty() || !m_profileToUse.isEmpty()) && m_instanceIdToLaunch.isEmpty())
@ -321,7 +254,7 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv)
{ {
// Root path is used for updates and portable data // Root path is used for updates and portable data
#if defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD) #if defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD) || defined(Q_OS_OPENBSD)
QDir foo(FS::PathCombine(binPath, "..")); // typically portable-root or /usr QDir foo(FS::PathCombine(binPath, "..")); // typically portable-root or /usr
m_rootPath = foo.absolutePath(); m_rootPath = foo.absolutePath();
#elif defined(Q_OS_WIN32) #elif defined(Q_OS_WIN32)
@ -337,7 +270,7 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv)
QString adjustedBy; QString adjustedBy;
QString dataPath; QString dataPath;
// change folder // change folder
QString dirParam = args["dir"].toString(); QString dirParam = parser.value("dir");
if (!dirParam.isEmpty()) if (!dirParam.isEmpty())
{ {
// the dir param. it makes multimc data path point to whatever the user specified // the dir param. it makes multimc data path point to whatever the user specified
@ -351,20 +284,11 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv)
dataPath = foo.absolutePath(); dataPath = foo.absolutePath();
adjustedBy = "Persistent data path"; adjustedBy = "Persistent data path";
#ifdef Q_OS_LINUX
// TODO: this should be removed in a future version
// TODO: provide a migration path similar to macOS migration
QDir bar(FS::PathCombine(QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation), "polymc"));
if (bar.exists()) {
dataPath = bar.absolutePath();
adjustedBy = "Legacy data path";
}
#endif
#ifndef Q_OS_MACOS #ifndef Q_OS_MACOS
if (QFile::exists(FS::PathCombine(m_rootPath, "portable.txt"))) { if (QFile::exists(FS::PathCombine(m_rootPath, "portable.txt"))) {
dataPath = m_rootPath; dataPath = m_rootPath;
adjustedBy = "Portable data path"; adjustedBy = "Portable data path";
m_portable = true;
} }
#endif #endif
} }
@ -376,9 +300,6 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv)
QString( QString(
"The launcher data folder could not be created.\n" "The launcher data folder could not be created.\n"
"\n" "\n"
#if defined(Q_OS_MAC)
MACOS_HINT
#endif
"Make sure you have the right permissions to the launcher data folder and any folder needed to access it.\n" "Make sure you have the right permissions to the launcher data folder and any folder needed to access it.\n"
"(%1)\n" "(%1)\n"
"\n" "\n"
@ -394,9 +315,6 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv)
QString( QString(
"The launcher data folder could not be opened.\n" "The launcher data folder could not be opened.\n"
"\n" "\n"
#if defined(Q_OS_MAC)
MACOS_HINT
#endif
"Make sure you have the right permissions to the launcher data folder.\n" "Make sure you have the right permissions to the launcher data folder.\n"
"(%1)\n" "(%1)\n"
"\n" "\n"
@ -407,7 +325,7 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv)
} }
/* /*
* Establish the mechanism for communication with an already running PolyMC that uses the same data path. * Establish the mechanism for communication with an already running PrismLauncher that uses the same data path.
* If there is one, tell it what the user actually wanted to do and exit. * If there is one, tell it what the user actually wanted to do and exit.
* We want to initialize this before logging to avoid messing with the log of a potential already running copy. * We want to initialize this before logging to avoid messing with the log of a potential already running copy.
*/ */
@ -425,12 +343,14 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv)
activate.command = "activate"; activate.command = "activate";
m_peerInstance->sendMessage(activate.serialize(), timeout); m_peerInstance->sendMessage(activate.serialize(), timeout);
if(!m_zipToImport.isEmpty()) if(!m_zipsToImport.isEmpty())
{ {
ApplicationMessage import; for (auto zip_url : m_zipsToImport) {
import.command = "import"; ApplicationMessage import;
import.args.insert("path", m_zipToImport.toString()); import.command = "import";
m_peerInstance->sendMessage(import.serialize(), timeout); import.args.insert("path", zip_url.toString());
m_peerInstance->sendMessage(import.serialize(), timeout);
}
} }
} }
else else
@ -477,9 +397,6 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv)
QString( QString(
"The launcher couldn't create a log file - the data folder is not writable.\n" "The launcher couldn't create a log file - the data folder is not writable.\n"
"\n" "\n"
#if defined(Q_OS_MAC)
MACOS_HINT
#endif
"Make sure you have write permissions to the data folder.\n" "Make sure you have write permissions to the data folder.\n"
"(%1)\n" "(%1)\n"
"\n" "\n"
@ -489,9 +406,67 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv)
return; return;
} }
qInstallMessageHandler(appDebugOutput); 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}");
bool foundLoggingRules = false;
auto logRulesFile = QStringLiteral("qtlogging.ini");
auto logRulesPath = FS::PathCombine(dataPath, logRulesFile);
qDebug() << "Testing" << logRulesPath << "...";
foundLoggingRules = QFile::exists(logRulesPath);
// search the dataPath()
// seach app data standard path
if(!foundLoggingRules && !isPortable() && dirParam.isEmpty()) {
logRulesPath = QStandardPaths::locate(QStandardPaths::AppDataLocation, FS::PathCombine("..", logRulesFile));
if(!logRulesPath.isEmpty()) {
qDebug() << "Found" << logRulesPath << "...";
foundLoggingRules = true;
}
}
// seach root path
if(!foundLoggingRules) {
logRulesPath = FS::PathCombine(m_rootPath, logRulesFile);
qDebug() << "Testing" << logRulesPath << "...";
foundLoggingRules = QFile::exists(logRulesPath);
}
if(foundLoggingRules) {
// load and set logging rules
qDebug() << "Loading logging rules from:" << logRulesPath;
QSettings loggingRules(logRulesPath, QSettings::IniFormat);
loggingRules.beginGroup("Rules");
QStringList rule_names = loggingRules.childKeys();
QStringList rules;
qDebug() << "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;
}
auto rules_str = rules.join("\n");
QLoggingCategory::setFilterRules(rules_str);
}
qDebug() << "<> Log initialized."; qDebug() << "<> Log initialized.";
} }
{
bool migrated = false;
if (!migrated)
migrated = handleDataMigration(dataPath, FS::PathCombine(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation), "../../PolyMC"), "PolyMC", "polymc.cfg");
if (!migrated)
migrated = handleDataMigration(dataPath, FS::PathCombine(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation), "../../multimc"), "MultiMC", "multimc.cfg");
}
{ {
qDebug() << BuildConfig.LAUNCHER_DISPLAYNAME << ", (c) 2013-2021 " << BuildConfig.LAUNCHER_COPYRIGHT; qDebug() << BuildConfig.LAUNCHER_DISPLAYNAME << ", (c) 2013-2021 " << BuildConfig.LAUNCHER_COPYRIGHT;
@ -541,15 +516,13 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv)
// Initialize application settings // Initialize application settings
{ {
m_settings.reset(new INISettingsObject(BuildConfig.LAUNCHER_CONFIGFILE, this)); // Provide a fallback for migration from PolyMC
// Updates m_settings.reset(new INISettingsObject({ BuildConfig.LAUNCHER_CONFIGFILE, "polymc.cfg", "multimc.cfg" }, this));
// Multiple channels are separated by spaces
m_settings->registerSetting("UpdateChannel", BuildConfig.VERSION_CHANNEL);
m_settings->registerSetting("AutoUpdate", true);
// Theming // Theming
m_settings->registerSetting("IconTheme", QString("pe_colored")); m_settings->registerSetting("IconTheme", QString("pe_colored"));
m_settings->registerSetting("ApplicationTheme", QString("system")); m_settings->registerSetting("ApplicationTheme", QString());
m_settings->registerSetting("BackgroundCat", QString("kitteh"));
// Remembered state // Remembered state
m_settings->registerSetting("LastUsedGroupForNewInstance", QString()); m_settings->registerSetting("LastUsedGroupForNewInstance", QString());
@ -587,6 +560,8 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv)
m_settings->registerSetting("InstanceDir", "instances"); m_settings->registerSetting("InstanceDir", "instances");
m_settings->registerSetting({"CentralModsDir", "ModsDir"}, "mods"); m_settings->registerSetting({"CentralModsDir", "ModsDir"}, "mods");
m_settings->registerSetting("IconsDir", "icons"); m_settings->registerSetting("IconsDir", "icons");
m_settings->registerSetting("DownloadsDir", QStandardPaths::writableLocation(QStandardPaths::DownloadLocation));
m_settings->registerSetting("DownloadsDirWatchRecursive", false);
// Editors // Editors
m_settings->registerSetting("JsonEditor", QString()); m_settings->registerSetting("JsonEditor", QString());
@ -614,7 +589,7 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv)
// Memory // Memory
m_settings->registerSetting({"MinMemAlloc", "MinMemoryAlloc"}, 512); m_settings->registerSetting({"MinMemAlloc", "MinMemoryAlloc"}, 512);
m_settings->registerSetting({"MaxMemAlloc", "MaxMemoryAlloc"}, 4096); m_settings->registerSetting({"MaxMemAlloc", "MaxMemoryAlloc"}, suitableMaxMem());
m_settings->registerSetting("PermGen", 128); m_settings->registerSetting("PermGen", 128);
// Java Settings // Java Settings
@ -662,6 +637,8 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv)
// The cat // The cat
m_settings->registerSetting("TheCat", false); m_settings->registerSetting("TheCat", false);
m_settings->registerSetting("ToolbarsLocked", false);
m_settings->registerSetting("InstSortMode", "Name"); m_settings->registerSetting("InstSortMode", "Name");
m_settings->registerSetting("SelectedInstance", QString()); m_settings->registerSetting("SelectedInstance", QString());
@ -680,6 +657,11 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv)
m_settings->registerSetting("UpdateDialogGeometry", ""); m_settings->registerSetting("UpdateDialogGeometry", "");
m_settings->registerSetting("ModDownloadGeometry", "");
m_settings->registerSetting("RPDownloadGeometry", "");
m_settings->registerSetting("TPDownloadGeometry", "");
m_settings->registerSetting("ShaderDownloadGeometry", "");
// HACK: This code feels so stupid is there a less stupid way of doing this? // HACK: This code feels so stupid is there a less stupid way of doing this?
{ {
m_settings->registerSetting("PastebinURL", ""); m_settings->registerSetting("PastebinURL", "");
@ -725,6 +707,7 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv)
m_settings->set("FlameKeyOverride", flameKey); m_settings->set("FlameKeyOverride", flameKey);
m_settings->reset("CFKeyOverride"); m_settings->reset("CFKeyOverride");
} }
m_settings->registerSetting("ModrinthToken", "");
m_settings->registerSetting("UserAgentOverride", ""); m_settings->registerSetting("UserAgentOverride", "");
// Init page provider // Init page provider
@ -740,6 +723,9 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv)
m_globalSettingsProvider->addPage<AccountListPage>(); m_globalSettingsProvider->addPage<AccountListPage>();
m_globalSettingsProvider->addPage<APIPage>(); m_globalSettingsProvider->addPage<APIPage>();
} }
PixmapCache::setInstance(new PixmapCache(this));
qDebug() << "<> Settings loaded."; qDebug() << "<> Settings loaded.";
} }
@ -749,7 +735,7 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv)
// initialize network access and proxy setup // initialize network access and proxy setup
{ {
m_network = new QNetworkAccessManager(); m_network.reset(new QNetworkAccessManager());
QString proxyTypeStr = settings()->get("ProxyType").toString(); QString proxyTypeStr = settings()->get("ProxyType").toString();
QString addr = settings()->get("ProxyAddr").toString(); QString addr = settings()->get("ProxyAddr").toString();
int port = settings()->get("ProxyPort").value<qint16>(); int port = settings()->get("ProxyPort").value<qint16>();
@ -771,10 +757,10 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv)
// initialize the updater // initialize the updater
if(BuildConfig.UPDATER_ENABLED) if(BuildConfig.UPDATER_ENABLED)
{ {
auto platform = getIdealPlatform(BuildConfig.BUILD_PLATFORM); qDebug() << "Initializing updater";
auto channelUrl = BuildConfig.UPDATER_BASE + platform + "/channels.json"; #ifdef Q_OS_MAC
qDebug() << "Initializing updater with platform: " << platform << " -- " << channelUrl; m_updater.reset(new MacSparkleUpdater());
m_updateChecker.reset(new UpdateChecker(m_network, channelUrl, BuildConfig.VERSION_CHANNEL, BuildConfig.VERSION_BUILD)); #endif
qDebug() << "<> Updater started."; qDebug() << "<> Updater started.";
} }
@ -796,29 +782,8 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv)
qDebug() << "<> Instance icons intialized."; qDebug() << "<> Instance icons intialized.";
} }
// Icon themes // Themes
{ m_themeManager = std::make_unique<ThemeManager>(m_mainWindow);
// TODO: icon themes and instance icons do not mesh well together. Rearrange and fix discrepancies!
// set icon theme search path!
auto searchPaths = QIcon::themeSearchPaths();
searchPaths.append("iconthemes");
QIcon::setThemeSearchPaths(searchPaths);
qDebug() << "<> Icon themes initialized.";
}
// Initialize widget themes
{
auto insertTheme = [this](ITheme * theme)
{
m_themes.insert(std::make_pair(theme->id(), std::unique_ptr<ITheme>(theme)));
};
auto darkTheme = new DarkTheme();
insertTheme(new SystemTheme());
insertTheme(darkTheme);
insertTheme(new BrightTheme());
insertTheme(new CustomTheme(darkTheme, "custom"));
qDebug() << "<> Widget themes initialized.";
}
// initialize and load all instances // initialize and load all instances
{ {
@ -864,7 +829,9 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv)
m_metacache->addBase("ModpacksCHPacks", QDir("cache/ModpacksCHPacks").absolutePath()); m_metacache->addBase("ModpacksCHPacks", QDir("cache/ModpacksCHPacks").absolutePath());
m_metacache->addBase("TechnicPacks", QDir("cache/TechnicPacks").absolutePath()); m_metacache->addBase("TechnicPacks", QDir("cache/TechnicPacks").absolutePath());
m_metacache->addBase("FlamePacks", QDir("cache/FlamePacks").absolutePath()); m_metacache->addBase("FlamePacks", QDir("cache/FlamePacks").absolutePath());
m_metacache->addBase("FlameMods", QDir("cache/FlameMods").absolutePath());
m_metacache->addBase("ModrinthPacks", QDir("cache/ModrinthPacks").absolutePath()); m_metacache->addBase("ModrinthPacks", QDir("cache/ModrinthPacks").absolutePath());
m_metacache->addBase("ModrinthModpacks", QDir("cache/ModrinthModpacks").absolutePath());
m_metacache->addBase("root", QDir::currentPath()); m_metacache->addBase("root", QDir::currentPath());
m_metacache->addBase("translations", QDir("translations").absolutePath()); m_metacache->addBase("translations", QDir("translations").absolutePath());
m_metacache->addBase("icons", QDir("cache/icons").absolutePath()); m_metacache->addBase("icons", QDir("cache/icons").absolutePath());
@ -908,17 +875,15 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv)
} }
}); });
{ applyCurrentlySelectedTheme(true);
setIconTheme(settings()->get("IconTheme").toString());
qDebug() << "<> Icon theme set."; updateCapabilities();
setApplicationTheme(settings()->get("ApplicationTheme").toString(), true);
qDebug() << "<> Application theme set.";
}
if(createSetupWizard()) if(createSetupWizard())
{ {
return; return;
} }
performMainStartupAction(); performMainStartupAction();
} }
@ -952,7 +917,8 @@ bool Application::createSetupWizard()
return false; return false;
}(); }();
bool pasteInterventionRequired = settings()->get("PastebinURL") != ""; bool pasteInterventionRequired = settings()->get("PastebinURL") != "";
bool wizardRequired = javaRequired || languageRequired || pasteInterventionRequired; bool themeInterventionRequired = settings()->get("ApplicationTheme") == "";
bool wizardRequired = javaRequired || languageRequired || pasteInterventionRequired || themeInterventionRequired;
if(wizardRequired) if(wizardRequired)
{ {
@ -971,6 +937,12 @@ bool Application::createSetupWizard()
{ {
m_setupWizard->addPage(new PasteWizardPage(m_setupWizard)); m_setupWizard->addPage(new PasteWizardPage(m_setupWizard));
} }
if (themeInterventionRequired)
{
settings()->set("ApplicationTheme", QString("system")); // set default theme after going into theme wizard
m_setupWizard->addPage(new ThemeWizardPage(m_setupWizard));
}
connect(m_setupWizard, &QDialog::finished, this, &Application::setupWizardFinished); connect(m_setupWizard, &QDialog::finished, this, &Application::setupWizardFinished);
m_setupWizard->show(); m_setupWizard->show();
return true; return true;
@ -978,18 +950,24 @@ bool Application::createSetupWizard()
return false; return false;
} }
bool Application::event(QEvent* event) { bool Application::event(QEvent* event)
{
#ifdef Q_OS_MACOS #ifdef Q_OS_MACOS
if (event->type() == QEvent::ApplicationStateChange) { if (event->type() == QEvent::ApplicationStateChange) {
auto ev = static_cast<QApplicationStateChangeEvent*>(event); auto ev = static_cast<QApplicationStateChangeEvent*>(event);
if (m_prevAppState == Qt::ApplicationActive if (m_prevAppState == Qt::ApplicationActive && ev->applicationState() == Qt::ApplicationActive) {
&& ev->applicationState() == Qt::ApplicationActive) {
emit clickedOnDock(); emit clickedOnDock();
} }
m_prevAppState = ev->applicationState(); m_prevAppState = ev->applicationState();
} }
#endif #endif
if (event->type() == QEvent::FileOpen) {
auto ev = static_cast<QFileOpenEvent*>(event);
m_mainWindow->processURLs({ ev->url() });
}
return QApplication::event(event); return QApplication::event(event);
} }
@ -1027,7 +1005,17 @@ void Application::performMainStartupAction()
qDebug() << " Launching with account" << m_profileToUse; qDebug() << " Launching with account" << m_profileToUse;
} }
launch(inst, true, nullptr, serverToJoin, accountToUse); launch(inst, true, false, nullptr, serverToJoin, accountToUse);
return;
}
}
if(!m_instanceIdToShowWindowOf.isEmpty())
{
auto inst = instances()->getInstanceById(m_instanceIdToShowWindowOf);
if(inst)
{
qDebug() << "<> Showing window of instance " << m_instanceIdToShowWindowOf;
showInstanceWindow(inst);
return; return;
} }
} }
@ -1037,10 +1025,10 @@ void Application::performMainStartupAction()
showMainWindow(false); showMainWindow(false);
qDebug() << "<> Main window shown."; qDebug() << "<> Main window shown.";
} }
if(!m_zipToImport.isEmpty()) if(!m_zipsToImport.isEmpty())
{ {
qDebug() << "<> Importing instance from zip:" << m_zipToImport; qDebug() << "<> Importing from zip:" << m_zipsToImport;
m_mainWindow->droppedURLs({ m_zipToImport }); m_mainWindow->processURLs( m_zipsToImport );
} }
} }
@ -1093,7 +1081,7 @@ void Application::messageReceived(const QByteArray& message)
qWarning() << "Received" << command << "message without a zip path/URL."; qWarning() << "Received" << command << "message without a zip path/URL.";
return; return;
} }
m_mainWindow->droppedURLs({ QUrl(path) }); m_mainWindow->processURLs({ QUrl::fromLocalFile(QFileInfo(path).absoluteFilePath()) });
} }
else if(command == "launch") else if(command == "launch")
{ {
@ -1131,6 +1119,7 @@ void Application::messageReceived(const QByteArray& message)
launch( launch(
instance, instance,
true, true,
false,
nullptr, nullptr,
serverObject, serverObject,
accountObject accountObject
@ -1156,51 +1145,30 @@ std::shared_ptr<JavaInstallList> Application::javalist()
return m_javalist; return m_javalist;
} }
std::vector<ITheme *> Application::getValidApplicationThemes() QList<ITheme*> Application::getValidApplicationThemes()
{ {
std::vector<ITheme *> ret; return m_themeManager->getValidApplicationThemes();
auto iter = m_themes.cbegin();
while (iter != m_themes.cend())
{
ret.push_back((*iter).second.get());
iter++;
}
return ret;
} }
bool Application::isFlatpak() void Application::applyCurrentlySelectedTheme(bool initial)
{ {
#ifdef Q_OS_LINUX m_themeManager->applyCurrentlySelectedTheme(initial);
return QFile::exists("/.flatpak-info");
#else
return false;
#endif
} }
void Application::setApplicationTheme(const QString& name, bool initial) void Application::setApplicationTheme(const QString& name)
{ {
auto systemPalette = qApp->palette(); m_themeManager->setApplicationTheme(name);
auto themeIter = m_themes.find(name);
if(themeIter != m_themes.end())
{
auto & theme = (*themeIter).second;
theme->apply(initial);
}
else
{
qWarning() << "Tried to set invalid theme:" << name;
}
} }
void Application::setIconTheme(const QString& name) void Application::setIconTheme(const QString& name)
{ {
QIcon::setThemeName(name); m_themeManager->setIconTheme(name);
} }
QIcon Application::getThemedIcon(const QString& name) QIcon Application::getThemedIcon(const QString& name)
{ {
if(name == "logo") { if(name == "logo") {
return QIcon(":/org.polymc.PolyMC.svg"); return QIcon(":/" + BuildConfig.LAUNCHER_SVGFILENAME);
} }
return QIcon::fromTheme(name); return QIcon::fromTheme(name);
} }
@ -1222,6 +1190,7 @@ bool Application::openJsonEditor(const QString &filename)
bool Application::launch( bool Application::launch(
InstancePtr instance, InstancePtr instance,
bool online, bool online,
bool demo,
BaseProfilerFactory *profiler, BaseProfilerFactory *profiler,
MinecraftServerTargetPtr serverToJoin, MinecraftServerTargetPtr serverToJoin,
MinecraftAccountPtr accountToUse MinecraftAccountPtr accountToUse
@ -1245,6 +1214,7 @@ bool Application::launch(
controller.reset(new LaunchController()); controller.reset(new LaunchController());
controller->setInstance(instance); controller->setInstance(instance);
controller->setOnline(online); controller->setOnline(online);
controller->setDemo(demo);
controller->setProfiler(profiler); controller->setProfiler(profiler);
controller->setServerToJoin(serverToJoin); controller->setServerToJoin(serverToJoin);
controller->setAccountToUse(accountToUse); controller->setAccountToUse(accountToUse);
@ -1258,6 +1228,9 @@ bool Application::launch(
} }
connect(controller.get(), &LaunchController::succeeded, this, &Application::controllerSucceeded); connect(controller.get(), &LaunchController::succeeded, this, &Application::controllerSucceeded);
connect(controller.get(), &LaunchController::failed, this, &Application::controllerFailed); connect(controller.get(), &LaunchController::failed, this, &Application::controllerFailed);
connect(controller.get(), &LaunchController::aborted, this, [this] {
controllerFailed(tr("Aborted"));
});
addRunningInstance(); addRunningInstance();
controller->start(); controller->start();
return true; return true;
@ -1412,6 +1385,7 @@ MainWindow* Application::showMainWindow(bool minimized)
m_mainWindow = new MainWindow(); m_mainWindow = new MainWindow();
m_mainWindow->restoreState(QByteArray::fromBase64(APPLICATION->settings()->get("MainWindowState").toByteArray())); m_mainWindow->restoreState(QByteArray::fromBase64(APPLICATION->settings()->get("MainWindowState").toByteArray()));
m_mainWindow->restoreGeometry(QByteArray::fromBase64(APPLICATION->settings()->get("MainWindowGeometry").toByteArray())); m_mainWindow->restoreGeometry(QByteArray::fromBase64(APPLICATION->settings()->get("MainWindowGeometry").toByteArray()));
if(minimized) if(minimized)
{ {
m_mainWindow->showMinimized(); m_mainWindow->showMinimized();
@ -1564,24 +1538,32 @@ shared_qobject_ptr<Meta::Index> Application::metadataIndex()
return m_metadataIndex; return m_metadataIndex;
} }
Application::Capabilities Application::currentCapabilities() void Application::updateCapabilities()
{ {
Capabilities c; m_capabilities = None;
if (!getMSAClientID().isEmpty()) if (!getMSAClientID().isEmpty())
c |= SupportsMSA; m_capabilities |= SupportsMSA;
if (!getFlameAPIKey().isEmpty()) if (!getFlameAPIKey().isEmpty())
c |= SupportsFlame; m_capabilities |= SupportsFlame;
return c;
#ifdef Q_OS_LINUX
if (gamemode_query_status() >= 0)
m_capabilities |= SupportsGameMode;
if (!MangoHud::getLibraryString().isEmpty())
m_capabilities |= SupportsMangoHud;
#endif
} }
QString Application::getJarPath(QString jarFile) QString Application::getJarPath(QString jarFile)
{ {
QStringList potentialPaths = { QStringList potentialPaths = {
#if defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD) || defined(Q_OS_OPENBSD) #if defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD) || defined(Q_OS_OPENBSD)
FS::PathCombine(m_rootPath, "share/jars"), FS::PathCombine(m_rootPath, "share/" + BuildConfig.LAUNCHER_APP_BINARY_NAME),
#endif #endif
FS::PathCombine(m_rootPath, "jars"), FS::PathCombine(m_rootPath, "jars"),
FS::PathCombine(applicationDirPath(), "jars") FS::PathCombine(applicationDirPath(), "jars"),
FS::PathCombine(applicationDirPath(), "..", "jars") // from inside build dir, for debuging
}; };
for(QString p : potentialPaths) for(QString p : potentialPaths)
{ {
@ -1612,6 +1594,15 @@ QString Application::getFlameAPIKey()
return BuildConfig.FLAME_API_KEY; return BuildConfig.FLAME_API_KEY;
} }
QString Application::getModrinthAPIToken()
{
QString tokenOverride = m_settings->get("ModrinthToken").toString();
if (!tokenOverride.isEmpty())
return tokenOverride;
return QString();
}
QString Application::getUserAgent() QString Application::getUserAgent()
{ {
QString uaOverride = m_settings->get("UserAgentOverride").toString(); QString uaOverride = m_settings->get("UserAgentOverride").toString();
@ -1632,3 +1623,113 @@ QString Application::getUserAgentUncached()
return BuildConfig.USER_AGENT_UNCACHED; return BuildConfig.USER_AGENT_UNCACHED;
} }
int Application::suitableMaxMem()
{
float totalRAM = (float)Sys::getSystemRam() / (float)Sys::mebibyte;
int maxMemoryAlloc;
// If totalRAM < 6GB, use (totalRAM / 1.5), else 4GB
if (totalRAM < (4096 * 1.5))
maxMemoryAlloc = (int) (totalRAM / 1.5);
else
maxMemoryAlloc = 4096;
return maxMemoryAlloc;
}
bool Application::handleDataMigration(const QString& currentData,
const QString& oldData,
const QString& name,
const QString& configFile) const
{
QString nomigratePath = FS::PathCombine(currentData, name + "_nomigrate.txt");
QStringList configPaths = { FS::PathCombine(oldData, configFile), FS::PathCombine(oldData, BuildConfig.LAUNCHER_CONFIGFILE) };
QLocale locale;
// Is there a valid config at the old location?
bool configExists = false;
for (QString configPath : configPaths) {
configExists |= QFileInfo::exists(configPath);
}
if (!configExists || QFileInfo::exists(nomigratePath)) {
qDebug() << "<> No migration needed from" << name;
return false;
}
QString message;
bool currentExists = QFileInfo::exists(FS::PathCombine(currentData, BuildConfig.LAUNCHER_CONFIGFILE));
if (currentExists) {
message = tr("Old data from %1 was found, but you already have existing data for %2. Sadly you will need to migrate yourself. Do "
"you want to be reminded of the pending data migration next time you start %2?")
.arg(name, BuildConfig.LAUNCHER_DISPLAYNAME);
} else {
message = tr("It looks like you used %1 before. Do you want to migrate your data to the new location of %2?")
.arg(name, BuildConfig.LAUNCHER_DISPLAYNAME);
QFileInfo logInfo(FS::PathCombine(oldData, name + "-0.log"));
if (logInfo.exists()) {
QString lastModified = logInfo.lastModified().toString(locale.dateFormat());
message = tr("It looks like you used %1 on %2 before. Do you want to migrate your data to the new location of %3?")
.arg(name, lastModified, BuildConfig.LAUNCHER_DISPLAYNAME);
}
}
QMessageBox::StandardButton askMoveDialogue =
QMessageBox::question(nullptr, BuildConfig.LAUNCHER_DISPLAYNAME, message, QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);
auto setDoNotMigrate = [&nomigratePath] {
QFile file(nomigratePath);
file.open(QIODevice::WriteOnly);
};
// create no-migrate file if user doesn't want to migrate
if (askMoveDialogue != QMessageBox::Yes) {
qDebug() << "<> Migration declined for" << name;
setDoNotMigrate();
return currentExists; // cancel further migrations, if we already have a data directory
}
if (!currentExists) {
// Migrate!
auto matcher = std::make_shared<MultiMatcher>();
matcher->add(std::make_shared<SimplePrefixMatcher>(configFile));
matcher->add(std::make_shared<SimplePrefixMatcher>(
BuildConfig.LAUNCHER_CONFIGFILE)); // it's possible that we already used that directory before
matcher->add(std::make_shared<SimplePrefixMatcher>("accounts.json"));
matcher->add(std::make_shared<SimplePrefixMatcher>("accounts/"));
matcher->add(std::make_shared<SimplePrefixMatcher>("assets/"));
matcher->add(std::make_shared<SimplePrefixMatcher>("icons/"));
matcher->add(std::make_shared<SimplePrefixMatcher>("instances/"));
matcher->add(std::make_shared<SimplePrefixMatcher>("libraries/"));
matcher->add(std::make_shared<SimplePrefixMatcher>("mods/"));
matcher->add(std::make_shared<SimplePrefixMatcher>("themes/"));
ProgressDialog diag;
DataMigrationTask task(nullptr, oldData, currentData, matcher);
if (diag.execWithTask(&task)) {
qDebug() << "<> Migration succeeded";
setDoNotMigrate();
} else {
QString reason = task.failReason();
QMessageBox::critical(nullptr, BuildConfig.LAUNCHER_DISPLAYNAME, tr("Migration failed! Reason: %1").arg(reason));
}
} else {
qWarning() << "<> Migration was skipped, due to existing data";
}
return true;
}
void Application::triggerUpdateCheck()
{
if (m_updater) {
qDebug() << "Checking for updates.";
m_updater->setBetaAllowed(false); // There are no other channels than stable
m_updater->checkForUpdates();
} else {
qDebug() << "Updater not available.";
}
}

View File

@ -1,7 +1,9 @@
// SPDX-License-Identifier: GPL-3.0-only // SPDX-License-Identifier: GPL-3.0-only
/* /*
* PolyMC - Minecraft Launcher * Prism Launcher - Minecraft Launcher
* Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net> * Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net>
* Copyright (C) 2022 Tayou <tayou@gmx.net>
* Copyright (C) 2023 TheKodeToad <TheKodeToad@proton.me>
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -42,7 +44,6 @@
#include <QIcon> #include <QIcon>
#include <QDateTime> #include <QDateTime>
#include <QUrl> #include <QUrl>
#include <updater/GoUpdate.h>
#include <BaseInstance.h> #include <BaseInstance.h>
@ -62,12 +63,13 @@ class AccountList;
class IconList; class IconList;
class QNetworkAccessManager; class QNetworkAccessManager;
class JavaInstallList; class JavaInstallList;
class UpdateChecker; class ExternalUpdater;
class BaseProfilerFactory; class BaseProfilerFactory;
class BaseDetachedToolFactory; class BaseDetachedToolFactory;
class TranslationsModel; class TranslationsModel;
class ITheme; class ITheme;
class MCEditTool; class MCEditTool;
class ThemeManager;
namespace Meta { namespace Meta {
class Index; class Index;
@ -95,6 +97,8 @@ public:
SupportsMSA = 1 << 0, SupportsMSA = 1 << 0,
SupportsFlame = 1 << 1, SupportsFlame = 1 << 1,
SupportsGameMode = 1 << 2,
SupportsMangoHud = 1 << 3,
}; };
Q_DECLARE_FLAGS(Capabilities, Capability) Q_DECLARE_FLAGS(Capabilities, Capability)
@ -114,18 +118,20 @@ public:
QIcon getThemedIcon(const QString& name); QIcon getThemedIcon(const QString& name);
bool isFlatpak();
void setIconTheme(const QString& name); void setIconTheme(const QString& name);
std::vector<ITheme *> getValidApplicationThemes(); void applyCurrentlySelectedTheme(bool initial = false);
void setApplicationTheme(const QString& name, bool initial); QList<ITheme*> getValidApplicationThemes();
shared_qobject_ptr<UpdateChecker> updateChecker() { void setApplicationTheme(const QString& name);
return m_updateChecker;
shared_qobject_ptr<ExternalUpdater> updater() {
return m_updater;
} }
void triggerUpdateCheck();
std::shared_ptr<TranslationsModel> translations(); std::shared_ptr<TranslationsModel> translations();
std::shared_ptr<JavaInstallList> javalist(); std::shared_ptr<JavaInstallList> javalist();
@ -162,7 +168,7 @@ public:
shared_qobject_ptr<Meta::Index> metadataIndex(); shared_qobject_ptr<Meta::Index> metadataIndex();
Capabilities currentCapabilities(); void updateCapabilities();
/*! /*!
* Finds and returns the full path to a jar file. * Finds and returns the full path to a jar file.
@ -172,6 +178,7 @@ public:
QString getMSAClientID(); QString getMSAClientID();
QString getFlameAPIKey(); QString getFlameAPIKey();
QString getModrinthAPIToken();
QString getUserAgent(); QString getUserAgent();
QString getUserAgentUncached(); QString getUserAgentUncached();
@ -180,6 +187,14 @@ public:
return m_rootPath; return m_rootPath;
} }
bool isPortable() {
return m_portable;
}
const Capabilities capabilities() {
return m_capabilities;
}
/*! /*!
* Opens a json file using either a system default editor, or, if not empty, the editor * Opens a json file using either a system default editor, or, if not empty, the editor
* specified in the settings * specified in the settings
@ -194,10 +209,13 @@ public:
void ShowGlobalSettings(class QWidget * parent, QString open_page = QString()); void ShowGlobalSettings(class QWidget * parent, QString open_page = QString());
int suitableMaxMem();
signals: signals:
void updateAllowedChanged(bool status); void updateAllowedChanged(bool status);
void globalSettingsAboutToOpen(); void globalSettingsAboutToOpen();
void globalSettingsClosed(); void globalSettingsClosed();
int currentCatChanged(int index);
#ifdef Q_OS_MACOS #ifdef Q_OS_MACOS
void clickedOnDock(); void clickedOnDock();
@ -207,6 +225,7 @@ public slots:
bool launch( bool launch(
InstancePtr instance, InstancePtr instance,
bool online = true, bool online = true,
bool demo = false,
BaseProfilerFactory *profiler = nullptr, BaseProfilerFactory *profiler = nullptr,
MinecraftServerTargetPtr serverToJoin = nullptr, MinecraftServerTargetPtr serverToJoin = nullptr,
MinecraftAccountPtr accountToUse = nullptr MinecraftAccountPtr accountToUse = nullptr
@ -222,6 +241,7 @@ private slots:
void setupWizardFinished(int status); void setupWizardFinished(int status);
private: private:
bool handleDataMigration(const QString & currentData, const QString & oldData, const QString & name, const QString & configFile) const;
bool createSetupWizard(); bool createSetupWizard();
void performMainStartupAction(); void performMainStartupAction();
@ -238,7 +258,7 @@ private:
shared_qobject_ptr<QNetworkAccessManager> m_network; shared_qobject_ptr<QNetworkAccessManager> m_network;
shared_qobject_ptr<UpdateChecker> m_updateChecker; shared_qobject_ptr<ExternalUpdater> m_updater;
shared_qobject_ptr<AccountList> m_accounts; shared_qobject_ptr<AccountList> m_accounts;
shared_qobject_ptr<HttpMetaCache> m_metacache; shared_qobject_ptr<HttpMetaCache> m_metacache;
@ -250,14 +270,16 @@ private:
std::shared_ptr<JavaInstallList> m_javalist; std::shared_ptr<JavaInstallList> m_javalist;
std::shared_ptr<TranslationsModel> m_translations; std::shared_ptr<TranslationsModel> m_translations;
std::shared_ptr<GenericPageProvider> m_globalSettingsProvider; std::shared_ptr<GenericPageProvider> m_globalSettingsProvider;
std::map<QString, std::unique_ptr<ITheme>> m_themes;
std::unique_ptr<MCEditTool> m_mcedit; std::unique_ptr<MCEditTool> m_mcedit;
QSet<QString> m_features; QSet<QString> m_features;
std::unique_ptr<ThemeManager> m_themeManager;
QMap<QString, std::shared_ptr<BaseProfilerFactory>> m_profilers; QMap<QString, std::shared_ptr<BaseProfilerFactory>> m_profilers;
QString m_rootPath; QString m_rootPath;
Status m_status = Application::StartingUp; Status m_status = Application::StartingUp;
Capabilities m_capabilities;
bool m_portable = false;
#ifdef Q_OS_MACOS #ifdef Q_OS_MACOS
Qt::ApplicationState m_prevAppState = Qt::ApplicationInactive; Qt::ApplicationState m_prevAppState = Qt::ApplicationInactive;
@ -292,7 +314,7 @@ public:
QString m_serverToJoin; QString m_serverToJoin;
QString m_profileToUse; QString m_profileToUse;
bool m_liveCheck = false; bool m_liveCheck = false;
QUrl m_zipToImport; QList<QUrl> m_zipsToImport;
QString m_instanceIdToShowWindowOf;
std::unique_ptr<QFile> logFile; std::unique_ptr<QFile> logFile;
}; };

View File

@ -47,8 +47,8 @@ void ApplicationMessage::parse(const QByteArray & input) {
args.clear(); args.clear();
auto parsedArgs = root.value("args").toObject(); auto parsedArgs = root.value("args").toObject();
for(auto iter = parsedArgs.begin(); iter != parsedArgs.end(); iter++) { for(auto iter = parsedArgs.constBegin(); iter != parsedArgs.constEnd(); iter++) {
args[iter.key()] = iter.value().toString(); args.insert(iter.key(), iter.value().toString());
} }
} }
@ -56,8 +56,8 @@ QByteArray ApplicationMessage::serialize() {
QJsonObject root; QJsonObject root;
root.insert("command", command); root.insert("command", command);
QJsonObject outArgs; QJsonObject outArgs;
for (auto iter = args.begin(); iter != args.end(); iter++) { for (auto iter = args.constBegin(); iter != args.constEnd(); iter++) {
outArgs[iter.key()] = iter.value(); outArgs.insert(iter.key(), iter.value());
} }
root.insert("args", outArgs); root.insert("args", outArgs);

View File

@ -1,12 +1,12 @@
#pragma once #pragma once
#include <QString> #include <QString>
#include <QMap> #include <QHash>
#include <QByteArray> #include <QByteArray>
struct ApplicationMessage { struct ApplicationMessage {
QString command; QString command;
QMap<QString, QString> args; QHash<QString, QString> args;
QByteArray serialize(); QByteArray serialize();
void parse(const QByteArray & input); void parse(const QByteArray & input);

View File

@ -17,13 +17,14 @@
#include <memory> #include <memory>
#include "BaseVersion.h"
class MinecraftInstance; class MinecraftInstance;
class QDir; class QDir;
class QString; class QString;
class QObject; class QObject;
class Task; class Task;
class BaseVersion; class BaseVersion;
typedef std::shared_ptr<BaseVersion> BaseVersionPtr;
class BaseInstaller class BaseInstaller
{ {
@ -35,7 +36,7 @@ public:
virtual bool add(MinecraftInstance *to); virtual bool add(MinecraftInstance *to);
virtual bool remove(MinecraftInstance *from); virtual bool remove(MinecraftInstance *from);
virtual Task *createInstallTask(MinecraftInstance *instance, BaseVersionPtr version, QObject *parent) = 0; virtual Task *createInstallTask(MinecraftInstance *instance, BaseVersion::Ptr version, QObject *parent) = 0;
protected: protected:
virtual QString id() const = 0; virtual QString id() const = 0;

View File

@ -40,6 +40,8 @@
#include <QDir> #include <QDir>
#include <QDebug> #include <QDebug>
#include <QRegularExpression> #include <QRegularExpression>
#include <QJsonDocument>
#include <QJsonObject>
#include "settings/INISettingsObject.h" #include "settings/INISettingsObject.h"
#include "settings/Setting.h" #include "settings/Setting.h"
@ -53,15 +55,24 @@ BaseInstance::BaseInstance(SettingsObjectPtr globalSettings, SettingsObjectPtr s
: QObject() : QObject()
{ {
m_settings = settings; m_settings = settings;
m_global_settings = globalSettings;
m_rootDir = rootDir; m_rootDir = rootDir;
m_settings->registerSetting("name", "Unnamed Instance"); m_settings->registerSetting("name", "Unnamed Instance");
m_settings->registerSetting("iconKey", "default"); m_settings->registerSetting("iconKey", "default");
m_settings->registerSetting("notes", ""); m_settings->registerSetting("notes", "");
m_settings->registerSetting("lastLaunchTime", 0); m_settings->registerSetting("lastLaunchTime", 0);
m_settings->registerSetting("totalTimePlayed", 0); m_settings->registerSetting("totalTimePlayed", 0);
m_settings->registerSetting("lastTimePlayed", 0); m_settings->registerSetting("lastTimePlayed", 0);
m_settings->registerSetting("linkedInstances", "[]");
// Game time override
auto gameTimeOverride = m_settings->registerSetting("OverrideGameTime", false);
m_settings->registerOverride(globalSettings->getSetting("ShowGameTime"), gameTimeOverride);
m_settings->registerOverride(globalSettings->getSetting("RecordGameTime"), gameTimeOverride);
// NOTE: Sometimees InstanceType is already registered, as it was used to identify the type of // NOTE: Sometimees InstanceType is already registered, as it was used to identify the type of
// a locally stored instance // a locally stored instance
if (!m_settings->getSetting("InstanceType")) if (!m_settings->getSetting("InstanceType"))
@ -107,49 +118,59 @@ QString BaseInstance::getPostExitCommand()
return settings()->get("PostExitCommand").toString(); return settings()->get("PostExitCommand").toString();
} }
bool BaseInstance::isManagedPack() bool BaseInstance::isManagedPack() const
{ {
return settings()->get("ManagedPack").toBool(); return m_settings->get("ManagedPack").toBool();
} }
QString BaseInstance::getManagedPackType() QString BaseInstance::getManagedPackType() const
{ {
return settings()->get("ManagedPackType").toString(); return m_settings->get("ManagedPackType").toString();
} }
QString BaseInstance::getManagedPackID() QString BaseInstance::getManagedPackID() const
{ {
return settings()->get("ManagedPackID").toString(); return m_settings->get("ManagedPackID").toString();
} }
QString BaseInstance::getManagedPackName() QString BaseInstance::getManagedPackName() const
{ {
return settings()->get("ManagedPackName").toString(); return m_settings->get("ManagedPackName").toString();
} }
QString BaseInstance::getManagedPackVersionID() QString BaseInstance::getManagedPackVersionID() const
{ {
return settings()->get("ManagedPackVersionID").toString(); return m_settings->get("ManagedPackVersionID").toString();
} }
QString BaseInstance::getManagedPackVersionName() QString BaseInstance::getManagedPackVersionName() const
{ {
return settings()->get("ManagedPackVersionName").toString(); return m_settings->get("ManagedPackVersionName").toString();
} }
void BaseInstance::setManagedPack(const QString& type, const QString& id, const QString& name, const QString& versionId, const QString& version) void BaseInstance::setManagedPack(const QString& type, const QString& id, const QString& name, const QString& versionId, const QString& version)
{ {
settings()->set("ManagedPack", true); m_settings->set("ManagedPack", true);
settings()->set("ManagedPackType", type); m_settings->set("ManagedPackType", type);
settings()->set("ManagedPackID", id); m_settings->set("ManagedPackID", id);
settings()->set("ManagedPackName", name); m_settings->set("ManagedPackName", name);
settings()->set("ManagedPackVersionID", versionId); m_settings->set("ManagedPackVersionID", versionId);
settings()->set("ManagedPackVersionName", version); m_settings->set("ManagedPackVersionName", version);
}
void BaseInstance::copyManagedPack(BaseInstance& other)
{
m_settings->set("ManagedPack", other.isManagedPack());
m_settings->set("ManagedPackType", other.getManagedPackType());
m_settings->set("ManagedPackID", other.getManagedPackID());
m_settings->set("ManagedPackName", other.getManagedPackName());
m_settings->set("ManagedPackVersionID", other.getManagedPackVersionID());
m_settings->set("ManagedPackVersionName", other.getManagedPackVersionName());
} }
int BaseInstance::getConsoleMaxLines() const int BaseInstance::getConsoleMaxLines() const
{ {
auto lineSetting = settings()->getSetting("ConsoleMaxLines"); auto lineSetting = m_settings->getSetting("ConsoleMaxLines");
bool conversionOk = false; bool conversionOk = false;
int maxLines = lineSetting->get().toInt(&conversionOk); int maxLines = lineSetting->get().toInt(&conversionOk);
if(!conversionOk) if(!conversionOk)
@ -162,7 +183,39 @@ int BaseInstance::getConsoleMaxLines() const
bool BaseInstance::shouldStopOnConsoleOverflow() const bool BaseInstance::shouldStopOnConsoleOverflow() const
{ {
return settings()->get("ConsoleOverflowStop").toBool(); return m_settings->get("ConsoleOverflowStop").toBool();
}
QStringList BaseInstance::getLinkedInstances() const
{
return m_settings->get("linkedInstances").toStringList();
}
void BaseInstance::setLinkedInstances(const QStringList& list)
{
auto linkedInstances = m_settings->get("linkedInstances").toStringList();
m_settings->set("linkedInstances", list);
}
void BaseInstance::addLinkedInstanceId(const QString& id)
{
auto linkedInstances = m_settings->get("linkedInstances").toStringList();
linkedInstances.append(id);
setLinkedInstances(linkedInstances);
}
bool BaseInstance::removeLinkedInstanceId(const QString& id)
{
auto linkedInstances = m_settings->get("linkedInstances").toStringList();
int numRemoved = linkedInstances.removeAll(id);
setLinkedInstances(linkedInstances);
return numRemoved > 0;
}
bool BaseInstance::isLinkedToInstanceId(const QString& id) const
{
auto linkedInstances = m_settings->get("linkedInstances").toStringList();
return linkedInstances.contains(id);
} }
void BaseInstance::iconUpdated(QString key) void BaseInstance::iconUpdated(QString key)
@ -237,7 +290,7 @@ void BaseInstance::setRunning(bool running)
int64_t BaseInstance::totalTimePlayed() const int64_t BaseInstance::totalTimePlayed() const
{ {
qint64 current = settings()->get("totalTimePlayed").toLongLong(); qint64 current = m_settings->get("totalTimePlayed").toLongLong();
if(m_isRunning) if(m_isRunning)
{ {
QDateTime timeNow = QDateTime::currentDateTime(); QDateTime timeNow = QDateTime::currentDateTime();
@ -253,7 +306,7 @@ int64_t BaseInstance::lastTimePlayed() const
QDateTime timeNow = QDateTime::currentDateTime(); QDateTime timeNow = QDateTime::currentDateTime();
return m_timeStarted.secsTo(timeNow); return m_timeStarted.secsTo(timeNow);
} }
return settings()->get("lastTimePlayed").toLongLong(); return m_settings->get("lastTimePlayed").toLongLong();
} }
void BaseInstance::resetTimePlayed() void BaseInstance::resetTimePlayed()
@ -272,8 +325,10 @@ QString BaseInstance::instanceRoot() const
return m_rootDir; return m_rootDir;
} }
SettingsObjectPtr BaseInstance::settings() const SettingsObjectPtr BaseInstance::settings()
{ {
loadSpecificSettings();
return m_settings; return m_settings;
} }
@ -336,11 +391,11 @@ QString BaseInstance::name() const
QString BaseInstance::windowTitle() const QString BaseInstance::windowTitle() const
{ {
return BuildConfig.LAUNCHER_NAME + ": " + name().replace(QRegularExpression("\\s+"), " "); return BuildConfig.LAUNCHER_DISPLAYNAME + ": " + name().replace(QRegularExpression("\\s+"), " ");
} }
// FIXME: why is this here? move it to MinecraftInstance!!! // FIXME: why is this here? move it to MinecraftInstance!!!
QStringList BaseInstance::extraArguments() const QStringList BaseInstance::extraArguments()
{ {
return Commandline::splitArgs(settings()->get("JvmArgs").toString()); return Commandline::splitArgs(settings()->get("JvmArgs").toString());
} }
@ -349,3 +404,8 @@ shared_qobject_ptr<LaunchTask> BaseInstance::getLaunchTask()
{ {
return m_launchProcess; return m_launchProcess;
} }
void BaseInstance::updateRuntimeContext()
{
// NOOP
}

View File

@ -54,6 +54,7 @@
#include "net/Mode.h" #include "net/Mode.h"
#include "minecraft/launch/MinecraftServerTarget.h" #include "minecraft/launch/MinecraftServerTarget.h"
#include "RuntimeContext.h"
class QDir; class QDir;
class Task; class Task;
@ -140,21 +141,22 @@ public:
QString getPostExitCommand(); QString getPostExitCommand();
QString getWrapperCommand(); QString getWrapperCommand();
bool isManagedPack(); bool isManagedPack() const;
QString getManagedPackType(); QString getManagedPackType() const;
QString getManagedPackID(); QString getManagedPackID() const;
QString getManagedPackName(); QString getManagedPackName() const;
QString getManagedPackVersionID(); QString getManagedPackVersionID() const;
QString getManagedPackVersionName(); QString getManagedPackVersionName() const;
void setManagedPack(const QString& type, const QString& id, const QString& name, const QString& versionId, const QString& version); 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 /// guess log level from a line of game log
virtual MessageLevel::Enum guessLevel(const QString &line, MessageLevel::Enum level) virtual MessageLevel::Enum guessLevel([[maybe_unused]] const QString &line, MessageLevel::Enum level)
{ {
return level; return level;
}; };
virtual QStringList extraArguments() const; virtual QStringList extraArguments();
/// Traits. Normally inside the version, depends on instance implementation. /// Traits. Normally inside the version, depends on instance implementation.
virtual QSet <QString> traits() const = 0; virtual QSet <QString> traits() const = 0;
@ -170,9 +172,18 @@ public:
/*! /*!
* \brief Gets this instance's settings object. * \brief Gets this instance's settings object.
* This settings object stores instance-specific settings. * This settings object stores instance-specific settings.
*
* Note that this method is not const.
* It may call loadSpecificSettings() to ensure those are loaded.
*
* \return A pointer to this instance's settings object. * \return A pointer to this instance's settings object.
*/ */
virtual SettingsObjectPtr settings() const; virtual SettingsObjectPtr settings();
/*!
* \brief Loads settings specific to an instance type if they're not already loaded.
*/
virtual void loadSpecificSettings() = 0;
/// returns a valid update task /// returns a valid update task
virtual Task::Ptr createUpdateTask(Net::Mode mode) = 0; virtual Task::Ptr createUpdateTask(Net::Mode mode) = 0;
@ -206,10 +217,16 @@ public:
virtual QString instanceConfigFolder() const = 0; virtual QString instanceConfigFolder() const = 0;
/// get variables this instance exports /// get variables this instance exports
virtual QMap<QString, QString> getVariables() const = 0; virtual QMap<QString, QString> getVariables() = 0;
virtual QString typeName() const = 0; virtual QString typeName() const = 0;
void updateRuntimeContext();
RuntimeContext runtimeContext() const
{
return m_runtimeContext;
}
bool hasVersionBroken() const bool hasVersionBroken() const
{ {
return m_hasBrokenVersion; return m_hasBrokenVersion;
@ -265,9 +282,20 @@ public:
int getConsoleMaxLines() const; int getConsoleMaxLines() const;
bool shouldStopOnConsoleOverflow() const; bool shouldStopOnConsoleOverflow() const;
QStringList getLinkedInstances() const;
void setLinkedInstances(const QStringList& list);
void addLinkedInstanceId(const QString& id);
bool removeLinkedInstanceId(const QString& id);
bool isLinkedToInstanceId(const QString& id) const;
protected: protected:
void changeStatus(Status newStatus); void changeStatus(Status newStatus);
SettingsObjectPtr globalSettings() const { return m_global_settings.lock(); };
bool isSpecificSettingsLoaded() const { return m_specific_settings_loaded; }
void setSpecificSettingsLoaded(bool loaded) { m_specific_settings_loaded = loaded; }
signals: signals:
/*! /*!
* \brief Signal emitted when properties relevant to the instance view change * \brief Signal emitted when properties relevant to the instance view change
@ -290,12 +318,17 @@ protected: /* data */
bool m_isRunning = false; bool m_isRunning = false;
shared_qobject_ptr<LaunchTask> m_launchProcess; shared_qobject_ptr<LaunchTask> m_launchProcess;
QDateTime m_timeStarted; QDateTime m_timeStarted;
RuntimeContext m_runtimeContext;
private: /* data */ private: /* data */
Status m_status = Status::Present; Status m_status = Status::Present;
bool m_crashed = false; bool m_crashed = false;
bool m_hasUpdate = false; bool m_hasUpdate = false;
bool m_hasBrokenVersion = false; bool m_hasBrokenVersion = false;
SettingsObjectWeakPtr m_global_settings;
bool m_specific_settings_loaded = false;
}; };
Q_DECLARE_METATYPE(shared_qobject_ptr<BaseInstance>) Q_DECLARE_METATYPE(shared_qobject_ptr<BaseInstance>)

View File

@ -25,6 +25,7 @@
class BaseVersion class BaseVersion
{ {
public: public:
using Ptr = std::shared_ptr<BaseVersion>;
virtual ~BaseVersion() {} virtual ~BaseVersion() {}
/*! /*!
* A string used to identify this version in config files. * A string used to identify this version in config files.
@ -54,6 +55,4 @@ public:
}; };
}; };
typedef std::shared_ptr<BaseVersion> BaseVersionPtr; Q_DECLARE_METATYPE(BaseVersion::Ptr)
Q_DECLARE_METATYPE(BaseVersionPtr)

View File

@ -40,20 +40,20 @@ BaseVersionList::BaseVersionList(QObject *parent) : QAbstractListModel(parent)
{ {
} }
BaseVersionPtr BaseVersionList::findVersion(const QString &descriptor) BaseVersion::Ptr BaseVersionList::findVersion(const QString &descriptor)
{ {
for (int i = 0; i < count(); i++) for (int i = 0; i < count(); i++)
{ {
if (at(i)->descriptor() == descriptor) if (at(i)->descriptor() == descriptor)
return at(i); return at(i);
} }
return BaseVersionPtr(); return nullptr;
} }
BaseVersionPtr BaseVersionList::getRecommended() const BaseVersion::Ptr BaseVersionList::getRecommended() const
{ {
if (count() <= 0) if (count() <= 0)
return BaseVersionPtr(); return nullptr;
else else
return at(0); return at(0);
} }
@ -66,7 +66,7 @@ QVariant BaseVersionList::data(const QModelIndex &index, int role) const
if (index.row() > count()) if (index.row() > count())
return QVariant(); return QVariant();
BaseVersionPtr version = at(index.row()); BaseVersion::Ptr version = at(index.row());
switch (role) switch (role)
{ {
@ -95,12 +95,12 @@ BaseVersionList::RoleList BaseVersionList::providesRoles() const
int BaseVersionList::rowCount(const QModelIndex &parent) const int BaseVersionList::rowCount(const QModelIndex &parent) const
{ {
// Return count // Return count
return count(); return parent.isValid() ? 0 : count();
} }
int BaseVersionList::columnCount(const QModelIndex &parent) const int BaseVersionList::columnCount(const QModelIndex &parent) const
{ {
return 1; return parent.isValid() ? 0 : 1;
} }
QHash<int, QByteArray> BaseVersionList::roleNames() const QHash<int, QByteArray> BaseVersionList::roleNames() const

View File

@ -70,7 +70,7 @@ public:
virtual bool isLoaded() = 0; virtual bool isLoaded() = 0;
//! Gets the version at the given index. //! Gets the version at the given index.
virtual const BaseVersionPtr at(int i) const = 0; virtual const BaseVersion::Ptr at(int i) const = 0;
//! Returns the number of versions in the list. //! Returns the number of versions in the list.
virtual int count() const = 0; virtual int count() const = 0;
@ -90,13 +90,13 @@ public:
* \return A const pointer to the version with the given descriptor. NULL if * \return A const pointer to the version with the given descriptor. NULL if
* one doesn't exist. * one doesn't exist.
*/ */
virtual BaseVersionPtr findVersion(const QString &descriptor); virtual BaseVersion::Ptr findVersion(const QString &descriptor);
/*! /*!
* \brief Gets the recommended version from this list * \brief Gets the recommended version from this list
* If the list doesn't support recommended versions, this works exactly as getLatestStable * If the list doesn't support recommended versions, this works exactly as getLatestStable
*/ */
virtual BaseVersionPtr getRecommended() const; virtual BaseVersion::Ptr getRecommended() const;
/*! /*!
* Sorts the version list. * Sorts the version list.
@ -117,5 +117,5 @@ slots:
* then copies the versions and sets their parents correctly. * then copies the versions and sets their parents correctly.
* \param versions List of versions whose parents should be set. * \param versions List of versions whose parents should be set.
*/ */
virtual void updateListData(QList<BaseVersionPtr> versions) = 0; virtual void updateListData(QList<BaseVersion::Ptr> versions) = 0;
}; };

View File

@ -24,20 +24,24 @@ set(CORE_SOURCES
NullInstance.h NullInstance.h
MMCZip.h MMCZip.h
MMCZip.cpp MMCZip.cpp
MMCStrings.h StringUtils.h
MMCStrings.cpp StringUtils.cpp
QVariantUtils.h
RuntimeContext.h
# Basic instance manipulation tasks (derived from InstanceTask) # Basic instance manipulation tasks (derived from InstanceTask)
InstanceCreationTask.h InstanceCreationTask.h
InstanceCreationTask.cpp InstanceCreationTask.cpp
InstanceCopyPrefs.h
InstanceCopyPrefs.cpp
InstanceCopyTask.h InstanceCopyTask.h
InstanceCopyTask.cpp InstanceCopyTask.cpp
InstanceImportTask.h InstanceImportTask.h
InstanceImportTask.cpp InstanceImportTask.cpp
# Mod downloading task # Resource downloading task
ModDownloadTask.h ResourceDownloadTask.h
ModDownloadTask.cpp ResourceDownloadTask.cpp
# Use tracking separate from memory management # Use tracking separate from memory management
Usable.h Usable.h
@ -86,13 +90,18 @@ set(CORE_SOURCES
# Time # Time
MMCTime.h MMCTime.h
MMCTime.cpp MMCTime.cpp
MTPixmapCache.h
) )
if (UNIX AND NOT CYGWIN AND NOT APPLE)
set(CORE_SOURCES
${CORE_SOURCES}
ecm_add_test(FileSystem_test.cpp LINK_LIBRARIES Launcher_logic Qt${QT_VERSION_MAJOR}::Test # MangoHud
TEST_NAME FileSystem) # TODO: needs testdata MangoHud.h
MangoHud.cpp
ecm_add_test(GZip_test.cpp LINK_LIBRARIES Launcher_logic Qt${QT_VERSION_MAJOR}::Test )
TEST_NAME GZip) endif()
set(PATHMATCHER_SOURCES set(PATHMATCHER_SOURCES
# Path matchers # Path matchers
@ -100,6 +109,7 @@ set(PATHMATCHER_SOURCES
pathmatcher/IPathMatcher.h pathmatcher/IPathMatcher.h
pathmatcher/MultiMatcher.h pathmatcher/MultiMatcher.h
pathmatcher/RegexpMatcher.h pathmatcher/RegexpMatcher.h
pathmatcher/SimplePrefixMatcher.h
) )
set(NET_SOURCES set(NET_SOURCES
@ -114,6 +124,8 @@ set(NET_SOURCES
net/HttpMetaCache.h net/HttpMetaCache.h
net/MetaCacheSink.cpp net/MetaCacheSink.cpp
net/MetaCacheSink.h net/MetaCacheSink.h
net/Logging.h
net/Logging.cpp
net/NetAction.h net/NetAction.h
net/NetJob.cpp net/NetJob.cpp
net/NetJob.h net/NetJob.h
@ -152,12 +164,6 @@ set(LAUNCH_SOURCES
# Old update system # Old update system
set(UPDATE_SOURCES set(UPDATE_SOURCES
updater/GoUpdate.h
updater/GoUpdate.cpp
updater/UpdateChecker.h
updater/UpdateChecker.cpp
updater/DownloadTask.h
updater/DownloadTask.cpp
updater/ExternalUpdater.h updater/ExternalUpdater.h
) )
@ -294,8 +300,6 @@ set(MINECRAFT_SOURCES
minecraft/Rule.h minecraft/Rule.h
minecraft/OneSixVersionFormat.cpp minecraft/OneSixVersionFormat.cpp
minecraft/OneSixVersionFormat.h minecraft/OneSixVersionFormat.h
minecraft/OpSys.cpp
minecraft/OpSys.h
minecraft/ParseUtils.cpp minecraft/ParseUtils.cpp
minecraft/ParseUtils.h minecraft/ParseUtils.h
minecraft/ProfileUtils.cpp minecraft/ProfileUtils.cpp
@ -303,6 +307,8 @@ set(MINECRAFT_SOURCES
minecraft/Library.cpp minecraft/Library.cpp
minecraft/Library.h minecraft/Library.h
minecraft/MojangDownloadInfo.h minecraft/MojangDownloadInfo.h
minecraft/VanillaInstanceCreationTask.cpp
minecraft/VanillaInstanceCreationTask.h
minecraft/VersionFile.cpp minecraft/VersionFile.cpp
minecraft/VersionFile.h minecraft/VersionFile.h
minecraft/VersionFilterData.h minecraft/VersionFilterData.h
@ -318,16 +324,44 @@ set(MINECRAFT_SOURCES
minecraft/mod/ModDetails.h minecraft/mod/ModDetails.h
minecraft/mod/ModFolderModel.h minecraft/mod/ModFolderModel.h
minecraft/mod/ModFolderModel.cpp minecraft/mod/ModFolderModel.cpp
minecraft/mod/Resource.h
minecraft/mod/Resource.cpp
minecraft/mod/ResourceFolderModel.h
minecraft/mod/ResourceFolderModel.cpp
minecraft/mod/DataPack.h
minecraft/mod/DataPack.cpp
minecraft/mod/ResourcePack.h
minecraft/mod/ResourcePack.cpp
minecraft/mod/ResourcePackFolderModel.h minecraft/mod/ResourcePackFolderModel.h
minecraft/mod/ResourcePackFolderModel.cpp minecraft/mod/ResourcePackFolderModel.cpp
minecraft/mod/TexturePack.h
minecraft/mod/TexturePack.cpp
minecraft/mod/ShaderPack.h
minecraft/mod/ShaderPack.cpp
minecraft/mod/WorldSave.h
minecraft/mod/WorldSave.cpp
minecraft/mod/TexturePackFolderModel.h minecraft/mod/TexturePackFolderModel.h
minecraft/mod/TexturePackFolderModel.cpp minecraft/mod/TexturePackFolderModel.cpp
minecraft/mod/ShaderPackFolderModel.h
minecraft/mod/tasks/BasicFolderLoadTask.h
minecraft/mod/tasks/ModFolderLoadTask.h minecraft/mod/tasks/ModFolderLoadTask.h
minecraft/mod/tasks/ModFolderLoadTask.cpp minecraft/mod/tasks/ModFolderLoadTask.cpp
minecraft/mod/tasks/LocalModParseTask.h minecraft/mod/tasks/LocalModParseTask.h
minecraft/mod/tasks/LocalModParseTask.cpp minecraft/mod/tasks/LocalModParseTask.cpp
minecraft/mod/tasks/LocalModUpdateTask.h minecraft/mod/tasks/LocalModUpdateTask.h
minecraft/mod/tasks/LocalModUpdateTask.cpp minecraft/mod/tasks/LocalModUpdateTask.cpp
minecraft/mod/tasks/LocalDataPackParseTask.h
minecraft/mod/tasks/LocalDataPackParseTask.cpp
minecraft/mod/tasks/LocalResourcePackParseTask.h
minecraft/mod/tasks/LocalResourcePackParseTask.cpp
minecraft/mod/tasks/LocalTexturePackParseTask.h
minecraft/mod/tasks/LocalTexturePackParseTask.cpp
minecraft/mod/tasks/LocalShaderPackParseTask.h
minecraft/mod/tasks/LocalShaderPackParseTask.cpp
minecraft/mod/tasks/LocalWorldSaveParseTask.h
minecraft/mod/tasks/LocalWorldSaveParseTask.cpp
minecraft/mod/tasks/LocalResourceParse.h
minecraft/mod/tasks/LocalResourceParse.cpp
# Assets # Assets
minecraft/AssetsUtils.h minecraft/AssetsUtils.h
@ -345,42 +379,6 @@ set(MINECRAFT_SOURCES
mojang/PackageManifest.cpp mojang/PackageManifest.cpp
minecraft/Agent.h) minecraft/Agent.h)
ecm_add_test(minecraft/GradleSpecifier_test.cpp LINK_LIBRARIES Launcher_logic Qt${QT_VERSION_MAJOR}::Test
TEST_NAME GradleSpecifier)
if(BUILD_TESTING)
add_executable(PackageManifest
mojang/PackageManifest_test.cpp
)
target_link_libraries(PackageManifest
Launcher_logic
Qt${QT_VERSION_MAJOR}::Test
)
target_include_directories(PackageManifest
PRIVATE ../cmake/UnitTest/
)
add_test(
NAME PackageManifest
COMMAND PackageManifest
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
)
endif()
# TODO: needs minecraft/testdata
ecm_add_test(minecraft/MojangVersionFormat_test.cpp LINK_LIBRARIES Launcher_logic Qt${QT_VERSION_MAJOR}::Test
TEST_NAME MojangVersionFormat)
ecm_add_test(minecraft/Library_test.cpp LINK_LIBRARIES Launcher_logic Qt${QT_VERSION_MAJOR}::Test
TEST_NAME Library)
# FIXME: shares data with FileSystem test
# TODO: needs testdata
ecm_add_test(minecraft/mod/ModFolderModel_test.cpp LINK_LIBRARIES Launcher_logic Qt${QT_VERSION_MAJOR}::Test
TEST_NAME ModFolderModel)
ecm_add_test(minecraft/ParseUtils_test.cpp LINK_LIBRARIES Launcher_logic Qt${QT_VERSION_MAJOR}::Test
TEST_NAME ParseUtils)
# the screenshots feature # the screenshots feature
set(SCREENSHOTS_SOURCES set(SCREENSHOTS_SOURCES
screenshots/Screenshot.h screenshots/Screenshot.h
@ -402,9 +400,6 @@ set(TASKS_SOURCES
tasks/MultipleOptionsTask.cpp tasks/MultipleOptionsTask.cpp
) )
ecm_add_test(tasks/Task_test.cpp LINK_LIBRARIES Launcher_logic Qt${QT_VERSION_MAJOR}::Test
TEST_NAME Task)
set(SETTINGS_SOURCES set(SETTINGS_SOURCES
# Settings # Settings
settings/INIFile.cpp settings/INIFile.cpp
@ -421,9 +416,6 @@ set(SETTINGS_SOURCES
settings/SettingsObject.h settings/SettingsObject.h
) )
ecm_add_test(settings/INIFile_test.cpp LINK_LIBRARIES Launcher_logic Qt${QT_VERSION_MAJOR}::Test
TEST_NAME INIFile)
set(JAVA_SOURCES set(JAVA_SOURCES
java/JavaChecker.h java/JavaChecker.h
java/JavaChecker.cpp java/JavaChecker.cpp
@ -439,9 +431,6 @@ set(JAVA_SOURCES
java/JavaVersion.cpp java/JavaVersion.cpp
) )
ecm_add_test(java/JavaVersion_test.cpp LINK_LIBRARIES Launcher_logic Qt${QT_VERSION_MAJOR}::Test
TEST_NAME JavaVersion)
set(TRANSLATIONS_SOURCES set(TRANSLATIONS_SOURCES
translations/TranslationsModel.h translations/TranslationsModel.h
translations/TranslationsModel.cpp translations/TranslationsModel.cpp
@ -481,7 +470,7 @@ set(API_SOURCES
modplatform/ModIndex.h modplatform/ModIndex.h
modplatform/ModIndex.cpp modplatform/ModIndex.cpp
modplatform/ModAPI.h modplatform/ResourceAPI.h
modplatform/EnsureMetadataTask.h modplatform/EnsureMetadataTask.h
modplatform/EnsureMetadataTask.cpp modplatform/EnsureMetadataTask.cpp
@ -492,8 +481,12 @@ set(API_SOURCES
modplatform/flame/FlameAPI.cpp modplatform/flame/FlameAPI.cpp
modplatform/modrinth/ModrinthAPI.h modplatform/modrinth/ModrinthAPI.h
modplatform/modrinth/ModrinthAPI.cpp modplatform/modrinth/ModrinthAPI.cpp
modplatform/helpers/NetworkModAPI.h modplatform/helpers/NetworkResourceAPI.h
modplatform/helpers/NetworkModAPI.cpp modplatform/helpers/NetworkResourceAPI.cpp
modplatform/helpers/HashUtils.h
modplatform/helpers/HashUtils.cpp
modplatform/helpers/OverrideUtils.h
modplatform/helpers/OverrideUtils.cpp
) )
set(FTB_SOURCES set(FTB_SOURCES
@ -519,6 +512,8 @@ set(FLAME_SOURCES
modplatform/flame/FileResolvingTask.cpp modplatform/flame/FileResolvingTask.cpp
modplatform/flame/FlameCheckUpdate.cpp modplatform/flame/FlameCheckUpdate.cpp
modplatform/flame/FlameCheckUpdate.h modplatform/flame/FlameCheckUpdate.h
modplatform/flame/FlameInstanceCreationTask.h
modplatform/flame/FlameInstanceCreationTask.cpp
) )
set(MODRINTH_SOURCES set(MODRINTH_SOURCES
@ -528,13 +523,10 @@ set(MODRINTH_SOURCES
modplatform/modrinth/ModrinthPackManifest.h modplatform/modrinth/ModrinthPackManifest.h
modplatform/modrinth/ModrinthCheckUpdate.cpp modplatform/modrinth/ModrinthCheckUpdate.cpp
modplatform/modrinth/ModrinthCheckUpdate.h modplatform/modrinth/ModrinthCheckUpdate.h
) modplatform/modrinth/ModrinthInstanceCreationTask.cpp
modplatform/modrinth/ModrinthInstanceCreationTask.h
set(MODPACKSCH_SOURCES modplatform/modrinth/ModrinthPackExportTask.cpp
modplatform/modpacksch/FTBPackInstallTask.h modplatform/modrinth/ModrinthPackExportTask.h
modplatform/modpacksch/FTBPackInstallTask.cpp
modplatform/modpacksch/FTBPackManifest.h
modplatform/modpacksch/FTBPackManifest.cpp
) )
set(PACKWIZ_SOURCES set(PACKWIZ_SOURCES
@ -542,9 +534,6 @@ set(PACKWIZ_SOURCES
modplatform/packwiz/Packwiz.cpp modplatform/packwiz/Packwiz.cpp
) )
# TODO: needs modplatform/packwiz/testdata
ecm_add_test(modplatform/packwiz/Packwiz_test.cpp LINK_LIBRARIES Launcher_logic Qt${QT_VERSION_MAJOR}::Test
TEST_NAME Packwiz)
set(TECHNIC_SOURCES set(TECHNIC_SOURCES
modplatform/technic/SingleZipPackInstallTask.h modplatform/technic/SingleZipPackInstallTask.h
@ -568,14 +557,87 @@ set(ATLAUNCHER_SOURCES
modplatform/atlauncher/ATLShareCode.h modplatform/atlauncher/ATLShareCode.h
) )
ecm_add_test(meta/Index_test.cpp LINK_LIBRARIES Launcher_logic Qt${QT_VERSION_MAJOR}::Test set(LINKEXE_SOURCES
TEST_NAME Index) filelink/FileLink.h
filelink/FileLink.cpp
FileSystem.h
FileSystem.cpp
Exception.h
StringUtils.h
StringUtils.cpp
DesktopServices.h
DesktopServices.cpp
)
######## Logging categories ########
ecm_qt_declare_logging_category(CORE_SOURCES
HEADER Logging.h
IDENTIFIER authCredentials
CATEGORY_NAME "launcher.auth.credentials"
DEFAULT_SEVERITY Warning
DESCRIPTION "Secrets and credentials for debugging purposes"
EXPORT "${Launcher_Name}"
)
ecm_qt_export_logging_category(
IDENTIFIER taskLogC
CATEGORY_NAME "launcher.task"
DEFAULT_SEVERITY Debug
DESCRIPTION "Task actions"
EXPORT "${Launcher_Name}"
)
ecm_qt_export_logging_category(
IDENTIFIER taskNetLogC
CATEGORY_NAME "launcher.task.net"
DEFAULT_SEVERITY Debug
DESCRIPTION "task network action"
EXPORT "${Launcher_Name}"
)
ecm_qt_export_logging_category(
IDENTIFIER taskDownloadLogC
CATEGORY_NAME "launcher.task.net.download"
DEFAULT_SEVERITY Debug
DESCRIPTION "task network download actions"
EXPORT "${Launcher_Name}"
)
ecm_qt_export_logging_category(
IDENTIFIER taskUploadLogC
CATEGORY_NAME "launcher.task.net.upload"
DEFAULT_SEVERITY Debug
DESCRIPTION "task network upload actions"
EXPORT "${Launcher_Name}"
)
ecm_qt_export_logging_category(
IDENTIFIER taskMetaCacheLogC
CATEGORY_NAME "launcher.task.net.metacache"
DEFAULT_SEVERITY Debug
DESCRIPTION "task network meta-cache actions"
EXPORT "${Launcher_Name}"
)
ecm_qt_export_logging_category(
IDENTIFIER taskHttpMetaCacheLogC
CATEGORY_NAME "launcher.task.net.metacache.http"
DEFAULT_SEVERITY Debug
DESCRIPTION "task network http meta-cache actions"
EXPORT "${Launcher_Name}"
)
if(KDE_INSTALL_LOGGINGCATEGORIESDIR) # only install if there is a standard path for this
ecm_qt_install_logging_categories(
EXPORT "${Launcher_Name}"
DESTINATION "${KDE_INSTALL_LOGGINGCATEGORIESDIR}"
)
endif()
################################ COMPILE ################################ ################################ COMPILE ################################
# we need zlib
find_package(ZLIB REQUIRED)
set(LOGIC_SOURCES set(LOGIC_SOURCES
${CORE_SOURCES} ${CORE_SOURCES}
${PATHMATCHER_SOURCES} ${PATHMATCHER_SOURCES}
@ -596,7 +658,6 @@ set(LOGIC_SOURCES
${FTB_SOURCES} ${FTB_SOURCES}
${FLAME_SOURCES} ${FLAME_SOURCES}
${MODRINTH_SOURCES} ${MODRINTH_SOURCES}
${MODPACKSCH_SOURCES}
${PACKWIZ_SOURCES} ${PACKWIZ_SOURCES}
${TECHNIC_SOURCES} ${TECHNIC_SOURCES}
${ATLAUNCHER_SOURCES} ${ATLAUNCHER_SOURCES}
@ -610,8 +671,8 @@ SET(LAUNCHER_SOURCES
# Application base # Application base
Application.h Application.h
Application.cpp Application.cpp
UpdateController.cpp DataMigrationTask.h
UpdateController.h DataMigrationTask.cpp
ApplicationMessage.h ApplicationMessage.h
ApplicationMessage.cpp ApplicationMessage.cpp
@ -620,7 +681,7 @@ SET(LAUNCHER_SOURCES
DesktopServices.cpp DesktopServices.cpp
VersionProxyModel.h VersionProxyModel.h
VersionProxyModel.cpp VersionProxyModel.cpp
HoeDown.h Markdown.h
# Super secret! # Super secret!
KonamiCode.h KonamiCode.h
@ -633,9 +694,12 @@ SET(LAUNCHER_SOURCES
resources/pe_light/pe_light.qrc resources/pe_light/pe_light.qrc
resources/pe_colored/pe_colored.qrc resources/pe_colored/pe_colored.qrc
resources/pe_blue/pe_blue.qrc resources/pe_blue/pe_blue.qrc
resources/breeze_dark/breeze_dark.qrc
resources/breeze_light/breeze_light.qrc
resources/OSX/OSX.qrc resources/OSX/OSX.qrc
resources/iOS/iOS.qrc resources/iOS/iOS.qrc
resources/flat/flat.qrc resources/flat/flat.qrc
resources/flat_white/flat_white.qrc
resources/documents/documents.qrc resources/documents/documents.qrc
../${Launcher_Branding_LogoQRC} ../${Launcher_Branding_LogoQRC}
@ -658,6 +722,10 @@ SET(LAUNCHER_SOURCES
# FIXME: maybe find a better home for this. # FIXME: maybe find a better home for this.
SkinUtils.cpp SkinUtils.cpp
SkinUtils.h SkinUtils.h
FileIgnoreProxy.cpp
FileIgnoreProxy.h
FastFileIconProvider.cpp
FastFileIconProvider.h
# GUI - setup wizard # GUI - setup wizard
ui/setupwizard/SetupWizard.h ui/setupwizard/SetupWizard.h
@ -669,6 +737,8 @@ SET(LAUNCHER_SOURCES
ui/setupwizard/LanguageWizardPage.h ui/setupwizard/LanguageWizardPage.h
ui/setupwizard/PasteWizardPage.cpp ui/setupwizard/PasteWizardPage.cpp
ui/setupwizard/PasteWizardPage.h ui/setupwizard/PasteWizardPage.h
ui/setupwizard/ThemeWizardPage.cpp
ui/setupwizard/ThemeWizardPage.h
# GUI - themes # GUI - themes
ui/themes/FusionTheme.cpp ui/themes/FusionTheme.cpp
@ -683,6 +753,8 @@ SET(LAUNCHER_SOURCES
ui/themes/ITheme.h ui/themes/ITheme.h
ui/themes/SystemTheme.cpp ui/themes/SystemTheme.cpp
ui/themes/SystemTheme.h ui/themes/SystemTheme.h
ui/themes/ThemeManager.cpp
ui/themes/ThemeManager.h
# Processes # Processes
LaunchController.h LaunchController.h
@ -707,9 +779,14 @@ SET(LAUNCHER_SOURCES
ui/pages/instance/GameOptionsPage.h ui/pages/instance/GameOptionsPage.h
ui/pages/instance/VersionPage.cpp ui/pages/instance/VersionPage.cpp
ui/pages/instance/VersionPage.h ui/pages/instance/VersionPage.h
ui/pages/instance/ManagedPackPage.cpp
ui/pages/instance/ManagedPackPage.h
ui/pages/instance/TexturePackPage.h ui/pages/instance/TexturePackPage.h
ui/pages/instance/TexturePackPage.cpp
ui/pages/instance/ResourcePackPage.h ui/pages/instance/ResourcePackPage.h
ui/pages/instance/ResourcePackPage.cpp
ui/pages/instance/ShaderPackPage.h ui/pages/instance/ShaderPackPage.h
ui/pages/instance/ShaderPackPage.cpp
ui/pages/instance/ModFolderPage.cpp ui/pages/instance/ModFolderPage.cpp
ui/pages/instance/ModFolderPage.h ui/pages/instance/ModFolderPage.h
ui/pages/instance/NotesPage.cpp ui/pages/instance/NotesPage.cpp
@ -751,11 +828,26 @@ SET(LAUNCHER_SOURCES
ui/pages/modplatform/VanillaPage.cpp ui/pages/modplatform/VanillaPage.cpp
ui/pages/modplatform/VanillaPage.h ui/pages/modplatform/VanillaPage.h
ui/pages/modplatform/ResourcePage.cpp
ui/pages/modplatform/ResourcePage.h
ui/pages/modplatform/ResourceModel.cpp
ui/pages/modplatform/ResourceModel.h
ui/pages/modplatform/ModPage.cpp ui/pages/modplatform/ModPage.cpp
ui/pages/modplatform/ModPage.h ui/pages/modplatform/ModPage.h
ui/pages/modplatform/ModModel.cpp ui/pages/modplatform/ModModel.cpp
ui/pages/modplatform/ModModel.h ui/pages/modplatform/ModModel.h
ui/pages/modplatform/ResourcePackPage.cpp
ui/pages/modplatform/ResourcePackModel.cpp
# Needed for MOC to find them without a corresponding .cpp
ui/pages/modplatform/TexturePackPage.h
ui/pages/modplatform/TexturePackModel.cpp
ui/pages/modplatform/ShaderPackPage.cpp
ui/pages/modplatform/ShaderPackModel.cpp
ui/pages/modplatform/atlauncher/AtlFilterModel.cpp ui/pages/modplatform/atlauncher/AtlFilterModel.cpp
ui/pages/modplatform/atlauncher/AtlFilterModel.h ui/pages/modplatform/atlauncher/AtlFilterModel.h
ui/pages/modplatform/atlauncher/AtlListModel.cpp ui/pages/modplatform/atlauncher/AtlListModel.cpp
@ -764,13 +856,8 @@ SET(LAUNCHER_SOURCES
ui/pages/modplatform/atlauncher/AtlOptionalModDialog.h ui/pages/modplatform/atlauncher/AtlOptionalModDialog.h
ui/pages/modplatform/atlauncher/AtlPage.cpp ui/pages/modplatform/atlauncher/AtlPage.cpp
ui/pages/modplatform/atlauncher/AtlPage.h ui/pages/modplatform/atlauncher/AtlPage.h
ui/pages/modplatform/atlauncher/AtlUserInteractionSupportImpl.cpp
ui/pages/modplatform/ftb/FtbFilterModel.cpp ui/pages/modplatform/atlauncher/AtlUserInteractionSupportImpl.h
ui/pages/modplatform/ftb/FtbFilterModel.h
ui/pages/modplatform/ftb/FtbListModel.cpp
ui/pages/modplatform/ftb/FtbListModel.h
ui/pages/modplatform/ftb/FtbPage.cpp
ui/pages/modplatform/ftb/FtbPage.h
ui/pages/modplatform/legacy_ftb/Page.cpp ui/pages/modplatform/legacy_ftb/Page.cpp
ui/pages/modplatform/legacy_ftb/Page.h ui/pages/modplatform/legacy_ftb/Page.h
@ -781,10 +868,10 @@ SET(LAUNCHER_SOURCES
ui/pages/modplatform/flame/FlameModel.h ui/pages/modplatform/flame/FlameModel.h
ui/pages/modplatform/flame/FlamePage.cpp ui/pages/modplatform/flame/FlamePage.cpp
ui/pages/modplatform/flame/FlamePage.h ui/pages/modplatform/flame/FlamePage.h
ui/pages/modplatform/flame/FlameModModel.cpp ui/pages/modplatform/flame/FlameResourceModels.cpp
ui/pages/modplatform/flame/FlameModModel.h ui/pages/modplatform/flame/FlameResourceModels.h
ui/pages/modplatform/flame/FlameModPage.cpp ui/pages/modplatform/flame/FlameResourcePages.cpp
ui/pages/modplatform/flame/FlameModPage.h ui/pages/modplatform/flame/FlameResourcePages.h
ui/pages/modplatform/modrinth/ModrinthPage.cpp ui/pages/modplatform/modrinth/ModrinthPage.cpp
ui/pages/modplatform/modrinth/ModrinthPage.h ui/pages/modplatform/modrinth/ModrinthPage.h
@ -799,10 +886,10 @@ SET(LAUNCHER_SOURCES
ui/pages/modplatform/ImportPage.cpp ui/pages/modplatform/ImportPage.cpp
ui/pages/modplatform/ImportPage.h ui/pages/modplatform/ImportPage.h
ui/pages/modplatform/modrinth/ModrinthModModel.cpp ui/pages/modplatform/modrinth/ModrinthResourceModels.cpp
ui/pages/modplatform/modrinth/ModrinthModModel.h ui/pages/modplatform/modrinth/ModrinthResourceModels.h
ui/pages/modplatform/modrinth/ModrinthModPage.cpp ui/pages/modplatform/modrinth/ModrinthResourcePages.cpp
ui/pages/modplatform/modrinth/ModrinthModPage.h ui/pages/modplatform/modrinth/ModrinthResourcePages.h
# GUI - dialogs # GUI - dialogs
ui/dialogs/AboutDialog.cpp ui/dialogs/AboutDialog.cpp
@ -819,8 +906,12 @@ SET(LAUNCHER_SOURCES
ui/dialogs/EditAccountDialog.h ui/dialogs/EditAccountDialog.h
ui/dialogs/ExportInstanceDialog.cpp ui/dialogs/ExportInstanceDialog.cpp
ui/dialogs/ExportInstanceDialog.h ui/dialogs/ExportInstanceDialog.h
ui/dialogs/ExportMrPackDialog.cpp
ui/dialogs/ExportMrPackDialog.h
ui/dialogs/IconPickerDialog.cpp ui/dialogs/IconPickerDialog.cpp
ui/dialogs/IconPickerDialog.h ui/dialogs/IconPickerDialog.h
ui/dialogs/ImportResourceDialog.cpp
ui/dialogs/ImportResourceDialog.h
ui/dialogs/LoginDialog.cpp ui/dialogs/LoginDialog.cpp
ui/dialogs/LoginDialog.h ui/dialogs/LoginDialog.h
ui/dialogs/MSALoginDialog.cpp ui/dialogs/MSALoginDialog.cpp
@ -839,16 +930,16 @@ SET(LAUNCHER_SOURCES
ui/dialogs/ProgressDialog.h ui/dialogs/ProgressDialog.h
ui/dialogs/ReviewMessageBox.cpp ui/dialogs/ReviewMessageBox.cpp
ui/dialogs/ReviewMessageBox.h ui/dialogs/ReviewMessageBox.h
ui/dialogs/UpdateDialog.cpp
ui/dialogs/UpdateDialog.h
ui/dialogs/VersionSelectDialog.cpp ui/dialogs/VersionSelectDialog.cpp
ui/dialogs/VersionSelectDialog.h ui/dialogs/VersionSelectDialog.h
ui/dialogs/SkinUploadDialog.cpp ui/dialogs/SkinUploadDialog.cpp
ui/dialogs/SkinUploadDialog.h ui/dialogs/SkinUploadDialog.h
ui/dialogs/ModDownloadDialog.cpp ui/dialogs/ResourceDownloadDialog.cpp
ui/dialogs/ModDownloadDialog.h ui/dialogs/ResourceDownloadDialog.h
ui/dialogs/ScrollMessageBox.cpp ui/dialogs/ScrollMessageBox.cpp
ui/dialogs/ScrollMessageBox.h ui/dialogs/ScrollMessageBox.h
ui/dialogs/BlockedModsDialog.cpp
ui/dialogs/BlockedModsDialog.h
ui/dialogs/ChooseProviderDialog.h ui/dialogs/ChooseProviderDialog.h
ui/dialogs/ChooseProviderDialog.cpp ui/dialogs/ChooseProviderDialog.cpp
ui/dialogs/ModUpdateDialog.cpp ui/dialogs/ModUpdateDialog.cpp
@ -875,8 +966,8 @@ SET(LAUNCHER_SOURCES
ui/widgets/LineSeparator.h ui/widgets/LineSeparator.h
ui/widgets/LogView.cpp ui/widgets/LogView.cpp
ui/widgets/LogView.h ui/widgets/LogView.h
ui/widgets/MCModInfoFrame.cpp ui/widgets/InfoFrame.cpp
ui/widgets/MCModInfoFrame.h ui/widgets/InfoFrame.h
ui/widgets/ModFilterWidget.cpp ui/widgets/ModFilterWidget.cpp
ui/widgets/ModFilterWidget.h ui/widgets/ModFilterWidget.h
ui/widgets/ModListView.cpp ui/widgets/ModListView.cpp
@ -884,6 +975,14 @@ SET(LAUNCHER_SOURCES
ui/widgets/PageContainer.cpp ui/widgets/PageContainer.cpp
ui/widgets/PageContainer.h ui/widgets/PageContainer.h
ui/widgets/PageContainer_p.h ui/widgets/PageContainer_p.h
ui/widgets/ProjectDescriptionPage.h
ui/widgets/ProjectDescriptionPage.cpp
ui/widgets/VariableSizedImageObject.h
ui/widgets/VariableSizedImageObject.cpp
ui/widgets/ProjectItem.h
ui/widgets/ProjectItem.cpp
ui/widgets/SubTaskProgressBar.h
ui/widgets/SubTaskProgressBar.cpp
ui/widgets/VersionListView.cpp ui/widgets/VersionListView.cpp
ui/widgets/VersionListView.h ui/widgets/VersionListView.h
ui/widgets/VersionSelectWidget.cpp ui/widgets/VersionSelectWidget.cpp
@ -892,6 +991,8 @@ SET(LAUNCHER_SOURCES
ui/widgets/ProgressWidget.cpp ui/widgets/ProgressWidget.cpp
ui/widgets/WideBar.h ui/widgets/WideBar.h
ui/widgets/WideBar.cpp ui/widgets/WideBar.cpp
ui/widgets/ThemeCustomizationWidget.h
ui/widgets/ThemeCustomizationWidget.cpp
# GUI - instance group view # GUI - instance group view
ui/instanceview/InstanceProxyModel.cpp ui/instanceview/InstanceProxyModel.cpp
@ -908,7 +1009,9 @@ SET(LAUNCHER_SOURCES
) )
qt_wrap_ui(LAUNCHER_UI qt_wrap_ui(LAUNCHER_UI
ui/MainWindow.ui
ui/setupwizard/PasteWizardPage.ui ui/setupwizard/PasteWizardPage.ui
ui/setupwizard/ThemeWizardPage.ui
ui/pages/global/AccountListPage.ui ui/pages/global/AccountListPage.ui
ui/pages/global/JavaPage.ui ui/pages/global/JavaPage.ui
ui/pages/global/LauncherPage.ui ui/pages/global/LauncherPage.ui
@ -924,33 +1027,36 @@ qt_wrap_ui(LAUNCHER_UI
ui/pages/instance/OtherLogsPage.ui ui/pages/instance/OtherLogsPage.ui
ui/pages/instance/InstanceSettingsPage.ui ui/pages/instance/InstanceSettingsPage.ui
ui/pages/instance/VersionPage.ui ui/pages/instance/VersionPage.ui
ui/pages/instance/ManagedPackPage.ui
ui/pages/instance/WorldListPage.ui ui/pages/instance/WorldListPage.ui
ui/pages/instance/ScreenshotsPage.ui ui/pages/instance/ScreenshotsPage.ui
ui/pages/modplatform/atlauncher/AtlOptionalModDialog.ui ui/pages/modplatform/atlauncher/AtlOptionalModDialog.ui
ui/pages/modplatform/atlauncher/AtlPage.ui ui/pages/modplatform/atlauncher/AtlPage.ui
ui/pages/modplatform/VanillaPage.ui ui/pages/modplatform/VanillaPage.ui
ui/pages/modplatform/ModPage.ui ui/pages/modplatform/ResourcePage.ui
ui/pages/modplatform/flame/FlamePage.ui ui/pages/modplatform/flame/FlamePage.ui
ui/pages/modplatform/legacy_ftb/Page.ui ui/pages/modplatform/legacy_ftb/Page.ui
ui/pages/modplatform/ImportPage.ui ui/pages/modplatform/ImportPage.ui
ui/pages/modplatform/ftb/FtbPage.ui
ui/pages/modplatform/modrinth/ModrinthPage.ui ui/pages/modplatform/modrinth/ModrinthPage.ui
ui/pages/modplatform/technic/TechnicPage.ui ui/pages/modplatform/technic/TechnicPage.ui
ui/widgets/InstanceCardWidget.ui ui/widgets/InstanceCardWidget.ui
ui/widgets/CustomCommands.ui ui/widgets/CustomCommands.ui
ui/widgets/MCModInfoFrame.ui ui/widgets/InfoFrame.ui
ui/widgets/ModFilterWidget.ui ui/widgets/ModFilterWidget.ui
ui/widgets/SubTaskProgressBar.ui
ui/widgets/ThemeCustomizationWidget.ui
ui/dialogs/CopyInstanceDialog.ui ui/dialogs/CopyInstanceDialog.ui
ui/dialogs/ProfileSetupDialog.ui ui/dialogs/ProfileSetupDialog.ui
ui/dialogs/ProgressDialog.ui ui/dialogs/ProgressDialog.ui
ui/dialogs/NewInstanceDialog.ui ui/dialogs/NewInstanceDialog.ui
ui/dialogs/UpdateDialog.ui
ui/dialogs/NewComponentDialog.ui ui/dialogs/NewComponentDialog.ui
ui/dialogs/NewsDialog.ui ui/dialogs/NewsDialog.ui
ui/dialogs/ProfileSelectDialog.ui ui/dialogs/ProfileSelectDialog.ui
ui/dialogs/SkinUploadDialog.ui ui/dialogs/SkinUploadDialog.ui
ui/dialogs/ExportInstanceDialog.ui ui/dialogs/ExportInstanceDialog.ui
ui/dialogs/ExportMrPackDialog.ui
ui/dialogs/IconPickerDialog.ui ui/dialogs/IconPickerDialog.ui
ui/dialogs/ImportResourceDialog.ui
ui/dialogs/MSALoginDialog.ui ui/dialogs/MSALoginDialog.ui
ui/dialogs/OfflineLoginDialog.ui ui/dialogs/OfflineLoginDialog.ui
ui/dialogs/AboutDialog.ui ui/dialogs/AboutDialog.ui
@ -958,6 +1064,7 @@ qt_wrap_ui(LAUNCHER_UI
ui/dialogs/EditAccountDialog.ui ui/dialogs/EditAccountDialog.ui
ui/dialogs/ReviewMessageBox.ui ui/dialogs/ReviewMessageBox.ui
ui/dialogs/ScrollMessageBox.ui ui/dialogs/ScrollMessageBox.ui
ui/dialogs/BlockedModsDialog.ui
ui/dialogs/ChooseProviderDialog.ui ui/dialogs/ChooseProviderDialog.ui
) )
@ -968,6 +1075,8 @@ qt_add_resources(LAUNCHER_RESOURCES
resources/pe_light/pe_light.qrc resources/pe_light/pe_light.qrc
resources/pe_colored/pe_colored.qrc resources/pe_colored/pe_colored.qrc
resources/pe_blue/pe_blue.qrc resources/pe_blue/pe_blue.qrc
resources/breeze_dark/breeze_dark.qrc
resources/breeze_light/breeze_light.qrc
resources/OSX/OSX.qrc resources/OSX/OSX.qrc
resources/iOS/iOS.qrc resources/iOS/iOS.qrc
resources/flat/flat.qrc resources/flat/flat.qrc
@ -982,17 +1091,18 @@ endif()
# Add executable # Add executable
add_library(Launcher_logic STATIC ${LOGIC_SOURCES} ${LAUNCHER_SOURCES} ${LAUNCHER_UI} ${LAUNCHER_RESOURCES}) add_library(Launcher_logic STATIC ${LOGIC_SOURCES} ${LAUNCHER_SOURCES} ${LAUNCHER_UI} ${LAUNCHER_RESOURCES})
target_include_directories(Launcher_logic PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
target_link_libraries(Launcher_logic target_link_libraries(Launcher_logic
systeminfo systeminfo
Launcher_classparser
Launcher_murmur2 Launcher_murmur2
nbt++ nbt++
${ZLIB_LIBRARIES} ${ZLIB_LIBRARIES}
optional-bare tomlplusplus::tomlplusplus
tomlc99 qdcss
BuildConfig BuildConfig
Katabasis Katabasis
Qt${QT_VERSION_MAJOR}::Widgets Qt${QT_VERSION_MAJOR}::Widgets
ghcFilesystem::ghc_filesystem
) )
if (UNIX AND NOT CYGWIN AND NOT APPLE) if (UNIX AND NOT CYGWIN AND NOT APPLE)
@ -1012,7 +1122,7 @@ target_link_libraries(Launcher_logic
) )
target_link_libraries(Launcher_logic target_link_libraries(Launcher_logic
QuaZip::QuaZip QuaZip::QuaZip
hoedown cmark::cmark
LocalPeer LocalPeer
Launcher_rainbow Launcher_rainbow
) )
@ -1057,6 +1167,41 @@ install(TARGETS ${Launcher_Name}
FRAMEWORK DESTINATION ${FRAMEWORK_DEST_DIR} COMPONENT Runtime FRAMEWORK DESTINATION ${FRAMEWORK_DEST_DIR} COMPONENT Runtime
) )
if(WIN32)
add_library(filelink_logic STATIC ${LINKEXE_SOURCES})
target_include_directories(filelink_logic PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
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
# Qt${QT_VERSION_MAJOR}::Concurrent
${Launcher_QT_LIBS}
)
add_executable("${Launcher_Name}_filelink" WIN32 filelink/main.cpp)
target_sources("${Launcher_Name}_filelink" PRIVATE filelink/filelink.exe.manifest)
target_link_libraries("${Launcher_Name}_filelink" filelink_logic)
if(DEFINED Launcher_APP_BINARY_NAME)
set_target_properties("${Launcher_Name}_filelink" PROPERTIES OUTPUT_NAME "${Launcher_APP_BINARY_NAME}_filelink")
endif()
if(DEFINED Launcher_BINARY_RPATH)
SET_TARGET_PROPERTIES("${Launcher_Name}_filelink" PROPERTIES INSTALL_RPATH "${Launcher_BINARY_RPATH}")
endif()
install(TARGETS "${Launcher_Name}_filelink"
BUNDLE DESTINATION "." COMPONENT Runtime
LIBRARY DESTINATION ${LIBRARY_DEST_DIR} COMPONENT Runtime
RUNTIME DESTINATION ${BINARY_DEST_DIR} COMPONENT Runtime
FRAMEWORK DESTINATION ${FRAMEWORK_DEST_DIR} COMPONENT Runtime
)
endif()
if (UNIX AND APPLE) if (UNIX AND APPLE)
# Add Sparkle updater # Add Sparkle updater
# It has to be copied here instead of just allowing fixup_bundle to install it, otherwise essential parts of # It has to be copied here instead of just allowing fixup_bundle to install it, otherwise essential parts of
@ -1073,97 +1218,106 @@ if(INSTALL_BUNDLE STREQUAL "full")
CODE "file(WRITE \"\${CMAKE_INSTALL_PREFIX}/${RESOURCES_DEST_DIR}/qt.conf\" \" \")" CODE "file(WRITE \"\${CMAKE_INSTALL_PREFIX}/${RESOURCES_DEST_DIR}/qt.conf\" \" \")"
COMPONENT Runtime COMPONENT Runtime
) )
# add qtlogging.ini as a config file
install(
FILES "qtlogging.ini"
DESTINATION ${CMAKE_INSTALL_PREFIX}/${RESOURCES_DEST_DIR}
COMPONENT Runtime
)
# Bundle plugins # Bundle plugins
if(CMAKE_BUILD_TYPE STREQUAL "Debug" OR CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo") # Image formats
# Image formats install(
DIRECTORY "${QT_PLUGINS_DIR}/imageformats"
CONFIGURATIONS Debug RelWithDebInfo ""
DESTINATION ${PLUGIN_DEST_DIR}
COMPONENT Runtime
REGEX "tga|tiff|mng" EXCLUDE
)
install(
DIRECTORY "${QT_PLUGINS_DIR}/imageformats"
CONFIGURATIONS Release MinSizeRel
DESTINATION ${PLUGIN_DEST_DIR}
COMPONENT Runtime
REGEX "tga|tiff|mng" EXCLUDE
REGEX "d\\." EXCLUDE
REGEX "_debug\\." EXCLUDE
REGEX "\\.dSYM" EXCLUDE
)
# Icon engines
install(
DIRECTORY "${QT_PLUGINS_DIR}/iconengines"
CONFIGURATIONS Debug RelWithDebInfo ""
DESTINATION ${PLUGIN_DEST_DIR}
COMPONENT Runtime
REGEX "fontawesome" EXCLUDE
)
install(
DIRECTORY "${QT_PLUGINS_DIR}/iconengines"
CONFIGURATIONS Release MinSizeRel
DESTINATION ${PLUGIN_DEST_DIR}
COMPONENT Runtime
REGEX "fontawesome" EXCLUDE
REGEX "d\\." EXCLUDE
REGEX "_debug\\." EXCLUDE
REGEX "\\.dSYM" EXCLUDE
)
# Platform plugins
install(
DIRECTORY "${QT_PLUGINS_DIR}/platforms"
CONFIGURATIONS Debug RelWithDebInfo ""
DESTINATION ${PLUGIN_DEST_DIR}
COMPONENT Runtime
REGEX "minimal|linuxfb|offscreen" EXCLUDE
)
install(
DIRECTORY "${QT_PLUGINS_DIR}/platforms"
CONFIGURATIONS Release MinSizeRel
DESTINATION ${PLUGIN_DEST_DIR}
COMPONENT Runtime
REGEX "minimal|linuxfb|offscreen" EXCLUDE
REGEX "[^2]d\\." EXCLUDE
REGEX "_debug\\." EXCLUDE
REGEX "\\.dSYM" EXCLUDE
)
# Style plugins
if(EXISTS "${QT_PLUGINS_DIR}/styles")
install( install(
DIRECTORY "${QT_PLUGINS_DIR}/imageformats" DIRECTORY "${QT_PLUGINS_DIR}/styles"
CONFIGURATIONS Debug RelWithDebInfo ""
DESTINATION ${PLUGIN_DEST_DIR} DESTINATION ${PLUGIN_DEST_DIR}
COMPONENT Runtime COMPONENT Runtime
REGEX "tga|tiff|mng" EXCLUDE
) )
# Icon engines
install( install(
DIRECTORY "${QT_PLUGINS_DIR}/iconengines" DIRECTORY "${QT_PLUGINS_DIR}/styles"
CONFIGURATIONS Release MinSizeRel
DESTINATION ${PLUGIN_DEST_DIR} DESTINATION ${PLUGIN_DEST_DIR}
COMPONENT Runtime COMPONENT Runtime
REGEX "fontawesome" EXCLUDE
)
# Platform plugins
install(
DIRECTORY "${QT_PLUGINS_DIR}/platforms"
DESTINATION ${PLUGIN_DEST_DIR}
COMPONENT Runtime
REGEX "minimal|linuxfb|offscreen" EXCLUDE
)
# Style plugins
if(EXISTS "${QT_PLUGINS_DIR}/styles")
install(
DIRECTORY "${QT_PLUGINS_DIR}/styles"
DESTINATION ${PLUGIN_DEST_DIR}
COMPONENT Runtime
)
endif()
# TLS plugins (Qt 6 only)
if(EXISTS "${QT_PLUGINS_DIR}/tls")
install(
DIRECTORY "${QT_PLUGINS_DIR}/tls"
DESTINATION ${PLUGIN_DEST_DIR}
COMPONENT Runtime
)
endif()
else()
# Image formats
install(
DIRECTORY "${QT_PLUGINS_DIR}/imageformats"
DESTINATION ${PLUGIN_DEST_DIR}
COMPONENT Runtime
REGEX "tga|tiff|mng" EXCLUDE
REGEX "d\\." EXCLUDE REGEX "d\\." EXCLUDE
REGEX "_debug\\." EXCLUDE REGEX "_debug\\." EXCLUDE
REGEX "\\.dSYM" EXCLUDE REGEX "\\.dSYM" EXCLUDE
) )
# Icon engines endif()
# TLS plugins (Qt 6 only)
if(EXISTS "${QT_PLUGINS_DIR}/tls")
install( install(
DIRECTORY "${QT_PLUGINS_DIR}/iconengines" DIRECTORY "${QT_PLUGINS_DIR}/tls"
CONFIGURATIONS Debug RelWithDebInfo ""
DESTINATION ${PLUGIN_DEST_DIR} DESTINATION ${PLUGIN_DEST_DIR}
COMPONENT Runtime COMPONENT Runtime
REGEX "fontawesome" EXCLUDE PATTERN "*qopensslbackend*" EXCLUDE
REGEX "d\\." EXCLUDE PATTERN "*qcertonlybackend*" EXCLUDE
REGEX "_debug\\." EXCLUDE
REGEX "\\.dSYM" EXCLUDE
) )
# Platform plugins
install( install(
DIRECTORY "${QT_PLUGINS_DIR}/platforms" DIRECTORY "${QT_PLUGINS_DIR}/tls"
CONFIGURATIONS Release MinSizeRel
DESTINATION ${PLUGIN_DEST_DIR} DESTINATION ${PLUGIN_DEST_DIR}
COMPONENT Runtime COMPONENT Runtime
REGEX "minimal|linuxfb|offscreen" EXCLUDE REGEX "dd\\." EXCLUDE
REGEX "d\\." EXCLUDE
REGEX "_debug\\." EXCLUDE REGEX "_debug\\." EXCLUDE
REGEX "\\.dSYM" EXCLUDE REGEX "\\.dSYM" EXCLUDE
PATTERN "*qopensslbackend*" EXCLUDE
PATTERN "*qcertonlybackend*" EXCLUDE
) )
# Style plugins
if(EXISTS "${QT_PLUGINS_DIR}/styles")
install(
DIRECTORY "${QT_PLUGINS_DIR}/styles"
DESTINATION ${PLUGIN_DEST_DIR}
COMPONENT Runtime
REGEX "d\\." EXCLUDE
REGEX "_debug\\." EXCLUDE
REGEX "\\.dSYM" EXCLUDE
)
endif()
# TLS plugins (Qt 6 only)
if(EXISTS "${QT_PLUGINS_DIR}/tls")
install(
DIRECTORY "${QT_PLUGINS_DIR}/tls"
DESTINATION ${PLUGIN_DEST_DIR}
COMPONENT Runtime
REGEX "_debug\\." EXCLUDE
REGEX "\\.dSYM" EXCLUDE
)
endif()
endif() endif()
configure_file( configure_file(
"${CMAKE_CURRENT_SOURCE_DIR}/install_prereqs.cmake.in" "${CMAKE_CURRENT_SOURCE_DIR}/install_prereqs.cmake.in"

View File

@ -92,412 +92,4 @@ QStringList splitArgs(QString args)
argv << current; argv << current;
return argv; return argv;
} }
Parser::Parser(FlagStyle::Enum flagStyle, ArgumentStyle::Enum argStyle)
{
m_flagStyle = flagStyle;
m_argStyle = argStyle;
}
// styles setter/getter
void Parser::setArgumentStyle(ArgumentStyle::Enum style)
{
m_argStyle = style;
}
ArgumentStyle::Enum Parser::argumentStyle()
{
return m_argStyle;
}
void Parser::setFlagStyle(FlagStyle::Enum style)
{
m_flagStyle = style;
}
FlagStyle::Enum Parser::flagStyle()
{
return m_flagStyle;
}
// setup methods
void Parser::addSwitch(QString name, bool def)
{
if (m_params.contains(name))
throw "Name not unique";
OptionDef *param = new OptionDef;
param->type = otSwitch;
param->name = name;
param->metavar = QString("<%1>").arg(name);
param->def = def;
m_options[name] = param;
m_params[name] = (CommonDef *)param;
m_optionList.append(param);
}
void Parser::addOption(QString name, QVariant def)
{
if (m_params.contains(name))
throw "Name not unique";
OptionDef *param = new OptionDef;
param->type = otOption;
param->name = name;
param->metavar = QString("<%1>").arg(name);
param->def = def;
m_options[name] = param;
m_params[name] = (CommonDef *)param;
m_optionList.append(param);
}
void Parser::addArgument(QString name, bool required, QVariant def)
{
if (m_params.contains(name))
throw "Name not unique";
PositionalDef *param = new PositionalDef;
param->name = name;
param->def = def;
param->required = required;
param->metavar = name;
m_positionals.append(param);
m_params[name] = (CommonDef *)param;
}
void Parser::addDocumentation(QString name, QString doc, QString metavar)
{
if (!m_params.contains(name))
throw "Name does not exist";
CommonDef *param = m_params[name];
param->doc = doc;
if (!metavar.isNull())
param->metavar = metavar;
}
void Parser::addShortOpt(QString name, QChar flag)
{
if (!m_params.contains(name))
throw "Name does not exist";
if (!m_options.contains(name))
throw "Name is not an Option or Swtich";
OptionDef *param = m_options[name];
m_flags[flag] = param;
param->flag = flag;
}
// help methods
QString Parser::compileHelp(QString progName, int helpIndent, bool useFlags)
{
QStringList help;
help << compileUsage(progName, useFlags) << "\r\n";
// positionals
if (!m_positionals.isEmpty())
{
help << "\r\n";
help << "Positional arguments:\r\n";
QListIterator<PositionalDef *> it2(m_positionals);
while (it2.hasNext())
{
PositionalDef *param = it2.next();
help << " " << param->metavar;
help << " " << QString(helpIndent - param->metavar.length() - 1, ' ');
help << param->doc << "\r\n";
}
}
// Options
if (!m_optionList.isEmpty())
{
help << "\r\n";
QString optPrefix, flagPrefix;
getPrefix(optPrefix, flagPrefix);
help << "Options & Switches:\r\n";
QListIterator<OptionDef *> it(m_optionList);
while (it.hasNext())
{
OptionDef *option = it.next();
help << " ";
int nameLength = optPrefix.length() + option->name.length();
if (!option->flag.isNull())
{
nameLength += 3 + flagPrefix.length();
help << flagPrefix << option->flag << ", ";
}
help << optPrefix << option->name;
if (option->type == otOption)
{
QString arg = QString("%1%2").arg(
((m_argStyle == ArgumentStyle::Equals) ? "=" : " "), option->metavar);
nameLength += arg.length();
help << arg;
}
help << " " << QString(helpIndent - nameLength - 1, ' ');
help << option->doc << "\r\n";
}
}
return help.join("");
}
QString Parser::compileUsage(QString progName, bool useFlags)
{
QStringList usage;
usage << "Usage: " << progName;
QString optPrefix, flagPrefix;
getPrefix(optPrefix, flagPrefix);
// options
QListIterator<OptionDef *> it(m_optionList);
while (it.hasNext())
{
OptionDef *option = it.next();
usage << " [";
if (!option->flag.isNull() && useFlags)
usage << flagPrefix << option->flag;
else
usage << optPrefix << option->name;
if (option->type == otOption)
usage << ((m_argStyle == ArgumentStyle::Equals) ? "=" : " ") << option->metavar;
usage << "]";
}
// arguments
QListIterator<PositionalDef *> it2(m_positionals);
while (it2.hasNext())
{
PositionalDef *param = it2.next();
usage << " " << (param->required ? "<" : "[");
usage << param->metavar;
usage << (param->required ? ">" : "]");
}
return usage.join("");
}
// parsing
QHash<QString, QVariant> Parser::parse(QStringList argv)
{
QHash<QString, QVariant> map;
QStringListIterator it(argv);
QString programName = it.next();
QString optionPrefix;
QString flagPrefix;
QListIterator<PositionalDef *> positionals(m_positionals);
QStringList expecting;
getPrefix(optionPrefix, flagPrefix);
while (it.hasNext())
{
QString arg = it.next();
if (!expecting.isEmpty())
// we were expecting an argument
{
QString name = expecting.first();
/*
if (map.contains(name))
throw ParsingError(
QString("Option %2%1 was given multiple times").arg(name, optionPrefix));
*/
map[name] = QVariant(arg);
expecting.removeFirst();
continue;
}
if (arg.startsWith(optionPrefix))
// we have an option
{
// qDebug("Found option %s", qPrintable(arg));
QString name = arg.mid(optionPrefix.length());
QString equals;
if ((m_argStyle == ArgumentStyle::Equals ||
m_argStyle == ArgumentStyle::SpaceAndEquals) &&
name.contains("="))
{
int i = name.indexOf("=");
equals = name.mid(i + 1);
name = name.left(i);
}
if (m_options.contains(name))
{
/*
if (map.contains(name))
throw ParsingError(QString("Option %2%1 was given multiple times")
.arg(name, optionPrefix));
*/
OptionDef *option = m_options[name];
if (option->type == otSwitch)
map[name] = true;
else // if (option->type == otOption)
{
if (m_argStyle == ArgumentStyle::Space)
expecting.append(name);
else if (!equals.isNull())
map[name] = equals;
else if (m_argStyle == ArgumentStyle::SpaceAndEquals)
expecting.append(name);
else
throw ParsingError(QString("Option %2%1 reqires an argument.")
.arg(name, optionPrefix));
}
continue;
}
throw ParsingError(QString("Unknown Option %2%1").arg(name, optionPrefix));
}
if (arg.startsWith(flagPrefix))
// we have (a) flag(s)
{
// qDebug("Found flags %s", qPrintable(arg));
QString flags = arg.mid(flagPrefix.length());
QString equals;
if ((m_argStyle == ArgumentStyle::Equals ||
m_argStyle == ArgumentStyle::SpaceAndEquals) &&
flags.contains("="))
{
int i = flags.indexOf("=");
equals = flags.mid(i + 1);
flags = flags.left(i);
}
for (int i = 0; i < flags.length(); i++)
{
QChar flag = flags.at(i);
if (!m_flags.contains(flag))
throw ParsingError(QString("Unknown flag %2%1").arg(flag, flagPrefix));
OptionDef *option = m_flags[flag];
/*
if (map.contains(option->name))
throw ParsingError(QString("Option %2%1 was given multiple times")
.arg(option->name, optionPrefix));
*/
if (option->type == otSwitch)
map[option->name] = true;
else // if (option->type == otOption)
{
if (m_argStyle == ArgumentStyle::Space)
expecting.append(option->name);
else if (!equals.isNull())
if (i == flags.length() - 1)
map[option->name] = equals;
else
throw ParsingError(QString("Flag %4%2 of Argument-requiring Option "
"%1 not last flag in %4%3")
.arg(option->name, flag, flags, flagPrefix));
else if (m_argStyle == ArgumentStyle::SpaceAndEquals)
expecting.append(option->name);
else
throw ParsingError(QString("Option %1 reqires an argument. (flag %3%2)")
.arg(option->name, flag, flagPrefix));
}
}
continue;
}
// must be a positional argument
if (!positionals.hasNext())
throw ParsingError(QString("Don't know what to do with '%1'").arg(arg));
PositionalDef *param = positionals.next();
map[param->name] = arg;
}
// check if we're missing something
if (!expecting.isEmpty())
throw ParsingError(QString("Was still expecting arguments for %2%1").arg(
expecting.join(QString(", ") + optionPrefix), optionPrefix));
while (positionals.hasNext())
{
PositionalDef *param = positionals.next();
if (param->required)
throw ParsingError(
QString("Missing required positional argument '%1'").arg(param->name));
else
map[param->name] = param->def;
}
// fill out gaps
QListIterator<OptionDef *> iter(m_optionList);
while (iter.hasNext())
{
OptionDef *option = iter.next();
if (!map.contains(option->name))
map[option->name] = option->def;
}
return map;
}
// clear defs
void Parser::clear()
{
m_flags.clear();
m_params.clear();
m_options.clear();
QMutableListIterator<OptionDef *> it(m_optionList);
while (it.hasNext())
{
OptionDef *option = it.next();
it.remove();
delete option;
}
QMutableListIterator<PositionalDef *> it2(m_positionals);
while (it2.hasNext())
{
PositionalDef *arg = it2.next();
it2.remove();
delete arg;
}
}
// Destructor
Parser::~Parser()
{
clear();
}
// getPrefix
void Parser::getPrefix(QString &opt, QString &flag)
{
if (m_flagStyle == FlagStyle::Windows)
opt = flag = "/";
else if (m_flagStyle == FlagStyle::Unix)
opt = flag = "-";
// else if (m_flagStyle == FlagStyle::GNU)
else
{
opt = "--";
flag = "-";
}
}
// ParsingError
ParsingError::ParsingError(const QString &what) : std::runtime_error(what.toStdString())
{
}
} }

View File

@ -17,12 +17,7 @@
#pragma once #pragma once
#include <exception>
#include <stdexcept>
#include <QString> #include <QString>
#include <QVariant>
#include <QHash>
#include <QStringList> #include <QStringList>
/** /**
@ -39,212 +34,4 @@ namespace Commandline
* @return a QStringList containing all arguments * @return a QStringList containing all arguments
*/ */
QStringList splitArgs(QString args); QStringList splitArgs(QString args);
/**
* @brief The FlagStyle enum
* Specifies how flags are decorated
*/
namespace FlagStyle
{
enum Enum
{
GNU, /**< --option and -o (GNU Style) */
Unix, /**< -option and -o (Unix Style) */
Windows, /**< /option and /o (Windows Style) */
#ifdef Q_OS_WIN32
Default = Windows
#else
Default = GNU
#endif
};
}
/**
* @brief The ArgumentStyle enum
*/
namespace ArgumentStyle
{
enum Enum
{
Space, /**< --option value */
Equals, /**< --option=value */
SpaceAndEquals, /**< --option[= ]value */
#ifdef Q_OS_WIN32
Default = Equals
#else
Default = SpaceAndEquals
#endif
};
}
/**
* @brief The ParsingError class
*/
class ParsingError : public std::runtime_error
{
public:
ParsingError(const QString &what);
};
/**
* @brief The Parser class
*/
class Parser
{
public:
/**
* @brief Parser constructor
* @param flagStyle the FlagStyle to use in this Parser
* @param argStyle the ArgumentStyle to use in this Parser
*/
Parser(FlagStyle::Enum flagStyle = FlagStyle::Default,
ArgumentStyle::Enum argStyle = ArgumentStyle::Default);
/**
* @brief set the flag style
* @param style
*/
void setFlagStyle(FlagStyle::Enum style);
/**
* @brief get the flag style
* @return
*/
FlagStyle::Enum flagStyle();
/**
* @brief set the argument style
* @param style
*/
void setArgumentStyle(ArgumentStyle::Enum style);
/**
* @brief get the argument style
* @return
*/
ArgumentStyle::Enum argumentStyle();
/**
* @brief define a boolean switch
* @param name the parameter name
* @param def the default value
*/
void addSwitch(QString name, bool def = false);
/**
* @brief define an option that takes an additional argument
* @param name the parameter name
* @param def the default value
*/
void addOption(QString name, QVariant def = QVariant());
/**
* @brief define a positional argument
* @param name the parameter name
* @param required wether this argument is required
* @param def the default value
*/
void addArgument(QString name, bool required = true, QVariant def = QVariant());
/**
* @brief adds a flag to an existing parameter
* @param name the (existing) parameter name
* @param flag the flag character
* @see addSwitch addArgument addOption
* Note: any one parameter can only have one flag
*/
void addShortOpt(QString name, QChar flag);
/**
* @brief adds documentation to a Parameter
* @param name the parameter name
* @param metavar a string to be displayed as placeholder for the value
* @param doc a QString containing the documentation
* Note: on positional arguments, metavar replaces the name as displayed.
* on options , metavar replaces the value placeholder
*/
void addDocumentation(QString name, QString doc, QString metavar = QString());
/**
* @brief generate a help message
* @param progName the program name to use in the help message
* @param helpIndent how much the parameter documentation should be indented
* @param flagsInUsage whether we should use flags instead of options in the usage
* @return a help message
*/
QString compileHelp(QString progName, int helpIndent = 22, bool flagsInUsage = true);
/**
* @brief generate a short usage message
* @param progName the program name to use in the usage message
* @param useFlags whether we should use flags instead of options
* @return a usage message
*/
QString compileUsage(QString progName, bool useFlags = true);
/**
* @brief parse
* @param argv a QStringList containing the program ARGV
* @return a QHash mapping argument names to their values
*/
QHash<QString, QVariant> parse(QStringList argv);
/**
* @brief clear all definitions
*/
void clear();
~Parser();
private:
FlagStyle::Enum m_flagStyle;
ArgumentStyle::Enum m_argStyle;
enum OptionType
{
otSwitch,
otOption
};
// Important: the common part MUST BE COMMON ON ALL THREE structs
struct CommonDef
{
QString name;
QString doc;
QString metavar;
QVariant def;
};
struct OptionDef
{
// common
QString name;
QString doc;
QString metavar;
QVariant def;
// option
OptionType type;
QChar flag;
};
struct PositionalDef
{
// common
QString name;
QString doc;
QString metavar;
QVariant def;
// positional
bool required;
};
QHash<QString, OptionDef *> m_options;
QHash<QChar, OptionDef *> m_flags;
QHash<QString, CommonDef *> m_params;
QList<PositionalDef *> m_positionals;
QList<OptionDef *> m_optionList;
void getPrefix(QString &opt, QString &flag);
};
} }

View File

@ -0,0 +1,96 @@
// SPDX-FileCopyrightText: 2022 Sefa Eyeoglu <contact@scrumplex.net>
//
// SPDX-License-Identifier: GPL-3.0-only
#include "DataMigrationTask.h"
#include "FileSystem.h"
#include <QDirIterator>
#include <QFileInfo>
#include <QMap>
#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)
{
m_copy.matcher(m_pathMatcher.get()).whitelist(true);
}
void DataMigrationTask::executeTask()
{
setStatus(tr("Scanning files..."));
// 1. Scan
// Check how many files we gotta copy
m_copyFuture = QtConcurrent::run(QThreadPool::globalInstance(), [&] {
return m_copy(true); // dry run to collect amount of files
});
connect(&m_copyFutureWatcher, &QFutureWatcher<bool>::finished, this, &DataMigrationTask::dryRunFinished);
connect(&m_copyFutureWatcher, &QFutureWatcher<bool>::canceled, this, &DataMigrationTask::dryRunAborted);
m_copyFutureWatcher.setFuture(m_copyFuture);
}
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;
}
// 2. Copy
// Actually copy all files now.
m_toCopy = m_copy.totalCopied();
connect(&m_copy, &FS::copy::fileCopied, [&, this](const QString& relativeName) {
QString shortenedName = relativeName;
// shorten the filename to hopefully fit into one line
if (shortenedName.length() > 50)
shortenedName = relativeName.left(20) + "" + relativeName.right(29);
setProgress(m_copy.totalCopied(), m_toCopy);
setStatus(tr("Copying %1…").arg(shortenedName));
});
m_copyFuture = QtConcurrent::run(QThreadPool::globalInstance(), [&] {
return m_copy(false); // actually copy now
});
connect(&m_copyFutureWatcher, &QFutureWatcher<bool>::finished, this, &DataMigrationTask::copyFinished);
connect(&m_copyFutureWatcher, &QFutureWatcher<bool>::canceled, this, &DataMigrationTask::copyAborted);
m_copyFutureWatcher.setFuture(m_copyFuture);
}
void DataMigrationTask::dryRunAborted()
{
emitFailed(tr("Aborted"));
}
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;
}
emitSucceeded();
}
void DataMigrationTask::copyAborted()
{
emitFailed(tr("Aborted"));
}

View File

@ -0,0 +1,42 @@
// SPDX-FileCopyrightText: 2022 Sefa Eyeoglu <contact@scrumplex.net>
//
// SPDX-License-Identifier: GPL-3.0-only
#pragma once
#include "FileSystem.h"
#include "pathmatcher/IPathMatcher.h"
#include "tasks/Task.h"
#include <QFuture>
#include <QFutureWatcher>
/*
* Migrate existing data from other MMC-like launchers.
*/
class DataMigrationTask : public Task {
Q_OBJECT
public:
explicit DataMigrationTask(QObject* parent, const QString& sourcePath, const QString& targetPath, const IPathMatcher::Ptr pathmatcher);
~DataMigrationTask() override = default;
protected:
virtual void executeTask() override;
protected slots:
void dryRunFinished();
void dryRunAborted();
void copyFinished();
void copyAborted();
private:
const QString& m_sourcePath;
const QString& m_targetPath;
const IPathMatcher::Ptr m_pathMatcher;
FS::copy m_copy;
int m_toCopy = 0;
QFuture<bool> m_copyFuture;
QFutureWatcher<bool> m_copyFutureWatcher;
};

View File

@ -37,7 +37,6 @@
#include <QDesktopServices> #include <QDesktopServices>
#include <QProcess> #include <QProcess>
#include <QDebug> #include <QDebug>
#include "Application.h"
/** /**
* This shouldn't exist, but until QTBUG-9328 and other unreported bugs are fixed, it needs to be a thing. * This shouldn't exist, but until QTBUG-9328 and other unreported bugs are fixed, it needs to be a thing.
@ -119,7 +118,7 @@ bool openDirectory(const QString &path, bool ensureExists)
return QDesktopServices::openUrl(QUrl::fromLocalFile(dir.absolutePath())); return QDesktopServices::openUrl(QUrl::fromLocalFile(dir.absolutePath()));
}; };
#if defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD) #if defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD)
if(!APPLICATION->isFlatpak()) if(!isFlatpak())
{ {
return IndirectOpen(f); return IndirectOpen(f);
} }
@ -140,7 +139,7 @@ bool openFile(const QString &path)
return QDesktopServices::openUrl(QUrl::fromLocalFile(path)); return QDesktopServices::openUrl(QUrl::fromLocalFile(path));
}; };
#if defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD) #if defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD)
if(!APPLICATION->isFlatpak()) if(!isFlatpak())
{ {
return IndirectOpen(f); return IndirectOpen(f);
} }
@ -158,7 +157,7 @@ bool openFile(const QString &application, const QString &path, const QString &wo
qDebug() << "Opening file" << path << "using" << application; qDebug() << "Opening file" << path << "using" << application;
#if defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD) #if defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD)
// FIXME: the pid here is fake. So if something depends on it, it will likely misbehave // FIXME: the pid here is fake. So if something depends on it, it will likely misbehave
if(!APPLICATION->isFlatpak()) if(!isFlatpak())
{ {
return IndirectOpen([&]() return IndirectOpen([&]()
{ {
@ -178,7 +177,7 @@ bool run(const QString &application, const QStringList &args, const QString &wor
{ {
qDebug() << "Running" << application << "with args" << args.join(' '); qDebug() << "Running" << application << "with args" << args.join(' ');
#if defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD) #if defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD)
if(!APPLICATION->isFlatpak()) if(!isFlatpak())
{ {
// FIXME: the pid here is fake. So if something depends on it, it will likely misbehave // FIXME: the pid here is fake. So if something depends on it, it will likely misbehave
return IndirectOpen([&]() return IndirectOpen([&]()
@ -203,7 +202,7 @@ bool openUrl(const QUrl &url)
return QDesktopServices::openUrl(url); return QDesktopServices::openUrl(url);
}; };
#if defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD) #if defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD)
if(!APPLICATION->isFlatpak()) if(!isFlatpak())
{ {
return IndirectOpen(f); return IndirectOpen(f);
} }
@ -216,4 +215,13 @@ bool openUrl(const QUrl &url)
#endif #endif
} }
bool isFlatpak()
{
#ifdef Q_OS_LINUX
return QFile::exists("/.flatpak-info");
#else
return false;
#endif
}
} }

View File

@ -33,4 +33,6 @@ namespace DesktopServices
* Open the URL, most likely in a browser. Maybe. * Open the URL, most likely in a browser. Maybe.
*/ */
bool openUrl(const QUrl &url); bool openUrl(const QUrl &url);
bool isFlatpak();
} }

View File

@ -0,0 +1,47 @@
// SPDX-License-Identifier: GPL-3.0-only
/*
* Prism Launcher - Minecraft Launcher
* Copyright (C) 2023 TheKodeToad <TheKodeToad@proton.me>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* 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 "FastFileIconProvider.h"
#include <QApplication>
#include <QStyle>
QIcon FastFileIconProvider::icon(const QFileInfo& info) const
{
#if QT_VERSION >= QT_VERSION_CHECK(6, 4, 0)
bool link = info.isSymbolicLink() || info.isAlias() || info.isShortcut();
#else
// in versions prior to 6.4 we don't have access to isAlias
bool link = info.isSymLink();
#endif
QStyle::StandardPixmap icon;
if (info.isDir()) {
if (link)
icon = QStyle::SP_DirLinkIcon;
else
icon = QStyle::SP_DirIcon;
} else {
if (link)
icon = QStyle::SP_FileLinkIcon;
else
icon = QStyle::SP_FileIcon;
}
return QApplication::style()->standardIcon(icon);
}

View File

@ -0,0 +1,26 @@
// SPDX-License-Identifier: GPL-3.0-only
/*
* Prism Launcher - Minecraft Launcher
* Copyright (C) 2023 TheKodeToad <TheKodeToad@proton.me>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* 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 <QFileIconProvider>
class FastFileIconProvider : public QFileIconProvider {
public:
QIcon icon(const QFileInfo& info) const override;
};

View File

@ -0,0 +1,256 @@
// SPDX-License-Identifier: GPL-3.0-only
/*
* Prism Launcher - Minecraft Launcher
* Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net>
* Copyright (C) 2023 TheKodeToad <TheKodeToad@proton.me>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* 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 "FileIgnoreProxy.h"
#include <QDebug>
#include <QFileSystemModel>
#include <QSortFilterProxyModel>
#include <QStack>
#include "FileSystem.h"
#include "SeparatorPrefixTree.h"
#include "StringUtils.h"
FileIgnoreProxy::FileIgnoreProxy(QString root, QObject* parent) : QSortFilterProxyModel(parent), root(root) {}
// NOTE: Sadly, we have to do sorting ourselves.
bool FileIgnoreProxy::lessThan(const QModelIndex& left, const QModelIndex& right) const
{
QFileSystemModel* fsm = qobject_cast<QFileSystemModel*>(sourceModel());
if (!fsm) {
return QSortFilterProxyModel::lessThan(left, right);
}
bool asc = sortOrder() == Qt::AscendingOrder ? true : false;
QFileInfo leftFileInfo = fsm->fileInfo(left);
QFileInfo rightFileInfo = fsm->fileInfo(right);
if (!leftFileInfo.isDir() && rightFileInfo.isDir()) {
return !asc;
}
if (leftFileInfo.isDir() && !rightFileInfo.isDir()) {
return asc;
}
// sort and proxy model breaks the original model...
if (sortColumn() == 0) {
return StringUtils::naturalCompare(leftFileInfo.fileName(), rightFileInfo.fileName(), Qt::CaseInsensitive) < 0;
}
if (sortColumn() == 1) {
auto leftSize = leftFileInfo.size();
auto rightSize = rightFileInfo.size();
if ((leftSize == rightSize) || (leftFileInfo.isDir() && rightFileInfo.isDir())) {
return StringUtils::naturalCompare(leftFileInfo.fileName(), rightFileInfo.fileName(), Qt::CaseInsensitive) < 0 ? asc : !asc;
}
return leftSize < rightSize;
}
return QSortFilterProxyModel::lessThan(left, right);
}
Qt::ItemFlags FileIgnoreProxy::flags(const QModelIndex& index) const
{
if (!index.isValid())
return Qt::NoItemFlags;
auto sourceIndex = mapToSource(index);
Qt::ItemFlags flags = sourceIndex.flags();
if (index.column() == 0) {
flags |= Qt::ItemIsUserCheckable;
if (sourceIndex.model()->hasChildren(sourceIndex)) {
flags |= Qt::ItemIsAutoTristate;
}
}
return flags;
}
QVariant FileIgnoreProxy::data(const QModelIndex& index, int role) const
{
QModelIndex sourceIndex = mapToSource(index);
if (index.column() == 0 && role == Qt::CheckStateRole) {
QFileSystemModel* fsm = qobject_cast<QFileSystemModel*>(sourceModel());
auto blockedPath = relPath(fsm->filePath(sourceIndex));
auto cover = blocked.cover(blockedPath);
if (!cover.isNull()) {
return QVariant(Qt::Unchecked);
} else if (blocked.exists(blockedPath)) {
return QVariant(Qt::PartiallyChecked);
} else {
return QVariant(Qt::Checked);
}
}
return sourceIndex.data(role);
}
bool FileIgnoreProxy::setData(const QModelIndex& index, const QVariant& value, int role)
{
if (index.column() == 0 && role == Qt::CheckStateRole) {
Qt::CheckState state = static_cast<Qt::CheckState>(value.toInt());
return setFilterState(index, state);
}
QModelIndex sourceIndex = mapToSource(index);
return QSortFilterProxyModel::sourceModel()->setData(sourceIndex, value, role);
}
QString FileIgnoreProxy::relPath(const QString& path) const
{
return QDir(root).relativeFilePath(path);
}
bool FileIgnoreProxy::setFilterState(QModelIndex index, Qt::CheckState state)
{
QFileSystemModel* fsm = qobject_cast<QFileSystemModel*>(sourceModel());
if (!fsm) {
return false;
}
QModelIndex sourceIndex = mapToSource(index);
auto blockedPath = relPath(fsm->filePath(sourceIndex));
bool changed = false;
if (state == Qt::Unchecked) {
// blocking a path
auto& node = 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);
qDebug() << "Blocked by cover" << cover;
// uncover
blocked.remove(cover);
// block all contents, except for any cover
QModelIndex rootIndex = fsm->index(FS::PathCombine(root, cover));
QModelIndex doing = rootIndex;
int row = 0;
QStack<QModelIndex> todo;
while (1) {
auto node = fsm->index(row, 0, doing);
if (!node.isValid()) {
if (!todo.size()) {
break;
} else {
doing = todo.pop();
row = 0;
continue;
}
}
auto relpath = relPath(fsm->filePath(node));
if (blockedPath.startsWith(relpath)) // cover found?
{
// continue processing cover later
todo.push(node);
} else {
// or just block this one.
blocked.insert(relpath);
}
row++;
}
}
changed = true;
}
if (changed) {
// update the thing
emit dataChanged(index, index, { Qt::CheckStateRole });
// update everything above index
QModelIndex up = index.parent();
while (1) {
if (!up.isValid())
break;
emit dataChanged(up, up, { Qt::CheckStateRole });
up = up.parent();
}
// and everything below the index
QModelIndex doing = index;
int row = 0;
QStack<QModelIndex> todo;
while (1) {
auto node = this->index(row, 0, doing);
if (!node.isValid()) {
if (!todo.size()) {
break;
} else {
doing = todo.pop();
row = 0;
continue;
}
}
emit dataChanged(node, node, { Qt::CheckStateRole });
todo.push(node);
row++;
}
// siblings and unrelated nodes are ignored
}
return true;
}
bool FileIgnoreProxy::shouldExpand(QModelIndex index)
{
QModelIndex sourceIndex = mapToSource(index);
QFileSystemModel* fsm = qobject_cast<QFileSystemModel*>(sourceModel());
if (!fsm) {
return false;
}
auto blockedPath = relPath(fsm->filePath(sourceIndex));
auto found = blocked.find(blockedPath);
if (found) {
return !found->leaf();
}
return false;
}
void FileIgnoreProxy::setBlockedPaths(QStringList paths)
{
beginResetModel();
blocked.clear();
blocked.insert(paths);
endResetModel();
}
bool FileIgnoreProxy::filterAcceptsColumn(int source_column, const QModelIndex& source_parent) const
{
Q_UNUSED(source_parent)
// adjust the columns you want to filter out here
// return false for those that will be hidden
if (source_column == 2 || source_column == 3)
return false;
return true;
}

View File

@ -0,0 +1,72 @@
// SPDX-License-Identifier: GPL-3.0-only
/*
* Prism Launcher - Minecraft Launcher
* Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net>
* Copyright (C) 2023 TheKodeToad <TheKodeToad@proton.me>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* 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 <QSortFilterProxyModel>
#include "SeparatorPrefixTree.h"
class FileIgnoreProxy : public QSortFilterProxyModel {
Q_OBJECT
public:
FileIgnoreProxy(QString root, QObject* parent);
// NOTE: Sadly, we have to do sorting ourselves.
bool lessThan(const QModelIndex& left, const QModelIndex& right) const;
virtual Qt::ItemFlags flags(const QModelIndex& index) const;
virtual QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const;
virtual bool setData(const QModelIndex& index, const QVariant& value, int role = Qt::EditRole);
QString relPath(const QString& path) const;
bool setFilterState(QModelIndex index, Qt::CheckState state);
bool shouldExpand(QModelIndex index);
void setBlockedPaths(QStringList paths);
inline const SeparatorPrefixTree<'/'>& blockedPaths() const { return blocked; }
inline SeparatorPrefixTree<'/'>& blockedPaths() { return blocked; }
protected:
bool filterAcceptsColumn(int source_column, const QModelIndex& source_parent) const;
private:
const QString root;
SeparatorPrefixTree<'/'> blocked;
};

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,9 @@
// SPDX-License-Identifier: GPL-3.0-only // SPDX-License-Identifier: GPL-3.0-only
/* /*
* PolyMC - Minecraft Launcher * Prism Launcher - Minecraft Launcher
* Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net> * Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net>
* Copyright (C) 2022 TheKodeToad <TheKodeToad@proton.me>
* Copyright (C) 2022 Rachel Powers <508861+Ryex@users.noreply.github.com>
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -38,32 +40,35 @@
#include "Exception.h" #include "Exception.h"
#include "pathmatcher/IPathMatcher.h" #include "pathmatcher/IPathMatcher.h"
#include <system_error>
#include <QDir> #include <QDir>
#include <QFlags> #include <QFlags>
#include <QLocalServer>
#include <QObject>
#include <QThread>
namespace FS namespace FS {
{
class FileSystemException : public ::Exception class FileSystemException : public ::Exception {
{ public:
public: FileSystemException(const QString& message) : Exception(message) {}
FileSystemException(const QString &message) : Exception(message) {}
}; };
/** /**
* write data to a file safely * write data to a file safely
*/ */
void write(const QString &filename, const QByteArray &data); void write(const QString& filename, const QByteArray& data);
/** /**
* read data from a file safely\ * read data from a file safely\
*/ */
QByteArray read(const QString &filename); QByteArray read(const QString& filename);
/** /**
* Update the last changed timestamp of an existing file * Update the last changed timestamp of an existing file
*/ */
bool updateTimestamp(const QString & filename); bool updateTimestamp(const QString& filename);
/** /**
* Creates all the folders in a path for the specified path * Creates all the folders in a path for the specified path
@ -77,49 +82,214 @@ bool ensureFilePathExists(QString filenamepath);
*/ */
bool ensureFolderPathExists(QString filenamepath); bool ensureFolderPathExists(QString filenamepath);
class copy /**
{ * @brief Copies a directory and it's contents from src to dest
public: */
copy(const QString & src, const QString & dst) class copy : public QObject {
Q_OBJECT
public:
copy(const QString& src, const QString& dst, QObject* parent = nullptr) : QObject(parent)
{ {
m_src.setPath(src); m_src.setPath(src);
m_dst.setPath(dst); m_dst.setPath(dst);
} }
copy & followSymlinks(const bool follow) copy& followSymlinks(const bool follow)
{ {
m_followSymlinks = follow; m_followSymlinks = follow;
return *this; return *this;
} }
copy & blacklist(const IPathMatcher * filter) copy& matcher(const IPathMatcher* filter)
{ {
m_blacklist = filter; m_matcher = filter;
return *this; return *this;
} }
bool operator()() copy& whitelist(bool whitelist)
{ {
return operator()(QString()); m_whitelist = whitelist;
return *this;
} }
private: bool operator()(bool dryRun = false) { return operator()(QString(), dryRun); }
bool operator()(const QString &offset);
private: int totalCopied() { return m_copied; }
signals:
void fileCopied(const QString& relativeName);
// TODO: maybe add a "shouldCopy" signal in the future?
private:
bool operator()(const QString& offset, bool dryRun = false);
private:
bool m_followSymlinks = true; bool m_followSymlinks = true;
const IPathMatcher * m_blacklist = nullptr; const IPathMatcher* m_matcher = nullptr;
bool m_whitelist = false;
QDir m_src; QDir m_src;
QDir m_dst; QDir m_dst;
int m_copied;
}; };
struct LinkPair {
QString src;
QString dst;
};
struct LinkResult {
QString src;
QString dst;
QString err_msg;
int err_value;
};
class ExternalLinkFileProcess : public QThread {
Q_OBJECT
public:
ExternalLinkFileProcess(QString server, bool useHardLinks, QObject* parent = nullptr)
: QThread(parent), m_useHardLinks(useHardLinks), m_server(server)
{}
void run() override
{
runLinkFile();
emit processExited();
}
signals:
void processExited();
private:
void runLinkFile();
bool m_useHardLinks = false;
QString m_server;
};
/**
* @brief links (a file / a directory and it's contents) from src to dest
*/
class create_link : public QObject {
Q_OBJECT
public:
create_link(const QList<LinkPair> path_pairs, QObject* parent = nullptr) : QObject(parent) { m_path_pairs.append(path_pairs); }
create_link(const QString& src, const QString& dst, QObject* parent = nullptr) : QObject(parent)
{
LinkPair pair = { src, dst };
m_path_pairs.append(pair);
}
create_link& useHardLinks(const bool useHard)
{
m_useHardLinks = useHard;
return *this;
}
create_link& matcher(const IPathMatcher* filter)
{
m_matcher = filter;
return *this;
}
create_link& whitelist(bool whitelist)
{
m_whitelist = whitelist;
return *this;
}
create_link& linkRecursively(bool recursive)
{
m_recursive = recursive;
return *this;
}
create_link& setMaxDepth(int depth)
{
m_max_depth = depth;
return *this;
}
create_link& debug(bool d)
{
m_debug = d;
return *this;
}
std::error_code getOSError() { return m_os_err; }
bool operator()(bool dryRun = false) { return operator()(QString(), dryRun); }
int totalLinked() { return m_linked; }
void runPrivileged() { runPrivileged(QString()); }
void runPrivileged(const QString& offset);
QList<LinkResult> getResults() { return m_path_results; }
signals:
void fileLinked(const QString& srcName, const QString& dstName);
void linkFailed(const QString& srcName, const QString& dstName, const QString& err_msg, int err_value);
void finished();
void finishedPrivileged(bool gotResults);
private:
bool operator()(const QString& offset, bool dryRun = false);
void make_link_list(const QString& offset);
bool make_links();
private:
bool m_useHardLinks = false;
const IPathMatcher* m_matcher = nullptr;
bool m_whitelist = false;
bool m_recursive = true;
/// @brief >= -1 = infinite, 0 = link files at src/* to dest/*, 1 = link files at src/*/* to dest/*/*, etc.
int m_max_depth = -1;
QList<LinkPair> m_path_pairs;
QList<LinkResult> m_path_results;
QList<LinkPair> m_links_to_make;
int m_linked;
bool m_debug = false;
std::error_code m_os_err;
QLocalServer m_linkServer;
};
/**
* @brief moves a file by renaming it
* @param source source file path
* @param dest destination filepath
*
*/
bool move(const QString& source, const QString& dest);
/** /**
* Delete a folder recursively * Delete a folder recursively
*/ */
bool deletePath(QString path); bool deletePath(QString path);
QString PathCombine(const QString &path1, const QString &path2); /**
QString PathCombine(const QString &path1, const QString &path2, const QString &path3); * Trash a folder / file
QString PathCombine(const QString &path1, const QString &path2, const QString &path3, const QString &path4); */
bool trash(QString path, QString* pathInTrash = nullptr);
QString AbsolutePath(QString path); QString PathCombine(const QString& path1, const QString& path2);
QString PathCombine(const QString& path1, const QString& path2, const QString& path3);
QString PathCombine(const QString& path1, const QString& path2, const QString& path3, const QString& path4);
QString AbsolutePath(const QString& path);
/**
* @brief depth of path. "foo.txt" -> 0 , "bar/foo.txt" -> 1, /baz/bar/foo.txt -> 2, etc.
*
* @param path path to measure
* @return int number of components before base path
*/
int pathDepth(const QString& path);
/**
* @brief cut off segments of path until it is a max of length depth
*
* @param path path to truncate
* @param depth max depth of new path
* @return QString truncated path
*/
QString pathTruncate(const QString& path, int depth);
/** /**
* Resolve an executable * Resolve an executable
@ -156,4 +326,199 @@ QString getDesktopDir();
// Overrides one folder with the contents of another, preserving items exclusive to the first folder // Overrides one folder with the contents of another, preserving items exclusive to the first folder
// Equivalent to doing QDir::rename, but allowing for overrides // Equivalent to doing QDir::rename, but allowing for overrides
bool overrideFolder(QString overwritten_path, QString override_path); bool overrideFolder(QString overwritten_path, QString override_path);
}
/**
* Creates a shortcut to the specified target file at the specified destination path.
*/
bool createShortcut(QString destination, QString target, QStringList args, QString name, QString icon);
enum class FilesystemType {
FAT,
NTFS,
REFS,
EXT,
EXT_2_OLD,
EXT_2_3_4,
XFS,
BTRFS,
NFS,
ZFS,
APFS,
HFS,
HFSPLUS,
HFSX,
FUSEBLK,
F2FS,
UNKNOWN
};
/**
* @brief Ordered Mapping of enum types to reported filesystem names
* this mapping is non exsaustive, it just attempts to capture the filesystems which could be reasonalbly be in use .
* all string values are in uppercase, use `QString.toUpper()` or equivalent during lookup.
*
* QMap is ordered
*
*/
static const QMap<FilesystemType, QStringList> s_filesystem_type_names = {
{FilesystemType::FAT, { "FAT" }},
{FilesystemType::NTFS, { "NTFS" }},
{FilesystemType::REFS, { "REFS" }},
{FilesystemType::EXT_2_OLD, { "EXT_2_OLD", "EXT2_OLD" }},
{FilesystemType::EXT_2_3_4, { "EXT2/3/4", "EXT_2_3_4", "EXT2", "EXT3", "EXT4" }},
{FilesystemType::EXT, { "EXT" }},
{FilesystemType::XFS, { "XFS" }},
{FilesystemType::BTRFS, { "BTRFS" }},
{FilesystemType::NFS, { "NFS" }},
{FilesystemType::ZFS, { "ZFS" }},
{FilesystemType::APFS, { "APFS" }},
{FilesystemType::HFS, { "HFS" }},
{FilesystemType::HFSPLUS, { "HFSPLUS" }},
{FilesystemType::HFSX, { "HFSX" }},
{FilesystemType::FUSEBLK, { "FUSEBLK" }},
{FilesystemType::F2FS, { "F2FS" }},
{FilesystemType::UNKNOWN, { "UNKNOWN" }}
};
/**
* @brief Get the string name of Filesystem enum object
*
* @param type
* @return QString
*/
QString getFilesystemTypeName(FilesystemType type);
/**
* @brief Get the Filesystem enum object from a name
* Does a lookup of the type name and returns an exact match
*
* @param name
* @return FilesystemType
*/
FilesystemType getFilesystemType(const QString& name);
/**
* @brief Get the Filesystem enum object from a name
* Does a fuzzy lookup of the type name and returns an apropreate match
*
* @param name
* @return FilesystemType
*/
FilesystemType getFilesystemTypeFuzzy(const QString& name);
struct FilesystemInfo {
FilesystemType fsType = FilesystemType::UNKNOWN;
QString fsTypeName;
int blockSize;
qint64 bytesAvailable;
qint64 bytesFree;
qint64 bytesTotal;
QString name;
QString rootPath;
};
/**
* @brief path to the near ancestor that exists
*
*/
QString nearestExistentAncestor(const QString& path);
/**
* @brief colect information about the filesystem under a file
*
*/
FilesystemInfo statFS(const QString& path);
static const QList<FilesystemType> s_clone_filesystems = { FilesystemType::BTRFS, FilesystemType::APFS, FilesystemType::ZFS,
FilesystemType::XFS, FilesystemType::REFS };
/**
* @brief if the Filesystem is reflink/clone capable
*
*/
bool canCloneOnFS(const QString& path);
bool canCloneOnFS(const FilesystemInfo& info);
bool canCloneOnFS(FilesystemType type);
/**
* @brief if the Filesystems are reflink/clone capable and both are on the same device
*
*/
bool canClone(const QString& src, const QString& dst);
/**
* @brief Copies a directory and it's contents from src to dest
*/
class clone : public QObject {
Q_OBJECT
public:
clone(const QString& src, const QString& dst, QObject* parent = nullptr) : QObject(parent)
{
m_src.setPath(src);
m_dst.setPath(dst);
}
clone& matcher(const IPathMatcher* filter)
{
m_matcher = filter;
return *this;
}
clone& whitelist(bool whitelist)
{
m_whitelist = whitelist;
return *this;
}
bool operator()(bool dryRun = false) { return operator()(QString(), dryRun); }
int totalCloned() { return m_cloned; }
signals:
void fileCloned(const QString& src, const QString& dst);
void cloneFailed(const QString& src, const QString& dst);
private:
bool operator()(const QString& offset, bool dryRun = false);
private:
const IPathMatcher* m_matcher = nullptr;
bool m_whitelist = false;
QDir m_src;
QDir m_dst;
int m_cloned;
};
/**
* @brief clone/reflink file from src to dst
*
*/
bool clone_file(const QString& src, const QString& dst, std::error_code& ec);
#if defined(Q_OS_WIN)
bool win_ioctl_clone(const std::wstring& src_path, const std::wstring& dst_path, std::error_code& ec);
#elif defined(Q_OS_LINUX)
bool linux_ficlone(const std::string& src_path, const std::string& dst_path, std::error_code& ec);
#elif defined(Q_OS_MACOS) || defined(Q_OS_FREEBSD) || defined(Q_OS_OPENBSD)
bool macos_bsd_clonefile(const std::string& src_path, const std::string& dst_path, std::error_code& ec);
#endif
static const QList<FilesystemType> s_non_link_filesystems = {
FilesystemType::FAT,
};
/**
* @brief if the Filesystem is symlink capable
*
*/
bool canLinkOnFS(const QString& path);
bool canLinkOnFS(const FilesystemInfo& info);
bool canLinkOnFS(FilesystemType type);
/**
* @brief if the Filesystem is symlink capable on both ends
*
*/
bool canLink(const QString& src, const QString& dst);
uintmax_t hardLinkCount(const QString& path);
} // namespace FS

View File

@ -1,122 +0,0 @@
#include <QTest>
#include <QTemporaryDir>
#include <QStandardPaths>
#include "FileSystem.h"
class FileSystemTest : public QObject
{
Q_OBJECT
const QString bothSlash = "/foo/";
const QString trailingSlash = "foo/";
const QString leadingSlash = "/foo";
private
slots:
void test_pathCombine()
{
QCOMPARE(QString("/foo/foo"), FS::PathCombine(bothSlash, bothSlash));
QCOMPARE(QString("foo/foo"), FS::PathCombine(trailingSlash, trailingSlash));
QCOMPARE(QString("/foo/foo"), FS::PathCombine(leadingSlash, leadingSlash));
QCOMPARE(QString("/foo/foo/foo"), FS::PathCombine(bothSlash, bothSlash, bothSlash));
QCOMPARE(QString("foo/foo/foo"), FS::PathCombine(trailingSlash, trailingSlash, trailingSlash));
QCOMPARE(QString("/foo/foo/foo"), FS::PathCombine(leadingSlash, leadingSlash, leadingSlash));
}
void test_PathCombine1_data()
{
QTest::addColumn<QString>("result");
QTest::addColumn<QString>("path1");
QTest::addColumn<QString>("path2");
QTest::newRow("qt 1") << "/abc/def/ghi/jkl" << "/abc/def" << "ghi/jkl";
QTest::newRow("qt 2") << "/abc/def/ghi/jkl" << "/abc/def/" << "ghi/jkl";
#if defined(Q_OS_WIN)
QTest::newRow("win native, from C:") << "C:/abc" << "C:" << "abc";
QTest::newRow("win native 1") << "C:/abc/def/ghi/jkl" << "C:\\abc\\def" << "ghi\\jkl";
QTest::newRow("win native 2") << "C:/abc/def/ghi/jkl" << "C:\\abc\\def\\" << "ghi\\jkl";
#endif
}
void test_PathCombine1()
{
QFETCH(QString, result);
QFETCH(QString, path1);
QFETCH(QString, path2);
QCOMPARE(FS::PathCombine(path1, path2), result);
}
void test_PathCombine2_data()
{
QTest::addColumn<QString>("result");
QTest::addColumn<QString>("path1");
QTest::addColumn<QString>("path2");
QTest::addColumn<QString>("path3");
QTest::newRow("qt 1") << "/abc/def/ghi/jkl" << "/abc" << "def" << "ghi/jkl";
QTest::newRow("qt 2") << "/abc/def/ghi/jkl" << "/abc/" << "def" << "ghi/jkl";
QTest::newRow("qt 3") << "/abc/def/ghi/jkl" << "/abc" << "def/" << "ghi/jkl";
QTest::newRow("qt 4") << "/abc/def/ghi/jkl" << "/abc/" << "def/" << "ghi/jkl";
#if defined(Q_OS_WIN)
QTest::newRow("win 1") << "C:/abc/def/ghi/jkl" << "C:\\abc" << "def" << "ghi\\jkl";
QTest::newRow("win 2") << "C:/abc/def/ghi/jkl" << "C:\\abc\\" << "def" << "ghi\\jkl";
QTest::newRow("win 3") << "C:/abc/def/ghi/jkl" << "C:\\abc" << "def\\" << "ghi\\jkl";
QTest::newRow("win 4") << "C:/abc/def/ghi/jkl" << "C:\\abc\\" << "def" << "ghi\\jkl";
#endif
}
void test_PathCombine2()
{
QFETCH(QString, result);
QFETCH(QString, path1);
QFETCH(QString, path2);
QFETCH(QString, path3);
QCOMPARE(FS::PathCombine(path1, path2, path3), result);
}
void test_copy()
{
QString folder = QFINDTESTDATA("testdata/test_folder");
auto f = [&folder]()
{
QTemporaryDir tempDir;
tempDir.setAutoRemove(true);
qDebug() << "From:" << folder << "To:" << tempDir.path();
QDir target_dir(FS::PathCombine(tempDir.path(), "test_folder"));
qDebug() << tempDir.path();
qDebug() << target_dir.path();
FS::copy c(folder, target_dir.path());
c();
for(auto entry: target_dir.entryList())
{
qDebug() << entry;
}
QVERIFY(target_dir.entryList().contains("pack.mcmeta"));
QVERIFY(target_dir.entryList().contains("assets"));
};
// first try variant without trailing /
QVERIFY(!folder.endsWith('/'));
f();
// then variant with trailing /
folder.append('/');
QVERIFY(folder.endsWith('/'));
f();
}
void test_getDesktop()
{
QCOMPARE(FS::getDesktopDir(), QStandardPaths::writableLocation(QStandardPaths::DesktopLocation));
}
};
QTEST_GUILESS_MAIN(FileSystemTest)
#include "FileSystem_test.moc"

View File

@ -72,7 +72,7 @@ bool GZip::unzip(const QByteArray &compressedBytes, QByteArray &uncompressedByte
uncompLength *= 2; uncompLength *= 2;
} }
strm.next_out = (Bytef *)(uncompressedBytes.data() + strm.total_out); strm.next_out = reinterpret_cast<Bytef *>((uncompressedBytes.data() + strm.total_out));
strm.avail_out = uncompLength - strm.total_out; strm.avail_out = uncompLength - strm.total_out;
// Inflate another chunk. // Inflate another chunk.
@ -129,7 +129,7 @@ bool GZip::zip(const QByteArray &uncompressedBytes, QByteArray &compressedBytes)
{ {
compressedBytes.resize(compressedBytes.size() * 2); compressedBytes.resize(compressedBytes.size() * 2);
} }
zs.next_out = (Bytef *) (compressedBytes.data() + offset); zs.next_out = reinterpret_cast<Bytef*>((compressedBytes.data() + offset));
temp = zs.avail_out = compressedBytes.size() - offset; temp = zs.avail_out = compressedBytes.size() - offset;
ret = deflate(&zs, Z_FINISH); ret = deflate(&zs, Z_FINISH);
offset += temp - zs.avail_out; offset += temp - zs.avail_out;

View File

@ -1,76 +0,0 @@
/* 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 <hoedown/html.h>
#include <hoedown/document.h>
#include <QString>
#include <QByteArray>
/**
* hoedown wrapper, because dealing with resource lifetime in C is stupid
*/
class HoeDown
{
public:
class buffer
{
public:
buffer(size_t unit = 4096)
{
buf = hoedown_buffer_new(unit);
}
~buffer()
{
hoedown_buffer_free(buf);
}
const char * cstr()
{
return hoedown_buffer_cstr(buf);
}
void put(QByteArray input)
{
hoedown_buffer_put(buf, (uint8_t *) input.data(), input.size());
}
const uint8_t * data() const
{
return buf->data;
}
size_t size() const
{
return buf->size;
}
hoedown_buffer * buf;
} ib, ob;
HoeDown()
{
renderer = hoedown_html_renderer_new((hoedown_html_flags) 0,0);
document = hoedown_document_new(renderer, (hoedown_extensions) 0, 8);
}
~HoeDown()
{
hoedown_document_free(document);
hoedown_html_renderer_free(renderer);
}
QString process(QByteArray input)
{
ib.put(input);
hoedown_document_render(document, ob.buf, ib.data(), ib.size());
return ob.cstr();
}
private:
hoedown_document * document;
hoedown_renderer * renderer;
};

View File

@ -0,0 +1,194 @@
//
// Created by marcelohdez on 10/22/22.
//
#include "InstanceCopyPrefs.h"
bool InstanceCopyPrefs::allTrue() const
{
return copySaves &&
keepPlaytime &&
copyGameOptions &&
copyResourcePacks &&
copyShaderPacks &&
copyServers &&
copyMods &&
copyScreenshots;
}
// Returns a single RegEx string of the selected folders/files to filter out (ex: ".minecraft/saves|.minecraft/server.dat")
QString InstanceCopyPrefs::getSelectedFiltersAsRegex() const
{
return getSelectedFiltersAsRegex({});
}
QString InstanceCopyPrefs::getSelectedFiltersAsRegex(const QStringList& additionalFilters) const
{
QStringList filters;
if(!copySaves)
filters << "saves";
if(!copyGameOptions)
filters << "options.txt";
if(!copyResourcePacks)
filters << "resourcepacks" << "texturepacks";
if(!copyShaderPacks)
filters << "shaderpacks";
if(!copyServers)
filters << "servers.dat" << "servers.dat_old" << "server-resource-packs";
if(!copyMods)
filters << "coremods" << "mods" << "config";
if(!copyScreenshots)
filters << "screenshots";
for (auto filter : additionalFilters) {
filters << filter;
}
// If we have any filters to add, join them as a single regex string to return:
if (!filters.isEmpty()) {
const QString MC_ROOT = "[.]?minecraft/";
// Ensure first filter starts with root, then join other filters with OR regex before root (ex: ".minecraft/saves|.minecraft/mods"):
return MC_ROOT + filters.join("|" + MC_ROOT);
}
return {};
}
// ======= Getters =======
bool InstanceCopyPrefs::isCopySavesEnabled() const
{
return copySaves;
}
bool InstanceCopyPrefs::isKeepPlaytimeEnabled() const
{
return keepPlaytime;
}
bool InstanceCopyPrefs::isCopyGameOptionsEnabled() const
{
return copyGameOptions;
}
bool InstanceCopyPrefs::isCopyResourcePacksEnabled() const
{
return copyResourcePacks;
}
bool InstanceCopyPrefs::isCopyShaderPacksEnabled() const
{
return copyShaderPacks;
}
bool InstanceCopyPrefs::isCopyServersEnabled() const
{
return copyServers;
}
bool InstanceCopyPrefs::isCopyModsEnabled() const
{
return copyMods;
}
bool InstanceCopyPrefs::isCopyScreenshotsEnabled() const
{
return copyScreenshots;
}
bool InstanceCopyPrefs::isUseSymLinksEnabled() const
{
return useSymLinks;
}
bool InstanceCopyPrefs::isUseHardLinksEnabled() const
{
return useHardLinks;
}
bool InstanceCopyPrefs::isLinkRecursivelyEnabled() const
{
return linkRecursively;
}
bool InstanceCopyPrefs::isDontLinkSavesEnabled() const
{
return dontLinkSaves;
}
bool InstanceCopyPrefs::isUseCloneEnabled() const
{
return useClone;
}
// ======= Setters =======
void InstanceCopyPrefs::enableCopySaves(bool b)
{
copySaves = b;
}
void InstanceCopyPrefs::enableKeepPlaytime(bool b)
{
keepPlaytime = b;
}
void InstanceCopyPrefs::enableCopyGameOptions(bool b)
{
copyGameOptions = b;
}
void InstanceCopyPrefs::enableCopyResourcePacks(bool b)
{
copyResourcePacks = b;
}
void InstanceCopyPrefs::enableCopyShaderPacks(bool b)
{
copyShaderPacks = b;
}
void InstanceCopyPrefs::enableCopyServers(bool b)
{
copyServers = b;
}
void InstanceCopyPrefs::enableCopyMods(bool b)
{
copyMods = b;
}
void InstanceCopyPrefs::enableCopyScreenshots(bool b)
{
copyScreenshots = b;
}
void InstanceCopyPrefs::enableUseSymLinks(bool b)
{
useSymLinks = b;
}
void InstanceCopyPrefs::enableLinkRecursively(bool b)
{
linkRecursively = b;
}
void InstanceCopyPrefs::enableUseHardLinks(bool b)
{
useHardLinks = b;
}
void InstanceCopyPrefs::enableDontLinkSaves(bool b)
{
dontLinkSaves = b;
}
void InstanceCopyPrefs::enableUseClone(bool b)
{
useClone = b;
}

View File

@ -0,0 +1,57 @@
//
// Created by marcelohdez on 10/22/22.
//
#pragma once
#include <QStringList>
struct InstanceCopyPrefs {
public:
[[nodiscard]] bool allTrue() const;
[[nodiscard]] QString getSelectedFiltersAsRegex() const;
[[nodiscard]] QString getSelectedFiltersAsRegex(const QStringList& additionalFilters) const;
// Getters
[[nodiscard]] bool isCopySavesEnabled() const;
[[nodiscard]] bool isKeepPlaytimeEnabled() const;
[[nodiscard]] bool isCopyGameOptionsEnabled() const;
[[nodiscard]] bool isCopyResourcePacksEnabled() const;
[[nodiscard]] bool isCopyShaderPacksEnabled() const;
[[nodiscard]] bool isCopyServersEnabled() const;
[[nodiscard]] bool isCopyModsEnabled() const;
[[nodiscard]] bool isCopyScreenshotsEnabled() const;
[[nodiscard]] bool isUseSymLinksEnabled() const;
[[nodiscard]] bool isLinkRecursivelyEnabled() const;
[[nodiscard]] bool isUseHardLinksEnabled() const;
[[nodiscard]] bool isDontLinkSavesEnabled() const;
[[nodiscard]] bool isUseCloneEnabled() const;
// Setters
void enableCopySaves(bool b);
void enableKeepPlaytime(bool b);
void enableCopyGameOptions(bool b);
void enableCopyResourcePacks(bool b);
void enableCopyShaderPacks(bool b);
void enableCopyServers(bool b);
void enableCopyMods(bool b);
void enableCopyScreenshots(bool b);
void enableUseSymLinks(bool b);
void enableLinkRecursively(bool b);
void enableUseHardLinks(bool b);
void enableDontLinkSaves(bool b);
void enableUseClone(bool b);
protected: // data
bool copySaves = true;
bool keepPlaytime = true;
bool copyGameOptions = true;
bool copyResourcePacks = true;
bool copyShaderPacks = true;
bool copyServers = true;
bool copyMods = true;
bool copyScreenshots = true;
bool useSymLinks = false;
bool linkRecursively = false;
bool useHardLinks = false;
bool dontLinkSaves = false;
bool useClone = false;
};

View File

@ -1,19 +1,34 @@
#include "InstanceCopyTask.h" #include "InstanceCopyTask.h"
#include "settings/INISettingsObject.h" #include <QDebug>
#include <QtConcurrentRun>
#include "FileSystem.h" #include "FileSystem.h"
#include "NullInstance.h" #include "NullInstance.h"
#include "pathmatcher/RegexpMatcher.h" #include "pathmatcher/RegexpMatcher.h"
#include <QtConcurrentRun> #include "settings/INISettingsObject.h"
InstanceCopyTask::InstanceCopyTask(InstancePtr origInstance, bool copySaves, bool keepPlaytime) InstanceCopyTask::InstanceCopyTask(InstancePtr origInstance, const InstanceCopyPrefs& prefs)
{ {
m_origInstance = origInstance; m_origInstance = origInstance;
m_keepPlaytime = keepPlaytime; m_keepPlaytime = prefs.isKeepPlaytimeEnabled();
m_useLinks = prefs.isUseSymLinksEnabled();
m_linkRecursively = prefs.isLinkRecursivelyEnabled();
m_useHardLinks = prefs.isLinkRecursivelyEnabled() && prefs.isUseHardLinksEnabled();
m_copySaves = prefs.isLinkRecursivelyEnabled() && prefs.isDontLinkSavesEnabled() && prefs.isCopySavesEnabled();
m_useClone = prefs.isUseCloneEnabled();
if(!copySaves) QString filters = prefs.getSelectedFiltersAsRegex();
{ if (m_useLinks || m_useHardLinks) {
if (!filters.isEmpty())
filters += "|";
filters += "instance.cfg";
}
qDebug() << "CopyFilters:" << filters;
if (!filters.isEmpty()) {
// Set regex filter:
// FIXME: get this from the original instance type... // FIXME: get this from the original instance type...
auto matcherReal = new RegexpMatcher("[.]?minecraft/saves"); auto matcherReal = new RegexpMatcher(filters);
matcherReal->caseSensitive(false); matcherReal->caseSensitive(false);
m_matcher.reset(matcherReal); m_matcher.reset(matcherReal);
} }
@ -23,10 +38,88 @@ void InstanceCopyTask::executeTask()
{ {
setStatus(tr("Copying instance %1").arg(m_origInstance->name())); setStatus(tr("Copying instance %1").arg(m_origInstance->name()));
FS::copy folderCopy(m_origInstance->instanceRoot(), m_stagingPath); auto copySaves = [&]() {
folderCopy.followSymlinks(false).blacklist(m_matcher.get()); QFileInfo mcDir(FS::PathCombine(m_stagingPath, "minecraft"));
QFileInfo dotMCDir(FS::PathCombine(m_stagingPath, ".minecraft"));
m_copyFuture = QtConcurrent::run(QThreadPool::globalInstance(), folderCopy); QString staging_mc_dir;
if (mcDir.exists() && !dotMCDir.exists())
staging_mc_dir = mcDir.filePath();
else
staging_mc_dir = dotMCDir.filePath();
FS::copy savesCopy(FS::PathCombine(m_origInstance->gameRoot(), "saves"), FS::PathCombine(staging_mc_dir, "saves"));
savesCopy.followSymlinks(true);
return savesCopy();
};
m_copyFuture = QtConcurrent::run(QThreadPool::globalInstance(), [this, copySaves] {
if (m_useClone) {
FS::clone folderClone(m_origInstance->instanceRoot(), m_stagingPath);
folderClone.matcher(m_matcher.get());
return folderClone();
} else if (m_useLinks || m_useHardLinks) {
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());
bool there_were_errors = false;
if (!folderLink()) {
#if defined Q_OS_WIN32
if (!m_useHardLinks) {
qDebug() << "EXPECTED: Link failure, Windows requires permissions for symlinks";
qDebug() << "attempting to run with privelage";
QEventLoop loop;
bool got_priv_results = false;
connect(&folderLink, &FS::create_link::finishedPrivileged, this, [&](bool gotResults) {
if (!gotResults) {
qDebug() << "Privileged run exited without results!";
}
got_priv_results = gotResults;
loop.quit();
});
folderLink.runPrivileged();
loop.exec(); // wait for the finished signal
for (auto result : folderLink.getResults()) {
if (result.err_value != 0) {
there_were_errors = true;
}
}
if (m_copySaves) {
there_were_errors |= !copySaves();
}
return got_priv_results && !there_were_errors;
} else {
qDebug() << "Link Failed!" << folderLink.getOSError().value() << folderLink.getOSError().message().c_str();
}
#else
qDebug() << "Link Failed!" << folderLink.getOSError().value() << folderLink.getOSError().message().c_str();
#endif
return false;
}
if (m_copySaves) {
there_were_errors |= !copySaves();
}
return !there_were_errors;
} else {
FS::copy folderCopy(m_origInstance->instanceRoot(), m_stagingPath);
folderCopy.followSymlinks(false).matcher(m_matcher.get());
return folderCopy();
}
});
connect(&m_copyFutureWatcher, &QFutureWatcher<bool>::finished, this, &InstanceCopyTask::copyFinished); connect(&m_copyFutureWatcher, &QFutureWatcher<bool>::finished, this, &InstanceCopyTask::copyFinished);
connect(&m_copyFutureWatcher, &QFutureWatcher<bool>::canceled, this, &InstanceCopyTask::copyAborted); connect(&m_copyFutureWatcher, &QFutureWatcher<bool>::canceled, this, &InstanceCopyTask::copyAborted);
m_copyFutureWatcher.setFuture(m_copyFuture); m_copyFutureWatcher.setFuture(m_copyFuture);
@ -35,20 +128,40 @@ void InstanceCopyTask::executeTask()
void InstanceCopyTask::copyFinished() void InstanceCopyTask::copyFinished()
{ {
auto successful = m_copyFuture.result(); auto successful = m_copyFuture.result();
if(!successful) if (!successful) {
{
emitFailed(tr("Instance folder copy failed.")); emitFailed(tr("Instance folder copy failed."));
return; return;
} }
// FIXME: shouldn't this be able to report errors? // FIXME: shouldn't this be able to report errors?
auto instanceSettings = std::make_shared<INISettingsObject>(FS::PathCombine(m_stagingPath, "instance.cfg")); auto instanceSettings = std::make_shared<INISettingsObject>(FS::PathCombine(m_stagingPath, "instance.cfg"));
InstancePtr inst(new NullInstance(m_globalSettings, instanceSettings, m_stagingPath)); InstancePtr inst(new NullInstance(m_globalSettings, instanceSettings, m_stagingPath));
inst->setName(m_instName); inst->setName(name());
inst->setIconKey(m_instIcon); inst->setIconKey(m_instIcon);
if(!m_keepPlaytime) { if (!m_keepPlaytime) {
inst->resetTimePlayed(); inst->resetTimePlayed();
} }
if (m_useLinks)
inst->addLinkedInstanceId(m_origInstance->id());
if (m_useLinks) {
auto allowed_symlinks_file = QFileInfo(FS::PathCombine(inst->gameRoot(), "allowed_symlinks.txt"));
QByteArray allowed_symlinks;
if (allowed_symlinks_file.exists()) {
allowed_symlinks.append(FS::read(allowed_symlinks_file.filePath()));
if (allowed_symlinks.right(1) != "\n")
allowed_symlinks.append("\n"); // we want to be on a new line
}
allowed_symlinks.append(m_origInstance->gameRoot().toUtf8());
allowed_symlinks.append("\n");
if (allowed_symlinks_file.isSymLink())
FS::deletePath(allowed_symlinks_file
.filePath()); // we dont want to modify the original. also make sure the resulting file is not itself a link.
FS::write(allowed_symlinks_file.filePath(), allowed_symlinks);
}
emitSucceeded(); emitSucceeded();
} }

View File

@ -1,20 +1,21 @@
#pragma once #pragma once
#include "tasks/Task.h"
#include "net/NetJob.h"
#include <QUrl>
#include <QFuture> #include <QFuture>
#include <QFutureWatcher> #include <QFutureWatcher>
#include "settings/SettingsObject.h" #include <QUrl>
#include "BaseVersion.h"
#include "BaseInstance.h" #include "BaseInstance.h"
#include "BaseVersion.h"
#include "InstanceCopyPrefs.h"
#include "InstanceTask.h" #include "InstanceTask.h"
#include "net/NetJob.h"
#include "settings/SettingsObject.h"
#include "tasks/Task.h"
class InstanceCopyTask : public InstanceTask class InstanceCopyTask : public InstanceTask
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit InstanceCopyTask(InstancePtr origInstance, bool copySaves, bool keepPlaytime); explicit InstanceCopyTask(InstancePtr origInstance, const InstanceCopyPrefs& prefs);
protected: protected:
//! Entry point for tasks. //! Entry point for tasks.
@ -22,10 +23,16 @@ protected:
void copyFinished(); void copyFinished();
void copyAborted(); void copyAborted();
private: /* data */ private:
/* data */
InstancePtr m_origInstance; InstancePtr m_origInstance;
QFuture<bool> m_copyFuture; QFuture<bool> m_copyFuture;
QFutureWatcher<bool> m_copyFutureWatcher; QFutureWatcher<bool> m_copyFutureWatcher;
std::unique_ptr<IPathMatcher> m_matcher; std::unique_ptr<IPathMatcher> m_matcher;
bool m_keepPlaytime; bool m_keepPlaytime;
bool m_useLinks = false;
bool m_useHardLinks = false;
bool m_copySaves = false;
bool m_linkRecursively = false;
bool m_useClone = false;
}; };

View File

@ -1,40 +1,60 @@
#include "InstanceCreationTask.h" #include "InstanceCreationTask.h"
#include "settings/INISettingsObject.h"
#include "FileSystem.h"
//FIXME: remove this #include <QDebug>
#include "minecraft/MinecraftInstance.h" #include <QFile>
#include "minecraft/PackProfile.h"
InstanceCreationTask::InstanceCreationTask(BaseVersionPtr version) InstanceCreationTask::InstanceCreationTask() = default;
{
m_version = version;
m_usingLoader = false;
}
InstanceCreationTask::InstanceCreationTask(BaseVersionPtr version, QString loader, BaseVersionPtr loaderVersion)
{
m_version = version;
m_usingLoader = true;
m_loader = loader;
m_loaderVersion = loaderVersion;
}
void InstanceCreationTask::executeTask() void InstanceCreationTask::executeTask()
{ {
setStatus(tr("Creating instance from version %1").arg(m_version->name())); setAbortable(true);
{
auto instanceSettings = std::make_shared<INISettingsObject>(FS::PathCombine(m_stagingPath, "instance.cfg")); if (updateInstance()) {
instanceSettings->suspendSave(); emitSucceeded();
MinecraftInstance inst(m_globalSettings, instanceSettings, m_stagingPath); return;
auto components = inst.getPackProfile();
components->buildingFromScratch();
components->setComponentVersion("net.minecraft", m_version->descriptor(), true);
if(m_usingLoader)
components->setComponentVersion(m_loader, m_loaderVersion->descriptor());
inst.setName(m_instName);
inst.setIconKey(m_instIcon);
instanceSettings->resumeSave();
} }
// When the user aborted in the update stage.
if (m_abort) {
emitAborted();
return;
}
if (!createInstance()) {
if (m_abort)
return;
qWarning() << "Instance creation failed!";
if (!m_error_message.isEmpty()) {
qWarning() << "Reason: " << m_error_message;
emitFailed(tr("Error while creating new instance:\n%1").arg(m_error_message));
} else {
emitFailed(tr("Error while creating new instance."));
}
return;
}
// If this is set, it means we're updating an instance. So, we now need to remove the
// files scheduled to, and we'd better not let the user abort in the middle of it, since it'd
// put the instance in an invalid state.
if (shouldOverride()) {
setAbortable(false);
setStatus(tr("Removing old conflicting files..."));
qDebug() << "Removing old files";
for (auto path : m_files_to_remove) {
if (!QFile::exists(path))
continue;
qDebug() << "Removing" << path;
if (!QFile::remove(path)) {
qCritical() << "Couldn't remove the old conflicting files.";
emitFailed(tr("Failed to remove old conflicting files."));
return;
}
}
}
emitSucceeded(); emitSucceeded();
return;
} }

View File

@ -1,26 +1,46 @@
#pragma once #pragma once
#include "tasks/Task.h"
#include "net/NetJob.h"
#include <QUrl>
#include "settings/SettingsObject.h"
#include "BaseVersion.h" #include "BaseVersion.h"
#include "InstanceTask.h" #include "InstanceTask.h"
class InstanceCreationTask : public InstanceTask class InstanceCreationTask : public InstanceTask {
{
Q_OBJECT Q_OBJECT
public: public:
explicit InstanceCreationTask(BaseVersionPtr version); InstanceCreationTask();
explicit InstanceCreationTask(BaseVersionPtr version, QString loader, BaseVersionPtr loaderVersion); virtual ~InstanceCreationTask() = default;
protected: protected:
//! Entry point for tasks. void executeTask() final override;
virtual void executeTask() override;
private: /* data */ /**
BaseVersionPtr m_version; * Tries to update an already existing instance.
bool m_usingLoader; *
QString m_loader; * This can be implemented by subclasses to provide a way of updating an already existing
BaseVersionPtr m_loaderVersion; * instance, according to that implementation's concept of 'identity' (i.e. instances that
* are updates / downgrades of one another).
*
* If this returns true, createInstance() will not run, so you should do all update steps in here.
* Otherwise, createInstance() is run as normal.
*/
virtual bool updateInstance() { return false; };
/**
* Creates a new instance.
*
* Returns whether the instance creation was successful (true) or not (false).
*/
virtual bool createInstance() { return false; };
QString getError() const { return m_error_message; }
protected:
void setError(const QString& message) { m_error_message = message; };
protected:
bool m_abort = false;
QStringList m_files_to_remove;
private:
QString m_error_message;
}; };

View File

@ -35,72 +35,74 @@
*/ */
#include "InstanceImportTask.h" #include "InstanceImportTask.h"
#include <QtConcurrentRun>
#include "Application.h" #include "Application.h"
#include "BaseInstance.h"
#include "FileSystem.h" #include "FileSystem.h"
#include "MMCZip.h" #include "MMCZip.h"
#include "NullInstance.h" #include "NullInstance.h"
#include "QObjectPtr.h"
#include "icons/IconList.h" #include "icons/IconList.h"
#include "icons/IconUtils.h" #include "icons/IconUtils.h"
#include "modplatform/technic/TechnicPackProcessor.h"
#include "modplatform/modrinth/ModrinthInstanceCreationTask.h"
#include "modplatform/flame/FlameInstanceCreationTask.h"
#include "settings/INISettingsObject.h" #include "settings/INISettingsObject.h"
// FIXME: this does not belong here, it's Minecraft/Flame specific #include <QtConcurrentRun>
#include <quazip/quazipdir.h>
#include "Json.h"
#include "minecraft/MinecraftInstance.h"
#include "minecraft/PackProfile.h"
#include "modplatform/flame/FileResolvingTask.h"
#include "modplatform/flame/PackManifest.h"
#include "modplatform/modrinth/ModrinthPackManifest.h"
#include "modplatform/technic/TechnicPackProcessor.h"
#include "Application.h"
#include "icons/IconList.h"
#include "net/ChecksumValidator.h"
#include "ui/dialogs/CustomMessageBox.h"
#include "ui/dialogs/ScrollMessageBox.h"
#include <algorithm> #include <algorithm>
InstanceImportTask::InstanceImportTask(const QUrl sourceUrl, QWidget* parent) #include <quazip/quazipdir.h>
{
m_sourceUrl = sourceUrl; InstanceImportTask::InstanceImportTask(const QUrl sourceUrl, QWidget* parent, QMap<QString, QString>&& extra_info)
m_parent = parent; : m_sourceUrl(sourceUrl), m_extra_info(extra_info), m_parent(parent)
} {}
bool InstanceImportTask::abort() bool InstanceImportTask::abort()
{ {
if (!canAbort())
return false;
if (m_filesNetJob) if (m_filesNetJob)
m_filesNetJob->abort(); m_filesNetJob->abort();
m_extractFuture.cancel(); if (m_extractFuture.isRunning()) {
// NOTE: The tasks created by QtConcurrent::run() can't actually get cancelled,
// but we can use this call to check the state when the extraction finishes.
m_extractFuture.cancel();
m_extractFuture.waitForFinished();
}
return false; return Task::abort();
} }
void InstanceImportTask::executeTask() void InstanceImportTask::executeTask()
{ {
if (m_sourceUrl.isLocalFile()) setAbortable(true);
{
if (m_sourceUrl.isLocalFile()) {
m_archivePath = m_sourceUrl.toLocalFile(); m_archivePath = m_sourceUrl.toLocalFile();
processZipPack(); processZipPack();
} } else {
else
{
setStatus(tr("Downloading modpack:\n%1").arg(m_sourceUrl.toString())); setStatus(tr("Downloading modpack:\n%1").arg(m_sourceUrl.toString()));
m_downloadRequired = true; m_downloadRequired = true;
const QString path = m_sourceUrl.host() + '/' + m_sourceUrl.path(); const QString path(m_sourceUrl.host() + '/' + m_sourceUrl.path());
auto entry = APPLICATION->metacache()->resolveEntry("general", path); auto entry = APPLICATION->metacache()->resolveEntry("general", path);
entry->setStale(true); entry->setStale(true);
m_filesNetJob = new NetJob(tr("Modpack download"), APPLICATION->network());
m_filesNetJob->addNetAction(Net::Download::makeCached(m_sourceUrl, entry));
m_archivePath = entry->getFullPath(); m_archivePath = entry->getFullPath();
auto job = m_filesNetJob.get();
connect(job, &NetJob::succeeded, this, &InstanceImportTask::downloadSucceeded); m_filesNetJob.reset(new NetJob(tr("Modpack download"), APPLICATION->network()));
connect(job, &NetJob::progress, this, &InstanceImportTask::downloadProgressChanged); m_filesNetJob->addNetAction(Net::Download::makeCached(m_sourceUrl, entry));
connect(job, &NetJob::failed, this, &InstanceImportTask::downloadFailed);
connect(m_filesNetJob.get(), &NetJob::succeeded, this, &InstanceImportTask::downloadSucceeded);
connect(m_filesNetJob.get(), &NetJob::progress, this, &InstanceImportTask::downloadProgressChanged);
connect(m_filesNetJob.get(), &NetJob::stepProgress, this, &InstanceImportTask::propogateStepProgress);
connect(m_filesNetJob.get(), &NetJob::failed, this, &InstanceImportTask::downloadFailed);
connect(m_filesNetJob.get(), &NetJob::aborted, this, &InstanceImportTask::downloadAborted);
m_filesNetJob->start(); m_filesNetJob->start();
} }
} }
@ -119,7 +121,13 @@ void InstanceImportTask::downloadFailed(QString reason)
void InstanceImportTask::downloadProgressChanged(qint64 current, qint64 total) void InstanceImportTask::downloadProgressChanged(qint64 current, qint64 total)
{ {
setProgress(current / 2, total); setProgress(current, total);
}
void InstanceImportTask::downloadAborted()
{
emitAborted();
m_filesNetJob.reset();
} }
void InstanceImportTask::processZipPack() void InstanceImportTask::processZipPack()
@ -161,18 +169,14 @@ void InstanceImportTask::processZipPack()
} }
else else
{ {
QString mmcRoot = MMCZip::findFolderOfFileInZip(m_packZip.get(), "instance.cfg"); QStringList paths_to_ignore { "overrides/" };
QString flameRoot = MMCZip::findFolderOfFileInZip(m_packZip.get(), "manifest.json");
if (!mmcRoot.isNull()) if (QString mmcRoot = MMCZip::findFolderOfFileInZip(m_packZip.get(), "instance.cfg", paths_to_ignore); !mmcRoot.isNull()) {
{
// process as MultiMC instance/pack // process as MultiMC instance/pack
qDebug() << "MultiMC:" << mmcRoot; qDebug() << "MultiMC:" << mmcRoot;
root = mmcRoot; root = mmcRoot;
m_modpackType = ModpackType::MultiMC; m_modpackType = ModpackType::MultiMC;
} } else if (QString flameRoot = MMCZip::findFolderOfFileInZip(m_packZip.get(), "manifest.json", paths_to_ignore); !flameRoot.isNull()) {
else if(!flameRoot.isNull())
{
// process as Flame pack // process as Flame pack
qDebug() << "Flame:" << flameRoot; qDebug() << "Flame:" << flameRoot;
root = flameRoot; root = flameRoot;
@ -188,18 +192,20 @@ void InstanceImportTask::processZipPack()
// make sure we extract just the pack // make sure we extract just the pack
m_extractFuture = QtConcurrent::run(QThreadPool::globalInstance(), MMCZip::extractSubDir, m_packZip.get(), root, extractDir.absolutePath()); m_extractFuture = QtConcurrent::run(QThreadPool::globalInstance(), MMCZip::extractSubDir, m_packZip.get(), root, extractDir.absolutePath());
connect(&m_extractFutureWatcher, &QFutureWatcher<QStringList>::finished, this, &InstanceImportTask::extractFinished); connect(&m_extractFutureWatcher, &QFutureWatcher<QStringList>::finished, this, &InstanceImportTask::extractFinished);
connect(&m_extractFutureWatcher, &QFutureWatcher<QStringList>::canceled, this, &InstanceImportTask::extractAborted);
m_extractFutureWatcher.setFuture(m_extractFuture); m_extractFutureWatcher.setFuture(m_extractFuture);
} }
void InstanceImportTask::extractFinished() void InstanceImportTask::extractFinished()
{ {
m_packZip.reset(); m_packZip.reset();
if (!m_extractFuture.result())
{ if (m_extractFuture.isCanceled())
return;
if (!m_extractFuture.result().has_value()) {
emitFailed(tr("Failed to extract modpack")); emitFailed(tr("Failed to extract modpack"));
return; return;
} }
QDir extractDir(m_stagingPath); QDir extractDir(m_stagingPath);
qDebug() << "Fixing permissions for extracted pack files..."; qDebug() << "Fixing permissions for extracted pack files...";
@ -253,300 +259,57 @@ void InstanceImportTask::extractFinished()
} }
} }
void InstanceImportTask::extractAborted()
{
emitFailed(tr("Instance import has been aborted."));
return;
}
void InstanceImportTask::processFlame() void InstanceImportTask::processFlame()
{ {
const static QMap<QString,QString> forgemap = { shared_qobject_ptr<FlameCreationTask> inst_creation_task = nullptr;
{"1.2.5", "3.4.9.171"}, if (!m_extra_info.isEmpty()) {
{"1.4.2", "6.0.1.355"}, auto pack_id_it = m_extra_info.constFind("pack_id");
{"1.4.7", "6.6.2.534"}, Q_ASSERT(pack_id_it != m_extra_info.constEnd());
{"1.5.2", "7.8.1.737"} auto pack_id = pack_id_it.value();
};
Flame::Manifest pack; auto pack_version_id_it = m_extra_info.constFind("pack_version_id");
try Q_ASSERT(pack_version_id_it != m_extra_info.constEnd());
{ auto pack_version_id = pack_version_id_it.value();
QString configPath = FS::PathCombine(m_stagingPath, "manifest.json");
Flame::loadManifest(pack, configPath); QString original_instance_id;
QFile::remove(configPath); auto original_instance_id_it = m_extra_info.constFind("original_instance_id");
} if (original_instance_id_it != m_extra_info.constEnd())
catch (const JSONValidationError &e) original_instance_id = original_instance_id_it.value();
{
emitFailed(tr("Could not understand pack manifest:\n") + e.cause()); inst_creation_task = makeShared<FlameCreationTask>(m_stagingPath, m_globalSettings, m_parent, pack_id, pack_version_id, original_instance_id);
return; } else {
} // FIXME: Find a way to get IDs in directly imported ZIPs
if(!pack.overrides.isEmpty()) inst_creation_task = makeShared<FlameCreationTask>(m_stagingPath, m_globalSettings, m_parent, QString(), QString());
{
QString overridePath = FS::PathCombine(m_stagingPath, pack.overrides);
if (QFile::exists(overridePath))
{
QString mcPath = FS::PathCombine(m_stagingPath, "minecraft");
if (!QFile::rename(overridePath, mcPath))
{
emitFailed(tr("Could not rename the overrides folder:\n") + pack.overrides);
return;
}
}
else
{
logWarning(tr("The specified overrides folder (%1) is missing. Maybe the modpack was already used before?").arg(pack.overrides));
}
} }
QString forgeVersion; inst_creation_task->setName(*this);
QString fabricVersion; inst_creation_task->setIcon(m_instIcon);
// TODO: is Quilt relevant here? inst_creation_task->setGroup(m_instGroup);
for(auto &loader: pack.minecraft.modLoaders) inst_creation_task->setConfirmUpdate(shouldConfirmUpdate());
{
auto id = loader.id; connect(inst_creation_task.get(), &Task::succeeded, this, [this, inst_creation_task] {
if(id.startsWith("forge-")) setOverride(inst_creation_task->shouldOverride(), inst_creation_task->originalInstanceID());
{ emitSucceeded();
id.remove("forge-");
forgeVersion = id;
continue;
}
if(id.startsWith("fabric-"))
{
id.remove("fabric-");
fabricVersion = id;
continue;
}
logWarning(tr("Unknown mod loader in manifest: %1").arg(id));
}
QString configPath = FS::PathCombine(m_stagingPath, "instance.cfg");
auto instanceSettings = std::make_shared<INISettingsObject>(configPath);
MinecraftInstance instance(m_globalSettings, instanceSettings, m_stagingPath);
auto mcVersion = pack.minecraft.version;
// Hack to correct some 'special sauce'...
if(mcVersion.endsWith('.'))
{
mcVersion.remove(QRegularExpression("[.]+$"));
logWarning(tr("Mysterious trailing dots removed from Minecraft version while importing pack."));
}
auto components = instance.getPackProfile();
components->buildingFromScratch();
components->setComponentVersion("net.minecraft", mcVersion, true);
if(!forgeVersion.isEmpty())
{
// FIXME: dirty, nasty, hack. Proper solution requires dependency resolution and knowledge of the metadata.
if(forgeVersion == "recommended")
{
if(forgemap.contains(mcVersion))
{
forgeVersion = forgemap[mcVersion];
}
else
{
logWarning(tr("Could not map recommended Forge version for Minecraft %1").arg(mcVersion));
}
}
components->setComponentVersion("net.minecraftforge", forgeVersion);
}
if(!fabricVersion.isEmpty())
{
components->setComponentVersion("net.fabricmc.fabric-loader", fabricVersion);
}
if (m_instIcon != "default")
{
instance.setIconKey(m_instIcon);
}
else
{
if(pack.name.contains("Direwolf20"))
{
instance.setIconKey("steve");
}
else if(pack.name.contains("FTB") || pack.name.contains("Feed The Beast"))
{
instance.setIconKey("ftb_logo");
}
else
{
// default to something other than the MultiMC default to distinguish these
instance.setIconKey("flame");
}
}
QString jarmodsPath = FS::PathCombine(m_stagingPath, "minecraft", "jarmods");
QFileInfo jarmodsInfo(jarmodsPath);
if(jarmodsInfo.isDir())
{
// install all the jar mods
qDebug() << "Found jarmods:";
QDir jarmodsDir(jarmodsPath);
QStringList jarMods;
for (auto info: jarmodsDir.entryInfoList(QDir::NoDotAndDotDot | QDir::Files))
{
qDebug() << info.fileName();
jarMods.push_back(info.absoluteFilePath());
}
auto profile = instance.getPackProfile();
profile->installJarMods(jarMods);
// nuke the original files
FS::deletePath(jarmodsPath);
}
instance.setName(m_instName);
m_modIdResolver = new Flame::FileResolvingTask(APPLICATION->network(), pack);
connect(m_modIdResolver.get(), &Flame::FileResolvingTask::succeeded, [&]()
{
auto results = m_modIdResolver->getResults();
//first check for blocked mods
QString text;
auto anyBlocked = false;
for(const auto& result: results.files.values()) {
if (!result.resolved || result.url.isEmpty()) {
text += QString("%1: <a href='%2'>%2</a><br/>").arg(result.fileName, result.websiteUrl);
anyBlocked = true;
}
}
if(anyBlocked) {
qWarning() << "Blocked mods found, displaying mod list";
auto message_dialog = new ScrollMessageBox(m_parent,
tr("Blocked mods found"),
tr("The following mods were blocked on third party launchers.<br/>"
"You will need to manually download them and add them to the modpack"),
text);
message_dialog->setModal(true);
if (message_dialog->exec()) {
m_filesNetJob = new NetJob(tr("Mod download"), APPLICATION->network());
for (const auto &result: m_modIdResolver->getResults().files) {
QString filename = result.fileName;
if (!result.required) {
filename += ".disabled";
}
auto relpath = FS::PathCombine("minecraft", result.targetFolder, filename);
auto path = FS::PathCombine(m_stagingPath, relpath);
switch (result.type) {
case Flame::File::Type::Folder: {
logWarning(tr("This 'Folder' may need extracting: %1").arg(relpath));
// fall-through intentional, we treat these as plain old mods and dump them wherever.
}
case Flame::File::Type::SingleFile:
case Flame::File::Type::Mod: {
if (!result.url.isEmpty()) {
qDebug() << "Will download" << result.url << "to" << path;
auto dl = Net::Download::makeFile(result.url, path);
m_filesNetJob->addNetAction(dl);
}
break;
}
case Flame::File::Type::Modpack:
logWarning(
tr("Nesting modpacks in modpacks is not implemented, nothing was downloaded: %1").arg(
relpath));
break;
case Flame::File::Type::Cmod2:
case Flame::File::Type::Ctoc:
case Flame::File::Type::Unknown:
logWarning(tr("Unrecognized/unhandled PackageType for: %1").arg(relpath));
break;
}
}
m_modIdResolver.reset();
connect(m_filesNetJob.get(), &NetJob::succeeded, this, [&]() {
m_filesNetJob.reset();
emitSucceeded();
}
);
connect(m_filesNetJob.get(), &NetJob::failed, [&](QString reason) {
m_filesNetJob.reset();
emitFailed(reason);
});
connect(m_filesNetJob.get(), &NetJob::progress, [&](qint64 current, qint64 total) {
setProgress(current, total);
});
setStatus(tr("Downloading mods..."));
m_filesNetJob->start();
} else {
m_modIdResolver.reset();
emitFailed("Canceled");
}
} else {
//TODO extract to function ?
m_filesNetJob = new NetJob(tr("Mod download"), APPLICATION->network());
for (const auto &result: m_modIdResolver->getResults().files) {
QString filename = result.fileName;
if (!result.required) {
filename += ".disabled";
}
auto relpath = FS::PathCombine("minecraft", result.targetFolder, filename);
auto path = FS::PathCombine(m_stagingPath, relpath);
switch (result.type) {
case Flame::File::Type::Folder: {
logWarning(tr("This 'Folder' may need extracting: %1").arg(relpath));
// fall-through intentional, we treat these as plain old mods and dump them wherever.
}
case Flame::File::Type::SingleFile:
case Flame::File::Type::Mod: {
if (!result.url.isEmpty()) {
qDebug() << "Will download" << result.url << "to" << path;
auto dl = Net::Download::makeFile(result.url, path);
m_filesNetJob->addNetAction(dl);
}
break;
}
case Flame::File::Type::Modpack:
logWarning(
tr("Nesting modpacks in modpacks is not implemented, nothing was downloaded: %1").arg(
relpath));
break;
case Flame::File::Type::Cmod2:
case Flame::File::Type::Ctoc:
case Flame::File::Type::Unknown:
logWarning(tr("Unrecognized/unhandled PackageType for: %1").arg(relpath));
break;
}
}
m_modIdResolver.reset();
connect(m_filesNetJob.get(), &NetJob::succeeded, this, [&]() {
m_filesNetJob.reset();
emitSucceeded();
}
);
connect(m_filesNetJob.get(), &NetJob::failed, [&](QString reason) {
m_filesNetJob.reset();
emitFailed(reason);
});
connect(m_filesNetJob.get(), &NetJob::progress, [&](qint64 current, qint64 total) {
setProgress(current, total);
});
setStatus(tr("Downloading mods..."));
m_filesNetJob->start();
}
}
);
connect(m_modIdResolver.get(), &Flame::FileResolvingTask::failed, [&](QString reason)
{
m_modIdResolver.reset();
emitFailed(tr("Unable to resolve mod IDs:\n") + reason);
}); });
connect(m_modIdResolver.get(), &Flame::FileResolvingTask::progress, [&](qint64 current, qint64 total) connect(inst_creation_task.get(), &Task::failed, this, &InstanceImportTask::emitFailed);
{ connect(inst_creation_task.get(), &Task::progress, this, &InstanceImportTask::setProgress);
setProgress(current, total); connect(inst_creation_task.get(), &Task::stepProgress, this, &InstanceImportTask::propogateStepProgress);
}); connect(inst_creation_task.get(), &Task::status, this, &InstanceImportTask::setStatus);
connect(m_modIdResolver.get(), &Flame::FileResolvingTask::status, [&](QString status) connect(inst_creation_task.get(), &Task::details, this, &InstanceImportTask::setDetails);
{
setStatus(status); connect(this, &Task::aborted, inst_creation_task.get(), &InstanceCreationTask::abort);
}); connect(inst_creation_task.get(), &Task::aborted, this, &Task::abort);
m_modIdResolver->start(); connect(inst_creation_task.get(), &Task::abortStatusChanged, this, &Task::setAbortable);
inst_creation_task->start();
} }
void InstanceImportTask::processTechnic() void InstanceImportTask::processTechnic()
{ {
shared_qobject_ptr<Technic::TechnicPackProcessor> packProcessor = new Technic::TechnicPackProcessor(); shared_qobject_ptr<Technic::TechnicPackProcessor> packProcessor{ new Technic::TechnicPackProcessor };
connect(packProcessor.get(), &Technic::TechnicPackProcessor::succeeded, this, &InstanceImportTask::emitSucceeded); connect(packProcessor.get(), &Technic::TechnicPackProcessor::succeeded, this, &InstanceImportTask::emitSucceeded);
connect(packProcessor.get(), &Technic::TechnicPackProcessor::failed, this, &InstanceImportTask::emitFailed); connect(packProcessor.get(), &Technic::TechnicPackProcessor::failed, this, &InstanceImportTask::emitFailed);
packProcessor->run(m_globalSettings, m_instName, m_instIcon, m_stagingPath); packProcessor->run(m_globalSettings, name(), m_instIcon, m_stagingPath);
} }
void InstanceImportTask::processMultiMC() void InstanceImportTask::processMultiMC()
@ -560,7 +323,7 @@ void InstanceImportTask::processMultiMC()
instance.resetTimePlayed(); instance.resetTimePlayed();
// set a new nice name // set a new nice name
instance.setName(m_instName); instance.setName(name());
// if the icon was specified by user, use that. otherwise pull icon from the pack // if the icon was specified by user, use that. otherwise pull icon from the pack
if (m_instIcon != "default") { if (m_instIcon != "default") {
@ -581,198 +344,55 @@ void InstanceImportTask::processMultiMC()
emitSucceeded(); emitSucceeded();
} }
// https://docs.modrinth.com/docs/modpacks/format_definition/
void InstanceImportTask::processModrinth() void InstanceImportTask::processModrinth()
{ {
std::vector<Modrinth::File> files; ModrinthCreationTask* inst_creation_task = nullptr;
QString minecraftVersion, fabricVersion, quiltVersion, forgeVersion; if (!m_extra_info.isEmpty()) {
try { auto pack_id_it = m_extra_info.constFind("pack_id");
QString indexPath = FS::PathCombine(m_stagingPath, "modrinth.index.json"); Q_ASSERT(pack_id_it != m_extra_info.constEnd());
auto doc = Json::requireDocument(indexPath); auto pack_id = pack_id_it.value();
auto obj = Json::requireObject(doc, "modrinth.index.json");
int formatVersion = Json::requireInteger(obj, "formatVersion", "modrinth.index.json");
if (formatVersion == 1) {
auto game = Json::requireString(obj, "game", "modrinth.index.json");
if (game != "minecraft") {
throw JSONValidationError("Unknown game: " + game);
}
auto jsonFiles = Json::requireIsArrayOf<QJsonObject>(obj, "files", "modrinth.index.json"); QString pack_version_id;
bool had_optional = false; auto pack_version_id_it = m_extra_info.constFind("pack_version_id");
for (auto modInfo : jsonFiles) { if (pack_version_id_it != m_extra_info.constEnd())
Modrinth::File file; pack_version_id = pack_version_id_it.value();
file.path = Json::requireString(modInfo, "path");
auto env = Json::ensureObject(modInfo, "env"); QString original_instance_id;
// 'env' field is optional auto original_instance_id_it = m_extra_info.constFind("original_instance_id");
if (!env.isEmpty()) { if (original_instance_id_it != m_extra_info.constEnd())
QString support = Json::ensureString(env, "client", "unsupported"); original_instance_id = original_instance_id_it.value();
if (support == "unsupported") {
continue;
} else if (support == "optional") {
// TODO: Make a review dialog for choosing which ones the user wants!
if (!had_optional) {
had_optional = true;
auto info = CustomMessageBox::selectable(
m_parent, tr("Optional mod detected!"),
tr("One or more mods from this modpack are optional. They will be downloaded, but disabled by default!"),
QMessageBox::Information);
info->exec();
}
if (file.path.endsWith(".jar")) inst_creation_task = new ModrinthCreationTask(m_stagingPath, m_globalSettings, m_parent, pack_id, pack_version_id, original_instance_id);
file.path += ".disabled"; } else {
} QString pack_id;
} if (!m_sourceUrl.isEmpty()) {
QRegularExpression regex(R"(data\/([^\/]*)\/versions)");
QJsonObject hashes = Json::requireObject(modInfo, "hashes"); pack_id = regex.match(m_sourceUrl.toString()).captured(1);
QString hash;
QCryptographicHash::Algorithm hashAlgorithm;
hash = Json::ensureString(hashes, "sha1");
hashAlgorithm = QCryptographicHash::Sha1;
if (hash.isEmpty()) {
hash = Json::ensureString(hashes, "sha512");
hashAlgorithm = QCryptographicHash::Sha512;
if (hash.isEmpty()) {
hash = Json::ensureString(hashes, "sha256");
hashAlgorithm = QCryptographicHash::Sha256;
if (hash.isEmpty()) {
throw JSONValidationError("No hash found for: " + file.path);
}
}
}
file.hash = QByteArray::fromHex(hash.toLatin1());
file.hashAlgorithm = hashAlgorithm;
// Do not use requireUrl, which uses StrictMode, instead use QUrl's default TolerantMode
// (as Modrinth seems to incorrectly handle spaces)
auto download_arr = Json::ensureArray(modInfo, "downloads");
for(auto download : download_arr) {
qWarning() << download.toString();
bool is_last = download.toString() == download_arr.last().toString();
auto download_url = QUrl(download.toString());
if (!download_url.isValid()) {
qDebug() << QString("Download URL (%1) for %2 is not a correctly formatted URL")
.arg(download_url.toString(), file.path);
if(is_last && file.downloads.isEmpty())
throw JSONValidationError(tr("Download URL for %1 is not a correctly formatted URL").arg(file.path));
}
else {
file.downloads.push_back(download_url);
}
}
files.push_back(file);
}
auto dependencies = Json::requireObject(obj, "dependencies", "modrinth.index.json");
for (auto it = dependencies.begin(), end = dependencies.end(); it != end; ++it) {
QString name = it.key();
if (name == "minecraft") {
minecraftVersion = Json::requireString(*it, "Minecraft version");
}
else if (name == "fabric-loader") {
fabricVersion = Json::requireString(*it, "Fabric Loader version");
}
else if (name == "quilt-loader") {
quiltVersion = Json::requireString(*it, "Quilt Loader version");
}
else if (name == "forge") {
forgeVersion = Json::requireString(*it, "Forge version");
}
else {
throw JSONValidationError("Unknown dependency type: " + name);
}
}
} else {
throw JSONValidationError(QStringLiteral("Unknown format version: %s").arg(formatVersion));
} }
QFile::remove(indexPath);
} catch (const JSONValidationError& e) { // FIXME: Find a way to get the ID in directly imported ZIPs
emitFailed(tr("Could not understand pack index:\n") + e.cause()); inst_creation_task = new ModrinthCreationTask(m_stagingPath, m_globalSettings, m_parent, pack_id);
return;
} }
inst_creation_task->setName(*this);
inst_creation_task->setIcon(m_instIcon);
inst_creation_task->setGroup(m_instGroup);
inst_creation_task->setConfirmUpdate(shouldConfirmUpdate());
auto mcPath = FS::PathCombine(m_stagingPath, ".minecraft"); connect(inst_creation_task, &Task::succeeded, this, [this, inst_creation_task] {
setOverride(inst_creation_task->shouldOverride(), inst_creation_task->originalInstanceID());
auto override_path = FS::PathCombine(m_stagingPath, "overrides"); emitSucceeded();
if (QFile::exists(override_path)) {
if (!QFile::rename(override_path, mcPath)) {
emitFailed(tr("Could not rename the overrides folder:\n") + "overrides");
return;
}
}
// Do client overrides
auto client_override_path = FS::PathCombine(m_stagingPath, "client-overrides");
if (QFile::exists(client_override_path)) {
if (!FS::overrideFolder(mcPath, client_override_path)) {
emitFailed(tr("Could not rename the client overrides folder:\n") + "client overrides");
return;
}
}
QString configPath = FS::PathCombine(m_stagingPath, "instance.cfg");
auto instanceSettings = std::make_shared<INISettingsObject>(configPath);
MinecraftInstance instance(m_globalSettings, instanceSettings, m_stagingPath);
auto components = instance.getPackProfile();
components->buildingFromScratch();
components->setComponentVersion("net.minecraft", minecraftVersion, true);
if (!fabricVersion.isEmpty())
components->setComponentVersion("net.fabricmc.fabric-loader", fabricVersion);
if (!quiltVersion.isEmpty())
components->setComponentVersion("org.quiltmc.quilt-loader", quiltVersion);
if (!forgeVersion.isEmpty())
components->setComponentVersion("net.minecraftforge", forgeVersion);
if (m_instIcon != "default")
{
instance.setIconKey(m_instIcon);
}
else
{
instance.setIconKey("modrinth");
}
instance.setName(m_instName);
instance.saveNow();
m_filesNetJob = new NetJob(tr("Mod download"), APPLICATION->network());
for (auto file : files)
{
auto path = FS::PathCombine(m_stagingPath, ".minecraft", file.path);
qDebug() << "Will try to download" << file.downloads.front() << "to" << path;
auto dl = Net::Download::makeFile(file.downloads.dequeue(), path);
dl->addValidator(new Net::ChecksumValidator(file.hashAlgorithm, file.hash));
m_filesNetJob->addNetAction(dl);
if (file.downloads.size() > 0) {
// FIXME: This really needs to be put into a ConcurrentTask of
// MultipleOptionsTask's , once those exist :)
connect(dl.get(), &NetAction::failed, [this, &file, path, dl]{
auto dl = Net::Download::makeFile(file.downloads.dequeue(), path);
dl->addValidator(new Net::ChecksumValidator(file.hashAlgorithm, file.hash));
m_filesNetJob->addNetAction(dl);
dl->succeeded();
});
}
}
connect(m_filesNetJob.get(), &NetJob::succeeded, this, [&]()
{
m_filesNetJob.reset();
emitSucceeded();
}
);
connect(m_filesNetJob.get(), &NetJob::failed, [&](const QString &reason)
{
m_filesNetJob.reset();
emitFailed(reason);
}); });
connect(m_filesNetJob.get(), &NetJob::progress, [&](qint64 current, qint64 total) connect(inst_creation_task, &Task::failed, this, &InstanceImportTask::emitFailed);
{ connect(inst_creation_task, &Task::progress, this, &InstanceImportTask::setProgress);
setProgress(current, total); connect(inst_creation_task, &Task::stepProgress, this, &InstanceImportTask::propogateStepProgress);
}); connect(inst_creation_task, &Task::status, this, &InstanceImportTask::setStatus);
setStatus(tr("Downloading mods...")); connect(inst_creation_task, &Task::details, this, &InstanceImportTask::setDetails);
m_filesNetJob->start(); connect(inst_creation_task, &Task::finished, inst_creation_task, &InstanceCreationTask::deleteLater);
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);
inst_creation_task->start();
} }

View File

@ -44,7 +44,7 @@
#include "QObjectPtr.h" #include "QObjectPtr.h"
#include "modplatform/flame/PackManifest.h" #include "modplatform/flame/PackManifest.h"
#include <nonstd/optional> #include <optional>
class QuaZip; class QuaZip;
namespace Flame namespace Flame
@ -56,9 +56,8 @@ class InstanceImportTask : public InstanceTask
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit InstanceImportTask(const QUrl sourceUrl, QWidget* parent = nullptr); explicit InstanceImportTask(const QUrl sourceUrl, QWidget* parent = nullptr, QMap<QString, QString>&& extra_info = {});
bool canAbort() const override { return true; }
bool abort() override; bool abort() override;
const QVector<Flame::File> &getBlockedFiles() const const QVector<Flame::File> &getBlockedFiles() const
{ {
@ -80,8 +79,8 @@ private slots:
void downloadSucceeded(); void downloadSucceeded();
void downloadFailed(QString reason); void downloadFailed(QString reason);
void downloadProgressChanged(qint64 current, qint64 total); void downloadProgressChanged(qint64 current, qint64 total);
void downloadAborted();
void extractFinished(); void extractFinished();
void extractAborted();
private: /* data */ private: /* data */
NetJob::Ptr m_filesNetJob; NetJob::Ptr m_filesNetJob;
@ -90,8 +89,8 @@ private: /* data */
QString m_archivePath; QString m_archivePath;
bool m_downloadRequired = false; bool m_downloadRequired = false;
std::unique_ptr<QuaZip> m_packZip; std::unique_ptr<QuaZip> m_packZip;
QFuture<nonstd::optional<QStringList>> m_extractFuture; QFuture<std::optional<QStringList>> m_extractFuture;
QFutureWatcher<nonstd::optional<QStringList>> m_extractFutureWatcher; QFutureWatcher<std::optional<QStringList>> m_extractFutureWatcher;
QVector<Flame::File> m_blockedMods; QVector<Flame::File> m_blockedMods;
enum class ModpackType{ enum class ModpackType{
Unknown, Unknown,
@ -101,6 +100,10 @@ private: /* data */
Modrinth, Modrinth,
} m_modpackType = ModpackType::Unknown; } m_modpackType = ModpackType::Unknown;
// Extra info we might need, that's available before, but can't be derived from
// the source URL / the resource it points to alone.
QMap<QString, QString> m_extra_info;
//FIXME: nuke //FIXME: nuke
QWidget* m_parent; QWidget* m_parent;
}; };

File diff suppressed because it is too large Load Diff

View File

@ -19,13 +19,15 @@
#include <QAbstractListModel> #include <QAbstractListModel>
#include <QSet> #include <QSet>
#include <QList> #include <QList>
#include <QStack>
#include <QPair>
#include "BaseInstance.h" #include "BaseInstance.h"
#include "QObjectPtr.h"
class QFileSystemWatcher; class QFileSystemWatcher;
class InstanceTask; class InstanceTask;
struct InstanceName;
using InstanceId = QString; using InstanceId = QString;
using GroupId = QString; using GroupId = QString;
using InstanceLocator = std::pair<InstancePtr, int>; using InstanceLocator = std::pair<InstancePtr, int>;
@ -46,6 +48,12 @@ enum class GroupsState
Dirty Dirty
}; };
struct TrashHistoryItem {
QString id;
QString polyPath;
QString trashPath;
QString groupName;
};
class InstanceList : public QAbstractListModel class InstanceList : public QAbstractListModel
{ {
@ -93,7 +101,10 @@ public:
InstListError loadList(); InstListError loadList();
void saveNow(); void saveNow();
/* O(n) */
InstancePtr getInstanceById(QString id) const; InstancePtr getInstanceById(QString id) const;
/* O(n) */
InstancePtr getInstanceByManagedName(const QString& managed_name) const;
QModelIndex getInstanceIndexById(const QString &id) const; QModelIndex getInstanceIndexById(const QString &id) const;
QStringList getGroups(); QStringList getGroups();
bool isGroupCollapsed(const QString &groupName); bool isGroupCollapsed(const QString &groupName);
@ -102,6 +113,9 @@ public:
void setInstanceGroup(const InstanceId & id, const GroupId& name); void setInstanceGroup(const InstanceId & id, const GroupId& name);
void deleteGroup(const GroupId & name); void deleteGroup(const GroupId & name);
bool trashInstance(const InstanceId &id);
bool trashedSomething();
void undoTrashInstance();
void deleteInstance(const InstanceId & id); void deleteInstance(const InstanceId & id);
// Wrap an instance creation task in some more task machinery and make it ready to be used // Wrap an instance creation task in some more task machinery and make it ready to be used
@ -116,8 +130,10 @@ public:
/** /**
* Commit the staging area given by @keyPath to the provider - used when creation succeeds. * Commit the staging area given by @keyPath to the provider - used when creation succeeds.
* Used by instance manipulation tasks. * Used by instance manipulation tasks.
* should_override is used when another similar instance already exists, and we want to override it
* - for instance, when updating it.
*/ */
bool commitStagedInstance(const QString & keyPath, const QString& instanceName, const QString & groupName); bool commitStagedInstance(const QString& keyPath, const InstanceName& instanceName, const QString& groupName, const InstanceTask&);
/** /**
* Destroy a previously created staging area given by @keyPath - used when creation fails. * Destroy a previously created staging area given by @keyPath - used when creation fails.
@ -138,6 +154,8 @@ public:
QStringList mimeTypes() const override; QStringList mimeTypes() const override;
QMimeData *mimeData(const QModelIndexList &indexes) const override; QMimeData *mimeData(const QModelIndexList &indexes) const override;
QStringList getLinkedInstancesById(const QString &id) const;
signals: signals:
void dataIsInvalid(); void dataIsInvalid();
void instancesChanged(); void instancesChanged();
@ -180,4 +198,6 @@ private:
QSet<InstanceId> instanceSet; QSet<InstanceId> instanceSet;
bool m_groupsLoaded = false; bool m_groupsLoaded = false;
bool m_instancesProbed = false; bool m_instancesProbed = false;
QStack<TrashHistoryItem> m_trashHistory;
}; };

View File

@ -5,6 +5,7 @@
#include "ui/pages/BasePageProvider.h" #include "ui/pages/BasePageProvider.h"
#include "ui/pages/instance/LogPage.h" #include "ui/pages/instance/LogPage.h"
#include "ui/pages/instance/VersionPage.h" #include "ui/pages/instance/VersionPage.h"
#include "ui/pages/instance/ManagedPackPage.h"
#include "ui/pages/instance/ModFolderPage.h" #include "ui/pages/instance/ModFolderPage.h"
#include "ui/pages/instance/ResourcePackPage.h" #include "ui/pages/instance/ResourcePackPage.h"
#include "ui/pages/instance/TexturePackPage.h" #include "ui/pages/instance/TexturePackPage.h"
@ -33,13 +34,15 @@ public:
values.append(new LogPage(inst)); values.append(new LogPage(inst));
std::shared_ptr<MinecraftInstance> onesix = std::dynamic_pointer_cast<MinecraftInstance>(inst); std::shared_ptr<MinecraftInstance> onesix = std::dynamic_pointer_cast<MinecraftInstance>(inst);
values.append(new VersionPage(onesix.get())); values.append(new VersionPage(onesix.get()));
values.append(ManagedPackPage::createPage(onesix.get()));
auto modsPage = new ModFolderPage(onesix.get(), onesix->loaderModList()); auto modsPage = new ModFolderPage(onesix.get(), onesix->loaderModList());
modsPage->setFilter("%1 (*.zip *.jar *.litemod)"); modsPage->setFilter("%1 (*.zip *.jar *.litemod *.nilmod)");
values.append(modsPage); values.append(modsPage);
values.append(new CoreModFolderPage(onesix.get(), onesix->coreModList())); values.append(new CoreModFolderPage(onesix.get(), onesix->coreModList()));
values.append(new ResourcePackPage(onesix.get())); values.append(new NilModFolderPage(onesix.get(), onesix->nilModList()));
values.append(new TexturePackPage(onesix.get())); values.append(new ResourcePackPage(onesix.get(), onesix->resourcePackList()));
values.append(new ShaderPackPage(onesix.get())); values.append(new TexturePackPage(onesix.get(), onesix->texturePackList()));
values.append(new ShaderPackPage(onesix.get(), onesix->shaderPackList()));
values.append(new NotesPage(onesix.get())); values.append(new NotesPage(onesix.get()));
values.append(new WorldListPage(onesix.get(), onesix->worldList())); values.append(new WorldListPage(onesix.get(), onesix->worldList()));
values.append(new ServersPage(onesix)); values.append(new ServersPage(onesix));

View File

@ -1,9 +1,75 @@
#include "InstanceTask.h" #include "InstanceTask.h"
InstanceTask::InstanceTask() #include "ui/dialogs/CustomMessageBox.h"
InstanceNameChange askForChangingInstanceName(QWidget* parent, const QString& old_name, const QString& new_name)
{ {
auto dialog =
CustomMessageBox::selectable(parent, QObject::tr("Change instance name"),
QObject::tr("The instance's name seems to include the old version. Would you like to update it?\n\n"
"Old name: %1\n"
"New name: %2")
.arg(old_name, new_name),
QMessageBox::Question, QMessageBox::No | QMessageBox::Yes);
auto result = dialog->exec();
if (result == QMessageBox::Yes)
return InstanceNameChange::ShouldChange;
return InstanceNameChange::ShouldKeep;
} }
InstanceTask::~InstanceTask() ShouldUpdate askIfShouldUpdate(QWidget *parent, QString original_version_name)
{ {
auto info = CustomMessageBox::selectable(
parent, QObject::tr("Similar modpack was found!"),
QObject::tr("One or more of your instances are from this same modpack%1. Do you want to create a "
"separate instance, or update the existing one?\n\nNOTE: Make sure you made a backup of your important instance data before "
"updating, as worlds can be corrupted and some configuration may be lost (due to pack overrides).")
.arg(original_version_name),
QMessageBox::Information, QMessageBox::Ok | QMessageBox::Reset | QMessageBox::Abort);
info->setButtonText(QMessageBox::Ok, QObject::tr("Update existing instance"));
info->setButtonText(QMessageBox::Abort, QObject::tr("Create new instance"));
info->setButtonText(QMessageBox::Reset, QObject::tr("Cancel"));
info->exec();
if (info->clickedButton() == info->button(QMessageBox::Ok))
return ShouldUpdate::Update;
if (info->clickedButton() == info->button(QMessageBox::Abort))
return ShouldUpdate::SkipUpdating;
return ShouldUpdate::Cancel;
} }
QString InstanceName::name() const
{
if (!m_modified_name.isEmpty())
return modifiedName();
return QString("%1 %2").arg(m_original_name, m_original_version);
}
QString InstanceName::originalName() const
{
return m_original_name;
}
QString InstanceName::modifiedName() const
{
if (!m_modified_name.isEmpty())
return m_modified_name;
return m_original_name;
}
QString InstanceName::version() const
{
return m_original_version;
}
void InstanceName::setName(InstanceName& other)
{
m_original_name = other.m_original_name;
m_original_version = other.m_original_version;
m_modified_name = other.m_modified_name;
}
InstanceTask::InstanceTask() : Task(), InstanceName() {}

View File

@ -1,52 +1,72 @@
#pragma once #pragma once
#include "tasks/Task.h"
#include "settings/SettingsObject.h" #include "settings/SettingsObject.h"
#include "tasks/Task.h"
class InstanceTask : public Task /* Helpers */
{ enum class InstanceNameChange { ShouldChange, ShouldKeep };
[[nodiscard]] InstanceNameChange askForChangingInstanceName(QWidget* parent, const QString& old_name, const QString& new_name);
enum class ShouldUpdate { Update, SkipUpdating, Cancel };
[[nodiscard]] ShouldUpdate askIfShouldUpdate(QWidget* parent, QString original_version_name);
struct InstanceName {
public:
InstanceName() = default;
InstanceName(QString name, QString version) : m_original_name(std::move(name)), m_original_version(std::move(version)) {}
[[nodiscard]] QString modifiedName() const;
[[nodiscard]] QString originalName() const;
[[nodiscard]] QString name() const;
[[nodiscard]] QString version() const;
void setName(QString name) { m_modified_name = name; }
void setName(InstanceName& other);
protected:
QString m_original_name;
QString m_original_version;
QString m_modified_name;
};
class InstanceTask : public Task, public InstanceName {
Q_OBJECT Q_OBJECT
public: public:
explicit InstanceTask(); InstanceTask();
virtual ~InstanceTask(); ~InstanceTask() override = default;
void setParentSettings(SettingsObjectPtr settings) void setParentSettings(SettingsObjectPtr settings) { m_globalSettings = settings; }
void setStagingPath(const QString& stagingPath) { m_stagingPath = stagingPath; }
void setIcon(const QString& icon) { m_instIcon = icon; }
void setGroup(const QString& group) { m_instGroup = group; }
QString group() const { return m_instGroup; }
[[nodiscard]] bool shouldConfirmUpdate() const { return m_confirm_update; }
void setConfirmUpdate(bool confirm) { m_confirm_update = confirm; }
bool shouldOverride() const { return m_override_existing; }
[[nodiscard]] QString originalInstanceID() const { return m_original_instance_id; };
protected:
void setOverride(bool override, QString instance_id_to_override = {})
{ {
m_globalSettings = settings; m_override_existing = override;
if (!instance_id_to_override.isEmpty())
m_original_instance_id = instance_id_to_override;
} }
void setStagingPath(const QString &stagingPath) protected: /* data */
{
m_stagingPath = stagingPath;
}
void setName(const QString &name)
{
m_instName = name;
}
QString name() const
{
return m_instName;
}
void setIcon(const QString &icon)
{
m_instIcon = icon;
}
void setGroup(const QString &group)
{
m_instGroup = group;
}
QString group() const
{
return m_instGroup;
}
protected: /* data */
SettingsObjectPtr m_globalSettings; SettingsObjectPtr m_globalSettings;
QString m_instName;
QString m_instIcon; QString m_instIcon;
QString m_instGroup; QString m_instGroup;
QString m_stagingPath; QString m_stagingPath;
bool m_override_existing = false;
bool m_confirm_update = true;
QString m_original_instance_id;
}; };

View File

@ -36,7 +36,7 @@
#include "JavaCommon.h" #include "JavaCommon.h"
#include "java/JavaUtils.h" #include "java/JavaUtils.h"
#include "ui/dialogs/CustomMessageBox.h" #include "ui/dialogs/CustomMessageBox.h"
#include <MMCStrings.h>
#include <QRegularExpression> #include <QRegularExpression>
bool JavaCommon::checkJVMArgs(QString jvmargs, QWidget *parent) bool JavaCommon::checkJVMArgs(QString jvmargs, QWidget *parent)
@ -122,8 +122,7 @@ void JavaCommon::TestCheck::run()
return; return;
} }
checker.reset(new JavaChecker()); checker.reset(new JavaChecker());
connect(checker.get(), SIGNAL(checkFinished(JavaCheckResult)), this, connect(checker.get(), &JavaChecker::checkFinished, this, &JavaCommon::TestCheck::checkFinished);
SLOT(checkFinished(JavaCheckResult)));
checker->m_path = m_path; checker->m_path = m_path;
checker->performCheck(); checker->performCheck();
} }
@ -137,8 +136,7 @@ void JavaCommon::TestCheck::checkFinished(JavaCheckResult result)
return; return;
} }
checker.reset(new JavaChecker()); checker.reset(new JavaChecker());
connect(checker.get(), SIGNAL(checkFinished(JavaCheckResult)), this, connect(checker.get(), &JavaChecker::checkFinished, this, &JavaCommon::TestCheck::checkFinishedWithArgs);
SLOT(checkFinishedWithArgs(JavaCheckResult)));
checker->m_path = m_path; checker->m_path = m_path;
checker->m_args = m_args; checker->m_args = m_args;
checker->m_minMem = m_minMem; checker->m_minMem = m_minMem;

View File

@ -93,8 +93,8 @@ void LaunchController::decideAccount()
auto reply = CustomMessageBox::selectable( auto reply = CustomMessageBox::selectable(
m_parentWidget, m_parentWidget,
tr("No Accounts"), tr("No Accounts"),
tr("In order to play Minecraft, you must have at least one Mojang or Microsoft " tr("In order to play Minecraft, you must have at least one Microsoft or Mojang "
"account logged in. " "account logged in. Mojang accounts can only be used offline. "
"Would you like to open the account manager to add an account now?"), "Would you like to open the account manager to add an account now?"),
QMessageBox::Information, QMessageBox::Information,
QMessageBox::Yes | QMessageBox::No QMessageBox::Yes | QMessageBox::No
@ -112,7 +112,15 @@ void LaunchController::decideAccount()
} }
} }
m_accountToUse = accounts->defaultAccount(); // Select the account to use. If the instance has a specific account set, that will be used. Otherwise, the default account will be used
auto instanceAccountId = m_instance->settings()->get("InstanceAccountId").toString();
auto instanceAccountIndex = accounts->findAccountByProfileId(instanceAccountId);
if (instanceAccountIndex == -1) {
m_accountToUse = accounts->defaultAccount();
} else {
m_accountToUse = accounts->at(instanceAccountIndex);
}
if (!m_accountToUse) if (!m_accountToUse)
{ {
// If no default account is set, ask the user which one to use. // If no default account is set, ask the user which one to use.
@ -145,18 +153,29 @@ void LaunchController::login() {
return; return;
} }
// we try empty password first :)
QString password;
// we loop until the user succeeds in logging in or gives up // we loop until the user succeeds in logging in or gives up
bool tryagain = true; bool tryagain = true;
// the failure. the default failure. unsigned int tries = 0;
const QString needLoginAgain = tr("Your account is currently not logged in. Please enter your password to log in again. <br /> <br /> This could be caused by a password change.");
QString failReason = needLoginAgain;
while (tryagain) while (tryagain)
{ {
if (tries > 0 && tries % 3 == 0) {
auto result = QMessageBox::question(
m_parentWidget,
tr("Continue launch?"),
tr("It looks like we couldn't launch after %1 tries. Do you want to continue trying?")
.arg(tries)
);
if (result == QMessageBox::No) {
emitAborted();
return;
}
}
tries++;
m_session = std::make_shared<AuthSession>(); m_session = std::make_shared<AuthSession>();
m_session->wants_online = m_online; m_session->wants_online = m_online;
m_session->demo = m_demo;
m_accountToUse->fillSession(m_session); m_accountToUse->fillSession(m_session);
// Launch immediately in true offline mode // Launch immediately in true offline mode
@ -174,12 +193,18 @@ void LaunchController::login() {
if(!m_session->wants_online) { if(!m_session->wants_online) {
// we ask the user for a player name // we ask the user for a player name
bool ok = false; bool ok = false;
QString message = tr("Choose your offline mode player name.");
if(m_session->demo) {
message = tr("Choose your demo mode player name.");
}
QString lastOfflinePlayerName = APPLICATION->settings()->get("LastOfflinePlayerName").toString(); QString lastOfflinePlayerName = APPLICATION->settings()->get("LastOfflinePlayerName").toString();
QString usedname = lastOfflinePlayerName.isEmpty() ? m_session->player_name : lastOfflinePlayerName; QString usedname = lastOfflinePlayerName.isEmpty() ? m_session->player_name : lastOfflinePlayerName;
QString name = QInputDialog::getText( QString name = QInputDialog::getText(
m_parentWidget, m_parentWidget,
tr("Player name"), tr("Player name"),
tr("Choose your offline mode player name."), message,
QLineEdit::Normal, QLineEdit::Normal,
usedname, usedname,
&ok &ok
@ -357,15 +382,15 @@ void LaunchController::launchInstance()
} }
resolved_servers = resolved_servers + "]\n\n"; resolved_servers = resolved_servers + "]\n\n";
} }
m_launcher->prependStep(new TextPrint(m_launcher.get(), resolved_servers, MessageLevel::Launcher)); m_launcher->prependStep(makeShared<TextPrint>(m_launcher.get(), resolved_servers, MessageLevel::Launcher));
} else { } else {
online_mode = "offline"; online_mode = m_demo ? "demo" : "offline";
} }
m_launcher->prependStep(new TextPrint(m_launcher.get(), "Launched instance in " + online_mode + " mode\n", MessageLevel::Launcher)); m_launcher->prependStep(makeShared<TextPrint>(m_launcher.get(), "Launched instance in " + online_mode + " mode\n", MessageLevel::Launcher));
// Prepend Version // Prepend Version
m_launcher->prependStep(new TextPrint(m_launcher.get(), BuildConfig.LAUNCHER_NAME + " version: " + BuildConfig.printableVersionString() + "\n\n", MessageLevel::Launcher)); m_launcher->prependStep(makeShared<TextPrint>(m_launcher.get(), BuildConfig.LAUNCHER_DISPLAYNAME + " version: " + BuildConfig.printableVersionString() + "\n\n", MessageLevel::Launcher));
m_launcher->start(); m_launcher->start();
} }

View File

@ -63,6 +63,10 @@ public:
m_online = online; m_online = online;
} }
void setDemo(bool demo) {
m_demo = demo;
}
void setProfiler(BaseProfilerFactory *profiler) { void setProfiler(BaseProfilerFactory *profiler) {
m_profiler = profiler; m_profiler = profiler;
} }
@ -101,6 +105,7 @@ private slots:
private: private:
BaseProfilerFactory *m_profiler = nullptr; BaseProfilerFactory *m_profiler = nullptr;
bool m_online = true; bool m_online = true;
bool m_demo = false;
InstancePtr m_instance; InstancePtr m_instance;
QWidget * m_parentWidget = nullptr; QWidget * m_parentWidget = nullptr;
InstanceWindow *m_console = nullptr; InstanceWindow *m_console = nullptr;

View File

@ -1,4 +1,4 @@
#!/bin/bash #!/usr/bin/env bash
# Basic start script for running the launcher with the libs packaged with it. # Basic start script for running the launcher with the libs packaged with it.
function printerror { function printerror {

View File

@ -1,7 +1,8 @@
// SPDX-License-Identifier: GPL-3.0-only // SPDX-License-Identifier: GPL-3.0-only
/* /*
* PolyMC - Minecraft Launcher * Prism Launcher - Minecraft Launcher
* Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net> * Copyright (C) 2022,2023 Sefa Eyeoglu <contact@scrumplex.net>
* Copyright (c) 2023 flowln <flowlnlnln@gmail.com>
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -34,20 +35,17 @@
*/ */
#include "LoggedProcess.h" #include "LoggedProcess.h"
#include "MessageLevel.h"
#include <QDebug> #include <QDebug>
#include <QTextDecoder>
#include "MessageLevel.h"
LoggedProcess::LoggedProcess(QObject *parent) : QProcess(parent) LoggedProcess::LoggedProcess(QObject *parent) : QProcess(parent)
{ {
// QProcess has a strange interface... let's map a lot of those into a few. // QProcess has a strange interface... let's map a lot of those into a few.
connect(this, &QProcess::readyReadStandardOutput, this, &LoggedProcess::on_stdOut); connect(this, &QProcess::readyReadStandardOutput, this, &LoggedProcess::on_stdOut);
connect(this, &QProcess::readyReadStandardError, this, &LoggedProcess::on_stdErr); connect(this, &QProcess::readyReadStandardError, this, &LoggedProcess::on_stdErr);
connect(this, SIGNAL(finished(int,QProcess::ExitStatus)), SLOT(on_exit(int,QProcess::ExitStatus))); connect(this, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished), this, &LoggedProcess::on_exit);
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) connect(this, &QProcess::errorOccurred, this, &LoggedProcess::on_error);
connect(this, SIGNAL(errorOccurred(QProcess::ProcessError)), this, SLOT(on_error(QProcess::ProcessError)));
#else
connect(this, SIGNAL(error(QProcess::ProcessError)), this, SLOT(on_error(QProcess::ProcessError)));
#endif
connect(this, &QProcess::stateChanged, this, &LoggedProcess::on_stateChange); connect(this, &QProcess::stateChanged, this, &LoggedProcess::on_stateChange);
} }
@ -59,25 +57,35 @@ LoggedProcess::~LoggedProcess()
} }
} }
QStringList reprocess(const QByteArray & data, QString & leftover) QStringList LoggedProcess::reprocess(const QByteArray& data, QTextDecoder& decoder)
{ {
QString str = leftover + QString::fromLocal8Bit(data); auto str = decoder.toUnicode(data);
str.remove('\r'); if (!m_leftover_line.isEmpty()) {
QStringList lines = str.split("\n"); str.prepend(m_leftover_line);
leftover = lines.takeLast(); m_leftover_line = "";
}
#if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
auto lines = str.remove(QChar::CarriageReturn).split(QChar::LineFeed, QString::SkipEmptyParts);
#else
auto lines = str.remove(QChar::CarriageReturn).split(QChar::LineFeed, Qt::SkipEmptyParts);
#endif
if (!str.endsWith(QChar::LineFeed))
m_leftover_line = lines.takeLast();
return lines; return lines;
} }
void LoggedProcess::on_stdErr() void LoggedProcess::on_stdErr()
{ {
auto lines = reprocess(readAllStandardError(), m_err_leftover); auto lines = reprocess(readAllStandardError(), m_err_decoder);
emit log(lines, MessageLevel::StdErr); emit log(lines, MessageLevel::StdErr);
} }
void LoggedProcess::on_stdOut() void LoggedProcess::on_stdOut()
{ {
auto lines = reprocess(readAllStandardOutput(), m_out_leftover); auto lines = reprocess(readAllStandardOutput(), m_out_decoder);
emit log(lines, MessageLevel::StdOut); emit log(lines, MessageLevel::StdOut);
} }
@ -86,18 +94,6 @@ void LoggedProcess::on_exit(int exit_code, QProcess::ExitStatus status)
// save the exit code // save the exit code
m_exit_code = exit_code; m_exit_code = exit_code;
// Flush console window
if (!m_err_leftover.isEmpty())
{
emit log({m_err_leftover}, MessageLevel::StdErr);
m_err_leftover.clear();
}
if (!m_out_leftover.isEmpty())
{
emit log({m_err_leftover}, MessageLevel::StdOut);
m_out_leftover.clear();
}
// based on state, send signals // based on state, send signals
if (!m_is_aborting) if (!m_is_aborting)
{ {

View File

@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-3.0-only // SPDX-License-Identifier: GPL-3.0-only
/* /*
* PolyMC - Minecraft Launcher * Prism Launcher - Minecraft Launcher
* Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net> * Copyright (C) 2022,2023 Sefa Eyeoglu <contact@scrumplex.net>
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -36,6 +36,7 @@
#pragma once #pragma once
#include <QProcess> #include <QProcess>
#include <QTextDecoder>
#include "MessageLevel.h" #include "MessageLevel.h"
/* /*
@ -87,9 +88,12 @@ private slots:
private: private:
void changeState(LoggedProcess::State state); void changeState(LoggedProcess::State state);
QStringList reprocess(const QByteArray& data, QTextDecoder& decoder);
private: private:
QString m_err_leftover; QTextDecoder m_err_decoder = QTextDecoder(QTextCodec::codecForLocale());
QString m_out_leftover; QTextDecoder m_out_decoder = QTextDecoder(QTextCodec::codecForLocale());
QString m_leftover_line;
bool m_killed = false; bool m_killed = false;
State m_state = NotRunning; State m_state = NotRunning;
int m_exit_code = 0; int m_exit_code = 0;

View File

@ -1,76 +0,0 @@
#include "MMCStrings.h"
/// TAKEN FROM Qt, because it doesn't expose it intelligently
static inline QChar getNextChar(const QString &s, int location)
{
return (location < s.length()) ? s.at(location) : QChar();
}
/// TAKEN FROM Qt, because it doesn't expose it intelligently
int Strings::naturalCompare(const QString &s1, const QString &s2, Qt::CaseSensitivity cs)
{
for (int l1 = 0, l2 = 0; l1 <= s1.count() && l2 <= s2.count(); ++l1, ++l2)
{
// skip spaces, tabs and 0's
QChar c1 = getNextChar(s1, l1);
while (c1.isSpace())
c1 = getNextChar(s1, ++l1);
QChar c2 = getNextChar(s2, l2);
while (c2.isSpace())
c2 = getNextChar(s2, ++l2);
if (c1.isDigit() && c2.isDigit())
{
while (c1.digitValue() == 0)
c1 = getNextChar(s1, ++l1);
while (c2.digitValue() == 0)
c2 = getNextChar(s2, ++l2);
int lookAheadLocation1 = l1;
int lookAheadLocation2 = l2;
int currentReturnValue = 0;
// find the last digit, setting currentReturnValue as we go if it isn't equal
for (QChar lookAhead1 = c1, lookAhead2 = c2;
(lookAheadLocation1 <= s1.length() && lookAheadLocation2 <= s2.length());
lookAhead1 = getNextChar(s1, ++lookAheadLocation1),
lookAhead2 = getNextChar(s2, ++lookAheadLocation2))
{
bool is1ADigit = !lookAhead1.isNull() && lookAhead1.isDigit();
bool is2ADigit = !lookAhead2.isNull() && lookAhead2.isDigit();
if (!is1ADigit && !is2ADigit)
break;
if (!is1ADigit)
return -1;
if (!is2ADigit)
return 1;
if (currentReturnValue == 0)
{
if (lookAhead1 < lookAhead2)
{
currentReturnValue = -1;
}
else if (lookAhead1 > lookAhead2)
{
currentReturnValue = 1;
}
}
}
if (currentReturnValue != 0)
return currentReturnValue;
}
if (cs == Qt::CaseInsensitive)
{
if (!c1.isLower())
c1 = c1.toLower();
if (!c2.isLower())
c2 = c2.toLower();
}
int r = QString::localeAwareCompare(c1, c2);
if (r < 0)
return -1;
if (r > 0)
return 1;
}
// The two strings are the same (02 == 2) so fall back to the normal sort
return QString::compare(s1, s2, cs);
}

View File

@ -1,8 +0,0 @@
#pragma once
#include <QString>
namespace Strings
{
int naturalCompare(const QString &s1, const QString &s2, Qt::CaseSensitivity cs);
}

View File

@ -18,6 +18,8 @@
#include <MMCTime.h> #include <MMCTime.h>
#include <QObject> #include <QObject>
#include <QDateTime>
#include <QTextStream>
QString Time::prettifyDuration(int64_t duration) { QString Time::prettifyDuration(int64_t duration) {
int seconds = (int) (duration % 60); int seconds = (int) (duration % 60);
@ -28,11 +30,73 @@ QString Time::prettifyDuration(int64_t duration) {
int days = (int) (duration / 24); int days = (int) (duration / 24);
if((hours == 0)&&(days == 0)) if((hours == 0)&&(days == 0))
{ {
return QObject::tr("%1m %2s").arg(minutes).arg(seconds); return QObject::tr("%1min %2s").arg(minutes).arg(seconds);
} }
if (days == 0) if (days == 0)
{ {
return QObject::tr("%1h %2m").arg(hours).arg(minutes); return QObject::tr("%1h %2min").arg(hours).arg(minutes);
} }
return QObject::tr("%1d %2h %3m").arg(days).arg(hours).arg(minutes); return QObject::tr("%1d %2h %3min").arg(days).arg(hours).arg(minutes);
} }
QString Time::humanReadableDuration(double duration, int precision) {
using days = std::chrono::duration<int, std::ratio<86400>>;
QString outStr;
QTextStream os(&outStr);
bool neg = false;
if (duration < 0) {
neg = true; // flag
duration *= -1; // invert
}
auto std_duration = std::chrono::duration<double>(duration);
auto d = std::chrono::duration_cast<days>(std_duration);
std_duration -= d;
auto h = std::chrono::duration_cast<std::chrono::hours>(std_duration);
std_duration -= h;
auto m = std::chrono::duration_cast<std::chrono::minutes>(std_duration);
std_duration -= m;
auto s = std::chrono::duration_cast<std::chrono::seconds>(std_duration);
std_duration -= s;
auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(std_duration);
auto dc = d.count();
auto hc = h.count();
auto mc = m.count();
auto sc = s.count();
auto msc = ms.count();
if (neg) {
os << '-';
}
if (dc) {
os << dc << QObject::tr("days");
}
if (hc) {
if (dc)
os << " ";
os << qSetFieldWidth(2) << hc << QObject::tr("h"); // hours
}
if (mc) {
if (dc || hc)
os << " ";
os << qSetFieldWidth(2) << mc << QObject::tr("m"); // minutes
}
if (dc || hc || mc || sc) {
if (dc || hc || mc)
os << " ";
os << qSetFieldWidth(2) << sc << QObject::tr("s"); // seconds
}
if ((msc && (precision > 0)) || !(dc || hc || mc || sc)) {
if (dc || hc || mc || sc)
os << " ";
os << qSetFieldWidth(0) << qSetRealNumberPrecision(precision) << msc << QObject::tr("ms"); // miliseconds
}
os.flush();
return outStr;
}

View File

@ -22,4 +22,13 @@ namespace Time {
QString prettifyDuration(int64_t duration); QString prettifyDuration(int64_t duration);
/**
* @brief Returns a string with short form time duration ie. `2days 1h3m4s56.0ms`.
* miliseconds are only included if `precision` is greater than 0.
*
* @param duration a number of seconds as floating point
* @param precision number of decmial points to display on fractons of a second, defualts to 0.
* @return QString
*/
QString humanReadableDuration(double duration, int precision = 0);
} }

View File

@ -39,6 +39,7 @@
#include "MMCZip.h" #include "MMCZip.h"
#include "FileSystem.h" #include "FileSystem.h"
#include <QCoreApplication>
#include <QDebug> #include <QDebug>
// ours // ours
@ -93,20 +94,28 @@ bool MMCZip::mergeZipFiles(QuaZip *into, QFileInfo from, QSet<QString> &containe
return true; return true;
} }
bool MMCZip::compressDirFiles(QuaZip *zip, QString dir, QFileInfoList files) bool MMCZip::compressDirFiles(QuaZip *zip, QString dir, QFileInfoList files, bool followSymlinks)
{ {
QDir directory(dir); QDir directory(dir);
if (!directory.exists()) return false; if (!directory.exists()) return false;
for (auto e : files) { for (auto e : files) {
auto filePath = directory.relativeFilePath(e.absoluteFilePath()); auto filePath = directory.relativeFilePath(e.absoluteFilePath());
if( !JlCompress::compressFile(zip, e.absoluteFilePath(), filePath)) return false; auto srcPath = e.absoluteFilePath();
if (followSymlinks) {
if (e.isSymLink()) {
srcPath = e.symLinkTarget();
} else {
srcPath = e.canonicalFilePath();
}
}
if( !JlCompress::compressFile(zip, srcPath, filePath)) return false;
} }
return true; return true;
} }
bool MMCZip::compressDirFiles(QString fileCompressed, QString dir, QFileInfoList files) bool MMCZip::compressDirFiles(QString fileCompressed, QString dir, QFileInfoList files, bool followSymlinks)
{ {
QuaZip zip(fileCompressed); QuaZip zip(fileCompressed);
QDir().mkpath(QFileInfo(fileCompressed).absolutePath()); QDir().mkpath(QFileInfo(fileCompressed).absolutePath());
@ -115,7 +124,7 @@ bool MMCZip::compressDirFiles(QString fileCompressed, QString dir, QFileInfoList
return false; return false;
} }
auto result = compressDirFiles(&zip, dir, files); auto result = compressDirFiles(&zip, dir, files, followSymlinks);
zip.close(); zip.close();
if(zip.getZipError()!=0) { if(zip.getZipError()!=0) {
@ -148,7 +157,7 @@ bool MMCZip::createModdedJar(QString sourceJarPath, QString targetJarPath, const
// do not merge disabled mods. // do not merge disabled mods.
if (!mod->enabled()) if (!mod->enabled())
continue; continue;
if (mod->type() == Mod::MOD_ZIPFILE) if (mod->type() == ResourceType::ZIPFILE)
{ {
if (!mergeZipFiles(&zipOut, mod->fileinfo(), addedFiles)) if (!mergeZipFiles(&zipOut, mod->fileinfo(), addedFiles))
{ {
@ -158,7 +167,7 @@ bool MMCZip::createModdedJar(QString sourceJarPath, QString targetJarPath, const
return false; return false;
} }
} }
else if (mod->type() == Mod::MOD_SINGLEFILE) else if (mod->type() == ResourceType::SINGLEFILE)
{ {
// FIXME: buggy - does not work with addedFiles // FIXME: buggy - does not work with addedFiles
auto filename = mod->fileinfo(); auto filename = mod->fileinfo();
@ -171,7 +180,7 @@ bool MMCZip::createModdedJar(QString sourceJarPath, QString targetJarPath, const
} }
addedFiles.insert(filename.fileName()); addedFiles.insert(filename.fileName());
} }
else if (mod->type() == Mod::MOD_FOLDER) else if (mod->type() == ResourceType::FOLDER)
{ {
// untested, but seems to be unused / not possible to reach // untested, but seems to be unused / not possible to reach
// FIXME: buggy - does not work with addedFiles // FIXME: buggy - does not work with addedFiles
@ -228,23 +237,27 @@ bool MMCZip::createModdedJar(QString sourceJarPath, QString targetJarPath, const
} }
// ours // ours
QString MMCZip::findFolderOfFileInZip(QuaZip * zip, const QString & what, const QString &root) QString MMCZip::findFolderOfFileInZip(QuaZip* zip, const QString& what, const QStringList& ignore_paths, const QString& root)
{ {
QuaZipDir rootDir(zip, root); QuaZipDir rootDir(zip, root);
for(auto fileName: rootDir.entryList(QDir::Files)) for (auto&& fileName : rootDir.entryList(QDir::Files)) {
{ if (fileName == what)
if(fileName == what)
return root; return root;
QCoreApplication::processEvents();
} }
for(auto fileName: rootDir.entryList(QDir::Dirs))
{ // Recurse the search to non-ignored subfolders
QString result = findFolderOfFileInZip(zip, what, root + fileName); for (auto&& fileName : rootDir.entryList(QDir::Dirs)) {
if(!result.isEmpty()) if (ignore_paths.contains(fileName))
{ continue;
QString result = findFolderOfFileInZip(zip, what, ignore_paths, root + fileName);
if (!result.isEmpty())
return result; return result;
}
} }
return QString();
return {};
} }
// ours // ours
@ -268,16 +281,17 @@ bool MMCZip::findFilesInZip(QuaZip * zip, const QString & what, QStringList & re
// ours // ours
nonstd::optional<QStringList> MMCZip::extractSubDir(QuaZip *zip, const QString & subdir, const QString &target) std::optional<QStringList> MMCZip::extractSubDir(QuaZip *zip, const QString & subdir, const QString &target)
{ {
QDir directory(target); auto target_top_dir = QUrl::fromLocalFile(target);
QStringList extracted; QStringList extracted;
qDebug() << "Extracting subdir" << subdir << "from" << zip->getZipName() << "to" << target; qDebug() << "Extracting subdir" << subdir << "from" << zip->getZipName() << "to" << target;
auto numEntries = zip->getEntriesCount(); auto numEntries = zip->getEntriesCount();
if(numEntries < 0) { if(numEntries < 0) {
qWarning() << "Failed to enumerate files in archive"; qWarning() << "Failed to enumerate files in archive";
return nonstd::nullopt; return std::nullopt;
} }
else if(numEntries == 0) { else if(numEntries == 0) {
qDebug() << "Extracting empty archives seems odd..."; qDebug() << "Extracting empty archives seems odd...";
@ -286,51 +300,56 @@ nonstd::optional<QStringList> MMCZip::extractSubDir(QuaZip *zip, const QString &
else if (!zip->goToFirstFile()) else if (!zip->goToFirstFile())
{ {
qWarning() << "Failed to seek to first file in zip"; qWarning() << "Failed to seek to first file in zip";
return nonstd::nullopt; return std::nullopt;
} }
do do {
{ QString file_name = zip->getCurrentFileName();
QString name = zip->getCurrentFileName(); if (!file_name.startsWith(subdir))
if(!name.startsWith(subdir))
{
continue; continue;
}
name.remove(0, subdir.size()); auto relative_file_name = QDir::fromNativeSeparators(file_name.remove(0, subdir.size()));
auto original_name = name; auto original_name = relative_file_name;
// Fix subdirs/files ending with a / getting transformed into absolute paths
if (relative_file_name.startsWith('/'))
relative_file_name = relative_file_name.mid(1);
// Fix weird "folders with a single file get squashed" thing // Fix weird "folders with a single file get squashed" thing
QString path; QString sub_path;
if(name.contains('/') && !name.endsWith('/')){ if (relative_file_name.contains('/') && !relative_file_name.endsWith('/')) {
path = name.section('/', 0, -2) + "/"; sub_path = relative_file_name.section('/', 0, -2) + '/';
FS::ensureFolderPathExists(FS::PathCombine(target, path)); FS::ensureFolderPathExists(FS::PathCombine(target, sub_path));
name = name.split('/').last(); relative_file_name = relative_file_name.split('/').last();
} }
QString absFilePath; QString target_file_path;
if(name.isEmpty()) if (relative_file_name.isEmpty()) {
{ target_file_path = target + '/';
absFilePath = directory.absoluteFilePath(name) + "/"; } else {
} target_file_path = FS::PathCombine(target_top_dir.toLocalFile(), sub_path, relative_file_name);
else if (relative_file_name.endsWith('/') && !target_file_path.endsWith('/'))
{ target_file_path += '/';
absFilePath = directory.absoluteFilePath(path + name);
} }
if (!JlCompress::extractFile(zip, "", absFilePath)) if (!target_top_dir.isParentOf(QUrl::fromLocalFile(target_file_path))) {
{ qWarning() << "Extracting" << relative_file_name << "was cancelled, because it was effectively outside of the target path" << target;
qWarning() << "Failed to extract file" << original_name << "to" << absFilePath; return std::nullopt;
}
if (!JlCompress::extractFile(zip, "", target_file_path)) {
qWarning() << "Failed to extract file" << original_name << "to" << target_file_path;
JlCompress::removeFile(extracted); JlCompress::removeFile(extracted);
return nonstd::nullopt; return std::nullopt;
} }
extracted.append(absFilePath); extracted.append(target_file_path);
QFile::setPermissions(absFilePath, QFileDevice::Permission::ReadUser | QFileDevice::Permission::WriteUser | QFileDevice::Permission::ExeUser); QFile::setPermissions(target_file_path, QFileDevice::Permission::ReadUser | QFileDevice::Permission::WriteUser | QFileDevice::Permission::ExeUser);
qDebug() << "Extracted file" << name << "to" << absFilePath; qDebug() << "Extracted file" << relative_file_name << "to" << target_file_path;
} while (zip->goToNextFile()); } while (zip->goToNextFile());
return extracted; return extracted;
} }
@ -341,7 +360,7 @@ bool MMCZip::extractRelFile(QuaZip *zip, const QString &file, const QString &tar
} }
// ours // ours
nonstd::optional<QStringList> MMCZip::extractDir(QString fileCompressed, QString dir) std::optional<QStringList> MMCZip::extractDir(QString fileCompressed, QString dir)
{ {
QuaZip zip(fileCompressed); QuaZip zip(fileCompressed);
if (!zip.open(QuaZip::mdUnzip)) if (!zip.open(QuaZip::mdUnzip))
@ -352,13 +371,13 @@ nonstd::optional<QStringList> MMCZip::extractDir(QString fileCompressed, QString
return QStringList(); return QStringList();
} }
qWarning() << "Could not open archive for unzipping:" << fileCompressed << "Error:" << zip.getZipError();; qWarning() << "Could not open archive for unzipping:" << fileCompressed << "Error:" << zip.getZipError();;
return nonstd::nullopt; return std::nullopt;
} }
return MMCZip::extractSubDir(&zip, "", dir); return MMCZip::extractSubDir(&zip, "", dir);
} }
// ours // ours
nonstd::optional<QStringList> MMCZip::extractDir(QString fileCompressed, QString subdir, QString dir) std::optional<QStringList> MMCZip::extractDir(QString fileCompressed, QString subdir, QString dir)
{ {
QuaZip zip(fileCompressed); QuaZip zip(fileCompressed);
if (!zip.open(QuaZip::mdUnzip)) if (!zip.open(QuaZip::mdUnzip))
@ -369,7 +388,7 @@ nonstd::optional<QStringList> MMCZip::extractDir(QString fileCompressed, QString
return QStringList(); return QStringList();
} }
qWarning() << "Could not open archive for unzipping:" << fileCompressed << "Error:" << zip.getZipError();; qWarning() << "Could not open archive for unzipping:" << fileCompressed << "Error:" << zip.getZipError();;
return nonstd::nullopt; return std::nullopt;
} }
return MMCZip::extractSubDir(&zip, subdir, dir); return MMCZip::extractSubDir(&zip, subdir, dir);
} }

View File

@ -42,7 +42,7 @@
#include <functional> #include <functional>
#include <quazip/JlCompress.h> #include <quazip/JlCompress.h>
#include <nonstd/optional> #include <optional>
namespace MMCZip namespace MMCZip
{ {
@ -59,18 +59,20 @@ namespace MMCZip
* \param zip target archive * \param zip target archive
* \param dir directory that will be compressed (to compress with relative paths) * \param dir directory that will be compressed (to compress with relative paths)
* \param files list of files to compress * \param files list of files to compress
* \param followSymlinks should follow symlinks when compressing file data
* \return true for success or false for failure * \return true for success or false for failure
*/ */
bool compressDirFiles(QuaZip *zip, QString dir, QFileInfoList files); bool compressDirFiles(QuaZip *zip, QString dir, QFileInfoList files, bool followSymlinks = false);
/** /**
* Compress directory, by providing a list of files to compress * Compress directory, by providing a list of files to compress
* \param fileCompressed target archive file * \param fileCompressed target archive file
* \param dir directory that will be compressed (to compress with relative paths) * \param dir directory that will be compressed (to compress with relative paths)
* \param files list of files to compress * \param files list of files to compress
* \param followSymlinks should follow symlinks when compressing file data
* \return true for success or false for failure * \return true for success or false for failure
*/ */
bool compressDirFiles(QString fileCompressed, QString dir, QFileInfoList files); bool compressDirFiles(QString fileCompressed, QString dir, QFileInfoList files, bool followSymlinks = false);
/** /**
* take a source jar, add mods to it, resulting in target jar * take a source jar, add mods to it, resulting in target jar
@ -80,9 +82,11 @@ namespace MMCZip
/** /**
* Find a single file in archive by file name (not path) * Find a single file in archive by file name (not path)
* *
* \param ignore_paths paths to skip when recursing the search
*
* \return the path prefix where the file is * \return the path prefix where the file is
*/ */
QString findFolderOfFileInZip(QuaZip * zip, const QString & what, const QString &root = QString("")); QString findFolderOfFileInZip(QuaZip * zip, const QString & what, const QStringList& ignore_paths = {}, const QString &root = QString(""));
/** /**
* Find a multiple files of the same name in archive by file name * Find a multiple files of the same name in archive by file name
@ -95,7 +99,7 @@ namespace MMCZip
/** /**
* Extract a subdirectory from an archive * Extract a subdirectory from an archive
*/ */
nonstd::optional<QStringList> extractSubDir(QuaZip *zip, const QString & subdir, const QString &target); std::optional<QStringList> extractSubDir(QuaZip *zip, const QString & subdir, const QString &target);
bool extractRelFile(QuaZip *zip, const QString & file, const QString &target); bool extractRelFile(QuaZip *zip, const QString & file, const QString &target);
@ -106,7 +110,7 @@ namespace MMCZip
* \param dir The directory to extract to, the current directory if left empty. * \param dir The directory to extract to, the current directory if left empty.
* \return The list of the full paths of the files extracted, empty on failure. * \return The list of the full paths of the files extracted, empty on failure.
*/ */
nonstd::optional<QStringList> extractDir(QString fileCompressed, QString dir); std::optional<QStringList> extractDir(QString fileCompressed, QString dir);
/** /**
* Extract a subdirectory from an archive * Extract a subdirectory from an archive
@ -116,7 +120,7 @@ namespace MMCZip
* \param dir The directory to extract to, the current directory if left empty. * \param dir The directory to extract to, the current directory if left empty.
* \return The list of the full paths of the files extracted, empty on failure. * \return The list of the full paths of the files extracted, empty on failure.
*/ */
nonstd::optional<QStringList> extractDir(QString fileCompressed, QString subdir, QString dir); std::optional<QStringList> extractDir(QString fileCompressed, QString subdir, QString dir);
/** /**
* Extract a single file from an archive into a directory * Extract a single file from an archive into a directory

95
launcher/MTPixmapCache.h Normal file
View File

@ -0,0 +1,95 @@
#pragma once
#include <QCoreApplication>
#include <QPixmapCache>
#include <QThread>
#define GET_TYPE() \
Qt::ConnectionType type; \
if (QThread::currentThread() != QCoreApplication::instance()->thread()) \
type = Qt::BlockingQueuedConnection; \
else \
type = Qt::DirectConnection;
#define DEFINE_FUNC_NO_PARAM(NAME, RET_TYPE) \
static RET_TYPE NAME() \
{ \
RET_TYPE ret; \
GET_TYPE() \
QMetaObject::invokeMethod(s_instance, "_" #NAME, type, Q_RETURN_ARG(RET_TYPE, ret)); \
return ret; \
}
#define DEFINE_FUNC_ONE_PARAM(NAME, RET_TYPE, PARAM_1_TYPE) \
static RET_TYPE NAME(PARAM_1_TYPE p1) \
{ \
RET_TYPE ret; \
GET_TYPE() \
QMetaObject::invokeMethod(s_instance, "_" #NAME, type, Q_RETURN_ARG(RET_TYPE, ret), Q_ARG(PARAM_1_TYPE, p1)); \
return ret; \
}
#define DEFINE_FUNC_TWO_PARAM(NAME, RET_TYPE, PARAM_1_TYPE, PARAM_2_TYPE) \
static RET_TYPE NAME(PARAM_1_TYPE p1, PARAM_2_TYPE p2) \
{ \
RET_TYPE ret; \
GET_TYPE() \
QMetaObject::invokeMethod(s_instance, "_" #NAME, type, Q_RETURN_ARG(RET_TYPE, ret), Q_ARG(PARAM_1_TYPE, p1), \
Q_ARG(PARAM_2_TYPE, p2)); \
return ret; \
}
/** A wrapper around QPixmapCache with thread affinity with the main thread.
*/
class PixmapCache final : public QObject {
Q_OBJECT
public:
PixmapCache(QObject* parent) : QObject(parent) {}
~PixmapCache() override = default;
static PixmapCache& instance() { return *s_instance; }
static void setInstance(PixmapCache* i) { s_instance = i; }
public:
DEFINE_FUNC_NO_PARAM(cacheLimit, int)
DEFINE_FUNC_NO_PARAM(clear, bool)
DEFINE_FUNC_TWO_PARAM(find, bool, const QString&, QPixmap*)
DEFINE_FUNC_TWO_PARAM(find, bool, const QPixmapCache::Key&, QPixmap*)
DEFINE_FUNC_TWO_PARAM(insert, bool, const QString&, const QPixmap&)
DEFINE_FUNC_ONE_PARAM(insert, QPixmapCache::Key, const QPixmap&)
DEFINE_FUNC_ONE_PARAM(remove, bool, const QString&)
DEFINE_FUNC_ONE_PARAM(remove, bool, const QPixmapCache::Key&)
DEFINE_FUNC_TWO_PARAM(replace, bool, const QPixmapCache::Key&, const QPixmap&)
DEFINE_FUNC_ONE_PARAM(setCacheLimit, bool, int)
// NOTE: Every function returns something non-void to simplify the macros.
private slots:
int _cacheLimit() { return QPixmapCache::cacheLimit(); }
bool _clear()
{
QPixmapCache::clear();
return true;
}
bool _find(const QString& key, QPixmap* pixmap) { return QPixmapCache::find(key, pixmap); }
bool _find(const QPixmapCache::Key& key, QPixmap* pixmap) { return QPixmapCache::find(key, pixmap); }
bool _insert(const QString& key, const QPixmap& pixmap) { return QPixmapCache::insert(key, pixmap); }
QPixmapCache::Key _insert(const QPixmap& pixmap) { return QPixmapCache::insert(pixmap); }
bool _remove(const QString& key)
{
QPixmapCache::remove(key);
return true;
}
bool _remove(const QPixmapCache::Key& key)
{
QPixmapCache::remove(key);
return true;
}
bool _replace(const QPixmapCache::Key& key, const QPixmap& pixmap) { return QPixmapCache::replace(key, pixmap); }
bool _setCacheLimit(int n)
{
QPixmapCache::setCacheLimit(n);
return true;
}
private:
static PixmapCache* s_instance;
};

109
launcher/MangoHud.cpp Normal file
View File

@ -0,0 +1,109 @@
// SPDX-License-Identifier: GPL-3.0-only
/*
* PrismLauncher - Minecraft Launcher
* Copyright (C) 2022 Jan Drögehoff <sentrycraft123@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/>.
*/
#include <QStringList>
#include <QDir>
#include <QString>
#include <QSysInfo>
#include <QtGlobal>
#include "MangoHud.h"
#include "FileSystem.h"
#include "Json.h"
namespace MangoHud {
QString getLibraryString()
{
/*
* Check for vulkan layers in this order:
*
* $VK_LAYER_PATH
* $XDG_DATA_DIRS (/usr/local/share/:/usr/share/)
* $XDG_DATA_HOME (~/.local/share)
* /etc
* $XDG_CONFIG_DIRS (/etc/xdg)
* $XDG_CONFIG_HOME (~/.config)
*/
QStringList vkLayerList;
{
QString home = QDir::homePath();
QString vkLayerPath = qEnvironmentVariable("VK_LAYER_PATH");
if (!vkLayerPath.isEmpty()) {
vkLayerList << vkLayerPath;
}
QStringList xdgDataDirs = qEnvironmentVariable("XDG_DATA_DIRS", "/usr/local/share/:/usr/share/").split(QLatin1String(":"));
for (QString dir : xdgDataDirs) {
vkLayerList << FS::PathCombine(dir, "vulkan", "implicit_layer.d");
}
QString xdgDataHome = qEnvironmentVariable("XDG_DATA_HOME");
if (xdgDataHome.isEmpty()) {
xdgDataHome = FS::PathCombine(home, ".local", "share");
}
vkLayerList << FS::PathCombine(xdgDataHome, "vulkan", "implicit_layer.d");
vkLayerList << "/etc";
QStringList xdgConfigDirs = qEnvironmentVariable("XDG_CONFIG_DIRS", "/etc/xdg").split(QLatin1String(":"));
for (QString dir : xdgConfigDirs) {
vkLayerList << FS::PathCombine(dir, "vulkan", "implicit_layer.d");
}
QString xdgConfigHome = qEnvironmentVariable("XDG_CONFIG_HOME");
if (xdgConfigHome.isEmpty()) {
xdgConfigHome = FS::PathCombine(home, ".config");
}
vkLayerList << FS::PathCombine(xdgConfigHome, "vulkan", "implicit_layer.d");
}
for (QString vkLayer : vkLayerList) {
// prefer to use architecture specific vulkan layers
QString currentArch = QSysInfo::currentCpuArchitecture();
if (currentArch == "arm64") {
currentArch = "aarch64";
}
QStringList manifestNames = { QString("MangoHud.%1.json").arg(currentArch), "MangoHud.json" };
QString filePath = "";
for (QString manifestName : manifestNames) {
QString tryPath = FS::PathCombine(vkLayer, manifestName);
if (QFile::exists(tryPath)) {
filePath = tryPath;
break;
}
}
if (filePath.isEmpty()) {
continue;
}
auto conf = Json::requireDocument(filePath, vkLayer);
auto confObject = Json::requireObject(conf, vkLayer);
auto layer = Json::ensureObject(confObject, "layer");
return Json::ensureString(layer, "library_path");
}
return QString();
}
} // namespace MangoHud

27
launcher/MangoHud.h Normal file
View File

@ -0,0 +1,27 @@
// SPDX-License-Identifier: GPL-3.0-only
/*
* PrismLauncher - Minecraft Launcher
* Copyright (C) 2022 Jan Drögehoff <sentrycraft123@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 <QString>
#include <QStringList>
namespace MangoHud {
QString getLibraryString();
}

34
launcher/Markdown.h Normal file
View File

@ -0,0 +1,34 @@
// SPDX-License-Identifier: GPL-3.0-only
/*
* Prism Launcher - Minecraft Launcher
* Copyright (C) 2023 Joshua Goins <josh@redstrate.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#pragma once
#include <QString>
#include <cmark.h>
static QString markdownToHTML(const QString& markdown)
{
const QByteArray markdownData = markdown.toUtf8();
char* buffer = cmark_markdown_to_html(markdownData.constData(), markdownData.length(), CMARK_OPT_NOBREAKS | CMARK_OPT_UNSAFE);
QString htmlStr(buffer);
free(buffer);
return htmlStr;
}

View File

@ -1,72 +0,0 @@
// SPDX-License-Identifier: GPL-3.0-only
/*
* PolyMC - Minecraft Launcher
* Copyright (c) 2022 flowln <flowlnlnln@gmail.com>
* Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net>
*
* 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 "ModDownloadTask.h"
#include "Application.h"
#include "minecraft/mod/ModFolderModel.h"
ModDownloadTask::ModDownloadTask(ModPlatform::IndexedPack mod, ModPlatform::IndexedVersion version, const std::shared_ptr<ModFolderModel> mods, bool is_indexed)
: m_mod(mod), m_mod_version(version), mods(mods)
{
if (is_indexed) {
m_update_task.reset(new LocalModUpdateTask(mods->indexDir(), m_mod, m_mod_version));
connect(m_update_task.get(), &LocalModUpdateTask::hasOldMod, this, &ModDownloadTask::hasOldMod);
addTask(m_update_task);
}
m_filesNetJob.reset(new NetJob(tr("Mod download"), APPLICATION->network()));
m_filesNetJob->setStatus(tr("Downloading mod:\n%1").arg(m_mod_version.downloadUrl));
m_filesNetJob->addNetAction(Net::Download::makeFile(m_mod_version.downloadUrl, mods->dir().absoluteFilePath(getFilename())));
connect(m_filesNetJob.get(), &NetJob::succeeded, this, &ModDownloadTask::downloadSucceeded);
connect(m_filesNetJob.get(), &NetJob::progress, this, &ModDownloadTask::downloadProgressChanged);
connect(m_filesNetJob.get(), &NetJob::failed, this, &ModDownloadTask::downloadFailed);
addTask(m_filesNetJob);
}
void ModDownloadTask::downloadSucceeded()
{
m_filesNetJob.reset();
auto name = std::get<0>(to_delete);
auto filename = std::get<1>(to_delete);
if (!name.isEmpty() && filename != m_mod_version.fileName) {
mods->uninstallMod(filename, true);
}
}
void ModDownloadTask::downloadFailed(QString reason)
{
emitFailed(reason);
m_filesNetJob.reset();
}
void ModDownloadTask::downloadProgressChanged(qint64 current, qint64 total)
{
emit progress(current, total);
}
// This indirection is done so that we don't delete a mod before being sure it was
// downloaded successfully!
void ModDownloadTask::hasOldMod(QString name, QString filename)
{
to_delete = {name, filename};
}

View File

@ -1,57 +0,0 @@
// SPDX-License-Identifier: GPL-3.0-only
/*
* PolyMC - Minecraft Launcher
* Copyright (c) 2022 flowln <flowlnlnln@gmail.com>
* Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net>
*
* 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 "net/NetJob.h"
#include "tasks/SequentialTask.h"
#include "modplatform/ModIndex.h"
#include "minecraft/mod/tasks/LocalModUpdateTask.h"
class ModFolderModel;
class ModDownloadTask : public SequentialTask {
Q_OBJECT
public:
explicit ModDownloadTask(ModPlatform::IndexedPack mod, ModPlatform::IndexedVersion version, const std::shared_ptr<ModFolderModel> mods, bool is_indexed = true);
const QString& getFilename() const { return m_mod_version.fileName; }
private:
ModPlatform::IndexedPack m_mod;
ModPlatform::IndexedVersion m_mod_version;
const std::shared_ptr<ModFolderModel> mods;
NetJob::Ptr m_filesNetJob;
LocalModUpdateTask::Ptr m_update_task;
void downloadProgressChanged(qint64 current, qint64 total);
void downloadFailed(QString reason);
void downloadSucceeded();
std::tuple<QString, QString> to_delete {"", ""};
private slots:
void hasOldMod(QString name, QString filename);
};

View File

@ -1,3 +1,38 @@
// SPDX-License-Identifier: GPL-3.0-only
/*
* PolyMC - Minecraft Launcher
* Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net>
*
* 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 #pragma once
#include "BaseInstance.h" #include "BaseInstance.h"
#include "launch/LaunchTask.h" #include "launch/LaunchTask.h"
@ -15,6 +50,10 @@ public:
void saveNow() override void saveNow() override
{ {
} }
void loadSpecificSettings() override
{
setSpecificSettingsLoaded(true);
}
QString getStatusbarDescription() override QString getStatusbarDescription() override
{ {
return tr("Unknown instance type"); return tr("Unknown instance type");
@ -43,7 +82,7 @@ public:
{ {
return QProcessEnvironment(); return QProcessEnvironment();
} }
QMap<QString, QString> getVariables() const override QMap<QString, QString> getVariables() override
{ {
return QMap<QString, QString>(); return QMap<QString, QString>();
} }
@ -80,4 +119,8 @@ public:
QString modsRoot() const override { QString modsRoot() const override {
return QString(); return QString();
} }
void updateRuntimeContext()
{
// NOOP
}
}; };

View File

@ -1,91 +1,53 @@
#pragma once #pragma once
#include <QObject>
#include <QSharedPointer>
#include <functional> #include <functional>
#include <memory> #include <memory>
#include <QObject>
namespace details
{
struct DeleteQObjectLater
{
void operator()(QObject *obj) const
{
obj->deleteLater();
}
};
}
/** /**
* A unique pointer class with unique pointer semantics intended for derivates of QObject * A unique pointer class with unique pointer semantics intended for derivates of QObject
* Calls deleteLater() instead of destroying the contained object immediately * Calls deleteLater() instead of destroying the contained object immediately
*/ */
template<typename T> using unique_qobject_ptr = std::unique_ptr<T, details::DeleteQObjectLater>; template <typename T>
using unique_qobject_ptr = QScopedPointer<T, QScopedPointerDeleteLater>;
/** /**
* A shared pointer class with shared pointer semantics intended for derivates of QObject * A shared pointer class with shared pointer semantics intended for derivates of QObject
* Calls deleteLater() instead of destroying the contained object immediately * Calls deleteLater() instead of destroying the contained object immediately
*/ */
template <typename T> template <typename T>
class shared_qobject_ptr class shared_qobject_ptr : public QSharedPointer<T> {
{ public:
public: constexpr explicit shared_qobject_ptr() : QSharedPointer<T>() {}
shared_qobject_ptr(){} constexpr explicit shared_qobject_ptr(T* ptr) : QSharedPointer<T>(ptr, &QObject::deleteLater) {}
shared_qobject_ptr(T * wrap) constexpr shared_qobject_ptr(std::nullptr_t null_ptr) : QSharedPointer<T>(null_ptr, &QObject::deleteLater) {}
{
reset(wrap);
}
shared_qobject_ptr(const shared_qobject_ptr<T>& other)
{
m_ptr = other.m_ptr;
}
template<typename Derived>
shared_qobject_ptr(const shared_qobject_ptr<Derived> &other)
{
m_ptr = other.unwrap();
}
public: template <typename Derived>
void reset(T * wrap) constexpr shared_qobject_ptr(const shared_qobject_ptr<Derived>& other) : QSharedPointer<T>(other)
{ {}
using namespace std::placeholders;
m_ptr.reset(wrap, std::bind(&QObject::deleteLater, _1));
}
void reset(const shared_qobject_ptr<T> &other)
{
m_ptr = other.m_ptr;
}
void reset()
{
m_ptr.reset();
}
T * get() const
{
return m_ptr.get();
}
T * operator->() const
{
return m_ptr.get();
}
T & operator*() const
{
return *m_ptr.get();
}
operator bool() const
{
return m_ptr.get() != nullptr;
}
const std::shared_ptr <T> unwrap() const
{
return m_ptr;
}
template<typename U>
bool operator==(const shared_qobject_ptr<U>& other) const {
return m_ptr == other.m_ptr;
}
template<typename U>
bool operator!=(const shared_qobject_ptr<U>& other) const {
return m_ptr != other.m_ptr;
}
private: template <typename Derived>
std::shared_ptr <T> m_ptr; constexpr shared_qobject_ptr(const QSharedPointer<Derived>& other) : QSharedPointer<T>(other)
{}
void reset() { QSharedPointer<T>::reset(); }
void reset(T*&& other)
{
shared_qobject_ptr<T> t(other);
this->swap(t);
}
void reset(const shared_qobject_ptr<T>& other)
{
shared_qobject_ptr<T> t(other);
this->swap(t);
}
}; };
template <typename T, typename... Args>
shared_qobject_ptr<T> makeShared(Args... args)
{
auto obj = new T(args...);
return shared_qobject_ptr<T>(obj);
}

View File

@ -1,7 +1,8 @@
// SPDX-License-Identifier: GPL-3.0-only // SPDX-License-Identifier: GPL-3.0-only
/* /*
* PolyMC - Minecraft Launcher * Prism Launcher - Minecraft Launcher
* Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net> * Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net>
* Copyright (C) 2023 flowln <flowlnlnln@gmail.com>
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -35,27 +36,35 @@
#pragma once #pragma once
#include "modplatform/ModAPI.h"
#include "ui/pages/modplatform/ModPage.h"
#include "modplatform/flame/FlameAPI.h" #include <QVariant>
#include <QList>
class FlameModPage : public ModPage { namespace QVariantUtils {
Q_OBJECT
public: template <typename T>
explicit FlameModPage(ModDownloadDialog* dialog, BaseInstance* instance); inline QList<T> toList(QVariant src) {
~FlameModPage() override = default; QVariantList variantList = src.toList();
inline auto displayName() const -> QString override { return "CurseForge"; } QList<T> list_t;
inline auto icon() const -> QIcon override { return APPLICATION->getThemedIcon("flame"); } list_t.reserve(variantList.size());
inline auto id() const -> QString override { return "curseforge"; } for (const QVariant& v : variantList)
inline auto helpPage() const -> QString override { return "Mod-platform"; } {
list_t.append(v.value<T>());
}
return list_t;
}
inline auto debugName() const -> QString override { return "Flame"; } template <typename T>
inline auto metaEntryBase() const -> QString override { return "FlameMods"; }; inline QVariant fromList(QList<T> val) {
QVariantList variantList;
variantList.reserve(val.size());
for (const T& v : val)
{
variantList.append(v);
}
auto validateVersion(ModPlatform::IndexedVersion& ver, QString mineVer, ModAPI::ModLoaderTypes loaders = ModAPI::Unspecified) const -> bool override; return variantList;
}
auto shouldDisplay() const -> bool override; }
};

View File

@ -0,0 +1,92 @@
// SPDX-License-Identifier: GPL-3.0-only
/*
* Prism Launcher - Minecraft Launcher
* Copyright (c) 2022-2023 flowln <flowlnlnln@gmail.com>
* Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net>
*
* 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 "ResourceDownloadTask.h"
#include "Application.h"
#include "minecraft/mod/ModFolderModel.h"
#include "minecraft/mod/ResourceFolderModel.h"
ResourceDownloadTask::ResourceDownloadTask(ModPlatform::IndexedPack::Ptr pack,
ModPlatform::IndexedVersion version,
const std::shared_ptr<ResourceFolderModel> packs,
bool is_indexed,
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);
addTask(m_update_task);
}
m_filesNetJob.reset(new NetJob(tr("Resource download"), APPLICATION->network()));
m_filesNetJob->setStatus(tr("Downloading resource:\n%1").arg(m_pack_version.downloadUrl));
QDir dir{ m_pack_model->dir() };
{
// FIXME: Make this more generic. May require adding additional info to IndexedVersion,
// or adquiring a reference to the base instance.
if (!m_custom_target_folder.isEmpty()) {
dir.cdUp();
dir.cd(m_custom_target_folder);
}
}
m_filesNetJob->addNetAction(Net::Download::makeFile(m_pack_version.downloadUrl, dir.absoluteFilePath(getFilename())));
connect(m_filesNetJob.get(), &NetJob::succeeded, this, &ResourceDownloadTask::downloadSucceeded);
connect(m_filesNetJob.get(), &NetJob::progress, this, &ResourceDownloadTask::downloadProgressChanged);
connect(m_filesNetJob.get(), &NetJob::stepProgress, this, &ResourceDownloadTask::propogateStepProgress);
connect(m_filesNetJob.get(), &NetJob::failed, this, &ResourceDownloadTask::downloadFailed);
addTask(m_filesNetJob);
}
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);
}
}
void ResourceDownloadTask::downloadFailed(QString reason)
{
emitFailed(reason);
m_filesNetJob.reset();
}
void ResourceDownloadTask::downloadProgressChanged(qint64 current, qint64 total)
{
emit progress(current, total);
}
// This indirection is done so that we don't delete a mod before being sure it was
// downloaded successfully!
void ResourceDownloadTask::hasOldResource(QString name, QString filename)
{
to_delete = { name, filename };
}

View File

@ -0,0 +1,61 @@
// SPDX-License-Identifier: GPL-3.0-only
/*
* Prism Launcher - Minecraft Launcher
* Copyright (c) 2022-2023 flowln <flowlnlnln@gmail.com>
* Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net>
*
* 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 "net/NetJob.h"
#include "tasks/SequentialTask.h"
#include "minecraft/mod/tasks/LocalModUpdateTask.h"
#include "modplatform/ModIndex.h"
class ResourceFolderModel;
class ResourceDownloadTask : public SequentialTask {
Q_OBJECT
public:
explicit ResourceDownloadTask(ModPlatform::IndexedPack::Ptr pack,
ModPlatform::IndexedVersion version,
const std::shared_ptr<ResourceFolderModel> packs,
bool is_indexed = true,
QString custom_target_folder = {});
const QString& getFilename() const { return m_pack_version.fileName; }
const QString& getCustomPath() const { return m_custom_target_folder; }
const QVariant& getVersionID() const { return m_pack_version.fileId; }
const QString& getName() const { return m_pack->name; }
ModPlatform::IndexedPack::Ptr getPack() { return m_pack; }
private:
ModPlatform::IndexedPack::Ptr m_pack;
ModPlatform::IndexedVersion m_pack_version;
const std::shared_ptr<ResourceFolderModel> m_pack_model;
QString m_custom_target_folder;
NetJob::Ptr m_filesNetJob;
LocalModUpdateTask::Ptr m_update_task;
void downloadProgressChanged(qint64 current, qint64 total);
void downloadFailed(QString reason);
void downloadSucceeded();
std::tuple<QString, QString> to_delete{ "", "" };
private slots:
void hasOldResource(QString name, QString filename);
};

88
launcher/RuntimeContext.h Normal file
View File

@ -0,0 +1,88 @@
// SPDX-License-Identifier: GPL-3.0-only
/*
* PolyMC - Minecraft Launcher
* Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net>
*
* 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 <QSet>
#include <QString>
#include "settings/SettingsObject.h"
struct RuntimeContext {
QString javaArchitecture;
QString javaRealArchitecture;
QString javaPath;
QString system;
QString mappedJavaRealArchitecture() const
{
if (javaRealArchitecture == "amd64")
return "x86_64";
if (javaRealArchitecture == "i386" || javaRealArchitecture == "i686")
return "x86";
if (javaRealArchitecture == "aarch64")
return "arm64";
if (javaRealArchitecture == "arm" || javaRealArchitecture == "armhf")
return "arm32";
return javaRealArchitecture;
}
void updateFromInstanceSettings(SettingsObjectPtr instanceSettings)
{
javaArchitecture = instanceSettings->get("JavaArchitecture").toString();
javaRealArchitecture = instanceSettings->get("JavaRealArchitecture").toString();
javaPath = instanceSettings->get("JavaPath").toString();
system = currentSystem();
}
QString getClassifier() const { return system + "-" + mappedJavaRealArchitecture(); }
// "Legacy" refers to the fact that Mojang assumed that these are the only two architectures
bool isLegacyArch() const
{
const QString mapped = mappedJavaRealArchitecture();
return mapped == "x86_64" || mapped == "x86";
}
bool classifierMatches(QString target) const
{
// try to match precise classifier "[os]-[arch]"
bool x = target == getClassifier();
// try to match imprecise classifier on legacy architectures "[os]"
if (!x && isLegacyArch())
x = target == system;
return x;
}
static QString currentSystem()
{
#if defined(Q_OS_LINUX)
return "linux";
#elif defined(Q_OS_MACOS)
return "osx";
#elif defined(Q_OS_WINDOWS)
return "windows";
#elif defined(Q_OS_FREEBSD)
return "freebsd";
#elif defined(Q_OS_OPENBSD)
return "openbsd";
#else
return "unknown";
#endif
}
};

184
launcher/StringUtils.cpp Normal file
View File

@ -0,0 +1,184 @@
// SPDX-License-Identifier: GPL-3.0-only
/*
* Prism Launcher - Minecraft Launcher
* Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net>
* Copyright (C) 2023 flowln <flowlnlnln@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/>.
*
* 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 "StringUtils.h"
#include <QRegularExpression>
#include <QUuid>
#include <cmath>
/// If you're wondering where these came from exactly, then know you're not the only one =D
/// TAKEN FROM Qt, because it doesn't expose it intelligently
static inline QChar getNextChar(const QString& s, int location)
{
return (location < s.length()) ? s.at(location) : QChar();
}
/// TAKEN FROM Qt, because it doesn't expose it intelligently
int StringUtils::naturalCompare(const QString& s1, const QString& s2, Qt::CaseSensitivity cs)
{
int l1 = 0, l2 = 0;
while (l1 <= s1.count() && l2 <= s2.count()) {
// skip spaces, tabs and 0's
QChar c1 = getNextChar(s1, l1);
while (c1.isSpace())
c1 = getNextChar(s1, ++l1);
QChar c2 = getNextChar(s2, l2);
while (c2.isSpace())
c2 = getNextChar(s2, ++l2);
if (c1.isDigit() && c2.isDigit()) {
while (c1.digitValue() == 0)
c1 = getNextChar(s1, ++l1);
while (c2.digitValue() == 0)
c2 = getNextChar(s2, ++l2);
int lookAheadLocation1 = l1;
int lookAheadLocation2 = l2;
int currentReturnValue = 0;
// find the last digit, setting currentReturnValue as we go if it isn't equal
for (QChar lookAhead1 = c1, lookAhead2 = c2; (lookAheadLocation1 <= s1.length() && lookAheadLocation2 <= s2.length());
lookAhead1 = getNextChar(s1, ++lookAheadLocation1), lookAhead2 = getNextChar(s2, ++lookAheadLocation2)) {
bool is1ADigit = !lookAhead1.isNull() && lookAhead1.isDigit();
bool is2ADigit = !lookAhead2.isNull() && lookAhead2.isDigit();
if (!is1ADigit && !is2ADigit)
break;
if (!is1ADigit)
return -1;
if (!is2ADigit)
return 1;
if (currentReturnValue == 0) {
if (lookAhead1 < lookAhead2) {
currentReturnValue = -1;
} else if (lookAhead1 > lookAhead2) {
currentReturnValue = 1;
}
}
}
if (currentReturnValue != 0)
return currentReturnValue;
}
if (cs == Qt::CaseInsensitive) {
if (!c1.isLower())
c1 = c1.toLower();
if (!c2.isLower())
c2 = c2.toLower();
}
int r = QString::localeAwareCompare(c1, c2);
if (r < 0)
return -1;
if (r > 0)
return 1;
l1 += 1;
l2 += 1;
}
// The two strings are the same (02 == 2) so fall back to the normal sort
return QString::compare(s1, s2, cs);
}
QString StringUtils::truncateUrlHumanFriendly(QUrl& url, int max_len, bool hard_limit)
{
auto display_options = QUrl::RemoveUserInfo | QUrl::RemoveFragment | QUrl::NormalizePathSegments;
auto str_url = url.toDisplayString(display_options);
if (str_url.length() <= max_len)
return str_url;
auto url_path_parts = url.path().split('/');
QString last_path_segment = url_path_parts.takeLast();
if (url_path_parts.size() >= 1 && url_path_parts.first().isEmpty())
url_path_parts.removeFirst(); // drop empty first segment (from leading / )
if (url_path_parts.size() >= 1)
url_path_parts.removeLast(); // drop the next to last path segment
auto url_template = QStringLiteral("%1://%2/%3%4");
auto url_compact = url_path_parts.isEmpty()
? url_template.arg(url.scheme(), url.host(), QStringList({ "...", last_path_segment }).join('/'), url.query())
: url_template.arg(url.scheme(), url.host(),
QStringList({ url_path_parts.join('/'), "...", last_path_segment }).join('/'), url.query());
// remove url parts one by one if it's still too long
while (url_compact.length() > max_len && url_path_parts.size() >= 1) {
url_path_parts.removeLast(); // drop the next to last path segment
url_compact = url_path_parts.isEmpty()
? url_template.arg(url.scheme(), url.host(), QStringList({ "...", last_path_segment }).join('/'), url.query())
: url_template.arg(url.scheme(), url.host(),
QStringList({ url_path_parts.join('/'), "...", last_path_segment }).join('/'), url.query());
}
if ((url_compact.length() >= max_len) && hard_limit) {
// still too long, truncate normaly
url_compact = QString(str_url);
auto to_remove = url_compact.length() - max_len + 3;
url_compact.remove(url_compact.length() - to_remove - 1, to_remove);
url_compact.append("...");
}
return url_compact;
}
static const QStringList s_units_si{ "KB", "MB", "GB", "TB" };
static const QStringList s_units_kibi{ "KiB", "MiB", "GiB", "TiB" };
QString StringUtils::humanReadableFileSize(double bytes, bool use_si, int decimal_points)
{
const QStringList units = use_si ? s_units_si : s_units_kibi;
const int scale = use_si ? 1000 : 1024;
int u = -1;
double r = pow(10, decimal_points);
do {
bytes /= scale;
u++;
} while (round(abs(bytes) * r) / r >= scale && u < units.length() - 1);
return QString::number(bytes, 'f', 2) + " " + units[u];
}
QString StringUtils::getRandomAlphaNumeric()
{
return QUuid::createUuid().toString(QUuid::Id128);
}

82
launcher/StringUtils.h Normal file
View File

@ -0,0 +1,82 @@
// SPDX-License-Identifier: GPL-3.0-only
/*
* Prism Launcher - Minecraft Launcher
* Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net>
* Copyright (C) 2023 flowln <flowlnlnln@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/>.
*
* 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 <QString>
#include <QUrl>
namespace StringUtils {
#if defined Q_OS_WIN32
using string = std::wstring;
inline string toStdString(QString s)
{
return s.toStdWString();
}
inline QString fromStdString(string s)
{
return QString::fromStdWString(s);
}
#else
using string = std::string;
inline string toStdString(QString s)
{
return s.toStdString();
}
inline QString fromStdString(string s)
{
return QString::fromStdString(s);
}
#endif
int naturalCompare(const QString& s1, const QString& s2, Qt::CaseSensitivity cs);
/**
* @brief Truncate a url while keeping its readability py placing the `...` in the middle of the path
* @param url Url to truncate
* @param max_len max lenght of url in charaters
* @param hard_limit if truncating the path can't get the url short enough, truncate it normaly.
*/
QString truncateUrlHumanFriendly(QUrl &url, int max_len, bool hard_limit = false);
QString humanReadableFileSize(double bytes, bool use_si = false, int decimal_points = 1);
QString getRandomAlphaNumeric();
} // namespace StringUtils

View File

@ -1,443 +0,0 @@
#include <QFile>
#include <QMessageBox>
#include <FileSystem.h>
#include <updater/GoUpdate.h>
#include "UpdateController.h"
#include <QApplication>
#include <thread>
#include <chrono>
#include <LocalPeer.h>
#include "BuildConfig.h"
// from <sys/stat.h>
#ifndef S_IRUSR
#define __S_IREAD 0400 /* Read by owner. */
#define __S_IWRITE 0200 /* Write by owner. */
#define __S_IEXEC 0100 /* Execute by owner. */
#define S_IRUSR __S_IREAD /* Read by owner. */
#define S_IWUSR __S_IWRITE /* Write by owner. */
#define S_IXUSR __S_IEXEC /* Execute by owner. */
#define S_IRGRP (S_IRUSR >> 3) /* Read by group. */
#define S_IWGRP (S_IWUSR >> 3) /* Write by group. */
#define S_IXGRP (S_IXUSR >> 3) /* Execute by group. */
#define S_IROTH (S_IRGRP >> 3) /* Read by others. */
#define S_IWOTH (S_IWGRP >> 3) /* Write by others. */
#define S_IXOTH (S_IXGRP >> 3) /* Execute by others. */
#endif
static QFile::Permissions unixModeToPermissions(const int mode)
{
QFile::Permissions perms;
if (mode & S_IRUSR)
{
perms |= QFile::ReadUser;
}
if (mode & S_IWUSR)
{
perms |= QFile::WriteUser;
}
if (mode & S_IXUSR)
{
perms |= QFile::ExeUser;
}
if (mode & S_IRGRP)
{
perms |= QFile::ReadGroup;
}
if (mode & S_IWGRP)
{
perms |= QFile::WriteGroup;
}
if (mode & S_IXGRP)
{
perms |= QFile::ExeGroup;
}
if (mode & S_IROTH)
{
perms |= QFile::ReadOther;
}
if (mode & S_IWOTH)
{
perms |= QFile::WriteOther;
}
if (mode & S_IXOTH)
{
perms |= QFile::ExeOther;
}
return perms;
}
static const QLatin1String liveCheckFile("live.check");
UpdateController::UpdateController(QWidget * parent, const QString& root, const QString updateFilesDir, GoUpdate::OperationList operations)
{
m_parent = parent;
m_root = root;
m_updateFilesDir = updateFilesDir;
m_operations = operations;
}
void UpdateController::installUpdates()
{
qint64 pid = -1;
QStringList args;
bool started = false;
qDebug() << "Installing updates.";
#ifdef Q_OS_WIN
QString finishCmd = QApplication::applicationFilePath();
#elif defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD) || defined (Q_OS_OPENBSD)
QString finishCmd = FS::PathCombine(m_root, BuildConfig.LAUNCHER_NAME);
#elif defined Q_OS_MAC
QString finishCmd = QApplication::applicationFilePath();
#else
#error Unsupported operating system.
#endif
QString backupPath = FS::PathCombine(m_root, "update", "backup");
QDir origin(m_root);
// clean up the backup folder. it should be empty before we start
if(!FS::deletePath(backupPath))
{
qWarning() << "couldn't remove previous backup folder" << backupPath;
}
// and it should exist.
if(!FS::ensureFolderPathExists(backupPath))
{
qWarning() << "couldn't create folder" << backupPath;
return;
}
bool useXPHack = false;
QString exePath;
QString exeOrigin;
QString exeBackup;
// perform the update operations
for(auto op: m_operations)
{
switch(op.type)
{
// replace = move original out to backup, if it exists, move the new file in its place
case GoUpdate::Operation::OP_REPLACE:
{
#ifdef Q_OS_WIN32
QString windowsExeName = BuildConfig.LAUNCHER_NAME + ".exe";
// hack for people renaming the .exe because ... reasons :)
if(op.destination == windowsExeName)
{
op.destination = QFileInfo(QApplication::applicationFilePath()).fileName();
}
#endif
QFileInfo destination (FS::PathCombine(m_root, op.destination));
if(destination.exists())
{
QString backupName = op.destination;
backupName.replace('/', '_');
QString backupFilePath = FS::PathCombine(backupPath, backupName);
if(!QFile::rename(destination.absoluteFilePath(), backupFilePath))
{
qWarning() << "Couldn't move:" << destination.absoluteFilePath() << "to" << backupFilePath;
m_failedOperationType = Replace;
m_failedFile = op.destination;
fail();
return;
}
BackupEntry be;
be.original = destination.absoluteFilePath();
be.backup = backupFilePath;
be.update = op.source;
m_replace_backups.append(be);
}
// make sure the folder we are putting this into exists
if(!FS::ensureFilePathExists(destination.absoluteFilePath()))
{
qWarning() << "REPLACE: Couldn't create folder:" << destination.absoluteFilePath();
m_failedOperationType = Replace;
m_failedFile = op.destination;
fail();
return;
}
// now move the new file in
if(!QFile::rename(op.source, destination.absoluteFilePath()))
{
qWarning() << "REPLACE: Couldn't move:" << op.source << "to" << destination.absoluteFilePath();
m_failedOperationType = Replace;
m_failedFile = op.destination;
fail();
return;
}
QFile::setPermissions(destination.absoluteFilePath(), unixModeToPermissions(op.destinationMode));
}
break;
// delete = move original to backup
case GoUpdate::Operation::OP_DELETE:
{
QString destFilePath = FS::PathCombine(m_root, op.destination);
if(QFile::exists(destFilePath))
{
QString backupName = op.destination;
backupName.replace('/', '_');
QString trashFilePath = FS::PathCombine(backupPath, backupName);
if(!QFile::rename(destFilePath, trashFilePath))
{
qWarning() << "DELETE: Couldn't move:" << op.destination << "to" << trashFilePath;
m_failedFile = op.destination;
m_failedOperationType = Delete;
fail();
return;
}
BackupEntry be;
be.original = destFilePath;
be.backup = trashFilePath;
m_delete_backups.append(be);
}
}
break;
}
}
// try to start the new binary
args = qApp->arguments();
args.removeFirst();
// on old Windows, do insane things... no error checking here, this is just to have something.
if(useXPHack)
{
QString script;
auto nativePath = QDir::toNativeSeparators(exePath);
auto nativeOriginPath = QDir::toNativeSeparators(exeOrigin);
auto nativeBackupPath = QDir::toNativeSeparators(exeBackup);
// so we write this vbscript thing...
QTextStream out(&script);
out << "WScript.Sleep 1000\n";
out << "Set fso=CreateObject(\"Scripting.FileSystemObject\")\n";
out << "Set shell=CreateObject(\"WScript.Shell\")\n";
out << "fso.MoveFile \"" << nativePath << "\", \"" << nativeBackupPath << "\"\n";
out << "fso.MoveFile \"" << nativeOriginPath << "\", \"" << nativePath << "\"\n";
out << "shell.Run \"" << nativePath << "\"\n";
QString scriptPath = FS::PathCombine(m_root, "update", "update.vbs");
// we save it
QFile scriptFile(scriptPath);
scriptFile.open(QIODevice::WriteOnly);
scriptFile.write(script.toLocal8Bit().replace("\n", "\r\n"));
scriptFile.close();
// we run it
started = QProcess::startDetached("wscript", {scriptPath}, m_root);
// and we quit. conscious thought.
qApp->quit();
return;
}
bool doLiveCheck = true;
bool startFailed = false;
// remove live check file, if any
if(QFile::exists(liveCheckFile))
{
if(!QFile::remove(liveCheckFile))
{
qWarning() << "Couldn't remove the" << liveCheckFile << "file! We will proceed without :(";
doLiveCheck = false;
}
}
if(doLiveCheck)
{
if(!args.contains("--alive"))
{
args.append("--alive");
}
}
// FIXME: reparse args and construct a safe variant from scratch. This is a workaround for GH-1874:
QStringList realargs;
int skip = 0;
for(auto & arg: args)
{
if(skip)
{
skip--;
continue;
}
if(arg == "-l")
{
skip = 1;
continue;
}
realargs.append(arg);
}
// start the updated application
started = QProcess::startDetached(finishCmd, realargs, QDir::currentPath(), &pid);
// much dumber check - just find out if the call
if(!started || pid == -1)
{
qWarning() << "Couldn't start new process properly!";
startFailed = true;
}
if(!startFailed && doLiveCheck)
{
int attempts = 0;
while(attempts < 10)
{
attempts++;
QString key;
std::this_thread::sleep_for(std::chrono::milliseconds(250));
if(!QFile::exists(liveCheckFile))
{
qWarning() << "Couldn't find the" << liveCheckFile << "file!";
startFailed = true;
continue;
}
try
{
key = QString::fromUtf8(FS::read(liveCheckFile));
auto id = ApplicationId::fromRawString(key);
LocalPeer peer(nullptr, id);
if(peer.isClient())
{
startFailed = false;
qDebug() << "Found process started with key " << key;
break;
}
else
{
startFailed = true;
qDebug() << "Process started with key " << key << "apparently died or is not reponding...";
break;
}
}
catch (const Exception &e)
{
qWarning() << "Couldn't read the" << liveCheckFile << "file!";
startFailed = true;
continue;
}
}
}
if(startFailed)
{
m_failedOperationType = Start;
fail();
return;
}
else
{
origin.rmdir(m_updateFilesDir);
qApp->quit();
return;
}
}
void UpdateController::fail()
{
qWarning() << "Update failed!";
QString msg;
bool doRollback = false;
QString failTitle = QObject::tr("Update failed!");
QString rollFailTitle = QObject::tr("Rollback failed!");
switch (m_failedOperationType)
{
case Replace:
{
msg = QObject::tr(
"Couldn't replace file %1. Changes will be reverted.\n"
"See the %2 log file for details."
).arg(m_failedFile, BuildConfig.LAUNCHER_NAME);
doRollback = true;
QMessageBox::critical(m_parent, failTitle, msg);
break;
}
case Delete:
{
msg = QObject::tr(
"Couldn't remove file %1. Changes will be reverted.\n"
"See the %2 log file for details."
).arg(m_failedFile, BuildConfig.LAUNCHER_NAME);
doRollback = true;
QMessageBox::critical(m_parent, failTitle, msg);
break;
}
case Start:
{
msg = QObject::tr("The new version didn't start or is too old and doesn't respond to startup checks.\n"
"\n"
"Roll back to previous version?");
auto result = QMessageBox::critical(
m_parent,
failTitle,
msg,
QMessageBox::Yes | QMessageBox::No,
QMessageBox::Yes
);
doRollback = (result == QMessageBox::Yes);
break;
}
case Nothing:
default:
return;
}
if(doRollback)
{
auto rollbackOK = rollback();
if(!rollbackOK)
{
msg = QObject::tr("The rollback failed too.\n"
"You will have to repair %1 manually.\n"
"Please let us know why and how this happened.").arg(BuildConfig.LAUNCHER_NAME);
QMessageBox::critical(m_parent, rollFailTitle, msg);
qApp->quit();
}
}
else
{
qApp->quit();
}
}
bool UpdateController::rollback()
{
bool revertOK = true;
// if the above failed, roll back changes
for(auto backup:m_replace_backups)
{
qWarning() << "restoring" << backup.original << "from" << backup.backup;
if(!QFile::rename(backup.original, backup.update))
{
revertOK = false;
qWarning() << "moving new" << backup.original << "back to" << backup.update << "failed!";
continue;
}
if(!QFile::rename(backup.backup, backup.original))
{
revertOK = false;
qWarning() << "restoring" << backup.original << "failed!";
}
}
for(auto backup:m_delete_backups)
{
qWarning() << "restoring" << backup.original << "from" << backup.backup;
if(!QFile::rename(backup.backup, backup.original))
{
revertOK = false;
qWarning() << "restoring" << backup.original << "failed!";
}
}
return revertOK;
}

View File

@ -1,44 +0,0 @@
#pragma once
#include <QString>
#include <QList>
#include <updater/GoUpdate.h>
class QWidget;
class UpdateController
{
public:
UpdateController(QWidget * parent, const QString &root, const QString updateFilesDir, GoUpdate::OperationList operations);
void installUpdates();
private:
void fail();
bool rollback();
private:
QString m_root;
QString m_updateFilesDir;
GoUpdate::OperationList m_operations;
QWidget * m_parent;
struct BackupEntry
{
// path where we got the new file from
QString update;
// path of what is being actually updated
QString original;
// path where the backup of the updated file was placed
QString backup;
};
QList <BackupEntry> m_replace_backups;
QList <BackupEntry> m_delete_backups;
enum Failure
{
Replace,
Delete,
Start,
Nothing
} m_failedOperationType = Nothing;
QString m_failedFile;
};

View File

@ -1,85 +1,128 @@
#include "Version.h" #include "Version.h"
#include <QStringList> #include <QDebug>
#include <QUrl>
#include <QRegularExpression> #include <QRegularExpression>
#include <QRegularExpressionMatch> #include <QRegularExpressionMatch>
#include <QUrl>
Version::Version(const QString &str) : m_string(str) Version::Version(QString str) : m_string(std::move(str))
{ {
parse(); parse();
} }
bool Version::operator<(const Version &other) const #define VERSION_OPERATOR(return_on_different) \
{ bool exclude_our_sections = false; \
const int size = qMax(m_sections.size(), other.m_sections.size()); bool exclude_their_sections = false; \
for (int i = 0; i < size; ++i) \
{ const auto size = qMax(m_sections.size(), other.m_sections.size()); \
const Section sec1 = (i >= m_sections.size()) ? Section("0") : m_sections.at(i); for (int i = 0; i < size; ++i) { \
const Section sec2 = Section sec1 = (i >= m_sections.size()) ? Section() : m_sections.at(i); \
(i >= other.m_sections.size()) ? Section("0") : other.m_sections.at(i); Section sec2 = (i >= other.m_sections.size()) ? Section() : other.m_sections.at(i); \
if (sec1 != sec2) \
{ { /* Don't include appendixes in the comparison */ \
return sec1 < sec2; if (sec1.isAppendix()) \
} exclude_our_sections = true; \
if (sec2.isAppendix()) \
exclude_their_sections = true; \
\
if (exclude_our_sections) { \
sec1 = Section(); \
if (sec2.m_isNull) \
break; \
} \
\
if (exclude_their_sections) { \
sec2 = Section(); \
if (sec1.m_isNull) \
break; \
} \
} \
\
if (sec1 != sec2) \
return return_on_different; \
} }
bool Version::operator<(const Version& other) const
{
VERSION_OPERATOR(sec1 < sec2)
return false; return false;
} }
bool Version::operator<=(const Version &other) const bool Version::operator==(const Version& other) const
{ {
return *this < other || *this == other; VERSION_OPERATOR(false)
}
bool Version::operator>(const Version &other) const
{
const int size = qMax(m_sections.size(), other.m_sections.size());
for (int i = 0; i < size; ++i)
{
const Section sec1 = (i >= m_sections.size()) ? Section("0") : m_sections.at(i);
const Section sec2 =
(i >= other.m_sections.size()) ? Section("0") : other.m_sections.at(i);
if (sec1 != sec2)
{
return sec1 > sec2;
}
}
return false;
}
bool Version::operator>=(const Version &other) const
{
return *this > other || *this == other;
}
bool Version::operator==(const Version &other) const
{
const int size = qMax(m_sections.size(), other.m_sections.size());
for (int i = 0; i < size; ++i)
{
const Section sec1 = (i >= m_sections.size()) ? Section("0") : m_sections.at(i);
const Section sec2 =
(i >= other.m_sections.size()) ? Section("0") : other.m_sections.at(i);
if (sec1 != sec2)
{
return false;
}
}
return true; return true;
} }
bool Version::operator!=(const Version &other) const bool Version::operator!=(const Version& other) const
{ {
return !operator==(other); return !operator==(other);
} }
bool Version::operator<=(const Version& other) const
{
return *this < other || *this == other;
}
bool Version::operator>(const Version& other) const
{
return !(*this <= other);
}
bool Version::operator>=(const Version& other) const
{
return !(*this < other);
}
void Version::parse() void Version::parse()
{ {
m_sections.clear(); m_sections.clear();
QString currentSection;
// FIXME: this is bad. versions can contain a lot more separators... if (m_string.isEmpty())
QStringList parts = m_string.split('.'); return;
for (const auto& part : parts) auto classChange = [&](QChar lastChar, QChar currentChar) {
{ if (lastChar.isNull())
m_sections.append(Section(part)); return false;
if (lastChar.isDigit() != currentChar.isDigit())
return true;
const QList<QChar> s_separators{ '.', '-', '+' };
if (s_separators.contains(currentChar) && currentSection.at(0) != currentChar)
return true;
return false;
};
currentSection += m_string.at(0);
for (int i = 1; i < m_string.size(); ++i) {
const auto& current_char = m_string.at(i);
if (classChange(m_string.at(i - 1), current_char)) {
if (!currentSection.isEmpty())
m_sections.append(Section(currentSection));
currentSection = "";
}
currentSection += current_char;
} }
if (!currentSection.isEmpty())
m_sections.append(Section(currentSection));
}
/// qDebug print support for the Version class
QDebug operator<<(QDebug debug, const Version& v)
{
QDebugStateSaver saver(debug);
debug.nospace() << "Version{ string: " << v.toString() << ", sections: [ ";
bool first = true;
for (auto s : v.m_sections) {
if (!first) debug.nospace() << ", ";
debug.nospace() << s.m_fullString;
first = false;
}
debug.nospace() << " ]" << " }";
return debug;
} }

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