Compare commits
715 Commits
Author | SHA1 | Date | |
---|---|---|---|
da25f3b84e | |||
1e34de98ab | |||
7b46f50cf1 | |||
cab40026f2 | |||
ac66bddeda | |||
f4237be9bd | |||
dd11ccb3fd | |||
c4549a5375 | |||
e9b3140d12 | |||
22f5128e39 | |||
ae1aa6f63e | |||
5adcc26190 | |||
db6dae7541 | |||
4e97f2a6fe | |||
4643046989 | |||
3c3ce71214 | |||
0682fe544a | |||
27e803e4a4 | |||
405c44c9e1 | |||
4c5f701b05 | |||
c7563a5f7c | |||
3ff3c335bc | |||
b9d5e1bbf1 | |||
e313b366a0 | |||
027c666265 | |||
4a3d94aaf9 | |||
c637e3657c | |||
9462dd3ddc | |||
c3524a9d57 | |||
53ff66c317 | |||
ec2ac2e80c | |||
27c72935f8 | |||
31c757d912 | |||
fcdc7a1a35 | |||
f13c776099 | |||
ebded1ec49 | |||
7b9d462fbc | |||
c174a1eb01 | |||
ac77997a7a | |||
fa352ff4d3 | |||
fd7745cbeb | |||
c348de96e4 | |||
1bb35b9204 | |||
cbbcc2d68b | |||
fcbf37f60f | |||
56ce7f5dcd | |||
0ccbc801cf | |||
4c52cc414f | |||
6b45386252 | |||
3acc761419 | |||
dd4c67b654 | |||
0c581cfb62 | |||
703bf9bb7a | |||
a40dee2230 | |||
cab9afa45f | |||
ba5946dc60 | |||
9bad83a551 | |||
a549828655 | |||
c1398a6a1a | |||
e11d1b5202 | |||
abdb846c3f | |||
b0b6dd8f87 | |||
4a971226e4 | |||
b10d4d3b8f | |||
6ed130fc16 | |||
90d4acd1a1 | |||
a42d2afcee | |||
ba020fbd21 | |||
af167e8e67 | |||
be82f4db9e | |||
6a97ac603a | |||
e59d3a339f | |||
db7cb12551 | |||
1049507b3f | |||
1303771b58 | |||
f6605bc3f8 | |||
80ec178d5f | |||
ef76bd355a | |||
b0a8bd7dfe | |||
5d8d7740ba | |||
3e64935844 | |||
7577115c3c | |||
2cb242e9b3 | |||
7aeccbb6b0 | |||
8406c7f431 | |||
8c98cc9458 | |||
715d7d4424 | |||
8e9eca6a97 | |||
5f15f51610 | |||
277de41200 | |||
63bce04648 | |||
76dfb7825a | |||
5cb0e75093 | |||
c730fd6e5f | |||
c2b97c3e3f | |||
e0ab8207ed | |||
ecad388846 | |||
9a120f43c8 | |||
4ff1306e0c | |||
1dd663af6e | |||
06d9821b2c | |||
abb20c65e3 | |||
9fb5674233 | |||
18ac109e5a | |||
14a0e85862 | |||
fa2b3bcc63 | |||
620555d210 | |||
ea3ceb382a | |||
37a30fbc3f | |||
99193a2d7b | |||
abfb99ba3f | |||
fcb311eecd | |||
54e4f88ada | |||
89125fde22 | |||
9f3eed6ca2 | |||
ab82358dcb | |||
75fddd0052 | |||
8a2c5f5b0d | |||
66caac0bbc | |||
ab8d897bd7 | |||
3024dbcf2c | |||
eeae3eca67 | |||
d0cda6d605 | |||
167e32a69f | |||
be2512bb4b | |||
c3f1c13a31 | |||
35cfb41a9c | |||
74cdf5350d | |||
9349232bd4 | |||
1811302deb | |||
e6564aa69f | |||
566a83b245 | |||
9eb9ddc668 | |||
cc5261051f | |||
fa870bc026 | |||
99d569ed0e | |||
a1a7b9c151 | |||
dc6340bf38 | |||
8732bea99b | |||
bbc6b71138 | |||
5fb096d7b9 | |||
cf8680f1ab | |||
115d8b5945 | |||
bd8b61651a | |||
d2ffaee9f8 | |||
8f61633551 | |||
d33d5b847d | |||
c8879df621 | |||
c367769781 | |||
02b44256b2 | |||
b6e722a048 | |||
7f2615b2a5 | |||
a232c2d509 | |||
c8205fda9f | |||
8df88e7fbb | |||
c8092269ba | |||
9d88f07955 | |||
f267375ac2 | |||
d44fa416ca | |||
41d7b27d43 | |||
5f461374b8 | |||
d5576779b7 | |||
c098be40ab | |||
333f7cc320 | |||
9180c751d8 | |||
131a04653f | |||
6e6d495bc7 | |||
2c07f758a0 | |||
251f0efec2 | |||
e8697068fb | |||
269c1bbf58 | |||
9b8493c304 | |||
c389a711ed | |||
382548e0a7 | |||
a90fc3d7fe | |||
48a6380e31 | |||
64ca96f470 | |||
59b3e30821 | |||
92e5e0e95b | |||
9202996c62 | |||
e22d54abd3 | |||
b53ba12fa2 | |||
335115041c | |||
bac67800be | |||
306df9e17f | |||
5f2e768376 | |||
575c92ec47 | |||
4d8bf0b621 | |||
954074942e | |||
341eb16a4c | |||
3a7eeff135 | |||
659f93b1de | |||
ea60e48d9d | |||
6054abaffb | |||
3a1feed723 | |||
85f3fc9944 | |||
87cf38a377 | |||
5e77b548b1 | |||
104de9e795 | |||
424f4a72ff | |||
ec6409914d | |||
6a25cacc3e | |||
b1af689546 | |||
0a5dfeb3d7 | |||
6a180f495f | |||
3672dbc5af | |||
81b50c0387 | |||
bd60c54911 | |||
87acaa0926 | |||
54d2c91320 | |||
94e7961df0 | |||
0d46ea5c71 | |||
6bd345b1ad | |||
cb384261b8 | |||
75301bec4b | |||
d00c320c00 | |||
e13ca94061 | |||
e02369ba6b | |||
82c35f2746 | |||
a9d935f9ef | |||
92f3154e8f | |||
eb06d0116f | |||
f66910d054 | |||
1b47132ebb | |||
a89cbf116d | |||
471ea680a5 | |||
51de84407f | |||
d252917792 | |||
dfa5f614aa | |||
f3a244e90a | |||
c7c83a35fa | |||
6025cd0ca5 | |||
ce05ce92bb | |||
a5fc640f2c | |||
0a4a3fece5 | |||
fcf728f3b5 | |||
cd4851c98b | |||
3db5f30403 | |||
58957122b9 | |||
8b46658b05 | |||
571e322d66 | |||
ddda02f092 | |||
bf6fa6bce4 | |||
025a3cf730 | |||
6d9eaee7f9 | |||
7471ce4530 | |||
149ffb844f | |||
4cf3ac42c8 | |||
d16c6b0e69 | |||
76e1aba58b | |||
c560d06b8d | |||
0681568d3e | |||
c7fdfb8116 | |||
c6b1a776dc | |||
8accb6f04e | |||
d1d055564c | |||
2741c58a01 | |||
64399dd8d6 | |||
f2ca11688e | |||
3c0c57359b | |||
062fc79286 | |||
2da565f5d4 | |||
e8373bbf65 | |||
26acc836d9 | |||
9c22af9685 | |||
75d0078a38 | |||
536b1a23fc | |||
cafff5e504 | |||
dd5c4b6864 | |||
a2c85a8531 | |||
de4d757650 | |||
f22cd0e8c7 | |||
702a1da0ac | |||
768007d980 | |||
2e40ab6244 | |||
95182ed74b | |||
8bc6cdf55c | |||
6c0b101fed | |||
9841c0a63d | |||
17d200dc88 | |||
c8fec556c0 | |||
b7f2959353 | |||
4899d3c458 | |||
c311dba465 | |||
75ec4256e2 | |||
bb5a91c179 | |||
8225f1ac92 | |||
06d16c6b13 | |||
90780818ca | |||
a160bd0062 | |||
7e0312493b | |||
ccfd06ad21 | |||
48c2146a42 | |||
abb9fa8cbd | |||
f99245b917 | |||
e35db82c27 | |||
6202525372 | |||
ec66c8fd3d | |||
19804c5718 | |||
fa5fa53592 | |||
da43ed8ce1 | |||
2d1f99b765 | |||
f01b8f29c6 | |||
440e9731e2 | |||
acdb54b88e | |||
00c3336ec8 | |||
a268ac7141 | |||
aedb513c9e | |||
ac3a7acc45 | |||
8409aa2571 | |||
199740cc61 | |||
a0f76cba62 | |||
5b8003cbe5 | |||
c0719102a0 | |||
9d8bbf34e6 | |||
ec9d0e70fb | |||
f1e44291cc | |||
b3b613d8b4 | |||
177b685557 | |||
71a4333f55 | |||
f1c21a912a | |||
84a142096f | |||
bb2b344d33 | |||
b96572774f | |||
641a96e4a9 | |||
9f8983b570 | |||
e42c5b00a4 | |||
a3d7ad731d | |||
dc98609ef8 | |||
c799faaca6 | |||
07e4c4d189 | |||
c4a8fd353c | |||
91524d6d6e | |||
c1201997a3 | |||
d814e21f0d | |||
49d122a2c4 | |||
0813eba367 | |||
4fe13c64a1 | |||
b3c2a56ece | |||
9c57b54a81 | |||
b131d3b2ec | |||
16bfafa29e | |||
f714adf6d2 | |||
dc9e250868 | |||
b6cf0359fa | |||
39bd04f06f | |||
d755174bee | |||
1229e90817 | |||
5a638fa977 | |||
5e9d49a910 | |||
ae39d16c11 | |||
b93daf1fb7 | |||
6545d250e8 | |||
b162351ff4 | |||
53468ea474 | |||
3697d70b48 | |||
e0c025b162 | |||
9e443faba3 | |||
f95cebaf06 | |||
9a8599e4ba | |||
2d68308d49 | |||
0dd1c26cf3 | |||
881b2f2b38 | |||
ca211558b5 | |||
3a03f90831 | |||
9020f632b2 | |||
8bdd2befe9 | |||
ebececf8c6 | |||
e1f28be151 | |||
10231aa404 | |||
139ff82432 | |||
4e8f075ff3 | |||
148775b3e9 | |||
075d900d45 | |||
5d1ca33b84 | |||
ccc493cb2b | |||
2745325ae0 | |||
84e9ce71b0 | |||
88fc1e32ee | |||
4f975bfb04 | |||
692b9cf0e0 | |||
ae354688c9 | |||
c9bf7f9896 | |||
e8929599a5 | |||
27f37315f8 | |||
c4f4e9e620 | |||
f2b850ad20 | |||
ccc27d1b7c | |||
4835ec3f6d | |||
40a9828fba | |||
04840d0638 | |||
38f12c50f7 | |||
ca8b62291f | |||
69d01204e0 | |||
1e3b896fda | |||
9e35560554 | |||
f9d4751ec0 | |||
a66e6a413f | |||
2c911a5475 | |||
e2c2a38005 | |||
aa4a6bb3be | |||
4af020161d | |||
f8b0d6453a | |||
0102e91940 | |||
1004211a66 | |||
f5cf4eb45f | |||
512395e3f1 | |||
9c6727e27f | |||
624ab25cd4 | |||
a70d1f1a91 | |||
3059f13011 | |||
6d1f9d4d02 | |||
d3e7d30ee0 | |||
5bbb4f31dc | |||
da70122d9c | |||
8556ff5eac | |||
adacab3349 | |||
613b351f13 | |||
80a29af497 | |||
7e1fad55d9 | |||
9b7cd029a7 | |||
c5d9944993 | |||
14717396eb | |||
9c71f364d2 | |||
be910374dc | |||
10de75623e | |||
7fc55b58fe | |||
12c8a04458 | |||
796e58b6f2 | |||
a7d37fa69a | |||
7b4b997a34 | |||
6b4469c6cc | |||
107a0ea852 | |||
6d7676202f | |||
0305b7a1fd | |||
02384f81c7 | |||
4536b19512 | |||
45f89c6255 | |||
b1cf77e847 | |||
037b0d7190 | |||
ff17202b43 | |||
a3d8313dcb | |||
36841eaf63 | |||
e24a183dad | |||
8596753a63 | |||
51183bef33 | |||
2cd837896d | |||
c75ae71190 | |||
48c20f5aaa | |||
929a035f96 | |||
5779f20fa1 | |||
384e0df9e1 | |||
a5b06514c6 | |||
a309f4e721 | |||
159d868b77 | |||
0854e83ce4 | |||
bb02226870 | |||
9ddbaaf7e8 | |||
3b7cc4391a | |||
70a055bc27 | |||
61db1c46be | |||
a60b2feb5f | |||
6ba031f048 | |||
812f00eb81 | |||
2f6973e08b | |||
fb14796ed7 | |||
7d912726d0 | |||
e3c8eb062c | |||
3cf81faabc | |||
0df605e559 | |||
e97a6ef957 | |||
c4dd8d9c72 | |||
bcfa3246cb | |||
f67871e79e | |||
11f892380e | |||
fd72cb034c | |||
b9be8d08d2 | |||
33d369d78c | |||
0e6e6a7521 | |||
eb692c2ee9 | |||
3eee38fedd | |||
0ba61bb590 | |||
9497485103 | |||
551d9c86ba | |||
e61e827eb9 | |||
92a5b12bd9 | |||
35d1330fe2 | |||
b4e0b7584a | |||
2341212337 | |||
53ea261350 | |||
a17e5d0a4d | |||
5d4a66ed8a | |||
8d2e7db178 | |||
383c93ff01 | |||
13d41bde7f | |||
d42d6fe25a | |||
beaac54dc9 | |||
70f8cb81b8 | |||
f8ca6b4867 | |||
49f5f67467 | |||
35d2ae3ef7 | |||
22ca572ae0 | |||
619fcbfabf | |||
292869141f | |||
ca9929214d | |||
121ad4e4bf | |||
2f87a4477e | |||
d72c511131 | |||
8b68c06547 | |||
b911151786 | |||
7531a2894b | |||
5b507a8944 | |||
d2f86cbf32 | |||
08dff6613b | |||
901ec15dc8 | |||
5284d604ef | |||
b2b4ab3f0c | |||
b646fc5a13 | |||
d35cbfd9c4 | |||
f25152e068 | |||
dd8946b15a | |||
305350fdc8 | |||
f31d5372e7 | |||
ca1a2bbe2c | |||
dba9199e58 | |||
e806903d7e | |||
41d8e3cbd7 | |||
5e32783c4e | |||
fdc3a4104b | |||
8199941a81 | |||
651d237200 | |||
6f5b380199 | |||
c746d77a06 | |||
9ab3841570 | |||
3a28741cc3 | |||
22f7a85cf2 | |||
86935068f5 | |||
00e12b776b | |||
3b96a9a8fa | |||
5ac5c767e0 | |||
f1d3d4a366 | |||
1160066f0d | |||
8d603d6162 | |||
076efc4cb2 | |||
2c62a34c2f | |||
2177aa2a6b | |||
e8a4902a3d | |||
e2952061af | |||
fcc4420cfe | |||
f5358aa1ca | |||
3d3f9a8609 | |||
1f176fcb7b | |||
3ca661127f | |||
407f9d9ef0 | |||
bff683e6d4 | |||
770da6317e | |||
cf3c2482c9 | |||
2001c5dec7 | |||
80cf716c98 | |||
37e1962845 | |||
f8c5d80c66 | |||
11841c47e6 | |||
71b1ac9f34 | |||
eda06df878 | |||
c4cb7ddc4f | |||
a8089b76c0 | |||
71516e6c72 | |||
88686ef065 | |||
0442b80a2c | |||
81c72c2038 | |||
3aa809b8c0 | |||
efa414c442 | |||
c39da093bf | |||
aa2c27bf69 | |||
1f92125a7f | |||
5c48b7dfab | |||
d664361b15 | |||
813de1c703 | |||
02f24117f0 | |||
7a7a937f1e | |||
0211ee3ef1 | |||
c569bfbe6d | |||
b925338688 | |||
2cf04d034a | |||
049aafd0a1 | |||
e0a04c5031 | |||
9d23ac562f | |||
0065a29901 | |||
8ea1ebaf1b | |||
5c2d3e430d | |||
b710b719a8 | |||
7df5091fdc | |||
5abb97362f | |||
b34239ebc6 | |||
7ef6c586c5 | |||
9d36cf4b5a | |||
04be2404ce | |||
7f4fd04cfe | |||
b2bcdb9d9b | |||
d81e2bb0b0 | |||
177c10bb0f | |||
304775952f | |||
ca00103ee2 | |||
3aa9f5c376 | |||
efc44c56a6 | |||
8b790a6dd9 | |||
f36930d812 | |||
232295bda7 | |||
451768ccf9 | |||
c1aaf89baa | |||
5ac528f141 | |||
33aac2985a | |||
361ce7818e | |||
ad6e3a0868 | |||
14a8ead6b4 | |||
bbf0508846 | |||
79314ee67b | |||
86b0637ef7 | |||
1c982b0182 | |||
cd5faee7d7 | |||
ec1e27031a | |||
02889b7a11 | |||
0eff21a4f1 | |||
0680945839 | |||
631e670775 | |||
4edd2cff9f | |||
0235eb5c28 | |||
8804b035b2 | |||
54e3438e37 | |||
ddfed7bb87 | |||
70c04745ee | |||
63d4486855 | |||
1d0e6bf453 | |||
a2d88f6df4 | |||
019c77f9f7 | |||
5b5c5afc3a | |||
af20b5ee0e | |||
a1b779da15 | |||
8b31c638f3 | |||
3da69d8e53 | |||
dd76fb0ec7 | |||
caeab926bc | |||
35caa3c21a | |||
7022d3d401 | |||
6d22794cf9 | |||
b50e584369 | |||
affc2521aa | |||
63098b6f19 | |||
83e1dd285a | |||
b9beb3c7d2 | |||
2dd2555a63 | |||
126e6d13aa | |||
236c0166f6 | |||
9a33fb1f49 | |||
2c2c22ccf8 | |||
55597b458c | |||
f55297eca9 | |||
0bc8baf117 | |||
5f9270ed4b | |||
81fe41a038 | |||
0316cf88aa | |||
917f8a31e3 | |||
aa770b63fb | |||
c1bf31cb27 | |||
86d99f80c3 | |||
975f77756d | |||
8172dcd2d5 | |||
b95c27ceef | |||
f78bb90ed9 | |||
dc129fd886 | |||
621e0ba4a8 | |||
f6de472da2 | |||
4b37c46889 | |||
c371558883 | |||
0bbd0ac0b9 | |||
ac93c64cd4 | |||
6cd4375aff | |||
a606b47a22 | |||
a62155c1c9 | |||
b4f750e7db | |||
b19e315615 | |||
41dba376a8 | |||
2896f70cd8 | |||
1a8c972aef | |||
cdaa397dcf | |||
9e6fa8f29a | |||
4d599eb118 | |||
4e9039be2d | |||
395e265564 | |||
b07853c9ef | |||
b635a7e693 | |||
f84fc783b6 | |||
2301a934b0 | |||
60e9d2754a | |||
d06c2cacb1 | |||
49c2bd477c | |||
46a3b4de6e | |||
6ecc8c5496 | |||
a1ff3b1ee3 | |||
d4b522b6cb | |||
3b524e99cc | |||
3329d94c9b | |||
a12118f1a0 | |||
5fe33a98a2 | |||
1d8196e11a | |||
c7f6f94930 | |||
131615811b | |||
3fa6e22430 | |||
c86ac772c8 | |||
52420963cf | |||
addf5f4e52 | |||
03d7300732 | |||
a97d0a36f4 | |||
e9c52ec696 | |||
75f2dab3c8 |
4
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
4
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
@ -1,6 +1,6 @@
|
|||||||
name: Bug Report
|
name: Bug Report
|
||||||
description: File a bug report
|
description: File a bug report
|
||||||
labels: [bug, needs-triage]
|
labels: [bug]
|
||||||
body:
|
body:
|
||||||
- type: markdown
|
- type: markdown
|
||||||
attributes:
|
attributes:
|
||||||
@ -8,7 +8,7 @@ body:
|
|||||||
If you need help with running Minecraft, please visit us on our Discord before making a bug report.
|
If you need help with running Minecraft, please visit us on our Discord before making a bug report.
|
||||||
|
|
||||||
Before submitting a bug report, please make sure you have read this *entire* form, and that:
|
Before submitting a bug report, please make sure you have read this *entire* form, and that:
|
||||||
* You have read the [FAQ](https://github.com/PolyMC/PolyMC/wiki/FAQ) and it has not answered your question
|
* You have read the [PolyMC wiki](https://polymc.org/wiki/) and it has not answered your question.
|
||||||
* Your bug is not caused by Minecraft or any mods you have installed.
|
* Your bug is not caused by Minecraft or any mods you have installed.
|
||||||
* Your issue has not been reported before, [make sure to use the search function!](https://github.com/PolyMC/PolyMC/issues)
|
* Your issue has not been reported before, [make sure to use the search function!](https://github.com/PolyMC/PolyMC/issues)
|
||||||
|
|
||||||
|
68
.github/ISSUE_TEMPLATE/rfc.yml
vendored
Normal file
68
.github/ISSUE_TEMPLATE/rfc.yml
vendored
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
# 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.
|
2
.github/ISSUE_TEMPLATE/suggestion.yml
vendored
2
.github/ISSUE_TEMPLATE/suggestion.yml
vendored
@ -1,6 +1,6 @@
|
|||||||
name: Suggestion
|
name: Suggestion
|
||||||
description: Make a suggestion
|
description: Make a suggestion
|
||||||
labels: [idea, needs-triage]
|
labels: [enhancement]
|
||||||
body:
|
body:
|
||||||
- type: markdown
|
- type: markdown
|
||||||
attributes:
|
attributes:
|
||||||
|
41
.github/scripts/prepare_JREs.sh
vendored
Executable file
41
.github/scripts/prepare_JREs.sh
vendored
Executable 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
|
19
.github/workflows/backport.yml
vendored
Normal file
19
.github/workflows/backport.yml
vendored
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
name: Backport PR to stable
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
branches: [ develop ]
|
||||||
|
types: [ closed ]
|
||||||
|
jobs:
|
||||||
|
release_pull_request:
|
||||||
|
if: github.event.pull_request.merged == true && contains(github.event.pull_request.labels.*.name, 'backport')
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: checkout
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
- name: Backport PR by cherry-pick-ing
|
||||||
|
uses: Nathanmalnoury/gh-backport-action@master
|
||||||
|
with:
|
||||||
|
pr_branch: 'stable'
|
||||||
|
github_token: ${{ secrets.GITHUB_TOKEN }}
|
255
.github/workflows/build.yml
vendored
Normal file
255
.github/workflows/build.yml
vendored
Normal file
@ -0,0 +1,255 @@
|
|||||||
|
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
|
||||||
|
|
||||||
|
- os: ubuntu-20.04
|
||||||
|
appimage: true
|
||||||
|
|
||||||
|
- os: windows-2022
|
||||||
|
name: "Windows-i686"
|
||||||
|
msystem: mingw32
|
||||||
|
|
||||||
|
- os: windows-2022
|
||||||
|
name: "Windows-x86_64"
|
||||||
|
msystem: mingw64
|
||||||
|
|
||||||
|
- os: macos-11
|
||||||
|
macosx_deployment_target: 10.13
|
||||||
|
|
||||||
|
runs-on: ${{ matrix.os }}
|
||||||
|
|
||||||
|
env:
|
||||||
|
MACOSX_DEPLOYMENT_TARGET: ${{ matrix.macosx_deployment_target }}
|
||||||
|
INSTALL_DIR: "install"
|
||||||
|
INSTALL_PORTABLE_DIR: "install-portable"
|
||||||
|
INSTALL_APPIMAGE_DIR: "install-appdir"
|
||||||
|
BUILD_DIR: "build"
|
||||||
|
|
||||||
|
steps:
|
||||||
|
##
|
||||||
|
# PREPARE
|
||||||
|
##
|
||||||
|
- 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 Qt (macOS)
|
||||||
|
if: runner.os == 'macOS'
|
||||||
|
run: |
|
||||||
|
brew update
|
||||||
|
brew install qt@5 ninja
|
||||||
|
|
||||||
|
- name: Update Qt (AppImage)
|
||||||
|
if: runner.os == 'Linux' && matrix.appimage == true
|
||||||
|
run: |
|
||||||
|
sudo add-apt-repository ppa:savoury1/qt-5-15
|
||||||
|
|
||||||
|
- name: Install Qt (Linux)
|
||||||
|
if: runner.os == 'Linux'
|
||||||
|
run: |
|
||||||
|
sudo apt-get -y update
|
||||||
|
sudo apt-get -y install qtbase5-dev qtchooser qt5-qmake qtbase5-dev-tools libqt5core5a libqt5network5 libqt5gui5 ninja-build
|
||||||
|
|
||||||
|
- name: Prepare AppImage (Linux)
|
||||||
|
if: runner.os == 'Linux' && matrix.appimage == 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"
|
||||||
|
|
||||||
|
${{ github.workspace }}/.github/scripts/prepare_JREs.sh
|
||||||
|
|
||||||
|
##
|
||||||
|
# CONFIGURE
|
||||||
|
##
|
||||||
|
|
||||||
|
- name: Configure CMake (macOS)
|
||||||
|
if: runner.os == 'macOS'
|
||||||
|
run: |
|
||||||
|
cmake -S . -B ${{ env.BUILD_DIR }} -DCMAKE_INSTALL_PREFIX=${{ env.INSTALL_DIR }} -DCMAKE_BUILD_TYPE=${{ inputs.build_type }} -DENABLE_LTO=ON -DQt5_DIR=/usr/local/opt/qt@5 -DCMAKE_PREFIX_PATH=/usr/local/opt/qt@5 -DLauncher_BUILD_PLATFORM=macOS -G Ninja
|
||||||
|
|
||||||
|
- name: Configure CMake (Windows)
|
||||||
|
if: runner.os == 'Windows'
|
||||||
|
shell: msys2 {0}
|
||||||
|
run: |
|
||||||
|
cmake -S . -B ${{ env.BUILD_DIR }} -DCMAKE_INSTALL_PREFIX=${{ env.INSTALL_DIR }} -DCMAKE_BUILD_TYPE=${{ inputs.build_type }} -DENABLE_LTO=ON -DLauncher_BUILD_PLATFORM=${{ matrix.name }} -G Ninja
|
||||||
|
|
||||||
|
- name: Configure CMake (Linux)
|
||||||
|
if: runner.os == 'Linux'
|
||||||
|
run: |
|
||||||
|
cmake -S . -B ${{ env.BUILD_DIR }} -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_BUILD_TYPE=${{ inputs.build_type }} -DENABLE_LTO=ON -DLauncher_BUILD_PLATFORM=Linux -G Ninja
|
||||||
|
|
||||||
|
##
|
||||||
|
# BUILD
|
||||||
|
##
|
||||||
|
|
||||||
|
- name: Build
|
||||||
|
if: runner.os != 'Windows'
|
||||||
|
run: |
|
||||||
|
cmake --build ${{ env.BUILD_DIR }}
|
||||||
|
|
||||||
|
- name: Build (Windows)
|
||||||
|
if: runner.os == 'Windows'
|
||||||
|
shell: msys2 {0}
|
||||||
|
run: |
|
||||||
|
cmake --build ${{ env.BUILD_DIR }}
|
||||||
|
|
||||||
|
##
|
||||||
|
# PACKAGE BUILDS
|
||||||
|
##
|
||||||
|
|
||||||
|
- name: Package (macOS)
|
||||||
|
if: runner.os == 'macOS'
|
||||||
|
run: |
|
||||||
|
cmake --install ${{ env.BUILD_DIR }}
|
||||||
|
|
||||||
|
cd ${{ env.INSTALL_DIR }}
|
||||||
|
chmod +x "PolyMC.app/Contents/MacOS/polymc"
|
||||||
|
sudo codesign --sign - --deep --force --entitlements "../program_info/App.entitlements" --options runtime "PolyMC.app/Contents/MacOS/polymc"
|
||||||
|
tar -czf ../PolyMC.tar.gz *
|
||||||
|
|
||||||
|
- name: Package (Windows)
|
||||||
|
if: runner.os == 'Windows'
|
||||||
|
shell: msys2 {0}
|
||||||
|
run: |
|
||||||
|
cmake --install ${{ env.BUILD_DIR }}
|
||||||
|
|
||||||
|
cd ${{ env.INSTALL_DIR }}
|
||||||
|
if [ "${{ matrix.msystem }}" == "mingw32" ]; then
|
||||||
|
cp /mingw32/bin/libcrypto-1_1.dll /mingw32/bin/libssl-1_1.dll ./
|
||||||
|
elif [ "${{ matrix.msystem }}" == "mingw64" ]; then
|
||||||
|
cp /mingw64/bin/libcrypto-1_1-x64.dll /mingw64/bin/libssl-1_1-x64.dll ./
|
||||||
|
fi
|
||||||
|
|
||||||
|
- name: Package (Windows, portable)
|
||||||
|
if: runner.os == 'Windows'
|
||||||
|
shell: msys2 {0}
|
||||||
|
run: |
|
||||||
|
cp -r ${{ env.INSTALL_DIR }} ${{ env.INSTALL_PORTABLE_DIR }} # cmake install on Windows is slow, let's just copy instead
|
||||||
|
cmake --install ${{ env.BUILD_DIR }} --prefix ${{ env.INSTALL_PORTABLE_DIR }} --component portable
|
||||||
|
|
||||||
|
- name: Package (Linux)
|
||||||
|
if: runner.os == 'Linux' && matrix.appimage != true
|
||||||
|
run: |
|
||||||
|
cmake --install ${{ env.BUILD_DIR }} --prefix ${{ env.INSTALL_DIR }}
|
||||||
|
|
||||||
|
cd ${{ env.INSTALL_DIR }}
|
||||||
|
tar --owner root --group root -czf ../PolyMC.tar.gz *
|
||||||
|
|
||||||
|
- name: Package (Linux, portable)
|
||||||
|
if: runner.os == 'Linux' && matrix.appimage != true
|
||||||
|
run: |
|
||||||
|
cmake --install ${{ env.BUILD_DIR }} --prefix ${{ env.INSTALL_PORTABLE_DIR }}
|
||||||
|
cmake --install ${{ env.BUILD_DIR }} --prefix ${{ env.INSTALL_PORTABLE_DIR }} --component portable
|
||||||
|
|
||||||
|
cd ${{ env.INSTALL_PORTABLE_DIR }}
|
||||||
|
tar -czf ../PolyMC-portable.tar.gz *
|
||||||
|
|
||||||
|
- name: Package AppImage (Linux)
|
||||||
|
if: runner.os == 'Linux' && matrix.appimage == true
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
cmake --install ${{ env.BUILD_DIR }} --prefix ${{ env.INSTALL_APPIMAGE_DIR }}/usr
|
||||||
|
|
||||||
|
export OUTPUT="PolyMC-${{ runner.os }}-${{ env.VERSION }}-${{ inputs.build_type }}-x86_64.AppImage"
|
||||||
|
|
||||||
|
chmod +x linuxdeploy-*.AppImage
|
||||||
|
|
||||||
|
mkdir -p ${{ env.INSTALL_APPIMAGE_DIR }}/usr/lib/jvm/java-{8,17}-openjdk
|
||||||
|
|
||||||
|
cp -r ${{ github.workspace }}/JREs/jre8/* ${{ env.INSTALL_APPIMAGE_DIR }}/usr/lib/jvm/java-8-openjdk
|
||||||
|
|
||||||
|
cp -r ${{ github.workspace }}/JREs/jre17/* ${{ env.INSTALL_APPIMAGE_DIR }}/usr/lib/jvm/java-17-openjdk
|
||||||
|
|
||||||
|
LD_LIBRARY_PATH="${LD_LIBRARY_PATH}:${{ env.INSTALL_APPIMAGE_DIR }}/usr/lib"
|
||||||
|
LD_LIBRARY_PATH="${LD_LIBRARY_PATH}:${{ env.INSTALL_APPIMAGE_DIR }}/usr/lib/jvm/java-8-openjdk/lib/amd64/server"
|
||||||
|
LD_LIBRARY_PATH="${LD_LIBRARY_PATH}:${{ env.INSTALL_APPIMAGE_DIR }}/usr/lib/jvm/java-8-openjdk/lib/amd64"
|
||||||
|
LD_LIBRARY_PATH="${LD_LIBRARY_PATH}:${{ env.INSTALL_APPIMAGE_DIR }}/usr/lib/jvm/java-17-openjdk/lib/server"
|
||||||
|
LD_LIBRARY_PATH="${LD_LIBRARY_PATH}:${{ env.INSTALL_APPIMAGE_DIR }}/usr/lib/jvm/java-17-openjdk/lib"
|
||||||
|
export LD_LIBRARY_PATH
|
||||||
|
|
||||||
|
./linuxdeploy-x86_64.AppImage --appdir ${{ env.INSTALL_APPIMAGE_DIR }} --output appimage --plugin qt -i ${{ env.INSTALL_APPIMAGE_DIR }}/usr/share/icons/hicolor/scalable/apps/org.polymc.PolyMC.svg
|
||||||
|
|
||||||
|
##
|
||||||
|
# UPLOAD BUILDS
|
||||||
|
##
|
||||||
|
|
||||||
|
- name: Upload binary tarball (macOS)
|
||||||
|
if: runner.os == 'macOS'
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: PolyMC-${{ runner.os }}-${{ env.VERSION }}-${{ inputs.build_type }}
|
||||||
|
path: PolyMC.tar.gz
|
||||||
|
|
||||||
|
- name: Upload binary zip (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 binary zip (Windows, portable)
|
||||||
|
if: runner.os == 'Windows'
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: PolyMC-${{ matrix.name }}-Portable-${{ env.VERSION }}-${{ inputs.build_type }}
|
||||||
|
path: ${{ env.INSTALL_PORTABLE_DIR }}/**
|
||||||
|
|
||||||
|
- name: Upload binary tarball (Linux)
|
||||||
|
if: runner.os == 'Linux' && matrix.appimage != true
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: PolyMC-${{ runner.os }}-${{ env.VERSION }}-${{ inputs.build_type }}
|
||||||
|
path: PolyMC.tar.gz
|
||||||
|
|
||||||
|
- name: Upload binary tarball (Linux, portable)
|
||||||
|
if: runner.os == 'Linux' && matrix.appimage != true
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: PolyMC-${{ runner.os }}-Portable-${{ env.VERSION }}-${{ inputs.build_type }}
|
||||||
|
path: PolyMC-portable.tar.gz
|
||||||
|
|
||||||
|
- name: Upload AppImage (Linux)
|
||||||
|
if: runner.os == 'Linux' && matrix.appimage == 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
|
||||||
|
|
||||||
|
|
61
.github/workflows/pr-comment.yml
vendored
Normal file
61
.github/workflows/pr-comment.yml
vendored
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
name: Comment on pull request
|
||||||
|
on:
|
||||||
|
workflow_run:
|
||||||
|
workflows: ['Test workflow with upload']
|
||||||
|
types: [completed]
|
||||||
|
jobs:
|
||||||
|
pr_comment:
|
||||||
|
if: github.event.workflow_run.event == 'pull_request' && github.event.workflow_run.conclusion == 'success'
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/github-script@v5
|
||||||
|
with:
|
||||||
|
# This snippet is public-domain, taken from
|
||||||
|
# https://github.com/oprypin/nightly.link/blob/master/.github/workflows/pr-comment.yml
|
||||||
|
script: |
|
||||||
|
async function upsertComment(owner, repo, issue_number, purpose, body) {
|
||||||
|
const {data: comments} = await github.rest.issues.listComments(
|
||||||
|
{owner, repo, issue_number});
|
||||||
|
|
||||||
|
const marker = `<!-- bot: ${purpose} -->`;
|
||||||
|
body = marker + "\n" + body;
|
||||||
|
|
||||||
|
const existing = comments.filter((c) => c.body.includes(marker));
|
||||||
|
if (existing.length > 0) {
|
||||||
|
const last = existing[existing.length - 1];
|
||||||
|
core.info(`Updating comment ${last.id}`);
|
||||||
|
await github.rest.issues.updateComment({
|
||||||
|
owner, repo,
|
||||||
|
body,
|
||||||
|
comment_id: last.id,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
core.info(`Creating a comment in issue / PR #${issue_number}`);
|
||||||
|
await github.rest.issues.createComment({issue_number, body, owner, repo});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const {owner, repo} = context.repo;
|
||||||
|
const run_id = ${{github.event.workflow_run.id}};
|
||||||
|
|
||||||
|
const pull_requests = ${{ toJSON(github.event.workflow_run.pull_requests) }};
|
||||||
|
if (!pull_requests.length) {
|
||||||
|
return core.error("This workflow doesn't match any pull requests!");
|
||||||
|
}
|
||||||
|
|
||||||
|
const artifacts = await github.paginate(
|
||||||
|
github.rest.actions.listWorkflowRunArtifacts, {owner, repo, run_id});
|
||||||
|
if (!artifacts.length) {
|
||||||
|
return core.error(`No artifacts found`);
|
||||||
|
}
|
||||||
|
let body = `Download the artifacts for this pull request:\n`;
|
||||||
|
for (const art of artifacts) {
|
||||||
|
body += `\n* [${art.name}.zip](https://nightly.link/${owner}/${repo}/actions/artifacts/${art.id}.zip)`;
|
||||||
|
}
|
||||||
|
|
||||||
|
core.info("Review thread message body:", body);
|
||||||
|
|
||||||
|
for (const pr of pull_requests) {
|
||||||
|
await upsertComment(owner, repo, pr.number,
|
||||||
|
"nightly-link", body);
|
||||||
|
}
|
30
.github/workflows/trigger_builds.yml
vendored
Normal file
30
.github/workflows/trigger_builds.yml
vendored
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
name: Build Application
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches-ignore:
|
||||||
|
- 'stable'
|
||||||
|
paths-ignore:
|
||||||
|
- '**.md'
|
||||||
|
- '**/LICENSE'
|
||||||
|
- 'flake.lock'
|
||||||
|
- '**.nix'
|
||||||
|
- 'packages/**'
|
||||||
|
- '.github/ISSUE_TEMPLATE/**'
|
||||||
|
pull_request:
|
||||||
|
paths-ignore:
|
||||||
|
- '**.md'
|
||||||
|
- '**/LICENSE'
|
||||||
|
- 'flake.lock'
|
||||||
|
- '**.nix'
|
||||||
|
- 'packages/**'
|
||||||
|
- '.github/ISSUE_TEMPLATE/**'
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
|
||||||
|
build_debug:
|
||||||
|
name: Build Debug
|
||||||
|
uses: ./.github/workflows/build.yml
|
||||||
|
with:
|
||||||
|
build_type: Debug
|
72
.github/workflows/trigger_release.yml
vendored
Normal file
72
.github/workflows/trigger_release.yml
vendored
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
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-Portable*/PolyMC-portable.tar.gz PolyMC-Linux-Portable-${{ env.VERSION }}.tar.gz
|
||||||
|
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-Portable-${{ 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
|
14
.gitignore
vendored
14
.gitignore
vendored
@ -14,6 +14,8 @@ CMakeLists.txt.user.*
|
|||||||
/.project
|
/.project
|
||||||
/.settings
|
/.settings
|
||||||
/.idea
|
/.idea
|
||||||
|
/.vscode
|
||||||
|
.clang-format
|
||||||
cmake-build-*/
|
cmake-build-*/
|
||||||
Debug
|
Debug
|
||||||
|
|
||||||
@ -40,13 +42,9 @@ run/
|
|||||||
|
|
||||||
.cache/
|
.cache/
|
||||||
|
|
||||||
# Flatpak builds
|
|
||||||
.flatpak-builder
|
|
||||||
flatbuild
|
|
||||||
builddir
|
|
||||||
# Deb
|
|
||||||
packages/debian/polymc/usr/
|
|
||||||
packages/debian/polymc.deb
|
|
||||||
packages/debian/polymc/DEBIAN/control
|
|
||||||
# Nix/NixOS
|
# Nix/NixOS
|
||||||
result/
|
result/
|
||||||
|
|
||||||
|
# Flatpak
|
||||||
|
.flatpak-builder
|
||||||
|
flatbuild
|
||||||
|
10
.gitmodules
vendored
10
.gitmodules
vendored
@ -1,8 +1,8 @@
|
|||||||
[submodule "depends/libnbtplusplus"]
|
[submodule "depends/libnbtplusplus"]
|
||||||
path = libraries/libnbtplusplus
|
path = libraries/libnbtplusplus
|
||||||
url = https://github.com/MultiMC/libnbtplusplus.git
|
url = https://github.com/PolyMC/libnbtplusplus.git
|
||||||
pushurl = git@github.com:MultiMC/libnbtplusplus.git
|
pushurl = git@github.com:PolyMC/libnbtplusplus.git
|
||||||
|
|
||||||
[submodule "libraries/quazip"]
|
[submodule "libraries/quazip"]
|
||||||
path = libraries/quazip
|
path = libraries/quazip
|
||||||
url = https://github.com/PolyMC/quazip.git
|
url = https://github.com/stachenov/quazip.git
|
||||||
pushurl = git@github.com:PolyMC/quazip.git
|
|
||||||
|
245
BUILD.md
245
BUILD.md
@ -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)
|
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).
|
||||||
* [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 -`.
|
|
||||||
|
181
CMakeLists.txt
181
CMakeLists.txt
@ -1,4 +1,4 @@
|
|||||||
cmake_minimum_required(VERSION 3.1)
|
cmake_minimum_required(VERSION 3.9.4)
|
||||||
|
|
||||||
if(WIN32)
|
if(WIN32)
|
||||||
# In Qt 5.1+ we have our own main() function, don't autolink to qtmain on Windows
|
# In Qt 5.1+ we have our own main() function, don't autolink to qtmain on Windows
|
||||||
@ -6,7 +6,7 @@ if(WIN32)
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
project(Launcher)
|
project(Launcher)
|
||||||
enable_testing()
|
include(CTest)
|
||||||
|
|
||||||
string(COMPARE EQUAL "${CMAKE_SOURCE_DIR}" "${CMAKE_BUILD_DIR}" IS_IN_SOURCE_BUILD)
|
string(COMPARE EQUAL "${CMAKE_SOURCE_DIR}" "${CMAKE_BUILD_DIR}" IS_IN_SOURCE_BUILD)
|
||||||
if(IS_IN_SOURCE_BUILD)
|
if(IS_IN_SOURCE_BUILD)
|
||||||
@ -43,48 +43,77 @@ set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -Werror=return-type")
|
|||||||
# Fix build with Qt 5.13
|
# Fix build with Qt 5.13
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DQT_NO_DEPRECATED_WARNINGS=Y")
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DQT_NO_DEPRECATED_WARNINGS=Y")
|
||||||
|
|
||||||
|
option(ENABLE_LTO "Enable Link Time Optimization" off)
|
||||||
|
|
||||||
|
if(ENABLE_LTO)
|
||||||
|
include(CheckIPOSupported)
|
||||||
|
check_ipo_supported(RESULT ipo_supported OUTPUT ipo_error)
|
||||||
|
|
||||||
|
if(ipo_supported AND (CMAKE_BUILD_TYPE STREQUAL "Release" OR CMAKE_BUILD_TYPE STREQUAL "MinSizeRel"))
|
||||||
|
message(STATUS "IPO / LTO enabled")
|
||||||
|
set(CMAKE_INTERPROCEDURAL_OPTIMIZATION TRUE)
|
||||||
|
elseif(ipo_supported)
|
||||||
|
message(STATUS "Not enabling IPO / LTO on debug builds")
|
||||||
|
else()
|
||||||
|
message(STATUS "IPO / LTO not supported: <${ipo_error}>")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
##################################### Set Application options #####################################
|
##################################### Set Application options #####################################
|
||||||
|
|
||||||
######## Set URLs ########
|
######## 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/help-pages/%1" CACHE STRING "URL (with arg %1 to be substituted with page-id) that gets opened when the user requests help")
|
||||||
|
|
||||||
######## Set version numbers ########
|
######## Set version numbers ########
|
||||||
set(Launcher_VERSION_MAJOR 1)
|
set(Launcher_VERSION_MAJOR 1)
|
||||||
set(Launcher_VERSION_MINOR 0)
|
set(Launcher_VERSION_MINOR 2)
|
||||||
set(Launcher_VERSION_HOTFIX 6)
|
set(Launcher_VERSION_HOTFIX 2)
|
||||||
|
|
||||||
# Build number
|
# Build number
|
||||||
set(Launcher_VERSION_BUILD -1 CACHE STRING "Build number. -1 for no build number.")
|
set(Launcher_VERSION_BUILD -1 CACHE STRING "Build number. -1 for no build number.")
|
||||||
|
|
||||||
# Build platform.
|
# Build platform.
|
||||||
set(Launcher_BUILD_PLATFORM "" CACHE STRING "A short string identifying the platform that this build was built for. Only used by the notification system and to display in the about dialog.")
|
set(Launcher_BUILD_PLATFORM "" CACHE STRING "A short string identifying the platform that this build was built for. Only used to display in the about dialog.")
|
||||||
|
|
||||||
# Channel list URL
|
# Channel list URL
|
||||||
set(Launcher_UPDATER_BASE "" CACHE STRING "Base URL for the updater.")
|
set(Launcher_UPDATER_BASE "" CACHE STRING "Base URL for the updater.")
|
||||||
|
|
||||||
# Notification URL
|
|
||||||
set(Launcher_NOTIFICATION_URL "" CACHE STRING "URL for checking for notifications.")
|
|
||||||
|
|
||||||
# The metadata server
|
# The metadata server
|
||||||
set(Launcher_META_URL "https://meta.polymc.org/v1/" CACHE STRING "URL to fetch PolyMC's meta files from.")
|
set(Launcher_META_URL "https://meta.polymc.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")
|
|
||||||
|
|
||||||
# Imgur API Client ID
|
# Imgur API Client ID
|
||||||
set(Launcher_IMGUR_CLIENT_ID "5b97b0713fba4a3" CACHE STRING "Client ID you can get from Imgur when you register an application")
|
set(Launcher_IMGUR_CLIENT_ID "5b97b0713fba4a3" CACHE STRING "Client ID you can get from Imgur when you register an application")
|
||||||
|
|
||||||
# MSA Client ID
|
# 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")
|
||||||
|
|
||||||
|
# CurseForge API Key
|
||||||
|
# CHANGE THIS IF YOU FORK THIS PROJECT!
|
||||||
|
set(Launcher_CURSEFORGE_API_KEY "$2a$10$iR1RdPDG95FWdILZbHuoMOlV4vL4eckBx7QPZR6SVZmliEb9ZQplu" CACHE STRING "CurseForge API Key")
|
||||||
|
|
||||||
# Bug tracker URL
|
# Bug tracker URL
|
||||||
set(Launcher_BUG_TRACKER_URL "https://github.com/PolyMC/PolyMC/issues" CACHE STRING "URL for the bug tracker.")
|
set(Launcher_BUG_TRACKER_URL "https://github.com/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:matrix.org" CACHE STRING "URL to the Matrix Space")
|
||||||
|
|
||||||
# Discord URL
|
# Discord URL
|
||||||
set(Launcher_DISCORD_URL "https://discord.gg/Z52pwxWCHP" CACHE STRING "URL for the Discord guild.")
|
set(Launcher_DISCORD_URL "https://discord.gg/Z52pwxWCHP" CACHE STRING "URL for the Discord guild.")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# Subreddit URL
|
# Subreddit URL
|
||||||
set(Launcher_SUBREDDIT_URL "" CACHE STRING "URL for the subreddit.")
|
set(Launcher_SUBREDDIT_URL "https://www.reddit.com/r/PolyMCLauncher/" CACHE STRING "URL for the subreddit.")
|
||||||
|
|
||||||
|
# Builds
|
||||||
|
set(Launcher_FORCE_BUNDLED_LIBS OFF CACHE BOOL "Prevent using system libraries, if they are available as submodules")
|
||||||
|
set(Launcher_QT_VERSION_MAJOR "5" CACHE STRING "Major Qt version to build against")
|
||||||
|
|
||||||
|
|
||||||
#### Check the current Git commit and branch
|
#### Check the current Git commit and branch
|
||||||
include(GetGitRevisionDescription)
|
include(GetGitRevisionDescription)
|
||||||
@ -94,6 +123,8 @@ message(STATUS "Git commit: ${Launcher_GIT_COMMIT}")
|
|||||||
message(STATUS "Git refspec: ${Launcher_GIT_REFSPEC}")
|
message(STATUS "Git refspec: ${Launcher_GIT_REFSPEC}")
|
||||||
|
|
||||||
set(Launcher_RELEASE_VERSION_NAME "${Launcher_VERSION_MAJOR}.${Launcher_VERSION_MINOR}.${Launcher_VERSION_HOTFIX}")
|
set(Launcher_RELEASE_VERSION_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.
|
#### Custom target to just print the version.
|
||||||
add_custom_target(version echo "Version: ${Launcher_RELEASE_VERSION_NAME}")
|
add_custom_target(version echo "Version: ${Launcher_RELEASE_VERSION_NAME}")
|
||||||
@ -102,12 +133,20 @@ add_custom_target(tcversion echo "\\#\\#teamcity[setParameter name=\\'env.LAUNCH
|
|||||||
################################ 3rd Party Libs ################################
|
################################ 3rd Party Libs ################################
|
||||||
|
|
||||||
# Find the required Qt parts
|
# Find the required Qt parts
|
||||||
find_package(Qt5Core REQUIRED)
|
if(Launcher_QT_VERSION_MAJOR EQUAL 5)
|
||||||
find_package(Qt5Widgets REQUIRED)
|
set(QT_VERSION_MAJOR 5)
|
||||||
find_package(Qt5Concurrent REQUIRED)
|
find_package(Qt5 REQUIRED COMPONENTS Core Widgets Concurrent Network Test Xml)
|
||||||
find_package(Qt5Network REQUIRED)
|
|
||||||
find_package(Qt5Test REQUIRED)
|
if(NOT Launcher_FORCE_BUNDLED_LIBS)
|
||||||
find_package(Qt5Xml REQUIRED)
|
find_package(QuaZip-Qt5 1.3)
|
||||||
|
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.
|
# The Qt5 cmake files don't provide its install paths, so ask qmake.
|
||||||
include(QMakeQuery)
|
include(QMakeQuery)
|
||||||
@ -129,45 +168,30 @@ add_subdirectory(program_info)
|
|||||||
|
|
||||||
####################################### Install layout #######################################
|
####################################### Install layout #######################################
|
||||||
|
|
||||||
# How to install the build results
|
if(NOT (UNIX AND APPLE))
|
||||||
set(Launcher_LAYOUT "auto" CACHE STRING "The layout for the launcher installation (auto, win-bundle, lin-nodeps, lin-system, mac-bundle)")
|
# Install "portable.txt" if selected component is "portable"
|
||||||
set_property(CACHE Launcher_LAYOUT PROPERTY STRINGS auto win-bundle lin-nodeps lin-system mac-bundle)
|
install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/${Launcher_Portable_File}" DESTINATION "." COMPONENT portable EXCLUDE_FROM_ALL)
|
||||||
|
|
||||||
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()
|
endif()
|
||||||
|
|
||||||
if(Launcher_LAYOUT_REAL STREQUAL "mac-bundle")
|
if(UNIX AND APPLE)
|
||||||
set(BINARY_DEST_DIR "${Launcher_Name}.app/Contents/MacOS")
|
set(BINARY_DEST_DIR "${Launcher_Name}.app/Contents/MacOS")
|
||||||
set(LIBRARY_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")
|
set(PLUGIN_DEST_DIR "${Launcher_Name}.app/Contents/MacOS")
|
||||||
set(RESOURCES_DEST_DIR "${Launcher_Name}.app/Contents/Resources")
|
set(RESOURCES_DEST_DIR "${Launcher_Name}.app/Contents/Resources")
|
||||||
set(JARS_DEST_DIR "${Launcher_Name}.app/Contents/MacOS/jars")
|
set(JARS_DEST_DIR "${Launcher_Name}.app/Contents/MacOS/jars")
|
||||||
|
|
||||||
set(BUNDLE_DEST_DIR ".")
|
|
||||||
|
|
||||||
# Apps to bundle
|
# Apps to bundle
|
||||||
set(APPS "\${CMAKE_INSTALL_PREFIX}/${Launcher_Name}.app")
|
set(APPS "\${CMAKE_INSTALL_PREFIX}/${Launcher_Name}.app")
|
||||||
|
|
||||||
# Mac bundle settings
|
# Mac bundle settings
|
||||||
set(MACOSX_BUNDLE_BUNDLE_NAME "${Launcher_Name}")
|
set(MACOSX_BUNDLE_BUNDLE_NAME "${Launcher_Name}")
|
||||||
set(MACOSX_BUNDLE_INFO_STRING "${Launcher_Name}: Minecraft launcher and management utility.")
|
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.multimc.${Launcher_Name}")
|
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_BUNDLE_VERSION "${Launcher_VERSION_MAJOR}.${Launcher_VERSION_MINOR}.${Launcher_VERSION_HOTFIX}")
|
||||||
set(MACOSX_BUNDLE_SHORT_VERSION_STRING "${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}")
|
||||||
set(MACOSX_BUNDLE_LONG_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}")
|
||||||
set(MACOSX_BUNDLE_ICON_FILE ${Launcher_Name}.icns)
|
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
|
# directories to look for dependencies
|
||||||
set(DIRS ${QT_LIBS_DIR} ${QT_LIBEXECS_DIR} ${CMAKE_LIBRARY_OUTPUT_DIRECTORY} ${CMAKE_RUNTIME_OUTPUT_DIRECTORY})
|
set(DIRS ${QT_LIBS_DIR} ${QT_LIBEXECS_DIR} ${CMAKE_LIBRARY_OUTPUT_DIRECTORY} ${CMAKE_RUNTIME_OUTPUT_DIRECTORY})
|
||||||
@ -178,13 +202,14 @@ if(Launcher_LAYOUT_REAL STREQUAL "mac-bundle")
|
|||||||
# Add the icon
|
# Add the icon
|
||||||
install(FILES ${Launcher_Branding_ICNS} DESTINATION ${RESOURCES_DEST_DIR} RENAME ${Launcher_Name}.icns)
|
install(FILES ${Launcher_Branding_ICNS} DESTINATION ${RESOURCES_DEST_DIR} RENAME ${Launcher_Name}.icns)
|
||||||
|
|
||||||
elseif(Launcher_LAYOUT_REAL STREQUAL "lin-nodeps")
|
elseif(UNIX)
|
||||||
set(BINARY_DEST_DIR "bin")
|
set(BINARY_DEST_DIR "bin")
|
||||||
set(LIBRARY_DEST_DIR "bin")
|
set(LIBRARY_DEST_DIR "lib${LIB_SUFFIX}")
|
||||||
set(PLUGIN_DEST_DIR "plugins")
|
set(JARS_DEST_DIR "share/jars")
|
||||||
set(BUNDLE_DEST_DIR ".")
|
set(LAUNCHER_DESKTOP_DEST_DIR "share/applications" CACHE STRING "Path to the desktop file directory")
|
||||||
set(RESOURCES_DEST_DIR ".")
|
set(LAUNCHER_METAINFO_DEST_DIR "share/metainfo" CACHE STRING "Path to the metainfo directory")
|
||||||
set(JARS_DEST_DIR "bin/jars")
|
set(LAUNCHER_ICON_DEST_DIR "share/icons/hicolor/scalable/apps" CACHE STRING "Path to the scalable icon directory")
|
||||||
|
set(LAUNCHER_MAN_DEST_DIR "share/man/man6" CACHE STRING "Path to the man page directory")
|
||||||
|
|
||||||
# install as bundle with no dependencies included
|
# install as bundle with no dependencies included
|
||||||
set(INSTALL_BUNDLE "nodeps")
|
set(INSTALL_BUNDLE "nodeps")
|
||||||
@ -192,37 +217,22 @@ elseif(Launcher_LAYOUT_REAL STREQUAL "lin-nodeps")
|
|||||||
# Set RPATH
|
# Set RPATH
|
||||||
SET(Launcher_BINARY_RPATH "$ORIGIN/")
|
SET(Launcher_BINARY_RPATH "$ORIGIN/")
|
||||||
|
|
||||||
# Install basic runner script
|
# jars path is determined on runtime, relative to "Application root path", generally /usr or the root of the portable bundle
|
||||||
|
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})
|
||||||
|
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/${Launcher_ManPage} DESTINATION ${LAUNCHER_MAN_DEST_DIR} RENAME "${Launcher_APP_BINARY_NAME}.6")
|
||||||
|
|
||||||
|
# Install basic runner script if component "portable" is selected
|
||||||
configure_file(launcher/Launcher.in "${CMAKE_CURRENT_BINARY_DIR}/LauncherScript" @ONLY)
|
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})
|
install(PROGRAMS "${CMAKE_CURRENT_BINARY_DIR}/LauncherScript" DESTINATION "." RENAME ${Launcher_Name} COMPONENT portable EXCLUDE_FROM_ALL)
|
||||||
|
|
||||||
elseif(Launcher_LAYOUT_REAL STREQUAL "lin-system")
|
elseif(WIN32)
|
||||||
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")
|
|
||||||
set(BINARY_DEST_DIR ".")
|
set(BINARY_DEST_DIR ".")
|
||||||
set(LIBRARY_DEST_DIR ".")
|
set(LIBRARY_DEST_DIR ".")
|
||||||
set(PLUGIN_DEST_DIR ".")
|
set(PLUGIN_DEST_DIR ".")
|
||||||
set(BUNDLE_DEST_DIR ".")
|
|
||||||
set(RESOURCES_DEST_DIR ".")
|
set(RESOURCES_DEST_DIR ".")
|
||||||
set(JARS_DEST_DIR "jars")
|
set(JARS_DEST_DIR "jars")
|
||||||
|
|
||||||
@ -235,7 +245,7 @@ elseif(Launcher_LAYOUT_REAL STREQUAL "win-bundle")
|
|||||||
# install as bundle
|
# install as bundle
|
||||||
set(INSTALL_BUNDLE "full")
|
set(INSTALL_BUNDLE "full")
|
||||||
else()
|
else()
|
||||||
message(FATAL_ERROR "No sensible install layout set.")
|
message(FATAL_ERROR "Platform not supported")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
################################ Included Libs ################################
|
################################ Included Libs ################################
|
||||||
@ -243,11 +253,9 @@ endif()
|
|||||||
include(ExternalProject)
|
include(ExternalProject)
|
||||||
set_directory_properties(PROPERTIES EP_BASE External)
|
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_USE_ZLIB "Build NBT library with zlib support" OFF)
|
||||||
option(NBT_BUILD_TESTS "Build NBT library tests" OFF) #FIXME: fix unit tests.
|
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/libnbtplusplus)
|
||||||
|
|
||||||
add_subdirectory(libraries/systeminfo) # system information library
|
add_subdirectory(libraries/systeminfo) # system information library
|
||||||
@ -255,7 +263,14 @@ add_subdirectory(libraries/hoedown) # markdown parser
|
|||||||
add_subdirectory(libraries/launcher) # java based launcher part for Minecraft
|
add_subdirectory(libraries/launcher) # java based launcher part for Minecraft
|
||||||
add_subdirectory(libraries/javacheck) # java compatibility checker
|
add_subdirectory(libraries/javacheck) # java compatibility checker
|
||||||
add_subdirectory(libraries/xz-embedded) # xz compression
|
add_subdirectory(libraries/xz-embedded) # xz compression
|
||||||
add_subdirectory(libraries/quazip) # zip manipulation library
|
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
|
||||||
|
else()
|
||||||
|
message(STATUS "Using system QuaZip")
|
||||||
|
endif()
|
||||||
add_subdirectory(libraries/rainbow) # Qt extension for colors
|
add_subdirectory(libraries/rainbow) # Qt extension for colors
|
||||||
add_subdirectory(libraries/iconfix) # fork of Qt's QIcon loader
|
add_subdirectory(libraries/iconfix) # fork of Qt's QIcon loader
|
||||||
add_subdirectory(libraries/LocalPeer) # fork of a library from Qt solutions
|
add_subdirectory(libraries/LocalPeer) # fork of a library from Qt solutions
|
||||||
|
136
CODE_OF_CONDUCT.md
Normal file
136
CODE_OF_CONDUCT.md
Normal 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
|
||||||
|
|
19
COPYING.md
19
COPYING.md
@ -1,12 +1,11 @@
|
|||||||
# PolyMC
|
# PolyMC
|
||||||
|
|
||||||
Copyright (C) 2012-2021 MultiMC Contributors
|
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
|
This program is free software: you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
the Free Software Foundation, version 3.
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
This program is distributed in the hope that it will be useful,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
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
|
You should have received a copy of the GNU General Public License
|
||||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
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)
|
# MinGW runtime (Windows)
|
||||||
|
|
||||||
Copyright (c) 2012 MinGW.org project
|
Copyright (c) 2012 MinGW.org project
|
||||||
|
108
README.md
108
README.md
@ -1,66 +1,88 @@
|
|||||||
<p align="center">
|
<p align="center">
|
||||||
<img src="/program_info/polymc-light.png#gh-light-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-dark.png#gh-dark-mode-only" alt="PolyMC logo"/>
|
<img src="./program_info/polymc-header.svg#gh-dark-mode-only" alt="PolyMC logo"/>
|
||||||
</p>
|
</p>
|
||||||
<br>
|
<br>
|
||||||
|
|
||||||
PolyMC is a custom launcher for Minecraft that focuses on predictability, long term stability and simplicity.
|
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.
|
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.
|
||||||
|
|
||||||
## 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>
|
|
||||||
<br>
|
<br>
|
||||||
[](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
|
# Installation
|
||||||
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!
|
|
||||||
|
|
||||||
### Building
|
- All downloads and instructions for PolyMC can be found [here](https://polymc.org/download/)
|
||||||
If you want to build PolyMC yourself, check [BUILD.md](BUILD.md) for build instructions.
|
- 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
|
## Development Builds
|
||||||
Just follow the existing formatting.
|
|
||||||
|
|
||||||
In general, in order of importance:
|
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.
|
||||||
* Make sure your IDE is not messing up line endings or whitespace and avoid using linters.
|
Portable builds are provided for AppImage on Linux, Windows, and macOS.
|
||||||
* 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
|
For Debian and Arch, you can use these packages for the latest development versions:
|
||||||
TODO
|
[](https://aur.archlinux.org/packages/polymc-git/)
|
||||||
|
[](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
|
# Help & Support
|
||||||
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
|
|
||||||
Feel free to create an issue if you need help. However, you might find it easier to ask in the Discord server.
|
Feel free to create an issue if you need help. However, you might find it easier to ask in the Discord server.
|
||||||
|
|
||||||
[](https://discord.gg/xq7fxrgtMP)
|
[](https://discord.gg/xq7fxrgtMP)
|
||||||
|
|
||||||
For people who don't want to use Discord, we have a Matrix Space which is bridged to the Discord server:
|
For people who don't want to use Discord, we have a Matrix Space which is bridged to the Discord server:
|
||||||
|
|
||||||
[](https://matrix.to/#/#polymc:polymc.org)
|
[](https://matrix.to/#/#polymc:matrix.org)
|
||||||
|
|
||||||
If there are any issues with the space or you are using a client that does not support the feature here are the individual rooms:
|
If there are any issues with the space or you are using a client that does not support the feature here are the individual rooms:
|
||||||
|
|
||||||
[](https://matrix.to/#/#support:polymc.org)
|
[](https://matrix.to/#/#polymc-development:matrix.org)
|
||||||
[](https://matrix.to/#/#discussion:polymc.org)
|
[](https://matrix.to/#/#polymc-discussion:matrix.org)
|
||||||
[](https://matrix.to/#/#development:polymc.org)
|
[](https://matrix.to/#/#polymc-github:matrix.org)
|
||||||
[](https://matrix.to/#/#news:polymc.org)
|
[](https://matrix.to/#/#polymc-maintainers:matrix.org)
|
||||||
|
[](https://matrix.to/#/#polymc-news:matrix.org)
|
||||||
|
[](https://matrix.to/#/#polymc-offtopic:matrix.org)
|
||||||
|
[](https://matrix.to/#/#polymc-support:matrix.org)
|
||||||
|
[](https://matrix.to/#/#polymc-voice:matrix.org)
|
||||||
|
|
||||||
|
we also have a subreddit you can post your issues and suggestions on:
|
||||||
|
|
||||||
|
[r/PolyMCLauncher](https://www.reddit.com/r/PolyMCLauncher/)
|
||||||
|
|
||||||
|
# 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 Instructions](https://polymc.org/wiki/development/build-instructions/) 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 information
|
||||||
|
To modify download information or change packaging information send a pull request or issue to the website [Here](https://github.com/PolyMC/polymc.github.io/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.
|
||||||
|
|
||||||
|
All launcher code is available under the GPL-3 license.
|
||||||
|
|
||||||
|
[Source for the website](https://github.com/PolyMC/polymc.github.io) is hosted under the AGPL-3 License.
|
||||||
|
|
||||||
|
The logo and related assets are under the CC BY-SA 4.0 license.
|
||||||
|
@ -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 "BuildConfig.h"
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
|
|
||||||
@ -12,6 +47,7 @@ Config::Config()
|
|||||||
LAUNCHER_DOMAIN = "@Launcher_Domain@";
|
LAUNCHER_DOMAIN = "@Launcher_Domain@";
|
||||||
LAUNCHER_CONFIGFILE = "@Launcher_ConfigFile@";
|
LAUNCHER_CONFIGFILE = "@Launcher_ConfigFile@";
|
||||||
LAUNCHER_GIT = "@Launcher_Git@";
|
LAUNCHER_GIT = "@Launcher_Git@";
|
||||||
|
LAUNCHER_DESKTOPFILENAME = "@Launcher_DesktopFileName@";
|
||||||
|
|
||||||
USER_AGENT = "@Launcher_UserAgent@";
|
USER_AGENT = "@Launcher_UserAgent@";
|
||||||
USER_AGENT_UNCACHED = USER_AGENT + " (Uncached)";
|
USER_AGENT_UNCACHED = USER_AGENT + " (Uncached)";
|
||||||
@ -24,30 +60,42 @@ Config::Config()
|
|||||||
|
|
||||||
BUILD_PLATFORM = "@Launcher_BUILD_PLATFORM@";
|
BUILD_PLATFORM = "@Launcher_BUILD_PLATFORM@";
|
||||||
UPDATER_BASE = "@Launcher_UPDATER_BASE@";
|
UPDATER_BASE = "@Launcher_UPDATER_BASE@";
|
||||||
NOTIFICATION_URL = "@Launcher_NOTIFICATION_URL@";
|
|
||||||
FULL_VERSION_STR = "@Launcher_VERSION_MAJOR@.@Launcher_VERSION_MINOR@.@Launcher_VERSION_BUILD@";
|
|
||||||
|
|
||||||
GIT_COMMIT = "@Launcher_GIT_COMMIT@";
|
GIT_COMMIT = "@Launcher_GIT_COMMIT@";
|
||||||
GIT_REFSPEC = "@Launcher_GIT_REFSPEC@";
|
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 = GIT_REFSPEC;
|
||||||
VERSION_CHANNEL.remove("refs/heads/");
|
VERSION_CHANNEL.remove("refs/heads/");
|
||||||
UPDATER_ENABLED = true;
|
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
|
else
|
||||||
{
|
{
|
||||||
VERSION_CHANNEL = QObject::tr("custom");
|
VERSION_CHANNEL = QObject::tr("unknown");
|
||||||
}
|
}
|
||||||
|
|
||||||
VERSION_STR = "@Launcher_VERSION_STRING@";
|
VERSION_STR = "@Launcher_VERSION_STRING@";
|
||||||
NEWS_RSS_URL = "@Launcher_NEWS_RSS_URL@";
|
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@";
|
IMGUR_CLIENT_ID = "@Launcher_IMGUR_CLIENT_ID@";
|
||||||
MSA_CLIENT_ID = "@Launcher_MSA_CLIENT_ID@";
|
MSA_CLIENT_ID = "@Launcher_MSA_CLIENT_ID@";
|
||||||
|
CURSEFORGE_API_KEY = "@Launcher_CURSEFORGE_API_KEY@";
|
||||||
META_URL = "@Launcher_META_URL@";
|
META_URL = "@Launcher_META_URL@";
|
||||||
|
|
||||||
BUG_TRACKER_URL = "@Launcher_BUG_TRACKER_URL@";
|
BUG_TRACKER_URL = "@Launcher_BUG_TRACKER_URL@";
|
||||||
|
TRANSLATIONS_URL = "@Launcher_TRANSLATIONS_URL@";
|
||||||
|
MATRIX_URL = "@Launcher_MATRIX_URL@";
|
||||||
DISCORD_URL = "@Launcher_DISCORD_URL@";
|
DISCORD_URL = "@Launcher_DISCORD_URL@";
|
||||||
SUBREDDIT_URL = "@Launcher_SUBREDDIT_URL@";
|
SUBREDDIT_URL = "@Launcher_SUBREDDIT_URL@";
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,46 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-3.0-only
|
||||||
|
/*
|
||||||
|
* PolyMC - Minecraft Launcher
|
||||||
|
* Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, version 3.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* This file incorporates work covered by the following copyright and
|
||||||
|
* permission notice:
|
||||||
|
*
|
||||||
|
* Copyright 2013-2021 MultiMC Contributors
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <QString>
|
#include <QString>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief The Config class holds all the build-time information passed from the build system.
|
* \brief The Config class holds all the build-time information passed from the build system.
|
||||||
*/
|
*/
|
||||||
class Config
|
class Config {
|
||||||
{
|
public:
|
||||||
public:
|
|
||||||
Config();
|
Config();
|
||||||
QString LAUNCHER_NAME;
|
QString LAUNCHER_NAME;
|
||||||
QString LAUNCHER_DISPLAYNAME;
|
QString LAUNCHER_DISPLAYNAME;
|
||||||
@ -14,6 +48,7 @@ public:
|
|||||||
QString LAUNCHER_DOMAIN;
|
QString LAUNCHER_DOMAIN;
|
||||||
QString LAUNCHER_CONFIGFILE;
|
QString LAUNCHER_CONFIGFILE;
|
||||||
QString LAUNCHER_GIT;
|
QString LAUNCHER_GIT;
|
||||||
|
QString LAUNCHER_DESKTOPFILENAME;
|
||||||
|
|
||||||
/// The major version number.
|
/// The major version number.
|
||||||
int VERSION_MAJOR;
|
int VERSION_MAJOR;
|
||||||
@ -38,20 +73,12 @@ public:
|
|||||||
/// URL for the updater's channel
|
/// URL for the updater's channel
|
||||||
QString UPDATER_BASE;
|
QString UPDATER_BASE;
|
||||||
|
|
||||||
|
|
||||||
/// User-Agent to use.
|
/// User-Agent to use.
|
||||||
QString USER_AGENT;
|
QString USER_AGENT;
|
||||||
|
|
||||||
/// User-Agent to use for uncached requests.
|
/// User-Agent to use for uncached requests.
|
||||||
QString USER_AGENT_UNCACHED;
|
QString USER_AGENT_UNCACHED;
|
||||||
|
|
||||||
|
|
||||||
/// URL for notifications
|
|
||||||
QString NOTIFICATION_URL;
|
|
||||||
|
|
||||||
/// Used for matching notifications
|
|
||||||
QString FULL_VERSION_STR;
|
|
||||||
|
|
||||||
/// The git commit hash of this build
|
/// The git commit hash of this build
|
||||||
QString GIT_COMMIT;
|
QString GIT_COMMIT;
|
||||||
|
|
||||||
@ -68,9 +95,14 @@ public:
|
|||||||
QString NEWS_RSS_URL;
|
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
|
* Client ID you can get from Imgur when you register an application
|
||||||
@ -82,12 +114,19 @@ public:
|
|||||||
*/
|
*/
|
||||||
QString MSA_CLIENT_ID;
|
QString MSA_CLIENT_ID;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Client API key for CurseForge
|
||||||
|
*/
|
||||||
|
QString CURSEFORGE_API_KEY;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Metadata repository URL prefix
|
* Metadata repository URL prefix
|
||||||
*/
|
*/
|
||||||
QString META_URL;
|
QString META_URL;
|
||||||
|
|
||||||
QString BUG_TRACKER_URL;
|
QString BUG_TRACKER_URL;
|
||||||
|
QString TRANSLATIONS_URL;
|
||||||
|
QString MATRIX_URL;
|
||||||
QString DISCORD_URL;
|
QString DISCORD_URL;
|
||||||
QString SUBREDDIT_URL;
|
QString SUBREDDIT_URL;
|
||||||
|
|
||||||
@ -95,8 +134,8 @@ public:
|
|||||||
QString LIBRARY_BASE = "https://libraries.minecraft.net/";
|
QString LIBRARY_BASE = "https://libraries.minecraft.net/";
|
||||||
QString AUTH_BASE = "https://authserver.mojang.com/";
|
QString AUTH_BASE = "https://authserver.mojang.com/";
|
||||||
QString IMGUR_BASE_URL = "https://api.imgur.com/3/";
|
QString IMGUR_BASE_URL = "https://api.imgur.com/3/";
|
||||||
QString FMLLIBS_BASE_URL = "https://files.multimc.org/fmllibs/";
|
QString FMLLIBS_BASE_URL = "https://files.polymc.org/fmllibs/";
|
||||||
QString TRANSLATIONS_BASE_URL = "https://files.multimc.org/translations/";
|
QString TRANSLATIONS_BASE_URL = "https://i18n.polymc.org/";
|
||||||
|
|
||||||
QString MODPACKSCH_API_BASE_URL = "https://api.modpacks.ch/";
|
QString MODPACKSCH_API_BASE_URL = "https://api.modpacks.ch/";
|
||||||
|
|
||||||
@ -104,6 +143,12 @@ public:
|
|||||||
|
|
||||||
QString ATL_DOWNLOAD_SERVER_URL = "https://download.nodecdn.net/containers/atl/";
|
QString ATL_DOWNLOAD_SERVER_URL = "https://download.nodecdn.net/containers/atl/";
|
||||||
|
|
||||||
|
QString TECHNIC_API_BASE_URL = "https://api.technicpack.net/";
|
||||||
|
/**
|
||||||
|
* The build that is reported to the Technic API.
|
||||||
|
*/
|
||||||
|
QString TECHNIC_API_BUILD = "multimc";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Converts the Version to a string.
|
* \brief Converts the Version to a string.
|
||||||
* \return The version number in string format (major.minor.revision.build).
|
* \return The version number in string format (major.minor.revision.build).
|
||||||
@ -112,4 +157,3 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
extern const Config BuildConfig;
|
extern const Config BuildConfig;
|
||||||
|
|
||||||
|
1532
changelog.md
1532
changelog.md
File diff suppressed because it is too large
Load Diff
@ -2,6 +2,10 @@
|
|||||||
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
<plist version="1.0">
|
<plist version="1.0">
|
||||||
<dict>
|
<dict>
|
||||||
|
<key>NSCameraUsageDescription</key>
|
||||||
|
<string>A Minecraft mod wants to access your camera.</string>
|
||||||
|
<key>NSMicrophoneUsageDescription</key>
|
||||||
|
<string>A Minecraft mod wants to access your microphone.</string>
|
||||||
<key>NSPrincipalClass</key>
|
<key>NSPrincipalClass</key>
|
||||||
<string>NSApplication</string>
|
<string>NSApplication</string>
|
||||||
<key>NSHighResolutionCapable</key>
|
<key>NSHighResolutionCapable</key>
|
||||||
|
@ -5,44 +5,46 @@ set(TEST_RESOURCE_PATH ${CMAKE_CURRENT_LIST_DIR})
|
|||||||
message(${TEST_RESOURCE_PATH})
|
message(${TEST_RESOURCE_PATH})
|
||||||
|
|
||||||
function(add_unit_test name)
|
function(add_unit_test name)
|
||||||
set(options "")
|
if(BUILD_TESTING)
|
||||||
set(oneValueArgs DATA)
|
set(options "")
|
||||||
set(multiValueArgs SOURCES LIBS)
|
set(oneValueArgs DATA)
|
||||||
|
set(multiValueArgs SOURCES LIBS)
|
||||||
|
|
||||||
cmake_parse_arguments(OPT "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN} )
|
cmake_parse_arguments(OPT "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN} )
|
||||||
|
|
||||||
if(WIN32)
|
if(WIN32)
|
||||||
add_executable(${name}_test ${OPT_SOURCES} ${TEST_RESOURCE_PATH}/UnitTest/test.rc)
|
add_executable(${name}_test ${OPT_SOURCES} ${TEST_RESOURCE_PATH}/UnitTest/test.rc)
|
||||||
else()
|
|
||||||
add_executable(${name}_test ${OPT_SOURCES})
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(NOT "${OPT_DATA}" STREQUAL "")
|
|
||||||
set(TEST_DATA_PATH "${CMAKE_CURRENT_BINARY_DIR}/data")
|
|
||||||
set(TEST_DATA_PATH_SRC "${CMAKE_CURRENT_SOURCE_DIR}/${OPT_DATA}")
|
|
||||||
message("From ${TEST_DATA_PATH_SRC} to ${TEST_DATA_PATH}")
|
|
||||||
string(REGEX REPLACE "[/\\:]" "_" DATA_TARGET_NAME "${TEST_DATA_PATH_SRC}")
|
|
||||||
if(UNIX)
|
|
||||||
# on unix we get the third / from the filename
|
|
||||||
set(TEST_DATA_URL "file://${TEST_DATA_PATH}")
|
|
||||||
else()
|
else()
|
||||||
# we don't on windows, so we have to add it ourselves
|
add_executable(${name}_test ${OPT_SOURCES})
|
||||||
set(TEST_DATA_URL "file:///${TEST_DATA_PATH}")
|
|
||||||
endif()
|
endif()
|
||||||
if(NOT TARGET "${DATA_TARGET_NAME}")
|
|
||||||
add_custom_target(${DATA_TARGET_NAME})
|
if(NOT "${OPT_DATA}" STREQUAL "")
|
||||||
add_dependencies(${name}_test ${DATA_TARGET_NAME})
|
set(TEST_DATA_PATH "${CMAKE_CURRENT_BINARY_DIR}/data")
|
||||||
add_custom_command(
|
set(TEST_DATA_PATH_SRC "${CMAKE_CURRENT_SOURCE_DIR}/${OPT_DATA}")
|
||||||
TARGET ${DATA_TARGET_NAME}
|
message("From ${TEST_DATA_PATH_SRC} to ${TEST_DATA_PATH}")
|
||||||
COMMAND ${CMAKE_COMMAND} "-DTEST_DATA_URL=${TEST_DATA_URL}" -DSOURCE=${TEST_DATA_PATH_SRC} -DDESTINATION=${TEST_DATA_PATH} -P ${TEST_RESOURCE_PATH}/UnitTest/generate_test_data.cmake
|
string(REGEX REPLACE "[/\\:]" "_" DATA_TARGET_NAME "${TEST_DATA_PATH_SRC}")
|
||||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
if(UNIX)
|
||||||
)
|
# on unix we get the third / from the filename
|
||||||
|
set(TEST_DATA_URL "file://${TEST_DATA_PATH}")
|
||||||
|
else()
|
||||||
|
# we don't on windows, so we have to add it ourselves
|
||||||
|
set(TEST_DATA_URL "file:///${TEST_DATA_PATH}")
|
||||||
|
endif()
|
||||||
|
if(NOT TARGET "${DATA_TARGET_NAME}")
|
||||||
|
add_custom_target(${DATA_TARGET_NAME})
|
||||||
|
add_dependencies(${name}_test ${DATA_TARGET_NAME})
|
||||||
|
add_custom_command(
|
||||||
|
TARGET ${DATA_TARGET_NAME}
|
||||||
|
COMMAND ${CMAKE_COMMAND} "-DTEST_DATA_URL=${TEST_DATA_URL}" -DSOURCE=${TEST_DATA_PATH_SRC} -DDESTINATION=${TEST_DATA_PATH} -P ${TEST_RESOURCE_PATH}/UnitTest/generate_test_data.cmake
|
||||||
|
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
||||||
|
)
|
||||||
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
target_link_libraries(${name}_test Qt5::Test ${OPT_LIBS})
|
||||||
|
|
||||||
|
target_include_directories(${name}_test PRIVATE "${TEST_RESOURCE_PATH}/UnitTest/")
|
||||||
|
|
||||||
|
add_test(NAME ${name} COMMAND ${name}_test WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
target_link_libraries(${name}_test Qt5::Test ${OPT_LIBS})
|
|
||||||
|
|
||||||
target_include_directories(${name}_test PRIVATE "${TEST_RESOURCE_PATH}/UnitTest/")
|
|
||||||
|
|
||||||
add_test(NAME ${name} COMMAND ${name}_test WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
|
|
||||||
endfunction()
|
endfunction()
|
||||||
|
@ -14,7 +14,7 @@ BEGIN
|
|||||||
BEGIN
|
BEGIN
|
||||||
BLOCK "000004b0"
|
BLOCK "000004b0"
|
||||||
BEGIN
|
BEGIN
|
||||||
VALUE "CompanyName", "MultiMC Contributors"
|
VALUE "CompanyName", "MultiMC & PolyMC Contributors"
|
||||||
VALUE "FileDescription", "Testcase"
|
VALUE "FileDescription", "Testcase"
|
||||||
VALUE "FileVersion", "1.0.0.0"
|
VALUE "FileVersion", "1.0.0.0"
|
||||||
VALUE "ProductName", "Launcher Testcase"
|
VALUE "ProductName", "Launcher Testcase"
|
||||||
|
40
flake.lock
generated
40
flake.lock
generated
@ -3,11 +3,11 @@
|
|||||||
"flake-compat": {
|
"flake-compat": {
|
||||||
"flake": false,
|
"flake": false,
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1641205782,
|
"lastModified": 1648199409,
|
||||||
"narHash": "sha256-4jY7RCWUoZ9cKD8co0/4tFARpWB+57+r1bLLvXNJliY=",
|
"narHash": "sha256-JwPKdC2PoVBkG6E+eWw3j6BMR6sL3COpYWfif7RVb8Y=",
|
||||||
"owner": "edolstra",
|
"owner": "edolstra",
|
||||||
"repo": "flake-compat",
|
"repo": "flake-compat",
|
||||||
"rev": "b7547d3eed6f32d06102ead8991ec52ab0a4f1a7",
|
"rev": "64a525ee38886ab9028e6f61790de0832aa3ef03",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@ -16,21 +16,6 @@
|
|||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"flake-utils": {
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1638122382,
|
|
||||||
"narHash": "sha256-sQzZzAbvKEqN9s0bzWuYmRaA03v40gaJ4+iL1LXjaeI=",
|
|
||||||
"owner": "numtide",
|
|
||||||
"repo": "flake-utils",
|
|
||||||
"rev": "74f7e4319258e287b0f9cb95426c9853b282730b",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "numtide",
|
|
||||||
"repo": "flake-utils",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"libnbtplusplus": {
|
"libnbtplusplus": {
|
||||||
"flake": false,
|
"flake": false,
|
||||||
"locked": {
|
"locked": {
|
||||||
@ -49,16 +34,16 @@
|
|||||||
},
|
},
|
||||||
"nixpkgs": {
|
"nixpkgs": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1641528457,
|
"lastModified": 1648219316,
|
||||||
"narHash": "sha256-FyU9E63n1W7Ql4pMnhW2/rO9OftWZ37pLppn/c1aisY=",
|
"narHash": "sha256-Ctij+dOi0ZZIfX5eMhgwugfvB+WZSrvVNAyAuANOsnQ=",
|
||||||
"owner": "nixos",
|
"owner": "nixos",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "ff377a78794d412a35245e05428c8f95fef3951f",
|
"rev": "30d3d79b7d3607d56546dd2a6b49e156ba0ec634",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
"owner": "nixos",
|
"owner": "nixos",
|
||||||
"ref": "nixos-unstable",
|
"ref": "nixpkgs-unstable",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
@ -66,15 +51,15 @@
|
|||||||
"quazip": {
|
"quazip": {
|
||||||
"flake": false,
|
"flake": false,
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1633895098,
|
"lastModified": 1643049383,
|
||||||
"narHash": "sha256-+Of0M2IAoTf1CyC0teCpsyurv6xfqiBo84V49dSeNTA=",
|
"narHash": "sha256-LcJY6yd6GyeL7X5MP4L94diceM1TYespWByliBsjK98=",
|
||||||
"owner": "multimc",
|
"owner": "stachenov",
|
||||||
"repo": "quazip",
|
"repo": "quazip",
|
||||||
"rev": "b1a72ac0bb5a732bf887a535ab75c6f9bedb6b6b",
|
"rev": "09ec1d10c6d627f895109b21728dda000cbfa7d1",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
"owner": "multimc",
|
"owner": "stachenov",
|
||||||
"repo": "quazip",
|
"repo": "quazip",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
@ -82,7 +67,6 @@
|
|||||||
"root": {
|
"root": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"flake-compat": "flake-compat",
|
"flake-compat": "flake-compat",
|
||||||
"flake-utils": "flake-utils",
|
|
||||||
"libnbtplusplus": "libnbtplusplus",
|
"libnbtplusplus": "libnbtplusplus",
|
||||||
"nixpkgs": "nixpkgs",
|
"nixpkgs": "nixpkgs",
|
||||||
"quazip": "quazip"
|
"quazip": "quazip"
|
||||||
|
77
flake.nix
77
flake.nix
@ -1,55 +1,34 @@
|
|||||||
{
|
{
|
||||||
description = "PolyMC flake";
|
description = "A custom launcher for Minecraft that allows you to easily manage multiple installations of Minecraft at once (Fork of MultiMC)";
|
||||||
inputs.nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
|
|
||||||
inputs.flake-utils.url = "github:numtide/flake-utils";
|
inputs = {
|
||||||
inputs.flake-compat = {
|
nixpkgs.url = "github:nixos/nixpkgs/nixpkgs-unstable";
|
||||||
url = "github:edolstra/flake-compat";
|
flake-compat = { url = "github:edolstra/flake-compat"; flake = false; };
|
||||||
flake = false;
|
libnbtplusplus = { url = "github:multimc/libnbtplusplus"; flake = false; };
|
||||||
};
|
quazip = { url = "github:stachenov/quazip"; flake = false; };
|
||||||
inputs.libnbtplusplus = {
|
|
||||||
url = "github:multimc/libnbtplusplus";
|
|
||||||
flake = false;
|
|
||||||
};
|
|
||||||
inputs.quazip = {
|
|
||||||
url = "github:multimc/quazip";
|
|
||||||
flake = false;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
outputs = inputs@{ self, nixpkgs, flake-utils, libnbtplusplus, quazip, ... }:
|
outputs = { self, nixpkgs, libnbtplusplus, quazip, ... }:
|
||||||
flake-utils.lib.eachSystem [ "x86_64-linux" "aarch64-linux" ] (system:
|
let
|
||||||
let
|
# Generate a user-friendly version number.
|
||||||
pkgs = import nixpkgs {
|
version = builtins.substring 0 8 self.lastModifiedDate;
|
||||||
inherit system;
|
|
||||||
};
|
|
||||||
|
|
||||||
packages = {
|
# System types to support (qtbase is currently broken for "aarch64-darwin")
|
||||||
polymc = pkgs.libsForQt5.callPackage ./packages/nix/polymc {
|
supportedSystems = [ "x86_64-linux" "x86_64-darwin" "aarch64-linux" ];
|
||||||
inherit self;
|
|
||||||
submoduleQuazip = quazip;
|
|
||||||
submoduleNbt = libnbtplusplus;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
# 'nix flake check' fails
|
|
||||||
overlay = (final: prev: rec {
|
|
||||||
polymc = prev.libsForQt5.callPackage ./packages/nix/polymc {
|
|
||||||
inherit self;
|
|
||||||
submoduleQuazip = quazip;
|
|
||||||
submoduleNbt = libnbtplusplus;
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
apps = {
|
# Helper function to generate an attrset '{ x86_64-linux = f "x86_64-linux"; ... }'.
|
||||||
polymc = flake-utils.lib.mkApp {
|
forAllSystems = nixpkgs.lib.genAttrs supportedSystems;
|
||||||
name = "polymc";
|
|
||||||
drv = packages.polymc;
|
# Nixpkgs instantiated for supported system types.
|
||||||
};
|
pkgs = forAllSystems (system: nixpkgs.legacyPackages.${system});
|
||||||
};
|
in
|
||||||
in
|
{
|
||||||
{
|
packages = forAllSystems (system: { polymc = pkgs.${system}.libsForQt5.callPackage ./packages/nix/polymc { inherit version self quazip libnbtplusplus; }; });
|
||||||
inherit packages overlay apps;
|
defaultPackage = forAllSystems (system: self.packages.${system}.polymc);
|
||||||
defaultPackage = packages.polymc;
|
|
||||||
defaultApp = apps.polymc;
|
apps = forAllSystems (system: { polymc = { type = "app"; program = "${self.defaultPackage.${system}}/bin/polymc"; }; });
|
||||||
}
|
defaultApp = forAllSystems (system: self.apps.${system}.polymc);
|
||||||
);
|
|
||||||
|
overlay = final: prev: { polymc = self.defaultPackage.${final.system}; };
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
@ -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 "Application.h"
|
||||||
#include "BuildConfig.h"
|
#include "BuildConfig.h"
|
||||||
|
|
||||||
@ -14,7 +49,7 @@
|
|||||||
#include "ui/pages/global/ProxyPage.h"
|
#include "ui/pages/global/ProxyPage.h"
|
||||||
#include "ui/pages/global/ExternalToolsPage.h"
|
#include "ui/pages/global/ExternalToolsPage.h"
|
||||||
#include "ui/pages/global/AccountListPage.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/pages/global/CustomCommandsPage.h"
|
||||||
|
|
||||||
#include "ui/themes/ITheme.h"
|
#include "ui/themes/ITheme.h"
|
||||||
@ -45,6 +80,7 @@
|
|||||||
#include <QStringList>
|
#include <QStringList>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <QStyleFactory>
|
#include <QStyleFactory>
|
||||||
|
#include <QWindow>
|
||||||
|
|
||||||
#include "InstanceList.h"
|
#include "InstanceList.h"
|
||||||
|
|
||||||
@ -187,30 +223,11 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv)
|
|||||||
setApplicationName(BuildConfig.LAUNCHER_NAME);
|
setApplicationName(BuildConfig.LAUNCHER_NAME);
|
||||||
setApplicationDisplayName(BuildConfig.LAUNCHER_DISPLAYNAME);
|
setApplicationDisplayName(BuildConfig.LAUNCHER_DISPLAYNAME);
|
||||||
setApplicationVersion(BuildConfig.printableVersionString());
|
setApplicationVersion(BuildConfig.printableVersionString());
|
||||||
|
#if (QT_VERSION >= QT_VERSION_CHECK(5,7,0))
|
||||||
|
setDesktopFileName(BuildConfig.LAUNCHER_DESKTOPFILENAME);
|
||||||
|
#endif
|
||||||
startTime = QDateTime::currentDateTime();
|
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Don't quit on hiding the last window
|
// Don't quit on hiding the last window
|
||||||
this->setQuitOnLastWindowClosed(false);
|
this->setQuitOnLastWindowClosed(false);
|
||||||
|
|
||||||
@ -283,14 +300,43 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
m_instanceIdToLaunch = args["launch"].toString();
|
m_instanceIdToLaunch = args["launch"].toString();
|
||||||
m_serverToJoin = args["server"].toString();
|
m_serverToJoin = args["server"].toString();
|
||||||
m_profileToUse = args["profile"].toString();
|
m_profileToUse = args["profile"].toString();
|
||||||
m_liveCheck = args["alive"].toBool();
|
m_liveCheck = args["alive"].toBool();
|
||||||
m_zipToImport = args["import"].toUrl();
|
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 origcwdPath = QDir::currentPath();
|
||||||
QString binPath = applicationDirPath();
|
QString binPath = applicationDirPath();
|
||||||
|
|
||||||
|
{
|
||||||
|
// Root path is used for updates and portable data
|
||||||
|
#if defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD)
|
||||||
|
QDir foo(FS::PathCombine(binPath, "..")); // typically portable-root or /usr
|
||||||
|
m_rootPath = foo.absolutePath();
|
||||||
|
#elif defined(Q_OS_WIN32)
|
||||||
|
m_rootPath = binPath;
|
||||||
|
#elif defined(Q_OS_MAC)
|
||||||
|
QDir foo(FS::PathCombine(binPath, "../.."));
|
||||||
|
m_rootPath = foo.absolutePath();
|
||||||
|
// on macOS, touch the root to force Finder to reload the .app metadata (and fix any icon change issues)
|
||||||
|
FS::updateTimestamp(m_rootPath);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef LAUNCHER_JARS_LOCATION
|
||||||
|
m_jarsPath = TOSTRING(LAUNCHER_JARS_LOCATION);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
QString adjustedBy;
|
QString adjustedBy;
|
||||||
QString dataPath;
|
QString dataPath;
|
||||||
// change folder
|
// change folder
|
||||||
@ -299,24 +345,30 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv)
|
|||||||
{
|
{
|
||||||
// the dir param. it makes multimc data path point to whatever the user specified
|
// the dir param. it makes multimc data path point to whatever the user specified
|
||||||
// on command line
|
// on command line
|
||||||
adjustedBy += "Command line " + dirParam;
|
adjustedBy = "Command line";
|
||||||
dataPath = dirParam;
|
dataPath = dirParam;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
#ifdef LAUNCHER_LINUX_DATADIR
|
QDir foo(FS::PathCombine(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation), ".."));
|
||||||
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"));
|
|
||||||
dataPath = foo.absolutePath();
|
dataPath = foo.absolutePath();
|
||||||
adjustedBy += "Fallback to special Mac location " + dataPath;
|
adjustedBy = "Persistent data path";
|
||||||
#else
|
|
||||||
dataPath = applicationDirPath();
|
#ifdef Q_OS_LINUX
|
||||||
adjustedBy += "Fallback to binary path " + dataPath;
|
// TODO: this should be removed in a future version
|
||||||
|
// TODO: provide a migration path similar to macOS migration
|
||||||
|
QDir bar(FS::PathCombine(QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation), "polymc"));
|
||||||
|
if (bar.exists()) {
|
||||||
|
dataPath = bar.absolutePath();
|
||||||
|
adjustedBy = "Legacy data path";
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef Q_OS_MACOS
|
||||||
|
if (QFile::exists(FS::PathCombine(m_rootPath, "portable.txt"))) {
|
||||||
|
dataPath = m_rootPath;
|
||||||
|
adjustedBy = "Portable data path";
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -357,20 +409,6 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv)
|
|||||||
return;
|
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)
|
#if defined(Q_OS_MAC)
|
||||||
// move user data to new location if on macOS and it still exists in Contents/MacOS
|
// move user data to new location if on macOS and it still exists in Contents/MacOS
|
||||||
QDir fi(applicationDirPath());
|
QDir fi(applicationDirPath());
|
||||||
@ -435,7 +473,7 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv)
|
|||||||
#endif
|
#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.
|
* If there is one, tell it what the user actually wanted to do and exit.
|
||||||
* We want to initialize this before logging to avoid messing with the log of a potential already running copy.
|
* We want to initialize this before logging to avoid messing with the log of a potential already running copy.
|
||||||
*/
|
*/
|
||||||
@ -520,24 +558,7 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv)
|
|||||||
qDebug() << "<> Log initialized.";
|
qDebug() << "<> Log initialized.";
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set up paths
|
|
||||||
{
|
{
|
||||||
// Root path is used for updates.
|
|
||||||
#if defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD)
|
|
||||||
QDir foo(FS::PathCombine(binPath, ".."));
|
|
||||||
m_rootPath = foo.absolutePath();
|
|
||||||
#elif defined(Q_OS_WIN32)
|
|
||||||
m_rootPath = binPath;
|
|
||||||
#elif defined(Q_OS_MAC)
|
|
||||||
QDir foo(FS::PathCombine(binPath, "../.."));
|
|
||||||
m_rootPath = foo.absolutePath();
|
|
||||||
// on macOS, touch the root to force Finder to reload the .app metadata (and fix any icon change issues)
|
|
||||||
FS::updateTimestamp(m_rootPath);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef MULTIMC_JARS_LOCATION
|
|
||||||
m_jarsPath = TOSTRING(MULTIMC_JARS_LOCATION);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
qDebug() << BuildConfig.LAUNCHER_DISPLAYNAME << ", (c) 2013-2021 " << BuildConfig.LAUNCHER_COPYRIGHT;
|
qDebug() << BuildConfig.LAUNCHER_DISPLAYNAME << ", (c) 2013-2021 " << BuildConfig.LAUNCHER_COPYRIGHT;
|
||||||
qDebug() << "Version : " << BuildConfig.printableVersionString();
|
qDebug() << "Version : " << BuildConfig.printableVersionString();
|
||||||
@ -566,26 +587,23 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv)
|
|||||||
qDebug() << "<> Paths set.";
|
qDebug() << "<> Paths set.";
|
||||||
}
|
}
|
||||||
|
|
||||||
do // once
|
if(m_liveCheck)
|
||||||
{
|
{
|
||||||
if(m_liveCheck)
|
QFile check(liveCheckFile);
|
||||||
|
if(check.open(QIODevice::WriteOnly | QIODevice::Truncate))
|
||||||
{
|
{
|
||||||
QFile check(liveCheckFile);
|
|
||||||
if(!check.open(QIODevice::WriteOnly | QIODevice::Truncate))
|
|
||||||
{
|
|
||||||
qWarning() << "Could not open" << liveCheckFile << "for writing!";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
auto payload = appID.toString().toUtf8();
|
auto payload = appID.toString().toUtf8();
|
||||||
if(check.write(payload) != payload.size())
|
if(check.write(payload) == payload.size())
|
||||||
{
|
{
|
||||||
|
check.close();
|
||||||
|
} else {
|
||||||
qWarning() << "Could not write into" << liveCheckFile << "!";
|
qWarning() << "Could not write into" << liveCheckFile << "!";
|
||||||
check.remove();
|
check.remove(); // also closes file!
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
check.close();
|
} else {
|
||||||
|
qWarning() << "Could not open" << liveCheckFile << "for writing!";
|
||||||
}
|
}
|
||||||
} while(false);
|
}
|
||||||
|
|
||||||
// Initialize application settings
|
// Initialize application settings
|
||||||
{
|
{
|
||||||
@ -595,15 +613,14 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv)
|
|||||||
m_settings->registerSetting("AutoUpdate", true);
|
m_settings->registerSetting("AutoUpdate", true);
|
||||||
|
|
||||||
// Theming
|
// Theming
|
||||||
m_settings->registerSetting("IconTheme", QString("multimc"));
|
m_settings->registerSetting("IconTheme", QString("pe_colored"));
|
||||||
m_settings->registerSetting("ApplicationTheme", QString("system"));
|
m_settings->registerSetting("ApplicationTheme", QString("system"));
|
||||||
|
|
||||||
// Notifications
|
|
||||||
m_settings->registerSetting("ShownNotifications", QString());
|
|
||||||
|
|
||||||
// Remembered state
|
// Remembered state
|
||||||
m_settings->registerSetting("LastUsedGroupForNewInstance", QString());
|
m_settings->registerSetting("LastUsedGroupForNewInstance", QString());
|
||||||
|
|
||||||
|
m_settings->registerSetting("MenuBarInsteadOfToolBar", false);
|
||||||
|
|
||||||
QString defaultMonospace;
|
QString defaultMonospace;
|
||||||
int defaultSize = 11;
|
int defaultSize = 11;
|
||||||
#ifdef Q_OS_WIN32
|
#ifdef Q_OS_WIN32
|
||||||
@ -662,7 +679,7 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv)
|
|||||||
|
|
||||||
// Memory
|
// Memory
|
||||||
m_settings->registerSetting({"MinMemAlloc", "MinMemoryAlloc"}, 512);
|
m_settings->registerSetting({"MinMemAlloc", "MinMemoryAlloc"}, 512);
|
||||||
m_settings->registerSetting({"MaxMemAlloc", "MaxMemoryAlloc"}, 1024);
|
m_settings->registerSetting({"MaxMemAlloc", "MaxMemoryAlloc"}, 4096);
|
||||||
m_settings->registerSetting("PermGen", 128);
|
m_settings->registerSetting("PermGen", 128);
|
||||||
|
|
||||||
// Java Settings
|
// Java Settings
|
||||||
@ -673,6 +690,7 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv)
|
|||||||
m_settings->registerSetting("JavaVendor", "");
|
m_settings->registerSetting("JavaVendor", "");
|
||||||
m_settings->registerSetting("LastHostname", "");
|
m_settings->registerSetting("LastHostname", "");
|
||||||
m_settings->registerSetting("JvmArgs", "");
|
m_settings->registerSetting("JvmArgs", "");
|
||||||
|
m_settings->registerSetting("IgnoreJavaCompatibility", false);
|
||||||
|
|
||||||
// Native library workarounds
|
// Native library workarounds
|
||||||
m_settings->registerSetting("UseNativeOpenAL", false);
|
m_settings->registerSetting("UseNativeOpenAL", false);
|
||||||
@ -686,6 +704,9 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv)
|
|||||||
// Minecraft launch method
|
// Minecraft launch method
|
||||||
m_settings->registerSetting("MCLaunchMethod", "LauncherPart");
|
m_settings->registerSetting("MCLaunchMethod", "LauncherPart");
|
||||||
|
|
||||||
|
// Minecraft offline player name
|
||||||
|
m_settings->registerSetting("LastOfflinePlayerName", "");
|
||||||
|
|
||||||
// Wrapper command for launch
|
// Wrapper command for launch
|
||||||
m_settings->registerSetting("WrapperCommand", "");
|
m_settings->registerSetting("WrapperCommand", "");
|
||||||
|
|
||||||
@ -714,8 +735,14 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv)
|
|||||||
|
|
||||||
m_settings->registerSetting("UpdateDialogGeometry", "");
|
m_settings->registerSetting("UpdateDialogGeometry", "");
|
||||||
|
|
||||||
// paste.ee API key
|
// pastebin URL
|
||||||
m_settings->registerSetting("PasteEEAPIKey", "multimc");
|
m_settings->registerSetting("PastebinURL", "https://0x0.st");
|
||||||
|
|
||||||
|
m_settings->registerSetting("CloseAfterLaunch", false);
|
||||||
|
m_settings->registerSetting("QuitAfterGameStop", false);
|
||||||
|
|
||||||
|
// Custom MSA credentials
|
||||||
|
m_settings->registerSetting("MSAClientIDOverride", "");
|
||||||
|
|
||||||
// Init page provider
|
// Init page provider
|
||||||
{
|
{
|
||||||
@ -728,7 +755,7 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv)
|
|||||||
m_globalSettingsProvider->addPage<ProxyPage>();
|
m_globalSettingsProvider->addPage<ProxyPage>();
|
||||||
m_globalSettingsProvider->addPage<ExternalToolsPage>();
|
m_globalSettingsProvider->addPage<ExternalToolsPage>();
|
||||||
m_globalSettingsProvider->addPage<AccountListPage>();
|
m_globalSettingsProvider->addPage<AccountListPage>();
|
||||||
m_globalSettingsProvider->addPage<PasteEEPage>();
|
m_globalSettingsProvider->addPage<APIPage>();
|
||||||
}
|
}
|
||||||
qDebug() << "<> Settings loaded.";
|
qDebug() << "<> Settings loaded.";
|
||||||
}
|
}
|
||||||
@ -1125,6 +1152,15 @@ std::vector<ITheme *> Application::getValidApplicationThemes()
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Application::isFlatpak()
|
||||||
|
{
|
||||||
|
#ifdef Q_OS_LINUX
|
||||||
|
return QFile::exists("/.flatpak-info");
|
||||||
|
#else
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
void Application::setApplicationTheme(const QString& name, bool initial)
|
void Application::setApplicationTheme(const QString& name, bool initial)
|
||||||
{
|
{
|
||||||
auto systemPalette = qApp->palette();
|
auto systemPalette = qApp->palette();
|
||||||
@ -1240,6 +1276,12 @@ bool Application::kill(InstancePtr instance)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Application::closeCurrentWindow()
|
||||||
|
{
|
||||||
|
if (focusWindow())
|
||||||
|
focusWindow()->close();
|
||||||
|
}
|
||||||
|
|
||||||
void Application::addRunningInstance()
|
void Application::addRunningInstance()
|
||||||
{
|
{
|
||||||
m_runningInstances ++;
|
m_runningInstances ++;
|
||||||
@ -1512,5 +1554,15 @@ QString Application::getJarsPath()
|
|||||||
{
|
{
|
||||||
return FS::PathCombine(QCoreApplication::applicationDirPath(), "jars");
|
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;
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,38 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-3.0-only
|
||||||
|
/*
|
||||||
|
* PolyMC - Minecraft Launcher
|
||||||
|
* Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, version 3.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* This file incorporates work covered by the following copyright and
|
||||||
|
* permission notice:
|
||||||
|
*
|
||||||
|
* Copyright 2013-2021 MultiMC Contributors
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
@ -69,6 +104,8 @@ public:
|
|||||||
|
|
||||||
QIcon getThemedIcon(const QString& name);
|
QIcon getThemedIcon(const QString& name);
|
||||||
|
|
||||||
|
bool isFlatpak();
|
||||||
|
|
||||||
void setIconTheme(const QString& name);
|
void setIconTheme(const QString& name);
|
||||||
|
|
||||||
std::vector<ITheme *> getValidApplicationThemes();
|
std::vector<ITheme *> getValidApplicationThemes();
|
||||||
@ -117,6 +154,8 @@ public:
|
|||||||
|
|
||||||
QString getJarsPath();
|
QString getJarsPath();
|
||||||
|
|
||||||
|
QString getMSAClientID();
|
||||||
|
|
||||||
/// this is the root of the 'installation'. Used for automatic updates
|
/// this is the root of the 'installation'. Used for automatic updates
|
||||||
const QString &root() {
|
const QString &root() {
|
||||||
return m_rootPath;
|
return m_rootPath;
|
||||||
@ -150,6 +189,7 @@ public slots:
|
|||||||
MinecraftAccountPtr accountToUse = nullptr
|
MinecraftAccountPtr accountToUse = nullptr
|
||||||
);
|
);
|
||||||
bool kill(InstancePtr instance);
|
bool kill(InstancePtr instance);
|
||||||
|
void closeCurrentWindow();
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void on_windowClose();
|
void on_windowClose();
|
||||||
|
@ -1,16 +1,36 @@
|
|||||||
/* Copyright 2013-2021 MultiMC Contributors
|
// SPDX-License-Identifier: GPL-3.0-only
|
||||||
|
/*
|
||||||
|
* PolyMC - Minecraft Launcher
|
||||||
|
* Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net>
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* This program is free software: you can redistribute it and/or modify
|
||||||
* you may not use this file except in compliance with the License.
|
* it under the terms of the GNU General Public License as published by
|
||||||
* You may obtain a copy of the License at
|
* the Free Software Foundation, version 3.
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* 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.
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* You should have received a copy of the GNU General Public License
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
*
|
||||||
* See the License for the specific language governing permissions and
|
* This file incorporates work covered by the following copyright and
|
||||||
* limitations under the License.
|
* 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 "BaseInstance.h"
|
#include "BaseInstance.h"
|
||||||
@ -39,6 +59,7 @@ BaseInstance::BaseInstance(SettingsObjectPtr globalSettings, SettingsObjectPtr s
|
|||||||
m_settings->registerSetting("lastLaunchTime", 0);
|
m_settings->registerSetting("lastLaunchTime", 0);
|
||||||
m_settings->registerSetting("totalTimePlayed", 0);
|
m_settings->registerSetting("totalTimePlayed", 0);
|
||||||
m_settings->registerSetting("lastTimePlayed", 0);
|
m_settings->registerSetting("lastTimePlayed", 0);
|
||||||
|
m_settings->registerSetting("InstanceType", "OneSix");
|
||||||
|
|
||||||
// Custom Commands
|
// Custom Commands
|
||||||
auto commandSetting = m_settings->registerSetting({"OverrideCommands","OverrideLaunchCmd"}, false);
|
auto commandSetting = m_settings->registerSetting({"OverrideCommands","OverrideLaunchCmd"}, false);
|
||||||
|
@ -1,16 +1,36 @@
|
|||||||
/* Copyright 2013-2021 MultiMC Contributors
|
// SPDX-License-Identifier: GPL-3.0-only
|
||||||
|
/*
|
||||||
|
* PolyMC - Minecraft Launcher
|
||||||
|
* Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net>
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* This program is free software: you can redistribute it and/or modify
|
||||||
* you may not use this file except in compliance with the License.
|
* it under the terms of the GNU General Public License as published by
|
||||||
* You may obtain a copy of the License at
|
* the Free Software Foundation, version 3.
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* 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.
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* You should have received a copy of the GNU General Public License
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
*
|
||||||
* See the License for the specific language governing permissions and
|
* This file incorporates work covered by the following copyright and
|
||||||
* limitations under the License.
|
* permission notice:
|
||||||
|
*
|
||||||
|
* Copyright 2013-2021 MultiMC Contributors
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
@ -37,6 +37,10 @@ set(CORE_SOURCES
|
|||||||
InstanceImportTask.h
|
InstanceImportTask.h
|
||||||
InstanceImportTask.cpp
|
InstanceImportTask.cpp
|
||||||
|
|
||||||
|
# Mod downloading task
|
||||||
|
ModDownloadTask.h
|
||||||
|
ModDownloadTask.cpp
|
||||||
|
|
||||||
# Use tracking separate from memory management
|
# Use tracking separate from memory management
|
||||||
Usable.h
|
Usable.h
|
||||||
|
|
||||||
@ -140,6 +144,8 @@ set(LAUNCH_SOURCES
|
|||||||
launch/steps/TextPrint.h
|
launch/steps/TextPrint.h
|
||||||
launch/steps/Update.cpp
|
launch/steps/Update.cpp
|
||||||
launch/steps/Update.h
|
launch/steps/Update.h
|
||||||
|
launch/steps/QuitAfterGameStop.cpp
|
||||||
|
launch/steps/QuitAfterGameStop.h
|
||||||
launch/LaunchStep.cpp
|
launch/LaunchStep.cpp
|
||||||
launch/LaunchStep.h
|
launch/LaunchStep.h
|
||||||
launch/LaunchTask.cpp
|
launch/LaunchTask.cpp
|
||||||
@ -170,13 +176,6 @@ add_unit_test(DownloadTask
|
|||||||
DATA updater/testdata
|
DATA updater/testdata
|
||||||
)
|
)
|
||||||
|
|
||||||
# Rarely used notifications
|
|
||||||
set(NOTIFICATIONS_SOURCES
|
|
||||||
# Notifications - short warning messages
|
|
||||||
notifications/NotificationChecker.h
|
|
||||||
notifications/NotificationChecker.cpp
|
|
||||||
)
|
|
||||||
|
|
||||||
# Backend for the news bar... there's usually no news.
|
# Backend for the news bar... there's usually no news.
|
||||||
set(NEWS_SOURCES
|
set(NEWS_SOURCES
|
||||||
# News System
|
# News System
|
||||||
@ -221,7 +220,11 @@ set(MINECRAFT_SOURCES
|
|||||||
minecraft/auth/flows/Mojang.h
|
minecraft/auth/flows/Mojang.h
|
||||||
minecraft/auth/flows/MSA.cpp
|
minecraft/auth/flows/MSA.cpp
|
||||||
minecraft/auth/flows/MSA.h
|
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.cpp
|
||||||
minecraft/auth/steps/EntitlementsStep.h
|
minecraft/auth/steps/EntitlementsStep.h
|
||||||
minecraft/auth/steps/GetSkinStep.cpp
|
minecraft/auth/steps/GetSkinStep.cpp
|
||||||
@ -232,6 +235,8 @@ set(MINECRAFT_SOURCES
|
|||||||
minecraft/auth/steps/MigrationEligibilityStep.h
|
minecraft/auth/steps/MigrationEligibilityStep.h
|
||||||
minecraft/auth/steps/MinecraftProfileStep.cpp
|
minecraft/auth/steps/MinecraftProfileStep.cpp
|
||||||
minecraft/auth/steps/MinecraftProfileStep.h
|
minecraft/auth/steps/MinecraftProfileStep.h
|
||||||
|
minecraft/auth/steps/MinecraftProfileStepMojang.cpp
|
||||||
|
minecraft/auth/steps/MinecraftProfileStepMojang.h
|
||||||
minecraft/auth/steps/MSAStep.cpp
|
minecraft/auth/steps/MSAStep.cpp
|
||||||
minecraft/auth/steps/MSAStep.h
|
minecraft/auth/steps/MSAStep.h
|
||||||
minecraft/auth/steps/XboxAuthorizationStep.cpp
|
minecraft/auth/steps/XboxAuthorizationStep.cpp
|
||||||
@ -278,13 +283,6 @@ set(MINECRAFT_SOURCES
|
|||||||
minecraft/launch/VerifyJavaInstall.cpp
|
minecraft/launch/VerifyJavaInstall.cpp
|
||||||
minecraft/launch/VerifyJavaInstall.h
|
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/GradleSpecifier.h
|
||||||
minecraft/MinecraftInstance.cpp
|
minecraft/MinecraftInstance.cpp
|
||||||
minecraft/MinecraftInstance.h
|
minecraft/MinecraftInstance.h
|
||||||
@ -352,28 +350,30 @@ set(MINECRAFT_SOURCES
|
|||||||
|
|
||||||
mojang/PackageManifest.h
|
mojang/PackageManifest.h
|
||||||
mojang/PackageManifest.cpp
|
mojang/PackageManifest.cpp
|
||||||
)
|
minecraft/Agent.h)
|
||||||
|
|
||||||
add_unit_test(GradleSpecifier
|
add_unit_test(GradleSpecifier
|
||||||
SOURCES minecraft/GradleSpecifier_test.cpp
|
SOURCES minecraft/GradleSpecifier_test.cpp
|
||||||
LIBS Launcher_logic
|
LIBS Launcher_logic
|
||||||
)
|
)
|
||||||
|
|
||||||
add_executable(PackageManifest
|
if(BUILD_TESTING)
|
||||||
mojang/PackageManifest_test.cpp
|
add_executable(PackageManifest
|
||||||
)
|
mojang/PackageManifest_test.cpp
|
||||||
target_link_libraries(PackageManifest
|
)
|
||||||
Launcher_logic
|
target_link_libraries(PackageManifest
|
||||||
Qt5::Test
|
Launcher_logic
|
||||||
)
|
Qt5::Test
|
||||||
target_include_directories(PackageManifest
|
)
|
||||||
PRIVATE ../cmake/UnitTest/
|
target_include_directories(PackageManifest
|
||||||
)
|
PRIVATE ../cmake/UnitTest/
|
||||||
add_test(
|
)
|
||||||
NAME PackageManifest
|
add_test(
|
||||||
COMMAND PackageManifest
|
NAME PackageManifest
|
||||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
COMMAND PackageManifest
|
||||||
)
|
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
add_unit_test(MojangVersionFormat
|
add_unit_test(MojangVersionFormat
|
||||||
SOURCES minecraft/MojangVersionFormat_test.cpp
|
SOURCES minecraft/MojangVersionFormat_test.cpp
|
||||||
@ -415,6 +415,11 @@ set(TASKS_SOURCES
|
|||||||
tasks/SequentialTask.cpp
|
tasks/SequentialTask.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
|
add_unit_test(Task
|
||||||
|
SOURCES tasks/Task_test.cpp
|
||||||
|
LIBS Launcher_logic
|
||||||
|
)
|
||||||
|
|
||||||
set(SETTINGS_SOURCES
|
set(SETTINGS_SOURCES
|
||||||
# Settings
|
# Settings
|
||||||
settings/INIFile.cpp
|
settings/INIFile.cpp
|
||||||
@ -491,6 +496,16 @@ set(META_SOURCES
|
|||||||
meta/Index.h
|
meta/Index.h
|
||||||
)
|
)
|
||||||
|
|
||||||
|
set(API_SOURCES
|
||||||
|
modplatform/ModAPI.h
|
||||||
|
|
||||||
|
modplatform/flame/FlameAPI.h
|
||||||
|
modplatform/modrinth/ModrinthAPI.h
|
||||||
|
|
||||||
|
modplatform/helpers/NetworkModAPI.h
|
||||||
|
modplatform/helpers/NetworkModAPI.cpp
|
||||||
|
)
|
||||||
|
|
||||||
set(FTB_SOURCES
|
set(FTB_SOURCES
|
||||||
modplatform/legacy_ftb/PackFetchTask.h
|
modplatform/legacy_ftb/PackFetchTask.h
|
||||||
modplatform/legacy_ftb/PackFetchTask.cpp
|
modplatform/legacy_ftb/PackFetchTask.cpp
|
||||||
@ -506,12 +521,19 @@ set(FLAME_SOURCES
|
|||||||
# Flame
|
# Flame
|
||||||
modplatform/flame/FlamePackIndex.cpp
|
modplatform/flame/FlamePackIndex.cpp
|
||||||
modplatform/flame/FlamePackIndex.h
|
modplatform/flame/FlamePackIndex.h
|
||||||
|
modplatform/flame/FlameModIndex.cpp
|
||||||
|
modplatform/flame/FlameModIndex.h
|
||||||
modplatform/flame/PackManifest.h
|
modplatform/flame/PackManifest.h
|
||||||
modplatform/flame/PackManifest.cpp
|
modplatform/flame/PackManifest.cpp
|
||||||
modplatform/flame/FileResolvingTask.h
|
modplatform/flame/FileResolvingTask.h
|
||||||
modplatform/flame/FileResolvingTask.cpp
|
modplatform/flame/FileResolvingTask.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
|
set(MODRINTH_SOURCES
|
||||||
|
modplatform/modrinth/ModrinthPackIndex.cpp
|
||||||
|
modplatform/modrinth/ModrinthPackIndex.h
|
||||||
|
)
|
||||||
|
|
||||||
set(MODPACKSCH_SOURCES
|
set(MODPACKSCH_SOURCES
|
||||||
modplatform/modpacksch/FTBPackInstallTask.h
|
modplatform/modpacksch/FTBPackInstallTask.h
|
||||||
modplatform/modpacksch/FTBPackInstallTask.cpp
|
modplatform/modpacksch/FTBPackInstallTask.cpp
|
||||||
@ -524,6 +546,8 @@ set(TECHNIC_SOURCES
|
|||||||
modplatform/technic/SingleZipPackInstallTask.cpp
|
modplatform/technic/SingleZipPackInstallTask.cpp
|
||||||
modplatform/technic/SolderPackInstallTask.h
|
modplatform/technic/SolderPackInstallTask.h
|
||||||
modplatform/technic/SolderPackInstallTask.cpp
|
modplatform/technic/SolderPackInstallTask.cpp
|
||||||
|
modplatform/technic/SolderPackManifest.h
|
||||||
|
modplatform/technic/SolderPackManifest.cpp
|
||||||
modplatform/technic/TechnicPackProcessor.h
|
modplatform/technic/TechnicPackProcessor.h
|
||||||
modplatform/technic/TechnicPackProcessor.cpp
|
modplatform/technic/TechnicPackProcessor.cpp
|
||||||
)
|
)
|
||||||
@ -553,7 +577,6 @@ set(LOGIC_SOURCES
|
|||||||
${NET_SOURCES}
|
${NET_SOURCES}
|
||||||
${LAUNCH_SOURCES}
|
${LAUNCH_SOURCES}
|
||||||
${UPDATE_SOURCES}
|
${UPDATE_SOURCES}
|
||||||
${NOTIFICATIONS_SOURCES}
|
|
||||||
${NEWS_SOURCES}
|
${NEWS_SOURCES}
|
||||||
${MINECRAFT_SOURCES}
|
${MINECRAFT_SOURCES}
|
||||||
${SCREENSHOTS_SOURCES}
|
${SCREENSHOTS_SOURCES}
|
||||||
@ -564,8 +587,10 @@ set(LOGIC_SOURCES
|
|||||||
${TOOLS_SOURCES}
|
${TOOLS_SOURCES}
|
||||||
${META_SOURCES}
|
${META_SOURCES}
|
||||||
${ICONS_SOURCES}
|
${ICONS_SOURCES}
|
||||||
|
${API_SOURCES}
|
||||||
${FTB_SOURCES}
|
${FTB_SOURCES}
|
||||||
${FLAME_SOURCES}
|
${FLAME_SOURCES}
|
||||||
|
${MODRINTH_SOURCES}
|
||||||
${MODPACKSCH_SOURCES}
|
${MODPACKSCH_SOURCES}
|
||||||
${TECHNIC_SOURCES}
|
${TECHNIC_SOURCES}
|
||||||
${ATLAUNCHER_SOURCES}
|
${ATLAUNCHER_SOURCES}
|
||||||
@ -685,8 +710,6 @@ SET(LAUNCHER_SOURCES
|
|||||||
ui/pages/instance/OtherLogsPage.h
|
ui/pages/instance/OtherLogsPage.h
|
||||||
ui/pages/instance/ServersPage.cpp
|
ui/pages/instance/ServersPage.cpp
|
||||||
ui/pages/instance/ServersPage.h
|
ui/pages/instance/ServersPage.h
|
||||||
ui/pages/instance/LegacyUpgradePage.cpp
|
|
||||||
ui/pages/instance/LegacyUpgradePage.h
|
|
||||||
ui/pages/instance/WorldListPage.cpp
|
ui/pages/instance/WorldListPage.cpp
|
||||||
ui/pages/instance/WorldListPage.h
|
ui/pages/instance/WorldListPage.h
|
||||||
|
|
||||||
@ -707,13 +730,18 @@ SET(LAUNCHER_SOURCES
|
|||||||
ui/pages/global/LauncherPage.h
|
ui/pages/global/LauncherPage.h
|
||||||
ui/pages/global/ProxyPage.cpp
|
ui/pages/global/ProxyPage.cpp
|
||||||
ui/pages/global/ProxyPage.h
|
ui/pages/global/ProxyPage.h
|
||||||
ui/pages/global/PasteEEPage.cpp
|
ui/pages/global/APIPage.cpp
|
||||||
ui/pages/global/PasteEEPage.h
|
ui/pages/global/APIPage.h
|
||||||
|
|
||||||
# GUI - platform pages
|
# GUI - platform pages
|
||||||
ui/pages/modplatform/VanillaPage.cpp
|
ui/pages/modplatform/VanillaPage.cpp
|
||||||
ui/pages/modplatform/VanillaPage.h
|
ui/pages/modplatform/VanillaPage.h
|
||||||
|
|
||||||
|
ui/pages/modplatform/ModPage.cpp
|
||||||
|
ui/pages/modplatform/ModPage.h
|
||||||
|
ui/pages/modplatform/ModModel.cpp
|
||||||
|
ui/pages/modplatform/ModModel.h
|
||||||
|
|
||||||
ui/pages/modplatform/atlauncher/AtlFilterModel.cpp
|
ui/pages/modplatform/atlauncher/AtlFilterModel.cpp
|
||||||
ui/pages/modplatform/atlauncher/AtlFilterModel.h
|
ui/pages/modplatform/atlauncher/AtlFilterModel.h
|
||||||
ui/pages/modplatform/atlauncher/AtlListModel.cpp
|
ui/pages/modplatform/atlauncher/AtlListModel.cpp
|
||||||
@ -739,6 +767,10 @@ SET(LAUNCHER_SOURCES
|
|||||||
ui/pages/modplatform/flame/FlameModel.h
|
ui/pages/modplatform/flame/FlameModel.h
|
||||||
ui/pages/modplatform/flame/FlamePage.cpp
|
ui/pages/modplatform/flame/FlamePage.cpp
|
||||||
ui/pages/modplatform/flame/FlamePage.h
|
ui/pages/modplatform/flame/FlamePage.h
|
||||||
|
ui/pages/modplatform/flame/FlameModModel.cpp
|
||||||
|
ui/pages/modplatform/flame/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.cpp
|
||||||
ui/pages/modplatform/technic/TechnicModel.h
|
ui/pages/modplatform/technic/TechnicModel.h
|
||||||
@ -748,6 +780,11 @@ SET(LAUNCHER_SOURCES
|
|||||||
ui/pages/modplatform/ImportPage.cpp
|
ui/pages/modplatform/ImportPage.cpp
|
||||||
ui/pages/modplatform/ImportPage.h
|
ui/pages/modplatform/ImportPage.h
|
||||||
|
|
||||||
|
ui/pages/modplatform/modrinth/ModrinthModel.cpp
|
||||||
|
ui/pages/modplatform/modrinth/ModrinthModel.h
|
||||||
|
ui/pages/modplatform/modrinth/ModrinthPage.cpp
|
||||||
|
ui/pages/modplatform/modrinth/ModrinthPage.h
|
||||||
|
|
||||||
# GUI - dialogs
|
# GUI - dialogs
|
||||||
ui/dialogs/AboutDialog.cpp
|
ui/dialogs/AboutDialog.cpp
|
||||||
ui/dialogs/AboutDialog.h
|
ui/dialogs/AboutDialog.h
|
||||||
@ -769,23 +806,26 @@ SET(LAUNCHER_SOURCES
|
|||||||
ui/dialogs/LoginDialog.h
|
ui/dialogs/LoginDialog.h
|
||||||
ui/dialogs/MSALoginDialog.cpp
|
ui/dialogs/MSALoginDialog.cpp
|
||||||
ui/dialogs/MSALoginDialog.h
|
ui/dialogs/MSALoginDialog.h
|
||||||
|
ui/dialogs/OfflineLoginDialog.cpp
|
||||||
|
ui/dialogs/OfflineLoginDialog.h
|
||||||
ui/dialogs/NewComponentDialog.cpp
|
ui/dialogs/NewComponentDialog.cpp
|
||||||
ui/dialogs/NewComponentDialog.h
|
ui/dialogs/NewComponentDialog.h
|
||||||
ui/dialogs/NewInstanceDialog.cpp
|
ui/dialogs/NewInstanceDialog.cpp
|
||||||
ui/dialogs/NewInstanceDialog.h
|
ui/dialogs/NewInstanceDialog.h
|
||||||
ui/dialogs/NotificationDialog.cpp
|
|
||||||
ui/dialogs/NotificationDialog.h
|
|
||||||
ui/pagedialog/PageDialog.cpp
|
ui/pagedialog/PageDialog.cpp
|
||||||
ui/pagedialog/PageDialog.h
|
ui/pagedialog/PageDialog.h
|
||||||
ui/dialogs/ProgressDialog.cpp
|
ui/dialogs/ProgressDialog.cpp
|
||||||
ui/dialogs/ProgressDialog.h
|
ui/dialogs/ProgressDialog.h
|
||||||
|
ui/dialogs/ReviewMessageBox.cpp
|
||||||
|
ui/dialogs/ReviewMessageBox.h
|
||||||
ui/dialogs/UpdateDialog.cpp
|
ui/dialogs/UpdateDialog.cpp
|
||||||
ui/dialogs/UpdateDialog.h
|
ui/dialogs/UpdateDialog.h
|
||||||
ui/dialogs/VersionSelectDialog.cpp
|
ui/dialogs/VersionSelectDialog.cpp
|
||||||
ui/dialogs/VersionSelectDialog.h
|
ui/dialogs/VersionSelectDialog.h
|
||||||
ui/dialogs/SkinUploadDialog.cpp
|
ui/dialogs/SkinUploadDialog.cpp
|
||||||
ui/dialogs/SkinUploadDialog.h
|
ui/dialogs/SkinUploadDialog.h
|
||||||
|
ui/dialogs/ModDownloadDialog.cpp
|
||||||
|
ui/dialogs/ModDownloadDialog.h
|
||||||
|
|
||||||
# GUI - widgets
|
# GUI - widgets
|
||||||
ui/widgets/Common.cpp
|
ui/widgets/Common.cpp
|
||||||
@ -810,6 +850,8 @@ SET(LAUNCHER_SOURCES
|
|||||||
ui/widgets/LogView.h
|
ui/widgets/LogView.h
|
||||||
ui/widgets/MCModInfoFrame.cpp
|
ui/widgets/MCModInfoFrame.cpp
|
||||||
ui/widgets/MCModInfoFrame.h
|
ui/widgets/MCModInfoFrame.h
|
||||||
|
ui/widgets/ModFilterWidget.cpp
|
||||||
|
ui/widgets/ModFilterWidget.h
|
||||||
ui/widgets/ModListView.cpp
|
ui/widgets/ModListView.cpp
|
||||||
ui/widgets/ModListView.h
|
ui/widgets/ModListView.h
|
||||||
ui/widgets/PageContainer.cpp
|
ui/widgets/PageContainer.cpp
|
||||||
@ -842,7 +884,7 @@ qt5_wrap_ui(LAUNCHER_UI
|
|||||||
ui/pages/global/AccountListPage.ui
|
ui/pages/global/AccountListPage.ui
|
||||||
ui/pages/global/JavaPage.ui
|
ui/pages/global/JavaPage.ui
|
||||||
ui/pages/global/LauncherPage.ui
|
ui/pages/global/LauncherPage.ui
|
||||||
ui/pages/global/PasteEEPage.ui
|
ui/pages/global/APIPage.ui
|
||||||
ui/pages/global/ProxyPage.ui
|
ui/pages/global/ProxyPage.ui
|
||||||
ui/pages/global/MinecraftPage.ui
|
ui/pages/global/MinecraftPage.ui
|
||||||
ui/pages/global/ExternalToolsPage.ui
|
ui/pages/global/ExternalToolsPage.ui
|
||||||
@ -855,11 +897,11 @@ qt5_wrap_ui(LAUNCHER_UI
|
|||||||
ui/pages/instance/InstanceSettingsPage.ui
|
ui/pages/instance/InstanceSettingsPage.ui
|
||||||
ui/pages/instance/VersionPage.ui
|
ui/pages/instance/VersionPage.ui
|
||||||
ui/pages/instance/WorldListPage.ui
|
ui/pages/instance/WorldListPage.ui
|
||||||
ui/pages/instance/LegacyUpgradePage.ui
|
|
||||||
ui/pages/instance/ScreenshotsPage.ui
|
ui/pages/instance/ScreenshotsPage.ui
|
||||||
ui/pages/modplatform/atlauncher/AtlOptionalModDialog.ui
|
ui/pages/modplatform/atlauncher/AtlOptionalModDialog.ui
|
||||||
ui/pages/modplatform/atlauncher/AtlPage.ui
|
ui/pages/modplatform/atlauncher/AtlPage.ui
|
||||||
ui/pages/modplatform/VanillaPage.ui
|
ui/pages/modplatform/VanillaPage.ui
|
||||||
|
ui/pages/modplatform/ModPage.ui
|
||||||
ui/pages/modplatform/flame/FlamePage.ui
|
ui/pages/modplatform/flame/FlamePage.ui
|
||||||
ui/pages/modplatform/legacy_ftb/Page.ui
|
ui/pages/modplatform/legacy_ftb/Page.ui
|
||||||
ui/pages/modplatform/ImportPage.ui
|
ui/pages/modplatform/ImportPage.ui
|
||||||
@ -868,11 +910,11 @@ qt5_wrap_ui(LAUNCHER_UI
|
|||||||
ui/widgets/InstanceCardWidget.ui
|
ui/widgets/InstanceCardWidget.ui
|
||||||
ui/widgets/CustomCommands.ui
|
ui/widgets/CustomCommands.ui
|
||||||
ui/widgets/MCModInfoFrame.ui
|
ui/widgets/MCModInfoFrame.ui
|
||||||
|
ui/widgets/ModFilterWidget.ui
|
||||||
ui/dialogs/CopyInstanceDialog.ui
|
ui/dialogs/CopyInstanceDialog.ui
|
||||||
ui/dialogs/ProfileSetupDialog.ui
|
ui/dialogs/ProfileSetupDialog.ui
|
||||||
ui/dialogs/ProgressDialog.ui
|
ui/dialogs/ProgressDialog.ui
|
||||||
ui/dialogs/NewInstanceDialog.ui
|
ui/dialogs/NewInstanceDialog.ui
|
||||||
ui/dialogs/NotificationDialog.ui
|
|
||||||
ui/dialogs/UpdateDialog.ui
|
ui/dialogs/UpdateDialog.ui
|
||||||
ui/dialogs/NewComponentDialog.ui
|
ui/dialogs/NewComponentDialog.ui
|
||||||
ui/dialogs/ProfileSelectDialog.ui
|
ui/dialogs/ProfileSelectDialog.ui
|
||||||
@ -880,9 +922,11 @@ qt5_wrap_ui(LAUNCHER_UI
|
|||||||
ui/dialogs/ExportInstanceDialog.ui
|
ui/dialogs/ExportInstanceDialog.ui
|
||||||
ui/dialogs/IconPickerDialog.ui
|
ui/dialogs/IconPickerDialog.ui
|
||||||
ui/dialogs/MSALoginDialog.ui
|
ui/dialogs/MSALoginDialog.ui
|
||||||
|
ui/dialogs/OfflineLoginDialog.ui
|
||||||
ui/dialogs/AboutDialog.ui
|
ui/dialogs/AboutDialog.ui
|
||||||
ui/dialogs/LoginDialog.ui
|
ui/dialogs/LoginDialog.ui
|
||||||
ui/dialogs/EditAccountDialog.ui
|
ui/dialogs/EditAccountDialog.ui
|
||||||
|
ui/dialogs/ReviewMessageBox.ui
|
||||||
)
|
)
|
||||||
|
|
||||||
qt5_add_resources(LAUNCHER_RESOURCES
|
qt5_add_resources(LAUNCHER_RESOURCES
|
||||||
@ -908,9 +952,8 @@ endif()
|
|||||||
add_library(Launcher_logic STATIC ${LOGIC_SOURCES} ${LAUNCHER_SOURCES} ${LAUNCHER_UI} ${LAUNCHER_RESOURCES})
|
add_library(Launcher_logic STATIC ${LOGIC_SOURCES} ${LAUNCHER_SOURCES} ${LAUNCHER_UI} ${LAUNCHER_RESOURCES})
|
||||||
target_link_libraries(Launcher_logic
|
target_link_libraries(Launcher_logic
|
||||||
systeminfo
|
systeminfo
|
||||||
Launcher_quazip
|
|
||||||
Launcher_classparser
|
Launcher_classparser
|
||||||
${NBT_NAME}
|
nbt++
|
||||||
${ZLIB_LIBRARIES}
|
${ZLIB_LIBRARIES}
|
||||||
optional-bare
|
optional-bare
|
||||||
tomlc99
|
tomlc99
|
||||||
@ -926,10 +969,10 @@ target_link_libraries(Launcher_logic
|
|||||||
)
|
)
|
||||||
target_link_libraries(Launcher_logic
|
target_link_libraries(Launcher_logic
|
||||||
Launcher_iconfix
|
Launcher_iconfix
|
||||||
${QUAZIP_LIBRARIES}
|
QuaZip::QuaZip
|
||||||
hoedown
|
hoedown
|
||||||
Launcher_rainbow
|
|
||||||
LocalPeer
|
LocalPeer
|
||||||
|
Launcher_rainbow
|
||||||
)
|
)
|
||||||
|
|
||||||
target_link_libraries(Launcher_logic)
|
target_link_libraries(Launcher_logic)
|
||||||
@ -950,7 +993,7 @@ if(DEFINED Launcher_APP_BINARY_DEFS)
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
install(TARGETS ${Launcher_Name}
|
install(TARGETS ${Launcher_Name}
|
||||||
BUNDLE DESTINATION ${BUNDLE_DEST_DIR} COMPONENT Runtime
|
BUNDLE DESTINATION "." COMPONENT Runtime
|
||||||
LIBRARY DESTINATION ${LIBRARY_DEST_DIR} COMPONENT Runtime
|
LIBRARY DESTINATION ${LIBRARY_DEST_DIR} COMPONENT Runtime
|
||||||
RUNTIME DESTINATION ${BINARY_DEST_DIR} COMPONENT Runtime
|
RUNTIME DESTINATION ${BINARY_DEST_DIR} COMPONENT Runtime
|
||||||
)
|
)
|
||||||
@ -971,7 +1014,7 @@ if(INSTALL_BUNDLE STREQUAL "full")
|
|||||||
DIRECTORY "${QT_PLUGINS_DIR}/imageformats"
|
DIRECTORY "${QT_PLUGINS_DIR}/imageformats"
|
||||||
DESTINATION ${PLUGIN_DEST_DIR}
|
DESTINATION ${PLUGIN_DEST_DIR}
|
||||||
COMPONENT Runtime
|
COMPONENT Runtime
|
||||||
REGEX "tga|tiff|mng|webp" EXCLUDE
|
REGEX "tga|tiff|mng" EXCLUDE
|
||||||
)
|
)
|
||||||
# Icon engines
|
# Icon engines
|
||||||
install(
|
install(
|
||||||
@ -1001,7 +1044,7 @@ if(INSTALL_BUNDLE STREQUAL "full")
|
|||||||
DIRECTORY "${QT_PLUGINS_DIR}/imageformats"
|
DIRECTORY "${QT_PLUGINS_DIR}/imageformats"
|
||||||
DESTINATION ${PLUGIN_DEST_DIR}
|
DESTINATION ${PLUGIN_DEST_DIR}
|
||||||
COMPONENT Runtime
|
COMPONENT Runtime
|
||||||
REGEX "tga|tiff|mng|webp" EXCLUDE
|
REGEX "tga|tiff|mng" EXCLUDE
|
||||||
REGEX "d\\." EXCLUDE
|
REGEX "d\\." EXCLUDE
|
||||||
REGEX "_debug\\." EXCLUDE
|
REGEX "_debug\\." EXCLUDE
|
||||||
REGEX "\\.dSYM" EXCLUDE
|
REGEX "\\.dSYM" EXCLUDE
|
||||||
|
@ -1,8 +1,43 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-3.0-only
|
||||||
|
/*
|
||||||
|
* PolyMC - Minecraft Launcher
|
||||||
|
* Copyright (C) 2022 dada513 <dada513@protonmail.com>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, version 3.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* This file incorporates work covered by the following copyright and
|
||||||
|
* permission notice:
|
||||||
|
*
|
||||||
|
* Copyright 2013-2022 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 "DesktopServices.h"
|
#include "DesktopServices.h"
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
#include <QDesktopServices>
|
#include <QDesktopServices>
|
||||||
#include <QProcess>
|
#include <QProcess>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
|
#include "Application.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This shouldn't exist, but until QTBUG-9328 and other unreported bugs are fixed, it needs to be a thing.
|
* This shouldn't exist, but until QTBUG-9328 and other unreported bugs are fixed, it needs to be a thing.
|
||||||
@ -84,7 +119,14 @@ bool openDirectory(const QString &path, bool ensureExists)
|
|||||||
return QDesktopServices::openUrl(QUrl::fromLocalFile(dir.absolutePath()));
|
return QDesktopServices::openUrl(QUrl::fromLocalFile(dir.absolutePath()));
|
||||||
};
|
};
|
||||||
#if defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD)
|
#if defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD)
|
||||||
return IndirectOpen(f);
|
if(!APPLICATION->isFlatpak())
|
||||||
|
{
|
||||||
|
return IndirectOpen(f);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return f();
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
return f();
|
return f();
|
||||||
#endif
|
#endif
|
||||||
@ -98,7 +140,14 @@ bool openFile(const QString &path)
|
|||||||
return QDesktopServices::openUrl(QUrl::fromLocalFile(path));
|
return QDesktopServices::openUrl(QUrl::fromLocalFile(path));
|
||||||
};
|
};
|
||||||
#if defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD)
|
#if defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD)
|
||||||
return IndirectOpen(f);
|
if(!APPLICATION->isFlatpak())
|
||||||
|
{
|
||||||
|
return IndirectOpen(f);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return f();
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
return f();
|
return f();
|
||||||
#endif
|
#endif
|
||||||
@ -109,10 +158,17 @@ bool openFile(const QString &application, const QString &path, const QString &wo
|
|||||||
qDebug() << "Opening file" << path << "using" << application;
|
qDebug() << "Opening file" << path << "using" << application;
|
||||||
#if defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD)
|
#if defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD)
|
||||||
// FIXME: the pid here is fake. So if something depends on it, it will likely misbehave
|
// FIXME: the pid here is fake. So if something depends on it, it will likely misbehave
|
||||||
return IndirectOpen([&]()
|
if(!APPLICATION->isFlatpak())
|
||||||
{
|
{
|
||||||
return QProcess::startDetached(application, QStringList() << path, workingDirectory);
|
return IndirectOpen([&]()
|
||||||
}, pid);
|
{
|
||||||
|
return QProcess::startDetached(application, QStringList() << path, workingDirectory);
|
||||||
|
}, pid);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return QProcess::startDetached(application, QStringList() << path, workingDirectory, pid);
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
return QProcess::startDetached(application, QStringList() << path, workingDirectory, pid);
|
return QProcess::startDetached(application, QStringList() << path, workingDirectory, pid);
|
||||||
#endif
|
#endif
|
||||||
@ -122,11 +178,18 @@ bool run(const QString &application, const QStringList &args, const QString &wor
|
|||||||
{
|
{
|
||||||
qDebug() << "Running" << application << "with args" << args.join(' ');
|
qDebug() << "Running" << application << "with args" << args.join(' ');
|
||||||
#if defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD)
|
#if defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD)
|
||||||
|
if(!APPLICATION->isFlatpak())
|
||||||
|
{
|
||||||
// FIXME: the pid here is fake. So if something depends on it, it will likely misbehave
|
// FIXME: the pid here is fake. So if something depends on it, it will likely misbehave
|
||||||
return IndirectOpen([&]()
|
return IndirectOpen([&]()
|
||||||
{
|
{
|
||||||
return QProcess::startDetached(application, args, workingDirectory);
|
return QProcess::startDetached(application, args, workingDirectory);
|
||||||
}, pid);
|
}, pid);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return QProcess::startDetached(application, args, workingDirectory, pid);
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
return QProcess::startDetached(application, args, workingDirectory, pid);
|
return QProcess::startDetached(application, args, workingDirectory, pid);
|
||||||
#endif
|
#endif
|
||||||
@ -140,7 +203,14 @@ bool openUrl(const QUrl &url)
|
|||||||
return QDesktopServices::openUrl(url);
|
return QDesktopServices::openUrl(url);
|
||||||
};
|
};
|
||||||
#if defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD)
|
#if defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD)
|
||||||
return IndirectOpen(f);
|
if(!APPLICATION->isFlatpak())
|
||||||
|
{
|
||||||
|
return IndirectOpen(f);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return f();
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
return f();
|
return f();
|
||||||
#endif
|
#endif
|
||||||
|
@ -42,7 +42,6 @@ void InstanceCopyTask::copyFinished()
|
|||||||
}
|
}
|
||||||
// FIXME: shouldn't this be able to report errors?
|
// FIXME: shouldn't this be able to report errors?
|
||||||
auto instanceSettings = std::make_shared<INISettingsObject>(FS::PathCombine(m_stagingPath, "instance.cfg"));
|
auto instanceSettings = std::make_shared<INISettingsObject>(FS::PathCombine(m_stagingPath, "instance.cfg"));
|
||||||
instanceSettings->registerSetting("InstanceType", "Legacy");
|
|
||||||
|
|
||||||
InstancePtr inst(new NullInstance(m_globalSettings, instanceSettings, m_stagingPath));
|
InstancePtr inst(new NullInstance(m_globalSettings, instanceSettings, m_stagingPath));
|
||||||
inst->setName(m_instName);
|
inst->setName(m_instName);
|
||||||
|
@ -9,6 +9,15 @@
|
|||||||
InstanceCreationTask::InstanceCreationTask(BaseVersionPtr version)
|
InstanceCreationTask::InstanceCreationTask(BaseVersionPtr version)
|
||||||
{
|
{
|
||||||
m_version = version;
|
m_version = version;
|
||||||
|
m_usingLoader = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
InstanceCreationTask::InstanceCreationTask(BaseVersionPtr version, QString loader, BaseVersionPtr loaderVersion)
|
||||||
|
{
|
||||||
|
m_version = version;
|
||||||
|
m_usingLoader = true;
|
||||||
|
m_loader = loader;
|
||||||
|
m_loaderVersion = loaderVersion;
|
||||||
}
|
}
|
||||||
|
|
||||||
void InstanceCreationTask::executeTask()
|
void InstanceCreationTask::executeTask()
|
||||||
@ -17,12 +26,12 @@ void InstanceCreationTask::executeTask()
|
|||||||
{
|
{
|
||||||
auto instanceSettings = std::make_shared<INISettingsObject>(FS::PathCombine(m_stagingPath, "instance.cfg"));
|
auto instanceSettings = std::make_shared<INISettingsObject>(FS::PathCombine(m_stagingPath, "instance.cfg"));
|
||||||
instanceSettings->suspendSave();
|
instanceSettings->suspendSave();
|
||||||
instanceSettings->registerSetting("InstanceType", "Legacy");
|
|
||||||
instanceSettings->set("InstanceType", "OneSix");
|
|
||||||
MinecraftInstance inst(m_globalSettings, instanceSettings, m_stagingPath);
|
MinecraftInstance inst(m_globalSettings, instanceSettings, m_stagingPath);
|
||||||
auto components = inst.getPackProfile();
|
auto components = inst.getPackProfile();
|
||||||
components->buildingFromScratch();
|
components->buildingFromScratch();
|
||||||
components->setComponentVersion("net.minecraft", m_version->descriptor(), true);
|
components->setComponentVersion("net.minecraft", m_version->descriptor(), true);
|
||||||
|
if(m_usingLoader)
|
||||||
|
components->setComponentVersion(m_loader, m_loaderVersion->descriptor());
|
||||||
inst.setName(m_instName);
|
inst.setName(m_instName);
|
||||||
inst.setIconKey(m_instIcon);
|
inst.setIconKey(m_instIcon);
|
||||||
instanceSettings->resumeSave();
|
instanceSettings->resumeSave();
|
||||||
|
@ -12,6 +12,7 @@ class InstanceCreationTask : public InstanceTask
|
|||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
explicit InstanceCreationTask(BaseVersionPtr version);
|
explicit InstanceCreationTask(BaseVersionPtr version);
|
||||||
|
explicit InstanceCreationTask(BaseVersionPtr version, QString loader, BaseVersionPtr loaderVersion);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
//! Entry point for tasks.
|
//! Entry point for tasks.
|
||||||
@ -19,4 +20,7 @@ protected:
|
|||||||
|
|
||||||
private: /* data */
|
private: /* data */
|
||||||
BaseVersionPtr m_version;
|
BaseVersionPtr m_version;
|
||||||
|
bool m_usingLoader;
|
||||||
|
QString m_loader;
|
||||||
|
BaseVersionPtr m_loaderVersion;
|
||||||
};
|
};
|
||||||
|
@ -29,7 +29,7 @@
|
|||||||
#include "modplatform/flame/FileResolvingTask.h"
|
#include "modplatform/flame/FileResolvingTask.h"
|
||||||
#include "modplatform/flame/PackManifest.h"
|
#include "modplatform/flame/PackManifest.h"
|
||||||
#include "Json.h"
|
#include "Json.h"
|
||||||
#include <quazipdir.h>
|
#include <quazip/quazipdir.h>
|
||||||
#include "modplatform/technic/TechnicPackProcessor.h"
|
#include "modplatform/technic/TechnicPackProcessor.h"
|
||||||
|
|
||||||
#include "icons/IconList.h"
|
#include "icons/IconList.h"
|
||||||
@ -40,6 +40,14 @@ InstanceImportTask::InstanceImportTask(const QUrl sourceUrl)
|
|||||||
m_sourceUrl = sourceUrl;
|
m_sourceUrl = sourceUrl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool InstanceImportTask::abort()
|
||||||
|
{
|
||||||
|
m_filesNetJob->abort();
|
||||||
|
m_extractFuture.cancel();
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
void InstanceImportTask::executeTask()
|
void InstanceImportTask::executeTask()
|
||||||
{
|
{
|
||||||
if (m_sourceUrl.isLocalFile())
|
if (m_sourceUrl.isLocalFile())
|
||||||
@ -241,6 +249,7 @@ void InstanceImportTask::processFlame()
|
|||||||
|
|
||||||
QString forgeVersion;
|
QString forgeVersion;
|
||||||
QString fabricVersion;
|
QString fabricVersion;
|
||||||
|
// TODO: is Quilt relevant here?
|
||||||
for(auto &loader: pack.minecraft.modLoaders)
|
for(auto &loader: pack.minecraft.modLoaders)
|
||||||
{
|
{
|
||||||
auto id = loader.id;
|
auto id = loader.id;
|
||||||
@ -261,8 +270,6 @@ void InstanceImportTask::processFlame()
|
|||||||
|
|
||||||
QString configPath = FS::PathCombine(m_stagingPath, "instance.cfg");
|
QString configPath = FS::PathCombine(m_stagingPath, "instance.cfg");
|
||||||
auto instanceSettings = std::make_shared<INISettingsObject>(configPath);
|
auto instanceSettings = std::make_shared<INISettingsObject>(configPath);
|
||||||
instanceSettings->registerSetting("InstanceType", "Legacy");
|
|
||||||
instanceSettings->set("InstanceType", "OneSix");
|
|
||||||
MinecraftInstance instance(m_globalSettings, instanceSettings, m_stagingPath);
|
MinecraftInstance instance(m_globalSettings, instanceSettings, m_stagingPath);
|
||||||
auto mcVersion = pack.minecraft.version;
|
auto mcVersion = pack.minecraft.version;
|
||||||
// Hack to correct some 'special sauce'...
|
// Hack to correct some 'special sauce'...
|
||||||
@ -285,7 +292,7 @@ void InstanceImportTask::processFlame()
|
|||||||
}
|
}
|
||||||
else
|
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);
|
components->setComponentVersion("net.minecraftforge", forgeVersion);
|
||||||
@ -422,7 +429,6 @@ void InstanceImportTask::processMultiMC()
|
|||||||
{
|
{
|
||||||
QString configPath = FS::PathCombine(m_stagingPath, "instance.cfg");
|
QString configPath = FS::PathCombine(m_stagingPath, "instance.cfg");
|
||||||
auto instanceSettings = std::make_shared<INISettingsObject>(configPath);
|
auto instanceSettings = std::make_shared<INISettingsObject>(configPath);
|
||||||
instanceSettings->registerSetting("InstanceType", "Legacy");
|
|
||||||
|
|
||||||
NullInstance instance(m_globalSettings, instanceSettings, m_stagingPath);
|
NullInstance instance(m_globalSettings, instanceSettings, m_stagingPath);
|
||||||
|
|
||||||
|
@ -37,6 +37,9 @@ class InstanceImportTask : public InstanceTask
|
|||||||
public:
|
public:
|
||||||
explicit InstanceImportTask(const QUrl sourceUrl);
|
explicit InstanceImportTask(const QUrl sourceUrl);
|
||||||
|
|
||||||
|
bool canAbort() const override { return true; }
|
||||||
|
bool abort() override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
//! Entry point for tasks.
|
//! Entry point for tasks.
|
||||||
virtual void executeTask() override;
|
virtual void executeTask() override;
|
||||||
|
@ -32,7 +32,6 @@
|
|||||||
#include "BaseInstance.h"
|
#include "BaseInstance.h"
|
||||||
#include "InstanceTask.h"
|
#include "InstanceTask.h"
|
||||||
#include "settings/INISettingsObject.h"
|
#include "settings/INISettingsObject.h"
|
||||||
#include "minecraft/legacy/LegacyInstance.h"
|
|
||||||
#include "NullInstance.h"
|
#include "NullInstance.h"
|
||||||
#include "minecraft/MinecraftInstance.h"
|
#include "minecraft/MinecraftInstance.h"
|
||||||
#include "FileSystem.h"
|
#include "FileSystem.h"
|
||||||
@ -544,23 +543,8 @@ InstancePtr InstanceList::loadInstance(const InstanceId& id)
|
|||||||
auto instanceRoot = FS::PathCombine(m_instDir, id);
|
auto instanceRoot = FS::PathCombine(m_instDir, id);
|
||||||
auto instanceSettings = std::make_shared<INISettingsObject>(FS::PathCombine(instanceRoot, "instance.cfg"));
|
auto instanceSettings = std::make_shared<INISettingsObject>(FS::PathCombine(instanceRoot, "instance.cfg"));
|
||||||
InstancePtr inst;
|
InstancePtr inst;
|
||||||
|
// TODO: Handle incompatible instances
|
||||||
instanceSettings->registerSetting("InstanceType", "Legacy");
|
inst.reset(new MinecraftInstance(m_globalSettings, instanceSettings, instanceRoot));
|
||||||
|
|
||||||
QString inst_type = instanceSettings->get("InstanceType").toString();
|
|
||||||
|
|
||||||
if (inst_type == "OneSix" || inst_type == "Nostalgia")
|
|
||||||
{
|
|
||||||
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();
|
qDebug() << "Loaded instance " << inst->name() << " from " << inst->instanceRoot();
|
||||||
return inst;
|
return inst;
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "minecraft/MinecraftInstance.h"
|
#include "minecraft/MinecraftInstance.h"
|
||||||
#include "minecraft/legacy/LegacyInstance.h"
|
|
||||||
#include <FileSystem.h>
|
#include <FileSystem.h>
|
||||||
#include "ui/pages/BasePage.h"
|
#include "ui/pages/BasePage.h"
|
||||||
#include "ui/pages/BasePageProvider.h"
|
#include "ui/pages/BasePageProvider.h"
|
||||||
@ -14,7 +13,6 @@
|
|||||||
#include "ui/pages/instance/ScreenshotsPage.h"
|
#include "ui/pages/instance/ScreenshotsPage.h"
|
||||||
#include "ui/pages/instance/InstanceSettingsPage.h"
|
#include "ui/pages/instance/InstanceSettingsPage.h"
|
||||||
#include "ui/pages/instance/OtherLogsPage.h"
|
#include "ui/pages/instance/OtherLogsPage.h"
|
||||||
#include "ui/pages/instance/LegacyUpgradePage.h"
|
|
||||||
#include "ui/pages/instance/WorldListPage.h"
|
#include "ui/pages/instance/WorldListPage.h"
|
||||||
#include "ui/pages/instance/ServersPage.h"
|
#include "ui/pages/instance/ServersPage.h"
|
||||||
#include "ui/pages/instance/GameOptionsPage.h"
|
#include "ui/pages/instance/GameOptionsPage.h"
|
||||||
@ -34,31 +32,20 @@ public:
|
|||||||
QList<BasePage *> values;
|
QList<BasePage *> values;
|
||||||
values.append(new LogPage(inst));
|
values.append(new LogPage(inst));
|
||||||
std::shared_ptr<MinecraftInstance> onesix = std::dynamic_pointer_cast<MinecraftInstance>(inst);
|
std::shared_ptr<MinecraftInstance> onesix = std::dynamic_pointer_cast<MinecraftInstance>(inst);
|
||||||
if(onesix)
|
values.append(new VersionPage(onesix.get()));
|
||||||
{
|
auto modsPage = new ModFolderPage(onesix.get(), onesix->loaderModList(), "mods", "loadermods", tr("Mods"), "Loader-mods");
|
||||||
values.append(new VersionPage(onesix.get()));
|
modsPage->setFilter("%1 (*.zip *.jar *.litemod)");
|
||||||
auto modsPage = new ModFolderPage(onesix.get(), onesix->loaderModList(), "mods", "loadermods", tr("Loader mods"), "Loader-mods");
|
values.append(modsPage);
|
||||||
modsPage->setFilter("%1 (*.zip *.jar *.litemod)");
|
values.append(new CoreModFolderPage(onesix.get(), onesix->coreModList(), "coremods", "coremods", tr("Core mods"), "Core-mods"));
|
||||||
values.append(modsPage);
|
values.append(new ResourcePackPage(onesix.get()));
|
||||||
values.append(new CoreModFolderPage(onesix.get(), onesix->coreModList(), "coremods", "coremods", tr("Core mods"), "Core-mods"));
|
values.append(new TexturePackPage(onesix.get()));
|
||||||
values.append(new ResourcePackPage(onesix.get()));
|
values.append(new ShaderPackPage(onesix.get()));
|
||||||
values.append(new TexturePackPage(onesix.get()));
|
values.append(new NotesPage(onesix.get()));
|
||||||
values.append(new ShaderPackPage(onesix.get()));
|
values.append(new WorldListPage(onesix.get(), onesix->worldList()));
|
||||||
values.append(new NotesPage(onesix.get()));
|
values.append(new ServersPage(onesix));
|
||||||
values.append(new WorldListPage(onesix.get(), onesix->worldList()));
|
// values.append(new GameOptionsPage(onesix.get()));
|
||||||
values.append(new ServersPage(onesix));
|
values.append(new ScreenshotsPage(FS::PathCombine(onesix->gameRoot(), "screenshots")));
|
||||||
// values.append(new GameOptionsPage(onesix.get()));
|
values.append(new InstanceSettingsPage(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();
|
auto logMatcher = inst->getLogFileMatcher();
|
||||||
if(logMatcher)
|
if(logMatcher)
|
||||||
{
|
{
|
||||||
@ -74,3 +61,4 @@ public:
|
|||||||
protected:
|
protected:
|
||||||
InstancePtr inst;
|
InstancePtr inst;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@ bool JavaCommon::checkJVMArgs(QString jvmargs, QWidget *parent)
|
|||||||
|| jvmargs.contains("-XX-MaxHeapSize") || jvmargs.contains("-XX:InitialHeapSize"))
|
|| jvmargs.contains("-XX-MaxHeapSize") || jvmargs.contains("-XX:InitialHeapSize"))
|
||||||
{
|
{
|
||||||
auto warnStr = QObject::tr(
|
auto warnStr = QObject::tr(
|
||||||
"You tried to manually set a JVM memory option (using \"-XX:PermSize\", \"-XX-MaxHeapSize\", \"-XX:InitialHeapSize\", \"-Xmx\" or \"-Xms\").\n"
|
"You tried to manually set a JVM memory option (using \"-XX:PermSize\", \"-XX-MaxHeapSize\", \"-XX:InitialHeapSize\", \"-Xmx\" or \"-Xms\").\n"
|
||||||
"There are dedicated boxes for these in the settings (Java tab, in the Memory group at the top).\n"
|
"There are dedicated boxes for these in the settings (Java tab, in the Memory group at the top).\n"
|
||||||
"This message will be displayed until you remove them from the JVM arguments.");
|
"This message will be displayed until you remove them from the JVM arguments.");
|
||||||
CustomMessageBox::selectable(
|
CustomMessageBox::selectable(
|
||||||
@ -17,6 +17,17 @@ bool JavaCommon::checkJVMArgs(QString jvmargs, QWidget *parent)
|
|||||||
QMessageBox::Warning)->exec();
|
QMessageBox::Warning)->exec();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
// block lunacy with passing required version to the JVM
|
||||||
|
if (jvmargs.contains(QRegExp("-version:.*"))) {
|
||||||
|
auto warnStr = QObject::tr(
|
||||||
|
"You tried to pass required Java version argument to the JVM (using \"-version:xxx\"). This is not safe and will not be allowed.\n"
|
||||||
|
"This message will be displayed until you remove this from the JVM arguments.");
|
||||||
|
CustomMessageBox::selectable(
|
||||||
|
parent, QObject::tr("JVM arguments warning"),
|
||||||
|
warnStr,
|
||||||
|
QMessageBox::Warning)->exec();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -40,7 +51,7 @@ void JavaCommon::javaArgsWereBad(QWidget *parent, JavaCheckResult result)
|
|||||||
auto htmlError = result.errorLog;
|
auto htmlError = result.errorLog;
|
||||||
QString text;
|
QString text;
|
||||||
htmlError.replace('\n', "<br />");
|
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);
|
text += QString("<font color=\"red\">%1</font>").arg(htmlError);
|
||||||
CustomMessageBox::selectable(parent, QObject::tr("Java test failure"), text, QMessageBox::Warning)->show();
|
CustomMessageBox::selectable(parent, QObject::tr("Java test failure"), text, QMessageBox::Warning)->show();
|
||||||
}
|
}
|
||||||
@ -49,8 +60,8 @@ void JavaCommon::javaBinaryWasBad(QWidget *parent, JavaCheckResult result)
|
|||||||
{
|
{
|
||||||
QString text;
|
QString text;
|
||||||
text += QObject::tr(
|
text += QObject::tr(
|
||||||
"The specified java binary didn't work.<br />You should use the auto-detect feature, "
|
"The specified Java binary didn't work.<br />You should use the auto-detect feature, "
|
||||||
"or set the path to the java executable.<br />");
|
"or set the path to the Java executable.<br />");
|
||||||
CustomMessageBox::selectable(parent, QObject::tr("Java test failure"), text, QMessageBox::Warning)->show();
|
CustomMessageBox::selectable(parent, QObject::tr("Java test failure"), text, QMessageBox::Warning)->show();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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 "LaunchController.h"
|
||||||
#include "minecraft/auth/AccountList.h"
|
#include "minecraft/auth/AccountList.h"
|
||||||
#include "Application.h"
|
#include "Application.h"
|
||||||
@ -36,7 +71,10 @@ void LaunchController::executeTask()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
JavaCommon::checkJVMArgs(m_instance->settings()->get("JvmArgs").toString(), m_parentWidget);
|
if(!JavaCommon::checkJVMArgs(m_instance->settings()->get("JvmArgs").toString(), m_parentWidget)) {
|
||||||
|
emitFailed(tr("Invalid Java arguments specified. Please fix this first."));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
login();
|
login();
|
||||||
}
|
}
|
||||||
@ -56,7 +94,7 @@ void LaunchController::decideAccount()
|
|||||||
m_parentWidget,
|
m_parentWidget,
|
||||||
tr("No Accounts"),
|
tr("No Accounts"),
|
||||||
tr("In order to play Minecraft, you must have at least one Mojang or Minecraft "
|
tr("In order to play Minecraft, you must have at least one Mojang or Minecraft "
|
||||||
"account logged in."
|
"account logged in. "
|
||||||
"Would you like to open the account manager to add an account now?"),
|
"Would you like to open the account manager to add an account now?"),
|
||||||
QMessageBox::Information,
|
QMessageBox::Information,
|
||||||
QMessageBox::Yes | QMessageBox::No
|
QMessageBox::Yes | QMessageBox::No
|
||||||
@ -116,6 +154,12 @@ void LaunchController::login() {
|
|||||||
m_session->wants_online = m_online;
|
m_session->wants_online = m_online;
|
||||||
m_accountToUse->fillSession(m_session);
|
m_accountToUse->fillSession(m_session);
|
||||||
|
|
||||||
|
// Launch immediately in true offline mode
|
||||||
|
if(m_accountToUse->isOffline()) {
|
||||||
|
launchInstance();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
switch(m_accountToUse->accountState()) {
|
switch(m_accountToUse->accountState()) {
|
||||||
case AccountState::Offline: {
|
case AccountState::Offline: {
|
||||||
m_session->wants_online = false;
|
m_session->wants_online = false;
|
||||||
@ -125,13 +169,14 @@ void LaunchController::login() {
|
|||||||
if(!m_session->wants_online) {
|
if(!m_session->wants_online) {
|
||||||
// we ask the user for a player name
|
// we ask the user for a player name
|
||||||
bool ok = false;
|
bool ok = false;
|
||||||
QString usedname = m_session->player_name;
|
QString lastOfflinePlayerName = APPLICATION->settings()->get("LastOfflinePlayerName").toString();
|
||||||
|
QString usedname = lastOfflinePlayerName.isEmpty() ? m_session->player_name : lastOfflinePlayerName;
|
||||||
QString name = QInputDialog::getText(
|
QString name = QInputDialog::getText(
|
||||||
m_parentWidget,
|
m_parentWidget,
|
||||||
tr("Player name"),
|
tr("Player name"),
|
||||||
tr("Choose your offline mode player name."),
|
tr("Choose your offline mode player name."),
|
||||||
QLineEdit::Normal,
|
QLineEdit::Normal,
|
||||||
m_session->player_name,
|
usedname,
|
||||||
&ok
|
&ok
|
||||||
);
|
);
|
||||||
if (!ok)
|
if (!ok)
|
||||||
@ -142,6 +187,7 @@ void LaunchController::login() {
|
|||||||
if (name.length())
|
if (name.length())
|
||||||
{
|
{
|
||||||
usedname = name;
|
usedname = name;
|
||||||
|
APPLICATION->settings()->set("LastOfflinePlayerName", usedname);
|
||||||
}
|
}
|
||||||
m_session->MakeOffline(usedname);
|
m_session->MakeOffline(usedname);
|
||||||
// offline flavored game from here :3
|
// offline flavored game from here :3
|
||||||
@ -222,6 +268,18 @@ void LaunchController::login() {
|
|||||||
emitFailed(errorString);
|
emitFailed(errorString);
|
||||||
return;
|
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: {
|
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.");
|
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(
|
QMessageBox::warning(
|
||||||
|
@ -1,3 +1,38 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-3.0-only
|
||||||
|
/*
|
||||||
|
* PolyMC - Minecraft Launcher
|
||||||
|
* Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, version 3.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* This file incorporates work covered by the following copyright and
|
||||||
|
* permission notice:
|
||||||
|
*
|
||||||
|
* Copyright 2013-2021 MultiMC Contributors
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <BaseInstance.h>
|
#include <BaseInstance.h>
|
||||||
|
@ -14,14 +14,14 @@ if [[ $EUID -eq 0 ]]; then
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
||||||
LAUNCHER_NAME=@Launcher_Name@
|
LAUNCHER_NAME=@Launcher_APP_BINARY_NAME@
|
||||||
LAUNCHER_DIR="$(dirname "$(readlink -f "$0")")"
|
LAUNCHER_DIR="$(dirname "$(readlink -f "$0")")"
|
||||||
echo "Launcher Dir: ${LAUNCHER_DIR}"
|
echo "Launcher Dir: ${LAUNCHER_DIR}"
|
||||||
|
|
||||||
# Set up env - filter out input LD_ variables but pass them in under different names
|
# Set up env - filter out input LD_ variables but pass them in under different names
|
||||||
export GAME_LIBRARY_PATH=${GAME_LIBRARY_PATH-${LD_LIBRARY_PATH}}
|
export GAME_LIBRARY_PATH=${GAME_LIBRARY_PATH-${LD_LIBRARY_PATH}}
|
||||||
export GAME_PRELOAD=${GAME_PRELOAD-${LD_PRELOAD}}
|
export GAME_PRELOAD=${GAME_PRELOAD-${LD_PRELOAD}}
|
||||||
export LD_LIBRARY_PATH="${LAUNCHER_DIR}/bin":$LAUNCHER_LIBRARY_PATH
|
export LD_LIBRARY_PATH="${LAUNCHER_DIR}/lib@LIB_SUFFIX@":$LAUNCHER_LIBRARY_PATH
|
||||||
export LD_PRELOAD=$LAUNCHER_PRELOAD
|
export LD_PRELOAD=$LAUNCHER_PRELOAD
|
||||||
export QT_PLUGIN_PATH="${LAUNCHER_DIR}/plugins"
|
export QT_PLUGIN_PATH="${LAUNCHER_DIR}/plugins"
|
||||||
export QT_FONTPATH="${LAUNCHER_DIR}/fonts"
|
export QT_FONTPATH="${LAUNCHER_DIR}/fonts"
|
||||||
|
@ -1,29 +1,48 @@
|
|||||||
/* Copyright 2013-2021 MultiMC Contributors
|
// SPDX-License-Identifier: GPL-3.0-only
|
||||||
|
/*
|
||||||
|
* PolyMC - Minecraft Launcher
|
||||||
|
* Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net>
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* This program is free software: you can redistribute it and/or modify
|
||||||
* you may not use this file except in compliance with the License.
|
* it under the terms of the GNU General Public License as published by
|
||||||
* You may obtain a copy of the License at
|
* the Free Software Foundation, version 3.
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* 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.
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* You should have received a copy of the GNU General Public License
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
*
|
||||||
* See the License for the specific language governing permissions and
|
* This file incorporates work covered by the following copyright and
|
||||||
* limitations under the License.
|
* 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 <quazip.h>
|
#include <quazip/quazip.h>
|
||||||
#include <quazipdir.h>
|
#include <quazip/quazipdir.h>
|
||||||
#include <quazipfile.h>
|
#include <quazip/quazipfile.h>
|
||||||
#include <JlCompress.h>
|
|
||||||
#include "MMCZip.h"
|
#include "MMCZip.h"
|
||||||
#include "FileSystem.h"
|
#include "FileSystem.h"
|
||||||
|
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
|
|
||||||
// ours
|
// 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());
|
QuaZip modZip(from.filePath());
|
||||||
modZip.open(QuaZip::mdUnzip);
|
modZip.open(QuaZip::mdUnzip);
|
||||||
@ -74,6 +93,39 @@ bool MMCZip::mergeZipFiles(QuaZip *into, QFileInfo from, QSet<QString> &containe
|
|||||||
return true;
|
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
|
// ours
|
||||||
bool MMCZip::createModdedJar(QString sourceJarPath, QString targetJarPath, const QList<Mod>& mods)
|
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)
|
else if (mod.type() == Mod::MOD_FOLDER)
|
||||||
{
|
{
|
||||||
|
// untested, but seems to be unused / not possible to reach
|
||||||
// FIXME: buggy - does not work with addedFiles
|
// FIXME: buggy - does not work with addedFiles
|
||||||
auto filename = mod.filename();
|
auto filename = mod.filename();
|
||||||
QString what_to_zip = filename.absoluteFilePath();
|
QString what_to_zip = filename.absoluteFilePath();
|
||||||
QDir dir(what_to_zip);
|
QDir dir(what_to_zip);
|
||||||
dir.cdUp();
|
dir.cdUp();
|
||||||
QString parent_dir = dir.absolutePath();
|
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();
|
zipOut.close();
|
||||||
QFile::remove(targetJarPath);
|
QFile::remove(targetJarPath);
|
||||||
@ -136,7 +197,7 @@ bool MMCZip::createModdedJar(QString sourceJarPath, QString targetJarPath, const
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
qDebug() << "Adding folder " << filename.fileName() << " from "
|
qDebug() << "Adding folder " << filename.fileName() << " from "
|
||||||
<< filename.absoluteFilePath();
|
<< filename.absoluteFilePath();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -310,3 +371,37 @@ bool MMCZip::extractFile(QString fileCompressed, QString file, QString target)
|
|||||||
}
|
}
|
||||||
return MMCZip::extractRelFile(&zip, file, 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;
|
||||||
|
}
|
||||||
|
@ -1,16 +1,36 @@
|
|||||||
/* Copyright 2013-2021 MultiMC Contributors
|
// SPDX-License-Identifier: GPL-3.0-only
|
||||||
|
/*
|
||||||
|
* PolyMC - Minecraft Launcher
|
||||||
|
* Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net>
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* This program is free software: you can redistribute it and/or modify
|
||||||
* you may not use this file except in compliance with the License.
|
* it under the terms of the GNU General Public License as published by
|
||||||
* You may obtain a copy of the License at
|
* the Free Software Foundation, version 3.
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* 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.
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* You should have received a copy of the GNU General Public License
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
*
|
||||||
* See the License for the specific language governing permissions and
|
* This file incorporates work covered by the following copyright and
|
||||||
* limitations under the License.
|
* permission notice:
|
||||||
|
*
|
||||||
|
* Copyright 2013-2021 MultiMC Contributors
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
@ -21,17 +41,36 @@
|
|||||||
#include "minecraft/mod/Mod.h"
|
#include "minecraft/mod/Mod.h"
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
|
||||||
#include <JlCompress.h>
|
#include <quazip/JlCompress.h>
|
||||||
#include <nonstd/optional>
|
#include <nonstd/optional>
|
||||||
|
|
||||||
namespace MMCZip
|
namespace MMCZip
|
||||||
{
|
{
|
||||||
|
using FilterFunction = std::function<bool(const QString &)>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Merge two zip files, using a filter function
|
* Merge two zip files, using a filter function
|
||||||
*/
|
*/
|
||||||
bool mergeZipFiles(QuaZip *into, QFileInfo from, QSet<QString> &contained,
|
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
|
* 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);
|
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);
|
||||||
}
|
}
|
||||||
|
39
launcher/ModDownloadTask.cpp
Normal file
39
launcher/ModDownloadTask.cpp
Normal 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();
|
||||||
|
}
|
||||||
|
|
35
launcher/ModDownloadTask.h
Normal file
35
launcher/ModDownloadTask.h
Normal 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();
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -93,7 +93,7 @@ void UpdateController::installUpdates()
|
|||||||
qDebug() << "Installing updates.";
|
qDebug() << "Installing updates.";
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
QString finishCmd = QApplication::applicationFilePath();
|
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);
|
QString finishCmd = FS::PathCombine(m_root, BuildConfig.LAUNCHER_NAME);
|
||||||
#elif defined Q_OS_MAC
|
#elif defined Q_OS_MAC
|
||||||
QString finishCmd = QApplication::applicationFilePath();
|
QString finishCmd = QApplication::applicationFilePath();
|
||||||
|
@ -103,11 +103,15 @@ void JavaChecker::finished(int exitcode, QProcess::ExitStatus status)
|
|||||||
for(QString line : lines)
|
for(QString line : lines)
|
||||||
{
|
{
|
||||||
line = line.trimmed();
|
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);
|
auto parts = line.split('=', QString::SkipEmptyParts);
|
||||||
if(parts.size() != 2 || parts[0].isEmpty() || parts[1].isEmpty())
|
if(parts.size() != 2 || parts[0].isEmpty() || parts[1].isEmpty())
|
||||||
{
|
{
|
||||||
success = false;
|
continue;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -125,7 +129,7 @@ void JavaChecker::finished(int exitcode, QProcess::ExitStatus status)
|
|||||||
auto os_arch = results["os.arch"];
|
auto os_arch = results["os.arch"];
|
||||||
auto java_version = results["java.version"];
|
auto java_version = results["java.version"];
|
||||||
auto java_vendor = results["java.vendor"];
|
auto java_vendor = results["java.vendor"];
|
||||||
bool is_64 = os_arch == "x86_64" || os_arch == "amd64";
|
bool is_64 = os_arch == "x86_64" || os_arch == "amd64" || os_arch == "aarch64" || os_arch == "arm64";
|
||||||
|
|
||||||
|
|
||||||
result.validity = JavaCheckResult::Validity::Valid;
|
result.validity = JavaCheckResult::Validity::Valid;
|
||||||
|
@ -120,8 +120,8 @@ void JavaInstallList::updateListData(QList<BaseVersionPtr> versions)
|
|||||||
|
|
||||||
bool sortJavas(BaseVersionPtr left, BaseVersionPtr right)
|
bool sortJavas(BaseVersionPtr left, BaseVersionPtr right)
|
||||||
{
|
{
|
||||||
auto rleft = std::dynamic_pointer_cast<JavaInstall>(left);
|
auto rleft = std::dynamic_pointer_cast<JavaInstall>(right);
|
||||||
auto rright = std::dynamic_pointer_cast<JavaInstall>(right);
|
auto rright = std::dynamic_pointer_cast<JavaInstall>(left);
|
||||||
return (*rleft) > (*rright);
|
return (*rleft) > (*rright);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -183,7 +183,7 @@ void JavaListLoadTask::javaCheckerFinished()
|
|||||||
JavaInstallPtr javaVersion(new JavaInstall());
|
JavaInstallPtr javaVersion(new JavaInstall());
|
||||||
|
|
||||||
javaVersion->id = result.javaVersion;
|
javaVersion->id = result.javaVersion;
|
||||||
javaVersion->arch = result.mojangPlatform;
|
javaVersion->arch = result.realPlatform;
|
||||||
javaVersion->path = result.path;
|
javaVersion->path = result.path;
|
||||||
candidates.append(javaVersion);
|
candidates.append(javaVersion);
|
||||||
|
|
||||||
|
@ -77,14 +77,14 @@ QProcessEnvironment CleanEnviroment()
|
|||||||
qDebug() << "Env: ignoring" << key << value;
|
qDebug() << "Env: ignoring" << key << value;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// filter MultiMC-related things
|
// filter PolyMC-related things
|
||||||
if(key.startsWith("QT_"))
|
if(key.startsWith("QT_"))
|
||||||
{
|
{
|
||||||
qDebug() << "Env: ignoring" << key << value;
|
qDebug() << "Env: ignoring" << key << value;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
#if defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD)
|
#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_"))
|
if(key.startsWith("LD_"))
|
||||||
{
|
{
|
||||||
qDebug() << "Env: ignoring" << key << value;
|
qDebug() << "Env: ignoring" << key << value;
|
||||||
@ -149,6 +149,21 @@ JavaInstallPtr JavaUtils::GetDefaultJava()
|
|||||||
return javaVersion;
|
return javaVersion;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QStringList addJavasFromEnv(QList<QString> javas)
|
||||||
|
{
|
||||||
|
QByteArray env = qgetenv("POLYMC_JAVA_PATHS");
|
||||||
|
#if defined(Q_OS_WIN32)
|
||||||
|
QList<QString> javaPaths = QString::fromLocal8Bit(env).replace("\\", "/").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)
|
#if defined(Q_OS_WIN32)
|
||||||
QList<JavaInstallPtr> JavaUtils::FindJavaFromRegistryKey(DWORD keyType, QString keyName, QString keyJavaDir, QString subkeySuffix)
|
QList<JavaInstallPtr> JavaUtils::FindJavaFromRegistryKey(DWORD keyType, QString keyName, QString keyJavaDir, QString subkeySuffix)
|
||||||
{
|
{
|
||||||
@ -290,7 +305,7 @@ QList<QString> JavaUtils::FindJavaPaths()
|
|||||||
KEY_WOW64_64KEY, "SOFTWARE\\Azul Systems\\Zulu", "InstallationPath");
|
KEY_WOW64_64KEY, "SOFTWARE\\Azul Systems\\Zulu", "InstallationPath");
|
||||||
QList<JavaInstallPtr> ZULU32s = this->FindJavaFromRegistryKey(
|
QList<JavaInstallPtr> ZULU32s = this->FindJavaFromRegistryKey(
|
||||||
KEY_WOW64_32KEY, "SOFTWARE\\Azul Systems\\Zulu", "InstallationPath");
|
KEY_WOW64_32KEY, "SOFTWARE\\Azul Systems\\Zulu", "InstallationPath");
|
||||||
|
|
||||||
// BellSoft Liberica
|
// BellSoft Liberica
|
||||||
QList<JavaInstallPtr> LIBERICA64s = this->FindJavaFromRegistryKey(
|
QList<JavaInstallPtr> LIBERICA64s = this->FindJavaFromRegistryKey(
|
||||||
KEY_WOW64_64KEY, "SOFTWARE\\BellSoft\\Liberica", "InstallationPath");
|
KEY_WOW64_64KEY, "SOFTWARE\\BellSoft\\Liberica", "InstallationPath");
|
||||||
@ -328,7 +343,7 @@ QList<QString> JavaUtils::FindJavaPaths()
|
|||||||
java_candidates.append(ADOPTIUMJDK32s);
|
java_candidates.append(ADOPTIUMJDK32s);
|
||||||
java_candidates.append(ZULU32s);
|
java_candidates.append(ZULU32s);
|
||||||
java_candidates.append(LIBERICA32s);
|
java_candidates.append(LIBERICA32s);
|
||||||
|
|
||||||
java_candidates.append(MakeJavaPtr(this->GetDefaultJava()->path));
|
java_candidates.append(MakeJavaPtr(this->GetDefaultJava()->path));
|
||||||
|
|
||||||
QList<QString> candidates;
|
QList<QString> candidates;
|
||||||
@ -340,7 +355,7 @@ QList<QString> JavaUtils::FindJavaPaths()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return candidates;
|
return addJavasFromEnv(candidates);
|
||||||
}
|
}
|
||||||
|
|
||||||
#elif defined(Q_OS_MAC)
|
#elif defined(Q_OS_MAC)
|
||||||
@ -363,7 +378,7 @@ QList<QString> JavaUtils::FindJavaPaths()
|
|||||||
javas.append(systemLibraryJVMDir.absolutePath() + "/" + java + "/Contents/Home/bin/java");
|
javas.append(systemLibraryJVMDir.absolutePath() + "/" + java + "/Contents/Home/bin/java");
|
||||||
javas.append(systemLibraryJVMDir.absolutePath() + "/" + java + "/Contents/Commands/java");
|
javas.append(systemLibraryJVMDir.absolutePath() + "/" + java + "/Contents/Commands/java");
|
||||||
}
|
}
|
||||||
return javas;
|
return addJavasFromEnv(javas);
|
||||||
}
|
}
|
||||||
|
|
||||||
#elif defined(Q_OS_LINUX)
|
#elif defined(Q_OS_LINUX)
|
||||||
@ -402,14 +417,14 @@ QList<QString> JavaUtils::FindJavaPaths()
|
|||||||
scanJavaDir("/usr/lib/jvm");
|
scanJavaDir("/usr/lib/jvm");
|
||||||
scanJavaDir("/usr/lib64/jvm");
|
scanJavaDir("/usr/lib64/jvm");
|
||||||
scanJavaDir("/usr/lib32/jvm");
|
scanJavaDir("/usr/lib32/jvm");
|
||||||
// javas stored in MultiMC's folder
|
// javas stored in PolyMC's folder
|
||||||
scanJavaDir("java");
|
scanJavaDir("java");
|
||||||
// manually installed JDKs in /opt
|
// manually installed JDKs in /opt
|
||||||
scanJavaDir("/opt/jdk");
|
scanJavaDir("/opt/jdk");
|
||||||
scanJavaDir("/opt/jdks");
|
scanJavaDir("/opt/jdks");
|
||||||
// flatpak
|
// flatpak
|
||||||
scanJavaDir("/app/jdk");
|
scanJavaDir("/app/jdk");
|
||||||
return javas;
|
return addJavasFromEnv(javas);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
QList<QString> JavaUtils::FindJavaPaths()
|
QList<QString> JavaUtils::FindJavaPaths()
|
||||||
@ -419,6 +434,6 @@ QList<QString> JavaUtils::FindJavaPaths()
|
|||||||
QList<QString> javas;
|
QList<QString> javas;
|
||||||
javas.append(this->GetDefaultJava()->path);
|
javas.append(this->GetDefaultJava()->path);
|
||||||
|
|
||||||
return javas;
|
return addJavasFromEnv(javas);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -1,18 +1,38 @@
|
|||||||
/* Copyright 2013-2021 MultiMC Contributors
|
// SPDX-License-Identifier: GPL-3.0-only
|
||||||
|
/*
|
||||||
|
* PolyMC - Minecraft Launcher
|
||||||
|
* Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net>
|
||||||
*
|
*
|
||||||
* Authors: Orochimarufan <orochimarufan.x3@gmail.com>
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, version 3.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* This program is distributed in the hope that it will be useful,
|
||||||
* you may not use this file except in compliance with the License.
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* You may obtain a copy of the License at
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* This file incorporates work covered by the following copyright and
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* permission notice:
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
*
|
||||||
* See the License for the specific language governing permissions and
|
* Copyright 2013-2021 MultiMC Contributors
|
||||||
* limitations under the License.
|
*
|
||||||
|
* Authors: Orochimarufan <orochimarufan.x3@gmail.com>
|
||||||
|
*
|
||||||
|
* 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 "launch/LaunchTask.h"
|
#include "launch/LaunchTask.h"
|
||||||
@ -212,7 +232,7 @@ shared_qobject_ptr<LogModel> LaunchTask::getLogModel()
|
|||||||
m_logModel->setMaxLines(m_instance->getConsoleMaxLines());
|
m_logModel->setMaxLines(m_instance->getConsoleMaxLines());
|
||||||
m_logModel->setStopOnOverflow(m_instance->shouldStopOnConsoleOverflow());
|
m_logModel->setStopOnOverflow(m_instance->shouldStopOnConsoleOverflow());
|
||||||
// FIXME: should this really be here?
|
// 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("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"
|
"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()));
|
" likely wasting harddrive space at an alarming rate!").arg(m_logModel->getMaxLines()));
|
||||||
}
|
}
|
||||||
@ -277,4 +297,3 @@ QString LaunchTask::substituteVariables(const QString &cmd) const
|
|||||||
}
|
}
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,16 +1,36 @@
|
|||||||
/* Copyright 2013-2021 MultiMC Contributors
|
// SPDX-License-Identifier: GPL-3.0-only
|
||||||
|
/*
|
||||||
|
* PolyMC - Minecraft Launcher
|
||||||
|
* Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net>
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* This program is free software: you can redistribute it and/or modify
|
||||||
* you may not use this file except in compliance with the License.
|
* it under the terms of the GNU General Public License as published by
|
||||||
* You may obtain a copy of the License at
|
* the Free Software Foundation, version 3.
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* 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.
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* You should have received a copy of the GNU General Public License
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
*
|
||||||
* See the License for the specific language governing permissions and
|
* This file incorporates work covered by the following copyright and
|
||||||
* limitations under the License.
|
* 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 "CheckJava.h"
|
#include "CheckJava.h"
|
||||||
@ -87,14 +107,14 @@ void CheckJava::checkJavaFinished(JavaCheckResult result)
|
|||||||
// Error message displayed if java can't start
|
// Error message displayed if java can't start
|
||||||
emit logLine(QString("Could not start java:"), MessageLevel::Error);
|
emit logLine(QString("Could not start java:"), MessageLevel::Error);
|
||||||
emit logLines(result.errorLog.split('\n'), MessageLevel::Error);
|
emit logLines(result.errorLog.split('\n'), MessageLevel::Error);
|
||||||
emit logLine("\nCheck your MultiMC Java settings.", MessageLevel::Launcher);
|
emit logLine(QString("\nCheck your Java settings."), MessageLevel::Launcher);
|
||||||
printSystemInfo(false, false);
|
printSystemInfo(false, false);
|
||||||
emitFailed(QString("Could not start java!"));
|
emitFailed(QString("Could not start java!"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
case JavaCheckResult::Validity::ReturnedInvalidData:
|
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 we don't understand:"), MessageLevel::Error);
|
||||||
emit logLines(result.outLog.split('\n'), MessageLevel::Warning);
|
emit logLines(result.outLog.split('\n'), MessageLevel::Warning);
|
||||||
emit logLine("\nMinecraft might not start properly.", MessageLevel::Launcher);
|
emit logLine("\nMinecraft might not start properly.", MessageLevel::Launcher);
|
||||||
printSystemInfo(false, false);
|
printSystemInfo(false, false);
|
||||||
@ -104,7 +124,8 @@ void CheckJava::checkJavaFinished(JavaCheckResult result)
|
|||||||
case JavaCheckResult::Validity::Valid:
|
case JavaCheckResult::Validity::Valid:
|
||||||
{
|
{
|
||||||
auto instance = m_parent->instance();
|
auto instance = m_parent->instance();
|
||||||
printJavaInfo(result.javaVersion.toString(), result.mojangPlatform, result.javaVendor);
|
printJavaInfo(result.javaVersion.toString(), result.realPlatform, result.javaVendor);
|
||||||
|
printSystemInfo(true, result.is_64bit);
|
||||||
instance->settings()->set("JavaVersion", result.javaVersion.toString());
|
instance->settings()->set("JavaVersion", result.javaVersion.toString());
|
||||||
instance->settings()->set("JavaArchitecture", result.mojangPlatform);
|
instance->settings()->set("JavaArchitecture", result.mojangPlatform);
|
||||||
instance->settings()->set("JavaVendor", result.javaVendor);
|
instance->settings()->set("JavaVendor", result.javaVendor);
|
||||||
@ -117,8 +138,7 @@ void CheckJava::checkJavaFinished(JavaCheckResult result)
|
|||||||
|
|
||||||
void CheckJava::printJavaInfo(const QString& version, const QString& architecture, const QString & vendor)
|
void CheckJava::printJavaInfo(const QString& version, const QString& architecture, const QString & vendor)
|
||||||
{
|
{
|
||||||
emit logLine(QString("Java is version %1, using %2-bit architecture, from %3.\n\n").arg(version, architecture, vendor), MessageLevel::Launcher);
|
emit logLine(QString("Java is version %1, using %2 architecture, from %3.\n\n").arg(version, architecture, vendor), MessageLevel::Launcher);
|
||||||
printSystemInfo(true, architecture == "64");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CheckJava::printSystemInfo(bool javaIsKnown, bool javaIs64bit)
|
void CheckJava::printSystemInfo(bool javaIsKnown, bool javaIs64bit)
|
||||||
|
26
launcher/launch/steps/QuitAfterGameStop.cpp
Normal file
26
launcher/launch/steps/QuitAfterGameStop.cpp
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-3.0-only
|
||||||
|
/*
|
||||||
|
* PolyMC - Minecraft Launcher
|
||||||
|
* Copyright (C) 2022 dada513 <dada513@protonmail.com>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, version 3.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "QuitAfterGameStop.h"
|
||||||
|
#include <launch/LaunchTask.h>
|
||||||
|
#include "Application.h"
|
||||||
|
|
||||||
|
void QuitAfterGameStop::executeTask()
|
||||||
|
{
|
||||||
|
APPLICATION->quit();
|
||||||
|
}
|
35
launcher/launch/steps/QuitAfterGameStop.h
Normal file
35
launcher/launch/steps/QuitAfterGameStop.h
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-3.0-only
|
||||||
|
/*
|
||||||
|
* PolyMC - Minecraft Launcher
|
||||||
|
* Copyright (C) 2022 dada513 <dada513@protonmail.com>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, version 3.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <launch/LaunchStep.h>
|
||||||
|
|
||||||
|
class QuitAfterGameStop: public LaunchStep
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit QuitAfterGameStop(LaunchTask *parent) :LaunchStep(parent){};
|
||||||
|
virtual ~QuitAfterGameStop() {};
|
||||||
|
|
||||||
|
virtual void executeTask();
|
||||||
|
virtual bool canAbort() const
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
@ -29,6 +29,10 @@ int main(int argc, char *argv[])
|
|||||||
QGuiApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);
|
QGuiApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0))
|
||||||
|
QApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::PassThrough);
|
||||||
|
#endif
|
||||||
|
|
||||||
// initialize Qt
|
// initialize Qt
|
||||||
Application app(argc, argv);
|
Application app(argc, argv);
|
||||||
|
|
||||||
|
36
launcher/minecraft/Agent.h
Normal file
36
launcher/minecraft/Agent.h
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QString>
|
||||||
|
|
||||||
|
#include "Library.h"
|
||||||
|
|
||||||
|
class Agent;
|
||||||
|
|
||||||
|
typedef std::shared_ptr<Agent> AgentPtr;
|
||||||
|
|
||||||
|
class Agent {
|
||||||
|
public:
|
||||||
|
Agent(LibraryPtr library, QString &argument)
|
||||||
|
{
|
||||||
|
m_library = library;
|
||||||
|
m_argument = argument;
|
||||||
|
}
|
||||||
|
|
||||||
|
public: /* methods */
|
||||||
|
|
||||||
|
LibraryPtr library() {
|
||||||
|
return m_library;
|
||||||
|
}
|
||||||
|
QString argument() {
|
||||||
|
return m_argument;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected: /* data */
|
||||||
|
|
||||||
|
/// The library pointing to the jar this Java agent is contained within
|
||||||
|
LibraryPtr m_library;
|
||||||
|
|
||||||
|
/// The argument to the Java agent, passed after an = if present
|
||||||
|
QString m_argument;
|
||||||
|
|
||||||
|
};
|
@ -591,7 +591,7 @@ void ComponentUpdateTask::resolveDependencies(bool checkOnly)
|
|||||||
{
|
{
|
||||||
component->m_version = "3.1.2";
|
component->m_version = "3.1.2";
|
||||||
}
|
}
|
||||||
else if (add.uid == "net.fabricmc.intermediary")
|
else if (add.uid == "net.fabricmc.intermediary" || add.uid == "org.quiltmc.hashed")
|
||||||
{
|
{
|
||||||
auto minecraft = std::find_if(components.begin(), components.end(), [](ComponentPtr & cmp){
|
auto minecraft = std::find_if(components.begin(), components.end(), [](ComponentPtr & cmp){
|
||||||
return cmp->getID() == "net.minecraft";
|
return cmp->getID() == "net.minecraft";
|
||||||
|
@ -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 "LaunchProfile.h"
|
#include "LaunchProfile.h"
|
||||||
#include <Version.h>
|
#include <Version.h>
|
||||||
|
|
||||||
@ -7,11 +42,13 @@ void LaunchProfile::clear()
|
|||||||
m_minecraftVersionType.clear();
|
m_minecraftVersionType.clear();
|
||||||
m_minecraftAssets.reset();
|
m_minecraftAssets.reset();
|
||||||
m_minecraftArguments.clear();
|
m_minecraftArguments.clear();
|
||||||
|
m_addnJvmArguments.clear();
|
||||||
m_tweakers.clear();
|
m_tweakers.clear();
|
||||||
m_mainClass.clear();
|
m_mainClass.clear();
|
||||||
m_appletClass.clear();
|
m_appletClass.clear();
|
||||||
m_libraries.clear();
|
m_libraries.clear();
|
||||||
m_mavenFiles.clear();
|
m_mavenFiles.clear();
|
||||||
|
m_agents.clear();
|
||||||
m_traits.clear();
|
m_traits.clear();
|
||||||
m_jarMods.clear();
|
m_jarMods.clear();
|
||||||
m_mainJar.reset();
|
m_mainJar.reset();
|
||||||
@ -45,6 +82,11 @@ void LaunchProfile::applyMinecraftArguments(const QString& minecraftArguments)
|
|||||||
applyString(minecraftArguments, this->m_minecraftArguments);
|
applyString(minecraftArguments, this->m_minecraftArguments);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void LaunchProfile::applyAddnJvmArguments(const QStringList& addnJvmArguments)
|
||||||
|
{
|
||||||
|
this->m_addnJvmArguments.append(addnJvmArguments);
|
||||||
|
}
|
||||||
|
|
||||||
void LaunchProfile::applyMinecraftVersionType(const QString& type)
|
void LaunchProfile::applyMinecraftVersionType(const QString& type)
|
||||||
{
|
{
|
||||||
applyString(type, this->m_minecraftVersionType);
|
applyString(type, this->m_minecraftVersionType);
|
||||||
@ -126,6 +168,11 @@ void LaunchProfile::applyMods(const QList<LibraryPtr>& mods)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void LaunchProfile::applyCompatibleJavaMajors(QList<int>& javaMajor)
|
||||||
|
{
|
||||||
|
m_compatibleJavaMajors.append(javaMajor);
|
||||||
|
}
|
||||||
|
|
||||||
void LaunchProfile::applyLibrary(LibraryPtr library)
|
void LaunchProfile::applyLibrary(LibraryPtr library)
|
||||||
{
|
{
|
||||||
if(!library->isActive())
|
if(!library->isActive())
|
||||||
@ -174,6 +221,22 @@ void LaunchProfile::applyMavenFile(LibraryPtr mavenFile)
|
|||||||
m_mavenFiles.append(Library::limitedCopy(mavenFile));
|
m_mavenFiles.append(Library::limitedCopy(mavenFile));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void LaunchProfile::applyAgent(AgentPtr agent)
|
||||||
|
{
|
||||||
|
auto lib = agent->library();
|
||||||
|
if(!lib->isActive())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(lib->isNative())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_agents.append(agent);
|
||||||
|
}
|
||||||
|
|
||||||
const LibraryPtr LaunchProfile::getMainJar() const
|
const LibraryPtr LaunchProfile::getMainJar() const
|
||||||
{
|
{
|
||||||
return m_mainJar;
|
return m_mainJar;
|
||||||
@ -255,6 +318,11 @@ QString LaunchProfile::getMinecraftArguments() const
|
|||||||
return m_minecraftArguments;
|
return m_minecraftArguments;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const QStringList & LaunchProfile::getAddnJvmArguments() const
|
||||||
|
{
|
||||||
|
return m_addnJvmArguments;
|
||||||
|
}
|
||||||
|
|
||||||
const QList<LibraryPtr> & LaunchProfile::getJarMods() const
|
const QList<LibraryPtr> & LaunchProfile::getJarMods() const
|
||||||
{
|
{
|
||||||
return m_jarMods;
|
return m_jarMods;
|
||||||
@ -275,6 +343,16 @@ const QList<LibraryPtr> & LaunchProfile::getMavenFiles() const
|
|||||||
return m_mavenFiles;
|
return m_mavenFiles;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const QList<AgentPtr> & LaunchProfile::getAgents() const
|
||||||
|
{
|
||||||
|
return m_agents;
|
||||||
|
}
|
||||||
|
|
||||||
|
const QList<int> & LaunchProfile::getCompatibleJavaMajors() const
|
||||||
|
{
|
||||||
|
return m_compatibleJavaMajors;
|
||||||
|
}
|
||||||
|
|
||||||
void LaunchProfile::getLibraryFiles(
|
void LaunchProfile::getLibraryFiles(
|
||||||
const QString& architecture,
|
const QString& architecture,
|
||||||
QStringList& jars,
|
QStringList& jars,
|
||||||
|
@ -1,6 +1,42 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-3.0-only
|
||||||
|
/*
|
||||||
|
* PolyMC - Minecraft Launcher
|
||||||
|
* Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, version 3.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* This file incorporates work covered by the following copyright and
|
||||||
|
* permission notice:
|
||||||
|
*
|
||||||
|
* Copyright 2013-2021 MultiMC Contributors
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <QString>
|
#include <QString>
|
||||||
#include "Library.h"
|
#include "Library.h"
|
||||||
|
#include "Agent.h"
|
||||||
#include <ProblemProvider.h>
|
#include <ProblemProvider.h>
|
||||||
|
|
||||||
class LaunchProfile: public ProblemProvider
|
class LaunchProfile: public ProblemProvider
|
||||||
@ -13,6 +49,7 @@ public: /* application of profile variables from patches */
|
|||||||
void applyMainClass(const QString& mainClass);
|
void applyMainClass(const QString& mainClass);
|
||||||
void applyAppletClass(const QString& appletClass);
|
void applyAppletClass(const QString& appletClass);
|
||||||
void applyMinecraftArguments(const QString& minecraftArguments);
|
void applyMinecraftArguments(const QString& minecraftArguments);
|
||||||
|
void applyAddnJvmArguments(const QStringList& minecraftArguments);
|
||||||
void applyMinecraftVersionType(const QString& type);
|
void applyMinecraftVersionType(const QString& type);
|
||||||
void applyMinecraftAssets(MojangAssetIndexInfo::Ptr assets);
|
void applyMinecraftAssets(MojangAssetIndexInfo::Ptr assets);
|
||||||
void applyTraits(const QSet<QString> &traits);
|
void applyTraits(const QSet<QString> &traits);
|
||||||
@ -21,6 +58,8 @@ public: /* application of profile variables from patches */
|
|||||||
void applyMods(const QList<LibraryPtr> &jarMods);
|
void applyMods(const QList<LibraryPtr> &jarMods);
|
||||||
void applyLibrary(LibraryPtr library);
|
void applyLibrary(LibraryPtr library);
|
||||||
void applyMavenFile(LibraryPtr library);
|
void applyMavenFile(LibraryPtr library);
|
||||||
|
void applyAgent(AgentPtr agent);
|
||||||
|
void applyCompatibleJavaMajors(QList<int>& javaMajor);
|
||||||
void applyMainJar(LibraryPtr jar);
|
void applyMainJar(LibraryPtr jar);
|
||||||
void applyProblemSeverity(ProblemSeverity severity);
|
void applyProblemSeverity(ProblemSeverity severity);
|
||||||
/// clear the profile
|
/// clear the profile
|
||||||
@ -33,12 +72,15 @@ public: /* getters for profile variables */
|
|||||||
QString getMinecraftVersionType() const;
|
QString getMinecraftVersionType() const;
|
||||||
MojangAssetIndexInfo::Ptr getMinecraftAssets() const;
|
MojangAssetIndexInfo::Ptr getMinecraftAssets() const;
|
||||||
QString getMinecraftArguments() const;
|
QString getMinecraftArguments() const;
|
||||||
|
const QStringList & getAddnJvmArguments() const;
|
||||||
const QSet<QString> & getTraits() const;
|
const QSet<QString> & getTraits() const;
|
||||||
const QStringList & getTweakers() const;
|
const QStringList & getTweakers() const;
|
||||||
const QList<LibraryPtr> & getJarMods() const;
|
const QList<LibraryPtr> & getJarMods() const;
|
||||||
const QList<LibraryPtr> & getLibraries() const;
|
const QList<LibraryPtr> & getLibraries() const;
|
||||||
const QList<LibraryPtr> & getNativeLibraries() const;
|
const QList<LibraryPtr> & getNativeLibraries() const;
|
||||||
const QList<LibraryPtr> & getMavenFiles() const;
|
const QList<LibraryPtr> & getMavenFiles() const;
|
||||||
|
const QList<AgentPtr> & getAgents() const;
|
||||||
|
const QList<int> & getCompatibleJavaMajors() const;
|
||||||
const LibraryPtr getMainJar() const;
|
const LibraryPtr getMainJar() const;
|
||||||
void getLibraryFiles(
|
void getLibraryFiles(
|
||||||
const QString & architecture,
|
const QString & architecture,
|
||||||
@ -69,6 +111,12 @@ private:
|
|||||||
*/
|
*/
|
||||||
QString m_minecraftArguments;
|
QString m_minecraftArguments;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Additional arguments to pass to the JVM in addition to those the user has configured,
|
||||||
|
* memory settings, etc.
|
||||||
|
*/
|
||||||
|
QStringList m_addnJvmArguments;
|
||||||
|
|
||||||
/// A list of all tweaker classes
|
/// A list of all tweaker classes
|
||||||
QStringList m_tweakers;
|
QStringList m_tweakers;
|
||||||
|
|
||||||
@ -84,6 +132,9 @@ private:
|
|||||||
/// the list of maven files to be placed in the libraries folder, but not acted upon
|
/// the list of maven files to be placed in the libraries folder, but not acted upon
|
||||||
QList<LibraryPtr> m_mavenFiles;
|
QList<LibraryPtr> m_mavenFiles;
|
||||||
|
|
||||||
|
/// the list of java agents to add to JVM arguments
|
||||||
|
QList<AgentPtr> m_agents;
|
||||||
|
|
||||||
/// the main jar
|
/// the main jar
|
||||||
LibraryPtr m_mainJar;
|
LibraryPtr m_mainJar;
|
||||||
|
|
||||||
@ -99,6 +150,9 @@ private:
|
|||||||
/// the list of mods
|
/// the list of mods
|
||||||
QList<LibraryPtr> m_mods;
|
QList<LibraryPtr> m_mods;
|
||||||
|
|
||||||
|
/// compatible java major versions
|
||||||
|
QList<int> m_compatibleJavaMajors;
|
||||||
|
|
||||||
ProblemSeverity m_problemSeverity = ProblemSeverity::None;
|
ProblemSeverity m_problemSeverity = ProblemSeverity::None;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
@ -156,7 +156,7 @@ public: /* methods */
|
|||||||
QStringList & failedLocalFiles, const QString & overridePath) const;
|
QStringList & failedLocalFiles, const QString & overridePath) const;
|
||||||
|
|
||||||
private: /* methods */
|
private: /* methods */
|
||||||
/// the default storage prefix used by MultiMC
|
/// the default storage prefix used by PolyMC
|
||||||
static QString defaultStoragePrefix();
|
static QString defaultStoragePrefix();
|
||||||
|
|
||||||
/// Get the prefix - root of the storage to be used
|
/// 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
|
/// DEPRECATED URL prefix of the maven repo where the file can be downloaded
|
||||||
QString m_repositoryURL;
|
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;
|
QString m_absoluteURL;
|
||||||
|
|
||||||
/// MultiMC extension - filename override
|
/// PolyMC extension - filename override
|
||||||
QString m_filename;
|
QString m_filename;
|
||||||
|
|
||||||
/// DEPRECATED MultiMC extension - display name
|
/// DEPRECATED PolyMC extension - display name
|
||||||
QString m_displayname;
|
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;
|
QString m_hint;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* storage - by default the local libraries folder in multimc, but could be elsewhere
|
* storage - by default the local libraries folder in polymc, but could be elsewhere
|
||||||
* MultiMC specific, because of FTB.
|
* PolyMC specific, because of FTB.
|
||||||
*/
|
*/
|
||||||
QString m_storagePrefix;
|
QString m_storagePrefix;
|
||||||
|
|
||||||
@ -215,3 +215,4 @@ protected: /* data */
|
|||||||
/// MOJANG: container with Mojang style download info
|
/// MOJANG: container with Mojang style download info
|
||||||
MojangLibraryDownloadInfo::Ptr m_mojangDownloads;
|
MojangLibraryDownloadInfo::Ptr m_mojangDownloads;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,4 +1,40 @@
|
|||||||
|
// 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 "MinecraftInstance.h"
|
#include "MinecraftInstance.h"
|
||||||
|
#include "BuildConfig.h"
|
||||||
#include "minecraft/launch/CreateGameFolders.h"
|
#include "minecraft/launch/CreateGameFolders.h"
|
||||||
#include "minecraft/launch/ExtractNatives.h"
|
#include "minecraft/launch/ExtractNatives.h"
|
||||||
#include "minecraft/launch/PrintInstanceInfo.h"
|
#include "minecraft/launch/PrintInstanceInfo.h"
|
||||||
@ -20,6 +56,7 @@
|
|||||||
#include "launch/steps/PreLaunchCommand.h"
|
#include "launch/steps/PreLaunchCommand.h"
|
||||||
#include "launch/steps/TextPrint.h"
|
#include "launch/steps/TextPrint.h"
|
||||||
#include "launch/steps/CheckJava.h"
|
#include "launch/steps/CheckJava.h"
|
||||||
|
#include "launch/steps/QuitAfterGameStop.h"
|
||||||
|
|
||||||
#include "minecraft/launch/LauncherPartLaunch.h"
|
#include "minecraft/launch/LauncherPartLaunch.h"
|
||||||
#include "minecraft/launch/DirectJavaLaunch.h"
|
#include "minecraft/launch/DirectJavaLaunch.h"
|
||||||
@ -88,6 +125,7 @@ MinecraftInstance::MinecraftInstance(SettingsObjectPtr globalSettings, SettingsO
|
|||||||
|
|
||||||
m_settings->registerOverride(globalSettings->getSetting("JavaPath"), javaOrLocation);
|
m_settings->registerOverride(globalSettings->getSetting("JavaPath"), javaOrLocation);
|
||||||
m_settings->registerOverride(globalSettings->getSetting("JvmArgs"), javaOrArgs);
|
m_settings->registerOverride(globalSettings->getSetting("JvmArgs"), javaOrArgs);
|
||||||
|
m_settings->registerOverride(globalSettings->getSetting("IgnoreJavaCompatibility"), javaOrLocation);
|
||||||
|
|
||||||
// special!
|
// special!
|
||||||
m_settings->registerPassthrough(globalSettings->getSetting("JavaTimestamp"), javaOrLocation);
|
m_settings->registerPassthrough(globalSettings->getSetting("JavaTimestamp"), javaOrLocation);
|
||||||
@ -124,18 +162,7 @@ MinecraftInstance::MinecraftInstance(SettingsObjectPtr globalSettings, SettingsO
|
|||||||
m_settings->registerSetting("JoinServerOnLaunch", false);
|
m_settings->registerSetting("JoinServerOnLaunch", false);
|
||||||
m_settings->registerSetting("JoinServerOnLaunchAddress", "");
|
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.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()
|
void MinecraftInstance::saveNow()
|
||||||
@ -303,6 +330,17 @@ QStringList MinecraftInstance::extraArguments() const
|
|||||||
list.append({"-Dfml.ignoreInvalidMinecraftCertificates=true",
|
list.append({"-Dfml.ignoreInvalidMinecraftCertificates=true",
|
||||||
"-Dfml.ignorePatchDiscrepancies=true"});
|
"-Dfml.ignorePatchDiscrepancies=true"});
|
||||||
}
|
}
|
||||||
|
auto addn = m_components->getProfile()->getAddnJvmArguments();
|
||||||
|
if (!addn.isEmpty()) {
|
||||||
|
list.append(addn);
|
||||||
|
}
|
||||||
|
auto agents = m_components->getProfile()->getAgents();
|
||||||
|
for (auto agent : agents)
|
||||||
|
{
|
||||||
|
QStringList jar, temp1, temp2, temp3;
|
||||||
|
agent->library()->getApplicableFiles(currentSystem, jar, temp1, temp2, temp3, getLocalLibraryPath());
|
||||||
|
list.append("-javaagent:"+jar[0]+(agent->argument().isEmpty() ? "" : "="+agent->argument()));
|
||||||
|
}
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -445,7 +483,7 @@ QStringList MinecraftInstance::processMinecraftArgs(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// blatant self-promotion.
|
// blatant self-promotion.
|
||||||
token_mapping["profile_name"] = token_mapping["version_name"] = "MultiMC5";
|
token_mapping["profile_name"] = token_mapping["version_name"] = BuildConfig.LAUNCHER_NAME;
|
||||||
|
|
||||||
token_mapping["version_type"] = profile->getMinecraftVersionType();
|
token_mapping["version_type"] = profile->getMinecraftVersionType();
|
||||||
|
|
||||||
@ -946,6 +984,11 @@ shared_qobject_ptr<LaunchTask> MinecraftInstance::createLaunchTask(AuthSessionPt
|
|||||||
{
|
{
|
||||||
process->setCensorFilter(createCensorFilterFromSession(session));
|
process->setCensorFilter(createCensorFilterFromSession(session));
|
||||||
}
|
}
|
||||||
|
if(APPLICATION->settings()->get("QuitAfterGameStop").toBool())
|
||||||
|
{
|
||||||
|
auto step = new QuitAfterGameStop(pptr);
|
||||||
|
process->appendStep(step);
|
||||||
|
}
|
||||||
m_launchProcess = process;
|
m_launchProcess = process;
|
||||||
emit launchTaskChanged(m_launchProcess);
|
emit launchTaskChanged(m_launchProcess);
|
||||||
return m_launchProcess;
|
return m_launchProcess;
|
||||||
|
@ -20,7 +20,7 @@
|
|||||||
#include <QUrl>
|
#include <QUrl>
|
||||||
|
|
||||||
#include "tasks/Task.h"
|
#include "tasks/Task.h"
|
||||||
#include <quazip.h>
|
#include <quazip/quazip.h>
|
||||||
|
|
||||||
#include "QObjectPtr.h"
|
#include "QObjectPtr.h"
|
||||||
|
|
||||||
|
@ -22,7 +22,7 @@
|
|||||||
#include "net/NetJob.h"
|
#include "net/NetJob.h"
|
||||||
#include "tasks/Task.h"
|
#include "tasks/Task.h"
|
||||||
#include "minecraft/VersionFilterData.h"
|
#include "minecraft/VersionFilterData.h"
|
||||||
#include <quazip.h>
|
#include <quazip/quazip.h>
|
||||||
|
|
||||||
class MinecraftVersion;
|
class MinecraftVersion;
|
||||||
class MinecraftInstance;
|
class MinecraftInstance;
|
||||||
|
@ -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 "MojangVersionFormat.h"
|
#include "MojangVersionFormat.h"
|
||||||
#include "OneSixVersionFormat.h"
|
#include "OneSixVersionFormat.h"
|
||||||
#include "MojangDownloadInfo.h"
|
#include "MojangDownloadInfo.h"
|
||||||
@ -183,6 +218,15 @@ void MojangVersionFormat::readVersionProperties(const QJsonObject &in, VersionFi
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (in.contains("compatibleJavaMajors"))
|
||||||
|
{
|
||||||
|
for (auto compatible : requireArray(in.value("compatibleJavaMajors")))
|
||||||
|
{
|
||||||
|
out->compatibleJavaMajors.append(requireInteger(compatible));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if(in.contains("downloads"))
|
if(in.contains("downloads"))
|
||||||
{
|
{
|
||||||
auto downloadsObj = requireObject(in, "downloads");
|
auto downloadsObj = requireObject(in, "downloads");
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
#include "OneSixVersionFormat.h"
|
#include "OneSixVersionFormat.h"
|
||||||
#include <Json.h>
|
#include <Json.h>
|
||||||
|
#include "minecraft/Agent.h"
|
||||||
#include "minecraft/ParseUtils.h"
|
#include "minecraft/ParseUtils.h"
|
||||||
#include <minecraft/MojangVersionFormat.h>
|
#include <minecraft/MojangVersionFormat.h>
|
||||||
|
|
||||||
@ -108,6 +109,14 @@ VersionFilePtr OneSixVersionFormat::versionFileFromJson(const QJsonDocument &doc
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (root.contains("+jvmArgs"))
|
||||||
|
{
|
||||||
|
for (auto arg : requireArray(root.value("+jvmArgs")))
|
||||||
|
{
|
||||||
|
out->addnJvmArguments.append(requireString(arg));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
if (root.contains("jarMods"))
|
if (root.contains("jarMods"))
|
||||||
{
|
{
|
||||||
@ -176,6 +185,21 @@ VersionFilePtr OneSixVersionFormat::versionFileFromJson(const QJsonDocument &doc
|
|||||||
readLibs("mavenFiles", out->mavenFiles);
|
readLibs("mavenFiles", out->mavenFiles);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(root.contains("+agents")) {
|
||||||
|
for (auto agentVal : requireArray(root.value("+agents")))
|
||||||
|
{
|
||||||
|
QJsonObject agentObj = requireObject(agentVal);
|
||||||
|
auto lib = libraryFromJson(*out, agentObj, filename);
|
||||||
|
QString arg = "";
|
||||||
|
if (agentObj.contains("argument"))
|
||||||
|
{
|
||||||
|
readString(agentObj, "argument", arg);
|
||||||
|
}
|
||||||
|
AgentPtr agent(new Agent(lib, arg));
|
||||||
|
out->agents.append(agent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// if we have mainJar, just use it
|
// if we have mainJar, just use it
|
||||||
if(root.contains("mainJar"))
|
if(root.contains("mainJar"))
|
||||||
{
|
{
|
||||||
|
@ -272,18 +272,6 @@ void PackProfile::save_internal()
|
|||||||
bool PackProfile::load()
|
bool PackProfile::load()
|
||||||
{
|
{
|
||||||
auto filename = componentsFilePath();
|
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...
|
// load the new component list and swap it with the current one...
|
||||||
ComponentContainer newComponents;
|
ComponentContainer newComponents;
|
||||||
@ -369,239 +357,6 @@ void PackProfile::updateFailed(const QString& error)
|
|||||||
invalidateLaunchProfile();
|
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
|
// END: save/load
|
||||||
|
|
||||||
void PackProfile::appendComponent(ComponentPtr component)
|
void PackProfile::appendComponent(ComponentPtr component)
|
||||||
@ -1169,15 +924,6 @@ std::shared_ptr<LaunchProfile> PackProfile::getProfile() const
|
|||||||
return d->m_profile;
|
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)
|
bool PackProfile::setComponentVersion(const QString& uid, const QString& version, bool important)
|
||||||
{
|
{
|
||||||
auto iter = d->componentIndex.find(uid);
|
auto iter = d->componentIndex.find(uid);
|
||||||
@ -1224,3 +970,20 @@ void PackProfile::disableInteraction(bool disable)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ModAPI::ModLoaderType PackProfile::getModLoader()
|
||||||
|
{
|
||||||
|
if (!getComponentVersion("net.minecraftforge").isEmpty())
|
||||||
|
{
|
||||||
|
return ModAPI::Forge;
|
||||||
|
}
|
||||||
|
else if (!getComponentVersion("net.fabricmc.fabric-loader").isEmpty())
|
||||||
|
{
|
||||||
|
return ModAPI::Fabric;
|
||||||
|
}
|
||||||
|
else if (!getComponentVersion("org.quiltmc.quilt-loader").isEmpty())
|
||||||
|
{
|
||||||
|
return ModAPI::Quilt;
|
||||||
|
}
|
||||||
|
return ModAPI::Unspecified;
|
||||||
|
}
|
||||||
|
@ -28,6 +28,7 @@
|
|||||||
#include "BaseVersion.h"
|
#include "BaseVersion.h"
|
||||||
#include "MojangDownloadInfo.h"
|
#include "MojangDownloadInfo.h"
|
||||||
#include "net/Mode.h"
|
#include "net/Mode.h"
|
||||||
|
#include "modplatform/ModAPI.h"
|
||||||
|
|
||||||
class MinecraftInstance;
|
class MinecraftInstance;
|
||||||
struct PackProfileData;
|
struct PackProfileData;
|
||||||
@ -117,6 +118,8 @@ public:
|
|||||||
// todo(merged): is this the best approach
|
// todo(merged): is this the best approach
|
||||||
void appendComponent(ComponentPtr component);
|
void appendComponent(ComponentPtr component);
|
||||||
|
|
||||||
|
ModAPI::ModLoaderType getModLoader();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void scheduleSave();
|
void scheduleSave();
|
||||||
bool saveIsScheduled() const;
|
bool saveIsScheduled() const;
|
||||||
@ -143,8 +146,6 @@ private:
|
|||||||
bool installCustomJar_internal(QString filepath);
|
bool installCustomJar_internal(QString filepath);
|
||||||
bool removeComponent_internal(ComponentPtr patch);
|
bool removeComponent_internal(ComponentPtr patch);
|
||||||
|
|
||||||
bool migratePreComponentConfig();
|
|
||||||
|
|
||||||
private: /* data */
|
private: /* data */
|
||||||
|
|
||||||
std::unique_ptr<PackProfileData> d;
|
std::unique_ptr<PackProfileData> d;
|
||||||
|
@ -18,18 +18,6 @@ struct PackProfileData
|
|||||||
// the launch profile (volatile, temporary thing created on demand)
|
// the launch profile (volatile, temporary thing created on demand)
|
||||||
std::shared_ptr<LaunchProfile> m_profile;
|
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
|
// persistent list of components and related machinery
|
||||||
ComponentContainer components;
|
ComponentContainer components;
|
||||||
ComponentIndex componentIndex;
|
ComponentIndex componentIndex;
|
||||||
|
@ -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 <QJsonArray>
|
#include <QJsonArray>
|
||||||
#include <QJsonDocument>
|
#include <QJsonDocument>
|
||||||
|
|
||||||
@ -32,10 +67,12 @@ void VersionFile::applyTo(LaunchProfile *profile)
|
|||||||
profile->applyMainClass(mainClass);
|
profile->applyMainClass(mainClass);
|
||||||
profile->applyAppletClass(appletClass);
|
profile->applyAppletClass(appletClass);
|
||||||
profile->applyMinecraftArguments(minecraftArguments);
|
profile->applyMinecraftArguments(minecraftArguments);
|
||||||
|
profile->applyAddnJvmArguments(addnJvmArguments);
|
||||||
profile->applyTweakers(addTweakers);
|
profile->applyTweakers(addTweakers);
|
||||||
profile->applyJarMods(jarMods);
|
profile->applyJarMods(jarMods);
|
||||||
profile->applyMods(mods);
|
profile->applyMods(mods);
|
||||||
profile->applyTraits(traits);
|
profile->applyTraits(traits);
|
||||||
|
profile->applyCompatibleJavaMajors(compatibleJavaMajors);
|
||||||
|
|
||||||
for (auto library : libraries)
|
for (auto library : libraries)
|
||||||
{
|
{
|
||||||
@ -45,6 +82,10 @@ void VersionFile::applyTo(LaunchProfile *profile)
|
|||||||
{
|
{
|
||||||
profile->applyMavenFile(mavenFile);
|
profile->applyMavenFile(mavenFile);
|
||||||
}
|
}
|
||||||
|
for (auto agent : agents)
|
||||||
|
{
|
||||||
|
profile->applyAgent(agent);
|
||||||
|
}
|
||||||
profile->applyProblemSeverity(getProblemSeverity());
|
profile->applyProblemSeverity(getProblemSeverity());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,3 +1,38 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-3.0-only
|
||||||
|
/*
|
||||||
|
* PolyMC - Minecraft Launcher
|
||||||
|
* Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, version 3.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* This file incorporates work covered by the following copyright and
|
||||||
|
* permission notice:
|
||||||
|
*
|
||||||
|
* Copyright 2013-2021 MultiMC Contributors
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <QString>
|
#include <QString>
|
||||||
@ -10,6 +45,7 @@
|
|||||||
#include "minecraft/Rule.h"
|
#include "minecraft/Rule.h"
|
||||||
#include "ProblemProvider.h"
|
#include "ProblemProvider.h"
|
||||||
#include "Library.h"
|
#include "Library.h"
|
||||||
|
#include "Agent.h"
|
||||||
#include <meta/JsonFormat.h>
|
#include <meta/JsonFormat.h>
|
||||||
|
|
||||||
class PackProfile;
|
class PackProfile;
|
||||||
@ -27,19 +63,19 @@ public: /* methods */
|
|||||||
void applyTo(LaunchProfile* profile);
|
void applyTo(LaunchProfile* profile);
|
||||||
|
|
||||||
public: /* data */
|
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;
|
int order = 0;
|
||||||
|
|
||||||
/// MultiMC: human readable name of this package
|
/// PolyMC: human readable name of this package
|
||||||
QString name;
|
QString name;
|
||||||
|
|
||||||
/// MultiMC: package ID of this package
|
/// PolyMC: package ID of this package
|
||||||
QString uid;
|
QString uid;
|
||||||
|
|
||||||
/// MultiMC: version of this package
|
/// PolyMC: version of this package
|
||||||
QString version;
|
QString version;
|
||||||
|
|
||||||
/// MultiMC: DEPRECATED dependency on a Minecraft version
|
/// PolyMC: DEPRECATED dependency on a Minecraft version
|
||||||
QString dependsOnMinecraftVersion;
|
QString dependsOnMinecraftVersion;
|
||||||
|
|
||||||
/// Mojang: DEPRECATED used to version the Mojang version format
|
/// Mojang: DEPRECATED used to version the Mojang version format
|
||||||
@ -51,12 +87,18 @@ public: /* data */
|
|||||||
/// Mojang: class to launch Minecraft with
|
/// Mojang: class to launch Minecraft with
|
||||||
QString mainClass;
|
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;
|
QString appletClass;
|
||||||
|
|
||||||
/// Mojang: Minecraft launch arguments (may contain placeholders for variable substitution)
|
/// Mojang: Minecraft launch arguments (may contain placeholders for variable substitution)
|
||||||
QString minecraftArguments;
|
QString minecraftArguments;
|
||||||
|
|
||||||
|
/// PolyMC: Additional JVM launch arguments
|
||||||
|
QStringList addnJvmArguments;
|
||||||
|
|
||||||
|
/// Mojang: list of compatible java majors
|
||||||
|
QList<int> compatibleJavaMajors;
|
||||||
|
|
||||||
/// Mojang: type of the Minecraft version
|
/// Mojang: type of the Minecraft version
|
||||||
QString type;
|
QString type;
|
||||||
|
|
||||||
@ -69,35 +111,38 @@ public: /* data */
|
|||||||
/// Mojang: DEPRECATED asset group to be used with Minecraft
|
/// Mojang: DEPRECATED asset group to be used with Minecraft
|
||||||
QString assets;
|
QString assets;
|
||||||
|
|
||||||
/// MultiMC: list of tweaker mod arguments for launchwrapper
|
/// PolyMC: list of tweaker mod arguments for launchwrapper
|
||||||
QStringList addTweakers;
|
QStringList addTweakers;
|
||||||
|
|
||||||
/// Mojang: list of libraries to add to the version
|
/// Mojang: list of libraries to add to the version
|
||||||
QList<LibraryPtr> libraries;
|
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;
|
QList<LibraryPtr> mavenFiles;
|
||||||
|
|
||||||
|
/// PolyMC: list of agents to add to JVM arguments
|
||||||
|
QList<AgentPtr> agents;
|
||||||
|
|
||||||
/// The main jar (Minecraft version library, normally)
|
/// The main jar (Minecraft version library, normally)
|
||||||
LibraryPtr mainJar;
|
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;
|
QSet<QString> traits;
|
||||||
|
|
||||||
/// MultiMC: list of jar mods added to this version
|
/// PolyMC: list of jar mods added to this version
|
||||||
QList<LibraryPtr> jarMods;
|
QList<LibraryPtr> jarMods;
|
||||||
|
|
||||||
/// MultiMC: list of mods added to this version
|
/// PolyMC: list of mods added to this version
|
||||||
QList<LibraryPtr> mods;
|
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!!!
|
* NOTE: this is shared with the meta format!!!
|
||||||
*/
|
*/
|
||||||
Meta::RequireSet requires;
|
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!!!
|
* NOTE: this is shared with the meta format!!!
|
||||||
*/
|
*/
|
||||||
Meta::RequireSet conflicts;
|
Meta::RequireSet conflicts;
|
||||||
@ -112,3 +157,4 @@ public:
|
|||||||
// Mojang: extended asset index download information
|
// Mojang: extended asset index download information
|
||||||
std::shared_ptr<MojangAssetIndexInfo> mojangAssetIndex;
|
std::shared_ptr<MojangAssetIndexInfo> mojangAssetIndex;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
#include <QString>
|
#include <QString>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <QSaveFile>
|
#include <QSaveFile>
|
||||||
|
#include <QDirIterator>
|
||||||
#include "World.h"
|
#include "World.h"
|
||||||
|
|
||||||
#include "GZip.h"
|
#include "GZip.h"
|
||||||
@ -26,9 +27,9 @@
|
|||||||
#include <io/stream_reader.h>
|
#include <io/stream_reader.h>
|
||||||
#include <tag_string.h>
|
#include <tag_string.h>
|
||||||
#include <tag_primitive.h>
|
#include <tag_primitive.h>
|
||||||
#include <quazip.h>
|
#include <quazip/quazip.h>
|
||||||
#include <quazipfile.h>
|
#include <quazip/quazipfile.h>
|
||||||
#include <quazipdir.h>
|
#include <quazip/quazipdir.h>
|
||||||
|
|
||||||
#include <QCoreApplication>
|
#include <QCoreApplication>
|
||||||
|
|
||||||
@ -187,6 +188,26 @@ bool putLevelDatDataToFS(const QFileInfo &file, QByteArray & data)
|
|||||||
return f.commit();
|
return f.commit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int64_t calculateWorldSize(const QFileInfo &file)
|
||||||
|
{
|
||||||
|
if (file.isFile() && file.suffix() == "zip")
|
||||||
|
{
|
||||||
|
return file.size();
|
||||||
|
}
|
||||||
|
else if(file.isDir())
|
||||||
|
{
|
||||||
|
QDirIterator it(file.absoluteFilePath(), QDir::Files, QDirIterator::Subdirectories);
|
||||||
|
int64_t total = 0;
|
||||||
|
while (it.hasNext())
|
||||||
|
{
|
||||||
|
total += it.fileInfo().size();
|
||||||
|
it.next();
|
||||||
|
}
|
||||||
|
return total;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
World::World(const QFileInfo &file)
|
World::World(const QFileInfo &file)
|
||||||
{
|
{
|
||||||
repath(file);
|
repath(file);
|
||||||
@ -196,6 +217,7 @@ void World::repath(const QFileInfo &file)
|
|||||||
{
|
{
|
||||||
m_containerFile = file;
|
m_containerFile = file;
|
||||||
m_folderName = file.fileName();
|
m_folderName = file.fileName();
|
||||||
|
m_size = calculateWorldSize(file);
|
||||||
if(file.isFile() && file.suffix() == "zip")
|
if(file.isFile() && file.suffix() == "zip")
|
||||||
{
|
{
|
||||||
m_iconFile = QString();
|
m_iconFile = QString();
|
||||||
@ -482,6 +504,7 @@ void World::loadFromLevelDat(QByteArray data)
|
|||||||
if(randomSeed) {
|
if(randomSeed) {
|
||||||
qDebug() << "Seed:" << *randomSeed;
|
qDebug() << "Seed:" << *randomSeed;
|
||||||
}
|
}
|
||||||
|
qDebug() << "Size:" << m_size;
|
||||||
qDebug() << "GameType:" << m_gameType.toLogString();
|
qDebug() << "GameType:" << m_gameType.toLogString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -52,6 +52,10 @@ public:
|
|||||||
{
|
{
|
||||||
return m_iconFile;
|
return m_iconFile;
|
||||||
}
|
}
|
||||||
|
int64_t bytes() const
|
||||||
|
{
|
||||||
|
return m_size;
|
||||||
|
}
|
||||||
QDateTime lastPlayed() const
|
QDateTime lastPlayed() const
|
||||||
{
|
{
|
||||||
return m_lastPlayed;
|
return m_lastPlayed;
|
||||||
@ -105,6 +109,7 @@ protected:
|
|||||||
QString m_iconFile;
|
QString m_iconFile;
|
||||||
QDateTime levelDatTime;
|
QDateTime levelDatTime;
|
||||||
QDateTime m_lastPlayed;
|
QDateTime m_lastPlayed;
|
||||||
|
int64_t m_size;
|
||||||
int64_t m_randomSeed = 0;
|
int64_t m_randomSeed = 0;
|
||||||
GameType m_gameType;
|
GameType m_gameType;
|
||||||
bool is_valid = false;
|
bool is_valid = false;
|
||||||
|
@ -14,7 +14,10 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "WorldList.h"
|
#include "WorldList.h"
|
||||||
|
|
||||||
|
#include "Application.h"
|
||||||
#include <FileSystem.h>
|
#include <FileSystem.h>
|
||||||
|
#include <Qt>
|
||||||
#include <QMimeData>
|
#include <QMimeData>
|
||||||
#include <QUrl>
|
#include <QUrl>
|
||||||
#include <QUuid>
|
#include <QUuid>
|
||||||
@ -150,7 +153,7 @@ bool WorldList::resetIcon(int row)
|
|||||||
|
|
||||||
int WorldList::columnCount(const QModelIndex &parent) const
|
int WorldList::columnCount(const QModelIndex &parent) const
|
||||||
{
|
{
|
||||||
return 3;
|
return 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
QVariant WorldList::data(const QModelIndex &index, int role) const
|
QVariant WorldList::data(const QModelIndex &index, int role) const
|
||||||
@ -164,6 +167,8 @@ QVariant WorldList::data(const QModelIndex &index, int role) const
|
|||||||
if (row < 0 || row >= worlds.size())
|
if (row < 0 || row >= worlds.size())
|
||||||
return QVariant();
|
return QVariant();
|
||||||
|
|
||||||
|
QLocale locale;
|
||||||
|
|
||||||
auto & world = worlds[row];
|
auto & world = worlds[row];
|
||||||
switch (role)
|
switch (role)
|
||||||
{
|
{
|
||||||
@ -179,10 +184,23 @@ QVariant WorldList::data(const QModelIndex &index, int role) const
|
|||||||
case LastPlayedColumn:
|
case LastPlayedColumn:
|
||||||
return world.lastPlayed();
|
return world.lastPlayed();
|
||||||
|
|
||||||
|
case SizeColumn:
|
||||||
|
return locale.formattedDataSize(world.bytes());
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return QVariant();
|
return QVariant();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case Qt::UserRole:
|
||||||
|
switch (column)
|
||||||
|
{
|
||||||
|
case SizeColumn:
|
||||||
|
return qVariantFromValue<qlonglong>(world.bytes());
|
||||||
|
|
||||||
|
default:
|
||||||
|
return data(index, Qt::DisplayRole);
|
||||||
|
}
|
||||||
|
|
||||||
case Qt::ToolTipRole:
|
case Qt::ToolTipRole:
|
||||||
{
|
{
|
||||||
return world.folderName();
|
return world.folderName();
|
||||||
@ -207,6 +225,10 @@ QVariant WorldList::data(const QModelIndex &index, int role) const
|
|||||||
{
|
{
|
||||||
return world.lastPlayed();
|
return world.lastPlayed();
|
||||||
}
|
}
|
||||||
|
case SizeRole:
|
||||||
|
{
|
||||||
|
return qVariantFromValue<qlonglong>(world.bytes());
|
||||||
|
}
|
||||||
case IconFileRole:
|
case IconFileRole:
|
||||||
{
|
{
|
||||||
return world.iconFile();
|
return world.iconFile();
|
||||||
@ -229,6 +251,9 @@ QVariant WorldList::headerData(int section, Qt::Orientation orientation, int rol
|
|||||||
return tr("Game Mode");
|
return tr("Game Mode");
|
||||||
case LastPlayedColumn:
|
case LastPlayedColumn:
|
||||||
return tr("Last Played");
|
return tr("Last Played");
|
||||||
|
case SizeColumn:
|
||||||
|
//: World size on disk
|
||||||
|
return tr("Size");
|
||||||
default:
|
default:
|
||||||
return QVariant();
|
return QVariant();
|
||||||
}
|
}
|
||||||
@ -242,6 +267,8 @@ QVariant WorldList::headerData(int section, Qt::Orientation orientation, int rol
|
|||||||
return tr("Game mode of the world.");
|
return tr("Game mode of the world.");
|
||||||
case LastPlayedColumn:
|
case LastPlayedColumn:
|
||||||
return tr("Date and time the world was last played.");
|
return tr("Date and time the world was last played.");
|
||||||
|
case SizeColumn:
|
||||||
|
return tr("Size of the world on disk.");
|
||||||
default:
|
default:
|
||||||
return QVariant();
|
return QVariant();
|
||||||
}
|
}
|
||||||
|
@ -32,7 +32,8 @@ public:
|
|||||||
{
|
{
|
||||||
NameColumn,
|
NameColumn,
|
||||||
GameModeColumn,
|
GameModeColumn,
|
||||||
LastPlayedColumn
|
LastPlayedColumn,
|
||||||
|
SizeColumn
|
||||||
};
|
};
|
||||||
|
|
||||||
enum Roles
|
enum Roles
|
||||||
@ -43,6 +44,7 @@ public:
|
|||||||
NameRole,
|
NameRole,
|
||||||
GameModeRole,
|
GameModeRole,
|
||||||
LastPlayedRole,
|
LastPlayedRole,
|
||||||
|
SizeRole,
|
||||||
IconFileRole
|
IconFileRole
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -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 "AccountData.h"
|
||||||
#include <QJsonDocument>
|
#include <QJsonDocument>
|
||||||
#include <QJsonObject>
|
#include <QJsonObject>
|
||||||
@ -314,6 +349,8 @@ bool AccountData::resumeStateFromV3(QJsonObject data) {
|
|||||||
type = AccountType::MSA;
|
type = AccountType::MSA;
|
||||||
} else if (typeS == "Mojang") {
|
} else if (typeS == "Mojang") {
|
||||||
type = AccountType::Mojang;
|
type = AccountType::Mojang;
|
||||||
|
} else if (typeS == "Offline") {
|
||||||
|
type = AccountType::Offline;
|
||||||
} else {
|
} else {
|
||||||
qWarning() << "Failed to parse account data: type is not recognized.";
|
qWarning() << "Failed to parse account data: type is not recognized.";
|
||||||
return false;
|
return false;
|
||||||
@ -325,6 +362,10 @@ bool AccountData::resumeStateFromV3(QJsonObject data) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(type == AccountType::MSA) {
|
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");
|
msaToken = tokenFromJSONV3(data, "msa");
|
||||||
userToken = tokenFromJSONV3(data, "utoken");
|
userToken = tokenFromJSONV3(data, "utoken");
|
||||||
xboxApiToken = tokenFromJSONV3(data, "xrp-main");
|
xboxApiToken = tokenFromJSONV3(data, "xrp-main");
|
||||||
@ -358,11 +399,15 @@ QJsonObject AccountData::saveState() const {
|
|||||||
}
|
}
|
||||||
else if (type == AccountType::MSA) {
|
else if (type == AccountType::MSA) {
|
||||||
output["type"] = "MSA";
|
output["type"] = "MSA";
|
||||||
|
output["msa-client-id"] = msaClientID;
|
||||||
tokenToJSONV3(output, msaToken, "msa");
|
tokenToJSONV3(output, msaToken, "msa");
|
||||||
tokenToJSONV3(output, userToken, "utoken");
|
tokenToJSONV3(output, userToken, "utoken");
|
||||||
tokenToJSONV3(output, xboxApiToken, "xrp-main");
|
tokenToJSONV3(output, xboxApiToken, "xrp-main");
|
||||||
tokenToJSONV3(output, mojangservicesToken, "xrp-mc");
|
tokenToJSONV3(output, mojangservicesToken, "xrp-mc");
|
||||||
}
|
}
|
||||||
|
else if (type == AccountType::Offline) {
|
||||||
|
output["type"] = "Offline";
|
||||||
|
}
|
||||||
|
|
||||||
tokenToJSONV3(output, yggdrasilToken, "ygg");
|
tokenToJSONV3(output, yggdrasilToken, "ygg");
|
||||||
profileToJSONV3(output, minecraftProfile, "profile");
|
profileToJSONV3(output, minecraftProfile, "profile");
|
||||||
@ -371,7 +416,7 @@ QJsonObject AccountData::saveState() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
QString AccountData::userName() const {
|
QString AccountData::userName() const {
|
||||||
if(type != AccountType::Mojang) {
|
if(type == AccountType::MSA) {
|
||||||
return QString();
|
return QString();
|
||||||
}
|
}
|
||||||
return yggdrasilToken.extra["userName"].toString();
|
return yggdrasilToken.extra["userName"].toString();
|
||||||
@ -427,6 +472,9 @@ QString AccountData::accountDisplayString() const {
|
|||||||
case AccountType::Mojang: {
|
case AccountType::Mojang: {
|
||||||
return userName();
|
return userName();
|
||||||
}
|
}
|
||||||
|
case AccountType::Offline: {
|
||||||
|
return userName();
|
||||||
|
}
|
||||||
case AccountType::MSA: {
|
case AccountType::MSA: {
|
||||||
if(xboxApiToken.extra.contains("gtg")) {
|
if(xboxApiToken.extra.contains("gtg")) {
|
||||||
return xboxApiToken.extra["gtg"].toString();
|
return xboxApiToken.extra["gtg"].toString();
|
||||||
|
@ -1,3 +1,38 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-3.0-only
|
||||||
|
/*
|
||||||
|
* PolyMC - Minecraft Launcher
|
||||||
|
* Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, version 3.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* This file incorporates work covered by the following copyright and
|
||||||
|
* permission notice:
|
||||||
|
*
|
||||||
|
* Copyright 2013-2021 MultiMC Contributors
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <QString>
|
#include <QString>
|
||||||
#include <QByteArray>
|
#include <QByteArray>
|
||||||
@ -38,7 +73,8 @@ struct MinecraftProfile {
|
|||||||
|
|
||||||
enum class AccountType {
|
enum class AccountType {
|
||||||
MSA,
|
MSA,
|
||||||
Mojang
|
Mojang,
|
||||||
|
Offline
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class AccountState {
|
enum class AccountState {
|
||||||
@ -46,6 +82,7 @@ enum class AccountState {
|
|||||||
Offline,
|
Offline,
|
||||||
Working,
|
Working,
|
||||||
Online,
|
Online,
|
||||||
|
Disabled,
|
||||||
Errored,
|
Errored,
|
||||||
Expired,
|
Expired,
|
||||||
Gone
|
Gone
|
||||||
@ -80,6 +117,7 @@ struct AccountData {
|
|||||||
bool legacy = false;
|
bool legacy = false;
|
||||||
bool canMigrateToMSA = false;
|
bool canMigrateToMSA = false;
|
||||||
|
|
||||||
|
QString msaClientID;
|
||||||
Katabasis::Token msaToken;
|
Katabasis::Token msaToken;
|
||||||
Katabasis::Token userToken;
|
Katabasis::Token userToken;
|
||||||
Katabasis::Token xboxApiToken;
|
Katabasis::Token xboxApiToken;
|
||||||
|
@ -1,16 +1,36 @@
|
|||||||
/* Copyright 2013-2021 MultiMC Contributors
|
// SPDX-License-Identifier: GPL-3.0-only
|
||||||
|
/*
|
||||||
|
* PolyMC - Minecraft Launcher
|
||||||
|
* Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net>
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* This program is free software: you can redistribute it and/or modify
|
||||||
* you may not use this file except in compliance with the License.
|
* it under the terms of the GNU General Public License as published by
|
||||||
* You may obtain a copy of the License at
|
* the Free Software Foundation, version 3.
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* 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.
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* You should have received a copy of the GNU General Public License
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
*
|
||||||
* See the License for the specific language governing permissions and
|
* This file incorporates work covered by the following copyright and
|
||||||
* limitations under the License.
|
* 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 "AccountList.h"
|
#include "AccountList.h"
|
||||||
@ -291,6 +311,9 @@ QVariant AccountList::data(const QModelIndex &index, int role) const
|
|||||||
case AccountState::Expired: {
|
case AccountState::Expired: {
|
||||||
return tr("Expired", "Account status");
|
return tr("Expired", "Account status");
|
||||||
}
|
}
|
||||||
|
case AccountState::Disabled: {
|
||||||
|
return tr("Disabled", "Account status");
|
||||||
|
}
|
||||||
case AccountState::Gone: {
|
case AccountState::Gone: {
|
||||||
return tr("Gone", "Account status");
|
return tr("Gone", "Account status");
|
||||||
}
|
}
|
||||||
@ -302,7 +325,7 @@ QVariant AccountList::data(const QModelIndex &index, int role) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
case MigrationColumn: {
|
case MigrationColumn: {
|
||||||
if(account->isMSA()) {
|
if(account->isMSA() || account->isOffline()) {
|
||||||
return tr("N/A", "Can Migrate?");
|
return tr("N/A", "Can Migrate?");
|
||||||
}
|
}
|
||||||
if (account->canMigrate()) {
|
if (account->canMigrate()) {
|
||||||
|
@ -1,16 +1,36 @@
|
|||||||
/* Copyright 2013-2021 MultiMC Contributors
|
// SPDX-License-Identifier: GPL-3.0-only
|
||||||
|
/*
|
||||||
|
* PolyMC - Minecraft Launcher
|
||||||
|
* Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net>
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* This program is free software: you can redistribute it and/or modify
|
||||||
* you may not use this file except in compliance with the License.
|
* it under the terms of the GNU General Public License as published by
|
||||||
* You may obtain a copy of the License at
|
* the Free Software Foundation, version 3.
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* 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.
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* You should have received a copy of the GNU General Public License
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
*
|
||||||
* See the License for the specific language governing permissions and
|
* This file incorporates work covered by the following copyright and
|
||||||
* limitations under the License.
|
* permission notice:
|
||||||
|
*
|
||||||
|
* Copyright 2013-2021 MultiMC Contributors
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
@ -24,7 +44,7 @@
|
|||||||
|
|
||||||
/*!
|
/*!
|
||||||
* List of available Mojang accounts.
|
* 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
|
class AccountList : public QAbstractListModel
|
||||||
{
|
{
|
||||||
@ -158,3 +178,4 @@ protected:
|
|||||||
*/
|
*/
|
||||||
bool m_autosave = false;
|
bool m_autosave = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,16 +1,36 @@
|
|||||||
/* Copyright 2013-2021 MultiMC Contributors
|
// SPDX-License-Identifier: GPL-3.0-only
|
||||||
|
/*
|
||||||
|
* PolyMC - Minecraft Launcher
|
||||||
|
* Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net>
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* This program is free software: you can redistribute it and/or modify
|
||||||
* you may not use this file except in compliance with the License.
|
* it under the terms of the GNU General Public License as published by
|
||||||
* You may obtain a copy of the License at
|
* the Free Software Foundation, version 3.
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* 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.
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* You should have received a copy of the GNU General Public License
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
*
|
||||||
* See the License for the specific language governing permissions and
|
* This file incorporates work covered by the following copyright and
|
||||||
* limitations under the License.
|
* 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 "AccountTask.h"
|
#include "AccountTask.h"
|
||||||
@ -43,6 +63,8 @@ QString AccountTask::getStateMessage() const
|
|||||||
return tr("Authentication task succeeded.");
|
return tr("Authentication task succeeded.");
|
||||||
case AccountTaskState::STATE_OFFLINE:
|
case AccountTaskState::STATE_OFFLINE:
|
||||||
return tr("Failed to contact the authentication server.");
|
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:
|
case AccountTaskState::STATE_FAILED_SOFT:
|
||||||
return tr("Encountered an error during authentication.");
|
return tr("Encountered an error during authentication.");
|
||||||
case AccountTaskState::STATE_FAILED_HARD:
|
case AccountTaskState::STATE_FAILED_HARD:
|
||||||
@ -78,6 +100,12 @@ bool AccountTask::changeState(AccountTaskState newState, QString reason)
|
|||||||
emitFailed(reason);
|
emitFailed(reason);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
case AccountTaskState::STATE_DISABLED: {
|
||||||
|
m_data->errorString = reason;
|
||||||
|
m_data->accountState = AccountState::Disabled;
|
||||||
|
emitFailed(reason);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
case AccountTaskState::STATE_FAILED_SOFT: {
|
case AccountTaskState::STATE_FAILED_SOFT: {
|
||||||
m_data->errorString = reason;
|
m_data->errorString = reason;
|
||||||
m_data->accountState = AccountState::Errored;
|
m_data->accountState = AccountState::Errored;
|
||||||
|
@ -1,16 +1,36 @@
|
|||||||
/* Copyright 2013-2021 MultiMC Contributors
|
// SPDX-License-Identifier: GPL-3.0-only
|
||||||
|
/*
|
||||||
|
* PolyMC - Minecraft Launcher
|
||||||
|
* Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net>
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* This program is free software: you can redistribute it and/or modify
|
||||||
* you may not use this file except in compliance with the License.
|
* it under the terms of the GNU General Public License as published by
|
||||||
* You may obtain a copy of the License at
|
* the Free Software Foundation, version 3.
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* 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.
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* You should have received a copy of the GNU General Public License
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
*
|
||||||
* See the License for the specific language governing permissions and
|
* This file incorporates work covered by the following copyright and
|
||||||
* limitations under the License.
|
* permission notice:
|
||||||
|
*
|
||||||
|
* Copyright 2013-2021 MultiMC Contributors
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
@ -35,6 +55,7 @@ enum class AccountTaskState
|
|||||||
STATE_CREATED,
|
STATE_CREATED,
|
||||||
STATE_WORKING,
|
STATE_WORKING,
|
||||||
STATE_SUCCEEDED,
|
STATE_SUCCEEDED,
|
||||||
|
STATE_DISABLED, //!< MSA Client ID has changed. Tell user to reloginn
|
||||||
STATE_FAILED_SOFT, //!< soft failure. authentication went through partially
|
STATE_FAILED_SOFT, //!< soft failure. authentication went through partially
|
||||||
STATE_FAILED_HARD, //!< hard failure. main tokens are invalid
|
STATE_FAILED_HARD, //!< hard failure. main tokens are invalid
|
||||||
STATE_FAILED_GONE, //!< hard failure. main tokens are invalid, and the account no longer exists
|
STATE_FAILED_GONE, //!< hard failure. main tokens are invalid, and the account no longer exists
|
||||||
|
@ -44,7 +44,7 @@ void AuthRequest::onRequestFinished() {
|
|||||||
if (reply_ != qobject_cast<QNetworkReply *>(sender())) {
|
if (reply_ != qobject_cast<QNetworkReply *>(sender())) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
httpStatus_ = 200;
|
httpStatus_ = reply_->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
|
||||||
finish();
|
finish();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,18 +1,38 @@
|
|||||||
/* Copyright 2013-2021 MultiMC Contributors
|
// SPDX-License-Identifier: GPL-3.0-only
|
||||||
|
/*
|
||||||
|
* PolyMC - Minecraft Launcher
|
||||||
|
* Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net>
|
||||||
*
|
*
|
||||||
* Authors: Orochimarufan <orochimarufan.x3@gmail.com>
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, version 3.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* This program is distributed in the hope that it will be useful,
|
||||||
* you may not use this file except in compliance with the License.
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* You may obtain a copy of the License at
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* This file incorporates work covered by the following copyright and
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* permission notice:
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
*
|
||||||
* See the License for the specific language governing permissions and
|
* Copyright 2013-2021 MultiMC Contributors
|
||||||
* limitations under the License.
|
*
|
||||||
|
* Authors: Orochimarufan <orochimarufan.x3@gmail.com>
|
||||||
|
*
|
||||||
|
* 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 "MinecraftAccount.h"
|
#include "MinecraftAccount.h"
|
||||||
@ -30,6 +50,7 @@
|
|||||||
|
|
||||||
#include "flows/MSA.h"
|
#include "flows/MSA.h"
|
||||||
#include "flows/Mojang.h"
|
#include "flows/Mojang.h"
|
||||||
|
#include "flows/Offline.h"
|
||||||
|
|
||||||
MinecraftAccount::MinecraftAccount(QObject* parent) : QObject(parent) {
|
MinecraftAccount::MinecraftAccount(QObject* parent) : QObject(parent) {
|
||||||
data.internalId = QUuid::createUuid().toString().remove(QRegExp("[{}-]"));
|
data.internalId = QUuid::createUuid().toString().remove(QRegExp("[{}-]"));
|
||||||
@ -68,6 +89,23 @@ MinecraftAccountPtr MinecraftAccount::createBlankMSA()
|
|||||||
return account;
|
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
|
QJsonObject MinecraftAccount::saveToJson() const
|
||||||
{
|
{
|
||||||
@ -111,6 +149,16 @@ shared_qobject_ptr<AccountTask> MinecraftAccount::loginMSA() {
|
|||||||
return m_currentTask;
|
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() {
|
shared_qobject_ptr<AccountTask> MinecraftAccount::refresh() {
|
||||||
if(m_currentTask) {
|
if(m_currentTask) {
|
||||||
return m_currentTask;
|
return m_currentTask;
|
||||||
@ -119,6 +167,9 @@ shared_qobject_ptr<AccountTask> MinecraftAccount::refresh() {
|
|||||||
if(data.type == AccountType::MSA) {
|
if(data.type == AccountType::MSA) {
|
||||||
m_currentTask.reset(new MSASilent(&data));
|
m_currentTask.reset(new MSASilent(&data));
|
||||||
}
|
}
|
||||||
|
else if(data.type == AccountType::Offline) {
|
||||||
|
m_currentTask.reset(new OfflineRefresh(&data));
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
m_currentTask.reset(new MojangRefresh(&data));
|
m_currentTask.reset(new MojangRefresh(&data));
|
||||||
}
|
}
|
||||||
@ -145,6 +196,9 @@ void MinecraftAccount::authFailed(QString reason)
|
|||||||
{
|
{
|
||||||
switch (m_currentTask->taskState()) {
|
switch (m_currentTask->taskState()) {
|
||||||
case AccountTaskState::STATE_OFFLINE:
|
case AccountTaskState::STATE_OFFLINE:
|
||||||
|
case AccountTaskState::STATE_DISABLED: {
|
||||||
|
// NOTE: user will need to fix this themselves.
|
||||||
|
}
|
||||||
case AccountTaskState::STATE_FAILED_SOFT: {
|
case AccountTaskState::STATE_FAILED_SOFT: {
|
||||||
// NOTE: this doesn't do much. There was an error of some sort.
|
// NOTE: this doesn't do much. There was an error of some sort.
|
||||||
}
|
}
|
||||||
|
@ -1,16 +1,36 @@
|
|||||||
/* Copyright 2013-2021 MultiMC Contributors
|
// SPDX-License-Identifier: GPL-3.0-only
|
||||||
|
/*
|
||||||
|
* PolyMC - Minecraft Launcher
|
||||||
|
* Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net>
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* This program is free software: you can redistribute it and/or modify
|
||||||
* you may not use this file except in compliance with the License.
|
* it under the terms of the GNU General Public License as published by
|
||||||
* You may obtain a copy of the License at
|
* the Free Software Foundation, version 3.
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* 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.
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* You should have received a copy of the GNU General Public License
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
*
|
||||||
* See the License for the specific language governing permissions and
|
* This file incorporates work covered by the following copyright and
|
||||||
* limitations under the License.
|
* permission notice:
|
||||||
|
*
|
||||||
|
* Copyright 2013-2021 MultiMC Contributors
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
@ -41,7 +61,7 @@ Q_DECLARE_METATYPE(MinecraftAccountPtr)
|
|||||||
* A profile within someone's Mojang account.
|
* A profile within someone's Mojang account.
|
||||||
*
|
*
|
||||||
* Currently, the profile system has not been implemented by Mojang yet,
|
* 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.
|
* we don't have to rip the code to pieces to add it later.
|
||||||
*/
|
*/
|
||||||
struct AccountProfile
|
struct AccountProfile
|
||||||
@ -73,6 +93,8 @@ public: /* construction */
|
|||||||
|
|
||||||
static MinecraftAccountPtr createBlankMSA();
|
static MinecraftAccountPtr createBlankMSA();
|
||||||
|
|
||||||
|
static MinecraftAccountPtr createOffline(const QString &username);
|
||||||
|
|
||||||
static MinecraftAccountPtr loadFromJsonV2(const QJsonObject &json);
|
static MinecraftAccountPtr loadFromJsonV2(const QJsonObject &json);
|
||||||
static MinecraftAccountPtr loadFromJsonV3(const QJsonObject &json);
|
static MinecraftAccountPtr loadFromJsonV3(const QJsonObject &json);
|
||||||
|
|
||||||
@ -89,6 +111,8 @@ public: /* manipulation */
|
|||||||
|
|
||||||
shared_qobject_ptr<AccountTask> loginMSA();
|
shared_qobject_ptr<AccountTask> loginMSA();
|
||||||
|
|
||||||
|
shared_qobject_ptr<AccountTask> loginOffline();
|
||||||
|
|
||||||
shared_qobject_ptr<AccountTask> refresh();
|
shared_qobject_ptr<AccountTask> refresh();
|
||||||
|
|
||||||
shared_qobject_ptr<AccountTask> currentTask();
|
shared_qobject_ptr<AccountTask> currentTask();
|
||||||
@ -128,6 +152,10 @@ public: /* queries */
|
|||||||
return data.type == AccountType::MSA;
|
return data.type == AccountType::MSA;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool isOffline() const {
|
||||||
|
return data.type == AccountType::Offline;
|
||||||
|
}
|
||||||
|
|
||||||
bool ownsMinecraft() const {
|
bool ownsMinecraft() const {
|
||||||
return data.minecraftEntitlement.ownsMinecraft;
|
return data.minecraftEntitlement.ownsMinecraft;
|
||||||
}
|
}
|
||||||
@ -149,6 +177,10 @@ public: /* queries */
|
|||||||
return "msa";
|
return "msa";
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case AccountType::Offline: {
|
||||||
|
return "offline";
|
||||||
|
}
|
||||||
|
break;
|
||||||
default: {
|
default: {
|
||||||
return "unknown";
|
return "unknown";
|
||||||
}
|
}
|
||||||
@ -198,3 +230,4 @@ slots:
|
|||||||
void authSucceeded();
|
void authSucceeded();
|
||||||
void authFailed(QString reason);
|
void authFailed(QString reason);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
#include "Parsers.h"
|
#include "Parsers.h"
|
||||||
|
#include "Json.h"
|
||||||
|
|
||||||
#include <QJsonDocument>
|
#include <QJsonDocument>
|
||||||
#include <QJsonArray>
|
#include <QJsonArray>
|
||||||
@ -94,7 +95,7 @@ bool parseXTokenResponse(QByteArray & data, Katabasis::Token &output, QString na
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if(!getString(obj.value("Token"), output.token)) {
|
if(!getString(obj.value("Token"), output.token)) {
|
||||||
qWarning() << "User Token is not a timestamp";
|
qWarning() << "User Token is not a string";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
auto arrayVal = obj.value("DisplayClaims").toObject().value("xui");
|
auto arrayVal = obj.value("DisplayClaims").toObject().value("xui");
|
||||||
@ -212,6 +213,180 @@ bool parseMinecraftProfile(QByteArray & data, MinecraftProfile &output) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
// these skin URLs are for the MHF_Steve and MHF_Alex accounts (made by a Mojang employee)
|
||||||
|
// they are needed because the session server doesn't return skin urls for default skins
|
||||||
|
static const QString SKIN_URL_STEVE = "http://textures.minecraft.net/texture/1a4af718455d4aab528e7a61f86fa25e6a369d1768dcb13f7df319a713eb810b";
|
||||||
|
static const QString SKIN_URL_ALEX = "http://textures.minecraft.net/texture/83cee5ca6afcdb171285aa00e8049c297b2dbeba0efb8ff970a5677a1b644032";
|
||||||
|
|
||||||
|
bool isDefaultModelSteve(QString uuid) {
|
||||||
|
// need to calculate *Java* hashCode of UUID
|
||||||
|
// if number is even, skin/model is steve, otherwise it is alex
|
||||||
|
|
||||||
|
// just in case dashes are in the id
|
||||||
|
uuid.remove('-');
|
||||||
|
|
||||||
|
if (uuid.size() != 32) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// qulonglong is guaranteed to be 64 bits
|
||||||
|
// we need to use unsigned numbers to guarantee truncation below
|
||||||
|
qulonglong most = uuid.left(16).toULongLong(nullptr, 16);
|
||||||
|
qulonglong least = uuid.right(16).toULongLong(nullptr, 16);
|
||||||
|
qulonglong xored = most ^ least;
|
||||||
|
return ((static_cast<quint32>(xored >> 32)) ^ static_cast<quint32>(xored)) % 2 == 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Uses session server for skin/cape lookup instead of profile,
|
||||||
|
because locked Mojang accounts cannot access profile endpoint
|
||||||
|
(https://api.minecraftservices.com/minecraft/profile/)
|
||||||
|
|
||||||
|
ref: https://wiki.vg/Mojang_API#UUID_to_Profile_and_Skin.2FCape
|
||||||
|
|
||||||
|
{
|
||||||
|
"id": "<profile identifier>",
|
||||||
|
"name": "<player name>",
|
||||||
|
"properties": [
|
||||||
|
{
|
||||||
|
"name": "textures",
|
||||||
|
"value": "<base64 string>"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
decoded base64 "value":
|
||||||
|
{
|
||||||
|
"timestamp": <java time in ms>,
|
||||||
|
"profileId": "<profile uuid>",
|
||||||
|
"profileName": "<player name>",
|
||||||
|
"textures": {
|
||||||
|
"SKIN": {
|
||||||
|
"url": "<player skin URL>"
|
||||||
|
},
|
||||||
|
"CAPE": {
|
||||||
|
"url": "<player cape URL>"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
bool parseMinecraftProfileMojang(QByteArray & data, MinecraftProfile &output) {
|
||||||
|
qDebug() << "Parsing Minecraft profile...";
|
||||||
|
#ifndef NDEBUG
|
||||||
|
qDebug() << data;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
QJsonParseError jsonError;
|
||||||
|
QJsonDocument doc = QJsonDocument::fromJson(data, &jsonError);
|
||||||
|
if(jsonError.error) {
|
||||||
|
qWarning() << "Failed to parse response as JSON: " << jsonError.errorString();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto obj = Json::requireObject(doc, "mojang minecraft profile");
|
||||||
|
if(!getString(obj.value("id"), output.id)) {
|
||||||
|
qWarning() << "Minecraft profile id is not a string";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!getString(obj.value("name"), output.name)) {
|
||||||
|
qWarning() << "Minecraft profile name is not a string";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto propsArray = obj.value("properties").toArray();
|
||||||
|
QByteArray texturePayload;
|
||||||
|
for( auto p : propsArray) {
|
||||||
|
auto pObj = p.toObject();
|
||||||
|
auto name = pObj.value("name");
|
||||||
|
if (!name.isString() || name.toString() != "textures") {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto value = pObj.value("value");
|
||||||
|
if (value.isString()) {
|
||||||
|
#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)
|
||||||
|
texturePayload = QByteArray::fromBase64(value.toString().toUtf8(), QByteArray::AbortOnBase64DecodingErrors);
|
||||||
|
#else
|
||||||
|
texturePayload = QByteArray::fromBase64(value.toString().toUtf8());
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!texturePayload.isEmpty()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (texturePayload.isNull()) {
|
||||||
|
qWarning() << "No texture payload data";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
doc = QJsonDocument::fromJson(texturePayload, &jsonError);
|
||||||
|
if(jsonError.error) {
|
||||||
|
qWarning() << "Failed to parse response as JSON: " << jsonError.errorString();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
obj = Json::requireObject(doc, "session texture payload");
|
||||||
|
auto textures = obj.value("textures");
|
||||||
|
if (!textures.isObject()) {
|
||||||
|
qWarning() << "No textures array in response";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Skin skinOut;
|
||||||
|
// fill in default skin info ourselves, as this endpoint doesn't provide it
|
||||||
|
bool steve = isDefaultModelSteve(output.id);
|
||||||
|
skinOut.variant = steve ? "classic" : "slim";
|
||||||
|
skinOut.url = steve ? SKIN_URL_STEVE : SKIN_URL_ALEX;
|
||||||
|
// sadly we can't figure this out, but I don't think it really matters...
|
||||||
|
skinOut.id = "00000000-0000-0000-0000-000000000000";
|
||||||
|
Cape capeOut;
|
||||||
|
auto tObj = textures.toObject();
|
||||||
|
for (auto idx = tObj.constBegin(); idx != tObj.constEnd(); ++idx) {
|
||||||
|
if (idx->isObject()) {
|
||||||
|
if (idx.key() == "SKIN") {
|
||||||
|
auto skin = idx->toObject();
|
||||||
|
if (!getString(skin.value("url"), skinOut.url)) {
|
||||||
|
qWarning() << "Skin url is not a string";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto maybeMeta = skin.find("metadata");
|
||||||
|
if (maybeMeta != skin.end() && maybeMeta->isObject()) {
|
||||||
|
auto meta = maybeMeta->toObject();
|
||||||
|
// might not be present
|
||||||
|
getString(meta.value("model"), skinOut.variant);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (idx.key() == "CAPE") {
|
||||||
|
auto cape = idx->toObject();
|
||||||
|
if (!getString(cape.value("url"), capeOut.url)) {
|
||||||
|
qWarning() << "Cape url is not a string";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// we don't know the cape ID as it is not returned from the session server
|
||||||
|
// so just fake it - changing capes is probably locked anyway :(
|
||||||
|
capeOut.alias = "cape";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
output.skin = skinOut;
|
||||||
|
if (capeOut.alias == "cape") {
|
||||||
|
output.capes = QMap<QString, Cape>({{capeOut.alias, capeOut}});
|
||||||
|
output.currentCape = capeOut.alias;
|
||||||
|
}
|
||||||
|
|
||||||
|
output.validity = Katabasis::Validity::Certain;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool parseMinecraftEntitlements(QByteArray & data, MinecraftEntitlement &output) {
|
bool parseMinecraftEntitlements(QByteArray & data, MinecraftEntitlement &output) {
|
||||||
qDebug() << "Parsing Minecraft entitlements...";
|
qDebug() << "Parsing Minecraft entitlements...";
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
|
@ -14,6 +14,7 @@ namespace Parsers
|
|||||||
bool parseMojangResponse(QByteArray &data, Katabasis::Token &output);
|
bool parseMojangResponse(QByteArray &data, Katabasis::Token &output);
|
||||||
|
|
||||||
bool parseMinecraftProfile(QByteArray &data, MinecraftProfile &output);
|
bool parseMinecraftProfile(QByteArray &data, MinecraftProfile &output);
|
||||||
|
bool parseMinecraftProfileMojang(QByteArray &data, MinecraftProfile &output);
|
||||||
bool parseMinecraftEntitlements(QByteArray &data, MinecraftEntitlement &output);
|
bool parseMinecraftEntitlements(QByteArray &data, MinecraftEntitlement &output);
|
||||||
bool parseRolloutResponse(QByteArray &data, bool& result);
|
bool parseRolloutResponse(QByteArray &data, bool& result);
|
||||||
}
|
}
|
||||||
|
@ -209,6 +209,28 @@ void Yggdrasil::processResponse(QJsonObject responseData) {
|
|||||||
m_data->yggdrasilToken.validity = Katabasis::Validity::Certain;
|
m_data->yggdrasilToken.validity = Katabasis::Validity::Certain;
|
||||||
m_data->yggdrasilToken.issueInstant = QDateTime::currentDateTimeUtc();
|
m_data->yggdrasilToken.issueInstant = QDateTime::currentDateTimeUtc();
|
||||||
|
|
||||||
|
// Get UUID here since we need it for later
|
||||||
|
auto profile = responseData.value("selectedProfile");
|
||||||
|
if (!profile.isObject()) {
|
||||||
|
changeState(AccountTaskState::STATE_FAILED_HARD, tr("Authentication server didn't send a selected profile."));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto profileObj = profile.toObject();
|
||||||
|
for (auto i = profileObj.constBegin(); i != profileObj.constEnd(); ++i) {
|
||||||
|
if (i.key() == "name" && i.value().isString()) {
|
||||||
|
m_data->minecraftProfile.name = i->toString();
|
||||||
|
}
|
||||||
|
else if (i.key() == "id" && i.value().isString()) {
|
||||||
|
m_data->minecraftProfile.id = i->toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_data->minecraftProfile.id.isEmpty()) {
|
||||||
|
changeState(AccountTaskState::STATE_FAILED_HARD, tr("Authentication server didn't send a UUID in selected profile."));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// We've made it through the minefield of possible errors. Return true to indicate that
|
// We've made it through the minefield of possible errors. Return true to indicate that
|
||||||
// we've succeeded.
|
// we've succeeded.
|
||||||
qDebug() << "Finished reading authentication response.";
|
qDebug() << "Finished reading authentication response.";
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
#include "Mojang.h"
|
#include "Mojang.h"
|
||||||
|
|
||||||
#include "minecraft/auth/steps/YggdrasilStep.h"
|
#include "minecraft/auth/steps/YggdrasilStep.h"
|
||||||
#include "minecraft/auth/steps/MinecraftProfileStep.h"
|
#include "minecraft/auth/steps/MinecraftProfileStepMojang.h"
|
||||||
#include "minecraft/auth/steps/MigrationEligibilityStep.h"
|
#include "minecraft/auth/steps/MigrationEligibilityStep.h"
|
||||||
#include "minecraft/auth/steps/GetSkinStep.h"
|
#include "minecraft/auth/steps/GetSkinStep.h"
|
||||||
|
|
||||||
@ -10,7 +10,7 @@ MojangRefresh::MojangRefresh(
|
|||||||
QObject *parent
|
QObject *parent
|
||||||
) : AuthFlow(data, parent) {
|
) : AuthFlow(data, parent) {
|
||||||
m_steps.append(new YggdrasilStep(m_data, QString()));
|
m_steps.append(new YggdrasilStep(m_data, QString()));
|
||||||
m_steps.append(new MinecraftProfileStep(m_data));
|
m_steps.append(new MinecraftProfileStepMojang(m_data));
|
||||||
m_steps.append(new MigrationEligibilityStep(m_data));
|
m_steps.append(new MigrationEligibilityStep(m_data));
|
||||||
m_steps.append(new GetSkinStep(m_data));
|
m_steps.append(new GetSkinStep(m_data));
|
||||||
}
|
}
|
||||||
@ -21,7 +21,7 @@ MojangLogin::MojangLogin(
|
|||||||
QObject *parent
|
QObject *parent
|
||||||
): AuthFlow(data, parent), m_password(password) {
|
): AuthFlow(data, parent), m_password(password) {
|
||||||
m_steps.append(new YggdrasilStep(m_data, m_password));
|
m_steps.append(new YggdrasilStep(m_data, m_password));
|
||||||
m_steps.append(new MinecraftProfileStep(m_data));
|
m_steps.append(new MinecraftProfileStepMojang(m_data));
|
||||||
m_steps.append(new MigrationEligibilityStep(m_data));
|
m_steps.append(new MigrationEligibilityStep(m_data));
|
||||||
m_steps.append(new GetSkinStep(m_data));
|
m_steps.append(new GetSkinStep(m_data));
|
||||||
}
|
}
|
||||||
|
17
launcher/minecraft/auth/flows/Offline.cpp
Normal file
17
launcher/minecraft/auth/flows/Offline.cpp
Normal 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));
|
||||||
|
}
|
22
launcher/minecraft/auth/flows/Offline.h
Normal file
22
launcher/minecraft/auth/flows/Offline.h
Normal 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
|
||||||
|
);
|
||||||
|
};
|
@ -50,7 +50,9 @@ void LauncherLoginStep::onRequestDone(
|
|||||||
auto requestor = qobject_cast<AuthRequest *>(QObject::sender());
|
auto requestor = qobject_cast<AuthRequest *>(QObject::sender());
|
||||||
requestor->deleteLater();
|
requestor->deleteLater();
|
||||||
|
|
||||||
|
#ifndef NDEBUG
|
||||||
qDebug() << data;
|
qDebug() << data;
|
||||||
|
#endif
|
||||||
if (error != QNetworkReply::NoError) {
|
if (error != QNetworkReply::NoError) {
|
||||||
qWarning() << "Reply error:" << error;
|
qWarning() << "Reply error:" << error;
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
|
@ -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 "MSAStep.h"
|
||||||
|
|
||||||
#include <QNetworkRequest>
|
#include <QNetworkRequest>
|
||||||
@ -12,9 +47,10 @@ using OAuth2 = Katabasis::DeviceFlow;
|
|||||||
using Activity = Katabasis::Activity;
|
using Activity = Katabasis::Activity;
|
||||||
|
|
||||||
MSAStep::MSAStep(AccountData* data, Action action) : AuthStep(data), m_action(action) {
|
MSAStep::MSAStep(AccountData* data, Action action) : AuthStep(data), m_action(action) {
|
||||||
|
m_clientId = APPLICATION->getMSAClientID();
|
||||||
OAuth2::Options opts;
|
OAuth2::Options opts;
|
||||||
opts.scope = "XboxLive.signin offline_access";
|
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.authorizationUrl = "https://login.microsoftonline.com/consumers/oauth2/v2.0/devicecode";
|
||||||
opts.accessTokenUrl = "https://login.microsoftonline.com/consumers/oauth2/v2.0/token";
|
opts.accessTokenUrl = "https://login.microsoftonline.com/consumers/oauth2/v2.0/token";
|
||||||
|
|
||||||
@ -48,6 +84,10 @@ void MSAStep::rehydrate() {
|
|||||||
void MSAStep::perform() {
|
void MSAStep::perform() {
|
||||||
switch(m_action) {
|
switch(m_action) {
|
||||||
case Refresh: {
|
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();
|
m_oauth2->refresh();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -57,6 +97,7 @@ void MSAStep::perform() {
|
|||||||
m_oauth2->setExtraRequestParams(extraOpts);
|
m_oauth2->setExtraRequestParams(extraOpts);
|
||||||
|
|
||||||
*m_data = AccountData();
|
*m_data = AccountData();
|
||||||
|
m_data->msaClientID = m_clientId;
|
||||||
m_oauth2->login();
|
m_oauth2->login();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -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
|
#pragma once
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
@ -29,4 +63,5 @@ private slots:
|
|||||||
private:
|
private:
|
||||||
Katabasis::DeviceFlow *m_oauth2 = nullptr;
|
Katabasis::DeviceFlow *m_oauth2 = nullptr;
|
||||||
Action m_action;
|
Action m_action;
|
||||||
|
QString m_clientId;
|
||||||
};
|
};
|
||||||
|
@ -56,6 +56,14 @@ void MinecraftProfileStep::onRequestDone(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (error != QNetworkReply::NoError) {
|
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(
|
emit finished(
|
||||||
AccountTaskState::STATE_FAILED_SOFT,
|
AccountTaskState::STATE_FAILED_SOFT,
|
||||||
tr("Minecraft Java profile acquisition failed.")
|
tr("Minecraft Java profile acquisition failed.")
|
||||||
|
94
launcher/minecraft/auth/steps/MinecraftProfileStepMojang.cpp
Normal file
94
launcher/minecraft/auth/steps/MinecraftProfileStepMojang.cpp
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
#include "MinecraftProfileStepMojang.h"
|
||||||
|
|
||||||
|
#include <QNetworkRequest>
|
||||||
|
|
||||||
|
#include "minecraft/auth/AuthRequest.h"
|
||||||
|
#include "minecraft/auth/Parsers.h"
|
||||||
|
|
||||||
|
MinecraftProfileStepMojang::MinecraftProfileStepMojang(AccountData* data) : AuthStep(data) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
MinecraftProfileStepMojang::~MinecraftProfileStepMojang() noexcept = default;
|
||||||
|
|
||||||
|
QString MinecraftProfileStepMojang::describe() {
|
||||||
|
return tr("Fetching the Minecraft profile.");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void MinecraftProfileStepMojang::perform() {
|
||||||
|
if (m_data->minecraftProfile.id.isEmpty()) {
|
||||||
|
emit finished(AccountTaskState::STATE_FAILED_HARD, tr("A UUID is required to get the profile."));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// use session server instead of profile due to profile endpoint being locked for locked Mojang accounts
|
||||||
|
QUrl url = QUrl("https://sessionserver.mojang.com/session/minecraft/profile/" + m_data->minecraftProfile.id);
|
||||||
|
QNetworkRequest req = QNetworkRequest(url);
|
||||||
|
AuthRequest *request = new AuthRequest(this);
|
||||||
|
connect(request, &AuthRequest::finished, this, &MinecraftProfileStepMojang::onRequestDone);
|
||||||
|
request->get(req);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MinecraftProfileStepMojang::rehydrate() {
|
||||||
|
// NOOP, for now. We only save bools and there's nothing to check.
|
||||||
|
}
|
||||||
|
|
||||||
|
void MinecraftProfileStepMojang::onRequestDone(
|
||||||
|
QNetworkReply::NetworkError error,
|
||||||
|
QByteArray data,
|
||||||
|
QList<QNetworkReply::RawHeaderPair> headers
|
||||||
|
) {
|
||||||
|
auto requestor = qobject_cast<AuthRequest *>(QObject::sender());
|
||||||
|
requestor->deleteLater();
|
||||||
|
|
||||||
|
#ifndef NDEBUG
|
||||||
|
qDebug() << data;
|
||||||
|
#endif
|
||||||
|
if (error == QNetworkReply::ContentNotFoundError) {
|
||||||
|
// NOTE: Succeed even if we do not have a profile. This is a valid account state.
|
||||||
|
if(m_data->type == AccountType::Mojang) {
|
||||||
|
m_data->minecraftEntitlement.canPlayMinecraft = false;
|
||||||
|
m_data->minecraftEntitlement.ownsMinecraft = false;
|
||||||
|
}
|
||||||
|
m_data->minecraftProfile = MinecraftProfile();
|
||||||
|
emit finished(
|
||||||
|
AccountTaskState::STATE_SUCCEEDED,
|
||||||
|
tr("Account has no Minecraft profile.")
|
||||||
|
);
|
||||||
|
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.")
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(!Parsers::parseMinecraftProfileMojang(data, m_data->minecraftProfile)) {
|
||||||
|
m_data->minecraftProfile = MinecraftProfile();
|
||||||
|
emit finished(
|
||||||
|
AccountTaskState::STATE_FAILED_SOFT,
|
||||||
|
tr("Minecraft Java profile response could not be parsed")
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(m_data->type == AccountType::Mojang) {
|
||||||
|
auto validProfile = m_data->minecraftProfile.validity == Katabasis::Validity::Certain;
|
||||||
|
m_data->minecraftEntitlement.canPlayMinecraft = validProfile;
|
||||||
|
m_data->minecraftEntitlement.ownsMinecraft = validProfile;
|
||||||
|
}
|
||||||
|
emit finished(
|
||||||
|
AccountTaskState::STATE_WORKING,
|
||||||
|
tr("Minecraft Java profile acquisition succeeded.")
|
||||||
|
);
|
||||||
|
}
|
22
launcher/minecraft/auth/steps/MinecraftProfileStepMojang.h
Normal file
22
launcher/minecraft/auth/steps/MinecraftProfileStepMojang.h
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <QObject>
|
||||||
|
|
||||||
|
#include "QObjectPtr.h"
|
||||||
|
#include "minecraft/auth/AuthStep.h"
|
||||||
|
|
||||||
|
|
||||||
|
class MinecraftProfileStepMojang : public AuthStep {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit MinecraftProfileStepMojang(AccountData *data);
|
||||||
|
virtual ~MinecraftProfileStepMojang() noexcept;
|
||||||
|
|
||||||
|
void perform() override;
|
||||||
|
void rehydrate() override;
|
||||||
|
|
||||||
|
QString describe() override;
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void onRequestDone(QNetworkReply::NetworkError, QByteArray, QList<QNetworkReply::RawHeaderPair>);
|
||||||
|
};
|
18
launcher/minecraft/auth/steps/OfflineStep.cpp
Normal file
18
launcher/minecraft/auth/steps/OfflineStep.cpp
Normal 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."));
|
||||||
|
}
|
19
launcher/minecraft/auth/steps/OfflineStep.h
Normal file
19
launcher/minecraft/auth/steps/OfflineStep.h
Normal 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;
|
||||||
|
};
|
@ -65,7 +65,7 @@ void XboxAuthorizationStep::onRequestDone(
|
|||||||
if(!processSTSError(error, data, headers)) {
|
if(!processSTSError(error, data, headers)) {
|
||||||
emit finished(
|
emit finished(
|
||||||
AccountTaskState::STATE_FAILED_SOFT,
|
AccountTaskState::STATE_FAILED_SOFT,
|
||||||
tr("Failed to get authorization for %1 services. Error %1.").arg(m_authorizationKind, error)
|
tr("Failed to get authorization for %1 services. Error %2.").arg(m_authorizationKind, error)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
@ -88,7 +88,7 @@ void DirectJavaLaunch::on_state(LoggedProcess::State state)
|
|||||||
case LoggedProcess::FailedToStart:
|
case LoggedProcess::FailedToStart:
|
||||||
{
|
{
|
||||||
//: Error message displayed if instance can't start
|
//: 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);
|
emit logLine(reason, MessageLevel::Fatal);
|
||||||
emitFailed(tr(reason));
|
emitFailed(tr(reason));
|
||||||
return;
|
return;
|
||||||
|
@ -17,8 +17,8 @@
|
|||||||
#include <minecraft/MinecraftInstance.h>
|
#include <minecraft/MinecraftInstance.h>
|
||||||
#include <launch/LaunchTask.h>
|
#include <launch/LaunchTask.h>
|
||||||
|
|
||||||
#include <quazip.h>
|
#include <quazip/quazip.h>
|
||||||
#include <quazipdir.h>
|
#include <quazip/quazipdir.h>
|
||||||
#include "MMCZip.h"
|
#include "MMCZip.h"
|
||||||
#include "FileSystem.h"
|
#include "FileSystem.h"
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
|
@ -25,6 +25,19 @@
|
|||||||
|
|
||||||
LauncherPartLaunch::LauncherPartLaunch(LaunchTask *parent) : LaunchStep(parent)
|
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::log, this, &LauncherPartLaunch::logLines);
|
||||||
connect(&m_process, &LoggedProcess::stateChanged, this, &LauncherPartLaunch::on_state);
|
connect(&m_process, &LoggedProcess::stateChanged, this, &LauncherPartLaunch::on_state);
|
||||||
}
|
}
|
||||||
@ -141,7 +154,7 @@ void LauncherPartLaunch::on_state(LoggedProcess::State state)
|
|||||||
case LoggedProcess::FailedToStart:
|
case LoggedProcess::FailedToStart:
|
||||||
{
|
{
|
||||||
//: Error message displayed if instace can't start
|
//: 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);
|
emit logLine(reason, MessageLevel::Fatal);
|
||||||
emitFailed(tr(reason));
|
emitFailed(tr(reason));
|
||||||
return;
|
return;
|
||||||
@ -155,6 +168,9 @@ void LauncherPartLaunch::on_state(LoggedProcess::State state)
|
|||||||
}
|
}
|
||||||
case LoggedProcess::Finished:
|
case LoggedProcess::Finished:
|
||||||
{
|
{
|
||||||
|
if (APPLICATION->settings()->get("CloseAfterLaunch").toBool())
|
||||||
|
APPLICATION->showMainWindow();
|
||||||
|
|
||||||
m_parent->setPid(-1);
|
m_parent->setPid(-1);
|
||||||
// if the exit code wasn't 0, report this as a crash
|
// if the exit code wasn't 0, report this as a crash
|
||||||
auto exitCode = m_process.exitCode();
|
auto exitCode = m_process.exitCode();
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user