Compare commits

...

399 Commits
1.0.5 ... 1.1.1

Author SHA1 Message Date
bd60c54911 Merge pull request #314 from Scrumplex/chore-bump-1.1.1
Bump to 1.1.1
2022-03-26 10:55:33 +01:00
a9d935f9ef Merge pull request #337 from oynqr/misc/create-vendored-tarball 2022-03-24 11:16:39 +01:00
eb06d0116f Merge pull request #334 from flowln/right_file_2
Fix skipping file in mod version parsing
2022-03-24 11:10:11 +01:00
6025cd0ca5 Merge pull request #330 from DioEgizio/notportable
bring back not portable windows builds
2022-03-22 20:11:15 +01:00
ce05ce92bb Merge pull request #322 from oynqr/build/static-rainbow
Build with static rainbow
2022-03-22 20:11:15 +01:00
a5fc640f2c Merge pull request #298 from Scrumplex/fix-i18n
Fix translatable strings
2022-03-22 20:11:15 +01:00
0a4a3fece5 Merge pull request #323 from Scrumplex/retranslate-pages
Retranslate all settings pages
2022-03-22 20:11:15 +01:00
fcf728f3b5 Merge pull request #315 from txtsd/display_scaling
Allow fractional DPI scaling
2022-03-22 20:11:15 +01:00
cd4851c98b Merge pull request #311 from DioEgizio/patch-2
fix webp
2022-03-22 20:11:15 +01:00
3db5f30403 Merge pull request #316 from Scrumplex/fix-disabled-controls 2022-03-22 20:11:15 +01:00
58957122b9 Merge pull request #306 from Scrumplex/limit-instance-lengths
Limit instance names to 128 chars
2022-03-22 20:11:15 +01:00
8b46658b05 Merge pull request #294 from oynqr/msys2
Switch to msys2 for Windows builds
2022-03-22 20:11:15 +01:00
571e322d66 Merge pull request #200 from Scrumplex/scrumplex-license-header 2022-03-22 20:11:15 +01:00
ddda02f092 Merge pull request #292 from lack/offline_username_limits
Limit offline username to 16 characters with override
2022-03-22 20:11:15 +01:00
bf6fa6bce4 Merge pull request #295 from Scrumplex/fix-portable
Make Launcher_PORTABLE work on all platforms
2022-03-22 20:11:15 +01:00
025a3cf730 Merge pull request #296 from flowln/right_file
Use primary file for mod downloading on Modrinth
2022-03-22 20:11:15 +01:00
6d9eaee7f9 Merge pull request #297 from DioEgizio/patch-1
bundle jre8u312 instead of latest on appimage
2022-03-22 20:11:15 +01:00
7471ce4530 Merge pull request #299 from flowln/paste_serv
Remove paste.polymc.org
2022-03-22 20:11:15 +01:00
149ffb844f Merge pull request #278 from Scrumplex/fix-copying
Clarify GPL-3.0-only
2022-03-22 20:11:15 +01:00
4cf3ac42c8 Merge pull request #280 from oynqr/gitdir-notfound-check
Add GITDIR-NOTFOUND check
2022-03-22 20:11:15 +01:00
d16c6b0e69 Merge pull request #265 from Scrumplex/fix-javacheck-appimage
Define JARs path relative to application root
2022-03-22 20:11:15 +01:00
76e1aba58b Merge pull request #273 from DioEgizio/extra-rebranding-macos
extra rebranding for macos
2022-03-22 20:11:15 +01:00
c560d06b8d Merge pull request #270 from flowln/dialog
Make a better "Mod download confirmation dialog"
2022-03-22 20:11:15 +01:00
0681568d3e Merge pull request #254 from Scrumplex/fix-update-metainfo
Update metainfo URLs
2022-03-22 20:11:15 +01:00
9f8983b570 Merge pull request #235 from Scrumplex/chore-bump-1.1.0
Bump to 1.1.0
2022-03-12 13:34:36 +00:00
e42c5b00a4 Merge pull request #251 from flowln/fix_tr 2022-03-12 10:58:36 +01:00
a3d7ad731d fix missing translation strings
my mistake, sorry! ToT
2022-03-11 18:43:17 -03:00
dc98609ef8 Merge pull request #241 from PolyMC/ZekeSmith-move-to-wiki-1 2022-03-11 10:42:13 +01:00
c799faaca6 fix: typos 2022-03-11 09:21:59 +01:00
07e4c4d189 Merge pull request #242 from deadmeu/develop
Fix missing space in "No Accounts" message
2022-03-11 14:53:05 +11:00
c4a8fd353c Merge pull request #243 from dada513/mx_button 2022-03-10 18:52:57 +01:00
91524d6d6e Merge pull request #247 from txtsd/actions_fix
Fix Ubuntu system Qt failure
2022-03-10 23:45:32 +11:00
c1201997a3 Fix Ubuntu system Qt failure 2022-03-10 13:38:16 +05:30
d814e21f0d add matrix button 2022-03-08 18:41:23 +01:00
49d122a2c4 Fix missing space in "No Accounts" message 2022-03-08 23:24:11 +10:00
0813eba367 Update BUILD.md 2022-03-08 19:09:54 +10:00
dc9e250868 Merge pull request #232 from Scrumplex/fix-help-links
Switch to polymc.org wiki
2022-03-08 01:22:34 +11:00
b6cf0359fa Merge pull request #230 from Scrumplex/fix-iconthemes
Reorganize icon themes
2022-03-08 01:20:35 +11:00
ae39d16c11 chore: bump to 1.1.0 2022-03-06 11:40:11 +01:00
b93daf1fb7 fix: update news links to point to polymc.org 2022-03-06 11:32:06 +01:00
6545d250e8 refactor: move help URL into buildconfig 2022-03-06 11:31:50 +01:00
b162351ff4 fix: switch to polymc.org wiki 2022-03-05 21:49:13 +01:00
53468ea474 Merge pull request #221 from flowln/install_button 2022-03-05 20:43:44 +01:00
3697d70b48 fix: reorganize icon themes
Rename MultiMC to Legacy
Simple (Colored) is now the first icon theme
Custom is now the last icon theme, which also fixes a loading issue when
Legacy was selected
Fix loading of Legacy theme
2022-03-05 20:29:54 +01:00
e0c025b162 fix extra spacing in resource packs and shader packs, and move button up
hopefully now its finally ok
2022-03-03 09:51:46 -03:00
9e443faba3 hack: hide 'Download Mods' button when not in the mods tab 2022-03-03 04:02:22 -03:00
f95cebaf06 change 'Install Mods' -> 'Download Mods' and change position 2022-03-03 01:10:10 -03:00
ca211558b5 Merge pull request #216 from txtsd/ignore_paths
Don't build when updating non-code
2022-03-02 11:48:45 +11:00
3a03f90831 Ignore certain paths for CI 2022-03-02 01:17:08 +05:30
9020f632b2 Merge pull request #214 from PolyMC/ZekeSmith-newReadme
Modify readme to use website
2022-03-01 16:56:41 +01:00
8bdd2befe9 Merge pull request #205 from timoreo22/fix-version-select
Fixed wrong version info
2022-03-01 16:56:10 +01:00
ebececf8c6 Update and link latest build to actions 2022-03-01 23:19:30 +10:00
e1f28be151 Merge pull request #163 from txtsd/windows_data_dir
Replace build layouts with Launcher_PORTABLE cmake flag
2022-03-02 00:03:31 +11:00
10231aa404 Modify readme to use website 2022-03-01 10:33:59 +10:00
139ff82432 Merge pull request #207 from flowln/curseforge_api 2022-02-28 13:35:58 +01:00
4e8f075ff3 fix: Do not loop when its not a fabric mod on Flame version validation
Since there's no validation for forge mods since the start, we were just
looping with no porpuse in this situation.
2022-02-27 22:02:43 -03:00
148775b3e9 Update FMLLIBS_BASE_URL
Updated FMLLIBS_BASE_URL to https://files.polymc.org/fmllibs/

Fixes #208
2022-02-27 19:40:52 +00:00
075d900d45 fix: Always tell Flame API which modloader we are using
Fixes #206 partially. Although we don't list mods that have no
compatibility with the mod loader we are using, mods that have support
for both loaders still show up, and the versions for both the loaders
are still shown.

Also simplifies a little the logic in
FlameModIndex::loadIndexedPackVersions
2022-02-27 16:07:45 -03:00
5d1ca33b84 Apply suggestions from code review
Co-authored-by: LennyMcLennington <lenny@sneed.church>
2022-02-27 08:35:47 -08:00
ccc493cb2b Cleanly free NetJob in flame modpack 2022-02-27 13:14:12 +01:00
2745325ae0 Fixed wrong version info 2022-02-27 11:55:24 +01:00
84e9ce71b0 Merge pull request #203 from glowiak/patch-4 2022-02-27 09:53:56 +01:00
88fc1e32ee Merge pull request #201 from Scrumplex/fix-instancetype-reregistration 2022-02-26 14:37:27 +01:00
4f975bfb04 Notify about needed AppBSD version 2022-02-26 13:04:35 +01:00
692b9cf0e0 Merge pull request #195 from babbaj/nix-refactor
nix: Use POLYMC_JAVA_PATHS
2022-02-26 07:34:19 +01:00
ae354688c9 Merge pull request #193 from flowln/develop
Allow for downloading multiple mods at once
2022-02-26 07:33:11 +01:00
c9bf7f9896 fix: load instances no matter their instance type 2022-02-26 00:31:37 +01:00
e8929599a5 nix: Use POLYMC_JAVA_PATHS 2022-02-25 16:47:47 -05:00
27f37315f8 Merge pull request #199 from Scrumplex/fix-translations 2022-02-25 17:47:08 +01:00
c4f4e9e620 merge upstream and resolve conflicts 2022-02-25 13:43:27 -03:00
f2b850ad20 Merge pull request #183 from timoreo22/fix-versions-segfault
Fixed segfault in mod download
2022-02-26 01:55:11 +11:00
ccc27d1b7c Merge pull request #192 from Scrumplex/refactor-remove-legacy-instances
Drop legacy instances
2022-02-26 01:54:15 +11:00
4835ec3f6d fix(i18n): update translations URL 2022-02-25 15:19:15 +01:00
40a9828fba fix: improve readability and set ok button as disabled by default 2022-02-23 19:17:33 -03:00
04840d0638 fix(ui): add translation func to text in the confirm dialog 2022-02-23 14:44:55 -03:00
38f12c50f7 Merge branch 'PolyMC:develop' into develop 2022-02-23 14:34:51 -03:00
ca8b62291f fix: use legacy data path if it exists 2022-02-23 16:22:53 +05:30
69d01204e0 Implement PR suggestions 2022-02-23 16:22:53 +05:30
1e3b896fda Replace layouts with LAUNCH_PORTABLE 2022-02-23 16:22:23 +05:30
9e35560554 Merge pull request #158 from txtsd/actions
CI: Release builds and workflow
2022-02-23 10:36:47 +01:00
f9d4751ec0 Use System Qt for generic Linux build 2022-02-22 20:40:16 +05:30
a66e6a413f Merge pull request #169 from Scrumplex/rfc-template
Add issue template for RFCs
2022-02-23 00:10:09 +10:00
2c911a5475 Merge pull request #174 from dada513/readme_better
Prepare readme for 1.1.0, mark unofficial packages as unofficial
2022-02-23 00:09:56 +10:00
e2c2a38005 Merge pull request #186 from theglitch76-forks/develop
Enable WSL support
2022-02-22 08:23:57 +01:00
aa4a6bb3be Merge pull request #172 from Scrumplex/fix-update-client-id
Switch to new MSA Client ID
2022-02-22 08:23:42 +01:00
4af020161d Merge pull request #180 from Scrumplex/feat-msa-clientid-detection
Detect MSA Client ID change
2022-02-22 08:23:28 +01:00
f8b0d6453a fix: sort mod list in confirmation dialog 2022-02-21 23:25:33 -03:00
0102e91940 feat: add confirm dialog for installing mods
When selecting multiple mods at once, it can become hard to keep track
of which ones you selected.

To address this, a dialog is now displayed
when you finish selecting the mods to download, showing you which ones
you selected and their filenames. From there, you can either accept it
and download the mods, or you can cancel it and go back to the mod
selection dialog.
2022-02-21 23:09:14 -03:00
1004211a66 fix(ui): change text in selection button when there's no valid version 2022-02-21 22:52:50 -03:00
f5cf4eb45f feat(ui): allow downloading multiple mods from CurseForge at once 2022-02-21 21:53:21 -03:00
512395e3f1 feat(ui): allow downloading multiple mods in Modrinth at once 2022-02-21 21:34:53 -03:00
9c6727e27f feat: change task container in ModDownloadDialog to a QHash
Previously, we used a unique_ptr to a ModDownloadTask to keep track of
the selected mod to download when we accepted the dialog.

In order to allow multiple mods to be selected at once for download,
this has been changed to a QHash where the key is the mods name (since
it doesn't seem right to allow for multiple versions of the same mod to
be downloaded at once), and the value is a pointer to the corresponding
ModDownloadTask.
2022-02-21 21:34:06 -03:00
624ab25cd4 refactor: set default InstanceType to OneSix 2022-02-21 22:59:07 +01:00
a70d1f1a91 refactor: drop LegacyInstance 2022-02-21 22:30:44 +01:00
3059f13011 refactor: drop migration for pre-component instances 2022-02-21 22:11:10 +01:00
d3e7d30ee0 Create releases in a separate workflow 2022-02-21 21:48:31 +05:30
5bbb4f31dc Add generic Linux system builds 2022-02-21 21:48:31 +05:30
8556ff5eac Revert ba6a97557a0d90d77e9eba560931414e39042447
Let evil win.
2022-02-20 15:00:23 -06:00
adacab3349 Fixed segfault when closing window while version info download is still going 2022-02-19 15:17:45 +01:00
613b351f13 Merge pull request #168 from Kloenk/nix_flake_meta
Nix flake meta
2022-02-19 08:25:30 +01:00
80a29af497 fix: typo for account disabled error messages 2022-02-18 19:18:29 +01:00
7e1fad55d9 Merge pull request #178 from Scrumplex/add-contributor-covenant
Add Contributor Covenant 2.1
2022-02-19 00:09:59 +10:00
9b7cd029a7 Grab short version 2022-02-18 19:27:15 +05:30
c5d9944993 feat(accounts): interrupt MSAStep when client ID doesn't match 2022-02-18 12:32:24 +01:00
14717396eb feat(accounts): save client id in MSAStep 2022-02-18 12:32:24 +01:00
9c71f364d2 feat(accounts): add disabled account state 2022-02-18 12:32:24 +01:00
be910374dc feat(accounts): support msa-client-id value 2022-02-18 12:32:24 +01:00
10de75623e readd all packages 2022-02-18 10:28:17 +01:00
7fc55b58fe chore: clarify trolling in code of conduct 2022-02-18 09:44:27 +01:00
12c8a04458 Merge pull request #173 from Scrumplex/fix-application-cpp
fix: improve code readability in Application.cpp
2022-02-17 23:43:59 +00:00
796e58b6f2 Merge pull request #176 from PolyMC/upstream-merge
upstream merge
2022-02-17 23:34:50 +00:00
a7d37fa69a chore: add Contributor Covenant 2022-02-17 23:55:34 +01:00
7b4b997a34 Merge remote-tracking branch 'upstream/develop' into develop 2022-02-17 15:47:43 -05:00
6b4469c6cc fix: combine errors if --launch is missing 2022-02-17 15:29:09 +01:00
107a0ea852 fix2 2022-02-17 13:19:35 +01:00
6d7676202f unofficial => community maintained 2022-02-17 12:53:44 +01:00
0305b7a1fd Prepare readme for 1.1.0, mark unofficial packages as unofficial 2022-02-17 11:55:09 +01:00
02384f81c7 Merge pull request #131 from glowiak/patch-1
Add Slackware package
2022-02-17 11:32:17 +01:00
4536b19512 Merge pull request #171 from DioEgizio/fix-org.polymc-macos
Change: set MACOSX_BUNDLE_GUI_IDENTIFIER to org.polymc (fixes org.multimc.PolyMC)
2022-02-16 21:07:50 +01:00
45f89c6255 Merge branch 'develop' into patch-1 2022-02-16 18:36:28 +01:00
b1cf77e847 update 2022-02-16 18:31:34 +01:00
037b0d7190 fix: improve code readability in Application.cpp 2022-02-16 17:33:28 +01:00
ff17202b43 refactor: switch to new MSA Client ID 2022-02-16 17:03:13 +01:00
a3d8313dcb Change: set MACOSX_BUNDLE_GUI_IDENTIFIER to org.polymc instead of org.multimc 2022-02-16 15:45:16 +01:00
36841eaf63 chore(github): add issue template for RFCs 2022-02-16 12:38:28 +01:00
e24a183dad Only trigger GH Release on stable branch 2022-02-15 14:38:26 +05:30
8596753a63 Allow building release builds and…
…trigger GH release using tags
2022-02-15 14:24:52 +05:30
51183bef33 nix: add meta attribute 2022-02-14 21:08:10 +01:00
2cd837896d Merge pull request #160 from Scrumplex/custom-be-gone 2022-02-14 16:56:53 +01:00
c75ae71190 flake.nix: drop aarch64-darwin
Currently qtbase is broken on aarch64-darwin, therefor dropping support, so the check can succeed
2022-02-14 15:45:51 +01:00
48c20f5aaa Merge pull request #164 from Scrumplex/rebase-stable
Merge stable into develop
2022-02-14 10:10:35 +01:00
929a035f96 Revert "make wsl work"
This reverts commit 5779f20fa1633577889b7bda839c5486eb2ba922.
2022-02-13 18:47:54 +00:00
5779f20fa1 make wsl work 2022-02-13 13:35:15 -05:00
384e0df9e1 Merge remote-tracking branch 'upstream/stable' into rebase-stable 2022-02-13 18:08:41 +01:00
a5b06514c6 Merge pull request #161 from Scrumplex/custom-clientid
Add MSA-Client-ID override in UI
2022-02-13 14:06:27 +00:00
a309f4e721 fix: MSA = Microsoft Authentication 2022-02-12 21:27:35 +01:00
159d868b77 fix(ui): explain why 'Add Microsoft' might be disabled 2022-02-12 21:27:35 +01:00
0854e83ce4 feat: implement MSA client id override
Closes #11
2022-02-12 21:27:32 +01:00
bb02226870 feat(ui): add custom MSA client id setting 2022-02-12 21:05:42 +01:00
9ddbaaf7e8 feat: use commit hash for channel if ref not available 2022-02-12 19:04:45 +01:00
3b7cc4391a fix: don't use custom for version channel
Closes #159
2022-02-12 18:17:56 +01:00
70a055bc27 Merge pull request #143 from Scrumplex/refactor-link-nbtpp-static 2022-02-12 17:47:38 +01:00
61db1c46be fix: use our own prefix for rainbow lib 2022-02-12 17:02:54 +01:00
a60b2feb5f Revert "refactor(build): link rainbow statically"
Windows build fails for some reason. Needs to be investigated later

This reverts commit 812f00eb81158bfb4c2d61b228c0c1c796641ac1.
2022-02-12 16:56:35 +01:00
6ba031f048 refactor(build): link iconfix statically 2022-02-12 16:10:53 +01:00
812f00eb81 refactor(build): link rainbow statically 2022-02-12 16:10:46 +01:00
2f6973e08b Merge pull request #157 from txtsd/actions_fix
Adjust OpenSSL step
2022-02-12 03:15:11 -08:00
fb14796ed7 Adjust OpenSSL step 2022-02-12 14:56:15 +05:30
7d912726d0 Merge pull request #134 from glowiak/patch-2
OpenBSD support and slackware build instructions
2022-02-12 03:30:24 +00:00
e3c8eb062c Merge pull request #149 from ZekeSmith/patch-1
License for assets
2022-02-12 03:29:59 +00:00
3cf81faabc change "loader mods" to "mods"
Closes: #128
2022-02-11 22:09:47 -05:00
0df605e559 Merge pull request #155 from txtsd/actions
fix(ci): Unsplit OpenSSL step
2022-02-12 02:22:23 +00:00
e97a6ef957 Unsplit OpenSSL step 2022-02-12 00:19:11 +05:30
c4dd8d9c72 Update LICENSE 2022-02-12 01:03:33 +10:00
bcfa3246cb Merge pull request #146 from dada513/macos_application_support
[MACOS] Move app data to Application Support
2022-02-11 13:52:56 +00:00
f67871e79e refactor(build): link nbt++ statically 2022-02-11 14:24:01 +01:00
11f892380e Merge pull request #145 from dada513/metainfix
Update metadata
2022-02-11 13:54:14 +01:00
fd72cb034c Merge pull request #140 from txtsd/actions
CI: Build AppImages
2022-02-11 12:38:03 +00:00
b9be8d08d2 Remove superfluous variable 2022-02-11 18:05:26 +05:30
33d369d78c Add missing deploy flags 2022-02-11 18:05:26 +05:30
0e6e6a7521 Remove generic Linux builds
They don't necessarily run on all distros
2022-02-11 18:05:26 +05:30
eb692c2ee9 Split OpenSSL step 2022-02-11 18:05:26 +05:30
3eee38fedd Make 32bit Windows build instead 2022-02-11 18:05:26 +05:30
0ba61bb590 Implement even more PR suggestions 2022-02-11 18:05:26 +05:30
9497485103 Implement more PR suggestions 2022-02-11 18:05:26 +05:30
551d9c86ba Implement PR suggestions 2022-02-11 18:05:26 +05:30
e61e827eb9 Use Adoptium JREs 2022-02-11 18:05:26 +05:30
92a5b12bd9 Remove PrefersNonDefaultGPU 2022-02-11 18:05:26 +05:30
35d1330fe2 Build AppImages for Linux
Now builds windows and macOS builds,
with windeployqt and macdeploqt.
Also adds SHA to the build filenames.
2022-02-11 18:05:26 +05:30
b4e0b7584a newlines 2022-02-11 13:17:11 +01:00
2341212337 Merge pull request #150 from dada513/fix_kwin_icon
Fix freedesktop icons. Again
2022-02-11 12:05:01 +00:00
53ea261350 Merge pull request #151 from dada513/rss_not_begone
Re-add RSS feed with the new PolyMC website
2022-02-11 12:03:29 +00:00
a17e5d0a4d Merge pull request #129 from timoreo22/fix-mod-name
Fixed the download menu putting the wrong name
2022-02-10 23:41:27 +00:00
5d4a66ed8a Merge pull request #152 from Scrumplex/update-translations-url
Update link to translations platform (Weblate)
2022-02-10 23:38:47 +00:00
8d2e7db178 fix: update link to translations platform 2022-02-10 14:55:52 +01:00
383c93ff01 Merge pull request #148 from helpimnotdrowning/develop
Fix Weblate link in README
2022-02-10 13:40:12 +00:00
13d41bde7f remove unused parsing of dates (bloat) 2022-02-10 13:57:18 +01:00
d42d6fe25a fix rss format 2022-02-10 13:57:06 +01:00
beaac54dc9 Merge remote-tracking branch 'polymc/develop' into rss_not_begone 2022-02-10 13:14:30 +01:00
70f8cb81b8 Initial RSS re-add and removed hardcoded strings 2022-02-10 13:14:25 +01:00
f8ca6b4867 Revert "refactor: remove news feed"
This reverts commit 361ce7818ec8891e9a35bdfac4cdea77a0b6a949.
2022-02-10 12:55:07 +01:00
49f5f67467 Update screenshots to use new site 2022-02-10 12:26:33 +01:00
35d2ae3ef7 Remove drama from readme and remove mmc discord link 2022-02-10 11:21:25 +00:00
22ca572ae0 ci: rebuild 2022-02-10 09:32:12 +01:00
619fcbfabf rename LAUNCHER_DESKTOPNAME to LAUNCHER_DESKTOPFILENAME 2022-02-10 08:56:34 +01:00
292869141f Merge remote-tracking branch 'polymc/develop' into fix_kwin_icon 2022-02-10 08:05:17 +01:00
ca9929214d Merge remote-tracking branch 'polymc/develop' into macos_application_support 2022-02-10 08:04:59 +01:00
121ad4e4bf Merge remote-tracking branch 'polymc/develop' into metainfix 2022-02-10 08:04:38 +01:00
2f87a4477e Fix desktop id for GH-150 2022-02-10 07:53:04 +01:00
d72c511131 Revert "Fix freedesktop icons" and fix icon on kwin 2022-02-10 07:46:41 +01:00
8b68c06547 License for assets
The PolyMC logo and assets are licensed under the CC BY-NC-SA 4.0 having it in this folder should help to clear this up.
2022-02-10 13:58:19 +10:00
b911151786 Fix Weblate link in README
original link was missing /projects/ dir and leading to a nonexistant page
2022-02-09 21:40:57 -06:00
7531a2894b Missed a closing parenthesis in README.md, oops. 2022-02-09 23:13:33 +00:00
5b507a8944 Add info about translating PolyMC to the README 2022-02-09 23:00:03 +00:00
d2f86cbf32 Move app data to Application Support 2022-02-09 12:23:18 +01:00
08dff6613b remove redundant data 2022-02-09 08:21:51 +01:00
901ec15dc8 Update metadata 2022-02-09 08:19:34 +01:00
5284d604ef translations 2022-02-09 00:02:51 +00:00
b2b4ab3f0c Update BUILD.md 2022-02-07 10:11:36 +01:00
b646fc5a13 Update build instructions for Slackware 14.2 2022-02-06 12:18:39 +01:00
d35cbfd9c4 Add Slackware instructions 2022-02-06 12:11:20 +01:00
f25152e068 Update BUILD.md 2022-02-06 12:06:08 +01:00
dd8946b15a Update BUILD.md 2022-02-06 12:03:17 +01:00
305350fdc8 Update BUILD.md 2022-02-06 09:41:13 +01:00
f31d5372e7 Update BUILD.md 2022-02-06 09:39:14 +01:00
ca1a2bbe2c Add OpenBSD instructions 2022-02-06 09:38:26 +01:00
dba9199e58 Support OpenBSD in UpdateController.cpp 2022-02-06 09:35:48 +01:00
e806903d7e Support OpenBSD without patches 2022-02-06 09:32:55 +01:00
41d8e3cbd7 add arches 2022-02-05 16:07:31 +01:00
5e32783c4e Update README.md 2022-02-05 16:05:34 +01:00
fdc3a4104b Add OpenBSD 2022-02-05 16:03:16 +01:00
8199941a81 Fix typo 2022-02-05 14:04:34 +01:00
651d237200 Update README.md 2022-02-04 21:07:34 +01:00
6f5b380199 Update README.md 2022-02-04 20:58:12 +01:00
c746d77a06 Update README.md
Co-authored-by: dada513 <dada513@protonmail.com>
2022-02-04 20:42:30 +01:00
9ab3841570 change fbsd icon
Co-authored-by: dada513 <dada513@protonmail.com>
2022-02-04 20:40:47 +01:00
3a28741cc3 Add FreeBSD 2022-02-04 18:12:32 +01:00
22f7a85cf2 Add Slackware package 2022-02-04 17:59:37 +01:00
86935068f5 Fix wrong mod file name 2022-02-04 16:24:19 +01:00
00e12b776b Merge pull request #126 from Scrumplex/fix-quazip-build
fix: link QuaZip statically
2022-02-04 07:40:09 -05:00
3b96a9a8fa Merge pull request #124 from babbaj/develop
nix: fix quazip input
2022-02-04 07:34:13 -05:00
5ac5c767e0 Merge pull request #125 from dada513/based_build_md
fix build.md
2022-02-04 07:33:22 -05:00
f1d3d4a366 fix: link QuaZip statically 2022-02-04 13:24:13 +01:00
1160066f0d fix build.md 2022-02-04 11:06:04 +00:00
8d603d6162 nix: fix quazip input 2022-02-04 02:13:48 -05:00
076efc4cb2 Merge branch 'update-quazip' of git://github.com/Scrumplex/PolyMC into develop 2022-02-03 14:14:12 -05:00
2c62a34c2f Merge branch 'feature/offline_mode' into develop 2022-02-03 13:59:25 -05:00
2177aa2a6b Merge branch 'offline-mode-accounts' of git://github.com/NyaomiDEV/PolyMC into feature/offline_mode 2022-02-03 13:54:27 -05:00
e8a4902a3d Merge branch 'feature/download_mods' into develop 2022-02-03 13:53:30 -05:00
e2952061af Merge branch 'feature/download_mods' of git://github.com/timoreo22/PolyMC into feature/download_mods 2022-02-03 13:45:20 -05:00
fcc4420cfe Merge branch 'feature/close_after_launch' into develop 2022-02-03 13:44:09 -05:00
f5358aa1ca Merge branch 'develop' into feature/close_after_launch 2022-02-03 13:43:44 -05:00
3d3f9a8609 make closeAfterLaunch good 2022-02-03 12:50:24 -05:00
1f176fcb7b fix aur formatting in README 2022-02-03 12:47:16 -05:00
3ca661127f NOISSUE Add missing tooltip for Export Instance action 2022-02-03 18:09:51 +01:00
407f9d9ef0 Merge remote-tracking branch 'upstream/develop' into develop 2022-02-02 11:17:04 -05:00
bff683e6d4 Merge pull request #108 from redstrate/improve_about_page
Improve the About page
2022-02-02 09:17:30 -05:00
770da6317e Merge pull request #122 from txtsd/actions
GitHub Actions for crossplatform builds
2022-02-02 09:14:12 -05:00
cf3c2482c9 fix some windows branding
Closes: #121
2022-02-02 08:46:26 -05:00
2001c5dec7 Merge pull request #123 from Skyblueborb/patch-1
Fix Gentoo Command Syntax
2022-02-02 08:41:31 -05:00
80cf716c98 Fix Gentoo Command Syntax
The proper syntax for adding repos is `eselect repository enable <repo>`
2022-02-02 10:34:26 +01:00
37e1962845 Add build.yml 2022-02-02 06:28:00 +00:00
f8c5d80c66 Merge pull request #4480 from Oreoezi/develop
Update BUILD.md
2022-02-01 22:33:45 +01:00
11841c47e6 Double braindead combo 2022-02-01 22:23:34 +01:00
71b1ac9f34 Fix braindead moments 2022-02-01 21:56:52 +01:00
eda06df878 Update BUILD.md 2022-02-01 20:33:38 +00:00
c4cb7ddc4f fix: bring back JAR Folder mods
what is this?
2022-01-31 21:40:59 +01:00
a8089b76c0 fix: bring back instance exports 2022-01-31 21:40:59 +01:00
71516e6c72 fix: set Launcher_FORCE_BUNDLED_LIBS=on by default
We need to wait for a new QuaZip release to become widely available, until we can turn this off again
2022-01-31 21:40:59 +01:00
88686ef065 refactor: restructure CMake to support future Qt versions 2022-01-31 21:40:59 +01:00
0442b80a2c refactor: simpler includes for quazip 2022-01-31 21:40:59 +01:00
81c72c2038 refactor: bring back methods that need to be reimplemented 2022-01-31 21:40:59 +01:00
3aa809b8c0 refactor: add in-tree QuaZip 2022-01-31 21:40:59 +01:00
efa414c442 refactor: initial migration to QuaZip 1.2
Let's move off our custom QuaZip. In the olden times we needed the
custom version of QuaZip, as it was basically unmaintained and on
SourceForge (eww). But nowadays it's maintained and on GitHub. See
new GitHub page: https://github.com/stachenov/quazip
2022-01-31 21:40:59 +01:00
c39da093bf change COPR to polymc/polymc 2022-01-31 12:35:30 -05:00
aa2c27bf69 Update to Modrinth API V2 2022-01-31 17:18:11 +01:00
1f92125a7f Move RPM package to a separate repo. 2022-01-31 10:41:05 -05:00
5c48b7dfab Merge pull request #104 from dada513/makedeb
Remove debian packages from repo
2022-01-31 10:40:12 -05:00
d664361b15 remove deb packaging 2022-01-31 10:36:57 -05:00
813de1c703 pkgs: remove debian packaging from repo 2022-01-31 16:03:50 +01:00
02f24117f0 better package list 2022-01-31 10:00:25 -05:00
7a7a937f1e remove changelog because it's annoying 2022-01-31 09:54:16 -05:00
0211ee3ef1 Add "PolyMC Contributors" to Credits section
This also adds a link to the PolyMC Contributors page on Github.
2022-01-31 09:09:58 -05:00
c569bfbe6d Merge pull request #111 from DioEgizio/patch-1
improve a bit MacOS build instructions
2022-01-30 11:33:42 -05:00
b925338688 Merge pull request #112 from muscaln/flake
Nix updates
2022-01-30 11:32:49 -05:00
2cf04d034a Merge pull request #4300 from Ghosty141/feature/screenshot_copy
GH-4044 Implemented copy screenshots to the clipboard
2022-01-30 16:11:47 +01:00
049aafd0a1 Merge pull request #4461 from Jan200101/rpm
Update rpm spec to support OpenSuse and conform to Fedora guidelines
2022-01-30 16:07:51 +01:00
e0a04c5031 Lock offline mode support behind insertion of at least one Minecraft account
Co-Authored-By: Naomi Calabretta <tony0000.ac@gmail.com>
2022-01-30 02:42:29 +01:00
9d23ac562f Add offline mode support 2022-01-30 02:35:56 +01:00
0065a29901 Close after Launch setting 2022-01-29 19:04:44 -05:00
8ea1ebaf1b I haven't tested qt 5.6, i use 5.12 2022-01-29 18:14:56 +01:00
5c2d3e430d Merge branch 'develop' into patch-1 2022-01-29 18:10:46 +01:00
b710b719a8 nix: use .desktop file provided by cmake 2022-01-29 17:38:12 +03:00
7df5091fdc flake.lock: Update
Flake lock file changes:

• Updated input 'flake-utils':
    'github:numtide/flake-utils/74f7e4319258e287b0f9cb95426c9853b282730b' (2021-11-28)
  → 'github:numtide/flake-utils/846b2ae0fc4cc943637d3d1def4454213e203cba' (2022-01-20)
• Updated input 'nixpkgs':
    'github:nixos/nixpkgs/b2737d4980a17cc2b7d600d7d0b32fd7333aca88' (2022-01-11)
  → 'github:nixos/nixpkgs/945ec499041db73043f745fad3b2a3a01e826081' (2022-01-26)
2022-01-29 17:35:50 +03:00
5abb97362f Merge pull request #102 from dada513/rework_docs
docs: rework README and BUILD
2022-01-29 09:24:08 -05:00
b34239ebc6 adoptium 2022-01-29 11:00:13 +01:00
7ef6c586c5 update readme 2022-01-29 10:59:04 +01:00
9d36cf4b5a fix another typo (omg I'm doing too commits) 2022-01-29 10:26:13 +01:00
04be2404ce fix typo 2022-01-29 10:24:49 +01:00
7f4fd04cfe not needed actually 2022-01-29 10:24:06 +01:00
b2bcdb9d9b fix a typo+explain better 2022-01-29 10:18:12 +01:00
d81e2bb0b0 extra refinements 2022-01-29 10:14:00 +01:00
177c10bb0f fix MacOS build instructions 2022-01-29 10:12:04 +01:00
304775952f EVEN MORE BASED 2022-01-29 09:40:27 +01:00
ca00103ee2 make packaging based 2022-01-29 08:56:04 +01:00
3aa9f5c376 Update rpm spec to support OpenSuse and conform to Fedora guidelines 2022-01-28 19:42:30 +01:00
efc44c56a6 Fix button being present in other pages 2022-01-28 19:32:42 +01:00
8b790a6dd9 Merge branch 'PolyMC:develop' into feature/download_mods 2022-01-28 18:12:35 +01:00
f36930d812 Merge pull request #107 from redstrate/fix_icon_bug
Fix icons changing when exiting the settings window
2022-01-28 09:31:41 -05:00
232295bda7 add gentoo instructions 2022-01-28 09:12:55 +01:00
451768ccf9 Merge remote-tracking branch 'upstream/develop' into rework_docs 2022-01-28 09:10:47 +01:00
c1aaf89baa Improve the About page
Improves #106. This more clearly marks the original MultiMC contributors,
and now correctly hides the "Build Platform" if this is set as empty. The
version label is now moved under the "PolyMC" title so it looks just a
little bit better (and matches other applications). The copyright on the
"About" page now correctly attributes the MultiMC contributors just like on
the "License" page.
2022-01-27 19:06:07 -05:00
5ac528f141 Fix icons changing when exiting the settings window 2022-01-27 18:37:57 -05:00
204e3dca22 fix version 2022-01-27 17:23:50 -05:00
33aac2985a Merge pull request #105 from Scrumplex/rss-begone
Remove news
2022-01-27 17:00:15 -05:00
361ce7818e refactor: remove news feed
Closes #63
2022-01-27 22:59:20 +01:00
ad6e3a0868 Fix meta 2022-01-27 16:58:28 -05:00
fd2269ac15 Fix meta 2022-01-27 16:54:05 -05:00
14a8ead6b4 fix conflict 2022-01-27 19:01:20 +01:00
bbf0508846 docs: rework README and BUILD 2022-01-27 18:59:44 +01:00
79314ee67b Merge pull request #103 from redstrate/fix_rpm_build
Fix RPM build instructions
2022-01-27 12:43:54 -05:00
86b0637ef7 Merge pull request #101 from redstrate/fix_freedesktop_icon
Fix Freedesktop icons
2022-01-27 09:56:39 -05:00
1c982b0182 Fix RPM build instructions 2022-01-27 13:17:26 +00:00
cd5faee7d7 Fix RPM spec referencing old desktop file 2022-01-27 08:06:35 -05:00
ec1e27031a Fix Freedesktop icons
This fixes #51. The desktop file is now exactly the same as the window class,
which is also now corrected to org.polymc.polymc. The file capitalization
is also consistent with other Freedesktop files as well.
2022-01-27 00:08:53 -05:00
02889b7a11 Merge pull request #67 from PolyMC/feature/no_paste_ee
Full replacement of paste.ee
2022-01-26 17:40:49 -05:00
0eff21a4f1 Validate Pastebin URL with regex 2022-01-26 00:34:02 +00:00
0680945839 Merge pull request #96 from dada513/develop
rebase with upstream
2022-01-24 19:36:31 -05:00
631e670775 Merge pull request #99 from Jan200101/PR/rpm-opensuse
remove explicit dependencies, correct dependencies to work on OpenSuse
2022-01-24 18:40:44 -05:00
4edd2cff9f remove explicit dependencies, correct dependencies to work on OpenSuse 2022-01-24 23:15:54 +01:00
0235eb5c28 Fix error message
The code is trying to get a string from a json object, and if that fails it should log "is not a string", not "is not a timestamp".
2022-01-24 11:44:47 +01:00
8804b035b2 NOISSUE log server response when failing to fetch profile 2022-01-24 11:44:47 +01:00
54e3438e37 NOISSUE correctly set http status code in auth reply 2022-01-24 11:44:47 +01:00
ddfed7bb87 NOISSUE in java checker, ignore invalid lines altogether
Declaring them as errors is just causing problems because Java
randomly prints garbage to STDOUT now.
2022-01-24 11:44:47 +01:00
70c04745ee NOISSUE add some logging to profile fetching failures 2022-01-24 11:44:47 +01:00
63d4486855 Merge pull request #4447 from Stypox/patch-1
Fix error message
2022-01-24 10:32:14 +01:00
1d0e6bf453 Changed modrinth author data to not be a list 2022-01-24 07:23:01 +01:00
a2d88f6df4 Fixed spacing 2022-01-24 07:12:19 +01:00
019c77f9f7 Merge pull request #52 from oynqr/develop
Default to system locale language
2022-01-23 15:00:26 -05:00
5b5c5afc3a Merge pull request #88 from Scrumplex/launch-msa-login
Add open page & copy code button to MSA login dialog
2022-01-23 14:55:05 -05:00
af20b5ee0e support paste.polymc.org 2022-01-23 12:54:58 -05:00
a1b779da15 Merge pull request #95 from danielhuang/patch-1
Add StartupWMClass to desktop file
2022-01-23 12:05:39 -05:00
8b31c638f3 Fix error message
The code is trying to get a string from a json object, and if that fails it should log "is not a string", not "is not a timestamp".
2022-01-22 21:58:32 +01:00
3da69d8e53 Update org.polymc.PolyMC.desktop.in 2022-01-22 14:13:21 -05:00
dd76fb0ec7 feat(MSALogin): add open page & copy code button
Closes #55
2022-01-20 21:04:48 +01:00
caeab926bc PasteUpload: Trim whitespace from response body 2022-01-19 19:05:52 +00:00
35caa3c21a Merge pull request #87 from Scrumplex/themed-header-image
Header image's text color should follow GitHub theme
2022-01-19 13:06:45 -05:00
7022d3d401 fix(readme): header color should follow GH theme
As browser color scheme preference and GitHub theme can be different
from each other, let's follow GitHub theme instead of browser
preference.
2022-01-19 18:59:24 +01:00
6d22794cf9 Reduce spaghettiness 2022-01-19 09:47:09 +01:00
b50e584369 PasteUpload task changed to use 0x0.st's protocol
- Modified PasteUpload task to upload the log file to 0x0.st and other
  services with the same protocol.

- Modified Paste settings UI to allow the user to select a custom paste
  URL, simplified the settings page code.
2022-01-19 08:27:26 +00:00
affc2521aa Various fixes 2022-01-18 12:28:55 +01:00
63098b6f19 Merge pull request #4428 from MandipJoshi/patch-1
Update README.md copyright date changed
2022-01-17 10:00:40 +01:00
83e1dd285a Set default lang only if index received 2022-01-17 09:52:04 +01:00
b9beb3c7d2 Sort system locale to front of list 2022-01-17 09:52:04 +01:00
2dd2555a63 Update selected language automatically 2022-01-17 09:52:04 +01:00
126e6d13aa Use isEmpty instead of 0 length check 2022-01-17 09:52:04 +01:00
236c0166f6 Default to system locale language 2022-01-17 09:52:04 +01:00
9a33fb1f49 Update README.md 2022-01-17 12:09:36 +05:45
2c2c22ccf8 Merge pull request #82 from PolyMC/revert-offline-mode
Revert offline mode support (#81 and #50)
2022-01-17 03:56:27 +00:00
55597b458c Revert "Merge pull request #50 from bexnoss/offline-mode"
This reverts commit b4f750e7db40352111417ea89a9f375ae8c746ab, reversing
changes made to b19e3156154ba0dd232a3d165b1759c57e2858f2.
2022-01-17 03:45:47 +00:00
f55297eca9 Revert "Merge pull request #81 from bexnoss/fix-msa-account-refresh"
This reverts commit 0bc8baf1172d6967cdb2993826e3469ecd9aab66, reversing
changes made to 81fe41a038ee12ff2ee0200525b39e4ad650bec2.
2022-01-17 03:45:33 +00:00
0bc8baf117 Merge pull request #81 from bexnoss/fix-msa-account-refresh 2022-01-16 17:32:13 -05:00
5f9270ed4b Fix MSA account refresh 2022-01-16 23:30:17 +01:00
81fe41a038 Default to colored icons, update copyright
Closes: #74
2022-01-16 12:03:30 -05:00
0316cf88aa Merge pull request #78 from bexnoss/readme-svg-header 2022-01-16 10:33:35 -05:00
917f8a31e3 NOISSUE log server response when failing to fetch profile 2022-01-16 12:51:42 +01:00
aa770b63fb NOISSUE correctly set http status code in auth reply 2022-01-16 12:46:20 +01:00
c1bf31cb27 NOISSUE in java checker, ignore invalid lines altogether
Declaring them as errors is just causing problems because Java
randomly prints garbage to STDOUT now.
2022-01-16 12:05:40 +01:00
86d99f80c3 NOISSUE add some logging to profile fetching failures 2022-01-16 11:43:19 +01:00
975f77756d Added curseforge selection 2022-01-16 11:20:21 +01:00
8172dcd2d5 Replace PNG README header with SVG
Instead of GitHub specific MarkDown based theming this uses CSS in SVG.
2022-01-16 07:55:10 +01:00
b95c27ceef fix readme formatting 2022-01-15 21:26:00 -05:00
f78bb90ed9 GH-4125 fix it better 2022-01-15 16:25:52 -05:00
dc129fd886 GH-4125 workaround for java printing garbage to stdout on bedrock linux 2022-01-15 16:25:52 -05:00
621e0ba4a8 Added smart file selection
This might fail in a few special cases
2022-01-15 10:25:24 +01:00
f6de472da2 Added a no version message 2022-01-15 09:06:48 +01:00
4b37c46889 Filtering per mod loader & mc version 2022-01-15 08:51:47 +01:00
c371558883 Merge pull request #68 from GriffintheFolf/execname
Fix program executable name for shell script
2022-01-14 21:46:46 -05:00
0bbd0ac0b9 Change method of shell script fix per suggestion
The Launcher.in file is now modified rather than CMakeLists.txt
2022-01-14 19:28:10 -07:00
ac93c64cd4 Fix program executable name for shell script 2022-01-14 16:59:16 -07:00
6cd4375aff add arch linux package to readme
closes: #53
2022-01-14 18:39:25 -05:00
a606b47a22 pastebin URL app setting 2022-01-14 18:30:02 -05:00
a62155c1c9 preliminary stuff for paste.ee removal 2022-01-14 18:20:06 -05:00
b4f750e7db Merge pull request #50 from bexnoss/offline-mode
Offline Mode Support
2022-01-14 18:03:35 -05:00
b19e315615 Set maximum memory allocated to 4GB by default 2022-01-14 17:34:50 -05:00
41dba376a8 remove 5 from display name
Closes: #58
2022-01-14 17:33:34 -05:00
2896f70cd8 Removing copyrights 2022-01-14 22:07:54 +01:00
1a8c972aef Fixed icons
Also having a mod loader is now enforced
2022-01-14 20:22:15 +01:00
cdaa397dcf Reword offline mode disclaimer 2022-01-14 14:19:31 +01:00
9e6fa8f29a Added the downloading of the mods 2022-01-14 12:47:18 +01:00
4d599eb118 Added modrinth icon 2022-01-14 10:51:44 +01:00
4e9039be2d Start of mod downloading 2022-01-14 09:56:27 +01:00
395e265564 Add offline mode disclaimer 2022-01-14 00:01:05 +01:00
b07853c9ef Merge pull request #61 from meguminloli/develop 2022-01-13 13:55:29 -05:00
b635a7e693 update NIX.md 2022-01-13 15:43:29 +02:00
f84fc783b6 removed redundant recs
removed file
2022-01-13 15:29:10 +02:00
2301a934b0 Merge pull request #59 from A-UNDERSCORE-D/patch-1 2022-01-13 08:19:08 -05:00
60e9d2754a changed flake.nix
removed result
2022-01-13 13:14:50 +02:00
A_D
d06c2cacb1 Readd original MultiMC/Launcher copyright
The original MMC code remains Apache.
2022-01-13 09:59:16 +02:00
49c2bd477c Merge pull request #45 from cidkidnix/develop 2022-01-12 21:11:09 -05:00
46a3b4de6e Remove unnecessary semicolon 2022-01-12 18:41:33 +01:00
6ecc8c5496 Remove unnecessary license header 2022-01-12 14:57:32 +01:00
a1ff3b1ee3 Add offline mode support 2022-01-12 14:26:02 +01:00
d4b522b6cb Add offline mode UI 2022-01-12 10:36:26 +01:00
3b524e99cc Merge pull request #46 from muscaln/java 2022-01-11 14:44:21 -05:00
3329d94c9b Introduce POLYMC_JAVA_PATHS env 2022-01-11 18:24:37 +03:00
a12118f1a0 Sort java versions from current to oldest 2022-01-11 17:40:58 +03:00
5fe33a98a2 nix: remove patch due to breakage 2022-01-10 18:24:49 -06:00
1d8196e11a More rebranding
Closes: #39

Mostly done with rebranding now. We just need to translate some services
to PolyMC.
2022-01-10 12:47:35 -05:00
c7f6f94930 Merge pull request #42 from Eonfge/patch-1 2022-01-10 12:02:12 -05:00
131615811b Set PrefersNonDefaultGPU for hybrid devices
With the Property 'PrefersNonDefaultGPU', you can signal to dekstop environments like GNOME that you want to run the application using the more powerful secondary graphics card, if such a card is available. Specification: https://specifications.freedesktop.org/desktop-entry-spec/latest/ar01s06.html

With this change, you won't have to include a special prime-run script.
2022-01-10 14:55:18 +01:00
3fa6e22430 Merge pull request #40 from Jan200101/PR/rpm-1.0.5 2022-01-09 17:57:18 -05:00
c86ac772c8 Update RPM and build instruction 2022-01-09 21:51:56 +01:00
52420963cf GH-4125 fix it better 2022-01-08 12:26:16 +01:00
addf5f4e52 NOISSUE update README for clarity 2022-01-08 11:45:10 +01:00
03d7300732 GH-4125 workaround for java printing garbage to stdout on bedrock linux 2022-01-08 11:14:07 +01:00
a97d0a36f4 NOISSUE Copy Image is not shown if the selection is > 1 2021-12-03 16:29:28 +01:00
e9c52ec696 NOISSUE Added Copy File(s) feature for the screenshot page
- Ctrl+C now copies the file instead of the image data
- Renamed Copy to Copy Image
2021-12-03 16:08:11 +01:00
75f2dab3c8 NOISSUE Implemented copy screenshots to the clipboard
- Added context-menu entry
- Ctrl+C keybind works as well
- If multiple screenshots are selected, only the first one gets copied
2021-12-03 03:11:53 +01:00
247 changed files with 8039 additions and 4758 deletions

69
.github/ISSUE_TEMPLATE/rfc.yml vendored Normal file
View File

@ -0,0 +1,69 @@
# Template based on https://gitlab.archlinux.org/archlinux/rfcs/-/blob/0ba3b61e987e197f8d1901709409b8564958f78a/rfcs/0000-template.rst
name: Request for Comment (RFC)
description: Propose a larger change and start a discussion.
labels: [RFC]
body:
- type: markdown
attributes:
value: |
### Use this form to suggest a larger change for PolyMC.
- type: textarea
attributes:
label: Goal
description: Short description, 1-2 sentences.
placeholder: Remove the cat from the launcher.
validations:
required: true
- type: textarea
attributes:
label: Motivation
description: |
Introduce the topic. If this is a not-well-known section of PolyMC, a detailed explanation of the background is recommended.
Some example points of discussion:
- 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!).
- Is there any precedent set by other software? If so, link to resources.
placeholder: I don't like cats. I think many users also don't like cats.
validations:
required: true
- type: textarea
attributes:
label: Specification
description: A concrete, thorough explanation of what is being planned.
placeholder: Remove the cat button and all references to the cat from the codebase. Including resource files.
validations:
required: true
- type: textarea
attributes:
label: Drawbacks
description: Carefully consider every possible objection and issue with your proposal. This section should be updated as feedback comes in from discussion.
placeholder: Some users might like cats.
validations:
required: true
- type: textarea
attributes:
label: Unresolved Questions
description: |
Are there any portions of your proposal which need to be discussed with the community before the RFC can proceed?
Be careful here -- an RFC with a lot of remaining questions is likely to be stalled.
If your RFC is mostly unresolved questions and not too much substance, it may not be ready.
placeholder: Do a lot of users care about the cat?
validations:
required: true
- type: textarea
attributes:
label: Alternatives Considered
description: A list of alternatives, that have been considered and offer equal or similar features to the proposed change.
placeholder: Maybe the cat could be replaced with an axolotl?
validations:
required: true
- type: checkboxes
attributes:
label: This suggestion is unique
options:
- label: I have searched the issue tracker and did not find an issue describing my suggestion, especially not one that has been rejected.
required: true
- type: textarea
attributes:
label: You may use the editor below to elaborate further.

41
.github/scripts/prepare_JREs.sh vendored Executable file
View File

@ -0,0 +1,41 @@
#!/usr/bin/env bash
URL_JDK8="https://api.adoptium.net/v3/binary/version/jdk8u312-b07/linux/x64/jre/hotspot/normal/eclipse"
URL_JDK17="https://api.adoptium.net/v3/binary/latest/17/ga/linux/x64/jre/hotspot/normal/eclipse"
mkdir -p JREs
pushd JREs
wget --content-disposition "$URL_JDK8"
wget --content-disposition "$URL_JDK17"
for file in *;
do
mkdir temp
re='(OpenJDK([[:digit:]]+)U-jre_x64_linux_hotspot_([[:digit:]]+)(.*).tar.gz)'
if [[ $file =~ $re ]];
then
version_major=${BASH_REMATCH[2]}
version_trailing=${BASH_REMATCH[4]}
if [ $version_major = 17 ];
then
hyphen='-'
else
hyphen=''
fi
version_edit=$(echo $version_trailing | sed -e 's/_/+/g' | sed -e 's/b/-b/g')
dir_name=jdk$hyphen$version_major$version_edit-jre
mkdir jre$version_major
tar -xzf $file -C temp
pushd temp/$dir_name
cp -r . ../../jre$version_major
popd
fi
rm -rf temp
done
popd

267
.github/workflows/build.yml vendored Normal file
View File

@ -0,0 +1,267 @@
name: Build
on:
workflow_call:
inputs:
build_type:
description: Type of build (Debug, Release, RelWithDebInfo, MinSizeRel)
type: string
default: Debug
jobs:
build:
strategy:
fail-fast: false
matrix:
include:
- os: ubuntu-20.04
qt_version: 5.12.8
qt_host: linux
- os: ubuntu-20.04
qt_version: 5.15.2
qt_host: linux
app_image: true
- os: windows-2022
name: "Windows-i686"
msystem: mingw32
portable: false
- os: windows-2022
name: "Windows-x86_64"
msystem: mingw64
portable: false
- os: windows-2022
name: "Windows-i686-portable"
msystem: mingw32
portable: true
- os: windows-2022
name: "Windows-x86_64-portable"
msystem: mingw64
portable: true
- os: macos-11
qt_version: 5.12.12
qt_host: mac
macosx_deployment_target: 10.12
runs-on: ${{ matrix.os }}
env:
MACOSX_DEPLOYMENT_TARGET: ${{ matrix.macosx_deployment_target }}
INSTALL_DIR: "install"
BUILD_DIR: "build"
steps:
- name: Checkout
uses: actions/checkout@v3
with:
submodules: 'true'
- name: 'Setup MSYS2'
if: runner.os == 'Windows'
uses: msys2/setup-msys2@v2
with:
msystem: ${{ matrix.msystem }}
update: true
install: >-
git
pacboy: >-
toolchain:p
cmake:p
ninja:p
qt5:p
- name: Set short version
shell: bash
run: |
ver_short=`git rev-parse --short HEAD`
echo "VERSION=$ver_short" >> $GITHUB_ENV
- name: Install OpenJDK
uses: actions/setup-java@v3
with:
distribution: 'temurin'
java-version: '17'
- name: Cache Qt
if: runner.os != 'Windows'
id: cache-qt
uses: actions/cache@v3
with:
path: "${{ github.workspace }}/Qt/"
key: ${{ runner.os }}-${{ matrix.qt_version }}-${{ matrix.qt_arch }}-qt_cache
- name: Install Qt
if: runner.os != 'Linux' && runner.os != 'Windows' || matrix.app_image == true
uses: jurplel/install-qt-action@v2
with:
version: ${{ matrix.qt_version }}
host: ${{ matrix.qt_host }}
arch: ${{ matrix.qt_arch }}
cached: ${{ steps.cache-qt.outputs.cache-hit }}
dir: "${{ github.workspace }}/Qt/"
- name: Install System Qt on Linux
if: runner.os == 'Linux' && matrix.app_image != true
run: |
sudo apt-get -y update
sudo apt-get -y install qtbase5-dev qtchooser qt5-qmake qtbase5-dev-tools libqt5core5a libqt5network5 libqt5gui5
- name: Install Ninja
if: runner.os != 'Windows'
uses: urkle/action-get-ninja@v1
- name: Download linuxdeploy family for AppImage on Linux
if: matrix.app_image == true
run: |
wget "https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-x86_64.AppImage"
wget "https://github.com/linuxdeploy/linuxdeploy-plugin-appimage/releases/download/continuous/linuxdeploy-plugin-appimage-x86_64.AppImage"
wget "https://github.com/linuxdeploy/linuxdeploy-plugin-qt/releases/download/continuous/linuxdeploy-plugin-qt-x86_64.AppImage"
- name: Download JREs for AppImage on Linux
if: matrix.app_image == true
shell: bash
run: |
${{ github.workspace }}/.github/scripts/prepare_JREs.sh
- name: Configure CMake
if: runner.os != 'Linux' && runner.os != 'Windows'
run: |
cmake -S . -B ${{ env.BUILD_DIR }} -DCMAKE_INSTALL_PREFIX=${{ env.INSTALL_DIR }} -DCMAKE_BUILD_TYPE=${{ inputs.build_type }} -G Ninja
- name: Configure CMake on Windows
if: runner.os == 'Windows' && matrix.portable != true
shell: msys2 {0}
run: |
cmake -S . -B ${{ env.BUILD_DIR }} -DCMAKE_INSTALL_PREFIX=${{ env.INSTALL_DIR }} -DCMAKE_BUILD_TYPE=${{ inputs.build_type }} -DLauncher_PORTABLE=OFF -G Ninja
- name: Configure CMake on Windows portable
if: runner.os == 'Windows' && matrix.portable == true
shell: msys2 {0}
run: |
cmake -S . -B ${{ env.BUILD_DIR }} -DCMAKE_INSTALL_PREFIX=${{ env.INSTALL_DIR }} -DCMAKE_BUILD_TYPE=${{ inputs.build_type }} -G Ninja
- name: Configure CMake on Linux
if: runner.os == 'Linux'
run: |
cmake -S . -B ${{ env.BUILD_DIR }} -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_BUILD_TYPE=${{ inputs.build_type }} -DLauncher_PORTABLE=OFF -G Ninja
- name: Build
if: runner.os != 'Windows'
run: |
cmake --build ${{ env.BUILD_DIR }}
- name: Build on Windows
if: runner.os == 'Windows'
shell: msys2 {0}
run: |
cmake --build ${{ env.BUILD_DIR }}
- name: Install
if: runner.os != 'Linux' && runner.os != 'Windows'
run: |
cmake --install ${{ env.BUILD_DIR }}
- name: Install on Windows
if: runner.os == 'Windows'
shell: msys2 {0}
run: |
cmake --install ${{ env.BUILD_DIR }}
- name: Install on Linux
if: runner.os == 'Linux'
run: |
DESTDIR=${{ env.INSTALL_DIR }} cmake --install ${{ env.BUILD_DIR }}
- name: Bundle AppImage
if: matrix.app_image == true
shell: bash
run: |
export OUTPUT="PolyMC-${{ runner.os }}-${{ env.VERSION }}-${{ inputs.build_type }}-x86_64.AppImage"
chmod +x linuxdeploy-*.AppImage
mkdir -p ${{ env.INSTALL_DIR }}/usr/lib/jvm/java-{8,17}-openjdk
cp -r ${{ github.workspace }}/JREs/jre8/* ${{ env.INSTALL_DIR }}/usr/lib/jvm/java-8-openjdk
cp -r ${{ github.workspace }}/JREs/jre17/* ${{ env.INSTALL_DIR }}/usr/lib/jvm/java-17-openjdk
export LD_LIBRARY_PATH="${LD_LIBRARY_PATH}:${{ env.INSTALL_DIR }}/usr/lib"
LD_LIBRARY_PATH="${LD_LIBRARY_PATH}:${{ env.INSTALL_DIR }}/usr/lib/jvm/java-8-openjdk/lib/amd64/server"
LD_LIBRARY_PATH="${LD_LIBRARY_PATH}:${{ env.INSTALL_DIR }}/usr/lib/jvm/java-8-openjdk/lib/amd64"
LD_LIBRARY_PATH="${LD_LIBRARY_PATH}:${{ env.INSTALL_DIR }}/usr/lib/jvm/java-17-openjdk/lib/server"
LD_LIBRARY_PATH="${LD_LIBRARY_PATH}:${{ env.INSTALL_DIR }}/usr/lib/jvm/java-17-openjdk/lib"
./linuxdeploy-x86_64.AppImage --appdir ${{ env.INSTALL_DIR }} --output appimage --plugin qt -i ${{ env.INSTALL_DIR }}/usr/share/icons/hicolor/scalable/apps/org.polymc.PolyMC.svg
- name: Run macdeployqt
if: runner.os == 'macOS'
run: |
cd ${{ env.INSTALL_DIR }}
macdeployqt "PolyMC.app" -executable="PolyMC.app/Contents/MacOS/polymc" -always-overwrite
- name: chmod binary on macOS
if: runner.os == 'macOS'
run: |
chmod +x "${{ github.workspace }}/${{ env.INSTALL_DIR }}/PolyMC.app/Contents/MacOS/polymc"
- name: tar bundle on macOS
if: runner.os == 'macOS'
run: |
cd ${{ env.INSTALL_DIR }}
tar -czf ../PolyMC.tar.gz *
- name: tar on Linux
if: runner.os == 'Linux' && matrix.app_image != true
run: |
cd ${{ env.INSTALL_DIR }}
tar -czf ../PolyMC.tar.gz *
- name: Upload Linux tar.gz
if: runner.os == 'Linux' && matrix.app_image != true
uses: actions/upload-artifact@v3
with:
name: PolyMC-${{ runner.os }}-${{ env.VERSION }}-${{ inputs.build_type }}
path: PolyMC.tar.gz
- name: Upload AppImage for Linux
if: matrix.app_image == true
uses: actions/upload-artifact@v3
with:
name: PolyMC-${{ runner.os }}-${{ env.VERSION }}-${{ inputs.build_type }}-x86_64.AppImage
path: PolyMC-${{ runner.os }}-${{ env.VERSION }}-${{ inputs.build_type }}-x86_64.AppImage
- name: Copy OpenSSL libs on Windows x86
if: runner.os == 'Windows' && matrix.msystem == 'mingw32'
shell: msys2 {0}
run: |
cp /mingw32/bin/libcrypto-1_1.dll ${{ env.INSTALL_DIR }}/
cp /mingw32/bin/libssl-1_1.dll ${{ env.INSTALL_DIR }}/
- name: Copy OpenSSL libs on Windows x86_64
if: runner.os == 'Windows' && matrix.msystem == 'mingw64'
shell: msys2 {0}
run: |
cp /mingw64/bin/libcrypto-1_1-x64.dll ${{ env.INSTALL_DIR }}/
cp /mingw64/bin/libssl-1_1-x64.dll ${{ env.INSTALL_DIR }}/
- name: Upload package for Windows
if: runner.os == 'Windows'
uses: actions/upload-artifact@v3
with:
name: PolyMC-${{ matrix.name }}-${{ env.VERSION }}-${{ inputs.build_type }}
path: ${{ env.INSTALL_DIR }}/**
- name: Upload package for macOS
if: runner.os == 'macOS'
uses: actions/upload-artifact@v3
with:
name: PolyMC-${{ runner.os }}-${{ env.VERSION }}-${{ inputs.build_type }}
path: PolyMC.tar.gz

32
.github/workflows/trigger_builds.yml vendored Normal file
View File

@ -0,0 +1,32 @@
name: Build Application
on:
push:
branches-ignore:
- 'stable'
paths-ignore:
- '**.md'
- '**/LICENSE'
- 'flake.lock'
- '**.nix'
pull_request:
paths-ignore:
- '**.md'
- '**/LICENSE'
- 'flake.lock'
- '**.nix'
workflow_dispatch:
jobs:
build_debug:
name: Build Debug
uses: ./.github/workflows/build.yml
with:
build_type: Debug
build_release:
name: Build Release
uses: ./.github/workflows/build.yml
with:
build_type: Release

70
.github/workflows/trigger_release.yml vendored Normal file
View File

@ -0,0 +1,70 @@
name: Build Application and Make Release
on:
push:
tags:
- '*'
jobs:
build_release:
name: Build Release
uses: ./.github/workflows/build.yml
with:
build_type: Release
create_release:
needs: build_release
runs-on: ubuntu-latest
outputs:
upload_url: ${{ steps.create_release.outputs.upload_url }}
steps:
- name: Checkout
uses: actions/checkout@v3
with:
submodules: 'true'
path: 'PolyMC-source'
- name: Download artifacts
uses: actions/download-artifact@v3
- name: Grab and store version
run: |
tag_name=$(echo ${{ github.ref }} | grep -oE "[^/]+$")
echo "VERSION=$tag_name" >> $GITHUB_ENV
- name: Package artifacts properly
run: |
mv ${{ github.workspace }}/PolyMC-source PolyMC-${{ env.VERSION }}
mv PolyMC-Linux*/PolyMC.tar.gz PolyMC-Linux-${{ env.VERSION }}.tar.gz
mv PolyMC-*.AppImage/PolyMC-*.AppImage PolyMC-Linux-${{ env.VERSION }}-x86_64.AppImage
mv PolyMC-macOS*/PolyMC.tar.gz PolyMC-macOS-${{ env.VERSION }}.tar.gz
tar -czf PolyMC-${{ env.VERSION }}.tar.gz PolyMC-${{ env.VERSION }}
for d in PolyMC-Windows-*; do
cd "${d}" || continue
ARCH="$(echo -n ${d} | cut -d '-' -f 3)"
PORT="$(echo -n ${d} | grep -o portable || true)"
NAME="PolyMC-Windows-${ARCH}"
test -z "${PORT}" || NAME="${NAME}-portable"
zip -r -9 "../${NAME}-${{ env.VERSION }}.zip" *
cd ..
done
- name: Create release
id: create_release
uses: softprops/action-gh-release@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag_name: ${{ github.ref }}
name: PolyMC ${{ env.VERSION }}
draft: true
prerelease: false
files: |
PolyMC-Linux-${{ env.VERSION }}.tar.gz
PolyMC-Linux-${{ env.VERSION }}-x86_64.AppImage
PolyMC-Windows-i686-${{ env.VERSION }}.zip
PolyMC-Windows-i686-portable-${{ env.VERSION }}.zip
PolyMC-Windows-x86_64-${{ env.VERSION }}.zip
PolyMC-Windows-x86_64-portable-${{ env.VERSION }}.zip
PolyMC-macOS-${{ env.VERSION }}.tar.gz
PolyMC-${{ env.VERSION }}.tar.gz

8
.gitignore vendored
View File

@ -40,13 +40,5 @@ run/
.cache/
# Flatpak builds
.flatpak-builder
flatbuild
builddir
# Deb
packages/debian/polymc/usr/
packages/debian/polymc.deb
packages/debian/polymc/DEBIAN/control
# Nix/NixOS
result/

4
.gitmodules vendored
View File

@ -2,7 +2,7 @@
path = libraries/libnbtplusplus
url = https://github.com/MultiMC/libnbtplusplus.git
pushurl = git@github.com:MultiMC/libnbtplusplus.git
[submodule "libraries/quazip"]
path = libraries/quazip
url = https://github.com/PolyMC/quazip.git
pushurl = git@github.com:PolyMC/quazip.git
url = https://github.com/stachenov/quazip.git

245
BUILD.md
View File

@ -1,244 +1,5 @@
Build Instructions
==================
# Build Instructions
# Contents
Build instructions are available on [the website](https://polymc.org/wiki/development/build-instructions/).
* [Note](#note)
* [Getting the source](#source)
* [Linux](#linux)
* [Windows](#windows)
* [macOS](#macos)
# Getting the source
Clone the source code using git and grab all the submodules:
```
git clone https://github.com/PolyMC/PolyMC.git
git submodule init
git submodule update
```
# Linux
Getting the project to build and run on Linux is easy if you use any modern and up-to-date linux distribution.
## Build dependencies
* A C++ compiler capable of building C++11 code.
* Qt Development tools 5.6 or newer (`qtbase5-dev qtchooser qt5-qmake qtbase5-dev-tools libqt5core5a libqt5network5 libqt5gui5` on Debian-based system)
* cmake 3.1 or newer (`cmake` on Debian-based system)
* zlib (`zlib1g-dev` on Debian-based system)
* Java JDK (`openjdk-17-jdk`on Debian-based system)
* GL headers (`libgl1-mesa-dev` on Debian-based system)
### Building a .deb
You need to install the build dependencies first
```
git clone https://github.com/PolyMC/PolyMC.git
git submodule init && git submodule update
cd packages/debian
./makedeb.sh
```
If everything works correctly, the .deb will be next to the build script, in `PolyMC/packages/debian`
### Building a .rpm
You don't need to install the build dependencies, as the script will use `dnf` to install them for you.
```
git clone https://github.com/PolyMC/PolyMC.git
cd packages/rpm
./makerpm.sh
```
If everything works correctly, the .rpm will be next to the build script, in `PolyMC/packages/rpm`
### Building from command line
You need a source folder, a build folder and an install folder.
```
# make all the folders
mkdir ~/PolyMC && cd ~/PolyMC
mkdir build
mkdir install
# clone the complete source
git clone --recursive https://github.com/PolyMC/PolyMC.git src
# configure the project
cd build
cmake -DCMAKE_INSTALL_PREFIX=../install ../src
make -j$(nproc) install
```
You can use IDEs like KDevelop or QtCreator to open the CMake project if you want to work on the code.
### Building & Installing to the System
This is the preferred method for installation, and is suitable for packages.
```
git clone --recursive https://github.com/PolyMC/PolyMC.git && cd PolyMC
# configure everything
cmake -S . -B build \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_INSTALL_PREFIX="/usr" \ # Use "/usr" for packages, otherwise, leave it at the default "/usr/local".
-DLauncher_LAYOUT=lin-system
make -j$(nproc) install # Optionally specify DESTDIR for packages (i.e. DESTDIR=${pkgdir})
```
### Installing Qt using the installer (optional)
1. Run the Qt installer.
2. Choose a place to install Qt.
3. Choose the components you want to install.
- You need Qt 5.6.x 64-bit ticked.
- You need Tools/Qt Creator ticked.
- Other components are selected by default, you can untick them if you don't need them.
4. Accept the license agreements.
5. Double check the install details and then click "Install".
- Installation can take a very long time, go grab a cup of tea or something and let it work.
### Loading the project in Qt Creator (optional)
1. Open Qt Creator.
2. Choose `File->Open File or Project`.
3. Navigate to the Launcher source folder you cloned and choose CMakeLists.txt.
4. Read the instructions that just popped up about a build location and choose one.
5. You should see "Run CMake" in the window.
- Make sure that Generator is set to "Unix Generator (Desktop Qt 5.6.x GCC 64bit)".
- Hit the "Run CMake" button.
- You'll see warnings and it might not be clear that it succeeded until you scroll to the bottom of the window.
- Hit "Finish" if CMake ran successfully.
6. Cross your fingers and press the Run button (bottom left of Qt Creator).
- If the project builds successfully it will run and the Launcher window will pop up.
**If this doesn't work for you, let us know on our Discord.**
# Windows
Getting the project to build and run on Windows is easy if you use Qt's IDE, Qt Creator. The project will simply not compile using Microsoft build tools, because that's not something we do. If it does compile, it is by chance only.
## Dependencies
* [Qt 5.6+ Development tools](http://qt-project.org/downloads) -- Qt Online Installer for Windows
- http://download.qt.io/new_archive/qt/5.6/5.6.0/qt-opensource-windows-x86-mingw492-5.6.0.exe
- Download the MinGW version (MSVC version does not work).
* [OpenSSL](https://github.com/IndySockets/OpenSSL-Binaries/tree/master/Archive/) -- Win32 OpenSSL, version 1.0.2g (from 2016)
- https://github.com/IndySockets/OpenSSL-Binaries/raw/master/Archive/openssl-1.0.2g-i386-win32.zip
- the usual OpenSSL for Windows (http://slproweb.com/products/Win32OpenSSL.html) only provides the newest version of OpenSSL, and we need the 1.0.2g version
- **Download the 32-bit version, not 64-bit.**
- Microsoft Visual C++ 2008 Redist is required for this, there's a link on the OpenSSL download page above next to the main download.
- We use a custom build of OpenSSL that doesn't have this dependency. For normal development, the custom build is not necessary though.
* [zlib 1.2+](http://gnuwin32.sourceforge.net/packages/zlib.htm) - the Setup is fine
* [Java JDK 8](https://adoptium.net/releases.html?variant=openjdk8) - Use the MSI installer.
* [CMake](http://www.cmake.org/cmake/resources/software.html) -- Windows (Win32 Installer)
Ensure that OpenSSL, zlib, Java and CMake are on `PATH`.
## Getting set up
### Installing Qt
1. Run the Qt installer
2. Choose a place to install Qt (C:\Qt is the default),
3. Choose the components you want to install
- You need Qt 5.6 (32 bit) ticked,
- You need Tools/Qt Creator ticked,
- Other components are selected by default, you can untick them if you don't need them.
4. Accept the license agreements,
5. Double check the install details and then click "Install"
- Installation can take a very long time, go grab a cup of tea or something and let it work.
### Installing OpenSSL
1. Download .zip file from the link above.
2. Unzip and add the directory to PATH, so CMake can find it.
### Installing CMake
1. Run the CMake installer,
2. It's easiest if you choose to add CMake to the PATH for all users,
- If you don't choose to do this, remember where you installed CMake.
### Loading the project
1. Open Qt Creator,
2. Choose File->Open File or Project,
3. Navigate to the Launcher source folder you cloned and choose CMakeLists.txt,
4. Read the instructions that just popped up about a build location and choose one,
5. If you chose not to add CMake to the system PATH, tell Qt Creator where you installed it,
- Otherwise you can skip this step.
6. You should see "Run CMake" in the window,
- Make sure that Generator is set to "MinGW Generator (Desktop Qt 5.6.x MinGW 32bit)",
- Hit the "Run CMake" button,
- You'll see warnings and it might not be clear that it succeeded until you scroll to the bottom of the window.
- Hit "Finish" if CMake ran successfully.
7. Cross your fingers and press the Run button (bottom left of Qt Creator)!
- If the project builds successfully it will run and the Launcher window will pop up,
- Test OpenSSL by making an instance and trying to log in. If Qt Creator couldn't find OpenSSL during the CMake stage, login will fail and you'll get an error.
The following .dlls are needed for the app to run (copy them to build directory if you want to be able to move the build to another pc):
```
platforms/qwindows.dll
libeay32.dll
libgcc_s_dw2-1.dll
libssp-0.dll
libstdc++-6.dll
libwinpthread-1.dll
Qt5Core.dll
Qt5Gui.dll
Qt5Network.dll
Qt5Svg.dll
Qt5Widgets.dll
Qt5Xml.dll
ssleay32.dll
zlib1.dll
```
**These build instructions worked for me (Drayshak) on a fresh Windows 8 x64 Professional install. If they don't work for you, let us know on our Discord.**
### Compile from command line on Windows
1. If you installed Qt with the web installer, there should be a shortcut called `Qt 5.4 for Desktop (MinGW 4.9 32-bit)` in the Start menu on Windows 7 and 10. Best way to find it is to search for it. Do note you cannot just use cmd.exe, you have to use the shortcut, otherwise the proper MinGW software will not be on the PATH.
2. Once that is open, change into your user directory, and clone PolyMC by doing `git clone --recursive https://github.com/PolyMC/PolyMC.git`, and change directory to the folder you cloned to.
3. Make a build directory, and change directory to the directory and do `cmake -G "MinGW Makefiles" -DCMAKE_INSTALL_PREFIX=C:\Path\that\makes\sense\for\you`. By default, it will install to C:\Program Files (x86), which you might not want, if you want a local installation. If you want to install it to that directory, make sure to run the command window as administrator.
3. Do `mingw32-make -jX`, where X is the number of cores your CPU has plus one.
4. Now to wait for it to compile. This could take some time. Hopefully it compiles properly.
5. Run the command `mingw32-make install`, and it should install PolyMC, to whatever the `-DCMAKE_INSTALL_PREFIX` was.
6. In most cases, whenever compiling, the OpenSSL dll's aren't put into the directory to where PolyMC installs, meaning you cannot log in. The best way to fix this is just to do `copy C:\OpenSSL-Win32\*.dll C:\Where\you\installed\PolyMC\to`. This should copy the required OpenSSL dll's to log in.
# macOS
### Install prerequisites:
- Install XCode Command Line tools
- Install the official build of CMake (https://cmake.org/download/)
- Install JDK 8 (https://www.oracle.com/java/technologies/javase/javase-jdk8-downloads.html)
- Get Qt 5.6 and install it (https://download.qt.io/new_archive/qt/5.6/5.6.3/)
### XCode Command Line tools
If you don't have XCode CommandLine tools installed, you can install them by using this command in the Terminal App
```bash
xcode-select --install
```
### Build
Pick an installation path - this is where the final `.app` will be constructed when you run `make install`. Supply it as the `CMAKE_INSTALL_PREFIX` argument during CMake configuration.
```
git clone --recursive https://github.com/PolyMC/PolyMC.git
cd Launcher
mkdir build
cd build
cmake \
-DCMAKE_C_COMPILER=/usr/bin/clang \
-DCMAKE_CXX_COMPILER=/usr/bin/clang++ \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_INSTALL_PREFIX:PATH="$(dirname $PWD)/dist/" \
-DCMAKE_PREFIX_PATH="/path/to/Qt5.6/" \
-DQt5_DIR="/path/to/Qt5.6/" \
-DLauncher_LAYOUT=mac-bundle \
-DCMAKE_OSX_DEPLOYMENT_TARGET=10.7 \
..
make install
```
**Note:** The final app bundle may not run due to code signing issues, which
need to be fixed with `codesign -fs -`.
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

@ -46,12 +46,14 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DQT_NO_DEPRECATED_WARNINGS=Y")
##################################### Set Application options #####################################
######## Set URLs ########
set(Launcher_NEWS_RSS_URL "https://multimc.org/rss.xml" CACHE STRING "URL to fetch Launcher's news RSS feed from.")
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_OPEN_URL "https://polymc.org/news" CACHE STRING "URL that gets opened when the user clicks 'More News'")
set(Launcher_HELP_URL "https://polymc.org/wiki/%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(Launcher_VERSION_MAJOR 1)
set(Launcher_VERSION_MINOR 0)
set(Launcher_VERSION_HOTFIX 5)
set(Launcher_VERSION_MINOR 1)
set(Launcher_VERSION_HOTFIX 1)
# Build number
set(Launcher_VERSION_BUILD -1 CACHE STRING "Build number. -1 for no build number.")
@ -66,26 +68,37 @@ set(Launcher_UPDATER_BASE "" CACHE STRING "Base URL for the updater.")
set(Launcher_NOTIFICATION_URL "" CACHE STRING "URL for checking for notifications.")
# The metadata server
set(Launcher_META_URL "https://meta.multimc.org/v1/" CACHE STRING "URL to fetch Launcher's meta files from.")
# paste.ee API key
set(Launcher_PASTE_EE_API_KEY "utLvciUouSURFzfjPxLBf5W4ISsUX4pwBDF7N1AfZ" CACHE STRING "API key you can get from paste.ee when you register an account")
set(Launcher_META_URL "https://meta.polymc.org/v1/" CACHE STRING "URL to fetch Launcher's meta files from.")
# Imgur API Client ID
set(Launcher_IMGUR_CLIENT_ID "5b97b0713fba4a3" CACHE STRING "Client ID you can get from Imgur when you register an application")
# MSA Client ID
set(Launcher_MSA_CLIENT_ID "17b47edd-c884-4997-926d-9e7f9a6b4647" CACHE STRING "Client ID you can get from Microsoft Identity Platform when you register an application")
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")
# Bug tracker URL
set(Launcher_BUG_TRACKER_URL "https://github.com/PolyMC/PolyMC/issues" CACHE STRING "URL for the bug tracker.")
# Translations Platform URL
set(Launcher_TRANSLATIONS_URL "https://hosted.weblate.org/projects/polymc/polymc/" CACHE STRING "URL for the translations platform.")
# Matrix Space
set(Launcher_MATRIX_URL "https://matrix.to/#/#polymc:polymc.org" CACHE STRING "URL to the Matrix Space")
# Discord URL
set(Launcher_DISCORD_URL "https://discord.gg/Z52pwxWCHP" CACHE STRING "URL for the Discord guild.")
# Subreddit URL
set(Launcher_SUBREDDIT_URL "" CACHE STRING "URL for the subreddit.")
# Builds
# TODO: Launcher_FORCE_BUNDLED_LIBS should be off in the future, but as of QuaZip 1.2, we can't do that yet.
set(Launcher_FORCE_BUNDLED_LIBS ON 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")
#### Check the current Git commit and branch
include(GetGitRevisionDescription)
get_git_head_revision(Launcher_GIT_REFSPEC Launcher_GIT_COMMIT)
@ -94,6 +107,8 @@ message(STATUS "Git commit: ${Launcher_GIT_COMMIT}")
message(STATUS "Git refspec: ${Launcher_GIT_REFSPEC}")
set(Launcher_RELEASE_VERSION_NAME "${Launcher_VERSION_MAJOR}.${Launcher_VERSION_MINOR}.${Launcher_VERSION_HOTFIX}")
string(TIMESTAMP TODAY "%Y-%m-%d")
set(Launcher_RELEASE_TIMESTAMP "${TODAY}")
#### Custom target to just print the version.
add_custom_target(version echo "Version: ${Launcher_RELEASE_VERSION_NAME}")
@ -102,12 +117,20 @@ add_custom_target(tcversion echo "\\#\\#teamcity[setParameter name=\\'env.LAUNCH
################################ 3rd Party Libs ################################
# Find the required Qt parts
find_package(Qt5Core REQUIRED)
find_package(Qt5Widgets REQUIRED)
find_package(Qt5Concurrent REQUIRED)
find_package(Qt5Network REQUIRED)
find_package(Qt5Test REQUIRED)
find_package(Qt5Xml REQUIRED)
if(Launcher_QT_VERSION_MAJOR EQUAL 5)
set(QT_VERSION_MAJOR 5)
find_package(Qt5 REQUIRED COMPONENTS Core Widgets Concurrent Network Test Xml)
if(NOT Launcher_FORCE_BUNDLED_LIBS)
find_package(QuaZip-Qt5 REQUIRED)
endif()
if (NOT QuaZip-Qt5_FOUND)
set(QUAZIP_QT_MAJOR_VERSION ${QT_VERSION_MAJOR} CACHE STRING "Qt version to use (4, 5 or 6), defaults to ${QT_VERSION_MAJOR}" FORCE)
set(FORCE_BUNDLED_QUAZIP 1)
endif()
else()
message(FATAL_ERROR "Qt version ${Launcher_QT_VERSION_MAJOR} is not supported")
endif()
# The Qt5 cmake files don't provide its install paths, so ask qmake.
include(QMakeQuery)
@ -129,25 +152,15 @@ add_subdirectory(program_info)
####################################### Install layout #######################################
# How to install the build results
set(Launcher_LAYOUT "auto" CACHE STRING "The layout for the launcher installation (auto, win-bundle, lin-nodeps, lin-system, mac-bundle)")
set_property(CACHE Launcher_LAYOUT PROPERTY STRINGS auto win-bundle lin-nodeps lin-system mac-bundle)
# Install the build results according to platform
set(Launcher_PORTABLE 1 CACHE BOOL "The type of installation (Portable or System)")
if (Launcher_PORTABLE)
# launcher/Application.cpp will use this value
set(Launcher_APP_BINARY_DEFS "-DLAUNCHER_PORTABLE")
endif()
if(Launcher_LAYOUT STREQUAL "auto")
if(UNIX AND APPLE)
set(Launcher_LAYOUT_REAL "mac-bundle")
elseif(UNIX)
set(Launcher_LAYOUT_REAL "lin-nodeps")
elseif(WIN32)
set(Launcher_LAYOUT_REAL "win-bundle")
else()
message(FATAL_ERROR "Cannot choose a sensible install layout for your platform.")
endif()
else()
set(Launcher_LAYOUT_REAL ${Launcher_LAYOUT})
endif()
if(Launcher_LAYOUT_REAL STREQUAL "mac-bundle")
set(BINARY_DEST_DIR "${Launcher_Name}.app/Contents/MacOS")
set(LIBRARY_DEST_DIR "${Launcher_Name}.app/Contents/MacOS")
set(PLUGIN_DEST_DIR "${Launcher_Name}.app/Contents/MacOS")
@ -161,13 +174,13 @@ if(Launcher_LAYOUT_REAL STREQUAL "mac-bundle")
# Mac bundle settings
set(MACOSX_BUNDLE_BUNDLE_NAME "${Launcher_Name}")
set(MACOSX_BUNDLE_INFO_STRING "${Launcher_Name}: Minecraft launcher and management utility.")
set(MACOSX_BUNDLE_GUI_IDENTIFIER "org.multimc.${Launcher_Name}")
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_GUI_IDENTIFIER "org.polymc.${Launcher_Name}")
set(MACOSX_BUNDLE_BUNDLE_VERSION "${Launcher_VERSION_MAJOR}.${Launcher_VERSION_MINOR}.${Launcher_VERSION_HOTFIX}.${Launcher_VERSION_BUILD}")
set(MACOSX_BUNDLE_SHORT_VERSION_STRING "${Launcher_VERSION_MAJOR}.${Launcher_VERSION_MINOR}.${Launcher_VERSION_HOTFIX}.${Launcher_VERSION_BUILD}")
set(MACOSX_BUNDLE_LONG_VERSION_STRING "${Launcher_VERSION_MAJOR}.${Launcher_VERSION_MINOR}.${Launcher_VERSION_HOTFIX}.${Launcher_VERSION_BUILD}")
set(MACOSX_BUNDLE_ICON_FILE ${Launcher_Name}.icns)
set(MACOSX_BUNDLE_COPYRIGHT "Copyright 2015-2021 ${Launcher_Copyright}")
set(MACOSX_BUNDLE_COPYRIGHT "Copyright 2021-2022 ${Launcher_Copyright}")
# directories to look for dependencies
set(DIRS ${QT_LIBS_DIR} ${QT_LIBEXECS_DIR} ${CMAKE_LIBRARY_OUTPUT_DIRECTORY} ${CMAKE_RUNTIME_OUTPUT_DIRECTORY})
@ -178,47 +191,38 @@ if(Launcher_LAYOUT_REAL STREQUAL "mac-bundle")
# Add the icon
install(FILES ${Launcher_Branding_ICNS} DESTINATION ${RESOURCES_DEST_DIR} RENAME ${Launcher_Name}.icns)
elseif(Launcher_LAYOUT_REAL STREQUAL "lin-nodeps")
elseif(UNIX)
set(BINARY_DEST_DIR "bin")
if(Launcher_PORTABLE)
set(LIBRARY_DEST_DIR "bin")
set(PLUGIN_DEST_DIR "plugins")
set(BUNDLE_DEST_DIR ".")
set(RESOURCES_DEST_DIR ".")
set(JARS_DEST_DIR "bin/jars")
# Install basic runner script
configure_file(launcher/Launcher.in "${CMAKE_CURRENT_BINARY_DIR}/LauncherScript" @ONLY)
install(PROGRAMS "${CMAKE_CURRENT_BINARY_DIR}/LauncherScript" DESTINATION ${BUNDLE_DEST_DIR} RENAME ${Launcher_Name})
else()
set(LIBRARY_DEST_DIR "lib${LIB_SUFFIX}")
set(JARS_DEST_DIR "share/jars")
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")
# jars path is determined on runtime, relative to "Application root path", generally /usr for Launcher_PORTABLE=0
set(Launcher_APP_BINARY_DEFS "-DLAUNCHER_JARS_LOCATION=${JARS_DEST_DIR}")
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${Launcher_Desktop} DESTINATION ${LAUNCHER_DESKTOP_DEST_DIR})
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${Launcher_MetaInfo} DESTINATION ${LAUNCHER_METAINFO_DEST_DIR})
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/${Launcher_SVG} DESTINATION ${LAUNCHER_ICON_DEST_DIR})
endif()
# install as bundle with no dependencies included
set(INSTALL_BUNDLE "nodeps")
# Set RPATH
SET(Launcher_BINARY_RPATH "$ORIGIN/")
# Install basic runner script
configure_file(launcher/Launcher.in "${CMAKE_CURRENT_BINARY_DIR}/LauncherScript" @ONLY)
install(PROGRAMS "${CMAKE_CURRENT_BINARY_DIR}/LauncherScript" DESTINATION ${BUNDLE_DEST_DIR} RENAME ${Launcher_Name})
elseif(Launcher_LAYOUT_REAL STREQUAL "lin-system")
set(Launcher_BINARY_DEST_DIR "bin" CACHE STRING "Path to the binary directory")
set(Launcher_LIBRARY_DEST_DIR "lib${LIB_SUFFIX}" CACHE STRING "Path to the library directory")
set(Launcher_SHARE_DEST_DIR "share/polymc" CACHE STRING "Path to the shared data directory")
set(JARS_DEST_DIR "${Launcher_SHARE_DEST_DIR}/jars")
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(BINARY_DEST_DIR ${Launcher_BINARY_DEST_DIR})
set(LIBRARY_DEST_DIR ${Launcher_LIBRARY_DEST_DIR})
MESSAGE(STATUS "Compiling for linux system with ${Launcher_SHARE_DEST_DIR} and LAUNCHER_LINUX_DATADIR")
SET(Launcher_APP_BINARY_DEFS "-DMULTIMC_JARS_LOCATION=${CMAKE_INSTALL_PREFIX}/${JARS_DEST_DIR}" "-DLAUNCHER_LINUX_DATADIR")
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${Launcher_Desktop} DESTINATION ${Launcher_DESKTOP_DEST_DIR})
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${Launcher_MetaInfo} DESTINATION ${Launcher_METAINFO_DEST_DIR})
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/${Launcher_SVG} DESTINATION ${Launcher_ICON_DEST_DIR})
# install as bundle with no dependencies included
set(INSTALL_BUNDLE "nodeps")
elseif(Launcher_LAYOUT_REAL STREQUAL "win-bundle")
elseif(WIN32)
set(BINARY_DEST_DIR ".")
set(LIBRARY_DEST_DIR ".")
set(PLUGIN_DEST_DIR ".")
@ -235,7 +239,7 @@ elseif(Launcher_LAYOUT_REAL STREQUAL "win-bundle")
# install as bundle
set(INSTALL_BUNDLE "full")
else()
message(FATAL_ERROR "No sensible install layout set.")
message(FATAL_ERROR "Platform not supported")
endif()
################################ Included Libs ################################
@ -243,11 +247,9 @@ endif()
include(ExternalProject)
set_directory_properties(PROPERTIES EP_BASE External)
option(NBT_BUILD_SHARED "Build NBT shared library" ON)
option(NBT_BUILD_SHARED "Build NBT shared library" OFF)
option(NBT_USE_ZLIB "Build NBT library with zlib support" OFF)
option(NBT_BUILD_TESTS "Build NBT library tests" OFF) #FIXME: fix unit tests.
set(NBT_NAME Launcher_nbt++)
set(NBT_DEST_DIR ${LIBRARY_DEST_DIR})
add_subdirectory(libraries/libnbtplusplus)
add_subdirectory(libraries/systeminfo) # system information library
@ -255,7 +257,12 @@ add_subdirectory(libraries/hoedown) # markdown parser
add_subdirectory(libraries/launcher) # java based launcher part for Minecraft
add_subdirectory(libraries/javacheck) # java compatibility checker
add_subdirectory(libraries/xz-embedded) # xz compression
if (FORCE_BUNDLED_QUAZIP)
message(STATUS "Using bundled QuaZip")
set(BUILD_SHARED_LIBS 0) # link statically to avoid conflicts.
set(QUAZIP_INSTALL 0)
add_subdirectory(libraries/quazip) # zip manipulation library
endif()
add_subdirectory(libraries/rainbow) # Qt extension for colors
add_subdirectory(libraries/iconfix) # fork of Qt's QIcon loader
add_subdirectory(libraries/LocalPeer) # fork of a library from Qt solutions

136
CODE_OF_CONDUCT.md Normal file
View File

@ -0,0 +1,136 @@
# Contributor Covenant Code of Conduct
This is a modified version of the Contributor Covenant.
See commit history to see our changes.
## Our Pledge
We as members, contributors, and leaders pledge to make participation in our
community a harassment-free experience for everyone, regardless of age, body
size, visible or invisible disability, ethnicity, sex characteristics, gender
identity and expression, level of experience, education, socio-economic status,
nationality, personal appearance, race, caste, color, religion, or sexual
identity and orientation.
We pledge to act and interact in ways that contribute to an open, welcoming,
diverse, inclusive, and healthy community.
## Our Standards
Examples of behavior that contributes to a positive environment for our
community include:
* Demonstrating empathy and kindness toward other people
* Being respectful of differing opinions, viewpoints, and experiences
* Giving and gracefully accepting constructive feedback
* Accepting responsibility and apologizing to those affected by our mistakes,
and learning from the experience
* Focusing on what is best not just for us as individuals, but for the overall
community
Examples of unacceptable behavior include:
* The use of sexualized language or imagery, and sexual attention or advances of
any kind
* Trolling (antagonistic, inflammatory, insincere behaviour), insulting or derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or email address,
without their explicit permission
* Other conduct which could reasonably be considered inappropriate in a
professional setting
## Enforcement Responsibilities
Community leaders are responsible for clarifying and enforcing our standards of
acceptable behavior and will take appropriate and fair corrective action in
response to any behavior that they deem inappropriate, threatening, offensive,
or harmful.
Community leaders have the right and responsibility to remove, edit, or reject
comments, commits, code, wiki edits, issues, and other contributions that are
not aligned to this Code of Conduct, and will communicate reasons for moderation
decisions when appropriate.
## Scope
This Code of Conduct applies within all community spaces, and also applies when
an individual is officially representing the community in public spaces.
Examples of representing our community include using an official e-mail address,
posting via an official social media account, or acting as an appointed
representative at an online or offline event.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported to the community leaders responsible for enforcement via email at
[polymc-enforcement@scrumplex.net](mailto:polymc-enforcement@scrumplex.net) (Email
address subject to change).
All complaints will be reviewed and investigated promptly and fairly.
All community leaders are obligated to respect the privacy and security of the
reporter of any incident.
## Enforcement Guidelines
Community leaders will follow these Community Impact Guidelines in determining
the consequences for any action they deem in violation of this Code of Conduct:
### 1. Correction
**Community Impact**: Use of inappropriate language or other behavior deemed
unprofessional or unwelcome in the community.
**Consequence**: A private, written warning from community leaders, providing
clarity around the nature of the violation and an explanation of why the
behavior was inappropriate. A public apology may be requested.
### 2. Warning
**Community Impact**: A violation through a single incident or series of
actions.
**Consequence**: A warning with consequences for continued behavior. No
interaction with the people involved, including unsolicited interaction with
those enforcing the Code of Conduct, for a specified period of time. This
includes avoiding interactions in community spaces as well as external channels
like social media. Violating these terms may lead to a temporary or permanent
ban.
### 3. Temporary Ban
**Community Impact**: A serious violation of community standards, including
sustained inappropriate behavior.
**Consequence**: A temporary ban from any sort of interaction or public
communication with the community for a specified period of time. No public or
private interaction with the people involved, including unsolicited interaction
with those enforcing the Code of Conduct, is allowed during this period.
Violating these terms may lead to a permanent ban.
### 4. Permanent Ban
**Community Impact**: Demonstrating a pattern of violation of community
standards, including sustained inappropriate behavior, harassment of an
individual, or aggression toward or disparagement of classes of individuals.
**Consequence**: A permanent ban from any sort of public interaction within the
community.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
version 2.1, available at
[https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1].
Community Impact Guidelines were inspired by
[Mozilla's code of conduct enforcement ladder][Mozilla CoC].
For answers to common questions about this code of conduct, see the FAQ at
[https://www.contributor-covenant.org/faq][FAQ]. Translations are available at
[https://www.contributor-covenant.org/translations][translations].
[homepage]: https://www.contributor-covenant.org
[v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html
[Mozilla CoC]: https://github.com/mozilla/diversity
[FAQ]: https://www.contributor-covenant.org/faq
[translations]: https://www.contributor-covenant.org/translations

View File

@ -1,12 +1,11 @@
# PolyMC
Copyright (C) 2012-2021 MultiMC Contributors
Copyright (C) 2021 PolyMC Contributors
Copyright (C) 2021-2022 PolyMC 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, either version 3 of the License, or
(at your option) any later version.
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
@ -16,6 +15,20 @@
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
# Launcher (https://github.com/MultiMC/Launcher)
Copyright 2012-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.
# MinGW runtime (Windows)
Copyright (c) 2012 MinGW.org project

View File

@ -1,55 +1,32 @@
<p align="center">
<img src="/program_info/polymc-light.png#gh-light-mode-only" alt="PolyMC logo"/>
<img src="/program_info/polymc-dark.png#gh-dark-mode-only" alt="PolyMC logo"/>
<img src="./program_info/polymc-header-black.svg#gh-light-mode-only" alt="PolyMC logo"/>
<img src="./program_info/polymc-header.svg#gh-dark-mode-only" alt="PolyMC logo"/>
</p>
<br>
PolyMC is a custom launcher for Minecraft that focuses on predictability, long term stability and simplicity.
This is a **fork** of the MultiMC Launcher and not endorsed by MultiMC. The PolyMC community felt that the maintainer was not acting in the spirit of Free Software so this fork was made. Read "[Why was this fork made?](https://github.com/PolyMC/PolyMC/wiki/FAQ)" on the wiki for more details.
## Packages
Several source build packages are available, along with experimental pre-built generic packages.
<a href='https://flathub.org/apps/details/org.polymc.PolyMC'><img width='240' alt='Download on Flathub' src='https://flathub.org/assets/badges/flathub-badge-en.png'/></a>
This is a **fork** of the MultiMC Launcher and not endorsed by MultiMC. The PolyMC community felt that the maintainer was not acting in the spirit of Free Software so this fork was made.
<br>
[![AUR package](https://img.shields.io/aur/version/polymc-git)](https://aur.archlinux.org/packages/polymc-git/)
- A [Nix](packages/nix/NIX.md) derivation is available in repo.
- A Gentoo ebuild is available in the [swirl](https://git.swurl.xyz/swirl/ebuilds) overlay, named `games-action/polymc`. Check the README for instructions on how to add the overlay.
- The Flatpak can be built using [this source](https://github.com/flathub/org.polymc.PolyMC).
- An RPM package is available on [COPR](https://copr.fedorainfracloud.org/coprs/sentry/polymc/), or can be built by going to the `packages/rpm` directory and running `rpmbuild -bb polymc.spec`.
- Generic, prebuilt packages (archived by version) can be found [here](https://packages.polymc.org/) ([latest](https://packages.polymc.org/latest)).
- Last build status: https://jenkins.polymc.org/job/PolyMC/lastBuild/
- [Linux (AMD64) System](https://packages.polymc.org/latest/lin64-system/lin64-system.tar.zst) ([SHA256](https://packages.polymc.org/latest/lin64-system/lin64-system.tar.zst.sha256)) - this is a generic system package intended to be used as a base for making distro-specific packages.
- [Windows (32-bit)](https://packages.polymc.org/latest/win32/win32.zip) ([SHA256](https://packages.polymc.org/latest/win32/win32.zip.sha256)) - this is a portable package, you can extract it anywhere and run it. This package needs testing.
- [Debian (AMD64)](https://packages.polymc.org/latest/deb/polymc-amd64.deb) ([SHA256](https://packages.polymc.org/latest/deb/polymc-amd64.deb.sha256)) - this is intended to be installed with `dpkg -i`. Alternatively, you may build the `.deb` yourself, by going to `packages/debian` and running `./makedeb.sh`.
- [AppImage (AMD64)](https://packages.polymc.org/latest/appimage/PolyMC-latest-x86_64.AppImage) ([SHA256](https://packages.polymc.org/latest/appimage/PolyMC-latest-x86_64.AppImage.sha256)) - `chmod +x` must be run on this file before usage. This should work on any distribution.
- MacOS currently does not have any packages. We are still working on setting up MacOS packaging.
## Development
If you want to contribute to PolyMC you might find it useful to join [#development:polymc.org on Matrix](https://matrix.to/#/#development:polymc.org) or join [our Discord server](https://discord.gg/xq7fxrgtMP), which is bridged with the PolyMC Matrix rooms. Thank you!
# Installation
### Building
If you want to build PolyMC yourself, check [BUILD.md](BUILD.md) for build instructions.
- All downloads and instructions for PolyMC can be found [here](https://polymc.org/download/)
- Last build status: https://github.com/PolyMC/PolyMC/actions
You can build the flatpak using [this source](https://github.com/flathub/org.polymc.PolyMC).
### Code formatting
Just follow the existing formatting.
## Development Builds
In general, in order of importance:
* Make sure your IDE is not messing up line endings or whitespace and avoid using linters.
* Prefer readability over dogma.
* Keep to the existing formatting.
* Indent with 4 space unless it's in a submodule.
* Keep lists (of arguments, parameters, initializers...) as lists, not paragraphs. It should either read from top to bottom, or left to right. Not both.
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.
Portable builds are provided for AppImage on Linux, Windows, and macOS.
## Translations
TODO
For Debian and Arch, 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)
## Forking/Redistributing/Custom builds policy
Do whatever you want, we don't care. Just follow the license. If you have any questions about this feel free to ask in an issue.
# Help & Support
## Help & Support
Feel free to create an issue if you need help. However, you might find it easier to ask in the Discord server.
[![PolyMC Discord](https://img.shields.io/discord/923671181020766230?label=PolyMC%20Discord)](https://discord.gg/xq7fxrgtMP)
@ -64,3 +41,34 @@ If there are any issues with the space or you are using a client that does not s
[![Discussion](https://img.shields.io/matrix/discussion:polymc.org?label=%23discussion&server_fqdn=matrix.polymc.org)](https://matrix.to/#/#discussion:polymc.org)
[![Development](https://img.shields.io/matrix/development:polymc.org?label=%23development&server_fqdn=matrix.polymc.org)](https://matrix.to/#/#development:polymc.org)
[![News](https://img.shields.io/matrix/news:polymc.org?label=%23news&server_fqdn=matrix.polymc.org)](https://matrix.to/#/#news:polymc.org)
# Development
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.md](BUILD.md) for build instructions.
## Code formatting
Just follow the existing formatting.
In general, in order of importance:
- Make sure your IDE is not messing up line endings or whitespace and avoid using linters.
- Prefer readability over dogma.
- Keep to the existing formatting.
- Indent with 4 space unless it's in a submodule.
- Keep lists (of arguments, parameters, initializers...) as lists, not paragraphs. It should either read from top to bottom, or left to right. Not both.
## 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
## Download infomation
To modify download infomation or change packaging infomation send a pull request or issue to the website [Here](https://github.com/PolyMC/polymc.github.io/blob/master/src/download.md)
## Forking/Redistributing/Custom builds policy
Do whatever you want, we don't care. Just follow the license. If you have any questions about this feel free to ask in an issue.

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.
*/
#include "BuildConfig.h"
#include <QObject>
@ -12,6 +47,7 @@ Config::Config()
LAUNCHER_DOMAIN = "@Launcher_Domain@";
LAUNCHER_CONFIGFILE = "@Launcher_ConfigFile@";
LAUNCHER_GIT = "@Launcher_Git@";
LAUNCHER_DESKTOPFILENAME = "@Launcher_DesktopFileName@";
USER_AGENT = "@Launcher_UserAgent@";
USER_AGENT_UNCACHED = USER_AGENT + " (Uncached)";
@ -29,25 +65,38 @@ Config::Config()
GIT_COMMIT = "@Launcher_GIT_COMMIT@";
GIT_REFSPEC = "@Launcher_GIT_REFSPEC@";
if(GIT_REFSPEC.startsWith("refs/heads/") && !UPDATER_BASE.isEmpty() && !BUILD_PLATFORM.isEmpty() && VERSION_BUILD >= 0)
if (GIT_REFSPEC == QStringLiteral("GITDIR-NOTFOUND"))
{
VERSION_CHANNEL = QStringLiteral("stable");
}
else if(GIT_REFSPEC.startsWith("refs/heads/"))
{
VERSION_CHANNEL = GIT_REFSPEC;
VERSION_CHANNEL.remove("refs/heads/");
if(!UPDATER_BASE.isEmpty() && !BUILD_PLATFORM.isEmpty() && VERSION_BUILD >= 0) {
UPDATER_ENABLED = true;
}
}
else if (!GIT_COMMIT.isEmpty())
{
VERSION_CHANNEL = GIT_COMMIT.mid(0, 8);
}
else
{
VERSION_CHANNEL = QObject::tr("custom");
VERSION_CHANNEL = QObject::tr("unknown");
}
VERSION_STR = "@Launcher_VERSION_STRING@";
NEWS_RSS_URL = "@Launcher_NEWS_RSS_URL@";
PASTE_EE_KEY = "@Launcher_PASTE_EE_API_KEY@";
NEWS_OPEN_URL = "@Launcher_NEWS_OPEN_URL@";
HELP_URL = "@Launcher_HELP_URL@";
IMGUR_CLIENT_ID = "@Launcher_IMGUR_CLIENT_ID@";
MSA_CLIENT_ID = "@Launcher_MSA_CLIENT_ID@";
META_URL = "@Launcher_META_URL@";
BUG_TRACKER_URL = "@Launcher_BUG_TRACKER_URL@";
TRANSLATIONS_URL = "@Launcher_TRANSLATIONS_URL@";
MATRIX_URL = "@Launcher_MATRIX_URL@";
DISCORD_URL = "@Launcher_DISCORD_URL@";
SUBREDDIT_URL = "@Launcher_SUBREDDIT_URL@";
}

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
#include <QString>
@ -14,6 +49,7 @@ public:
QString LAUNCHER_DOMAIN;
QString LAUNCHER_CONFIGFILE;
QString LAUNCHER_GIT;
QString LAUNCHER_DESKTOPFILENAME;
/// The major version number.
int VERSION_MAJOR;
@ -68,9 +104,14 @@ public:
QString NEWS_RSS_URL;
/**
* API key you can get from paste.ee when you register an account
* URL that gets opened when the user clicks "More News"
*/
QString PASTE_EE_KEY;
QString NEWS_OPEN_URL;
/**
* URL (with arg %1 to be substituted with page-id) that gets opened when the user requests help
*/
QString HELP_URL;
/**
* Client ID you can get from Imgur when you register an application
@ -88,6 +129,8 @@ public:
QString META_URL;
QString BUG_TRACKER_URL;
QString TRANSLATIONS_URL;
QString MATRIX_URL;
QString DISCORD_URL;
QString SUBREDDIT_URL;
@ -95,8 +138,8 @@ public:
QString LIBRARY_BASE = "https://libraries.minecraft.net/";
QString AUTH_BASE = "https://authserver.mojang.com/";
QString IMGUR_BASE_URL = "https://api.imgur.com/3/";
QString FMLLIBS_BASE_URL = "https://files.multimc.org/fmllibs/";
QString TRANSLATIONS_BASE_URL = "https://files.multimc.org/translations/";
QString FMLLIBS_BASE_URL = "https://files.polymc.org/fmllibs/";
QString TRANSLATIONS_BASE_URL = "https://i18n.polymc.org/";
QString MODPACKSCH_API_BASE_URL = "https://api.modpacks.ch/";

File diff suppressed because it is too large Load Diff

View File

@ -14,7 +14,7 @@ BEGIN
BEGIN
BLOCK "000004b0"
BEGIN
VALUE "CompanyName", "MultiMC Contributors"
VALUE "CompanyName", "MultiMC & PolyMC Contributors"
VALUE "FileDescription", "Testcase"
VALUE "FileVersion", "1.0.0.0"
VALUE "ProductName", "Launcher Testcase"

22
flake.lock generated
View File

@ -18,11 +18,11 @@
},
"flake-utils": {
"locked": {
"lastModified": 1638122382,
"narHash": "sha256-sQzZzAbvKEqN9s0bzWuYmRaA03v40gaJ4+iL1LXjaeI=",
"lastModified": 1642700792,
"narHash": "sha256-XqHrk7hFb+zBvRg6Ghl+AZDq03ov6OshJLiSWOoX5es=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "74f7e4319258e287b0f9cb95426c9853b282730b",
"rev": "846b2ae0fc4cc943637d3d1def4454213e203cba",
"type": "github"
},
"original": {
@ -49,11 +49,11 @@
},
"nixpkgs": {
"locked": {
"lastModified": 1641528457,
"narHash": "sha256-FyU9E63n1W7Ql4pMnhW2/rO9OftWZ37pLppn/c1aisY=",
"lastModified": 1643169865,
"narHash": "sha256-+KIpNRazbc8Gac9jdWCKQkFv9bjceaLaLhlwqUEYu8c=",
"owner": "nixos",
"repo": "nixpkgs",
"rev": "ff377a78794d412a35245e05428c8f95fef3951f",
"rev": "945ec499041db73043f745fad3b2a3a01e826081",
"type": "github"
},
"original": {
@ -66,15 +66,15 @@
"quazip": {
"flake": false,
"locked": {
"lastModified": 1633895098,
"narHash": "sha256-+Of0M2IAoTf1CyC0teCpsyurv6xfqiBo84V49dSeNTA=",
"owner": "multimc",
"lastModified": 1643049383,
"narHash": "sha256-LcJY6yd6GyeL7X5MP4L94diceM1TYespWByliBsjK98=",
"owner": "stachenov",
"repo": "quazip",
"rev": "b1a72ac0bb5a732bf887a535ab75c6f9bedb6b6b",
"rev": "09ec1d10c6d627f895109b21728dda000cbfa7d1",
"type": "github"
},
"original": {
"owner": "multimc",
"owner": "stachenov",
"repo": "quazip",
"type": "github"
}

View File

@ -11,17 +11,26 @@
flake = false;
};
inputs.quazip = {
url = "github:multimc/quazip";
url = "github:stachenov/quazip";
flake = false;
};
outputs = inputs@{ self, nixpkgs, flake-utils, libnbtplusplus, quazip, ... }:
flake-utils.lib.eachSystem [ "x86_64-linux" "aarch64-linux" ] (system:
outputs = args@{ self, nixpkgs, flake-utils, libnbtplusplus, quazip, ... }:
let
pkgs = import nixpkgs {
inherit system;
systems = [
"aarch64-linux"
# "aarch64-darwin" # qtbase is currently broken
"i686-linux"
"x86_64-darwin"
"x86_64-linux"
];
in {
overlay = final: prev: {
inherit (self.packages.${final.system}) polymc;
};
} // flake-utils.lib.eachSystem systems (system:
let pkgs = import nixpkgs { inherit system; };
in {
packages = {
polymc = pkgs.libsForQt5.callPackage ./packages/nix/polymc {
inherit self;
@ -29,27 +38,13 @@
submoduleNbt = libnbtplusplus;
};
};
# 'nix flake check' fails
overlay = (final: prev: rec {
polymc = prev.libsForQt5.callPackage ./packages/nix/polymc {
inherit self;
submoduleQuazip = quazip;
submoduleNbt = libnbtplusplus;
};
});
apps = {
polymc = flake-utils.lib.mkApp {
name = "polymc";
drv = packages.polymc;
drv = self.packages.${system}.polymc;
};
};
in
{
inherit packages overlay apps;
defaultPackage = packages.polymc;
defaultApp = apps.polymc;
}
);
defaultPackage = self.packages.${system}.polymc;
defaultApp = self.apps.${system}.polymc;
});
}

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.
*/
#include "Application.h"
#include "BuildConfig.h"
@ -14,7 +49,7 @@
#include "ui/pages/global/ProxyPage.h"
#include "ui/pages/global/ExternalToolsPage.h"
#include "ui/pages/global/AccountListPage.h"
#include "ui/pages/global/PasteEEPage.h"
#include "ui/pages/global/APIPage.h"
#include "ui/pages/global/CustomCommandsPage.h"
#include "ui/themes/ITheme.h"
@ -187,29 +222,10 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv)
setApplicationName(BuildConfig.LAUNCHER_NAME);
setApplicationDisplayName(BuildConfig.LAUNCHER_DISPLAYNAME);
setApplicationVersion(BuildConfig.printableVersionString());
startTime = QDateTime::currentDateTime();
#ifdef Q_OS_LINUX
{
QFile osrelease("/proc/sys/kernel/osrelease");
if (osrelease.open(QFile::ReadOnly | QFile::Text)) {
QTextStream in(&osrelease);
auto contents = in.readAll();
if(
contents.contains("WSL", Qt::CaseInsensitive) ||
contents.contains("Microsoft", Qt::CaseInsensitive)
) {
showFatalErrorMessage(
"Unsupported system detected!",
"Linux-on-Windows distributions are not supported.\n\n"
"Please use the Windows binary when playing on Windows."
);
return;
}
}
}
#if (QT_VERSION >= QT_VERSION_CHECK(5,7,0))
setDesktopFileName(BuildConfig.LAUNCHER_DESKTOPFILENAME);
#endif
startTime = QDateTime::currentDateTime();
// Don't quit on hiding the last window
this->setQuitOnLastWindowClosed(false);
@ -283,12 +299,21 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv)
return;
}
}
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
if((!m_serverToJoin.isEmpty() || !m_profileToUse.isEmpty()) && m_instanceIdToLaunch.isEmpty())
{
std::cerr << "--server and --profile can only be used in combination with --launch!" << std::endl;
m_status = Application::Failed;
return;
}
QString origcwdPath = QDir::currentPath();
QString binPath = applicationDirPath();
QString adjustedBy;
@ -304,16 +329,20 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv)
}
else
{
#ifdef LAUNCHER_LINUX_DATADIR
QString xdgDataHome = QFile::decodeName(qgetenv("XDG_DATA_HOME"));
if (xdgDataHome.isEmpty())
xdgDataHome = QDir::homePath() + QLatin1String("/.local/share");
dataPath = xdgDataHome + "/polymc";
adjustedBy += "XDG standard " + dataPath;
#elif defined(Q_OS_MAC)
QDir foo(FS::PathCombine(applicationDirPath(), "../../Data"));
#if !defined(LAUNCHER_PORTABLE) || defined(Q_OS_MAC)
QDir foo(FS::PathCombine(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation), ".."));
dataPath = foo.absolutePath();
adjustedBy += "Fallback to special Mac location " + dataPath;
adjustedBy += dataPath;
#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 " + dataPath;
}
#endif
#else
dataPath = applicationDirPath();
adjustedBy += "Fallback to binary path " + dataPath;
@ -357,20 +386,6 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv)
return;
}
if(m_instanceIdToLaunch.isEmpty() && !m_serverToJoin.isEmpty())
{
std::cerr << "--server can only be used in combination with --launch!" << std::endl;
m_status = Application::Failed;
return;
}
if(m_instanceIdToLaunch.isEmpty() && !m_profileToUse.isEmpty())
{
std::cerr << "--account can only be used in combination with --launch!" << std::endl;
m_status = Application::Failed;
return;
}
#if defined(Q_OS_MAC)
// move user data to new location if on macOS and it still exists in Contents/MacOS
QDir fi(applicationDirPath());
@ -435,7 +450,7 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv)
#endif
/*
* Establish the mechanism for communication with an already running MultiMC that uses the same data path.
* Establish the mechanism for communication with an already running PolyMC that uses the same data path.
* 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.
*/
@ -535,8 +550,8 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv)
FS::updateTimestamp(m_rootPath);
#endif
#ifdef MULTIMC_JARS_LOCATION
m_jarsPath = TOSTRING(MULTIMC_JARS_LOCATION);
#ifdef LAUNCHER_JARS_LOCATION
m_jarsPath = TOSTRING(LAUNCHER_JARS_LOCATION);
#endif
qDebug() << BuildConfig.LAUNCHER_DISPLAYNAME << ", (c) 2013-2021 " << BuildConfig.LAUNCHER_COPYRIGHT;
@ -566,26 +581,23 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv)
qDebug() << "<> Paths set.";
}
do // once
{
if(m_liveCheck)
{
QFile check(liveCheckFile);
if(!check.open(QIODevice::WriteOnly | QIODevice::Truncate))
if(check.open(QIODevice::WriteOnly | QIODevice::Truncate))
{
qWarning() << "Could not open" << liveCheckFile << "for writing!";
break;
}
auto payload = appID.toString().toUtf8();
if(check.write(payload) != payload.size())
if(check.write(payload) == payload.size())
{
qWarning() << "Could not write into" << liveCheckFile << "!";
check.remove();
break;
}
check.close();
} else {
qWarning() << "Could not write into" << liveCheckFile << "!";
check.remove(); // also closes file!
}
} else {
qWarning() << "Could not open" << liveCheckFile << "for writing!";
}
}
} while(false);
// Initialize application settings
{
@ -595,7 +607,7 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv)
m_settings->registerSetting("AutoUpdate", true);
// Theming
m_settings->registerSetting("IconTheme", QString("multimc"));
m_settings->registerSetting("IconTheme", QString("pe_colored"));
m_settings->registerSetting("ApplicationTheme", QString("system"));
// Notifications
@ -662,7 +674,7 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv)
// Memory
m_settings->registerSetting({"MinMemAlloc", "MinMemoryAlloc"}, 512);
m_settings->registerSetting({"MaxMemAlloc", "MaxMemoryAlloc"}, 1024);
m_settings->registerSetting({"MaxMemAlloc", "MaxMemoryAlloc"}, 4096);
m_settings->registerSetting("PermGen", 128);
// Java Settings
@ -714,8 +726,13 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv)
m_settings->registerSetting("UpdateDialogGeometry", "");
// paste.ee API key
m_settings->registerSetting("PasteEEAPIKey", "multimc");
// pastebin URL
m_settings->registerSetting("PastebinURL", "https://0x0.st");
m_settings->registerSetting("CloseAfterLaunch", false);
// Custom MSA credentials
m_settings->registerSetting("MSAClientIDOverride", "");
// Init page provider
{
@ -728,7 +745,7 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv)
m_globalSettingsProvider->addPage<ProxyPage>();
m_globalSettingsProvider->addPage<ExternalToolsPage>();
m_globalSettingsProvider->addPage<AccountListPage>();
m_globalSettingsProvider->addPage<PasteEEPage>();
m_globalSettingsProvider->addPage<APIPage>();
}
qDebug() << "<> Settings loaded.";
}
@ -1512,5 +1529,15 @@ QString Application::getJarsPath()
{
return FS::PathCombine(QCoreApplication::applicationDirPath(), "jars");
}
return m_jarsPath;
return FS::PathCombine(m_rootPath, m_jarsPath);
}
QString Application::getMSAClientID()
{
QString clientIDOverride = m_settings->get("MSAClientIDOverride").toString();
if (!clientIDOverride.isEmpty()) {
return clientIDOverride;
}
return BuildConfig.MSA_CLIENT_ID;
}

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
#include <QApplication>
@ -117,6 +152,8 @@ public:
QString getJarsPath();
QString getMSAClientID();
/// this is the root of the 'installation'. Used for automatic updates
const QString &root() {
return m_rootPath;

View File

@ -1,4 +1,24 @@
/* Copyright 2013-2021 MultiMC Contributors
// 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.
@ -39,6 +59,7 @@ BaseInstance::BaseInstance(SettingsObjectPtr globalSettings, SettingsObjectPtr s
m_settings->registerSetting("lastLaunchTime", 0);
m_settings->registerSetting("totalTimePlayed", 0);
m_settings->registerSetting("lastTimePlayed", 0);
m_settings->registerSetting("InstanceType", "OneSix");
// Custom Commands
auto commandSetting = m_settings->registerSetting({"OverrideCommands","OverrideLaunchCmd"}, false);

View File

@ -1,4 +1,24 @@
/* Copyright 2013-2021 MultiMC Contributors
// 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.

View File

@ -37,6 +37,10 @@ set(CORE_SOURCES
InstanceImportTask.h
InstanceImportTask.cpp
# Mod downloading task
ModDownloadTask.h
ModDownloadTask.cpp
# Use tracking separate from memory management
Usable.h
@ -221,7 +225,11 @@ set(MINECRAFT_SOURCES
minecraft/auth/flows/Mojang.h
minecraft/auth/flows/MSA.cpp
minecraft/auth/flows/MSA.h
minecraft/auth/flows/Offline.cpp
minecraft/auth/flows/Offline.h
minecraft/auth/steps/OfflineStep.cpp
minecraft/auth/steps/OfflineStep.h
minecraft/auth/steps/EntitlementsStep.cpp
minecraft/auth/steps/EntitlementsStep.h
minecraft/auth/steps/GetSkinStep.cpp
@ -278,13 +286,6 @@ set(MINECRAFT_SOURCES
minecraft/launch/VerifyJavaInstall.cpp
minecraft/launch/VerifyJavaInstall.h
minecraft/legacy/LegacyModList.h
minecraft/legacy/LegacyModList.cpp
minecraft/legacy/LegacyInstance.h
minecraft/legacy/LegacyInstance.cpp
minecraft/legacy/LegacyUpgradeTask.h
minecraft/legacy/LegacyUpgradeTask.cpp
minecraft/GradleSpecifier.h
minecraft/MinecraftInstance.cpp
minecraft/MinecraftInstance.h
@ -506,12 +507,19 @@ set(FLAME_SOURCES
# Flame
modplatform/flame/FlamePackIndex.cpp
modplatform/flame/FlamePackIndex.h
modplatform/flame/FlameModIndex.cpp
modplatform/flame/FlameModIndex.h
modplatform/flame/PackManifest.h
modplatform/flame/PackManifest.cpp
modplatform/flame/FileResolvingTask.h
modplatform/flame/FileResolvingTask.cpp
)
set(MODRINTH_SOURCES
modplatform/modrinth/ModrinthPackIndex.cpp
modplatform/modrinth/ModrinthPackIndex.h
)
set(MODPACKSCH_SOURCES
modplatform/modpacksch/FTBPackInstallTask.h
modplatform/modpacksch/FTBPackInstallTask.cpp
@ -566,6 +574,7 @@ set(LOGIC_SOURCES
${ICONS_SOURCES}
${FTB_SOURCES}
${FLAME_SOURCES}
${MODRINTH_SOURCES}
${MODPACKSCH_SOURCES}
${TECHNIC_SOURCES}
${ATLAUNCHER_SOURCES}
@ -685,8 +694,6 @@ SET(LAUNCHER_SOURCES
ui/pages/instance/OtherLogsPage.h
ui/pages/instance/ServersPage.cpp
ui/pages/instance/ServersPage.h
ui/pages/instance/LegacyUpgradePage.cpp
ui/pages/instance/LegacyUpgradePage.h
ui/pages/instance/WorldListPage.cpp
ui/pages/instance/WorldListPage.h
@ -707,8 +714,8 @@ SET(LAUNCHER_SOURCES
ui/pages/global/LauncherPage.h
ui/pages/global/ProxyPage.cpp
ui/pages/global/ProxyPage.h
ui/pages/global/PasteEEPage.cpp
ui/pages/global/PasteEEPage.h
ui/pages/global/APIPage.cpp
ui/pages/global/APIPage.h
# GUI - platform pages
ui/pages/modplatform/VanillaPage.cpp
@ -739,6 +746,10 @@ SET(LAUNCHER_SOURCES
ui/pages/modplatform/flame/FlameModel.h
ui/pages/modplatform/flame/FlamePage.cpp
ui/pages/modplatform/flame/FlamePage.h
ui/pages/modplatform/flame/FlameModModel.cpp
ui/pages/modplatform/flame/FlameModModel.h
ui/pages/modplatform/flame/FlameModPage.cpp
ui/pages/modplatform/flame/FlameModPage.h
ui/pages/modplatform/technic/TechnicModel.cpp
ui/pages/modplatform/technic/TechnicModel.h
@ -748,6 +759,11 @@ SET(LAUNCHER_SOURCES
ui/pages/modplatform/ImportPage.cpp
ui/pages/modplatform/ImportPage.h
ui/pages/modplatform/modrinth/ModrinthModel.cpp
ui/pages/modplatform/modrinth/ModrinthModel.h
ui/pages/modplatform/modrinth/ModrinthPage.cpp
ui/pages/modplatform/modrinth/ModrinthPage.h
# GUI - dialogs
ui/dialogs/AboutDialog.cpp
ui/dialogs/AboutDialog.h
@ -769,6 +785,8 @@ SET(LAUNCHER_SOURCES
ui/dialogs/LoginDialog.h
ui/dialogs/MSALoginDialog.cpp
ui/dialogs/MSALoginDialog.h
ui/dialogs/OfflineLoginDialog.cpp
ui/dialogs/OfflineLoginDialog.h
ui/dialogs/NewComponentDialog.cpp
ui/dialogs/NewComponentDialog.h
ui/dialogs/NewInstanceDialog.cpp
@ -779,12 +797,16 @@ SET(LAUNCHER_SOURCES
ui/pagedialog/PageDialog.h
ui/dialogs/ProgressDialog.cpp
ui/dialogs/ProgressDialog.h
ui/dialogs/ReviewMessageBox.cpp
ui/dialogs/ReviewMessageBox.h
ui/dialogs/UpdateDialog.cpp
ui/dialogs/UpdateDialog.h
ui/dialogs/VersionSelectDialog.cpp
ui/dialogs/VersionSelectDialog.h
ui/dialogs/SkinUploadDialog.cpp
ui/dialogs/SkinUploadDialog.h
ui/dialogs/ModDownloadDialog.cpp
ui/dialogs/ModDownloadDialog.h
# GUI - widgets
@ -842,7 +864,7 @@ qt5_wrap_ui(LAUNCHER_UI
ui/pages/global/AccountListPage.ui
ui/pages/global/JavaPage.ui
ui/pages/global/LauncherPage.ui
ui/pages/global/PasteEEPage.ui
ui/pages/global/APIPage.ui
ui/pages/global/ProxyPage.ui
ui/pages/global/MinecraftPage.ui
ui/pages/global/ExternalToolsPage.ui
@ -855,16 +877,17 @@ qt5_wrap_ui(LAUNCHER_UI
ui/pages/instance/InstanceSettingsPage.ui
ui/pages/instance/VersionPage.ui
ui/pages/instance/WorldListPage.ui
ui/pages/instance/LegacyUpgradePage.ui
ui/pages/instance/ScreenshotsPage.ui
ui/pages/modplatform/atlauncher/AtlOptionalModDialog.ui
ui/pages/modplatform/atlauncher/AtlPage.ui
ui/pages/modplatform/VanillaPage.ui
ui/pages/modplatform/flame/FlamePage.ui
ui/pages/modplatform/flame/FlameModPage.ui
ui/pages/modplatform/legacy_ftb/Page.ui
ui/pages/modplatform/ImportPage.ui
ui/pages/modplatform/ftb/FtbPage.ui
ui/pages/modplatform/technic/TechnicPage.ui
ui/pages/modplatform/modrinth/ModrinthPage.ui
ui/widgets/InstanceCardWidget.ui
ui/widgets/CustomCommands.ui
ui/widgets/MCModInfoFrame.ui
@ -880,9 +903,11 @@ qt5_wrap_ui(LAUNCHER_UI
ui/dialogs/ExportInstanceDialog.ui
ui/dialogs/IconPickerDialog.ui
ui/dialogs/MSALoginDialog.ui
ui/dialogs/OfflineLoginDialog.ui
ui/dialogs/AboutDialog.ui
ui/dialogs/LoginDialog.ui
ui/dialogs/EditAccountDialog.ui
ui/dialogs/ReviewMessageBox.ui
)
qt5_add_resources(LAUNCHER_RESOURCES
@ -908,9 +933,8 @@ endif()
add_library(Launcher_logic STATIC ${LOGIC_SOURCES} ${LAUNCHER_SOURCES} ${LAUNCHER_UI} ${LAUNCHER_RESOURCES})
target_link_libraries(Launcher_logic
systeminfo
Launcher_quazip
Launcher_classparser
${NBT_NAME}
nbt++
${ZLIB_LIBRARIES}
optional-bare
tomlc99
@ -926,10 +950,10 @@ target_link_libraries(Launcher_logic
)
target_link_libraries(Launcher_logic
Launcher_iconfix
${QUAZIP_LIBRARIES}
QuaZip::QuaZip
hoedown
Launcher_rainbow
LocalPeer
Launcher_rainbow
)
target_link_libraries(Launcher_logic)
@ -971,7 +995,7 @@ if(INSTALL_BUNDLE STREQUAL "full")
DIRECTORY "${QT_PLUGINS_DIR}/imageformats"
DESTINATION ${PLUGIN_DEST_DIR}
COMPONENT Runtime
REGEX "tga|tiff|mng|webp" EXCLUDE
REGEX "tga|tiff|mng" EXCLUDE
)
# Icon engines
install(
@ -1001,7 +1025,7 @@ if(INSTALL_BUNDLE STREQUAL "full")
DIRECTORY "${QT_PLUGINS_DIR}/imageformats"
DESTINATION ${PLUGIN_DEST_DIR}
COMPONENT Runtime
REGEX "tga|tiff|mng|webp" EXCLUDE
REGEX "tga|tiff|mng" EXCLUDE
REGEX "d\\." EXCLUDE
REGEX "_debug\\." EXCLUDE
REGEX "\\.dSYM" EXCLUDE

View File

@ -42,7 +42,6 @@ void InstanceCopyTask::copyFinished()
}
// FIXME: shouldn't this be able to report errors?
auto instanceSettings = std::make_shared<INISettingsObject>(FS::PathCombine(m_stagingPath, "instance.cfg"));
instanceSettings->registerSetting("InstanceType", "Legacy");
InstancePtr inst(new NullInstance(m_globalSettings, instanceSettings, m_stagingPath));
inst->setName(m_instName);

View File

@ -17,8 +17,6 @@ void InstanceCreationTask::executeTask()
{
auto instanceSettings = std::make_shared<INISettingsObject>(FS::PathCombine(m_stagingPath, "instance.cfg"));
instanceSettings->suspendSave();
instanceSettings->registerSetting("InstanceType", "Legacy");
instanceSettings->set("InstanceType", "OneSix");
MinecraftInstance inst(m_globalSettings, instanceSettings, m_stagingPath);
auto components = inst.getPackProfile();
components->buildingFromScratch();

View File

@ -29,7 +29,7 @@
#include "modplatform/flame/FileResolvingTask.h"
#include "modplatform/flame/PackManifest.h"
#include "Json.h"
#include <quazipdir.h>
#include <quazip/quazipdir.h>
#include "modplatform/technic/TechnicPackProcessor.h"
#include "icons/IconList.h"
@ -261,8 +261,6 @@ void InstanceImportTask::processFlame()
QString configPath = FS::PathCombine(m_stagingPath, "instance.cfg");
auto instanceSettings = std::make_shared<INISettingsObject>(configPath);
instanceSettings->registerSetting("InstanceType", "Legacy");
instanceSettings->set("InstanceType", "OneSix");
MinecraftInstance instance(m_globalSettings, instanceSettings, m_stagingPath);
auto mcVersion = pack.minecraft.version;
// Hack to correct some 'special sauce'...
@ -285,7 +283,7 @@ void InstanceImportTask::processFlame()
}
else
{
logWarning(tr("Could not map recommended forge version for Minecraft %1").arg(mcVersion));
logWarning(tr("Could not map recommended Forge version for Minecraft %1").arg(mcVersion));
}
}
components->setComponentVersion("net.minecraftforge", forgeVersion);
@ -422,7 +420,6 @@ void InstanceImportTask::processMultiMC()
{
QString configPath = FS::PathCombine(m_stagingPath, "instance.cfg");
auto instanceSettings = std::make_shared<INISettingsObject>(configPath);
instanceSettings->registerSetting("InstanceType", "Legacy");
NullInstance instance(m_globalSettings, instanceSettings, m_stagingPath);

View File

@ -32,7 +32,6 @@
#include "BaseInstance.h"
#include "InstanceTask.h"
#include "settings/INISettingsObject.h"
#include "minecraft/legacy/LegacyInstance.h"
#include "NullInstance.h"
#include "minecraft/MinecraftInstance.h"
#include "FileSystem.h"
@ -544,23 +543,8 @@ InstancePtr InstanceList::loadInstance(const InstanceId& id)
auto instanceRoot = FS::PathCombine(m_instDir, id);
auto instanceSettings = std::make_shared<INISettingsObject>(FS::PathCombine(instanceRoot, "instance.cfg"));
InstancePtr inst;
instanceSettings->registerSetting("InstanceType", "Legacy");
QString inst_type = instanceSettings->get("InstanceType").toString();
if (inst_type == "OneSix" || inst_type == "Nostalgia")
{
// TODO: Handle incompatible instances
inst.reset(new MinecraftInstance(m_globalSettings, instanceSettings, instanceRoot));
}
else if (inst_type == "Legacy")
{
inst.reset(new LegacyInstance(m_globalSettings, instanceSettings, instanceRoot));
}
else
{
inst.reset(new NullInstance(m_globalSettings, instanceSettings, instanceRoot));
}
qDebug() << "Loaded instance " << inst->name() << " from " << inst->instanceRoot();
return inst;
}

View File

@ -1,6 +1,5 @@
#pragma once
#include "minecraft/MinecraftInstance.h"
#include "minecraft/legacy/LegacyInstance.h"
#include <FileSystem.h>
#include "ui/pages/BasePage.h"
#include "ui/pages/BasePageProvider.h"
@ -14,7 +13,6 @@
#include "ui/pages/instance/ScreenshotsPage.h"
#include "ui/pages/instance/InstanceSettingsPage.h"
#include "ui/pages/instance/OtherLogsPage.h"
#include "ui/pages/instance/LegacyUpgradePage.h"
#include "ui/pages/instance/WorldListPage.h"
#include "ui/pages/instance/ServersPage.h"
#include "ui/pages/instance/GameOptionsPage.h"
@ -34,10 +32,8 @@ public:
QList<BasePage *> values;
values.append(new LogPage(inst));
std::shared_ptr<MinecraftInstance> onesix = std::dynamic_pointer_cast<MinecraftInstance>(inst);
if(onesix)
{
values.append(new VersionPage(onesix.get()));
auto modsPage = new ModFolderPage(onesix.get(), onesix->loaderModList(), "mods", "loadermods", tr("Loader mods"), "Loader-mods");
auto modsPage = new ModFolderPage(onesix.get(), onesix->loaderModList(), "mods", "loadermods", tr("Mods"), "Loader-mods");
modsPage->setFilter("%1 (*.zip *.jar *.litemod)");
values.append(modsPage);
values.append(new CoreModFolderPage(onesix.get(), onesix->coreModList(), "coremods", "coremods", tr("Core mods"), "Core-mods"));
@ -50,15 +46,6 @@ public:
// values.append(new GameOptionsPage(onesix.get()));
values.append(new ScreenshotsPage(FS::PathCombine(onesix->gameRoot(), "screenshots")));
values.append(new InstanceSettingsPage(onesix.get()));
}
std::shared_ptr<LegacyInstance> legacy = std::dynamic_pointer_cast<LegacyInstance>(inst);
if(legacy)
{
values.append(new LegacyUpgradePage(legacy));
values.append(new NotesPage(legacy.get()));
values.append(new WorldListPage(legacy.get(), legacy->worldList()));
values.append(new ScreenshotsPage(FS::PathCombine(legacy->gameRoot(), "screenshots")));
}
auto logMatcher = inst->getLogFileMatcher();
if(logMatcher)
{
@ -74,3 +61,4 @@ public:
protected:
InstancePtr inst;
};

View File

@ -40,7 +40,7 @@ void JavaCommon::javaArgsWereBad(QWidget *parent, JavaCheckResult result)
auto htmlError = result.errorLog;
QString text;
htmlError.replace('\n', "<br />");
text += QObject::tr("The specified java binary didn't work with the arguments you provided:<br />");
text += QObject::tr("The specified Java binary didn't work with the arguments you provided:<br />");
text += QString("<font color=\"red\">%1</font>").arg(htmlError);
CustomMessageBox::selectable(parent, QObject::tr("Java test failure"), text, QMessageBox::Warning)->show();
}
@ -49,8 +49,8 @@ void JavaCommon::javaBinaryWasBad(QWidget *parent, JavaCheckResult result)
{
QString text;
text += QObject::tr(
"The specified java binary didn't work.<br />You should use the auto-detect feature, "
"or set the path to the java executable.<br />");
"The specified Java binary didn't work.<br />You should use the auto-detect feature, "
"or set the path to the Java executable.<br />");
CustomMessageBox::selectable(parent, QObject::tr("Java test failure"), text, QMessageBox::Warning)->show();
}

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.
*/
#include "LaunchController.h"
#include "minecraft/auth/AccountList.h"
#include "Application.h"
@ -116,6 +151,12 @@ void LaunchController::login() {
m_session->wants_online = m_online;
m_accountToUse->fillSession(m_session);
// Launch immediately in true offline mode
if(m_accountToUse->isOffline()) {
launchInstance();
return;
}
switch(m_accountToUse->accountState()) {
case AccountState::Offline: {
m_session->wants_online = false;
@ -222,6 +263,18 @@ void LaunchController::login() {
emitFailed(errorString);
return;
}
case AccountState::Disabled: {
auto errorString = tr("The launcher's client identification has changed. Please remove this account and add it again.");
QMessageBox::warning(
m_parentWidget,
tr("Client identification changed"),
errorString,
QMessageBox::StandardButton::Ok,
QMessageBox::StandardButton::Ok
);
emitFailed(errorString);
return;
}
case AccountState::Gone: {
auto errorString = tr("The account no longer exists on the servers. It may have been migrated, in which case please add the new account you migrated this one to.");
QMessageBox::warning(

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
#include <QObject>
#include <BaseInstance.h>

View File

@ -14,7 +14,7 @@ if [[ $EUID -eq 0 ]]; then
fi
LAUNCHER_NAME=@Launcher_Name@
LAUNCHER_NAME=@Launcher_APP_BINARY_NAME@
LAUNCHER_DIR="$(dirname "$(readlink -f "$0")")"
echo "Launcher Dir: ${LAUNCHER_DIR}"

View File

@ -1,4 +1,24 @@
/* Copyright 2013-2021 MultiMC Contributors
// 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.
@ -13,17 +33,16 @@
* limitations under the License.
*/
#include <quazip.h>
#include <quazipdir.h>
#include <quazipfile.h>
#include <JlCompress.h>
#include <quazip/quazip.h>
#include <quazip/quazipdir.h>
#include <quazip/quazipfile.h>
#include "MMCZip.h"
#include "FileSystem.h"
#include <QDebug>
// ours
bool MMCZip::mergeZipFiles(QuaZip *into, QFileInfo from, QSet<QString> &contained, const JlCompress::FilterFunction filter)
bool MMCZip::mergeZipFiles(QuaZip *into, QFileInfo from, QSet<QString> &contained, const FilterFunction filter)
{
QuaZip modZip(from.filePath());
modZip.open(QuaZip::mdUnzip);
@ -74,6 +93,39 @@ bool MMCZip::mergeZipFiles(QuaZip *into, QFileInfo from, QSet<QString> &containe
return true;
}
bool MMCZip::compressDirFiles(QuaZip *zip, QString dir, QFileInfoList files)
{
QDir directory(dir);
if (!directory.exists()) return false;
for (auto e : files) {
auto filePath = directory.relativeFilePath(e.absoluteFilePath());
if( !JlCompress::compressFile(zip, e.absoluteFilePath(), filePath)) return false;
}
return true;
}
bool MMCZip::compressDirFiles(QString fileCompressed, QString dir, QFileInfoList files)
{
QuaZip zip(fileCompressed);
QDir().mkpath(QFileInfo(fileCompressed).absolutePath());
if(!zip.open(QuaZip::mdCreate)) {
QFile::remove(fileCompressed);
return false;
}
auto result = compressDirFiles(&zip, dir, files);
zip.close();
if(zip.getZipError()!=0) {
QFile::remove(fileCompressed);
return false;
}
return result;
}
// ours
bool MMCZip::createModdedJar(QString sourceJarPath, QString targetJarPath, const QList<Mod>& mods)
{
@ -122,13 +174,22 @@ bool MMCZip::createModdedJar(QString sourceJarPath, QString targetJarPath, const
}
else if (mod.type() == Mod::MOD_FOLDER)
{
// untested, but seems to be unused / not possible to reach
// FIXME: buggy - does not work with addedFiles
auto filename = mod.filename();
QString what_to_zip = filename.absoluteFilePath();
QDir dir(what_to_zip);
dir.cdUp();
QString parent_dir = dir.absolutePath();
if (!JlCompress::compressSubDir(&zipOut, what_to_zip, parent_dir, addedFiles))
auto files = QFileInfoList();
MMCZip::collectFileListRecursively(what_to_zip, nullptr, &files, nullptr);
for (auto e : files) {
if (addedFiles.contains(e.filePath()))
files.removeAll(e);
}
if (!MMCZip::compressDirFiles(&zipOut, parent_dir, files))
{
zipOut.close();
QFile::remove(targetJarPath);
@ -310,3 +371,37 @@ bool MMCZip::extractFile(QString fileCompressed, QString file, QString target)
}
return MMCZip::extractRelFile(&zip, file, target);
}
bool MMCZip::collectFileListRecursively(const QString& rootDir, const QString& subDir, QFileInfoList *files,
MMCZip::FilterFunction excludeFilter) {
QDir rootDirectory(rootDir);
if (!rootDirectory.exists()) return false;
QDir directory;
if (subDir == nullptr)
directory = rootDirectory;
else
directory = QDir(subDir);
if (!directory.exists()) return false; // shouldn't ever happen
// recurse directories
QFileInfoList entries = directory.entryInfoList(QDir::AllDirs | QDir::NoDotAndDotDot | QDir::Hidden);
for (const auto& e: entries) {
if (!collectFileListRecursively(rootDir, e.filePath(), files, excludeFilter))
return false;
}
// collect files
entries = directory.entryInfoList(QDir::Files);
for (const auto& e: entries) {
QString relativeFilePath = rootDirectory.relativeFilePath(e.absoluteFilePath());
if (excludeFilter && excludeFilter(relativeFilePath)) {
qDebug() << "Skipping file " << relativeFilePath;
continue;
}
files->append(e.filePath()); // we want the original paths for MMCZip::compressDirFiles
}
return true;
}

View File

@ -1,4 +1,24 @@
/* Copyright 2013-2021 MultiMC Contributors
// 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.
@ -21,17 +41,36 @@
#include "minecraft/mod/Mod.h"
#include <functional>
#include <JlCompress.h>
#include <quazip/JlCompress.h>
#include <nonstd/optional>
namespace MMCZip
{
using FilterFunction = std::function<bool(const QString &)>;
/**
* Merge two zip files, using a filter function
*/
bool mergeZipFiles(QuaZip *into, QFileInfo from, QSet<QString> &contained,
const JlCompress::FilterFunction filter = nullptr);
const FilterFunction filter = nullptr);
/**
* Compress directory, by providing a list of files to compress
* \param zip target archive
* \param dir directory that will be compressed (to compress with relative paths)
* \param files list of files to compress
* \return true for success or false for failure
*/
bool compressDirFiles(QuaZip *zip, QString dir, QFileInfoList files);
/**
* Compress directory, by providing a list of files to compress
* \param fileCompressed target archive file
* \param dir directory that will be compressed (to compress with relative paths)
* \param files list of files to compress
* \return true for success or false for failure
*/
bool compressDirFiles(QString fileCompressed, QString dir, QFileInfoList files);
/**
* take a source jar, add mods to it, resulting in target jar
@ -89,4 +128,13 @@ namespace MMCZip
*/
bool extractFile(QString fileCompressed, QString file, QString dir);
/**
* Populate a QFileInfoList with a directory tree recursively, while allowing to excludeFilter what shouldn't be included.
* \param rootDir directory to start off
* \param subDir subdirectory, should be nullptr for first invocation
* \param files resulting list of QFileInfo
* \param excludeFilter function to excludeFilter which files shouldn't be included (returning true means to excude)
* \return true for success or false for failure
*/
bool collectFileListRecursively(const QString &rootDir, const QString &subDir, QFileInfoList *files, FilterFunction excludeFilter);
}

View File

@ -0,0 +1,39 @@
#include "ModDownloadTask.h"
#include "Application.h"
ModDownloadTask::ModDownloadTask(const QUrl sourceUrl,const QString filename, const std::shared_ptr<ModFolderModel> mods)
: m_sourceUrl(sourceUrl), mods(mods), filename(filename) {
}
void ModDownloadTask::executeTask() {
setStatus(tr("Downloading mod:\n%1").arg(m_sourceUrl.toString()));
m_filesNetJob.reset(new NetJob(tr("Mod download"), APPLICATION->network()));
m_filesNetJob->addNetAction(Net::Download::makeFile(m_sourceUrl, mods->dir().absoluteFilePath(filename)));
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);
m_filesNetJob->start();
}
void ModDownloadTask::downloadSucceeded()
{
emitSucceeded();
m_filesNetJob.reset();
}
void ModDownloadTask::downloadFailed(QString reason)
{
emitFailed(reason);
m_filesNetJob.reset();
}
void ModDownloadTask::downloadProgressChanged(qint64 current, qint64 total)
{
emit progress(current, total);
}
bool ModDownloadTask::abort() {
return m_filesNetJob->abort();
}

View File

@ -0,0 +1,35 @@
#pragma once
#include "QObjectPtr.h"
#include "tasks/Task.h"
#include "minecraft/mod/ModFolderModel.h"
#include "net/NetJob.h"
#include <QUrl>
class ModDownloadTask : public Task {
Q_OBJECT
public:
explicit ModDownloadTask(const QUrl sourceUrl, const QString filename, const std::shared_ptr<ModFolderModel> mods);
const QString& getFilename() const { return filename; }
public slots:
bool abort() override;
protected:
//! Entry point for tasks.
void executeTask() override;
private:
QUrl m_sourceUrl;
NetJob::Ptr m_filesNetJob;
const std::shared_ptr<ModFolderModel> mods;
const QString filename;
void downloadProgressChanged(qint64 current, qint64 total);
void downloadFailed(QString reason);
void downloadSucceeded();
};

View File

@ -93,7 +93,7 @@ void UpdateController::installUpdates()
qDebug() << "Installing updates.";
#ifdef Q_OS_WIN
QString finishCmd = QApplication::applicationFilePath();
#elif defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD)
#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();

View File

@ -103,11 +103,15 @@ void JavaChecker::finished(int exitcode, QProcess::ExitStatus status)
for(QString line : lines)
{
line = line.trimmed();
// NOTE: workaround for GH-4125, where garbage is getting printed into stdout on bedrock linux
if (line.contains("/bedrock/strata")) {
continue;
}
auto parts = line.split('=', QString::SkipEmptyParts);
if(parts.size() != 2 || parts[0].isEmpty() || parts[1].isEmpty())
{
success = false;
continue;
}
else
{

View File

@ -120,8 +120,8 @@ void JavaInstallList::updateListData(QList<BaseVersionPtr> versions)
bool sortJavas(BaseVersionPtr left, BaseVersionPtr right)
{
auto rleft = std::dynamic_pointer_cast<JavaInstall>(left);
auto rright = std::dynamic_pointer_cast<JavaInstall>(right);
auto rleft = std::dynamic_pointer_cast<JavaInstall>(right);
auto rright = std::dynamic_pointer_cast<JavaInstall>(left);
return (*rleft) > (*rright);
}

View File

@ -77,14 +77,14 @@ QProcessEnvironment CleanEnviroment()
qDebug() << "Env: ignoring" << key << value;
continue;
}
// filter MultiMC-related things
// filter PolyMC-related things
if(key.startsWith("QT_"))
{
qDebug() << "Env: ignoring" << key << value;
continue;
}
#if defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD)
// Do not pass LD_* variables to java. They were intended for MultiMC
// Do not pass LD_* variables to java. They were intended for PolyMC
if(key.startsWith("LD_"))
{
qDebug() << "Env: ignoring" << key << value;
@ -149,6 +149,21 @@ JavaInstallPtr JavaUtils::GetDefaultJava()
return javaVersion;
}
QStringList addJavasFromEnv(QList<QString> javas)
{
QByteArray env = qgetenv("POLYMC_JAVA_PATHS");
#if defined(Q_OS_WIN32)
QList<QString> javaPaths = QString::fromLocal8Bit(env).split(QLatin1String(";"));
#else
QList<QString> javaPaths = QString::fromLocal8Bit(env).split(QLatin1String(":"));
#endif
for(QString i : javaPaths)
{
javas.append(i);
};
return javas;
}
#if defined(Q_OS_WIN32)
QList<JavaInstallPtr> JavaUtils::FindJavaFromRegistryKey(DWORD keyType, QString keyName, QString keyJavaDir, QString subkeySuffix)
{
@ -363,7 +378,7 @@ QList<QString> JavaUtils::FindJavaPaths()
javas.append(systemLibraryJVMDir.absolutePath() + "/" + java + "/Contents/Home/bin/java");
javas.append(systemLibraryJVMDir.absolutePath() + "/" + java + "/Contents/Commands/java");
}
return javas;
return addJavasFromEnv(javas);
}
#elif defined(Q_OS_LINUX)
@ -402,14 +417,14 @@ QList<QString> JavaUtils::FindJavaPaths()
scanJavaDir("/usr/lib/jvm");
scanJavaDir("/usr/lib64/jvm");
scanJavaDir("/usr/lib32/jvm");
// javas stored in MultiMC's folder
// javas stored in PolyMC's folder
scanJavaDir("java");
// manually installed JDKs in /opt
scanJavaDir("/opt/jdk");
scanJavaDir("/opt/jdks");
// flatpak
scanJavaDir("/app/jdk");
return javas;
return addJavasFromEnv(javas);
}
#else
QList<QString> JavaUtils::FindJavaPaths()
@ -419,6 +434,6 @@ QList<QString> JavaUtils::FindJavaPaths()
QList<QString> javas;
javas.append(this->GetDefaultJava()->path);
return javas;
return addJavasFromEnv(javas);
}
#endif

View File

@ -212,7 +212,7 @@ shared_qobject_ptr<LogModel> LaunchTask::getLogModel()
m_logModel->setMaxLines(m_instance->getConsoleMaxLines());
m_logModel->setStopOnOverflow(m_instance->shouldStopOnConsoleOverflow());
// FIXME: should this really be here?
m_logModel->setOverflowMessage(tr("MultiMC stopped watching the game log because the log length surpassed %1 lines.\n"
m_logModel->setOverflowMessage(tr("PolyMC stopped watching the game log because the log length surpassed %1 lines.\n"
"You may have to fix your mods because the game is still logging to files and"
" likely wasting harddrive space at an alarming rate!").arg(m_logModel->getMaxLines()));
}
@ -277,4 +277,3 @@ QString LaunchTask::substituteVariables(const QString &cmd) const
}
return out;
}

View File

@ -87,14 +87,14 @@ void CheckJava::checkJavaFinished(JavaCheckResult result)
// Error message displayed if java can't start
emit logLine(QString("Could not start java:"), MessageLevel::Error);
emit logLines(result.errorLog.split('\n'), MessageLevel::Error);
emit logLine("\nCheck your MultiMC Java settings.", MessageLevel::Launcher);
emit logLine("\nCheck your PolyMC Java settings.", MessageLevel::Launcher);
printSystemInfo(false, false);
emitFailed(QString("Could not start java!"));
return;
}
case JavaCheckResult::Validity::ReturnedInvalidData:
{
emit logLine(QString("Java checker returned some invalid data MultiMC doesn't understand:"), MessageLevel::Error);
emit logLine(QString("Java checker returned some invalid data PolyMC doesn't understand:"), MessageLevel::Error);
emit logLines(result.outLog.split('\n'), MessageLevel::Warning);
emit logLine("\nMinecraft might not start properly.", MessageLevel::Launcher);
printSystemInfo(false, false);

View File

@ -29,6 +29,10 @@ int main(int argc, char *argv[])
QGuiApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);
#endif
#if (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0))
QApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::PassThrough);
#endif
// initialize Qt
Application app(argc, argv);

View File

@ -156,7 +156,7 @@ public: /* methods */
QStringList & failedLocalFiles, const QString & overridePath) const;
private: /* methods */
/// the default storage prefix used by MultiMC
/// the default storage prefix used by PolyMC
static QString defaultStoragePrefix();
/// Get the prefix - root of the storage to be used
@ -177,23 +177,23 @@ protected: /* data */
/// DEPRECATED URL prefix of the maven repo where the file can be downloaded
QString m_repositoryURL;
/// DEPRECATED: MultiMC-specific absolute URL. takes precedence over the implicit maven repo URL, if defined
/// DEPRECATED: PolyMC-specific absolute URL. takes precedence over the implicit maven repo URL, if defined
QString m_absoluteURL;
/// MultiMC extension - filename override
/// PolyMC extension - filename override
QString m_filename;
/// DEPRECATED MultiMC extension - display name
/// DEPRECATED PolyMC extension - display name
QString m_displayname;
/**
* MultiMC-specific type hint - modifies how the library is treated
* PolyMC-specific type hint - modifies how the library is treated
*/
QString m_hint;
/**
* storage - by default the local libraries folder in multimc, but could be elsewhere
* MultiMC specific, because of FTB.
* storage - by default the local libraries folder in polymc, but could be elsewhere
* PolyMC specific, because of FTB.
*/
QString m_storagePrefix;
@ -215,3 +215,4 @@ protected: /* data */
/// MOJANG: container with Mojang style download info
MojangLibraryDownloadInfo::Ptr m_mojangDownloads;
};

View File

@ -124,18 +124,7 @@ MinecraftInstance::MinecraftInstance(SettingsObjectPtr globalSettings, SettingsO
m_settings->registerSetting("JoinServerOnLaunch", false);
m_settings->registerSetting("JoinServerOnLaunchAddress", "");
// DEPRECATED: Read what versions the user configuration thinks should be used
m_settings->registerSetting({"IntendedVersion", "MinecraftVersion"}, "");
m_settings->registerSetting("LWJGLVersion", "");
m_settings->registerSetting("ForgeVersion", "");
m_settings->registerSetting("LiteloaderVersion", "");
m_components.reset(new PackProfile(this));
m_components->setOldConfigVersion("net.minecraft", m_settings->get("IntendedVersion").toString());
auto setting = m_settings->getSetting("LWJGLVersion");
m_components->setOldConfigVersion("org.lwjgl", m_settings->get("LWJGLVersion").toString());
m_components->setOldConfigVersion("net.minecraftforge", m_settings->get("ForgeVersion").toString());
m_components->setOldConfigVersion("com.mumfrey.liteloader", m_settings->get("LiteloaderVersion").toString());
}
void MinecraftInstance::saveNow()
@ -445,7 +434,7 @@ QStringList MinecraftInstance::processMinecraftArgs(
}
// blatant self-promotion.
token_mapping["profile_name"] = token_mapping["version_name"] = "MultiMC5";
token_mapping["profile_name"] = token_mapping["version_name"] = "PolyMC";
token_mapping["version_type"] = profile->getMinecraftVersionType();

View File

@ -20,7 +20,7 @@
#include <QUrl>
#include "tasks/Task.h"
#include <quazip.h>
#include <quazip/quazip.h>
#include "QObjectPtr.h"

View File

@ -22,7 +22,7 @@
#include "net/NetJob.h"
#include "tasks/Task.h"
#include "minecraft/VersionFilterData.h"
#include <quazip.h>
#include <quazip/quazip.h>
class MinecraftVersion;
class MinecraftInstance;

View File

@ -272,18 +272,6 @@ void PackProfile::save_internal()
bool PackProfile::load()
{
auto filename = componentsFilePath();
QFile componentsFile(filename);
// migrate old config to new one, if needed
if(!componentsFile.exists())
{
if(!migratePreComponentConfig())
{
// FIXME: the user should be notified...
qCritical() << "Failed to convert old pre-component config for instance" << d->m_instance->name();
return false;
}
}
// load the new component list and swap it with the current one...
ComponentContainer newComponents;
@ -369,239 +357,6 @@ void PackProfile::updateFailed(const QString& error)
invalidateLaunchProfile();
}
// NOTE this is really old stuff, and only needs to be used when loading the old hardcoded component-unaware format (loadPreComponentConfig).
static void upgradeDeprecatedFiles(QString root, QString instanceName)
{
auto versionJsonPath = FS::PathCombine(root, "version.json");
auto customJsonPath = FS::PathCombine(root, "custom.json");
auto mcJson = FS::PathCombine(root, "patches" , "net.minecraft.json");
QString sourceFile;
QString renameFile;
// convert old crap.
if(QFile::exists(customJsonPath))
{
sourceFile = customJsonPath;
renameFile = versionJsonPath;
}
else if(QFile::exists(versionJsonPath))
{
sourceFile = versionJsonPath;
}
if(!sourceFile.isEmpty() && !QFile::exists(mcJson))
{
if(!FS::ensureFilePathExists(mcJson))
{
qWarning() << "Couldn't create patches folder for" << instanceName;
return;
}
if(!renameFile.isEmpty() && QFile::exists(renameFile))
{
if(!QFile::rename(renameFile, renameFile + ".old"))
{
qWarning() << "Couldn't rename" << renameFile << "to" << renameFile + ".old" << "in" << instanceName;
return;
}
}
auto file = ProfileUtils::parseJsonFile(QFileInfo(sourceFile), false);
ProfileUtils::removeLwjglFromPatch(file);
file->uid = "net.minecraft";
file->version = file->minecraftVersion;
file->name = "Minecraft";
Meta::Require needsLwjgl;
needsLwjgl.uid = "org.lwjgl";
file->requires.insert(needsLwjgl);
if(!ProfileUtils::saveJsonFile(OneSixVersionFormat::versionFileToJson(file), mcJson))
{
return;
}
if(!QFile::rename(sourceFile, sourceFile + ".old"))
{
qWarning() << "Couldn't rename" << sourceFile << "to" << sourceFile + ".old" << "in" << instanceName;
return;
}
}
}
/*
* Migrate old layout to the component based one...
* - Part of the version information is taken from `instance.cfg` (fed to this class from outside).
* - Part is taken from the old order.json file.
* - Part is loaded from loose json files in the instance's `patches` directory.
*/
bool PackProfile::migratePreComponentConfig()
{
// upgrade the very old files from the beginnings of MultiMC 5
upgradeDeprecatedFiles(d->m_instance->instanceRoot(), d->m_instance->name());
QList<ComponentPtr> components;
QSet<QString> loaded;
auto addBuiltinPatch = [&](const QString &uid, bool asDependency, const QString & emptyVersion, const Meta::Require & req, const Meta::Require & conflict)
{
auto jsonFilePath = FS::PathCombine(d->m_instance->instanceRoot(), "patches" , uid + ".json");
auto intendedVersion = d->getOldConfigVersion(uid);
// load up the base minecraft patch
ComponentPtr component;
if(QFile::exists(jsonFilePath))
{
if(intendedVersion.isEmpty())
{
intendedVersion = emptyVersion;
}
auto file = ProfileUtils::parseJsonFile(QFileInfo(jsonFilePath), false);
// fix uid
file->uid = uid;
// if version is missing, add it from the outside.
if(file->version.isEmpty())
{
file->version = intendedVersion;
}
// if this is a dependency (LWJGL), mark it also as volatile
if(asDependency)
{
file->m_volatile = true;
}
// insert requirements if needed
if(!req.uid.isEmpty())
{
file->requires.insert(req);
}
// insert conflicts if needed
if(!conflict.uid.isEmpty())
{
file->conflicts.insert(conflict);
}
// FIXME: @QUALITY do not ignore return value
ProfileUtils::saveJsonFile(OneSixVersionFormat::versionFileToJson(file), jsonFilePath);
component = new Component(this, uid, file);
component->m_version = intendedVersion;
}
else if(!intendedVersion.isEmpty())
{
auto metaVersion = APPLICATION->metadataIndex()->get(uid, intendedVersion);
component = new Component(this, metaVersion);
}
else
{
return;
}
component->m_dependencyOnly = asDependency;
component->m_important = !asDependency;
components.append(component);
};
// TODO: insert depends and conflicts here if these are customized files...
Meta::Require reqLwjgl;
reqLwjgl.uid = "org.lwjgl";
reqLwjgl.suggests = "2.9.1";
Meta::Require conflictLwjgl3;
conflictLwjgl3.uid = "org.lwjgl3";
Meta::Require nullReq;
addBuiltinPatch("org.lwjgl", true, "2.9.1", nullReq, conflictLwjgl3);
addBuiltinPatch("net.minecraft", false, QString(), reqLwjgl, nullReq);
// first, collect all other file-based patches and load them
QMap<QString, ComponentPtr> loadedComponents;
QDir patchesDir(FS::PathCombine(d->m_instance->instanceRoot(),"patches"));
for (auto info : patchesDir.entryInfoList(QStringList() << "*.json", QDir::Files))
{
// parse the file
qDebug() << "Reading" << info.fileName();
auto file = ProfileUtils::parseJsonFile(info, true);
// correct missing or wrong uid based on the file name
QString uid = info.completeBaseName();
// ignore builtins, they've been handled already
if (uid == "net.minecraft")
continue;
if (uid == "org.lwjgl")
continue;
// handle horrible corner cases
if(uid.isEmpty())
{
// if you have a file named '.json', make it just go away.
// FIXME: @QUALITY do not ignore return value
QFile::remove(info.absoluteFilePath());
continue;
}
file->uid = uid;
// FIXME: @QUALITY do not ignore return value
ProfileUtils::saveJsonFile(OneSixVersionFormat::versionFileToJson(file), info.absoluteFilePath());
auto component = new Component(this, file->uid, file);
auto version = d->getOldConfigVersion(file->uid);
if(!version.isEmpty())
{
component->m_version = version;
}
loadedComponents[file->uid] = component;
}
// try to load the other 'hardcoded' patches (forge, liteloader), if they weren't loaded from files
auto loadSpecial = [&](const QString & uid, int order)
{
auto patchVersion = d->getOldConfigVersion(uid);
if(!patchVersion.isEmpty() && !loadedComponents.contains(uid))
{
auto patch = new Component(this, APPLICATION->metadataIndex()->get(uid, patchVersion));
patch->setOrder(order);
loadedComponents[uid] = patch;
}
};
loadSpecial("net.minecraftforge", 5);
loadSpecial("com.mumfrey.liteloader", 10);
// load the old order.json file, if present
ProfileUtils::PatchOrder userOrder;
ProfileUtils::readOverrideOrders(FS::PathCombine(d->m_instance->instanceRoot(), "order.json"), userOrder);
// now add all the patches by user sort order
for (auto uid : userOrder)
{
// ignore builtins
if (uid == "net.minecraft")
continue;
if (uid == "org.lwjgl")
continue;
// ordering has a patch that is gone?
if(!loadedComponents.contains(uid))
{
continue;
}
components.append(loadedComponents.take(uid));
}
// is there anything left to sort? - this is used when there are leftover components that aren't part of the order.json
if(!loadedComponents.isEmpty())
{
// inserting into multimap by order number as key sorts the patches and detects duplicates
QMultiMap<int, ComponentPtr> files;
auto iter = loadedComponents.begin();
while(iter != loadedComponents.end())
{
files.insert((*iter)->getOrder(), *iter);
iter++;
}
// then just extract the patches and put them in the list
for (auto order : files.keys())
{
const auto &values = files.values(order);
for(auto &value: values)
{
// TODO: put back the insertion of problem messages here, so the user knows about the id duplication
components.append(value);
}
}
}
// new we have a complete list of components...
return savePackProfile(componentsFilePath(), components);
}
// END: save/load
void PackProfile::appendComponent(ComponentPtr component)
@ -1169,15 +924,6 @@ std::shared_ptr<LaunchProfile> PackProfile::getProfile() const
return d->m_profile;
}
void PackProfile::setOldConfigVersion(const QString& uid, const QString& version)
{
if(version.isEmpty())
{
return;
}
d->m_oldConfigVersions[uid] = version;
}
bool PackProfile::setComponentVersion(const QString& uid, const QString& version, bool important)
{
auto iter = d->componentIndex.find(uid);

View File

@ -143,8 +143,6 @@ private:
bool installCustomJar_internal(QString filepath);
bool removeComponent_internal(ComponentPtr patch);
bool migratePreComponentConfig();
private: /* data */
std::unique_ptr<PackProfileData> d;

View File

@ -18,18 +18,6 @@ struct PackProfileData
// the launch profile (volatile, temporary thing created on demand)
std::shared_ptr<LaunchProfile> m_profile;
// version information migrated from instance.cfg file. Single use on migration!
std::map<QString, QString> m_oldConfigVersions;
QString getOldConfigVersion(const QString& uid) const
{
const auto iter = m_oldConfigVersions.find(uid);
if(iter != m_oldConfigVersions.cend())
{
return (*iter).second;
}
return QString();
}
// persistent list of components and related machinery
ComponentContainer components;
ComponentIndex componentIndex;

View File

@ -27,19 +27,19 @@ public: /* methods */
void applyTo(LaunchProfile* profile);
public: /* data */
/// MultiMC: order hint for this version file if no explicit order is set
/// PolyMC: order hint for this version file if no explicit order is set
int order = 0;
/// MultiMC: human readable name of this package
/// PolyMC: human readable name of this package
QString name;
/// MultiMC: package ID of this package
/// PolyMC: package ID of this package
QString uid;
/// MultiMC: version of this package
/// PolyMC: version of this package
QString version;
/// MultiMC: DEPRECATED dependency on a Minecraft version
/// PolyMC: DEPRECATED dependency on a Minecraft version
QString dependsOnMinecraftVersion;
/// Mojang: DEPRECATED used to version the Mojang version format
@ -51,7 +51,7 @@ public: /* data */
/// Mojang: class to launch Minecraft with
QString mainClass;
/// MultiMC: class to launch legacy Minecraft with (embed in a custom window)
/// PolyMC: class to launch legacy Minecraft with (embed in a custom window)
QString appletClass;
/// Mojang: Minecraft launch arguments (may contain placeholders for variable substitution)
@ -69,35 +69,35 @@ public: /* data */
/// Mojang: DEPRECATED asset group to be used with Minecraft
QString assets;
/// MultiMC: list of tweaker mod arguments for launchwrapper
/// PolyMC: list of tweaker mod arguments for launchwrapper
QStringList addTweakers;
/// Mojang: list of libraries to add to the version
QList<LibraryPtr> libraries;
/// MultiMC: list of maven files to put in the libraries folder, but not in classpath
/// PolyMC: list of maven files to put in the libraries folder, but not in classpath
QList<LibraryPtr> mavenFiles;
/// The main jar (Minecraft version library, normally)
LibraryPtr mainJar;
/// MultiMC: list of attached traits of this version file - used to enable features
/// PolyMC: list of attached traits of this version file - used to enable features
QSet<QString> traits;
/// MultiMC: list of jar mods added to this version
/// PolyMC: list of jar mods added to this version
QList<LibraryPtr> jarMods;
/// MultiMC: list of mods added to this version
/// PolyMC: list of mods added to this version
QList<LibraryPtr> mods;
/**
* MultiMC: set of packages this depends on
* PolyMC: set of packages this depends on
* NOTE: this is shared with the meta format!!!
*/
Meta::RequireSet requires;
/**
* MultiMC: set of packages this conflicts with
* PolyMC: set of packages this conflicts with
* NOTE: this is shared with the meta format!!!
*/
Meta::RequireSet conflicts;
@ -112,3 +112,4 @@ public:
// Mojang: extended asset index download information
std::shared_ptr<MojangAssetIndexInfo> mojangAssetIndex;
};

View File

@ -26,9 +26,9 @@
#include <io/stream_reader.h>
#include <tag_string.h>
#include <tag_primitive.h>
#include <quazip.h>
#include <quazipfile.h>
#include <quazipdir.h>
#include <quazip/quazip.h>
#include <quazip/quazipfile.h>
#include <quazip/quazipdir.h>
#include <QCoreApplication>

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.
*/
#include "AccountData.h"
#include <QJsonDocument>
#include <QJsonObject>
@ -314,6 +349,8 @@ bool AccountData::resumeStateFromV3(QJsonObject data) {
type = AccountType::MSA;
} else if (typeS == "Mojang") {
type = AccountType::Mojang;
} else if (typeS == "Offline") {
type = AccountType::Offline;
} else {
qWarning() << "Failed to parse account data: type is not recognized.";
return false;
@ -325,6 +362,10 @@ bool AccountData::resumeStateFromV3(QJsonObject data) {
}
if(type == AccountType::MSA) {
auto clientIDV = data.value("msa-client-id");
if (clientIDV.isString()) {
msaClientID = clientIDV.toString();
} // leave msaClientID empty if it doesn't exist or isn't a string
msaToken = tokenFromJSONV3(data, "msa");
userToken = tokenFromJSONV3(data, "utoken");
xboxApiToken = tokenFromJSONV3(data, "xrp-main");
@ -358,11 +399,15 @@ QJsonObject AccountData::saveState() const {
}
else if (type == AccountType::MSA) {
output["type"] = "MSA";
output["msa-client-id"] = msaClientID;
tokenToJSONV3(output, msaToken, "msa");
tokenToJSONV3(output, userToken, "utoken");
tokenToJSONV3(output, xboxApiToken, "xrp-main");
tokenToJSONV3(output, mojangservicesToken, "xrp-mc");
}
else if (type == AccountType::Offline) {
output["type"] = "Offline";
}
tokenToJSONV3(output, yggdrasilToken, "ygg");
profileToJSONV3(output, minecraftProfile, "profile");
@ -371,7 +416,7 @@ QJsonObject AccountData::saveState() const {
}
QString AccountData::userName() const {
if(type != AccountType::Mojang) {
if(type == AccountType::MSA) {
return QString();
}
return yggdrasilToken.extra["userName"].toString();
@ -427,6 +472,9 @@ QString AccountData::accountDisplayString() const {
case AccountType::Mojang: {
return userName();
}
case AccountType::Offline: {
return userName();
}
case AccountType::MSA: {
if(xboxApiToken.extra.contains("gtg")) {
return xboxApiToken.extra["gtg"].toString();

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
#include <QString>
#include <QByteArray>
@ -38,7 +73,8 @@ struct MinecraftProfile {
enum class AccountType {
MSA,
Mojang
Mojang,
Offline
};
enum class AccountState {
@ -46,6 +82,7 @@ enum class AccountState {
Offline,
Working,
Online,
Disabled,
Errored,
Expired,
Gone
@ -80,6 +117,7 @@ struct AccountData {
bool legacy = false;
bool canMigrateToMSA = false;
QString msaClientID;
Katabasis::Token msaToken;
Katabasis::Token userToken;
Katabasis::Token xboxApiToken;

View File

@ -1,4 +1,24 @@
/* Copyright 2013-2021 MultiMC Contributors
// 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.
@ -291,6 +311,9 @@ QVariant AccountList::data(const QModelIndex &index, int role) const
case AccountState::Expired: {
return tr("Expired", "Account status");
}
case AccountState::Disabled: {
return tr("Disabled", "Account status");
}
case AccountState::Gone: {
return tr("Gone", "Account status");
}
@ -302,7 +325,7 @@ QVariant AccountList::data(const QModelIndex &index, int role) const
}
case MigrationColumn: {
if(account->isMSA()) {
if(account->isMSA() || account->isOffline()) {
return tr("N/A", "Can Migrate?");
}
if (account->canMigrate()) {

View File

@ -1,4 +1,24 @@
/* Copyright 2013-2021 MultiMC Contributors
// 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.
@ -24,7 +44,7 @@
/*!
* List of available Mojang accounts.
* This should be loaded in the background by MultiMC on startup.
* This should be loaded in the background by PolyMC on startup.
*/
class AccountList : public QAbstractListModel
{
@ -158,3 +178,4 @@ protected:
*/
bool m_autosave = false;
};

View File

@ -1,4 +1,24 @@
/* Copyright 2013-2021 MultiMC Contributors
// 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.
@ -43,6 +63,8 @@ QString AccountTask::getStateMessage() const
return tr("Authentication task succeeded.");
case AccountTaskState::STATE_OFFLINE:
return tr("Failed to contact the authentication server.");
case AccountTaskState::STATE_DISABLED:
return tr("Client ID has changed. New session needs to be created.");
case AccountTaskState::STATE_FAILED_SOFT:
return tr("Encountered an error during authentication.");
case AccountTaskState::STATE_FAILED_HARD:
@ -78,6 +100,12 @@ bool AccountTask::changeState(AccountTaskState newState, QString reason)
emitFailed(reason);
return false;
}
case AccountTaskState::STATE_DISABLED: {
m_data->errorString = reason;
m_data->accountState = AccountState::Disabled;
emitFailed(reason);
return false;
}
case AccountTaskState::STATE_FAILED_SOFT: {
m_data->errorString = reason;
m_data->accountState = AccountState::Errored;

View File

@ -1,4 +1,24 @@
/* Copyright 2013-2021 MultiMC Contributors
// 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.
@ -35,6 +55,7 @@ enum class AccountTaskState
STATE_CREATED,
STATE_WORKING,
STATE_SUCCEEDED,
STATE_DISABLED, //!< MSA Client ID has changed. Tell user to reloginn
STATE_FAILED_SOFT, //!< soft failure. authentication went through partially
STATE_FAILED_HARD, //!< hard failure. main tokens are invalid
STATE_FAILED_GONE, //!< hard failure. main tokens are invalid, and the account no longer exists

View File

@ -44,7 +44,7 @@ void AuthRequest::onRequestFinished() {
if (reply_ != qobject_cast<QNetworkReply *>(sender())) {
return;
}
httpStatus_ = 200;
httpStatus_ = reply_->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
finish();
}

View File

@ -1,4 +1,24 @@
/* Copyright 2013-2021 MultiMC Contributors
// 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
*
* Authors: Orochimarufan <orochimarufan.x3@gmail.com>
*
@ -30,6 +50,7 @@
#include "flows/MSA.h"
#include "flows/Mojang.h"
#include "flows/Offline.h"
MinecraftAccount::MinecraftAccount(QObject* parent) : QObject(parent) {
data.internalId = QUuid::createUuid().toString().remove(QRegExp("[{}-]"));
@ -68,6 +89,23 @@ MinecraftAccountPtr MinecraftAccount::createBlankMSA()
return account;
}
MinecraftAccountPtr MinecraftAccount::createOffline(const QString &username)
{
MinecraftAccountPtr account = new MinecraftAccount();
account->data.type = AccountType::Offline;
account->data.yggdrasilToken.token = "offline";
account->data.yggdrasilToken.validity = Katabasis::Validity::Certain;
account->data.yggdrasilToken.issueInstant = QDateTime::currentDateTimeUtc();
account->data.yggdrasilToken.extra["userName"] = username;
account->data.yggdrasilToken.extra["clientToken"] = QUuid::createUuid().toString().remove(QRegExp("[{}-]"));
account->data.minecraftEntitlement.ownsMinecraft = true;
account->data.minecraftEntitlement.canPlayMinecraft = true;
account->data.minecraftProfile.id = QUuid::createUuid().toString().remove(QRegExp("[{}-]"));
account->data.minecraftProfile.name = username;
account->data.minecraftProfile.validity = Katabasis::Validity::Certain;
return account;
}
QJsonObject MinecraftAccount::saveToJson() const
{
@ -111,6 +149,16 @@ shared_qobject_ptr<AccountTask> MinecraftAccount::loginMSA() {
return m_currentTask;
}
shared_qobject_ptr<AccountTask> MinecraftAccount::loginOffline() {
Q_ASSERT(m_currentTask.get() == nullptr);
m_currentTask.reset(new OfflineLogin(&data));
connect(m_currentTask.get(), SIGNAL(succeeded()), SLOT(authSucceeded()));
connect(m_currentTask.get(), SIGNAL(failed(QString)), SLOT(authFailed(QString)));
emit activityChanged(true);
return m_currentTask;
}
shared_qobject_ptr<AccountTask> MinecraftAccount::refresh() {
if(m_currentTask) {
return m_currentTask;
@ -119,6 +167,9 @@ shared_qobject_ptr<AccountTask> MinecraftAccount::refresh() {
if(data.type == AccountType::MSA) {
m_currentTask.reset(new MSASilent(&data));
}
else if(data.type == AccountType::Offline) {
m_currentTask.reset(new OfflineRefresh(&data));
}
else {
m_currentTask.reset(new MojangRefresh(&data));
}
@ -145,6 +196,9 @@ void MinecraftAccount::authFailed(QString reason)
{
switch (m_currentTask->taskState()) {
case AccountTaskState::STATE_OFFLINE:
case AccountTaskState::STATE_DISABLED: {
// NOTE: user will need to fix this themselves.
}
case AccountTaskState::STATE_FAILED_SOFT: {
// NOTE: this doesn't do much. There was an error of some sort.
}

View File

@ -1,4 +1,24 @@
/* Copyright 2013-2021 MultiMC Contributors
// 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.
@ -41,7 +61,7 @@ Q_DECLARE_METATYPE(MinecraftAccountPtr)
* A profile within someone's Mojang account.
*
* Currently, the profile system has not been implemented by Mojang yet,
* but we might as well add some things for it in MultiMC right now so
* but we might as well add some things for it in PolyMC right now so
* we don't have to rip the code to pieces to add it later.
*/
struct AccountProfile
@ -73,6 +93,8 @@ public: /* construction */
static MinecraftAccountPtr createBlankMSA();
static MinecraftAccountPtr createOffline(const QString &username);
static MinecraftAccountPtr loadFromJsonV2(const QJsonObject &json);
static MinecraftAccountPtr loadFromJsonV3(const QJsonObject &json);
@ -89,6 +111,8 @@ public: /* manipulation */
shared_qobject_ptr<AccountTask> loginMSA();
shared_qobject_ptr<AccountTask> loginOffline();
shared_qobject_ptr<AccountTask> refresh();
shared_qobject_ptr<AccountTask> currentTask();
@ -128,6 +152,10 @@ public: /* queries */
return data.type == AccountType::MSA;
}
bool isOffline() const {
return data.type == AccountType::Offline;
}
bool ownsMinecraft() const {
return data.minecraftEntitlement.ownsMinecraft;
}
@ -149,6 +177,10 @@ public: /* queries */
return "msa";
}
break;
case AccountType::Offline: {
return "offline";
}
break;
default: {
return "unknown";
}
@ -198,3 +230,4 @@ slots:
void authSucceeded();
void authFailed(QString reason);
};

View File

@ -94,7 +94,7 @@ bool parseXTokenResponse(QByteArray & data, Katabasis::Token &output, QString na
return false;
}
if(!getString(obj.value("Token"), output.token)) {
qWarning() << "User Token is not a timestamp";
qWarning() << "User Token is not a string";
return false;
}
auto arrayVal = obj.value("DisplayClaims").toObject().value("xui");

View File

@ -0,0 +1,17 @@
#include "Offline.h"
#include "minecraft/auth/steps/OfflineStep.h"
OfflineRefresh::OfflineRefresh(
AccountData *data,
QObject *parent
) : AuthFlow(data, parent) {
m_steps.append(new OfflineStep(m_data));
}
OfflineLogin::OfflineLogin(
AccountData *data,
QObject *parent
) : AuthFlow(data, parent) {
m_steps.append(new OfflineStep(m_data));
}

View File

@ -0,0 +1,22 @@
#pragma once
#include "AuthFlow.h"
class OfflineRefresh : public AuthFlow
{
Q_OBJECT
public:
explicit OfflineRefresh(
AccountData *data,
QObject *parent = 0
);
};
class OfflineLogin : public AuthFlow
{
Q_OBJECT
public:
explicit OfflineLogin(
AccountData *data,
QObject *parent = 0
);
};

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.
*/
#include "MSAStep.h"
#include <QNetworkRequest>
@ -12,9 +47,10 @@ using OAuth2 = Katabasis::DeviceFlow;
using Activity = Katabasis::Activity;
MSAStep::MSAStep(AccountData* data, Action action) : AuthStep(data), m_action(action) {
m_clientId = APPLICATION->getMSAClientID();
OAuth2::Options opts;
opts.scope = "XboxLive.signin offline_access";
opts.clientIdentifier = BuildConfig.MSA_CLIENT_ID;
opts.clientIdentifier = m_clientId;
opts.authorizationUrl = "https://login.microsoftonline.com/consumers/oauth2/v2.0/devicecode";
opts.accessTokenUrl = "https://login.microsoftonline.com/consumers/oauth2/v2.0/token";
@ -48,6 +84,10 @@ void MSAStep::rehydrate() {
void MSAStep::perform() {
switch(m_action) {
case Refresh: {
if (m_data->msaClientID != m_clientId) {
emit hideVerificationUriAndCode();
emit finished(AccountTaskState::STATE_DISABLED, tr("Microsoft user authentication failed - client identification has changed."));
}
m_oauth2->refresh();
return;
}
@ -57,6 +97,7 @@ void MSAStep::perform() {
m_oauth2->setExtraRequestParams(extraOpts);
*m_data = AccountData();
m_data->msaClientID = m_clientId;
m_oauth2->login();
return;
}

View File

@ -1,3 +1,37 @@
// 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
#include <QObject>
@ -29,4 +63,5 @@ private slots:
private:
Katabasis::DeviceFlow *m_oauth2 = nullptr;
Action m_action;
QString m_clientId;
};

View File

@ -56,6 +56,14 @@ void MinecraftProfileStep::onRequestDone(
return;
}
if (error != QNetworkReply::NoError) {
qWarning() << "Error getting profile:";
qWarning() << " HTTP Status: " << requestor->httpStatus_;
qWarning() << " Internal error no.: " << error;
qWarning() << " Error string: " << requestor->errorString_;
qWarning() << " Response:";
qWarning() << QString::fromUtf8(data);
emit finished(
AccountTaskState::STATE_FAILED_SOFT,
tr("Minecraft Java profile acquisition failed.")

View File

@ -0,0 +1,18 @@
#include "OfflineStep.h"
#include "Application.h"
OfflineStep::OfflineStep(AccountData* data) : AuthStep(data) {}
OfflineStep::~OfflineStep() noexcept = default;
QString OfflineStep::describe() {
return tr("Creating offline account.");
}
void OfflineStep::rehydrate() {
// NOOP
}
void OfflineStep::perform() {
emit finished(AccountTaskState::STATE_WORKING, tr("Created offline account."));
}

View File

@ -0,0 +1,19 @@
#pragma once
#include <QObject>
#include "QObjectPtr.h"
#include "minecraft/auth/AuthStep.h"
#include <katabasis/DeviceFlow.h>
class OfflineStep : public AuthStep {
Q_OBJECT
public:
explicit OfflineStep(AccountData *data);
virtual ~OfflineStep() noexcept;
void perform() override;
void rehydrate() override;
QString describe() override;
};

View File

@ -88,7 +88,7 @@ void DirectJavaLaunch::on_state(LoggedProcess::State state)
case LoggedProcess::FailedToStart:
{
//: Error message displayed if instance can't start
const char *reason = QT_TR_NOOP("Could not launch minecraft!");
const char *reason = QT_TR_NOOP("Could not launch Minecraft!");
emit logLine(reason, MessageLevel::Fatal);
emitFailed(tr(reason));
return;

View File

@ -17,8 +17,8 @@
#include <minecraft/MinecraftInstance.h>
#include <launch/LaunchTask.h>
#include <quazip.h>
#include <quazipdir.h>
#include <quazip/quazip.h>
#include <quazip/quazipdir.h>
#include "MMCZip.h"
#include "FileSystem.h"
#include <QDir>

View File

@ -25,6 +25,19 @@
LauncherPartLaunch::LauncherPartLaunch(LaunchTask *parent) : LaunchStep(parent)
{
if (APPLICATION->settings()->get("CloseAfterLaunch").toBool())
{
std::shared_ptr<QMetaObject::Connection> connection{new QMetaObject::Connection};
*connection = connect(&m_process, &LoggedProcess::log, this, [=](QStringList lines, MessageLevel::Enum level) {
qDebug() << lines;
if (lines.filter(QRegularExpression(".*Setting user.+", QRegularExpression::CaseInsensitiveOption)).length() != 0)
{
APPLICATION->closeAllWindows();
disconnect(*connection);
}
});
}
connect(&m_process, &LoggedProcess::log, this, &LauncherPartLaunch::logLines);
connect(&m_process, &LoggedProcess::stateChanged, this, &LauncherPartLaunch::on_state);
}
@ -141,7 +154,7 @@ void LauncherPartLaunch::on_state(LoggedProcess::State state)
case LoggedProcess::FailedToStart:
{
//: Error message displayed if instace can't start
const char *reason = QT_TR_NOOP("Could not launch minecraft!");
const char *reason = QT_TR_NOOP("Could not launch Minecraft!");
emit logLine(reason, MessageLevel::Fatal);
emitFailed(tr(reason));
return;
@ -155,6 +168,8 @@ void LauncherPartLaunch::on_state(LoggedProcess::State state)
}
case LoggedProcess::Finished:
{
if (APPLICATION->settings()->get("CloseAfterLaunch").toBool())
APPLICATION->showMainWindow();
m_parent->setPid(-1);
// if the exit code wasn't 0, report this as a crash
auto exitCode = m_process.exitCode();

View File

@ -23,7 +23,7 @@ MinecraftServerTarget MinecraftServerTarget::parse(const QString &fullAddress) {
// The logic below replicates the exact logic minecraft uses for parsing server addresses.
// While the conversion is not lossless and eats errors, it ensures the same behavior
// within Minecraft and MultiMC when entering server addresses.
// within Minecraft and PolyMC when entering server addresses.
if (fullAddress.startsWith("["))
{
int bracket = fullAddress.indexOf("]");

View File

@ -1,256 +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.
*/
#include <QFileInfo>
#include <minecraft/launch/LauncherPartLaunch.h>
#include <QDir>
#include <settings/Setting.h>
#include "LegacyInstance.h"
#include "minecraft/legacy/LegacyModList.h"
#include "minecraft/WorldList.h"
#include <MMCZip.h>
#include <FileSystem.h>
LegacyInstance::LegacyInstance(SettingsObjectPtr globalSettings, SettingsObjectPtr settings, const QString &rootDir)
: BaseInstance(globalSettings, settings, rootDir)
{
settings->registerSetting("NeedsRebuild", true);
settings->registerSetting("ShouldUpdate", false);
settings->registerSetting("JarVersion", QString());
settings->registerSetting("IntendedJarVersion", QString());
/*
* custom base jar has no default. it is determined in code... see the accessor methods for
*it
*
* for instances that DO NOT have the CustomBaseJar setting (legacy instances),
* [.]minecraft/bin/mcbackup.jar is the default base jar
*/
settings->registerSetting("UseCustomBaseJar", true);
settings->registerSetting("CustomBaseJar", "");
}
QString LegacyInstance::mainJarToPreserve() const
{
bool customJar = m_settings->get("UseCustomBaseJar").toBool();
if(customJar)
{
auto base = baseJar();
if(QFile::exists(base))
{
return base;
}
}
auto runnable = runnableJar();
if(QFile::exists(runnable))
{
return runnable;
}
return QString();
}
QString LegacyInstance::baseJar() const
{
bool customJar = m_settings->get("UseCustomBaseJar").toBool();
if (customJar)
{
return customBaseJar();
}
else
return defaultBaseJar();
}
QString LegacyInstance::customBaseJar() const
{
QString value = m_settings->get("CustomBaseJar").toString();
if (value.isNull() || value.isEmpty())
{
return defaultCustomBaseJar();
}
return value;
}
bool LegacyInstance::shouldUseCustomBaseJar() const
{
return m_settings->get("UseCustomBaseJar").toBool();
}
Task::Ptr LegacyInstance::createUpdateTask(Net::Mode)
{
return nullptr;
}
std::shared_ptr<LegacyModList> LegacyInstance::jarModList() const
{
if (!jar_mod_list)
{
auto list = new LegacyModList(jarModsDir(), modListFile());
jar_mod_list.reset(list);
}
jar_mod_list->update();
return jar_mod_list;
}
QString LegacyInstance::gameRoot() const
{
QFileInfo mcDir(FS::PathCombine(instanceRoot(), "minecraft"));
QFileInfo dotMCDir(FS::PathCombine(instanceRoot(), ".minecraft"));
if (mcDir.exists() && !dotMCDir.exists())
return mcDir.filePath();
else
return dotMCDir.filePath();
}
QString LegacyInstance::binRoot() const
{
return FS::PathCombine(gameRoot(), "bin");
}
QString LegacyInstance::modsRoot() const {
return FS::PathCombine(gameRoot(), "mods");
}
QString LegacyInstance::jarModsDir() const
{
return FS::PathCombine(instanceRoot(), "instMods");
}
QString LegacyInstance::libDir() const
{
return FS::PathCombine(gameRoot(), "lib");
}
QString LegacyInstance::savesDir() const
{
return FS::PathCombine(gameRoot(), "saves");
}
QString LegacyInstance::coreModsDir() const
{
return FS::PathCombine(gameRoot(), "coremods");
}
QString LegacyInstance::resourceDir() const
{
return FS::PathCombine(gameRoot(), "resources");
}
QString LegacyInstance::texturePacksDir() const
{
return FS::PathCombine(gameRoot(), "texturepacks");
}
QString LegacyInstance::runnableJar() const
{
return FS::PathCombine(binRoot(), "minecraft.jar");
}
QString LegacyInstance::modListFile() const
{
return FS::PathCombine(instanceRoot(), "modlist");
}
QString LegacyInstance::instanceConfigFolder() const
{
return FS::PathCombine(gameRoot(), "config");
}
bool LegacyInstance::shouldRebuild() const
{
return m_settings->get("NeedsRebuild").toBool();
}
QString LegacyInstance::currentVersionId() const
{
return m_settings->get("JarVersion").toString();
}
QString LegacyInstance::intendedVersionId() const
{
return m_settings->get("IntendedJarVersion").toString();
}
bool LegacyInstance::shouldUpdate() const
{
QVariant var = settings()->get("ShouldUpdate");
if (!var.isValid() || var.toBool() == false)
{
return intendedVersionId() != currentVersionId();
}
return true;
}
QString LegacyInstance::defaultBaseJar() const
{
return "versions/" + intendedVersionId() + "/" + intendedVersionId() + ".jar";
}
QString LegacyInstance::defaultCustomBaseJar() const
{
return FS::PathCombine(binRoot(), "mcbackup.jar");
}
std::shared_ptr<WorldList> LegacyInstance::worldList() const
{
if (!m_world_list)
{
m_world_list.reset(new WorldList(savesDir()));
}
return m_world_list;
}
QString LegacyInstance::typeName() const
{
return tr("Legacy");
}
QString LegacyInstance::getStatusbarDescription()
{
return tr("Instance from previous versions.");
}
QStringList LegacyInstance::verboseDescription(AuthSessionPtr session, MinecraftServerTargetPtr serverToJoin)
{
QStringList out;
auto alltraits = traits();
if(alltraits.size())
{
out << "Traits:";
for (auto trait : alltraits)
{
out << " " + trait;
}
out << "";
}
QString windowParams;
if (settings()->get("LaunchMaximized").toBool())
{
out << "Window size: max (if available)";
}
else
{
auto width = settings()->get("MinecraftWinWidth").toInt();
auto height = settings()->get("MinecraftWinHeight").toInt();
out << "Window size: " + QString::number(width) + " x " + QString::number(height);
}
out << "";
return out;
}

View File

@ -1,142 +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 "BaseInstance.h"
#include "launch/LaunchTask.h"
class ModFolderModel;
class LegacyModList;
class WorldList;
class Task;
/*
* WHY: Legacy instances - from MultiMC 3 and 4 - are here only to provide a way to upgrade them to the current format.
*/
class LegacyInstance : public BaseInstance
{
Q_OBJECT
public:
explicit LegacyInstance(SettingsObjectPtr globalSettings, SettingsObjectPtr settings, const QString &rootDir);
virtual void saveNow() override {}
/// Path to the instance's minecraft.jar
QString runnableJar() const;
//! Path to the instance's modlist file.
QString modListFile() const;
////// Directories //////
QString libDir() const;
QString savesDir() const;
QString texturePacksDir() const;
QString jarModsDir() const;
QString coreModsDir() const;
QString resourceDir() const;
QString instanceConfigFolder() const override;
QString gameRoot() const override; // Path to the instance's minecraft directory.
QString modsRoot() const override; // Path to the instance's minecraft directory.
QString binRoot() const; // Path to the instance's minecraft bin directory.
/// Get the curent base jar of this instance. By default, it's the
/// versions/$version/$version.jar
QString baseJar() const;
/// the default base jar of this instance
QString defaultBaseJar() const;
/// the default custom base jar of this instance
QString defaultCustomBaseJar() const;
// the main jar that we actually want to keep when migrating the instance
QString mainJarToPreserve() const;
/*!
* Whether or not custom base jar is used
*/
bool shouldUseCustomBaseJar() const;
/*!
* The value of the custom base jar
*/
QString customBaseJar() const;
std::shared_ptr<LegacyModList> jarModList() const;
std::shared_ptr<WorldList> worldList() const;
/*!
* Whether or not the instance's minecraft.jar needs to be rebuilt.
* If this is true, when the instance launches, its jar mods will be
* re-added to a fresh minecraft.jar file.
*/
bool shouldRebuild() const;
QString currentVersionId() const;
QString intendedVersionId() const;
QSet<QString> traits() const override
{
return {"legacy-instance", "texturepacks"};
};
virtual bool shouldUpdate() const;
virtual Task::Ptr createUpdateTask(Net::Mode mode) override;
virtual QString typeName() const override;
bool canLaunch() const override
{
return false;
}
bool canEdit() const override
{
return true;
}
bool canExport() const override
{
return false;
}
shared_qobject_ptr<LaunchTask> createLaunchTask(
AuthSessionPtr account, MinecraftServerTargetPtr serverToJoin) override
{
return nullptr;
}
IPathMatcher::Ptr getLogFileMatcher() override
{
return nullptr;
}
QString getLogFileRoot() override
{
return gameRoot();
}
QString getStatusbarDescription() override;
QStringList verboseDescription(AuthSessionPtr session, MinecraftServerTargetPtr serverToJoin) override;
QProcessEnvironment createEnvironment() override
{
return QProcessEnvironment();
}
QMap<QString, QString> getVariables() const override
{
return {};
}
protected:
mutable std::shared_ptr<LegacyModList> jar_mod_list;
mutable std::shared_ptr<WorldList> m_world_list;
};

View File

@ -1,136 +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.
*/
#include "LegacyModList.h"
#include <FileSystem.h>
#include <QString>
#include <QDebug>
LegacyModList::LegacyModList(const QString &dir, const QString &list_file)
: m_dir(dir), m_list_file(list_file)
{
FS::ensureFolderPathExists(m_dir.absolutePath());
m_dir.setFilter(QDir::Readable | QDir::NoDotAndDotDot | QDir::Files | QDir::Dirs);
m_dir.setSorting(QDir::Name | QDir::IgnoreCase | QDir::LocaleAware);
}
struct OrderItem
{
QString id;
bool enabled = false;
};
typedef QList<OrderItem> OrderList;
static void internalSort(QList<LegacyModList::Mod> &what)
{
auto predicate = [](const LegacyModList::Mod &left, const LegacyModList::Mod &right)
{
return left.fileName().localeAwareCompare(right.fileName()) < 0;
};
std::sort(what.begin(), what.end(), predicate);
}
static OrderList readListFile(const QString &m_list_file)
{
OrderList itemList;
if (m_list_file.isNull() || m_list_file.isEmpty())
return itemList;
QFile textFile(m_list_file);
if (!textFile.open(QIODevice::ReadOnly | QIODevice::Text))
return OrderList();
QTextStream textStream;
textStream.setAutoDetectUnicode(true);
textStream.setDevice(&textFile);
while (true)
{
QString line = textStream.readLine();
if (line.isNull() || line.isEmpty())
break;
else
{
OrderItem it;
it.enabled = !line.endsWith(".disabled");
if (!it.enabled)
{
line.chop(9);
}
it.id = line;
itemList.append(it);
}
}
textFile.close();
return itemList;
}
bool LegacyModList::update()
{
if (!m_dir.exists() || !m_dir.isReadable())
return false;
QList<Mod> orderedMods;
QList<Mod> newMods;
m_dir.refresh();
auto folderContents = m_dir.entryInfoList();
// first, process the ordered items (if any)
OrderList listOrder = readListFile(m_list_file);
for (auto item : listOrder)
{
QFileInfo infoEnabled(m_dir.filePath(item.id));
QFileInfo infoDisabled(m_dir.filePath(item.id + ".disabled"));
int idxEnabled = folderContents.indexOf(infoEnabled);
int idxDisabled = folderContents.indexOf(infoDisabled);
bool isEnabled;
// if both enabled and disabled versions are present, it's a special case...
if (idxEnabled >= 0 && idxDisabled >= 0)
{
// we only process the one we actually have in the order file.
// and exactly as we have it.
// THIS IS A CORNER CASE
isEnabled = item.enabled;
}
else
{
// only one is present.
// we pick the one that we found.
// we assume the mod was enabled/disabled by external means
isEnabled = idxEnabled >= 0;
}
int idx = isEnabled ? idxEnabled : idxDisabled;
QFileInfo &info = isEnabled ? infoEnabled : infoDisabled;
// if the file from the index file exists
if (idx != -1)
{
// remove from the actual folder contents list
folderContents.takeAt(idx);
// append the new mod
orderedMods.append(info);
}
}
// if there are any untracked files... append them sorted at the end
if (folderContents.size())
{
for (auto entry : folderContents)
{
newMods.append(entry);
}
internalSort(newMods);
orderedMods.append(newMods);
}
mods.swap(orderedMods);
return true;
}

View File

@ -1,47 +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 <QList>
#include <QString>
#include <QDir>
class LegacyModList
{
public:
using Mod = QFileInfo;
LegacyModList(const QString &dir, const QString &list_file = QString());
/// Reloads the mod list and returns true if the list changed.
bool update();
QDir dir()
{
return m_dir;
}
const QList<Mod> & allMods()
{
return mods;
}
protected:
QDir m_dir;
QString m_list_file;
QList<Mod> mods;
};

View File

@ -1,138 +0,0 @@
#include "LegacyUpgradeTask.h"
#include "settings/INISettingsObject.h"
#include "FileSystem.h"
#include "NullInstance.h"
#include "pathmatcher/RegexpMatcher.h"
#include <QtConcurrentRun>
#include "LegacyInstance.h"
#include "minecraft/MinecraftInstance.h"
#include "minecraft/PackProfile.h"
#include "LegacyModList.h"
#include "classparser.h"
LegacyUpgradeTask::LegacyUpgradeTask(InstancePtr origInstance)
{
m_origInstance = origInstance;
}
void LegacyUpgradeTask::executeTask()
{
setStatus(tr("Copying instance %1").arg(m_origInstance->name()));
FS::copy folderCopy(m_origInstance->instanceRoot(), m_stagingPath);
folderCopy.followSymlinks(true);
m_copyFuture = QtConcurrent::run(QThreadPool::globalInstance(), folderCopy);
connect(&m_copyFutureWatcher, &QFutureWatcher<bool>::finished, this, &LegacyUpgradeTask::copyFinished);
connect(&m_copyFutureWatcher, &QFutureWatcher<bool>::canceled, this, &LegacyUpgradeTask::copyAborted);
m_copyFutureWatcher.setFuture(m_copyFuture);
}
static QString decideVersion(const QString& currentVersion, const QString& intendedVersion)
{
if(intendedVersion != currentVersion)
{
if(!intendedVersion.isEmpty())
{
return intendedVersion;
}
else if(!currentVersion.isEmpty())
{
return currentVersion;
}
}
else
{
if(!intendedVersion.isEmpty())
{
return intendedVersion;
}
}
return QString();
}
void LegacyUpgradeTask::copyFinished()
{
auto successful = m_copyFuture.result();
if(!successful)
{
emitFailed(tr("Instance folder copy failed."));
return;
}
auto legacyInst = std::dynamic_pointer_cast<LegacyInstance>(m_origInstance);
auto instanceSettings = std::make_shared<INISettingsObject>(FS::PathCombine(m_stagingPath, "instance.cfg"));
instanceSettings->registerSetting("InstanceType", "Legacy");
instanceSettings->set("InstanceType", "OneSix");
// NOTE: this scope ensures the instance is fully saved before we emitSucceeded
{
MinecraftInstance inst(m_globalSettings, instanceSettings, m_stagingPath);
inst.setName(m_instName);
QString preferredVersionNumber = decideVersion(legacyInst->currentVersionId(), legacyInst->intendedVersionId());
if(preferredVersionNumber.isNull())
{
// try to decide version based on the jar(s?)
preferredVersionNumber = classparser::GetMinecraftJarVersion(legacyInst->baseJar());
if(preferredVersionNumber.isNull())
{
preferredVersionNumber = classparser::GetMinecraftJarVersion(legacyInst->runnableJar());
if(preferredVersionNumber.isNull())
{
emitFailed(tr("Could not decide Minecraft version."));
return;
}
}
}
auto components = inst.getPackProfile();
components->buildingFromScratch();
components->setComponentVersion("net.minecraft", preferredVersionNumber, true);
QString jarPath = legacyInst->mainJarToPreserve();
if(!jarPath.isNull())
{
qDebug() << "Preserving base jar! : " << jarPath;
// FIXME: handle case when the jar is unreadable?
// TODO: check the hash, if it's the same as the upstream jar, do not do this
components->installCustomJar(jarPath);
}
auto jarMods = legacyInst->jarModList()->allMods();
for(auto & jarMod: jarMods)
{
QString modPath = jarMod.absoluteFilePath();
qDebug() << "jarMod: " << modPath;
components->installJarMods({modPath});
}
// remove all the extra garbage we no longer need
auto removeAll = [&](const QString &root, const QStringList &things)
{
for(auto &thing : things)
{
auto removePath = FS::PathCombine(root, thing);
QFileInfo stat(removePath);
if(stat.isDir())
{
FS::deletePath(removePath);
}
else
{
QFile::remove(removePath);
}
}
};
QStringList rootRemovables = {"modlist", "version", "instMods"};
QStringList mcRemovables = {"bin", "MultiMCLauncher.jar", "icon.png"};
removeAll(inst.instanceRoot(), rootRemovables);
removeAll(inst.gameRoot(), mcRemovables);
}
emitSucceeded();
}
void LegacyUpgradeTask::copyAborted()
{
emitFailed(tr("Instance folder copy has been aborted."));
return;
}

View File

@ -1,29 +0,0 @@
#pragma once
#include "InstanceTask.h"
#include "net/NetJob.h"
#include <QUrl>
#include <QFuture>
#include <QFutureWatcher>
#include "settings/SettingsObject.h"
#include "BaseVersion.h"
#include "BaseInstance.h"
class LegacyUpgradeTask : public InstanceTask
{
Q_OBJECT
public:
explicit LegacyUpgradeTask(InstancePtr origInstance);
protected:
//! Entry point for tasks.
virtual void executeTask() override;
void copyFinished();
void copyAborted();
private: /* data */
InstancePtr m_origInstance;
QFuture<bool> m_copyFuture;
QFutureWatcher<bool> m_copyFutureWatcher;
};

View File

@ -4,8 +4,8 @@
#include <QJsonObject>
#include <QJsonArray>
#include <QJsonValue>
#include <quazip.h>
#include <quazipfile.h>
#include <quazip/quazip.h>
#include <quazip/quazipfile.h>
#include <toml.h>
#include "settings/INIFile.h"

View File

@ -14,7 +14,7 @@ void FoldersTask::executeTask()
QDir mcDir(m_inst->gameRoot());
if (!mcDir.exists() && !mcDir.mkpath("."))
{
emitFailed(tr("Failed to create folder for minecraft binaries."));
emitFailed(tr("Failed to create folder for Minecraft binaries."));
return;
}
emitSucceeded();

View File

@ -19,7 +19,7 @@
#include <QtConcurrent/QtConcurrent>
#include <quazip.h>
#include <quazip/quazip.h>
#include "MMCZip.h"
#include "minecraft/OneSixVersionFormat.h"
@ -720,8 +720,6 @@ void PackInstallTask::install()
auto instanceConfigPath = FS::PathCombine(m_stagingPath, "instance.cfg");
auto instanceSettings = std::make_shared<INISettingsObject>(instanceConfigPath);
instanceSettings->suspendSave();
instanceSettings->registerSetting("InstanceType", "Legacy");
instanceSettings->set("InstanceType", "OneSix");
MinecraftInstance instance(m_globalSettings, instanceSettings, m_stagingPath);
auto components = instance.getPackProfile();

View File

@ -0,0 +1,101 @@
#include <QObject>
#include "FlameModIndex.h"
#include "Json.h"
#include "net/NetJob.h"
#include "BaseInstance.h"
#include "minecraft/MinecraftInstance.h"
#include "minecraft/PackProfile.h"
void FlameMod::loadIndexedPack(FlameMod::IndexedPack & pack, QJsonObject & obj)
{
pack.addonId = Json::requireInteger(obj, "id");
pack.name = Json::requireString(obj, "name");
pack.websiteUrl = Json::ensureString(obj, "websiteUrl", "");
pack.description = Json::ensureString(obj, "summary", "");
bool thumbnailFound = false;
auto attachments = Json::requireArray(obj, "attachments");
for(auto attachmentRaw: attachments) {
auto attachmentObj = Json::requireObject(attachmentRaw);
bool isDefault = attachmentObj.value("isDefault").toBool(false);
if(isDefault) {
thumbnailFound = true;
pack.logoName = Json::requireString(attachmentObj, "title");
pack.logoUrl = Json::requireString(attachmentObj, "thumbnailUrl");
break;
}
}
if(!thumbnailFound) {
throw JSONValidationError(QString("Pack without an icon, skipping: %1").arg(pack.name));
}
auto authors = Json::requireArray(obj, "authors");
for(auto authorIter: authors) {
auto author = Json::requireObject(authorIter);
FlameMod::ModpackAuthor packAuthor;
packAuthor.name = Json::requireString(author, "name");
packAuthor.url = Json::requireString(author, "url");
pack.authors.append(packAuthor);
}
}
void FlameMod::loadIndexedPackVersions(FlameMod::IndexedPack & pack, QJsonArray & arr, const shared_qobject_ptr<QNetworkAccessManager>& network, BaseInstance * inst)
{
QVector<FlameMod::IndexedVersion> unsortedVersions;
bool hasFabric = !((MinecraftInstance *)inst)->getPackProfile()->getComponentVersion("net.fabricmc.fabric-loader").isEmpty();
QString mcVersion = ((MinecraftInstance *)inst)->getPackProfile()->getComponentVersion("net.minecraft");
for(auto versionIter: arr) {
auto obj = versionIter.toObject();
auto versionArray = Json::requireArray(obj, "gameVersion");
if (versionArray.isEmpty()) {
continue;
}
FlameMod::IndexedVersion file;
for(auto mcVer : versionArray){
file.mcVersion.append(mcVer.toString());
}
file.addonId = pack.addonId;
file.fileId = Json::requireInteger(obj, "id");
file.date = Json::requireString(obj, "fileDate");
file.version = Json::requireString(obj, "displayName");
file.downloadUrl = Json::requireString(obj, "downloadUrl");
file.fileName = Json::requireString(obj, "fileName");
auto modules = Json::requireArray(obj, "modules");
bool is_valid_fabric_version = false;
for(auto m : modules){
auto fname = Json::requireString(m.toObject(),"foldername");
// FIXME: This does not work properly when a mod supports more than one mod loader, since
// they bundle the meta files for all of them in the same arquive, even when that version
// doesn't support the given mod loader.
if(hasFabric){
if(fname == "fabric.mod.json"){
is_valid_fabric_version = true;
break;
}
}
else break;
// NOTE: Since we're not validating forge versions, we can just skip this loop.
}
if(hasFabric && !is_valid_fabric_version)
continue;
unsortedVersions.append(file);
}
auto orderSortPredicate = [](const IndexedVersion & a, const IndexedVersion & b) -> bool
{
//dates are in RFC 3339 format
return a.date > b.date;
};
std::sort(unsortedVersions.begin(), unsortedVersions.end(), orderSortPredicate);
pack.versions = unsortedVersions;
pack.versionsLoaded = true;
}

View File

@ -0,0 +1,50 @@
//
// Created by timoreo on 16/01/2022.
//
#pragma once
#include <QList>
#include <QMetaType>
#include <QString>
#include <QVector>
#include <QNetworkAccessManager>
#include <QObjectPtr.h>
#include "net/NetJob.h"
#include "BaseInstance.h"
namespace FlameMod {
struct ModpackAuthor {
QString name;
QString url;
};
struct IndexedVersion {
int addonId;
int fileId;
QString version;
QVector<QString> mcVersion;
QString downloadUrl;
QString date;
QString fileName;
};
struct IndexedPack
{
int addonId;
QString name;
QString description;
QList<ModpackAuthor> authors;
QString logoName;
QString logoUrl;
QString websiteUrl;
bool versionsLoaded = false;
QVector<IndexedVersion> versions;
};
void loadIndexedPack(IndexedPack & m, QJsonObject & obj);
void loadIndexedPackVersions(IndexedPack &pack, QJsonArray &arr, const shared_qobject_ptr<QNetworkAccessManager> &network, BaseInstance *inst);
}
Q_DECLARE_METATYPE(FlameMod::IndexedPack)

View File

@ -114,7 +114,7 @@ void PackInstallTask::install()
//ok, found minecraft dir, move contents to instance dir
if(!QDir().rename(m_stagingPath + "/unzip/minecraft", m_stagingPath + "/.minecraft"))
{
emitFailed(tr("Failed to move unzipped minecraft!"));
emitFailed(tr("Failed to move unzipped Minecraft!"));
return;
}
}
@ -122,8 +122,6 @@ void PackInstallTask::install()
QString instanceConfigPath = FS::PathCombine(m_stagingPath, "instance.cfg");
auto instanceSettings = std::make_shared<INISettingsObject>(instanceConfigPath);
instanceSettings->suspendSave();
instanceSettings->registerSetting("InstanceType", "Legacy");
instanceSettings->set("InstanceType", "OneSix");
MinecraftInstance instance(m_globalSettings, instanceSettings, m_stagingPath);
auto components = instance.getPackProfile();

View File

@ -1,8 +1,8 @@
#pragma once
#include "InstanceTask.h"
#include "net/NetJob.h"
#include "quazip.h"
#include "quazipdir.h"
#include <quazip/quazip.h>
#include <quazip/quazipdir.h>
#include "meta/Index.h"
#include "meta/Version.h"
#include "meta/VersionList.h"

View File

@ -181,8 +181,6 @@ void PackInstallTask::install()
auto instanceConfigPath = FS::PathCombine(m_stagingPath, "instance.cfg");
auto instanceSettings = std::make_shared<INISettingsObject>(instanceConfigPath);
instanceSettings->suspendSave();
instanceSettings->registerSetting("InstanceType", "Legacy");
instanceSettings->set("InstanceType", "OneSix");
MinecraftInstance instance(m_globalSettings, instanceSettings, m_stagingPath);
auto components = instance.getPackProfile();

View File

@ -0,0 +1,98 @@
#include <QObject>
#include "ModrinthPackIndex.h"
#include "Json.h"
#include "net/NetJob.h"
#include "BaseInstance.h"
#include "minecraft/MinecraftInstance.h"
#include "minecraft/PackProfile.h"
void Modrinth::loadIndexedPack(Modrinth::IndexedPack & pack, QJsonObject & obj)
{
pack.addonId = Json::requireString(obj, "project_id");
pack.name = Json::requireString(obj, "title");
pack.websiteUrl = Json::ensureString(obj, "page_url", "");
pack.description = Json::ensureString(obj, "description", "");
pack.logoUrl = Json::requireString(obj, "icon_url");
pack.logoName = pack.addonId;
Modrinth::ModpackAuthor modAuthor;
modAuthor.name = Json::requireString(obj, "author");
modAuthor.url = "https://modrinth.com/user/"+modAuthor.name;
pack.author = modAuthor;
}
void Modrinth::loadIndexedPackVersions(Modrinth::IndexedPack & pack, QJsonArray & arr, const shared_qobject_ptr<QNetworkAccessManager>& network, BaseInstance * inst)
{
QVector<Modrinth::IndexedVersion> unsortedVersions;
bool hasFabric = !((MinecraftInstance *)inst)->getPackProfile()->getComponentVersion("net.fabricmc.fabric-loader").isEmpty();
QString mcVersion = ((MinecraftInstance *)inst)->getPackProfile()->getComponentVersion("net.minecraft");
for(auto versionIter: arr) {
auto obj = versionIter.toObject();
Modrinth::IndexedVersion file;
file.addonId = Json::requireString(obj,"project_id") ;
file.fileId = Json::requireString(obj, "id");
file.date = Json::requireString(obj, "date_published");
auto versionArray = Json::requireArray(obj, "game_versions");
if (versionArray.empty()) {
continue;
}
for(auto mcVer : versionArray){
file.mcVersion.append(mcVer.toString());
}
auto loaders = Json::requireArray(obj,"loaders");
for(auto loader : loaders){
file.loaders.append(loader.toString());
}
file.version = Json::requireString(obj, "name");
auto files = Json::requireArray(obj, "files");
int i = 0;
// Find correct file (needed in cases where one version may have multiple files)
// Will default to the last one if there's no primary (though I think Modrinth requires that
// at least one file is primary, idk)
// NOTE: files.count() is 1-indexed, so we need to subtract 1 to become 0-indexed
while (i < files.count() - 1){
auto parent = files[i].toObject();
auto fileName = Json::requireString(parent, "filename");
// Grab the correct mod loader
if(hasFabric){
if(fileName.contains("forge",Qt::CaseInsensitive)){
i++;
continue;
}
} else if(fileName.contains("fabric", Qt::CaseInsensitive)){
i++;
continue;
}
// Grab the primary file, if available
if(Json::requireBoolean(parent, "primary"))
break;
i++;
}
auto parent = files[i].toObject();
if(parent.contains("url")) {
file.downloadUrl = Json::requireString(parent, "url");
file.fileName = Json::requireString(parent, "filename");
unsortedVersions.append(file);
}
}
auto orderSortPredicate = [](const IndexedVersion & a, const IndexedVersion & b) -> bool
{
//dates are in RFC 3339 format
return a.date > b.date;
};
std::sort(unsortedVersions.begin(), unsortedVersions.end(), orderSortPredicate);
pack.versions = unsortedVersions;
pack.versionsLoaded = true;
}

View File

@ -0,0 +1,48 @@
#pragma once
#include <QList>
#include <QMetaType>
#include <QString>
#include <QVector>
#include <QNetworkAccessManager>
#include <QObjectPtr.h>
#include "net/NetJob.h"
#include "BaseInstance.h"
namespace Modrinth {
struct ModpackAuthor {
QString name;
QString url;
};
struct IndexedVersion {
QString addonId;
QString fileId;
QString version;
QVector<QString> mcVersion;
QString downloadUrl;
QString date;
QString fileName;
QVector<QString> loaders;
};
struct IndexedPack
{
QString addonId;
QString name;
QString description;
ModpackAuthor author;
QString logoName;
QString logoUrl;
QString websiteUrl;
bool versionsLoaded = false;
QVector<IndexedVersion> versions;
};
void loadIndexedPack(IndexedPack & m, QJsonObject & obj);
void loadIndexedPackVersions(IndexedPack &pack, QJsonArray &arr, const shared_qobject_ptr<QNetworkAccessManager> &network, BaseInstance *inst);
}
Q_DECLARE_METATYPE(Modrinth::IndexedPack)

View File

@ -18,7 +18,7 @@
#include "InstanceTask.h"
#include "net/NetJob.h"
#include "quazip.h"
#include <quazip/quazip.h>
#include <QFutureWatcher>
#include <QStringList>

View File

@ -19,9 +19,9 @@
#include <Json.h>
#include <minecraft/MinecraftInstance.h>
#include <minecraft/PackProfile.h>
#include <quazip.h>
#include <quazipdir.h>
#include <quazipfile.h>
#include <quazip/quazip.h>
#include <quazip/quazipdir.h>
#include <quazip/quazipfile.h>
#include <settings/INISettingsObject.h>
#include <memory>
@ -31,8 +31,6 @@ void Technic::TechnicPackProcessor::run(SettingsObjectPtr globalSettings, const
QString minecraftPath = FS::PathCombine(stagingPath, ".minecraft");
QString configPath = FS::PathCombine(stagingPath, "instance.cfg");
auto instanceSettings = std::make_shared<INISettingsObject>(configPath);
instanceSettings->registerSetting("InstanceType", "Legacy");
instanceSettings->set("InstanceType", "OneSix");
MinecraftInstance instance(globalSettings, instanceSettings, stagingPath);
instance.setName(instName);
@ -90,7 +88,7 @@ void Technic::TechnicPackProcessor::run(SettingsObjectPtr globalSettings, const
else
{
if (minecraftVersion.isEmpty())
emit failed(tr("Could not find \"version.json\" inside \"bin/modpack.jar\", but minecraft version is unknown"));
emit failed(tr("Could not find \"version.json\" inside \"bin/modpack.jar\", but Minecraft version is unknown"));
components->setComponentVersion("net.minecraft", minecraftVersion, true);
components->installJarMods({modpackJar});

View File

@ -8,44 +8,34 @@
#include <QJsonDocument>
#include <QFile>
PasteUpload::PasteUpload(QWidget *window, QString text, QString key) : m_window(window)
PasteUpload::PasteUpload(QWidget *window, QString text, QString url) : m_window(window), m_uploadUrl(url), m_text(text.toUtf8())
{
m_key = key;
QByteArray temp;
QJsonObject topLevelObj;
QJsonObject sectionObject;
sectionObject.insert("contents", text);
QJsonArray sectionArray;
sectionArray.append(sectionObject);
topLevelObj.insert("description", "Log Upload");
topLevelObj.insert("sections", sectionArray);
QJsonDocument docOut;
docOut.setObject(topLevelObj);
m_jsonContent = docOut.toJson();
}
PasteUpload::~PasteUpload()
{
}
bool PasteUpload::validateText()
{
return m_jsonContent.size() <= maxSize();
}
void PasteUpload::executeTask()
{
QNetworkRequest request(QUrl("https://api.paste.ee/v1/pastes"));
QNetworkRequest request{QUrl(m_uploadUrl)};
request.setHeader(QNetworkRequest::UserAgentHeader, BuildConfig.USER_AGENT_UNCACHED);
request.setRawHeader("Content-Type", "application/json");
request.setRawHeader("Content-Length", QByteArray::number(m_jsonContent.size()));
request.setRawHeader("X-Auth-Token", m_key.toStdString().c_str());
QHttpMultiPart *multiPart = new QHttpMultiPart{QHttpMultiPart::FormDataType};
QNetworkReply *rep = APPLICATION->network()->post(request, m_jsonContent);
QHttpPart filePart;
filePart.setBody(m_text);
filePart.setHeader(QNetworkRequest::ContentTypeHeader, "text/plain");
filePart.setHeader(QNetworkRequest::ContentDispositionHeader, "form-data; name=\"file\"; filename=\"log.txt\"");
multiPart->append(filePart);
QNetworkReply *rep = APPLICATION->network()->post(request, multiPart);
multiPart->setParent(rep);
m_reply = std::shared_ptr<QNetworkReply>(rep);
setStatus(tr("Uploading to paste.ee"));
setStatus(tr("Uploading to %1").arg(m_uploadUrl));
connect(rep, &QNetworkReply::uploadProgress, this, &Task::setProgress);
connect(rep, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(downloadError(QNetworkReply::NetworkError)));
connect(rep, SIGNAL(finished()), this, SLOT(downloadFinished()));
@ -61,45 +51,23 @@ void PasteUpload::downloadError(QNetworkReply::NetworkError error)
void PasteUpload::downloadFinished()
{
QByteArray data = m_reply->readAll();
// if the download succeeded
if (m_reply->error() == QNetworkReply::NetworkError::NoError)
int statusCode = m_reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
if (m_reply->error() != QNetworkReply::NetworkError::NoError)
{
m_reply.reset();
QJsonParseError jsonError;
QJsonDocument doc = QJsonDocument::fromJson(data, &jsonError);
if (jsonError.error != QJsonParseError::NoError)
{
emitFailed(jsonError.errorString());
return;
}
if (!parseResult(doc))
{
emitFailed(tr("paste.ee returned an error. Please consult the logs for more information"));
return;
}
}
// else the download failed
else
{
emitFailed(QString("Network error: %1").arg(m_reply->errorString()));
emitFailed(tr("Network error: %1").arg(m_reply->errorString()));
m_reply.reset();
return;
}
else if (statusCode != 200 && statusCode != 201)
{
QString reasonPhrase = m_reply->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toString();
emitFailed(tr("Error: %1 returned unexpected status code %2 %3").arg(m_uploadUrl).arg(statusCode).arg(reasonPhrase));
qCritical() << m_uploadUrl << " returned unexpected status code " << statusCode << " with body: " << data;
m_reply.reset();
return;
}
m_pasteLink = QString::fromUtf8(data).trimmed();
emitSucceeded();
}
bool PasteUpload::parseResult(QJsonDocument doc)
{
auto object = doc.object();
auto status = object.value("success").toBool();
if (!status)
{
qCritical() << "paste.ee reported error:" << QString(object.value("error").toString());
return false;
}
m_pasteLink = object.value("link").toString();
m_pasteID = object.value("id").toString();
qDebug() << m_pasteLink;
return true;
}

View File

@ -8,37 +8,21 @@ class PasteUpload : public Task
{
Q_OBJECT
public:
PasteUpload(QWidget *window, QString text, QString key = "public");
PasteUpload(QWidget *window, QString text, QString url);
virtual ~PasteUpload();
QString pasteLink()
{
return m_pasteLink;
}
QString pasteID()
{
return m_pasteID;
}
int maxSize()
{
// 2MB for paste.ee - public
if(m_key == "public")
return 1024*1024*2;
// 12MB for paste.ee - with actual key
return 1024*1024*12;
}
bool validateText();
protected:
virtual void executeTask();
private:
bool parseResult(QJsonDocument doc);
QString m_error;
QWidget *m_window;
QString m_pasteID;
QString m_pasteLink;
QString m_key;
QByteArray m_jsonContent;
QString m_uploadUrl;
QByteArray m_text;
std::shared_ptr<QNetworkReply> m_reply;
public
slots:

View File

@ -70,7 +70,7 @@ void NewsChecker::rssDownloadFinished()
}
// If the parsing succeeded, read it.
QDomNodeList items = doc.elementsByTagName("item");
QDomNodeList items = doc.elementsByTagName("entry");
m_newsEntries.clear();
for (int i = 0; i < items.length(); i++)
{

View File

@ -24,18 +24,14 @@ NewsEntry::NewsEntry(QObject* parent) :
this->title = tr("Untitled");
this->content = tr("No content.");
this->link = "";
this->author = tr("Unknown Author");
this->pubDate = QDateTime::currentDateTime();
}
NewsEntry::NewsEntry(const QString& title, const QString& content, const QString& link, const QString& author, const QDateTime& pubDate, QObject* parent) :
NewsEntry::NewsEntry(const QString& title, const QString& content, const QString& link, QObject* parent) :
QObject(parent)
{
this->title = title;
this->content = content;
this->link = link;
this->author = author;
this->pubDate = pubDate;
}
/*!
@ -59,19 +55,11 @@ bool NewsEntry::fromXmlElement(const QDomElement& element, NewsEntry* entry, QSt
{
QString title = childValue(element, "title", tr("Untitled"));
QString content = childValue(element, "description", tr("No content."));
QString link = childValue(element, "link");
QString author = childValue(element, "dc:creator", tr("Unknown Author"));
QString pubDateStr = childValue(element, "pubDate");
// FIXME: For now, we're just ignoring timezones. We assume that all time zones in the RSS feed are the same.
QString dateFormat("ddd, dd MMM yyyy hh:mm:ss");
QDateTime pubDate = QDateTime::fromString(pubDateStr, dateFormat);
QString link = childValue(element, "id");
entry->title = title;
entry->content = content;
entry->link = link;
entry->author = author;
entry->pubDate = pubDate;
return true;
}

View File

@ -18,8 +18,6 @@
#include <QObject>
#include <QString>
#include <QDomElement>
#include <QDateTime>
#include <memory>
class NewsEntry : public QObject
@ -36,7 +34,7 @@ public:
* Constructs a new news entry.
* Note that content may contain HTML.
*/
NewsEntry(const QString& title, const QString& content, const QString& link, const QString& author, const QDateTime& pubDate, QObject* parent=0);
NewsEntry(const QString& title, const QString& content, const QString& link, QObject* parent=0);
/*!
* Attempts to load information from the given XML element into the given news entry pointer.
@ -53,12 +51,6 @@ public:
//! URL to the post.
QString link;
//! The post's author.
QString author;
//! The date and time that this post was published.
QDateTime pubDate;
};
typedef std::shared_ptr<NewsEntry> NewsEntryPtr;

View File

@ -44,7 +44,7 @@ void NotificationChecker::checkForNotifications()
if (!m_notificationsUrl.isValid())
{
qCritical() << "Failed to check for notifications. No notifications URL set."
<< "If you'd like to use MultiMC's notification system, please pass the "
<< "If you'd like to use PolyMC's notification system, please pass the "
"URL to CMake at compile time.";
return;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

View File

@ -246,9 +246,13 @@
<!-- placeholder when loading screenshot images -->
<file>scalable/screenshot-placeholder.svg</file>
<!-- matrix logo -->
<file>scalable/matrix.svg</file>
<!-- discord logo icon thing. from discord. traced from bitmap -->
<file>scalable/discord.svg</file>
<!-- instance icons -->
<file>32x32/instances/chicken.png</file>
<file>128x128/instances/chicken.png</file>
@ -268,6 +272,9 @@
<file>32x32/instances/flame.png</file>
<file>128x128/instances/flame.png</file>
<file>32x32/instances/modrinth.png</file>
<file>128x128/instances/modrinth.png</file>
<file>32x32/instances/gear.png</file>
<file>128x128/instances/gear.png</file>

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