Compare commits
342 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 | |||
4fe13c64a1 | |||
b3c2a56ece | |||
9c57b54a81 | |||
b131d3b2ec | |||
16bfafa29e | |||
f714adf6d2 | |||
39bd04f06f | |||
d755174bee | |||
1229e90817 | |||
5a638fa977 | |||
5e9d49a910 | |||
9a8599e4ba | |||
2d68308d49 | |||
0dd1c26cf3 | |||
881b2f2b38 | |||
6d1f9d4d02 | |||
da70122d9c |
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)
|
||||||
|
|
||||||
|
5
.github/ISSUE_TEMPLATE/rfc.yml
vendored
5
.github/ISSUE_TEMPLATE/rfc.yml
vendored
@ -1,7 +1,7 @@
|
|||||||
# Template based on https://gitlab.archlinux.org/archlinux/rfcs/-/blob/0ba3b61e987e197f8d1901709409b8564958f78a/rfcs/0000-template.rst
|
# Template based on https://gitlab.archlinux.org/archlinux/rfcs/-/blob/0ba3b61e987e197f8d1901709409b8564958f78a/rfcs/0000-template.rst
|
||||||
name: Request for Comment (RFC)
|
name: Request for Comment (RFC)
|
||||||
description: Propose a larger change and start a discussion.
|
description: Propose a larger change and start a discussion.
|
||||||
labels: [RFC]
|
labels: [rfc]
|
||||||
body:
|
body:
|
||||||
- type: markdown
|
- type: markdown
|
||||||
attributes:
|
attributes:
|
||||||
@ -21,8 +21,7 @@ body:
|
|||||||
Introduce the topic. If this is a not-well-known section of PolyMC, a detailed explanation of the background is recommended.
|
Introduce the topic. If this is a not-well-known section of PolyMC, a detailed explanation of the background is recommended.
|
||||||
Some example points of discussion:
|
Some example points of discussion:
|
||||||
- What specific problems are you facing right now that you're trying to address?
|
- What specific problems are you facing right now that you're trying to address?
|
||||||
- Are there any previous discussions? Link to them and summarize them (don't
|
- Are there any previous discussions? Link to them and summarize them (don't force your readers to read them though!).
|
||||||
- force your readers to read them though!).
|
|
||||||
- Is there any precedent set by other software? If so, link to resources.
|
- 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.
|
placeholder: I don't like cats. I think many users also don't like cats.
|
||||||
validations:
|
validations:
|
||||||
|
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:
|
||||||
|
2
.github/scripts/prepare_JREs.sh
vendored
2
.github/scripts/prepare_JREs.sh
vendored
@ -1,6 +1,6 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
URL_JDK8="https://api.adoptium.net/v3/binary/latest/8/ga/linux/x64/jre/hotspot/normal/eclipse"
|
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"
|
URL_JDK17="https://api.adoptium.net/v3/binary/latest/17/ga/linux/x64/jre/hotspot/normal/eclipse"
|
||||||
|
|
||||||
mkdir -p JREs
|
mkdir -p JREs
|
||||||
|
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 }}
|
297
.github/workflows/build.yml
vendored
297
.github/workflows/build.yml
vendored
@ -16,58 +16,52 @@ jobs:
|
|||||||
include:
|
include:
|
||||||
|
|
||||||
- os: ubuntu-20.04
|
- os: ubuntu-20.04
|
||||||
qt_version: 5.12.8
|
|
||||||
qt_host: linux
|
|
||||||
|
|
||||||
- os: ubuntu-20.04
|
- os: ubuntu-20.04
|
||||||
qt_version: 5.15.2
|
appimage: true
|
||||||
qt_host: linux
|
|
||||||
app_image: true
|
|
||||||
|
|
||||||
- os: windows-2022
|
- os: windows-2022
|
||||||
qt_version: 5.15.2
|
name: "Windows-i686"
|
||||||
qt_host: windows
|
msystem: mingw32
|
||||||
qt_arch: win32_mingw81
|
|
||||||
|
- os: windows-2022
|
||||||
|
name: "Windows-x86_64"
|
||||||
|
msystem: mingw64
|
||||||
|
|
||||||
- os: macos-11
|
- os: macos-11
|
||||||
qt_version: 5.12.12
|
macosx_deployment_target: 10.13
|
||||||
qt_host: mac
|
|
||||||
macosx_deployment_target: 10.12
|
|
||||||
|
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
|
|
||||||
env:
|
env:
|
||||||
MACOSX_DEPLOYMENT_TARGET: ${{ matrix.macosx_deployment_target }}
|
MACOSX_DEPLOYMENT_TARGET: ${{ matrix.macosx_deployment_target }}
|
||||||
INSTALL_DIR: "install"
|
INSTALL_DIR: "install"
|
||||||
|
INSTALL_PORTABLE_DIR: "install-portable"
|
||||||
|
INSTALL_APPIMAGE_DIR: "install-appdir"
|
||||||
BUILD_DIR: "build"
|
BUILD_DIR: "build"
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Install 32bit mingw on Windows
|
##
|
||||||
if: runner.os == 'Windows'
|
# PREPARE
|
||||||
uses: egor-tensin/setup-mingw@v2
|
##
|
||||||
with:
|
|
||||||
platform: x86
|
|
||||||
|
|
||||||
- name: Install 32bit zlib via Strawberry on Windows
|
|
||||||
if: runner.os == 'Windows'
|
|
||||||
run: |
|
|
||||||
choco install strawberryperl -y --force --x86
|
|
||||||
|
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v3
|
||||||
with:
|
with:
|
||||||
submodules: 'true'
|
submodules: 'true'
|
||||||
|
|
||||||
# We need to do this here because it inexplicably fails if we split the step
|
- name: 'Setup MSYS2'
|
||||||
- name: Download and install OpenSSL libs on Windows
|
|
||||||
if: runner.os == 'Windows'
|
if: runner.os == 'Windows'
|
||||||
run: |
|
uses: msys2/setup-msys2@v2
|
||||||
python -m pip install --upgrade pip
|
with:
|
||||||
python -m pip install aqtinstall==2.0.5
|
msystem: ${{ matrix.msystem }}
|
||||||
python -m aqt install-tool -O "${{ github.workspace }}\Qt\" windows desktop tools_openssl_x86
|
update: true
|
||||||
mkdir ${{ env.INSTALL_DIR }}
|
install: >-
|
||||||
copy "${{ github.workspace }}\Qt\Tools\OpenSSL\Win_x86\bin\libssl-1_1.dll" "${{ github.workspace }}\${{ env.INSTALL_DIR }}\"
|
git
|
||||||
copy "${{ github.workspace }}\Qt\Tools\OpenSSL\Win_x86\bin\libcrypto-1_1.dll" "${{ github.workspace }}\${{ env.INSTALL_DIR }}\"
|
pacboy: >-
|
||||||
|
toolchain:p
|
||||||
|
cmake:p
|
||||||
|
ninja:p
|
||||||
|
qt5:p
|
||||||
|
|
||||||
- name: Set short version
|
- name: Set short version
|
||||||
shell: bash
|
shell: bash
|
||||||
@ -75,148 +69,187 @@ jobs:
|
|||||||
ver_short=`git rev-parse --short HEAD`
|
ver_short=`git rev-parse --short HEAD`
|
||||||
echo "VERSION=$ver_short" >> $GITHUB_ENV
|
echo "VERSION=$ver_short" >> $GITHUB_ENV
|
||||||
|
|
||||||
- name: Install OpenJDK
|
- name: Install Qt (macOS)
|
||||||
uses: AdoptOpenJDK/install-jdk@v1
|
if: runner.os == 'macOS'
|
||||||
with:
|
run: |
|
||||||
version: '17'
|
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: Cache Qt
|
- name: Install Qt (Linux)
|
||||||
id: cache-qt
|
if: runner.os == 'Linux'
|
||||||
uses: actions/cache@v2
|
|
||||||
with:
|
|
||||||
path: "${{ github.workspace }}/Qt/"
|
|
||||||
key: ${{ runner.os }}-${{ matrix.qt_version }}-${{ matrix.qt_arch }}-qt_cache
|
|
||||||
|
|
||||||
- name: Install Qt
|
|
||||||
if: runner.os != 'Linux' || matrix.app_image == true
|
|
||||||
uses: jurplel/install-qt-action@v2
|
|
||||||
with:
|
|
||||||
version: ${{ matrix.qt_version }}
|
|
||||||
host: ${{ matrix.qt_host }}
|
|
||||||
arch: ${{ matrix.qt_arch }}
|
|
||||||
cached: ${{ steps.cache-qt.outputs.cache-hit }}
|
|
||||||
dir: "${{ github.workspace }}/Qt/"
|
|
||||||
|
|
||||||
- name: Install System Qt on Linux
|
|
||||||
if: runner.os == 'Linux' && matrix.app_image != true
|
|
||||||
run: |
|
run: |
|
||||||
sudo apt-get -y update
|
sudo apt-get -y update
|
||||||
sudo apt-get -y install qtbase5-dev qtchooser qt5-qmake qtbase5-dev-tools libqt5core5a libqt5network5 libqt5gui5
|
sudo apt-get -y install qtbase5-dev qtchooser qt5-qmake qtbase5-dev-tools libqt5core5a libqt5network5 libqt5gui5 ninja-build
|
||||||
|
|
||||||
- name: Install Ninja
|
- name: Prepare AppImage (Linux)
|
||||||
uses: urkle/action-get-ninja@v1
|
if: runner.os == 'Linux' && matrix.appimage == true
|
||||||
|
|
||||||
- name: Download linuxdeploy family for AppImage on Linux
|
|
||||||
if: matrix.app_image == true
|
|
||||||
run: |
|
run: |
|
||||||
wget "https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-x86_64.AppImage"
|
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-appimage/releases/download/continuous/linuxdeploy-plugin-appimage-x86_64.AppImage"
|
||||||
wget "https://github.com/linuxdeploy/linuxdeploy-plugin-qt/releases/download/continuous/linuxdeploy-plugin-qt-x86_64.AppImage"
|
wget "https://github.com/linuxdeploy/linuxdeploy-plugin-qt/releases/download/continuous/linuxdeploy-plugin-qt-x86_64.AppImage"
|
||||||
|
|
||||||
- name: Download JREs for AppImage on Linux
|
|
||||||
if: matrix.app_image == true
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
${{ github.workspace }}/.github/scripts/prepare_JREs.sh
|
${{ github.workspace }}/.github/scripts/prepare_JREs.sh
|
||||||
|
|
||||||
- name: Configure CMake
|
##
|
||||||
if: runner.os != 'Linux'
|
# CONFIGURE
|
||||||
run: |
|
##
|
||||||
cmake -S . -B ${{ env.BUILD_DIR }} -DCMAKE_INSTALL_PREFIX=${{ env.INSTALL_DIR }} -DCMAKE_BUILD_TYPE=${{ inputs.build_type }} -G Ninja
|
|
||||||
|
|
||||||
- name: Configure CMake on Linux
|
- 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'
|
if: runner.os == 'Linux'
|
||||||
run: |
|
run: |
|
||||||
cmake -S . -B ${{ env.BUILD_DIR }} -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_BUILD_TYPE=${{ inputs.build_type }} -DLauncher_PORTABLE=OFF -G Ninja
|
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
|
- name: Build
|
||||||
|
if: runner.os != 'Windows'
|
||||||
run: |
|
run: |
|
||||||
cmake --build ${{ env.BUILD_DIR }}
|
cmake --build ${{ env.BUILD_DIR }}
|
||||||
|
|
||||||
- name: Install
|
- name: Build (Windows)
|
||||||
if: runner.os != 'Linux'
|
if: runner.os == 'Windows'
|
||||||
|
shell: msys2 {0}
|
||||||
|
run: |
|
||||||
|
cmake --build ${{ env.BUILD_DIR }}
|
||||||
|
|
||||||
|
##
|
||||||
|
# PACKAGE BUILDS
|
||||||
|
##
|
||||||
|
|
||||||
|
- name: Package (macOS)
|
||||||
|
if: runner.os == 'macOS'
|
||||||
run: |
|
run: |
|
||||||
cmake --install ${{ env.BUILD_DIR }}
|
cmake --install ${{ env.BUILD_DIR }}
|
||||||
|
|
||||||
- name: Install on Linux
|
cd ${{ env.INSTALL_DIR }}
|
||||||
if: runner.os == 'Linux'
|
chmod +x "PolyMC.app/Contents/MacOS/polymc"
|
||||||
run: |
|
sudo codesign --sign - --deep --force --entitlements "../program_info/App.entitlements" --options runtime "PolyMC.app/Contents/MacOS/polymc"
|
||||||
DESTDIR=${{ env.INSTALL_DIR }} cmake --install ${{ env.BUILD_DIR }}
|
tar -czf ../PolyMC.tar.gz *
|
||||||
|
|
||||||
- name: Bundle AppImage
|
- name: Package (Windows)
|
||||||
if: matrix.app_image == true
|
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
|
shell: bash
|
||||||
run: |
|
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"
|
export OUTPUT="PolyMC-${{ runner.os }}-${{ env.VERSION }}-${{ inputs.build_type }}-x86_64.AppImage"
|
||||||
|
|
||||||
chmod +x linuxdeploy-*.AppImage
|
chmod +x linuxdeploy-*.AppImage
|
||||||
|
|
||||||
mkdir -p ${{ env.INSTALL_DIR }}/usr/lib/jvm/java-{8,17}-openjdk
|
mkdir -p ${{ env.INSTALL_APPIMAGE_DIR }}/usr/lib/jvm/java-{8,17}-openjdk
|
||||||
|
|
||||||
cp -r ${{ github.workspace }}/JREs/jre8/* ${{ env.INSTALL_DIR }}/usr/lib/jvm/java-8-openjdk
|
cp -r ${{ github.workspace }}/JREs/jre8/* ${{ env.INSTALL_APPIMAGE_DIR }}/usr/lib/jvm/java-8-openjdk
|
||||||
|
|
||||||
cp -r ${{ github.workspace }}/JREs/jre17/* ${{ env.INSTALL_DIR }}/usr/lib/jvm/java-17-openjdk
|
cp -r ${{ github.workspace }}/JREs/jre17/* ${{ env.INSTALL_APPIMAGE_DIR }}/usr/lib/jvm/java-17-openjdk
|
||||||
|
|
||||||
export LD_LIBRARY_PATH="${LD_LIBRARY_PATH}:${{ env.INSTALL_DIR }}/usr/lib"
|
LD_LIBRARY_PATH="${LD_LIBRARY_PATH}:${{ env.INSTALL_APPIMAGE_DIR }}/usr/lib"
|
||||||
LD_LIBRARY_PATH="${LD_LIBRARY_PATH}:${{ env.INSTALL_DIR }}/usr/lib/jvm/java-8-openjdk/lib/amd64/server"
|
LD_LIBRARY_PATH="${LD_LIBRARY_PATH}:${{ env.INSTALL_APPIMAGE_DIR }}/usr/lib/jvm/java-8-openjdk/lib/amd64/server"
|
||||||
LD_LIBRARY_PATH="${LD_LIBRARY_PATH}:${{ env.INSTALL_DIR }}/usr/lib/jvm/java-8-openjdk/lib/amd64"
|
LD_LIBRARY_PATH="${LD_LIBRARY_PATH}:${{ env.INSTALL_APPIMAGE_DIR }}/usr/lib/jvm/java-8-openjdk/lib/amd64"
|
||||||
LD_LIBRARY_PATH="${LD_LIBRARY_PATH}:${{ env.INSTALL_DIR }}/usr/lib/jvm/java-17-openjdk/lib/server"
|
LD_LIBRARY_PATH="${LD_LIBRARY_PATH}:${{ env.INSTALL_APPIMAGE_DIR }}/usr/lib/jvm/java-17-openjdk/lib/server"
|
||||||
LD_LIBRARY_PATH="${LD_LIBRARY_PATH}:${{ env.INSTALL_DIR }}/usr/lib/jvm/java-17-openjdk/lib"
|
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_DIR }} --output appimage --plugin qt -i ${{ env.INSTALL_DIR }}/usr/share/icons/hicolor/scalable/apps/org.polymc.PolyMC.svg
|
./linuxdeploy-x86_64.AppImage --appdir ${{ env.INSTALL_APPIMAGE_DIR }} --output appimage --plugin qt -i ${{ env.INSTALL_APPIMAGE_DIR }}/usr/share/icons/hicolor/scalable/apps/org.polymc.PolyMC.svg
|
||||||
|
|
||||||
- name: Run windeployqt
|
##
|
||||||
if: runner.os == 'Windows'
|
# UPLOAD BUILDS
|
||||||
run: |
|
##
|
||||||
windeployqt --no-translations --no-system-d3d-compiler --no-opengl-sw "${{ env.INSTALL_DIR }}/polymc.exe"
|
|
||||||
|
|
||||||
- name: Run macdeployqt
|
- name: Upload binary tarball (macOS)
|
||||||
if: runner.os == 'macOS'
|
if: runner.os == 'macOS'
|
||||||
run: |
|
uses: actions/upload-artifact@v3
|
||||||
cd ${{ env.INSTALL_DIR }}
|
|
||||||
macdeployqt "PolyMC.app" -executable="PolyMC.app/Contents/MacOS/polymc" -always-overwrite
|
|
||||||
|
|
||||||
- name: chmod binary on macOS
|
|
||||||
if: runner.os == 'macOS'
|
|
||||||
run: |
|
|
||||||
chmod +x "${{ github.workspace }}/${{ env.INSTALL_DIR }}/PolyMC.app/Contents/MacOS/polymc"
|
|
||||||
|
|
||||||
- name: tar bundle on macOS
|
|
||||||
if: runner.os == 'macOS'
|
|
||||||
run: |
|
|
||||||
cd ${{ env.INSTALL_DIR }}
|
|
||||||
tar -czf ../PolyMC.tar.gz *
|
|
||||||
|
|
||||||
- name: tar on Linux
|
|
||||||
if: runner.os == 'Linux' && matrix.app_image != true
|
|
||||||
run: |
|
|
||||||
cd ${{ env.INSTALL_DIR }}
|
|
||||||
tar -czf ../PolyMC.tar.gz *
|
|
||||||
|
|
||||||
- name: Upload Linux tar.gz
|
|
||||||
if: runner.os == 'Linux' && matrix.app_image != true
|
|
||||||
uses: actions/upload-artifact@v2
|
|
||||||
with:
|
with:
|
||||||
name: PolyMC-${{ runner.os }}-${{ env.VERSION }}-${{ inputs.build_type }}
|
name: PolyMC-${{ runner.os }}-${{ env.VERSION }}-${{ inputs.build_type }}
|
||||||
path: PolyMC.tar.gz
|
path: PolyMC.tar.gz
|
||||||
|
|
||||||
- name: Upload AppImage for Linux
|
- name: Upload binary zip (Windows)
|
||||||
if: matrix.app_image == true
|
if: runner.os == 'Windows'
|
||||||
uses: actions/upload-artifact@v2
|
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:
|
with:
|
||||||
name: PolyMC-${{ runner.os }}-${{ env.VERSION }}-${{ inputs.build_type }}-x86_64.AppImage
|
name: PolyMC-${{ runner.os }}-${{ env.VERSION }}-${{ inputs.build_type }}-x86_64.AppImage
|
||||||
path: PolyMC-${{ runner.os }}-${{ env.VERSION }}-${{ inputs.build_type }}-x86_64.AppImage
|
path: PolyMC-${{ runner.os }}-${{ env.VERSION }}-${{ inputs.build_type }}-x86_64.AppImage
|
||||||
|
|
||||||
- name: Upload package for Windows
|
|
||||||
if: runner.os == 'Windows'
|
|
||||||
uses: actions/upload-artifact@v2
|
|
||||||
with:
|
|
||||||
name: PolyMC-${{ runner.os }}-${{ env.VERSION }}-${{ inputs.build_type }}
|
|
||||||
path: ${{ env.INSTALL_DIR }}/**
|
|
||||||
|
|
||||||
- name: Upload package for macOS
|
|
||||||
if: runner.os == 'macOS'
|
|
||||||
uses: actions/upload-artifact@v2
|
|
||||||
with:
|
|
||||||
name: PolyMC-${{ runner.os }}-${{ env.VERSION }}-${{ inputs.build_type }}
|
|
||||||
path: PolyMC.tar.gz
|
|
||||||
|
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);
|
||||||
|
}
|
10
.github/workflows/trigger_builds.yml
vendored
10
.github/workflows/trigger_builds.yml
vendored
@ -9,12 +9,16 @@ on:
|
|||||||
- '**/LICENSE'
|
- '**/LICENSE'
|
||||||
- 'flake.lock'
|
- 'flake.lock'
|
||||||
- '**.nix'
|
- '**.nix'
|
||||||
|
- 'packages/**'
|
||||||
|
- '.github/ISSUE_TEMPLATE/**'
|
||||||
pull_request:
|
pull_request:
|
||||||
paths-ignore:
|
paths-ignore:
|
||||||
- '**.md'
|
- '**.md'
|
||||||
- '**/LICENSE'
|
- '**/LICENSE'
|
||||||
- 'flake.lock'
|
- 'flake.lock'
|
||||||
- '**.nix'
|
- '**.nix'
|
||||||
|
- 'packages/**'
|
||||||
|
- '.github/ISSUE_TEMPLATE/**'
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
@ -24,9 +28,3 @@ jobs:
|
|||||||
uses: ./.github/workflows/build.yml
|
uses: ./.github/workflows/build.yml
|
||||||
with:
|
with:
|
||||||
build_type: Debug
|
build_type: Debug
|
||||||
|
|
||||||
build_release:
|
|
||||||
name: Build Release
|
|
||||||
uses: ./.github/workflows/build.yml
|
|
||||||
with:
|
|
||||||
build_type: Release
|
|
||||||
|
101
.github/workflows/trigger_release.yml
vendored
101
.github/workflows/trigger_release.yml
vendored
@ -19,10 +19,37 @@ jobs:
|
|||||||
outputs:
|
outputs:
|
||||||
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
||||||
steps:
|
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
|
- name: Grab and store version
|
||||||
run: |
|
run: |
|
||||||
tag_name=$(echo ${{ github.ref }} | grep -oE "[^/]+$")
|
tag_name=$(echo ${{ github.ref }} | grep -oE "[^/]+$")
|
||||||
echo "VERSION=$tag_name" >> $GITHUB_ENV
|
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
|
- name: Create release
|
||||||
id: create_release
|
id: create_release
|
||||||
uses: softprops/action-gh-release@v1
|
uses: softprops/action-gh-release@v1
|
||||||
@ -33,67 +60,13 @@ jobs:
|
|||||||
name: PolyMC ${{ env.VERSION }}
|
name: PolyMC ${{ env.VERSION }}
|
||||||
draft: true
|
draft: true
|
||||||
prerelease: false
|
prerelease: false
|
||||||
|
files: |
|
||||||
upload_release:
|
PolyMC-Linux-${{ env.VERSION }}.tar.gz
|
||||||
needs: create_release
|
PolyMC-Linux-Portable-${{ env.VERSION }}.tar.gz
|
||||||
runs-on: ubuntu-latest
|
PolyMC-Linux-${{ env.VERSION }}-x86_64.AppImage
|
||||||
steps:
|
PolyMC-Windows-i686-${{ env.VERSION }}.zip
|
||||||
|
PolyMC-Windows-i686-Portable-${{ env.VERSION }}.zip
|
||||||
- name: Download artifacts
|
PolyMC-Windows-x86_64-${{ env.VERSION }}.zip
|
||||||
uses: actions/download-artifact@v2
|
PolyMC-Windows-x86_64-Portable-${{ env.VERSION }}.zip
|
||||||
|
PolyMC-macOS-${{ env.VERSION }}.tar.gz
|
||||||
- name: Grab and store version
|
PolyMC-${{ env.VERSION }}.tar.gz
|
||||||
run: |
|
|
||||||
tag_name=$(echo ${{ github.ref }} | grep -oE "[^/]+$")
|
|
||||||
echo "VERSION=$tag_name" >> $GITHUB_ENV
|
|
||||||
|
|
||||||
- name: Package artifacts properly
|
|
||||||
run: |
|
|
||||||
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-Windows* PolyMC-Windows-${{ env.VERSION }}
|
|
||||||
mv PolyMC-macOS*/PolyMC.tar.gz PolyMC-macOS-${{ env.VERSION }}.tar.gz
|
|
||||||
|
|
||||||
cd PolyMC-Windows-${{ env.VERSION }}
|
|
||||||
zip -r -9 ../PolyMC-Windows-${{ env.VERSION }}.zip *
|
|
||||||
cd ..
|
|
||||||
|
|
||||||
- name: Upload Linux asset
|
|
||||||
uses: actions/upload-release-asset@v1
|
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
with:
|
|
||||||
upload_url: ${{ needs.create_release.outputs.upload_url }}
|
|
||||||
asset_name: PolyMC-Linux-${{ env.VERSION }}.tar.gz
|
|
||||||
asset_path: PolyMC-Linux-${{ env.VERSION }}.tar.gz
|
|
||||||
asset_content_type: application/gzip
|
|
||||||
|
|
||||||
- name: Upload Linux AppImage asset
|
|
||||||
uses: actions/upload-release-asset@v1
|
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
with:
|
|
||||||
upload_url: ${{ needs.create_release.outputs.upload_url }}
|
|
||||||
asset_name: PolyMC-Linux-${{ env.VERSION }}-x86_64.AppImage
|
|
||||||
asset_path: PolyMC-Linux-${{ env.VERSION }}-x86_64.AppImage
|
|
||||||
asset_content_type: application/x-executable
|
|
||||||
|
|
||||||
- name: Upload Windows asset
|
|
||||||
uses: actions/upload-release-asset@v1
|
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
with:
|
|
||||||
upload_url: ${{ needs.create_release.outputs.upload_url }}
|
|
||||||
asset_name: PolyMC-Windows-${{ env.VERSION }}.zip
|
|
||||||
asset_path: PolyMC-Windows-${{ env.VERSION }}.zip
|
|
||||||
asset_content_type: application/zip
|
|
||||||
|
|
||||||
- name: Upload macOS asset
|
|
||||||
uses: actions/upload-release-asset@v1
|
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
with:
|
|
||||||
upload_url: ${{ needs.create_release.outputs.upload_url }}
|
|
||||||
asset_name: PolyMC-macOS-${{ env.VERSION }}.tar.gz
|
|
||||||
asset_path: PolyMC-macOS-${{ env.VERSION }}.tar.gz
|
|
||||||
asset_content_type: application/gzip
|
|
||||||
|
6
.gitignore
vendored
6
.gitignore
vendored
@ -14,6 +14,8 @@ CMakeLists.txt.user.*
|
|||||||
/.project
|
/.project
|
||||||
/.settings
|
/.settings
|
||||||
/.idea
|
/.idea
|
||||||
|
/.vscode
|
||||||
|
.clang-format
|
||||||
cmake-build-*/
|
cmake-build-*/
|
||||||
Debug
|
Debug
|
||||||
|
|
||||||
@ -42,3 +44,7 @@ run/
|
|||||||
|
|
||||||
# Nix/NixOS
|
# Nix/NixOS
|
||||||
result/
|
result/
|
||||||
|
|
||||||
|
# Flatpak
|
||||||
|
.flatpak-builder
|
||||||
|
flatbuild
|
||||||
|
4
.gitmodules
vendored
4
.gitmodules
vendored
@ -1,7 +1,7 @@
|
|||||||
[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
|
||||||
|
108
CMakeLists.txt
108
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,30 +43,43 @@ 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://polymc.org/feed/feed.xml" CACHE STRING "URL to fetch PolyMC'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_NEWS_OPEN_URL "https://polymc.org/news" CACHE STRING "URL that gets opened when the user clicks 'More News'")
|
||||||
set(Launcher_HELP_URL "https://polymc.org/wiki/%1" CACHE STRING "URL (with arg %1 to be substituted with page-id) that gets opened when the user requests help")
|
set(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 1)
|
set(Launcher_VERSION_MINOR 2)
|
||||||
set(Launcher_VERSION_HOTFIX 0)
|
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 Launcher's meta files from.")
|
set(Launcher_META_URL "https://meta.polymc.org/v1/" CACHE STRING "URL to fetch Launcher's meta files from.")
|
||||||
|
|
||||||
@ -76,6 +89,10 @@ set(Launcher_IMGUR_CLIENT_ID "5b97b0713fba4a3" CACHE STRING "Client ID you can g
|
|||||||
# MSA Client ID
|
# MSA Client ID
|
||||||
set(Launcher_MSA_CLIENT_ID "549033b2-1532-4d4e-ae77-1bbaa46f9d74" CACHE STRING "Client ID you can get from Microsoft Identity Platform when you register an application")
|
set(Launcher_MSA_CLIENT_ID "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.")
|
||||||
|
|
||||||
@ -83,7 +100,7 @@ set(Launcher_BUG_TRACKER_URL "https://github.com/PolyMC/PolyMC/issues" CACHE STR
|
|||||||
set(Launcher_TRANSLATIONS_URL "https://hosted.weblate.org/projects/polymc/polymc/" CACHE STRING "URL for the translations platform.")
|
set(Launcher_TRANSLATIONS_URL "https://hosted.weblate.org/projects/polymc/polymc/" CACHE STRING "URL for the translations platform.")
|
||||||
|
|
||||||
# Matrix Space
|
# Matrix Space
|
||||||
set(Launcher_MATRIX_URL "https://matrix.to/#/#polymc:polymc.org" CACHE STRING "URL to the 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.")
|
||||||
@ -91,11 +108,10 @@ set(Launcher_DISCORD_URL "https://discord.gg/Z52pwxWCHP" CACHE STRING "URL for t
|
|||||||
|
|
||||||
|
|
||||||
# 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
|
# Builds
|
||||||
# TODO: Launcher_FORCE_BUNDLED_LIBS should be off in the future, but as of QuaZip 1.2, we can't do that yet.
|
set(Launcher_FORCE_BUNDLED_LIBS OFF CACHE BOOL "Prevent using system libraries, if they are available as submodules")
|
||||||
set(Launcher_FORCE_BUNDLED_LIBS ON CACHE BOOL "Prevent using system libraries, if they are available as submodules")
|
|
||||||
set(Launcher_QT_VERSION_MAJOR "5" CACHE STRING "Major Qt version to build against")
|
set(Launcher_QT_VERSION_MAJOR "5" CACHE STRING "Major Qt version to build against")
|
||||||
|
|
||||||
|
|
||||||
@ -122,7 +138,7 @@ if(Launcher_QT_VERSION_MAJOR EQUAL 5)
|
|||||||
find_package(Qt5 REQUIRED COMPONENTS Core Widgets Concurrent Network Test Xml)
|
find_package(Qt5 REQUIRED COMPONENTS Core Widgets Concurrent Network Test Xml)
|
||||||
|
|
||||||
if(NOT Launcher_FORCE_BUNDLED_LIBS)
|
if(NOT Launcher_FORCE_BUNDLED_LIBS)
|
||||||
find_package(QuaZip-Qt5 REQUIRED)
|
find_package(QuaZip-Qt5 1.3)
|
||||||
endif()
|
endif()
|
||||||
if (NOT QuaZip-Qt5_FOUND)
|
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(QUAZIP_QT_MAJOR_VERSION ${QT_VERSION_MAJOR} CACHE STRING "Qt version to use (4, 5 or 6), defaults to ${QT_VERSION_MAJOR}" FORCE)
|
||||||
@ -152,9 +168,10 @@ add_subdirectory(program_info)
|
|||||||
|
|
||||||
####################################### Install layout #######################################
|
####################################### Install layout #######################################
|
||||||
|
|
||||||
# Install the build results according to platform
|
if(NOT (UNIX AND APPLE))
|
||||||
set(Launcher_PORTABLE 1 CACHE BOOL "The type of installation (Portable or System)")
|
# Install "portable.txt" if selected component is "portable"
|
||||||
|
install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/${Launcher_Portable_File}" DESTINATION "." COMPONENT portable EXCLUDE_FROM_ALL)
|
||||||
|
endif()
|
||||||
|
|
||||||
if(UNIX AND APPLE)
|
if(UNIX AND APPLE)
|
||||||
set(BINARY_DEST_DIR "${Launcher_Name}.app/Contents/MacOS")
|
set(BINARY_DEST_DIR "${Launcher_Name}.app/Contents/MacOS")
|
||||||
@ -163,20 +180,18 @@ if(UNIX AND APPLE)
|
|||||||
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.polymc.${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})
|
||||||
@ -189,30 +204,12 @@ if(UNIX AND APPLE)
|
|||||||
|
|
||||||
elseif(UNIX)
|
elseif(UNIX)
|
||||||
set(BINARY_DEST_DIR "bin")
|
set(BINARY_DEST_DIR "bin")
|
||||||
if(Launcher_PORTABLE)
|
set(LIBRARY_DEST_DIR "lib${LIB_SUFFIX}")
|
||||||
set(LIBRARY_DEST_DIR "bin")
|
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(JARS_DEST_DIR "bin/jars")
|
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")
|
||||||
# launcher/Application.cpp will use this value
|
set(LAUNCHER_MAN_DEST_DIR "share/man/man6" CACHE STRING "Path to the man page directory")
|
||||||
set(Launcher_APP_BINARY_DEFS "-DLAUNCHER_PORTABLE")
|
|
||||||
|
|
||||||
# Install basic runner script
|
|
||||||
configure_file(launcher/Launcher.in "${CMAKE_CURRENT_BINARY_DIR}/LauncherScript" @ONLY)
|
|
||||||
install(PROGRAMS "${CMAKE_CURRENT_BINARY_DIR}/LauncherScript" DESTINATION ${BUNDLE_DEST_DIR} RENAME ${Launcher_Name})
|
|
||||||
else()
|
|
||||||
set(LIBRARY_DEST_DIR "lib${LIB_SUFFIX}")
|
|
||||||
set(JARS_DEST_DIR "share/jars")
|
|
||||||
set(LAUNCHER_DESKTOP_DEST_DIR "share/applications" CACHE STRING "Path to the desktop file directory")
|
|
||||||
set(LAUNCHER_METAINFO_DEST_DIR "share/metainfo" CACHE STRING "Path to the metainfo directory")
|
|
||||||
set(LAUNCHER_ICON_DEST_DIR "share/icons/hicolor/scalable/apps" CACHE STRING "Path to the scalable icon directory")
|
|
||||||
|
|
||||||
set(Launcher_APP_BINARY_DEFS "-DMULTIMC_JARS_LOCATION=${CMAKE_INSTALL_PREFIX}/${JARS_DEST_DIR}")
|
|
||||||
|
|
||||||
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${Launcher_Desktop} DESTINATION ${LAUNCHER_DESKTOP_DEST_DIR})
|
|
||||||
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${Launcher_MetaInfo} DESTINATION ${LAUNCHER_METAINFO_DEST_DIR})
|
|
||||||
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/${Launcher_SVG} DESTINATION ${LAUNCHER_ICON_DEST_DIR})
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# install as bundle with no dependencies included
|
# install as bundle with no dependencies included
|
||||||
set(INSTALL_BUNDLE "nodeps")
|
set(INSTALL_BUNDLE "nodeps")
|
||||||
@ -220,11 +217,22 @@ elseif(UNIX)
|
|||||||
# Set RPATH
|
# Set RPATH
|
||||||
SET(Launcher_BINARY_RPATH "$ORIGIN/")
|
SET(Launcher_BINARY_RPATH "$ORIGIN/")
|
||||||
|
|
||||||
|
# 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)
|
||||||
|
install(PROGRAMS "${CMAKE_CURRENT_BINARY_DIR}/LauncherScript" DESTINATION "." RENAME ${Launcher_Name} COMPONENT portable EXCLUDE_FROM_ALL)
|
||||||
|
|
||||||
elseif(WIN32)
|
elseif(WIN32)
|
||||||
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")
|
||||||
|
|
||||||
@ -260,6 +268,8 @@ if (FORCE_BUNDLED_QUAZIP)
|
|||||||
set(BUILD_SHARED_LIBS 0) # link statically to avoid conflicts.
|
set(BUILD_SHARED_LIBS 0) # link statically to avoid conflicts.
|
||||||
set(QUAZIP_INSTALL 0)
|
set(QUAZIP_INSTALL 0)
|
||||||
add_subdirectory(libraries/quazip) # zip manipulation library
|
add_subdirectory(libraries/quazip) # zip manipulation library
|
||||||
|
else()
|
||||||
|
message(STATUS "Using system QuaZip")
|
||||||
endif()
|
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
|
||||||
|
@ -5,8 +5,7 @@
|
|||||||
|
|
||||||
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
|
||||||
|
30
README.md
30
README.md
@ -33,14 +33,22 @@ Feel free to create an issue if you need help. However, you might find it easier
|
|||||||
|
|
||||||
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
|
# Development
|
||||||
|
|
||||||
@ -48,7 +56,7 @@ If you want to contribute to PolyMC you might find it useful to join our Discord
|
|||||||
|
|
||||||
## Building
|
## Building
|
||||||
|
|
||||||
If you want to build PolyMC yourself, check [BUILD.md](BUILD.md) for build instructions.
|
If you want to build PolyMC yourself, check [Build Instructions](https://polymc.org/wiki/development/build-instructions/) for build instructions.
|
||||||
|
|
||||||
## Code formatting
|
## Code formatting
|
||||||
|
|
||||||
@ -66,9 +74,15 @@ In general, in order of importance:
|
|||||||
|
|
||||||
The translation effort for PolyMC is hosted on [Weblate](https://hosted.weblate.org/projects/polymc/polymc/) and information about translating PolyMC is available at https://github.com/PolyMC/Translations
|
The translation effort for PolyMC is hosted on [Weblate](https://hosted.weblate.org/projects/polymc/polymc/) and information about translating PolyMC is available at https://github.com/PolyMC/Translations
|
||||||
|
|
||||||
## Download infomation
|
## Download information
|
||||||
To modify download infomation or change packaging infomation send a pull request or issue to the website [Here](https://github.com/PolyMC/polymc.github.io/blob/master/src/download.md)
|
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
|
## 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.
|
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>
|
||||||
|
|
||||||
@ -25,12 +60,14 @@ 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/"))
|
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/");
|
||||||
@ -53,6 +90,7 @@ Config::Config()
|
|||||||
HELP_URL = "@Launcher_HELP_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@";
|
||||||
|
@ -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;
|
||||||
@ -39,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;
|
||||||
|
|
||||||
@ -88,6 +114,11 @@ 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
|
||||||
*/
|
*/
|
||||||
@ -112,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).
|
||||||
@ -120,4 +157,3 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
extern const Config BuildConfig;
|
extern const Config BuildConfig;
|
||||||
|
|
||||||
|
@ -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()
|
||||||
|
30
flake.lock
generated
30
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": 1642700792,
|
|
||||||
"narHash": "sha256-XqHrk7hFb+zBvRg6Ghl+AZDq03ov6OshJLiSWOoX5es=",
|
|
||||||
"owner": "numtide",
|
|
||||||
"repo": "flake-utils",
|
|
||||||
"rev": "846b2ae0fc4cc943637d3d1def4454213e203cba",
|
|
||||||
"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": 1643169865,
|
"lastModified": 1648219316,
|
||||||
"narHash": "sha256-+KIpNRazbc8Gac9jdWCKQkFv9bjceaLaLhlwqUEYu8c=",
|
"narHash": "sha256-Ctij+dOi0ZZIfX5eMhgwugfvB+WZSrvVNAyAuANOsnQ=",
|
||||||
"owner": "nixos",
|
"owner": "nixos",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "945ec499041db73043f745fad3b2a3a01e826081",
|
"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"
|
||||||
}
|
}
|
||||||
@ -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"
|
||||||
|
74
flake.nix
74
flake.nix
@ -1,50 +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:stachenov/quazip";
|
|
||||||
flake = false;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
outputs = args@{ self, nixpkgs, flake-utils, libnbtplusplus, quazip, ... }:
|
outputs = { self, nixpkgs, libnbtplusplus, quazip, ... }:
|
||||||
let
|
let
|
||||||
systems = [
|
# Generate a user-friendly version number.
|
||||||
"aarch64-linux"
|
version = builtins.substring 0 8 self.lastModifiedDate;
|
||||||
# "aarch64-darwin" # qtbase is currently broken
|
|
||||||
"i686-linux"
|
# System types to support (qtbase is currently broken for "aarch64-darwin")
|
||||||
"x86_64-darwin"
|
supportedSystems = [ "x86_64-linux" "x86_64-darwin" "aarch64-linux" ];
|
||||||
"x86_64-linux"
|
|
||||||
];
|
# Helper function to generate an attrset '{ x86_64-linux = f "x86_64-linux"; ... }'.
|
||||||
in {
|
forAllSystems = nixpkgs.lib.genAttrs supportedSystems;
|
||||||
overlay = final: prev: {
|
|
||||||
inherit (self.packages.${final.system}) polymc;
|
# Nixpkgs instantiated for supported system types.
|
||||||
};
|
pkgs = forAllSystems (system: nixpkgs.legacyPackages.${system});
|
||||||
} // flake-utils.lib.eachSystem systems (system:
|
in
|
||||||
let pkgs = import nixpkgs { inherit system; };
|
{
|
||||||
in {
|
packages = forAllSystems (system: { polymc = pkgs.${system}.libsForQt5.callPackage ./packages/nix/polymc { inherit version self quazip libnbtplusplus; }; });
|
||||||
packages = {
|
defaultPackage = forAllSystems (system: self.packages.${system}.polymc);
|
||||||
polymc = pkgs.libsForQt5.callPackage ./packages/nix/polymc {
|
|
||||||
inherit self;
|
apps = forAllSystems (system: { polymc = { type = "app"; program = "${self.defaultPackage.${system}}/bin/polymc"; }; });
|
||||||
submoduleQuazip = quazip;
|
defaultApp = forAllSystems (system: self.apps.${system}.polymc);
|
||||||
submoduleNbt = libnbtplusplus;
|
|
||||||
};
|
overlay = final: prev: { polymc = self.defaultPackage.${final.system}; };
|
||||||
};
|
};
|
||||||
apps = {
|
|
||||||
polymc = flake-utils.lib.mkApp {
|
|
||||||
name = "polymc";
|
|
||||||
drv = self.packages.${system}.polymc;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
defaultPackage = self.packages.${system}.polymc;
|
|
||||||
defaultApp = self.apps.${system}.polymc;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
@ -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"
|
||||||
|
|
||||||
@ -45,6 +80,7 @@
|
|||||||
#include <QStringList>
|
#include <QStringList>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <QStyleFactory>
|
#include <QStyleFactory>
|
||||||
|
#include <QWindow>
|
||||||
|
|
||||||
#include "InstanceList.h"
|
#include "InstanceList.h"
|
||||||
|
|
||||||
@ -281,6 +317,26 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv)
|
|||||||
|
|
||||||
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
|
||||||
@ -289,15 +345,14 @@ 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
|
||||||
{
|
{
|
||||||
#if !defined(LAUNCHER_PORTABLE) || defined(Q_OS_MAC)
|
|
||||||
QDir foo(FS::PathCombine(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation), ".."));
|
QDir foo(FS::PathCombine(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation), ".."));
|
||||||
dataPath = foo.absolutePath();
|
dataPath = foo.absolutePath();
|
||||||
adjustedBy += dataPath;
|
adjustedBy = "Persistent data path";
|
||||||
|
|
||||||
#ifdef Q_OS_LINUX
|
#ifdef Q_OS_LINUX
|
||||||
// TODO: this should be removed in a future version
|
// TODO: this should be removed in a future version
|
||||||
@ -305,12 +360,15 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv)
|
|||||||
QDir bar(FS::PathCombine(QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation), "polymc"));
|
QDir bar(FS::PathCombine(QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation), "polymc"));
|
||||||
if (bar.exists()) {
|
if (bar.exists()) {
|
||||||
dataPath = bar.absolutePath();
|
dataPath = bar.absolutePath();
|
||||||
adjustedBy += "Legacy data path " + dataPath;
|
adjustedBy = "Legacy data path";
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#else
|
|
||||||
dataPath = applicationDirPath();
|
#ifndef Q_OS_MACOS
|
||||||
adjustedBy += "Fallback to binary path " + dataPath;
|
if (QFile::exists(FS::PathCombine(m_rootPath, "portable.txt"))) {
|
||||||
|
dataPath = m_rootPath;
|
||||||
|
adjustedBy = "Portable data path";
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -500,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();
|
||||||
@ -575,12 +616,11 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv)
|
|||||||
m_settings->registerSetting("IconTheme", QString("pe_colored"));
|
m_settings->registerSetting("IconTheme", QString("pe_colored"));
|
||||||
m_settings->registerSetting("ApplicationTheme", QString("system"));
|
m_settings->registerSetting("ApplicationTheme", QString("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
|
||||||
@ -650,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);
|
||||||
@ -663,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", "");
|
||||||
|
|
||||||
@ -695,6 +739,7 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv)
|
|||||||
m_settings->registerSetting("PastebinURL", "https://0x0.st");
|
m_settings->registerSetting("PastebinURL", "https://0x0.st");
|
||||||
|
|
||||||
m_settings->registerSetting("CloseAfterLaunch", false);
|
m_settings->registerSetting("CloseAfterLaunch", false);
|
||||||
|
m_settings->registerSetting("QuitAfterGameStop", false);
|
||||||
|
|
||||||
// Custom MSA credentials
|
// Custom MSA credentials
|
||||||
m_settings->registerSetting("MSAClientIDOverride", "");
|
m_settings->registerSetting("MSAClientIDOverride", "");
|
||||||
@ -1107,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();
|
||||||
@ -1222,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 ++;
|
||||||
@ -1494,10 +1554,10 @@ 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 Application::getMSAClientID()
|
||||||
{
|
{
|
||||||
QString clientIDOverride = m_settings->get("MSAClientIDOverride").toString();
|
QString clientIDOverride = m_settings->get("MSAClientIDOverride").toString();
|
||||||
if (!clientIDOverride.isEmpty()) {
|
if (!clientIDOverride.isEmpty()) {
|
||||||
|
@ -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();
|
||||||
@ -152,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"
|
||||||
|
@ -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
|
||||||
|
@ -144,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
|
||||||
@ -174,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
|
||||||
@ -240,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
|
||||||
@ -353,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
|
||||||
@ -416,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
|
||||||
@ -492,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
|
||||||
@ -532,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
|
||||||
)
|
)
|
||||||
@ -561,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}
|
||||||
@ -572,6 +587,7 @@ 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}
|
${MODRINTH_SOURCES}
|
||||||
@ -721,6 +737,11 @@ SET(LAUNCHER_SOURCES
|
|||||||
ui/pages/modplatform/VanillaPage.cpp
|
ui/pages/modplatform/VanillaPage.cpp
|
||||||
ui/pages/modplatform/VanillaPage.h
|
ui/pages/modplatform/VanillaPage.h
|
||||||
|
|
||||||
|
ui/pages/modplatform/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
|
||||||
@ -791,12 +812,12 @@ SET(LAUNCHER_SOURCES
|
|||||||
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
|
||||||
@ -806,7 +827,6 @@ SET(LAUNCHER_SOURCES
|
|||||||
ui/dialogs/ModDownloadDialog.cpp
|
ui/dialogs/ModDownloadDialog.cpp
|
||||||
ui/dialogs/ModDownloadDialog.h
|
ui/dialogs/ModDownloadDialog.h
|
||||||
|
|
||||||
|
|
||||||
# GUI - widgets
|
# GUI - widgets
|
||||||
ui/widgets/Common.cpp
|
ui/widgets/Common.cpp
|
||||||
ui/widgets/Common.h
|
ui/widgets/Common.h
|
||||||
@ -830,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
|
||||||
@ -879,21 +901,20 @@ qt5_wrap_ui(LAUNCHER_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/flame/FlameModPage.ui
|
|
||||||
ui/pages/modplatform/legacy_ftb/Page.ui
|
ui/pages/modplatform/legacy_ftb/Page.ui
|
||||||
ui/pages/modplatform/ImportPage.ui
|
ui/pages/modplatform/ImportPage.ui
|
||||||
ui/pages/modplatform/ftb/FtbPage.ui
|
ui/pages/modplatform/ftb/FtbPage.ui
|
||||||
ui/pages/modplatform/technic/TechnicPage.ui
|
ui/pages/modplatform/technic/TechnicPage.ui
|
||||||
ui/pages/modplatform/modrinth/ModrinthPage.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
|
||||||
@ -905,6 +926,7 @@ qt5_wrap_ui(LAUNCHER_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
|
||||||
@ -949,8 +971,8 @@ target_link_libraries(Launcher_logic
|
|||||||
Launcher_iconfix
|
Launcher_iconfix
|
||||||
QuaZip::QuaZip
|
QuaZip::QuaZip
|
||||||
hoedown
|
hoedown
|
||||||
PolyMC_rainbow
|
|
||||||
LocalPeer
|
LocalPeer
|
||||||
|
Launcher_rainbow
|
||||||
)
|
)
|
||||||
|
|
||||||
target_link_libraries(Launcher_logic)
|
target_link_libraries(Launcher_logic)
|
||||||
@ -971,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
|
||||||
)
|
)
|
||||||
@ -992,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(
|
||||||
@ -1022,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
|
||||||
|
@ -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()
|
||||||
@ -21,6 +30,8 @@ void InstanceCreationTask::executeTask()
|
|||||||
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;
|
||||||
};
|
};
|
||||||
|
@ -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;
|
||||||
@ -283,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);
|
||||||
|
@ -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;
|
||||||
|
@ -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();
|
||||||
}
|
}
|
||||||
@ -131,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)
|
||||||
@ -148,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
|
||||||
|
@ -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>
|
||||||
|
@ -21,7 +21,7 @@ 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,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 <quazip/quazip.h>
|
#include <quazip/quazip.h>
|
||||||
|
@ -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
|
||||||
|
@ -129,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;
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
@ -153,7 +153,7 @@ QStringList addJavasFromEnv(QList<QString> javas)
|
|||||||
{
|
{
|
||||||
QByteArray env = qgetenv("POLYMC_JAVA_PATHS");
|
QByteArray env = qgetenv("POLYMC_JAVA_PATHS");
|
||||||
#if defined(Q_OS_WIN32)
|
#if defined(Q_OS_WIN32)
|
||||||
QList<QString> javaPaths = QString::fromLocal8Bit(env).split(QLatin1String(";"));
|
QList<QString> javaPaths = QString::fromLocal8Bit(env).replace("\\", "/").split(QLatin1String(";"));
|
||||||
#else
|
#else
|
||||||
QList<QString> javaPaths = QString::fromLocal8Bit(env).split(QLatin1String(":"));
|
QList<QString> javaPaths = QString::fromLocal8Bit(env).split(QLatin1String(":"));
|
||||||
#endif
|
#endif
|
||||||
@ -355,7 +355,7 @@ QList<QString> JavaUtils::FindJavaPaths()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return candidates;
|
return addJavasFromEnv(candidates);
|
||||||
}
|
}
|
||||||
|
|
||||||
#elif defined(Q_OS_MAC)
|
#elif defined(Q_OS_MAC)
|
||||||
|
@ -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("PolyMC 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()));
|
||||||
}
|
}
|
||||||
|
@ -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 PolyMC 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 PolyMC 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;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
@ -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);
|
||||||
@ -292,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;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -434,7 +483,7 @@ QStringList MinecraftInstance::processMinecraftArgs(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// blatant self-promotion.
|
// blatant self-promotion.
|
||||||
token_mapping["profile_name"] = token_mapping["version_name"] = "PolyMC";
|
token_mapping["profile_name"] = token_mapping["version_name"] = BuildConfig.LAUNCHER_NAME;
|
||||||
|
|
||||||
token_mapping["version_type"] = profile->getMinecraftVersionType();
|
token_mapping["version_type"] = profile->getMinecraftVersionType();
|
||||||
|
|
||||||
@ -935,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;
|
||||||
|
@ -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"))
|
||||||
{
|
{
|
||||||
|
@ -970,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;
|
||||||
|
@ -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;
|
||||||
@ -57,6 +93,12 @@ public: /* data */
|
|||||||
/// 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;
|
||||||
|
|
||||||
@ -78,6 +120,9 @@ public: /* data */
|
|||||||
/// PolyMC: 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;
|
||||||
|
|
||||||
|
@ -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"
|
||||||
@ -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>
|
||||||
|
@ -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>
|
||||||
|
@ -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"
|
||||||
|
@ -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
|
||||||
|
@ -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"
|
||||||
|
@ -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
|
||||||
|
@ -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"
|
||||||
|
@ -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
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
#include "Parsers.h"
|
#include "Parsers.h"
|
||||||
|
#include "Json.h"
|
||||||
|
|
||||||
#include <QJsonDocument>
|
#include <QJsonDocument>
|
||||||
#include <QJsonArray>
|
#include <QJsonArray>
|
||||||
@ -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));
|
||||||
}
|
}
|
||||||
|
@ -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>
|
||||||
|
@ -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>
|
||||||
|
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>);
|
||||||
|
};
|
@ -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;
|
||||||
|
@ -154,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;
|
||||||
@ -170,6 +170,7 @@ void LauncherPartLaunch::on_state(LoggedProcess::State state)
|
|||||||
{
|
{
|
||||||
if (APPLICATION->settings()->get("CloseAfterLaunch").toBool())
|
if (APPLICATION->settings()->get("CloseAfterLaunch").toBool())
|
||||||
APPLICATION->showMainWindow();
|
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();
|
||||||
|
@ -1,50 +1,75 @@
|
|||||||
|
// 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 "VerifyJavaInstall.h"
|
#include "VerifyJavaInstall.h"
|
||||||
|
|
||||||
#include <launch/LaunchTask.h>
|
#include "java/JavaVersion.h"
|
||||||
#include <minecraft/MinecraftInstance.h>
|
#include "minecraft/PackProfile.h"
|
||||||
#include <minecraft/PackProfile.h>
|
#include "minecraft/MinecraftInstance.h"
|
||||||
#include <minecraft/VersionFilterData.h>
|
|
||||||
|
|
||||||
#ifdef major
|
|
||||||
#undef major
|
|
||||||
#endif
|
|
||||||
#ifdef minor
|
|
||||||
#undef minor
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void VerifyJavaInstall::executeTask() {
|
void VerifyJavaInstall::executeTask() {
|
||||||
auto m_inst = std::dynamic_pointer_cast<MinecraftInstance>(m_parent->instance());
|
auto instance = std::dynamic_pointer_cast<MinecraftInstance>(m_parent->instance());
|
||||||
|
auto packProfile = instance->getPackProfile();
|
||||||
|
auto settings = instance->settings();
|
||||||
|
auto storedVersion = settings->get("JavaVersion").toString();
|
||||||
|
auto ignoreCompatibility = settings->get("IgnoreJavaCompatibility").toBool();
|
||||||
|
|
||||||
auto javaVersion = m_inst->getJavaVersion();
|
auto compatibleMajors = packProfile->getProfile()->getCompatibleJavaMajors();
|
||||||
auto minecraftComponent = m_inst->getPackProfile()->getComponent("net.minecraft");
|
|
||||||
|
|
||||||
// Java 17 requirement
|
JavaVersion javaVersion(storedVersion);
|
||||||
if (minecraftComponent->getReleaseDateTime() >= g_VersionFilterData.java17BeginsDate) {
|
|
||||||
if (javaVersion.major() < 17) {
|
if (compatibleMajors.isEmpty() || compatibleMajors.contains(javaVersion.major()))
|
||||||
emit logLine("Minecraft 1.18 Pre Release 2 and above require the use of Java 17",
|
{
|
||||||
MessageLevel::Fatal);
|
emitSucceeded();
|
||||||
emitFailed(tr("Minecraft 1.18 Pre Release 2 and above require the use of Java 17"));
|
return;
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Java 16 requirement
|
|
||||||
else if (minecraftComponent->getReleaseDateTime() >= g_VersionFilterData.java16BeginsDate) {
|
|
||||||
if (javaVersion.major() < 16) {
|
|
||||||
emit logLine("Minecraft 21w19a and above require the use of Java 16",
|
|
||||||
MessageLevel::Fatal);
|
|
||||||
emitFailed(tr("Minecraft 21w19a and above require the use of Java 16"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Java 8 requirement
|
|
||||||
else if (minecraftComponent->getReleaseDateTime() >= g_VersionFilterData.java8BeginsDate) {
|
|
||||||
if (javaVersion.major() < 8) {
|
|
||||||
emit logLine("Minecraft 17w13a and above require the use of Java 8",
|
|
||||||
MessageLevel::Fatal);
|
|
||||||
emitFailed(tr("Minecraft 17w13a and above require the use of Java 8"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
emitSucceeded();
|
|
||||||
|
if (ignoreCompatibility)
|
||||||
|
{
|
||||||
|
emit logLine(tr("Java major version is incompatible. Things might break."), MessageLevel::Warning);
|
||||||
|
emitSucceeded();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
emit logLine(tr("This instance is not compatible with Java version %1.\n"
|
||||||
|
"Please switch to one of the following Java versions for this instance:").arg(javaVersion.major()),
|
||||||
|
MessageLevel::Error);
|
||||||
|
for (auto major : compatibleMajors)
|
||||||
|
{
|
||||||
|
emit logLine(tr("Java version %1").arg(major), MessageLevel::Error);
|
||||||
|
}
|
||||||
|
emitFailed(QString("Incompatible Java major version"));
|
||||||
}
|
}
|
||||||
|
@ -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 <launch/LaunchStep.h>
|
#include <launch/LaunchStep.h>
|
||||||
|
#include <launch/LaunchTask.h>
|
||||||
|
|
||||||
class VerifyJavaInstall : public LaunchStep {
|
class VerifyJavaInstall : public LaunchStep {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
@ -391,7 +391,7 @@ void LocalModParseTask::processAsZip()
|
|||||||
zip.close();
|
zip.close();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if (zip.setCurrentFile("fabric.mod.json"))
|
else if (zip.setCurrentFile("fabric.mod.json")) // TODO: Support quilt.mod.json
|
||||||
{
|
{
|
||||||
if (!file.open(QIODevice::ReadOnly))
|
if (!file.open(QIODevice::ReadOnly))
|
||||||
{
|
{
|
||||||
|
@ -14,7 +14,7 @@ void FoldersTask::executeTask()
|
|||||||
QDir mcDir(m_inst->gameRoot());
|
QDir mcDir(m_inst->gameRoot());
|
||||||
if (!mcDir.exists() && !mcDir.mkpath("."))
|
if (!mcDir.exists() && !mcDir.mkpath("."))
|
||||||
{
|
{
|
||||||
emitFailed(tr("Failed to create folder for minecraft binaries."));
|
emitFailed(tr("Failed to create folder for Minecraft binaries."));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
emitSucceeded();
|
emitSucceeded();
|
||||||
|
@ -48,6 +48,10 @@ void LibrariesTask::executeTask()
|
|||||||
libArtifactPool.append(profile->getLibraries());
|
libArtifactPool.append(profile->getLibraries());
|
||||||
libArtifactPool.append(profile->getNativeLibraries());
|
libArtifactPool.append(profile->getNativeLibraries());
|
||||||
libArtifactPool.append(profile->getMavenFiles());
|
libArtifactPool.append(profile->getMavenFiles());
|
||||||
|
for (auto agent : profile->getAgents())
|
||||||
|
{
|
||||||
|
libArtifactPool.append(agent->library());
|
||||||
|
}
|
||||||
libArtifactPool.append(profile->getMainJar());
|
libArtifactPool.append(profile->getMainJar());
|
||||||
processArtifactPool(libArtifactPool, failedLocalLibraries, inst->getLocalLibraryPath());
|
processArtifactPool(libArtifactPool, failedLocalLibraries, inst->getLocalLibraryPath());
|
||||||
|
|
||||||
|
69
launcher/modplatform/ModAPI.h
Normal file
69
launcher/modplatform/ModAPI.h
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QString>
|
||||||
|
#include <QList>
|
||||||
|
|
||||||
|
#include "Version.h"
|
||||||
|
|
||||||
|
namespace ModPlatform {
|
||||||
|
class ListModel;
|
||||||
|
}
|
||||||
|
|
||||||
|
class ModAPI {
|
||||||
|
protected:
|
||||||
|
using CallerType = ModPlatform::ListModel;
|
||||||
|
|
||||||
|
public:
|
||||||
|
virtual ~ModAPI() = default;
|
||||||
|
|
||||||
|
// https://docs.curseforge.com/?http#tocS_ModLoaderType
|
||||||
|
enum ModLoaderType { Unspecified = 0, Forge = 1, Cauldron = 2, LiteLoader = 3, Fabric = 4, Quilt = 5 };
|
||||||
|
|
||||||
|
struct SearchArgs {
|
||||||
|
int offset;
|
||||||
|
QString search;
|
||||||
|
QString sorting;
|
||||||
|
ModLoaderType mod_loader;
|
||||||
|
std::list<Version> versions;
|
||||||
|
};
|
||||||
|
|
||||||
|
virtual void searchMods(CallerType* caller, SearchArgs&& args) const = 0;
|
||||||
|
|
||||||
|
|
||||||
|
struct VersionSearchArgs {
|
||||||
|
QString addonId;
|
||||||
|
std::list<Version> mcVersions;
|
||||||
|
ModLoaderType loader;
|
||||||
|
};
|
||||||
|
|
||||||
|
virtual void getVersions(CallerType* caller, VersionSearchArgs&& args) const = 0;
|
||||||
|
|
||||||
|
static auto getModLoaderString(ModLoaderType type) -> const QString {
|
||||||
|
switch (type) {
|
||||||
|
case Unspecified:
|
||||||
|
break;
|
||||||
|
case Forge:
|
||||||
|
return "forge";
|
||||||
|
case Cauldron:
|
||||||
|
return "cauldron";
|
||||||
|
case LiteLoader:
|
||||||
|
return "liteloader";
|
||||||
|
case Fabric:
|
||||||
|
return "fabric";
|
||||||
|
case Quilt:
|
||||||
|
return "quilt";
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
inline auto getGameVersionsString(std::list<Version> mcVersions) const -> QString
|
||||||
|
{
|
||||||
|
QString s;
|
||||||
|
for(auto& ver : mcVersions){
|
||||||
|
s += QString("%1,").arg(ver.toString());
|
||||||
|
}
|
||||||
|
s.remove(s.length() - 1, 1); //remove last comma
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
};
|
42
launcher/modplatform/ModIndex.h
Normal file
42
launcher/modplatform/ModIndex.h
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QList>
|
||||||
|
#include <QMetaType>
|
||||||
|
#include <QString>
|
||||||
|
#include <QVariant>
|
||||||
|
#include <QVector>
|
||||||
|
|
||||||
|
namespace ModPlatform {
|
||||||
|
|
||||||
|
struct ModpackAuthor {
|
||||||
|
QString name;
|
||||||
|
QString url;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct IndexedVersion {
|
||||||
|
QVariant addonId;
|
||||||
|
QVariant fileId;
|
||||||
|
QString version;
|
||||||
|
QVector<QString> mcVersion;
|
||||||
|
QString downloadUrl;
|
||||||
|
QString date;
|
||||||
|
QString fileName;
|
||||||
|
QVector<QString> loaders = {};
|
||||||
|
};
|
||||||
|
|
||||||
|
struct IndexedPack {
|
||||||
|
QVariant addonId;
|
||||||
|
QString name;
|
||||||
|
QString description;
|
||||||
|
QList<ModpackAuthor> authors;
|
||||||
|
QString logoName;
|
||||||
|
QString logoUrl;
|
||||||
|
QString websiteUrl;
|
||||||
|
|
||||||
|
bool versionsLoaded = false;
|
||||||
|
QVector<IndexedVersion> versions;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace ModPlatform
|
||||||
|
|
||||||
|
Q_DECLARE_METATYPE(ModPlatform::IndexedPack)
|
@ -1,14 +1,9 @@
|
|||||||
#include "FileResolvingTask.h"
|
#include "FileResolvingTask.h"
|
||||||
#include "Json.h"
|
#include "Json.h"
|
||||||
|
|
||||||
namespace {
|
|
||||||
const char * metabase = "https://cursemeta.dries007.net";
|
|
||||||
}
|
|
||||||
|
|
||||||
Flame::FileResolvingTask::FileResolvingTask(shared_qobject_ptr<QNetworkAccessManager> network, Flame::Manifest& toProcess)
|
Flame::FileResolvingTask::FileResolvingTask(shared_qobject_ptr<QNetworkAccessManager> network, Flame::Manifest& toProcess)
|
||||||
: m_network(network), m_toProcess(toProcess)
|
: m_network(network), m_toProcess(toProcess)
|
||||||
{
|
{}
|
||||||
}
|
|
||||||
|
|
||||||
void Flame::FileResolvingTask::executeTask()
|
void Flame::FileResolvingTask::executeTask()
|
||||||
{
|
{
|
||||||
@ -17,14 +12,13 @@ void Flame::FileResolvingTask::executeTask()
|
|||||||
m_dljob = new NetJob("Mod id resolver", m_network);
|
m_dljob = new NetJob("Mod id resolver", m_network);
|
||||||
results.resize(m_toProcess.files.size());
|
results.resize(m_toProcess.files.size());
|
||||||
int index = 0;
|
int index = 0;
|
||||||
for(auto & file: m_toProcess.files)
|
for (auto& file : m_toProcess.files) {
|
||||||
{
|
|
||||||
auto projectIdStr = QString::number(file.projectId);
|
auto projectIdStr = QString::number(file.projectId);
|
||||||
auto fileIdStr = QString::number(file.fileId);
|
auto fileIdStr = QString::number(file.fileId);
|
||||||
QString metaurl = QString("%1/%2/%3.json").arg(metabase, projectIdStr, fileIdStr);
|
QString metaurl = QString("https://api.curseforge.com/v1/mods/%1/files/%2").arg(projectIdStr, fileIdStr);
|
||||||
auto dl = Net::Download::makeByteArray(QUrl(metaurl), &results[index]);
|
auto dl = Net::Download::makeByteArray(QUrl(metaurl), &results[index]);
|
||||||
m_dljob->addNetAction(dl);
|
m_dljob->addNetAction(dl);
|
||||||
index ++;
|
index++;
|
||||||
}
|
}
|
||||||
connect(m_dljob.get(), &NetJob::finished, this, &Flame::FileResolvingTask::netJobFinished);
|
connect(m_dljob.get(), &NetJob::finished, this, &Flame::FileResolvingTask::netJobFinished);
|
||||||
m_dljob->start();
|
m_dljob->start();
|
||||||
@ -34,16 +28,11 @@ void Flame::FileResolvingTask::netJobFinished()
|
|||||||
{
|
{
|
||||||
bool failed = false;
|
bool failed = false;
|
||||||
int index = 0;
|
int index = 0;
|
||||||
for(auto & bytes: results)
|
for (auto& bytes : results) {
|
||||||
{
|
auto& out = m_toProcess.files[index];
|
||||||
auto & out = m_toProcess.files[index];
|
try {
|
||||||
try
|
|
||||||
{
|
|
||||||
failed &= (!out.parseFromBytes(bytes));
|
failed &= (!out.parseFromBytes(bytes));
|
||||||
}
|
} catch (const JSONValidationError& e) {
|
||||||
catch (const JSONValidationError &e)
|
|
||||||
{
|
|
||||||
|
|
||||||
qCritical() << "Resolving of" << out.projectId << out.fileId << "failed because of a parsing error:";
|
qCritical() << "Resolving of" << out.projectId << out.fileId << "failed because of a parsing error:";
|
||||||
qCritical() << e.cause();
|
qCritical() << e.cause();
|
||||||
qCritical() << "JSON:";
|
qCritical() << "JSON:";
|
||||||
@ -52,12 +41,9 @@ void Flame::FileResolvingTask::netJobFinished()
|
|||||||
}
|
}
|
||||||
index++;
|
index++;
|
||||||
}
|
}
|
||||||
if(!failed)
|
if (!failed) {
|
||||||
{
|
|
||||||
emitSucceeded();
|
emitSucceeded();
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
emitFailed(tr("Some mod ID resolving tasks failed."));
|
emitFailed(tr("Some mod ID resolving tasks failed."));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
63
launcher/modplatform/flame/FlameAPI.h
Normal file
63
launcher/modplatform/flame/FlameAPI.h
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "modplatform/helpers/NetworkModAPI.h"
|
||||||
|
|
||||||
|
class FlameAPI : public NetworkModAPI {
|
||||||
|
private:
|
||||||
|
inline auto getSortFieldInt(QString sortString) const -> int
|
||||||
|
{
|
||||||
|
return sortString == "Featured" ? 1
|
||||||
|
: sortString == "Popularity" ? 2
|
||||||
|
: sortString == "LastUpdated" ? 3
|
||||||
|
: sortString == "Name" ? 4
|
||||||
|
: sortString == "Author" ? 5
|
||||||
|
: sortString == "TotalDownloads" ? 6
|
||||||
|
: sortString == "Category" ? 7
|
||||||
|
: sortString == "GameVersion" ? 8
|
||||||
|
: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
inline auto getModSearchURL(SearchArgs& args) const -> QString override
|
||||||
|
{
|
||||||
|
auto gameVersionStr = args.versions.size() != 0 ? QString("gameVersion=%1").arg(args.versions.front().toString()) : QString();
|
||||||
|
|
||||||
|
return QString(
|
||||||
|
"https://api.curseforge.com/v1/mods/search?"
|
||||||
|
"gameId=432&"
|
||||||
|
"classId=6&"
|
||||||
|
|
||||||
|
"index=%1&"
|
||||||
|
"pageSize=25&"
|
||||||
|
"searchFilter=%2&"
|
||||||
|
"sortField=%3&"
|
||||||
|
"sortOrder=desc&"
|
||||||
|
"modLoaderType=%4&"
|
||||||
|
"%5")
|
||||||
|
.arg(args.offset)
|
||||||
|
.arg(args.search)
|
||||||
|
.arg(getSortFieldInt(args.sorting))
|
||||||
|
.arg(getMappedModLoader(args.mod_loader))
|
||||||
|
.arg(gameVersionStr);
|
||||||
|
};
|
||||||
|
|
||||||
|
inline auto getVersionsURL(VersionSearchArgs& args) const -> QString override
|
||||||
|
{
|
||||||
|
QString gameVersionQuery = args.mcVersions.size() == 1 ? QString("gameVersion=%1&").arg(args.mcVersions.front().toString()) : "";
|
||||||
|
QString modLoaderQuery = QString("modLoaderType=%1&").arg(getMappedModLoader(args.loader));
|
||||||
|
|
||||||
|
return QString("https://api.curseforge.com/v1/mods/%1/files?pageSize=10000&%2%3")
|
||||||
|
.arg(args.addonId)
|
||||||
|
.arg(gameVersionQuery)
|
||||||
|
.arg(modLoaderQuery);
|
||||||
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
|
static auto getMappedModLoader(const ModLoaderType type) -> const ModLoaderType
|
||||||
|
{
|
||||||
|
// TODO: remove this once Quilt drops official Fabric support
|
||||||
|
if (type == Quilt) // NOTE: Most if not all Fabric mods should work *currently*
|
||||||
|
return Fabric;
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
};
|
@ -1,64 +1,55 @@
|
|||||||
#include <QObject>
|
|
||||||
#include "FlameModIndex.h"
|
#include "FlameModIndex.h"
|
||||||
|
|
||||||
#include "Json.h"
|
#include "Json.h"
|
||||||
#include "net/NetJob.h"
|
|
||||||
#include "BaseInstance.h"
|
|
||||||
#include "minecraft/MinecraftInstance.h"
|
#include "minecraft/MinecraftInstance.h"
|
||||||
#include "minecraft/PackProfile.h"
|
#include "minecraft/PackProfile.h"
|
||||||
|
#include "modplatform/flame/FlameAPI.h"
|
||||||
|
#include "net/NetJob.h"
|
||||||
|
|
||||||
|
void FlameMod::loadIndexedPack(ModPlatform::IndexedPack& pack, QJsonObject& obj)
|
||||||
void FlameMod::loadIndexedPack(FlameMod::IndexedPack & pack, QJsonObject & obj)
|
|
||||||
{
|
{
|
||||||
pack.addonId = Json::requireInteger(obj, "id");
|
pack.addonId = Json::requireInteger(obj, "id");
|
||||||
pack.name = Json::requireString(obj, "name");
|
pack.name = Json::requireString(obj, "name");
|
||||||
pack.websiteUrl = Json::ensureString(obj, "websiteUrl", "");
|
pack.websiteUrl = Json::ensureString(Json::ensureObject(obj, "links"), "websiteUrl", "");
|
||||||
pack.description = Json::ensureString(obj, "summary", "");
|
pack.description = Json::ensureString(obj, "summary", "");
|
||||||
|
|
||||||
bool thumbnailFound = false;
|
QJsonObject logo = Json::requireObject(obj, "logo");
|
||||||
auto attachments = Json::requireArray(obj, "attachments");
|
pack.logoName = Json::requireString(logo, "title");
|
||||||
for(auto attachmentRaw: attachments) {
|
pack.logoUrl = Json::requireString(logo, "thumbnailUrl");
|
||||||
auto attachmentObj = Json::requireObject(attachmentRaw);
|
|
||||||
bool isDefault = attachmentObj.value("isDefault").toBool(false);
|
|
||||||
if(isDefault) {
|
|
||||||
thumbnailFound = true;
|
|
||||||
pack.logoName = Json::requireString(attachmentObj, "title");
|
|
||||||
pack.logoUrl = Json::requireString(attachmentObj, "thumbnailUrl");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!thumbnailFound) {
|
|
||||||
throw JSONValidationError(QString("Pack without an icon, skipping: %1").arg(pack.name));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
auto authors = Json::requireArray(obj, "authors");
|
auto authors = Json::requireArray(obj, "authors");
|
||||||
for(auto authorIter: authors) {
|
for (auto authorIter : authors) {
|
||||||
auto author = Json::requireObject(authorIter);
|
auto author = Json::requireObject(authorIter);
|
||||||
FlameMod::ModpackAuthor packAuthor;
|
ModPlatform::ModpackAuthor packAuthor;
|
||||||
packAuthor.name = Json::requireString(author, "name");
|
packAuthor.name = Json::requireString(author, "name");
|
||||||
packAuthor.url = Json::requireString(author, "url");
|
packAuthor.url = Json::requireString(author, "url");
|
||||||
pack.authors.append(packAuthor);
|
pack.authors.append(packAuthor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void FlameMod::loadIndexedPackVersions(FlameMod::IndexedPack & pack, QJsonArray & arr, const shared_qobject_ptr<QNetworkAccessManager>& network, BaseInstance * inst)
|
void FlameMod::loadIndexedPackVersions(ModPlatform::IndexedPack& pack,
|
||||||
|
QJsonArray& arr,
|
||||||
|
const shared_qobject_ptr<QNetworkAccessManager>& network,
|
||||||
|
BaseInstance* inst)
|
||||||
{
|
{
|
||||||
QVector<FlameMod::IndexedVersion> unsortedVersions;
|
QVector<ModPlatform::IndexedVersion> unsortedVersions;
|
||||||
bool hasFabric = !((MinecraftInstance *)inst)->getPackProfile()->getComponentVersion("net.fabricmc.fabric-loader").isEmpty();
|
auto profile = (dynamic_cast<MinecraftInstance*>(inst))->getPackProfile();
|
||||||
QString mcVersion = ((MinecraftInstance *)inst)->getPackProfile()->getComponentVersion("net.minecraft");
|
QString mcVersion = profile->getComponentVersion("net.minecraft");
|
||||||
|
|
||||||
for(auto versionIter: arr) {
|
for (auto versionIter : arr) {
|
||||||
auto obj = versionIter.toObject();
|
auto obj = versionIter.toObject();
|
||||||
|
|
||||||
auto versionArray = Json::requireArray(obj, "gameVersion");
|
auto versionArray = Json::requireArray(obj, "gameVersions");
|
||||||
if (versionArray.isEmpty()) {
|
if (versionArray.isEmpty()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
FlameMod::IndexedVersion file;
|
ModPlatform::IndexedVersion file;
|
||||||
for(auto mcVer : versionArray){
|
for (auto mcVer : versionArray) {
|
||||||
file.mcVersion.append(mcVer.toString());
|
auto str = mcVer.toString();
|
||||||
|
|
||||||
|
if (str.contains('.'))
|
||||||
|
file.mcVersion.append(str);
|
||||||
}
|
}
|
||||||
|
|
||||||
file.addonId = pack.addonId;
|
file.addonId = pack.addonId;
|
||||||
@ -68,31 +59,11 @@ void FlameMod::loadIndexedPackVersions(FlameMod::IndexedPack & pack, QJsonArray
|
|||||||
file.downloadUrl = Json::requireString(obj, "downloadUrl");
|
file.downloadUrl = Json::requireString(obj, "downloadUrl");
|
||||||
file.fileName = Json::requireString(obj, "fileName");
|
file.fileName = Json::requireString(obj, "fileName");
|
||||||
|
|
||||||
auto modules = Json::requireArray(obj, "modules");
|
|
||||||
bool is_valid_fabric_version = false;
|
|
||||||
for(auto m : modules){
|
|
||||||
auto fname = Json::requireString(m.toObject(),"foldername");
|
|
||||||
// FIXME: This does not work properly when a mod supports more than one mod loader, since
|
|
||||||
// they bundle the meta files for all of them in the same arquive, even when that version
|
|
||||||
// doesn't support the given mod loader.
|
|
||||||
if(hasFabric){
|
|
||||||
if(fname == "fabric.mod.json"){
|
|
||||||
is_valid_fabric_version = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else break;
|
|
||||||
// NOTE: Since we're not validating forge versions, we can just skip this loop.
|
|
||||||
}
|
|
||||||
|
|
||||||
if(hasFabric && !is_valid_fabric_version)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
unsortedVersions.append(file);
|
unsortedVersions.append(file);
|
||||||
}
|
}
|
||||||
auto orderSortPredicate = [](const IndexedVersion & a, const IndexedVersion & b) -> bool
|
|
||||||
{
|
auto orderSortPredicate = [](const ModPlatform::IndexedVersion& a, const ModPlatform::IndexedVersion& b) -> bool {
|
||||||
//dates are in RFC 3339 format
|
// dates are in RFC 3339 format
|
||||||
return a.date > b.date;
|
return a.date > b.date;
|
||||||
};
|
};
|
||||||
std::sort(unsortedVersions.begin(), unsortedVersions.end(), orderSortPredicate);
|
std::sort(unsortedVersions.begin(), unsortedVersions.end(), orderSortPredicate);
|
||||||
|
@ -3,48 +3,18 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <QList>
|
|
||||||
#include <QMetaType>
|
#include "modplatform/ModIndex.h"
|
||||||
#include <QString>
|
|
||||||
#include <QVector>
|
|
||||||
#include <QNetworkAccessManager>
|
|
||||||
#include <QObjectPtr.h>
|
|
||||||
#include "net/NetJob.h"
|
|
||||||
#include "BaseInstance.h"
|
#include "BaseInstance.h"
|
||||||
|
#include <QNetworkAccessManager>
|
||||||
|
|
||||||
namespace FlameMod {
|
namespace FlameMod {
|
||||||
struct ModpackAuthor {
|
|
||||||
QString name;
|
|
||||||
QString url;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct IndexedVersion {
|
void loadIndexedPack(ModPlatform::IndexedPack& m, QJsonObject& obj);
|
||||||
int addonId;
|
void loadIndexedPackVersions(ModPlatform::IndexedPack& pack,
|
||||||
int fileId;
|
QJsonArray& arr,
|
||||||
QString version;
|
const shared_qobject_ptr<QNetworkAccessManager>& network,
|
||||||
QVector<QString> mcVersion;
|
BaseInstance* inst);
|
||||||
QString downloadUrl;
|
|
||||||
QString date;
|
|
||||||
QString fileName;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct IndexedPack
|
} // namespace FlameMod
|
||||||
{
|
|
||||||
int addonId;
|
|
||||||
QString name;
|
|
||||||
QString description;
|
|
||||||
QList<ModpackAuthor> authors;
|
|
||||||
QString logoName;
|
|
||||||
QString logoUrl;
|
|
||||||
QString websiteUrl;
|
|
||||||
|
|
||||||
bool versionsLoaded = false;
|
|
||||||
QVector<IndexedVersion> versions;
|
|
||||||
};
|
|
||||||
|
|
||||||
void loadIndexedPack(IndexedPack & m, QJsonObject & obj);
|
|
||||||
void loadIndexedPackVersions(IndexedPack &pack, QJsonArray &arr, const shared_qobject_ptr<QNetworkAccessManager> &network, BaseInstance *inst);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
Q_DECLARE_METATYPE(FlameMod::IndexedPack)
|
|
||||||
|
@ -2,76 +2,63 @@
|
|||||||
|
|
||||||
#include "Json.h"
|
#include "Json.h"
|
||||||
|
|
||||||
void Flame::loadIndexedPack(Flame::IndexedPack & pack, QJsonObject & obj)
|
void Flame::loadIndexedPack(Flame::IndexedPack& pack, QJsonObject& obj)
|
||||||
{
|
{
|
||||||
pack.addonId = Json::requireInteger(obj, "id");
|
pack.addonId = Json::requireInteger(obj, "id");
|
||||||
pack.name = Json::requireString(obj, "name");
|
pack.name = Json::requireString(obj, "name");
|
||||||
pack.websiteUrl = Json::ensureString(obj, "websiteUrl", "");
|
pack.websiteUrl = Json::ensureString(obj, "websiteUrl", "");
|
||||||
pack.description = Json::ensureString(obj, "summary", "");
|
pack.description = Json::ensureString(obj, "summary", "");
|
||||||
|
|
||||||
bool thumbnailFound = false;
|
auto logo = Json::requireObject(obj, "logo");
|
||||||
auto attachments = Json::requireArray(obj, "attachments");
|
pack.logoName = Json::requireString(logo, "title");
|
||||||
for(auto attachmentRaw: attachments) {
|
pack.logoUrl = Json::requireString(logo, "thumbnailUrl");
|
||||||
auto attachmentObj = Json::requireObject(attachmentRaw);
|
|
||||||
bool isDefault = attachmentObj.value("isDefault").toBool(false);
|
|
||||||
if(isDefault) {
|
|
||||||
thumbnailFound = true;
|
|
||||||
pack.logoName = Json::requireString(attachmentObj, "title");
|
|
||||||
pack.logoUrl = Json::requireString(attachmentObj, "thumbnailUrl");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!thumbnailFound) {
|
|
||||||
throw JSONValidationError(QString("Pack without an icon, skipping: %1").arg(pack.name));
|
|
||||||
}
|
|
||||||
|
|
||||||
auto authors = Json::requireArray(obj, "authors");
|
auto authors = Json::requireArray(obj, "authors");
|
||||||
for(auto authorIter: authors) {
|
for (auto authorIter : authors) {
|
||||||
auto author = Json::requireObject(authorIter);
|
auto author = Json::requireObject(authorIter);
|
||||||
Flame::ModpackAuthor packAuthor;
|
Flame::ModpackAuthor packAuthor;
|
||||||
packAuthor.name = Json::requireString(author, "name");
|
packAuthor.name = Json::requireString(author, "name");
|
||||||
packAuthor.url = Json::requireString(author, "url");
|
packAuthor.url = Json::requireString(author, "url");
|
||||||
pack.authors.append(packAuthor);
|
pack.authors.append(packAuthor);
|
||||||
}
|
}
|
||||||
int defaultFileId = Json::requireInteger(obj, "defaultFileId");
|
int defaultFileId = Json::requireInteger(obj, "mainFileId");
|
||||||
|
|
||||||
bool found = false;
|
bool found = false;
|
||||||
// check if there are some files before adding the pack
|
// check if there are some files before adding the pack
|
||||||
auto files = Json::requireArray(obj, "latestFiles");
|
auto files = Json::requireArray(obj, "latestFiles");
|
||||||
for(auto fileIter: files) {
|
for (auto fileIter : files) {
|
||||||
auto file = Json::requireObject(fileIter);
|
auto file = Json::requireObject(fileIter);
|
||||||
int id = Json::requireInteger(file, "id");
|
int id = Json::requireInteger(file, "id");
|
||||||
|
|
||||||
// NOTE: for now, ignore everything that's not the default...
|
// NOTE: for now, ignore everything that's not the default...
|
||||||
if(id != defaultFileId) {
|
if (id != defaultFileId) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto versionArray = Json::requireArray(file, "gameVersion");
|
auto versionArray = Json::requireArray(file, "gameVersions");
|
||||||
if(versionArray.size() < 1) {
|
if (versionArray.size() < 1) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
found = true;
|
found = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if(!found) {
|
if (!found) {
|
||||||
throw JSONValidationError(QString("Pack with no good file, skipping: %1").arg(pack.name));
|
throw JSONValidationError(QString("Pack with no good file, skipping: %1").arg(pack.name));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Flame::loadIndexedPackVersions(Flame::IndexedPack & pack, QJsonArray & arr)
|
void Flame::loadIndexedPackVersions(Flame::IndexedPack& pack, QJsonArray& arr)
|
||||||
{
|
{
|
||||||
QVector<Flame::IndexedVersion> unsortedVersions;
|
QVector<Flame::IndexedVersion> unsortedVersions;
|
||||||
for(auto versionIter: arr) {
|
for (auto versionIter : arr) {
|
||||||
auto version = Json::requireObject(versionIter);
|
auto version = Json::requireObject(versionIter);
|
||||||
Flame::IndexedVersion file;
|
Flame::IndexedVersion file;
|
||||||
|
|
||||||
file.addonId = pack.addonId;
|
file.addonId = pack.addonId;
|
||||||
file.fileId = Json::requireInteger(version, "id");
|
file.fileId = Json::requireInteger(version, "id");
|
||||||
auto versionArray = Json::requireArray(version, "gameVersion");
|
auto versionArray = Json::requireArray(version, "gameVersions");
|
||||||
if(versionArray.size() < 1) {
|
if (versionArray.size() < 1) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -82,10 +69,7 @@ void Flame::loadIndexedPackVersions(Flame::IndexedPack & pack, QJsonArray & arr)
|
|||||||
unsortedVersions.append(file);
|
unsortedVersions.append(file);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto orderSortPredicate = [](const IndexedVersion & a, const IndexedVersion & b) -> bool
|
auto orderSortPredicate = [](const IndexedVersion& a, const IndexedVersion& b) -> bool { return a.fileId > b.fileId; };
|
||||||
{
|
|
||||||
return a.fileId > b.fileId;
|
|
||||||
};
|
|
||||||
std::sort(unsortedVersions.begin(), unsortedVersions.end(), orderSortPredicate);
|
std::sort(unsortedVersions.begin(), unsortedVersions.end(), orderSortPredicate);
|
||||||
pack.versions = unsortedVersions;
|
pack.versions = unsortedVersions;
|
||||||
pack.versionsLoaded = true;
|
pack.versionsLoaded = true;
|
||||||
|
@ -1,28 +1,27 @@
|
|||||||
#include "PackManifest.h"
|
#include "PackManifest.h"
|
||||||
#include "Json.h"
|
#include "Json.h"
|
||||||
|
|
||||||
static void loadFileV1(Flame::File & f, QJsonObject & file)
|
static void loadFileV1(Flame::File& f, QJsonObject& file)
|
||||||
{
|
{
|
||||||
f.projectId = Json::requireInteger(file, "projectID");
|
f.projectId = Json::requireInteger(file, "projectID");
|
||||||
f.fileId = Json::requireInteger(file, "fileID");
|
f.fileId = Json::requireInteger(file, "fileID");
|
||||||
f.required = Json::ensureBoolean(file, QString("required"), true);
|
f.required = Json::ensureBoolean(file, QString("required"), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void loadModloaderV1(Flame::Modloader & m, QJsonObject & modLoader)
|
static void loadModloaderV1(Flame::Modloader& m, QJsonObject& modLoader)
|
||||||
{
|
{
|
||||||
m.id = Json::requireString(modLoader, "id");
|
m.id = Json::requireString(modLoader, "id");
|
||||||
m.primary = Json::ensureBoolean(modLoader, QString("primary"), false);
|
m.primary = Json::ensureBoolean(modLoader, QString("primary"), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void loadMinecraftV1(Flame::Minecraft & m, QJsonObject & minecraft)
|
static void loadMinecraftV1(Flame::Minecraft& m, QJsonObject& minecraft)
|
||||||
{
|
{
|
||||||
m.version = Json::requireString(minecraft, "version");
|
m.version = Json::requireString(minecraft, "version");
|
||||||
// extra libraries... apparently only used for a custom Minecraft launcher in the 1.2.5 FTB retro pack
|
// extra libraries... apparently only used for a custom Minecraft launcher in the 1.2.5 FTB retro pack
|
||||||
// intended use is likely hardcoded in the 'Flame' client, the manifest says nothing
|
// intended use is likely hardcoded in the 'Flame' client, the manifest says nothing
|
||||||
m.libraries = Json::ensureString(minecraft, QString("libraries"), QString());
|
m.libraries = Json::ensureString(minecraft, QString("libraries"), QString());
|
||||||
auto arr = Json::ensureArray(minecraft, "modLoaders", QJsonArray());
|
auto arr = Json::ensureArray(minecraft, "modLoaders", QJsonArray());
|
||||||
for (QJsonValueRef item : arr)
|
for (QJsonValueRef item : arr) {
|
||||||
{
|
|
||||||
auto obj = Json::requireObject(item);
|
auto obj = Json::requireObject(item);
|
||||||
Flame::Modloader loader;
|
Flame::Modloader loader;
|
||||||
loadModloaderV1(loader, obj);
|
loadModloaderV1(loader, obj);
|
||||||
@ -30,16 +29,15 @@ static void loadMinecraftV1(Flame::Minecraft & m, QJsonObject & minecraft)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void loadManifestV1(Flame::Manifest & m, QJsonObject & manifest)
|
static void loadManifestV1(Flame::Manifest& m, QJsonObject& manifest)
|
||||||
{
|
{
|
||||||
auto mc = Json::requireObject(manifest, "minecraft");
|
auto mc = Json::requireObject(manifest, "minecraft");
|
||||||
loadMinecraftV1(m.minecraft, mc);
|
loadMinecraftV1(m.minecraft, mc);
|
||||||
m.name = Json::ensureString(manifest, QString("name"), "Unnamed");
|
m.name = Json::ensureString(manifest, QString("name"), "Unnamed");
|
||||||
m.version = Json::ensureString(manifest, QString("version"), QString());
|
m.version = Json::ensureString(manifest, QString("version"), QString());
|
||||||
m.author = Json::ensureString(manifest, QString("author"), "Anonymous Coward");
|
m.author = Json::ensureString(manifest, QString("author"), "Anonymous");
|
||||||
auto arr = Json::ensureArray(manifest, "files", QJsonArray());
|
auto arr = Json::ensureArray(manifest, "files", QJsonArray());
|
||||||
for (QJsonValueRef item : arr)
|
for (QJsonValueRef item : arr) {
|
||||||
{
|
|
||||||
auto obj = Json::requireObject(item);
|
auto obj = Json::requireObject(item);
|
||||||
Flame::File file;
|
Flame::File file;
|
||||||
loadFileV1(file, obj);
|
loadFileV1(file, obj);
|
||||||
@ -48,18 +46,16 @@ static void loadManifestV1(Flame::Manifest & m, QJsonObject & manifest)
|
|||||||
m.overrides = Json::ensureString(manifest, "overrides", "overrides");
|
m.overrides = Json::ensureString(manifest, "overrides", "overrides");
|
||||||
}
|
}
|
||||||
|
|
||||||
void Flame::loadManifest(Flame::Manifest & m, const QString &filepath)
|
void Flame::loadManifest(Flame::Manifest& m, const QString& filepath)
|
||||||
{
|
{
|
||||||
auto doc = Json::requireDocument(filepath);
|
auto doc = Json::requireDocument(filepath);
|
||||||
auto obj = Json::requireObject(doc);
|
auto obj = Json::requireObject(doc);
|
||||||
m.manifestType = Json::requireString(obj, "manifestType");
|
m.manifestType = Json::requireString(obj, "manifestType");
|
||||||
if(m.manifestType != "minecraftModpack")
|
if (m.manifestType != "minecraftModpack") {
|
||||||
{
|
|
||||||
throw JSONValidationError("Not a modpack manifest!");
|
throw JSONValidationError("Not a modpack manifest!");
|
||||||
}
|
}
|
||||||
m.manifestVersion = Json::requireInteger(obj, "manifestVersion");
|
m.manifestVersion = Json::requireInteger(obj, "manifestVersion");
|
||||||
if(m.manifestVersion != 1)
|
if (m.manifestVersion != 1) {
|
||||||
{
|
|
||||||
throw JSONValidationError(QString("Unknown manifest version (%1)").arg(m.manifestVersion));
|
throw JSONValidationError(QString("Unknown manifest version (%1)").arg(m.manifestVersion));
|
||||||
}
|
}
|
||||||
loadManifestV1(m, obj);
|
loadManifestV1(m, obj);
|
||||||
@ -68,59 +64,30 @@ void Flame::loadManifest(Flame::Manifest & m, const QString &filepath)
|
|||||||
bool Flame::File::parseFromBytes(const QByteArray& bytes)
|
bool Flame::File::parseFromBytes(const QByteArray& bytes)
|
||||||
{
|
{
|
||||||
auto doc = Json::requireDocument(bytes);
|
auto doc = Json::requireDocument(bytes);
|
||||||
auto obj = Json::requireObject(doc);
|
if (!doc.isObject()) {
|
||||||
// result code signifies true failure.
|
throw JSONValidationError(QString("data is not an object? that's not supposed to happen"));
|
||||||
if(obj.contains("code"))
|
|
||||||
{
|
|
||||||
qCritical() << "Resolving of" << projectId << fileId << "failed because of a negative result:";
|
|
||||||
qCritical() << bytes;
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
fileName = Json::requireString(obj, "FileNameOnDisk");
|
auto obj = Json::ensureObject(doc.object(), "data");
|
||||||
QString rawUrl = Json::requireString(obj, "DownloadURL");
|
|
||||||
|
fileName = Json::requireString(obj, "fileName");
|
||||||
|
|
||||||
|
QString rawUrl = Json::requireString(obj, "downloadUrl");
|
||||||
url = QUrl(rawUrl, QUrl::TolerantMode);
|
url = QUrl(rawUrl, QUrl::TolerantMode);
|
||||||
if(!url.isValid())
|
if (!url.isValid()) {
|
||||||
{
|
|
||||||
throw JSONValidationError(QString("Invalid URL: %1").arg(rawUrl));
|
throw JSONValidationError(QString("Invalid URL: %1").arg(rawUrl));
|
||||||
}
|
}
|
||||||
// This is a piece of a Flame project JSON pulled out into the file metadata (here) for convenience
|
// This is a piece of a Flame project JSON pulled out into the file metadata (here) for convenience
|
||||||
// It is also optional
|
// It is also optional
|
||||||
QJsonObject projObj = Json::ensureObject(obj, "_Project", {});
|
type = File::Type::SingleFile;
|
||||||
if(!projObj.isEmpty())
|
|
||||||
{
|
if (fileName.endsWith(".zip")) {
|
||||||
QString strType = Json::ensureString(projObj, "PackageType", "mod").toLower();
|
// this is probably a resource pack
|
||||||
if(strType == "singlefile")
|
targetFolder = "resourcepacks";
|
||||||
{
|
} else {
|
||||||
type = File::Type::SingleFile;
|
// this is probably a mod, dunno what else could modpacks download
|
||||||
}
|
targetFolder = "mods";
|
||||||
else if(strType == "ctoc")
|
|
||||||
{
|
|
||||||
type = File::Type::Ctoc;
|
|
||||||
}
|
|
||||||
else if(strType == "cmod2")
|
|
||||||
{
|
|
||||||
type = File::Type::Cmod2;
|
|
||||||
}
|
|
||||||
else if(strType == "mod")
|
|
||||||
{
|
|
||||||
type = File::Type::Mod;
|
|
||||||
}
|
|
||||||
else if(strType == "folder")
|
|
||||||
{
|
|
||||||
type = File::Type::Folder;
|
|
||||||
}
|
|
||||||
else if(strType == "modpack")
|
|
||||||
{
|
|
||||||
type = File::Type::Modpack;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
qCritical() << "Resolving of" << projectId << fileId << "failed because of unknown file type:" << strType;
|
|
||||||
type = File::Type::Unknown;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
targetFolder = Json::ensureString(projObj, "Path", "mods");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
resolved = true;
|
resolved = true;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
60
launcher/modplatform/helpers/NetworkModAPI.cpp
Normal file
60
launcher/modplatform/helpers/NetworkModAPI.cpp
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
#include "NetworkModAPI.h"
|
||||||
|
|
||||||
|
#include "ui/pages/modplatform/ModModel.h"
|
||||||
|
|
||||||
|
#include "Application.h"
|
||||||
|
#include "net/NetJob.h"
|
||||||
|
|
||||||
|
void NetworkModAPI::searchMods(CallerType* caller, SearchArgs&& args) const
|
||||||
|
{
|
||||||
|
auto netJob = new NetJob(QString("%1::Search").arg(caller->debugName()), APPLICATION->network());
|
||||||
|
auto searchUrl = getModSearchURL(args);
|
||||||
|
|
||||||
|
auto response = new QByteArray();
|
||||||
|
netJob->addNetAction(Net::Download::makeByteArray(QUrl(searchUrl), response));
|
||||||
|
|
||||||
|
QObject::connect(netJob, &NetJob::started, caller, [caller, netJob] { caller->setActiveJob(netJob); });
|
||||||
|
QObject::connect(netJob, &NetJob::failed, caller, &CallerType::searchRequestFailed);
|
||||||
|
QObject::connect(netJob, &NetJob::succeeded, caller, [caller, response] {
|
||||||
|
QJsonParseError parse_error{};
|
||||||
|
QJsonDocument doc = QJsonDocument::fromJson(*response, &parse_error);
|
||||||
|
if (parse_error.error != QJsonParseError::NoError) {
|
||||||
|
qWarning() << "Error while parsing JSON response from " << caller->debugName() << " at " << parse_error.offset
|
||||||
|
<< " reason: " << parse_error.errorString();
|
||||||
|
qWarning() << *response;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
caller->searchRequestFinished(doc);
|
||||||
|
});
|
||||||
|
|
||||||
|
netJob->start();
|
||||||
|
}
|
||||||
|
|
||||||
|
void NetworkModAPI::getVersions(CallerType* caller, VersionSearchArgs&& args) const
|
||||||
|
{
|
||||||
|
auto netJob = new NetJob(QString("%1::ModVersions(%2)").arg(caller->debugName()).arg(args.addonId), APPLICATION->network());
|
||||||
|
auto response = new QByteArray();
|
||||||
|
|
||||||
|
netJob->addNetAction(Net::Download::makeByteArray(getVersionsURL(args), response));
|
||||||
|
|
||||||
|
QObject::connect(netJob, &NetJob::succeeded, caller, [response, caller, args] {
|
||||||
|
QJsonParseError parse_error{};
|
||||||
|
QJsonDocument doc = QJsonDocument::fromJson(*response, &parse_error);
|
||||||
|
if (parse_error.error != QJsonParseError::NoError) {
|
||||||
|
qWarning() << "Error while parsing JSON response from " << caller->debugName() << " at " << parse_error.offset
|
||||||
|
<< " reason: " << parse_error.errorString();
|
||||||
|
qWarning() << *response;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
caller->versionRequestSucceeded(doc, args.addonId);
|
||||||
|
});
|
||||||
|
|
||||||
|
QObject::connect(netJob, &NetJob::finished, caller, [response, netJob] {
|
||||||
|
netJob->deleteLater();
|
||||||
|
delete response;
|
||||||
|
});
|
||||||
|
|
||||||
|
netJob->start();
|
||||||
|
}
|
13
launcher/modplatform/helpers/NetworkModAPI.h
Normal file
13
launcher/modplatform/helpers/NetworkModAPI.h
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "modplatform/ModAPI.h"
|
||||||
|
|
||||||
|
class NetworkModAPI : public ModAPI {
|
||||||
|
public:
|
||||||
|
void searchMods(CallerType* caller, SearchArgs&& args) const override;
|
||||||
|
void getVersions(CallerType* caller, VersionSearchArgs&& args) const override;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual auto getModSearchURL(SearchArgs& args) const -> QString = 0;
|
||||||
|
virtual auto getVersionsURL(VersionSearchArgs& args) const -> QString = 0;
|
||||||
|
};
|
@ -114,7 +114,7 @@ void PackInstallTask::install()
|
|||||||
//ok, found minecraft dir, move contents to instance dir
|
//ok, found minecraft dir, move contents to instance dir
|
||||||
if(!QDir().rename(m_stagingPath + "/unzip/minecraft", m_stagingPath + "/.minecraft"))
|
if(!QDir().rename(m_stagingPath + "/unzip/minecraft", m_stagingPath + "/.minecraft"))
|
||||||
{
|
{
|
||||||
emitFailed(tr("Failed to move unzipped minecraft!"));
|
emitFailed(tr("Failed to move unzipped Minecraft!"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
89
launcher/modplatform/modrinth/ModrinthAPI.h
Normal file
89
launcher/modplatform/modrinth/ModrinthAPI.h
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "modplatform/ModAPI.h"
|
||||||
|
#include "modplatform/helpers/NetworkModAPI.h"
|
||||||
|
|
||||||
|
#include <QDebug>
|
||||||
|
|
||||||
|
class ModrinthAPI : public NetworkModAPI {
|
||||||
|
public:
|
||||||
|
inline auto getAuthorURL(const QString& name) const -> QString { return "https://modrinth.com/user/" + name; };
|
||||||
|
|
||||||
|
static auto getModLoaderStrings(ModLoaderType type) -> const QStringList
|
||||||
|
{
|
||||||
|
QStringList l;
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case Unspecified:
|
||||||
|
for (auto loader : {Forge, Fabric, Quilt})
|
||||||
|
{
|
||||||
|
l << ModAPI::getModLoaderString(loader);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Quilt:
|
||||||
|
l << ModAPI::getModLoaderString(Fabric);
|
||||||
|
default:
|
||||||
|
l << ModAPI::getModLoaderString(type);
|
||||||
|
}
|
||||||
|
return l;
|
||||||
|
}
|
||||||
|
|
||||||
|
static auto getModLoaderFilters(ModLoaderType type) -> const QString
|
||||||
|
{
|
||||||
|
QStringList l;
|
||||||
|
for (auto loader : getModLoaderStrings(type))
|
||||||
|
{
|
||||||
|
l << QString("\"categories:%1\"").arg(loader);
|
||||||
|
}
|
||||||
|
return l.join(',');
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
inline auto getModSearchURL(SearchArgs& args) const -> QString override
|
||||||
|
{
|
||||||
|
if (!validateModLoader(args.mod_loader)) {
|
||||||
|
qWarning() << "Modrinth only have Forge and Fabric-compatible mods!";
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
return QString(
|
||||||
|
"https://api.modrinth.com/v2/search?"
|
||||||
|
"offset=%1&"
|
||||||
|
"limit=25&"
|
||||||
|
"query=%2&"
|
||||||
|
"index=%3&"
|
||||||
|
"facets=[[%4],%5[\"project_type:mod\"]]")
|
||||||
|
.arg(args.offset)
|
||||||
|
.arg(args.search)
|
||||||
|
.arg(args.sorting)
|
||||||
|
.arg(getModLoaderFilters(args.mod_loader))
|
||||||
|
.arg(getGameVersionsArray(args.versions));
|
||||||
|
};
|
||||||
|
|
||||||
|
inline auto getVersionsURL(VersionSearchArgs& args) const -> QString override
|
||||||
|
{
|
||||||
|
return QString("https://api.modrinth.com/v2/project/%1/version?"
|
||||||
|
"game_versions=[%2]"
|
||||||
|
"loaders=[\"%3\"]")
|
||||||
|
.arg(args.addonId)
|
||||||
|
.arg(getGameVersionsString(args.mcVersions))
|
||||||
|
.arg(getModLoaderStrings(args.loader).join("\",\""));
|
||||||
|
};
|
||||||
|
|
||||||
|
auto getGameVersionsArray(std::list<Version> mcVersions) const -> QString
|
||||||
|
{
|
||||||
|
QString s;
|
||||||
|
for(auto& ver : mcVersions){
|
||||||
|
s += QString("\"versions:%1\",").arg(ver.toString());
|
||||||
|
}
|
||||||
|
s.remove(s.length() - 1, 1); //remove last comma
|
||||||
|
return s.isEmpty() ? QString() : QString("[%1],").arg(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline auto validateModLoader(ModLoaderType modLoader) const -> bool
|
||||||
|
{
|
||||||
|
return modLoader == Unspecified || modLoader == Forge || modLoader == Fabric || modLoader == Quilt;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
@ -1,92 +1,88 @@
|
|||||||
#include <QObject>
|
|
||||||
#include "ModrinthPackIndex.h"
|
#include "ModrinthPackIndex.h"
|
||||||
|
#include "ModrinthAPI.h"
|
||||||
|
|
||||||
#include "Json.h"
|
#include "Json.h"
|
||||||
#include "net/NetJob.h"
|
|
||||||
#include "BaseInstance.h"
|
|
||||||
#include "minecraft/MinecraftInstance.h"
|
#include "minecraft/MinecraftInstance.h"
|
||||||
#include "minecraft/PackProfile.h"
|
#include "minecraft/PackProfile.h"
|
||||||
|
#include "net/NetJob.h"
|
||||||
|
|
||||||
|
static ModrinthAPI api;
|
||||||
|
|
||||||
void Modrinth::loadIndexedPack(Modrinth::IndexedPack & pack, QJsonObject & obj)
|
void Modrinth::loadIndexedPack(ModPlatform::IndexedPack& pack, QJsonObject& obj)
|
||||||
{
|
{
|
||||||
pack.addonId = Json::requireString(obj, "project_id");
|
pack.addonId = Json::requireString(obj, "project_id");
|
||||||
pack.name = Json::requireString(obj, "title");
|
pack.name = Json::requireString(obj, "title");
|
||||||
pack.websiteUrl = Json::ensureString(obj, "page_url", "");
|
|
||||||
|
QString slug = Json::ensureString(obj, "slug", "");
|
||||||
|
if (!slug.isEmpty())
|
||||||
|
pack.websiteUrl = "https://modrinth.com/mod/" + Json::ensureString(obj, "slug", "");
|
||||||
|
else
|
||||||
|
pack.websiteUrl = "";
|
||||||
|
|
||||||
pack.description = Json::ensureString(obj, "description", "");
|
pack.description = Json::ensureString(obj, "description", "");
|
||||||
|
|
||||||
pack.logoUrl = Json::requireString(obj, "icon_url");
|
pack.logoUrl = Json::requireString(obj, "icon_url");
|
||||||
pack.logoName = pack.addonId;
|
pack.logoName = pack.addonId.toString();
|
||||||
|
|
||||||
Modrinth::ModpackAuthor modAuthor;
|
ModPlatform::ModpackAuthor modAuthor;
|
||||||
modAuthor.name = Json::requireString(obj, "author");
|
modAuthor.name = Json::requireString(obj, "author");
|
||||||
modAuthor.url = "https://modrinth.com/user/"+modAuthor.name;
|
modAuthor.url = api.getAuthorURL(modAuthor.name);
|
||||||
pack.author = modAuthor;
|
pack.authors.append(modAuthor);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Modrinth::loadIndexedPackVersions(Modrinth::IndexedPack & pack, QJsonArray & arr, const shared_qobject_ptr<QNetworkAccessManager>& network, BaseInstance * inst)
|
void Modrinth::loadIndexedPackVersions(ModPlatform::IndexedPack& pack,
|
||||||
|
QJsonArray& arr,
|
||||||
|
const shared_qobject_ptr<QNetworkAccessManager>& network,
|
||||||
|
BaseInstance* inst)
|
||||||
{
|
{
|
||||||
QVector<Modrinth::IndexedVersion> unsortedVersions;
|
QVector<ModPlatform::IndexedVersion> unsortedVersions;
|
||||||
bool hasFabric = !((MinecraftInstance *)inst)->getPackProfile()->getComponentVersion("net.fabricmc.fabric-loader").isEmpty();
|
QString mcVersion = (static_cast<MinecraftInstance*>(inst))->getPackProfile()->getComponentVersion("net.minecraft");
|
||||||
QString mcVersion = ((MinecraftInstance *)inst)->getPackProfile()->getComponentVersion("net.minecraft");
|
|
||||||
|
|
||||||
for(auto versionIter: arr) {
|
for (auto versionIter : arr) {
|
||||||
auto obj = versionIter.toObject();
|
auto obj = versionIter.toObject();
|
||||||
Modrinth::IndexedVersion file;
|
ModPlatform::IndexedVersion file;
|
||||||
file.addonId = Json::requireString(obj,"project_id") ;
|
file.addonId = Json::requireString(obj, "project_id");
|
||||||
file.fileId = Json::requireString(obj, "id");
|
file.fileId = Json::requireString(obj, "id");
|
||||||
file.date = Json::requireString(obj, "date_published");
|
file.date = Json::requireString(obj, "date_published");
|
||||||
auto versionArray = Json::requireArray(obj, "game_versions");
|
auto versionArray = Json::requireArray(obj, "game_versions");
|
||||||
if (versionArray.empty()) {
|
if (versionArray.empty()) { continue; }
|
||||||
continue;
|
for (auto mcVer : versionArray) {
|
||||||
}
|
|
||||||
for(auto mcVer : versionArray){
|
|
||||||
file.mcVersion.append(mcVer.toString());
|
file.mcVersion.append(mcVer.toString());
|
||||||
}
|
}
|
||||||
auto loaders = Json::requireArray(obj,"loaders");
|
auto loaders = Json::requireArray(obj, "loaders");
|
||||||
for(auto loader : loaders){
|
for (auto loader : loaders) {
|
||||||
file.loaders.append(loader.toString());
|
file.loaders.append(loader.toString());
|
||||||
}
|
}
|
||||||
file.version = Json::requireString(obj, "name");
|
file.version = Json::requireString(obj, "name");
|
||||||
|
|
||||||
auto files = Json::requireArray(obj, "files");
|
auto files = Json::requireArray(obj, "files");
|
||||||
int i = 0;
|
int i = 0;
|
||||||
while (files.count() > 1 && i < files.count()){
|
|
||||||
//try to resolve the correct file
|
// Find correct file (needed in cases where one version may have multiple files)
|
||||||
|
// Will default to the last one if there's no primary (though I think Modrinth requires that
|
||||||
|
// at least one file is primary, idk)
|
||||||
|
// NOTE: files.count() is 1-indexed, so we need to subtract 1 to become 0-indexed
|
||||||
|
while (i < files.count() - 1){
|
||||||
auto parent = files[i].toObject();
|
auto parent = files[i].toObject();
|
||||||
auto fileName = Json::requireString(parent, "filename");
|
auto fileName = Json::requireString(parent, "filename");
|
||||||
//avoid grabbing "dev" files
|
|
||||||
if(fileName.contains("javadocs",Qt::CaseInsensitive) || fileName.contains("sources",Qt::CaseInsensitive)){
|
// Grab the primary file, if available
|
||||||
i++;
|
if(Json::requireBoolean(parent, "primary"))
|
||||||
continue;
|
break;
|
||||||
}
|
|
||||||
//grab the correct mod loader
|
i++;
|
||||||
if(fileName.contains("forge",Qt::CaseInsensitive) || fileName.contains("fabric",Qt::CaseInsensitive) ){
|
|
||||||
if(hasFabric){
|
|
||||||
if(fileName.contains("forge",Qt::CaseInsensitive)){
|
|
||||||
i++;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}else{
|
|
||||||
if(fileName.contains("fabric",Qt::CaseInsensitive)){
|
|
||||||
i++;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto parent = files[i].toObject();
|
auto parent = files[i].toObject();
|
||||||
if(parent.contains("url")) {
|
if (parent.contains("url")) {
|
||||||
file.downloadUrl = Json::requireString(parent, "url");
|
file.downloadUrl = Json::requireString(parent, "url");
|
||||||
file.fileName = Json::requireString(parent, "filename");
|
file.fileName = Json::requireString(parent, "filename");
|
||||||
|
|
||||||
unsortedVersions.append(file);
|
unsortedVersions.append(file);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
auto orderSortPredicate = [](const IndexedVersion & a, const IndexedVersion & b) -> bool
|
auto orderSortPredicate = [](const ModPlatform::IndexedVersion& a, const ModPlatform::IndexedVersion& b) -> bool {
|
||||||
{
|
// dates are in RFC 3339 format
|
||||||
//dates are in RFC 3339 format
|
|
||||||
return a.date > b.date;
|
return a.date > b.date;
|
||||||
};
|
};
|
||||||
std::sort(unsortedVersions.begin(), unsortedVersions.end(), orderSortPredicate);
|
std::sort(unsortedVersions.begin(), unsortedVersions.end(), orderSortPredicate);
|
||||||
|
@ -1,48 +1,16 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <QList>
|
#include "modplatform/ModIndex.h"
|
||||||
#include <QMetaType>
|
|
||||||
#include <QString>
|
|
||||||
#include <QVector>
|
|
||||||
#include <QNetworkAccessManager>
|
|
||||||
#include <QObjectPtr.h>
|
|
||||||
#include "net/NetJob.h"
|
|
||||||
#include "BaseInstance.h"
|
#include "BaseInstance.h"
|
||||||
|
#include <QNetworkAccessManager>
|
||||||
|
|
||||||
namespace Modrinth {
|
namespace Modrinth {
|
||||||
|
|
||||||
struct ModpackAuthor {
|
void loadIndexedPack(ModPlatform::IndexedPack& m, QJsonObject& obj);
|
||||||
QString name;
|
void loadIndexedPackVersions(ModPlatform::IndexedPack& pack,
|
||||||
QString url;
|
QJsonArray& arr,
|
||||||
};
|
const shared_qobject_ptr<QNetworkAccessManager>& network,
|
||||||
|
BaseInstance* inst);
|
||||||
|
|
||||||
struct IndexedVersion {
|
} // namespace Modrinth
|
||||||
QString addonId;
|
|
||||||
QString fileId;
|
|
||||||
QString version;
|
|
||||||
QVector<QString> mcVersion;
|
|
||||||
QString downloadUrl;
|
|
||||||
QString date;
|
|
||||||
QString fileName;
|
|
||||||
QVector<QString> loaders;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct IndexedPack
|
|
||||||
{
|
|
||||||
QString addonId;
|
|
||||||
QString name;
|
|
||||||
QString description;
|
|
||||||
ModpackAuthor author;
|
|
||||||
QString logoName;
|
|
||||||
QString logoUrl;
|
|
||||||
QString websiteUrl;
|
|
||||||
|
|
||||||
bool versionsLoaded = false;
|
|
||||||
QVector<IndexedVersion> versions;
|
|
||||||
};
|
|
||||||
|
|
||||||
void loadIndexedPack(IndexedPack & m, QJsonObject & obj);
|
|
||||||
void loadIndexedPackVersions(IndexedPack &pack, QJsonArray &arr, const shared_qobject_ptr<QNetworkAccessManager> &network, BaseInstance *inst);
|
|
||||||
}
|
|
||||||
|
|
||||||
Q_DECLARE_METATYPE(Modrinth::IndexedPack)
|
|
||||||
|
@ -1,16 +1,36 @@
|
|||||||
/* Copyright 2013-2021 MultiMC Contributors
|
// SPDX-License-Identifier: GPL-3.0-only
|
||||||
|
/*
|
||||||
|
* PolyMC - Minecraft Launcher
|
||||||
|
* Copyright (c) 2021-2022 Jamie Mansfield <jmansfield@cadixdev.org>
|
||||||
*
|
*
|
||||||
* 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 "SolderPackInstallTask.h"
|
#include "SolderPackInstallTask.h"
|
||||||
@ -19,16 +39,23 @@
|
|||||||
#include <Json.h>
|
#include <Json.h>
|
||||||
#include <QtConcurrentRun>
|
#include <QtConcurrentRun>
|
||||||
#include <MMCZip.h>
|
#include <MMCZip.h>
|
||||||
|
|
||||||
#include "TechnicPackProcessor.h"
|
#include "TechnicPackProcessor.h"
|
||||||
|
#include "SolderPackManifest.h"
|
||||||
|
#include "net/ChecksumValidator.h"
|
||||||
|
|
||||||
Technic::SolderPackInstallTask::SolderPackInstallTask(
|
Technic::SolderPackInstallTask::SolderPackInstallTask(
|
||||||
shared_qobject_ptr<QNetworkAccessManager> network,
|
shared_qobject_ptr<QNetworkAccessManager> network,
|
||||||
const QUrl &sourceUrl,
|
const QUrl &solderUrl,
|
||||||
|
const QString &pack,
|
||||||
|
const QString &version,
|
||||||
const QString &minecraftVersion
|
const QString &minecraftVersion
|
||||||
) {
|
) {
|
||||||
m_sourceUrl = sourceUrl;
|
m_solderUrl = solderUrl;
|
||||||
m_minecraftVersion = minecraftVersion;
|
m_pack = pack;
|
||||||
|
m_version = version;
|
||||||
m_network = network;
|
m_network = network;
|
||||||
|
m_minecraftVersion = minecraftVersion;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Technic::SolderPackInstallTask::abort() {
|
bool Technic::SolderPackInstallTask::abort() {
|
||||||
@ -41,34 +68,12 @@ bool Technic::SolderPackInstallTask::abort() {
|
|||||||
|
|
||||||
void Technic::SolderPackInstallTask::executeTask()
|
void Technic::SolderPackInstallTask::executeTask()
|
||||||
{
|
{
|
||||||
setStatus(tr("Finding recommended version:\n%1").arg(m_sourceUrl.toString()));
|
setStatus(tr("Resolving modpack files"));
|
||||||
m_filesNetJob = new NetJob(tr("Finding recommended version"), m_network);
|
|
||||||
m_filesNetJob->addNetAction(Net::Download::makeByteArray(m_sourceUrl, &m_response));
|
|
||||||
auto job = m_filesNetJob.get();
|
|
||||||
connect(job, &NetJob::succeeded, this, &Technic::SolderPackInstallTask::versionSucceeded);
|
|
||||||
connect(job, &NetJob::failed, this, &Technic::SolderPackInstallTask::downloadFailed);
|
|
||||||
m_filesNetJob->start();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Technic::SolderPackInstallTask::versionSucceeded()
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
QJsonDocument doc = Json::requireDocument(m_response);
|
|
||||||
QJsonObject obj = Json::requireObject(doc);
|
|
||||||
QString version = Json::requireString(obj, "recommended", "__placeholder__");
|
|
||||||
m_sourceUrl = m_sourceUrl.toString() + '/' + version;
|
|
||||||
}
|
|
||||||
catch (const JSONValidationError &e)
|
|
||||||
{
|
|
||||||
emitFailed(e.cause());
|
|
||||||
m_filesNetJob.reset();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
setStatus(tr("Resolving modpack files:\n%1").arg(m_sourceUrl.toString()));
|
|
||||||
m_filesNetJob = new NetJob(tr("Resolving modpack files"), m_network);
|
m_filesNetJob = new NetJob(tr("Resolving modpack files"), m_network);
|
||||||
m_filesNetJob->addNetAction(Net::Download::makeByteArray(m_sourceUrl, &m_response));
|
auto sourceUrl = QString("%1/modpack/%2/%3").arg(m_solderUrl.toString(), m_pack, m_version);
|
||||||
|
m_filesNetJob->addNetAction(Net::Download::makeByteArray(sourceUrl, &m_response));
|
||||||
|
|
||||||
auto job = m_filesNetJob.get();
|
auto job = m_filesNetJob.get();
|
||||||
connect(job, &NetJob::succeeded, this, &Technic::SolderPackInstallTask::fileListSucceeded);
|
connect(job, &NetJob::succeeded, this, &Technic::SolderPackInstallTask::fileListSucceeded);
|
||||||
connect(job, &NetJob::failed, this, &Technic::SolderPackInstallTask::downloadFailed);
|
connect(job, &NetJob::failed, this, &Technic::SolderPackInstallTask::downloadFailed);
|
||||||
@ -77,38 +82,47 @@ void Technic::SolderPackInstallTask::versionSucceeded()
|
|||||||
|
|
||||||
void Technic::SolderPackInstallTask::fileListSucceeded()
|
void Technic::SolderPackInstallTask::fileListSucceeded()
|
||||||
{
|
{
|
||||||
setStatus(tr("Downloading modpack:"));
|
setStatus(tr("Downloading modpack"));
|
||||||
QStringList modUrls;
|
|
||||||
try
|
QJsonParseError parse_error {};
|
||||||
{
|
QJsonDocument doc = QJsonDocument::fromJson(m_response, &parse_error);
|
||||||
QJsonDocument doc = Json::requireDocument(m_response);
|
if (parse_error.error != QJsonParseError::NoError) {
|
||||||
QJsonObject obj = Json::requireObject(doc);
|
qWarning() << "Error while parsing JSON response from Solder at " << parse_error.offset << " reason: " << parse_error.errorString();
|
||||||
QString minecraftVersion = Json::ensureString(obj, "minecraft", QString(), "__placeholder__");
|
qWarning() << m_response;
|
||||||
if (!minecraftVersion.isEmpty())
|
return;
|
||||||
m_minecraftVersion = minecraftVersion;
|
|
||||||
QJsonArray mods = Json::requireArray(obj, "mods", "'mods'");
|
|
||||||
for (auto mod: mods)
|
|
||||||
{
|
|
||||||
QJsonObject modObject = Json::requireObject(mod);
|
|
||||||
modUrls.append(Json::requireString(modObject, "url", "'url'"));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
catch (const JSONValidationError &e)
|
auto obj = doc.object();
|
||||||
{
|
|
||||||
emitFailed(e.cause());
|
TechnicSolder::PackBuild build;
|
||||||
|
try {
|
||||||
|
TechnicSolder::loadPackBuild(build, obj);
|
||||||
|
}
|
||||||
|
catch (const JSONValidationError& e) {
|
||||||
|
emitFailed(tr("Could not understand pack manifest:\n") + e.cause());
|
||||||
m_filesNetJob.reset();
|
m_filesNetJob.reset();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!build.minecraft.isEmpty())
|
||||||
|
m_minecraftVersion = build.minecraft;
|
||||||
|
|
||||||
m_filesNetJob = new NetJob(tr("Downloading modpack"), m_network);
|
m_filesNetJob = new NetJob(tr("Downloading modpack"), m_network);
|
||||||
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
for (auto &modUrl: modUrls)
|
for (const auto &mod : build.mods) {
|
||||||
{
|
|
||||||
auto path = FS::PathCombine(m_outputDir.path(), QString("%1").arg(i));
|
auto path = FS::PathCombine(m_outputDir.path(), QString("%1").arg(i));
|
||||||
m_filesNetJob->addNetAction(Net::Download::makeFile(modUrl, path));
|
|
||||||
|
auto dl = Net::Download::makeFile(mod.url, path);
|
||||||
|
if (!mod.md5.isEmpty()) {
|
||||||
|
auto rawMd5 = QByteArray::fromHex(mod.md5.toLatin1());
|
||||||
|
dl->addValidator(new Net::ChecksumValidator(QCryptographicHash::Md5, rawMd5));
|
||||||
|
}
|
||||||
|
m_filesNetJob->addNetAction(dl);
|
||||||
|
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_modCount = modUrls.size();
|
m_modCount = build.mods.size();
|
||||||
|
|
||||||
connect(m_filesNetJob.get(), &NetJob::succeeded, this, &Technic::SolderPackInstallTask::downloadSucceeded);
|
connect(m_filesNetJob.get(), &NetJob::succeeded, this, &Technic::SolderPackInstallTask::downloadSucceeded);
|
||||||
connect(m_filesNetJob.get(), &NetJob::progress, this, &Technic::SolderPackInstallTask::downloadProgressChanged);
|
connect(m_filesNetJob.get(), &NetJob::progress, this, &Technic::SolderPackInstallTask::downloadProgressChanged);
|
||||||
@ -206,6 +220,5 @@ void Technic::SolderPackInstallTask::extractFinished()
|
|||||||
void Technic::SolderPackInstallTask::extractAborted()
|
void Technic::SolderPackInstallTask::extractAborted()
|
||||||
{
|
{
|
||||||
emitFailed(tr("Instance import has been aborted."));
|
emitFailed(tr("Instance import has been aborted."));
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,16 +1,36 @@
|
|||||||
/* Copyright 2013-2021 MultiMC Contributors
|
// SPDX-License-Identifier: GPL-3.0-only
|
||||||
|
/*
|
||||||
|
* PolyMC - Minecraft Launcher
|
||||||
|
* Copyright (c) 2021-2022 Jamie Mansfield <jmansfield@cadixdev.org>
|
||||||
*
|
*
|
||||||
* 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
|
||||||
@ -27,7 +47,7 @@ namespace Technic
|
|||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
explicit SolderPackInstallTask(shared_qobject_ptr<QNetworkAccessManager> network, const QUrl &sourceUrl, const QString &minecraftVersion);
|
explicit SolderPackInstallTask(shared_qobject_ptr<QNetworkAccessManager> network, const QUrl &solderUrl, const QString& pack, const QString& version, const QString &minecraftVersion);
|
||||||
|
|
||||||
bool canAbort() const override { return true; }
|
bool canAbort() const override { return true; }
|
||||||
bool abort() override;
|
bool abort() override;
|
||||||
@ -37,7 +57,6 @@ namespace Technic
|
|||||||
virtual void executeTask() override;
|
virtual void executeTask() override;
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void versionSucceeded();
|
|
||||||
void fileListSucceeded();
|
void fileListSucceeded();
|
||||||
void downloadSucceeded();
|
void downloadSucceeded();
|
||||||
void downloadFailed(QString reason);
|
void downloadFailed(QString reason);
|
||||||
@ -51,7 +70,9 @@ namespace Technic
|
|||||||
shared_qobject_ptr<QNetworkAccessManager> m_network;
|
shared_qobject_ptr<QNetworkAccessManager> m_network;
|
||||||
|
|
||||||
NetJob::Ptr m_filesNetJob;
|
NetJob::Ptr m_filesNetJob;
|
||||||
QUrl m_sourceUrl;
|
QUrl m_solderUrl;
|
||||||
|
QString m_pack;
|
||||||
|
QString m_version;
|
||||||
QString m_minecraftVersion;
|
QString m_minecraftVersion;
|
||||||
QByteArray m_response;
|
QByteArray m_response;
|
||||||
QTemporaryDir m_outputDir;
|
QTemporaryDir m_outputDir;
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user