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
|
||||
description: File a bug report
|
||||
labels: [bug, needs-triage]
|
||||
labels: [bug]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
@ -8,7 +8,7 @@ body:
|
||||
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:
|
||||
* 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 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
|
||||
name: Request for Comment (RFC)
|
||||
description: Propose a larger change and start a discussion.
|
||||
labels: [RFC]
|
||||
labels: [rfc]
|
||||
body:
|
||||
- type: markdown
|
||||
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.
|
||||
Some example points of discussion:
|
||||
- What specific problems are you facing right now that you're trying to address?
|
||||
- Are there any previous discussions? Link to them and summarize them (don't
|
||||
- force your readers to read them though!).
|
||||
- Are there any previous discussions? Link to them and summarize them (don't force your readers to read them though!).
|
||||
- Is there any precedent set by other software? If so, link to resources.
|
||||
placeholder: I don't like cats. I think many users also don't like cats.
|
||||
validations:
|
||||
|
2
.github/ISSUE_TEMPLATE/suggestion.yml
vendored
2
.github/ISSUE_TEMPLATE/suggestion.yml
vendored
@ -1,6 +1,6 @@
|
||||
name: Suggestion
|
||||
description: Make a suggestion
|
||||
labels: [idea, needs-triage]
|
||||
labels: [enhancement]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
|
2
.github/scripts/prepare_JREs.sh
vendored
2
.github/scripts/prepare_JREs.sh
vendored
@ -1,6 +1,6 @@
|
||||
#!/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"
|
||||
|
||||
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:
|
||||
|
||||
- os: ubuntu-20.04
|
||||
qt_version: 5.12.8
|
||||
qt_host: linux
|
||||
|
||||
- os: ubuntu-20.04
|
||||
qt_version: 5.15.2
|
||||
qt_host: linux
|
||||
app_image: true
|
||||
appimage: true
|
||||
|
||||
- os: windows-2022
|
||||
qt_version: 5.15.2
|
||||
qt_host: windows
|
||||
qt_arch: win32_mingw81
|
||||
name: "Windows-i686"
|
||||
msystem: mingw32
|
||||
|
||||
- os: windows-2022
|
||||
name: "Windows-x86_64"
|
||||
msystem: mingw64
|
||||
|
||||
- os: macos-11
|
||||
qt_version: 5.12.12
|
||||
qt_host: mac
|
||||
macosx_deployment_target: 10.12
|
||||
macosx_deployment_target: 10.13
|
||||
|
||||
runs-on: ${{ matrix.os }}
|
||||
|
||||
env:
|
||||
MACOSX_DEPLOYMENT_TARGET: ${{ matrix.macosx_deployment_target }}
|
||||
INSTALL_DIR: "install"
|
||||
INSTALL_PORTABLE_DIR: "install-portable"
|
||||
INSTALL_APPIMAGE_DIR: "install-appdir"
|
||||
BUILD_DIR: "build"
|
||||
|
||||
steps:
|
||||
- name: Install 32bit mingw on Windows
|
||||
if: runner.os == 'Windows'
|
||||
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
|
||||
|
||||
##
|
||||
# PREPARE
|
||||
##
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
submodules: 'true'
|
||||
|
||||
# We need to do this here because it inexplicably fails if we split the step
|
||||
- name: Download and install OpenSSL libs on Windows
|
||||
- name: 'Setup MSYS2'
|
||||
if: runner.os == 'Windows'
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
python -m pip install aqtinstall==2.0.5
|
||||
python -m aqt install-tool -O "${{ github.workspace }}\Qt\" windows desktop tools_openssl_x86
|
||||
mkdir ${{ env.INSTALL_DIR }}
|
||||
copy "${{ github.workspace }}\Qt\Tools\OpenSSL\Win_x86\bin\libssl-1_1.dll" "${{ github.workspace }}\${{ env.INSTALL_DIR }}\"
|
||||
copy "${{ github.workspace }}\Qt\Tools\OpenSSL\Win_x86\bin\libcrypto-1_1.dll" "${{ github.workspace }}\${{ env.INSTALL_DIR }}\"
|
||||
uses: msys2/setup-msys2@v2
|
||||
with:
|
||||
msystem: ${{ matrix.msystem }}
|
||||
update: true
|
||||
install: >-
|
||||
git
|
||||
pacboy: >-
|
||||
toolchain:p
|
||||
cmake:p
|
||||
ninja:p
|
||||
qt5:p
|
||||
|
||||
- name: Set short version
|
||||
shell: bash
|
||||
@ -75,148 +69,187 @@ jobs:
|
||||
ver_short=`git rev-parse --short HEAD`
|
||||
echo "VERSION=$ver_short" >> $GITHUB_ENV
|
||||
|
||||
- name: Install OpenJDK
|
||||
uses: AdoptOpenJDK/install-jdk@v1
|
||||
with:
|
||||
version: '17'
|
||||
- name: Install Qt (macOS)
|
||||
if: runner.os == 'macOS'
|
||||
run: |
|
||||
brew update
|
||||
brew install qt@5 ninja
|
||||
|
||||
- name: Update Qt (AppImage)
|
||||
if: runner.os == 'Linux' && matrix.appimage == true
|
||||
run: |
|
||||
sudo add-apt-repository ppa:savoury1/qt-5-15
|
||||
|
||||
- name: Cache Qt
|
||||
id: cache-qt
|
||||
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
|
||||
- name: Install Qt (Linux)
|
||||
if: runner.os == 'Linux'
|
||||
run: |
|
||||
sudo apt-get -y update
|
||||
sudo apt-get -y install qtbase5-dev qtchooser qt5-qmake qtbase5-dev-tools libqt5core5a libqt5network5 libqt5gui5
|
||||
sudo apt-get -y install qtbase5-dev qtchooser qt5-qmake qtbase5-dev-tools libqt5core5a libqt5network5 libqt5gui5 ninja-build
|
||||
|
||||
- name: Install Ninja
|
||||
uses: urkle/action-get-ninja@v1
|
||||
|
||||
- name: Download linuxdeploy family for AppImage on Linux
|
||||
if: matrix.app_image == true
|
||||
- name: Prepare AppImage (Linux)
|
||||
if: runner.os == 'Linux' && matrix.appimage == true
|
||||
run: |
|
||||
wget "https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-x86_64.AppImage"
|
||||
wget "https://github.com/linuxdeploy/linuxdeploy-plugin-appimage/releases/download/continuous/linuxdeploy-plugin-appimage-x86_64.AppImage"
|
||||
wget "https://github.com/linuxdeploy/linuxdeploy-plugin-qt/releases/download/continuous/linuxdeploy-plugin-qt-x86_64.AppImage"
|
||||
|
||||
- name: Download JREs for AppImage on Linux
|
||||
if: matrix.app_image == true
|
||||
shell: bash
|
||||
run: |
|
||||
${{ github.workspace }}/.github/scripts/prepare_JREs.sh
|
||||
|
||||
- name: Configure CMake
|
||||
if: runner.os != 'Linux'
|
||||
run: |
|
||||
cmake -S . -B ${{ env.BUILD_DIR }} -DCMAKE_INSTALL_PREFIX=${{ env.INSTALL_DIR }} -DCMAKE_BUILD_TYPE=${{ inputs.build_type }} -G Ninja
|
||||
##
|
||||
# CONFIGURE
|
||||
##
|
||||
|
||||
- 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'
|
||||
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
|
||||
if: runner.os != 'Windows'
|
||||
run: |
|
||||
cmake --build ${{ env.BUILD_DIR }}
|
||||
|
||||
- name: Install
|
||||
if: runner.os != 'Linux'
|
||||
- name: Build (Windows)
|
||||
if: runner.os == 'Windows'
|
||||
shell: msys2 {0}
|
||||
run: |
|
||||
cmake --build ${{ env.BUILD_DIR }}
|
||||
|
||||
##
|
||||
# PACKAGE BUILDS
|
||||
##
|
||||
|
||||
- name: Package (macOS)
|
||||
if: runner.os == 'macOS'
|
||||
run: |
|
||||
cmake --install ${{ env.BUILD_DIR }}
|
||||
|
||||
- name: Install on Linux
|
||||
if: runner.os == 'Linux'
|
||||
run: |
|
||||
DESTDIR=${{ env.INSTALL_DIR }} cmake --install ${{ env.BUILD_DIR }}
|
||||
cd ${{ env.INSTALL_DIR }}
|
||||
chmod +x "PolyMC.app/Contents/MacOS/polymc"
|
||||
sudo codesign --sign - --deep --force --entitlements "../program_info/App.entitlements" --options runtime "PolyMC.app/Contents/MacOS/polymc"
|
||||
tar -czf ../PolyMC.tar.gz *
|
||||
|
||||
- name: Bundle AppImage
|
||||
if: matrix.app_image == true
|
||||
- name: Package (Windows)
|
||||
if: runner.os == 'Windows'
|
||||
shell: msys2 {0}
|
||||
run: |
|
||||
cmake --install ${{ env.BUILD_DIR }}
|
||||
|
||||
cd ${{ env.INSTALL_DIR }}
|
||||
if [ "${{ matrix.msystem }}" == "mingw32" ]; then
|
||||
cp /mingw32/bin/libcrypto-1_1.dll /mingw32/bin/libssl-1_1.dll ./
|
||||
elif [ "${{ matrix.msystem }}" == "mingw64" ]; then
|
||||
cp /mingw64/bin/libcrypto-1_1-x64.dll /mingw64/bin/libssl-1_1-x64.dll ./
|
||||
fi
|
||||
|
||||
- name: Package (Windows, portable)
|
||||
if: runner.os == 'Windows'
|
||||
shell: msys2 {0}
|
||||
run: |
|
||||
cp -r ${{ env.INSTALL_DIR }} ${{ env.INSTALL_PORTABLE_DIR }} # cmake install on Windows is slow, let's just copy instead
|
||||
cmake --install ${{ env.BUILD_DIR }} --prefix ${{ env.INSTALL_PORTABLE_DIR }} --component portable
|
||||
|
||||
- name: Package (Linux)
|
||||
if: runner.os == 'Linux' && matrix.appimage != true
|
||||
run: |
|
||||
cmake --install ${{ env.BUILD_DIR }} --prefix ${{ env.INSTALL_DIR }}
|
||||
|
||||
cd ${{ env.INSTALL_DIR }}
|
||||
tar --owner root --group root -czf ../PolyMC.tar.gz *
|
||||
|
||||
- name: Package (Linux, portable)
|
||||
if: runner.os == 'Linux' && matrix.appimage != true
|
||||
run: |
|
||||
cmake --install ${{ env.BUILD_DIR }} --prefix ${{ env.INSTALL_PORTABLE_DIR }}
|
||||
cmake --install ${{ env.BUILD_DIR }} --prefix ${{ env.INSTALL_PORTABLE_DIR }} --component portable
|
||||
|
||||
cd ${{ env.INSTALL_PORTABLE_DIR }}
|
||||
tar -czf ../PolyMC-portable.tar.gz *
|
||||
|
||||
- name: Package AppImage (Linux)
|
||||
if: runner.os == 'Linux' && matrix.appimage == true
|
||||
shell: bash
|
||||
run: |
|
||||
cmake --install ${{ env.BUILD_DIR }} --prefix ${{ env.INSTALL_APPIMAGE_DIR }}/usr
|
||||
|
||||
export OUTPUT="PolyMC-${{ runner.os }}-${{ env.VERSION }}-${{ inputs.build_type }}-x86_64.AppImage"
|
||||
|
||||
chmod +x linuxdeploy-*.AppImage
|
||||
|
||||
mkdir -p ${{ env.INSTALL_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_DIR }}/usr/lib/jvm/java-8-openjdk/lib/amd64/server"
|
||||
LD_LIBRARY_PATH="${LD_LIBRARY_PATH}:${{ env.INSTALL_DIR }}/usr/lib/jvm/java-8-openjdk/lib/amd64"
|
||||
LD_LIBRARY_PATH="${LD_LIBRARY_PATH}:${{ env.INSTALL_DIR }}/usr/lib/jvm/java-17-openjdk/lib/server"
|
||||
LD_LIBRARY_PATH="${LD_LIBRARY_PATH}:${{ env.INSTALL_DIR }}/usr/lib/jvm/java-17-openjdk/lib"
|
||||
LD_LIBRARY_PATH="${LD_LIBRARY_PATH}:${{ env.INSTALL_APPIMAGE_DIR }}/usr/lib"
|
||||
LD_LIBRARY_PATH="${LD_LIBRARY_PATH}:${{ env.INSTALL_APPIMAGE_DIR }}/usr/lib/jvm/java-8-openjdk/lib/amd64/server"
|
||||
LD_LIBRARY_PATH="${LD_LIBRARY_PATH}:${{ env.INSTALL_APPIMAGE_DIR }}/usr/lib/jvm/java-8-openjdk/lib/amd64"
|
||||
LD_LIBRARY_PATH="${LD_LIBRARY_PATH}:${{ env.INSTALL_APPIMAGE_DIR }}/usr/lib/jvm/java-17-openjdk/lib/server"
|
||||
LD_LIBRARY_PATH="${LD_LIBRARY_PATH}:${{ env.INSTALL_APPIMAGE_DIR }}/usr/lib/jvm/java-17-openjdk/lib"
|
||||
export LD_LIBRARY_PATH
|
||||
|
||||
./linuxdeploy-x86_64.AppImage --appdir ${{ env.INSTALL_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'
|
||||
run: |
|
||||
windeployqt --no-translations --no-system-d3d-compiler --no-opengl-sw "${{ env.INSTALL_DIR }}/polymc.exe"
|
||||
##
|
||||
# UPLOAD BUILDS
|
||||
##
|
||||
|
||||
- name: Run macdeployqt
|
||||
- name: Upload binary tarball (macOS)
|
||||
if: runner.os == 'macOS'
|
||||
run: |
|
||||
cd ${{ env.INSTALL_DIR }}
|
||||
macdeployqt "PolyMC.app" -executable="PolyMC.app/Contents/MacOS/polymc" -always-overwrite
|
||||
|
||||
- name: chmod binary on macOS
|
||||
if: runner.os == 'macOS'
|
||||
run: |
|
||||
chmod +x "${{ github.workspace }}/${{ env.INSTALL_DIR }}/PolyMC.app/Contents/MacOS/polymc"
|
||||
|
||||
- name: tar bundle on macOS
|
||||
if: runner.os == 'macOS'
|
||||
run: |
|
||||
cd ${{ env.INSTALL_DIR }}
|
||||
tar -czf ../PolyMC.tar.gz *
|
||||
|
||||
- name: tar on Linux
|
||||
if: runner.os == 'Linux' && matrix.app_image != true
|
||||
run: |
|
||||
cd ${{ env.INSTALL_DIR }}
|
||||
tar -czf ../PolyMC.tar.gz *
|
||||
|
||||
- name: Upload Linux tar.gz
|
||||
if: runner.os == 'Linux' && matrix.app_image != true
|
||||
uses: actions/upload-artifact@v2
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: PolyMC-${{ runner.os }}-${{ env.VERSION }}-${{ inputs.build_type }}
|
||||
path: PolyMC.tar.gz
|
||||
|
||||
- name: Upload AppImage for Linux
|
||||
if: matrix.app_image == true
|
||||
uses: actions/upload-artifact@v2
|
||||
- name: Upload binary zip (Windows)
|
||||
if: runner.os == 'Windows'
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: PolyMC-${{ matrix.name }}-${{ env.VERSION }}-${{ inputs.build_type }}
|
||||
path: ${{ env.INSTALL_DIR }}/**
|
||||
|
||||
- name: Upload binary zip (Windows, portable)
|
||||
if: runner.os == 'Windows'
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: PolyMC-${{ matrix.name }}-Portable-${{ env.VERSION }}-${{ inputs.build_type }}
|
||||
path: ${{ env.INSTALL_PORTABLE_DIR }}/**
|
||||
|
||||
- name: Upload binary tarball (Linux)
|
||||
if: runner.os == 'Linux' && matrix.appimage != true
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: PolyMC-${{ runner.os }}-${{ env.VERSION }}-${{ inputs.build_type }}
|
||||
path: PolyMC.tar.gz
|
||||
|
||||
- name: Upload binary tarball (Linux, portable)
|
||||
if: runner.os == 'Linux' && matrix.appimage != true
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: PolyMC-${{ runner.os }}-Portable-${{ env.VERSION }}-${{ inputs.build_type }}
|
||||
path: PolyMC-portable.tar.gz
|
||||
|
||||
- name: Upload AppImage (Linux)
|
||||
if: runner.os == 'Linux' && matrix.appimage == true
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: PolyMC-${{ runner.os }}-${{ env.VERSION }}-${{ inputs.build_type }}-x86_64.AppImage
|
||||
path: PolyMC-${{ runner.os }}-${{ env.VERSION }}-${{ inputs.build_type }}-x86_64.AppImage
|
||||
|
||||
- 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'
|
||||
- 'flake.lock'
|
||||
- '**.nix'
|
||||
- 'packages/**'
|
||||
- '.github/ISSUE_TEMPLATE/**'
|
||||
pull_request:
|
||||
paths-ignore:
|
||||
- '**.md'
|
||||
- '**/LICENSE'
|
||||
- 'flake.lock'
|
||||
- '**.nix'
|
||||
- 'packages/**'
|
||||
- '.github/ISSUE_TEMPLATE/**'
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
@ -24,9 +28,3 @@ jobs:
|
||||
uses: ./.github/workflows/build.yml
|
||||
with:
|
||||
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:
|
||||
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
submodules: 'true'
|
||||
path: 'PolyMC-source'
|
||||
- name: Download artifacts
|
||||
uses: actions/download-artifact@v3
|
||||
- name: Grab and store version
|
||||
run: |
|
||||
tag_name=$(echo ${{ github.ref }} | grep -oE "[^/]+$")
|
||||
echo "VERSION=$tag_name" >> $GITHUB_ENV
|
||||
- name: Package artifacts properly
|
||||
run: |
|
||||
mv ${{ github.workspace }}/PolyMC-source PolyMC-${{ env.VERSION }}
|
||||
mv PolyMC-Linux-Portable*/PolyMC-portable.tar.gz PolyMC-Linux-Portable-${{ env.VERSION }}.tar.gz
|
||||
mv PolyMC-Linux*/PolyMC.tar.gz PolyMC-Linux-${{ env.VERSION }}.tar.gz
|
||||
mv PolyMC-*.AppImage/PolyMC-*.AppImage PolyMC-Linux-${{ env.VERSION }}-x86_64.AppImage
|
||||
mv PolyMC-macOS*/PolyMC.tar.gz PolyMC-macOS-${{ env.VERSION }}.tar.gz
|
||||
|
||||
tar -czf PolyMC-${{ env.VERSION }}.tar.gz PolyMC-${{ env.VERSION }}
|
||||
|
||||
for d in PolyMC-Windows-*; do
|
||||
cd "${d}" || continue
|
||||
ARCH="$(echo -n ${d} | cut -d '-' -f 3)"
|
||||
PORT="$(echo -n ${d} | grep -o Portable || true)"
|
||||
NAME="PolyMC-Windows-${ARCH}"
|
||||
test -z "${PORT}" || NAME="${NAME}-Portable"
|
||||
zip -r -9 "../${NAME}-${{ env.VERSION }}.zip" *
|
||||
cd ..
|
||||
done
|
||||
|
||||
- name: Create release
|
||||
id: create_release
|
||||
uses: softprops/action-gh-release@v1
|
||||
@ -33,67 +60,13 @@ jobs:
|
||||
name: PolyMC ${{ env.VERSION }}
|
||||
draft: true
|
||||
prerelease: false
|
||||
|
||||
upload_release:
|
||||
needs: create_release
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
|
||||
- name: Download artifacts
|
||||
uses: actions/download-artifact@v2
|
||||
|
||||
- name: Grab and store version
|
||||
run: |
|
||||
tag_name=$(echo ${{ github.ref }} | grep -oE "[^/]+$")
|
||||
echo "VERSION=$tag_name" >> $GITHUB_ENV
|
||||
|
||||
- name: Package artifacts properly
|
||||
run: |
|
||||
mv 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
|
||||
files: |
|
||||
PolyMC-Linux-${{ env.VERSION }}.tar.gz
|
||||
PolyMC-Linux-Portable-${{ env.VERSION }}.tar.gz
|
||||
PolyMC-Linux-${{ env.VERSION }}-x86_64.AppImage
|
||||
PolyMC-Windows-i686-${{ env.VERSION }}.zip
|
||||
PolyMC-Windows-i686-Portable-${{ env.VERSION }}.zip
|
||||
PolyMC-Windows-x86_64-${{ env.VERSION }}.zip
|
||||
PolyMC-Windows-x86_64-Portable-${{ env.VERSION }}.zip
|
||||
PolyMC-macOS-${{ env.VERSION }}.tar.gz
|
||||
PolyMC-${{ env.VERSION }}.tar.gz
|
||||
|
6
.gitignore
vendored
6
.gitignore
vendored
@ -14,6 +14,8 @@ CMakeLists.txt.user.*
|
||||
/.project
|
||||
/.settings
|
||||
/.idea
|
||||
/.vscode
|
||||
.clang-format
|
||||
cmake-build-*/
|
||||
Debug
|
||||
|
||||
@ -42,3 +44,7 @@ run/
|
||||
|
||||
# Nix/NixOS
|
||||
result/
|
||||
|
||||
# Flatpak
|
||||
.flatpak-builder
|
||||
flatbuild
|
||||
|
4
.gitmodules
vendored
4
.gitmodules
vendored
@ -1,7 +1,7 @@
|
||||
[submodule "depends/libnbtplusplus"]
|
||||
path = libraries/libnbtplusplus
|
||||
url = https://github.com/MultiMC/libnbtplusplus.git
|
||||
pushurl = git@github.com:MultiMC/libnbtplusplus.git
|
||||
url = https://github.com/PolyMC/libnbtplusplus.git
|
||||
pushurl = git@github.com:PolyMC/libnbtplusplus.git
|
||||
|
||||
[submodule "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)
|
||||
# In Qt 5.1+ we have our own main() function, don't autolink to qtmain on Windows
|
||||
@ -6,7 +6,7 @@ if(WIN32)
|
||||
endif()
|
||||
|
||||
project(Launcher)
|
||||
enable_testing()
|
||||
include(CTest)
|
||||
|
||||
string(COMPARE EQUAL "${CMAKE_SOURCE_DIR}" "${CMAKE_BUILD_DIR}" 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
|
||||
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 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_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(Launcher_VERSION_MAJOR 1)
|
||||
set(Launcher_VERSION_MINOR 1)
|
||||
set(Launcher_VERSION_HOTFIX 0)
|
||||
set(Launcher_VERSION_MINOR 2)
|
||||
set(Launcher_VERSION_HOTFIX 2)
|
||||
|
||||
# Build number
|
||||
set(Launcher_VERSION_BUILD -1 CACHE STRING "Build number. -1 for no build number.")
|
||||
|
||||
# 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
|
||||
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
|
||||
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
|
||||
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
|
||||
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.")
|
||||
|
||||
# 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
|
||||
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
|
||||
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
|
||||
# TODO: Launcher_FORCE_BUNDLED_LIBS should be off in the future, but as of QuaZip 1.2, we can't do that yet.
|
||||
set(Launcher_FORCE_BUNDLED_LIBS ON CACHE BOOL "Prevent using system libraries, if they are available as submodules")
|
||||
set(Launcher_FORCE_BUNDLED_LIBS OFF CACHE BOOL "Prevent using system libraries, if they are available as submodules")
|
||||
set(Launcher_QT_VERSION_MAJOR "5" CACHE STRING "Major Qt version to build against")
|
||||
|
||||
|
||||
@ -122,7 +138,7 @@ if(Launcher_QT_VERSION_MAJOR EQUAL 5)
|
||||
find_package(Qt5 REQUIRED COMPONENTS Core Widgets Concurrent Network Test Xml)
|
||||
|
||||
if(NOT Launcher_FORCE_BUNDLED_LIBS)
|
||||
find_package(QuaZip-Qt5 REQUIRED)
|
||||
find_package(QuaZip-Qt5 1.3)
|
||||
endif()
|
||||
if (NOT QuaZip-Qt5_FOUND)
|
||||
set(QUAZIP_QT_MAJOR_VERSION ${QT_VERSION_MAJOR} CACHE STRING "Qt version to use (4, 5 or 6), defaults to ${QT_VERSION_MAJOR}" FORCE)
|
||||
@ -152,9 +168,10 @@ add_subdirectory(program_info)
|
||||
|
||||
####################################### Install layout #######################################
|
||||
|
||||
# Install the build results according to platform
|
||||
set(Launcher_PORTABLE 1 CACHE BOOL "The type of installation (Portable or System)")
|
||||
|
||||
if(NOT (UNIX AND APPLE))
|
||||
# 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)
|
||||
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(JARS_DEST_DIR "${Launcher_Name}.app/Contents/MacOS/jars")
|
||||
|
||||
set(BUNDLE_DEST_DIR ".")
|
||||
|
||||
# Apps to bundle
|
||||
set(APPS "\${CMAKE_INSTALL_PREFIX}/${Launcher_Name}.app")
|
||||
|
||||
# Mac bundle settings
|
||||
set(MACOSX_BUNDLE_BUNDLE_NAME "${Launcher_Name}")
|
||||
set(MACOSX_BUNDLE_INFO_STRING "${Launcher_Name}: Minecraft launcher and management utility.")
|
||||
set(MACOSX_BUNDLE_INFO_STRING "${Launcher_Name}: A custom launcher for Minecraft that allows you to easily manage multiple installations of Minecraft at once.")
|
||||
set(MACOSX_BUNDLE_GUI_IDENTIFIER "org.polymc.${Launcher_Name}")
|
||||
set(MACOSX_BUNDLE_BUNDLE_VERSION "${Launcher_VERSION_MAJOR}.${Launcher_VERSION_MINOR}.${Launcher_VERSION_HOTFIX}.${Launcher_VERSION_BUILD}")
|
||||
set(MACOSX_BUNDLE_SHORT_VERSION_STRING "${Launcher_VERSION_MAJOR}.${Launcher_VERSION_MINOR}.${Launcher_VERSION_HOTFIX}.${Launcher_VERSION_BUILD}")
|
||||
set(MACOSX_BUNDLE_LONG_VERSION_STRING "${Launcher_VERSION_MAJOR}.${Launcher_VERSION_MINOR}.${Launcher_VERSION_HOTFIX}.${Launcher_VERSION_BUILD}")
|
||||
set(MACOSX_BUNDLE_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}")
|
||||
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_COPYRIGHT "Copyright 2015-2021 ${Launcher_Copyright}")
|
||||
set(MACOSX_BUNDLE_COPYRIGHT "Copyright 2021-2022 ${Launcher_Copyright}")
|
||||
|
||||
# directories to look for dependencies
|
||||
set(DIRS ${QT_LIBS_DIR} ${QT_LIBEXECS_DIR} ${CMAKE_LIBRARY_OUTPUT_DIRECTORY} ${CMAKE_RUNTIME_OUTPUT_DIRECTORY})
|
||||
@ -189,30 +204,12 @@ if(UNIX AND APPLE)
|
||||
|
||||
elseif(UNIX)
|
||||
set(BINARY_DEST_DIR "bin")
|
||||
if(Launcher_PORTABLE)
|
||||
set(LIBRARY_DEST_DIR "bin")
|
||||
set(BUNDLE_DEST_DIR ".")
|
||||
set(JARS_DEST_DIR "bin/jars")
|
||||
|
||||
# launcher/Application.cpp will use this value
|
||||
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()
|
||||
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_MAN_DEST_DIR "share/man/man6" CACHE STRING "Path to the man page directory")
|
||||
|
||||
# install as bundle with no dependencies included
|
||||
set(INSTALL_BUNDLE "nodeps")
|
||||
@ -220,11 +217,22 @@ elseif(UNIX)
|
||||
# Set RPATH
|
||||
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)
|
||||
set(BINARY_DEST_DIR ".")
|
||||
set(LIBRARY_DEST_DIR ".")
|
||||
set(PLUGIN_DEST_DIR ".")
|
||||
set(BUNDLE_DEST_DIR ".")
|
||||
set(RESOURCES_DEST_DIR ".")
|
||||
set(JARS_DEST_DIR "jars")
|
||||
|
||||
@ -260,6 +268,8 @@ if (FORCE_BUNDLED_QUAZIP)
|
||||
set(BUILD_SHARED_LIBS 0) # link statically to avoid conflicts.
|
||||
set(QUAZIP_INSTALL 0)
|
||||
add_subdirectory(libraries/quazip) # zip manipulation library
|
||||
else()
|
||||
message(STATUS "Using system QuaZip")
|
||||
endif()
|
||||
add_subdirectory(libraries/rainbow) # Qt extension for colors
|
||||
add_subdirectory(libraries/iconfix) # fork of Qt's QIcon loader
|
||||
|
@ -5,8 +5,7 @@
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
the Free Software Foundation, version 3.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
|
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:
|
||||
|
||||
[](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:
|
||||
|
||||
[](https://matrix.to/#/#support:polymc.org)
|
||||
[](https://matrix.to/#/#discussion:polymc.org)
|
||||
[](https://matrix.to/#/#development:polymc.org)
|
||||
[](https://matrix.to/#/#news:polymc.org)
|
||||
[](https://matrix.to/#/#polymc-development:matrix.org)
|
||||
[](https://matrix.to/#/#polymc-discussion:matrix.org)
|
||||
[](https://matrix.to/#/#polymc-github:matrix.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
|
||||
|
||||
@ -48,7 +56,7 @@ If you want to contribute to PolyMC you might find it useful to join our Discord
|
||||
|
||||
## 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
|
||||
|
||||
@ -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
|
||||
|
||||
## Download infomation
|
||||
To modify download infomation or change packaging infomation send a pull request or issue to the website [Here](https://github.com/PolyMC/polymc.github.io/blob/master/src/download.md)
|
||||
## Download information
|
||||
To modify download information or change packaging information send a pull request or issue to the website [Here](https://github.com/PolyMC/polymc.github.io/blob/master/src/download.md)
|
||||
|
||||
## Forking/Redistributing/Custom builds policy
|
||||
|
||||
Do whatever you want, we don't care. Just follow the license. If you have any questions about this feel free to ask in an issue.
|
||||
|
||||
All launcher code is available under the GPL-3 license.
|
||||
|
||||
[Source for the website](https://github.com/PolyMC/polymc.github.io) is hosted under the AGPL-3 License.
|
||||
|
||||
The logo and related assets are under the CC BY-SA 4.0 license.
|
||||
|
@ -1,3 +1,38 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
/*
|
||||
* PolyMC - Minecraft Launcher
|
||||
* Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, version 3.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* This file incorporates work covered by the following copyright and
|
||||
* permission notice:
|
||||
*
|
||||
* Copyright 2013-2021 MultiMC Contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "BuildConfig.h"
|
||||
#include <QObject>
|
||||
|
||||
@ -25,12 +60,14 @@ Config::Config()
|
||||
|
||||
BUILD_PLATFORM = "@Launcher_BUILD_PLATFORM@";
|
||||
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_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.remove("refs/heads/");
|
||||
@ -53,6 +90,7 @@ Config::Config()
|
||||
HELP_URL = "@Launcher_HELP_URL@";
|
||||
IMGUR_CLIENT_ID = "@Launcher_IMGUR_CLIENT_ID@";
|
||||
MSA_CLIENT_ID = "@Launcher_MSA_CLIENT_ID@";
|
||||
CURSEFORGE_API_KEY = "@Launcher_CURSEFORGE_API_KEY@";
|
||||
META_URL = "@Launcher_META_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
|
||||
#include <QString>
|
||||
|
||||
/**
|
||||
* \brief The Config class holds all the build-time information passed from the build system.
|
||||
*/
|
||||
class Config
|
||||
{
|
||||
public:
|
||||
class Config {
|
||||
public:
|
||||
Config();
|
||||
QString LAUNCHER_NAME;
|
||||
QString LAUNCHER_DISPLAYNAME;
|
||||
@ -39,20 +73,12 @@ public:
|
||||
/// URL for the updater's channel
|
||||
QString UPDATER_BASE;
|
||||
|
||||
|
||||
/// User-Agent to use.
|
||||
QString USER_AGENT;
|
||||
|
||||
/// User-Agent to use for uncached requests.
|
||||
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
|
||||
QString GIT_COMMIT;
|
||||
|
||||
@ -88,6 +114,11 @@ public:
|
||||
*/
|
||||
QString MSA_CLIENT_ID;
|
||||
|
||||
/**
|
||||
* Client API key for CurseForge
|
||||
*/
|
||||
QString CURSEFORGE_API_KEY;
|
||||
|
||||
/**
|
||||
* Metadata repository URL prefix
|
||||
*/
|
||||
@ -112,6 +143,12 @@ public:
|
||||
|
||||
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.
|
||||
* \return The version number in string format (major.minor.revision.build).
|
||||
@ -120,4 +157,3 @@ public:
|
||||
};
|
||||
|
||||
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">
|
||||
<plist version="1.0">
|
||||
<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>
|
||||
<string>NSApplication</string>
|
||||
<key>NSHighResolutionCapable</key>
|
||||
|
@ -5,44 +5,46 @@ set(TEST_RESOURCE_PATH ${CMAKE_CURRENT_LIST_DIR})
|
||||
message(${TEST_RESOURCE_PATH})
|
||||
|
||||
function(add_unit_test name)
|
||||
set(options "")
|
||||
set(oneValueArgs DATA)
|
||||
set(multiValueArgs SOURCES LIBS)
|
||||
if(BUILD_TESTING)
|
||||
set(options "")
|
||||
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)
|
||||
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}")
|
||||
if(WIN32)
|
||||
add_executable(${name}_test ${OPT_SOURCES} ${TEST_RESOURCE_PATH}/UnitTest/test.rc)
|
||||
else()
|
||||
# we don't on windows, so we have to add it ourselves
|
||||
set(TEST_DATA_URL "file:///${TEST_DATA_PATH}")
|
||||
add_executable(${name}_test ${OPT_SOURCES})
|
||||
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}
|
||||
)
|
||||
|
||||
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()
|
||||
# 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()
|
||||
|
||||
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()
|
||||
|
||||
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()
|
||||
|
30
flake.lock
generated
30
flake.lock
generated
@ -3,11 +3,11 @@
|
||||
"flake-compat": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"lastModified": 1641205782,
|
||||
"narHash": "sha256-4jY7RCWUoZ9cKD8co0/4tFARpWB+57+r1bLLvXNJliY=",
|
||||
"lastModified": 1648199409,
|
||||
"narHash": "sha256-JwPKdC2PoVBkG6E+eWw3j6BMR6sL3COpYWfif7RVb8Y=",
|
||||
"owner": "edolstra",
|
||||
"repo": "flake-compat",
|
||||
"rev": "b7547d3eed6f32d06102ead8991ec52ab0a4f1a7",
|
||||
"rev": "64a525ee38886ab9028e6f61790de0832aa3ef03",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@ -16,21 +16,6 @@
|
||||
"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": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
@ -49,16 +34,16 @@
|
||||
},
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1643169865,
|
||||
"narHash": "sha256-+KIpNRazbc8Gac9jdWCKQkFv9bjceaLaLhlwqUEYu8c=",
|
||||
"lastModified": 1648219316,
|
||||
"narHash": "sha256-Ctij+dOi0ZZIfX5eMhgwugfvB+WZSrvVNAyAuANOsnQ=",
|
||||
"owner": "nixos",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "945ec499041db73043f745fad3b2a3a01e826081",
|
||||
"rev": "30d3d79b7d3607d56546dd2a6b49e156ba0ec634",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nixos",
|
||||
"ref": "nixos-unstable",
|
||||
"ref": "nixpkgs-unstable",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
@ -82,7 +67,6 @@
|
||||
"root": {
|
||||
"inputs": {
|
||||
"flake-compat": "flake-compat",
|
||||
"flake-utils": "flake-utils",
|
||||
"libnbtplusplus": "libnbtplusplus",
|
||||
"nixpkgs": "nixpkgs",
|
||||
"quazip": "quazip"
|
||||
|
74
flake.nix
74
flake.nix
@ -1,50 +1,34 @@
|
||||
{
|
||||
description = "PolyMC flake";
|
||||
inputs.nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
|
||||
inputs.flake-utils.url = "github:numtide/flake-utils";
|
||||
inputs.flake-compat = {
|
||||
url = "github:edolstra/flake-compat";
|
||||
flake = false;
|
||||
};
|
||||
inputs.libnbtplusplus = {
|
||||
url = "github:multimc/libnbtplusplus";
|
||||
flake = false;
|
||||
};
|
||||
inputs.quazip = {
|
||||
url = "github:stachenov/quazip";
|
||||
flake = false;
|
||||
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/nixpkgs-unstable";
|
||||
flake-compat = { url = "github:edolstra/flake-compat"; flake = false; };
|
||||
libnbtplusplus = { url = "github:multimc/libnbtplusplus"; flake = false; };
|
||||
quazip = { url = "github:stachenov/quazip"; flake = false; };
|
||||
};
|
||||
|
||||
outputs = args@{ self, nixpkgs, flake-utils, libnbtplusplus, quazip, ... }:
|
||||
outputs = { self, nixpkgs, libnbtplusplus, quazip, ... }:
|
||||
let
|
||||
systems = [
|
||||
"aarch64-linux"
|
||||
# "aarch64-darwin" # qtbase is currently broken
|
||||
"i686-linux"
|
||||
"x86_64-darwin"
|
||||
"x86_64-linux"
|
||||
];
|
||||
in {
|
||||
overlay = final: prev: {
|
||||
inherit (self.packages.${final.system}) polymc;
|
||||
};
|
||||
} // flake-utils.lib.eachSystem systems (system:
|
||||
let pkgs = import nixpkgs { inherit system; };
|
||||
in {
|
||||
packages = {
|
||||
polymc = pkgs.libsForQt5.callPackage ./packages/nix/polymc {
|
||||
inherit self;
|
||||
submoduleQuazip = quazip;
|
||||
submoduleNbt = libnbtplusplus;
|
||||
};
|
||||
};
|
||||
apps = {
|
||||
polymc = flake-utils.lib.mkApp {
|
||||
name = "polymc";
|
||||
drv = self.packages.${system}.polymc;
|
||||
};
|
||||
};
|
||||
defaultPackage = self.packages.${system}.polymc;
|
||||
defaultApp = self.apps.${system}.polymc;
|
||||
});
|
||||
# Generate a user-friendly version number.
|
||||
version = builtins.substring 0 8 self.lastModifiedDate;
|
||||
|
||||
# System types to support (qtbase is currently broken for "aarch64-darwin")
|
||||
supportedSystems = [ "x86_64-linux" "x86_64-darwin" "aarch64-linux" ];
|
||||
|
||||
# Helper function to generate an attrset '{ x86_64-linux = f "x86_64-linux"; ... }'.
|
||||
forAllSystems = nixpkgs.lib.genAttrs supportedSystems;
|
||||
|
||||
# Nixpkgs instantiated for supported system types.
|
||||
pkgs = forAllSystems (system: nixpkgs.legacyPackages.${system});
|
||||
in
|
||||
{
|
||||
packages = forAllSystems (system: { polymc = pkgs.${system}.libsForQt5.callPackage ./packages/nix/polymc { inherit version self quazip libnbtplusplus; }; });
|
||||
defaultPackage = forAllSystems (system: self.packages.${system}.polymc);
|
||||
|
||||
apps = forAllSystems (system: { polymc = { type = "app"; program = "${self.defaultPackage.${system}}/bin/polymc"; }; });
|
||||
defaultApp = forAllSystems (system: self.apps.${system}.polymc);
|
||||
|
||||
overlay = final: prev: { polymc = self.defaultPackage.${final.system}; };
|
||||
};
|
||||
}
|
||||
|
@ -1,3 +1,38 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
/*
|
||||
* PolyMC - Minecraft Launcher
|
||||
* Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, version 3.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* This file incorporates work covered by the following copyright and
|
||||
* permission notice:
|
||||
*
|
||||
* Copyright 2013-2021 MultiMC Contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "Application.h"
|
||||
#include "BuildConfig.h"
|
||||
|
||||
@ -45,6 +80,7 @@
|
||||
#include <QStringList>
|
||||
#include <QDebug>
|
||||
#include <QStyleFactory>
|
||||
#include <QWindow>
|
||||
|
||||
#include "InstanceList.h"
|
||||
|
||||
@ -281,6 +317,26 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv)
|
||||
|
||||
QString origcwdPath = QDir::currentPath();
|
||||
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 dataPath;
|
||||
// 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
|
||||
// on command line
|
||||
adjustedBy += "Command line " + dirParam;
|
||||
adjustedBy = "Command line";
|
||||
dataPath = dirParam;
|
||||
}
|
||||
else
|
||||
{
|
||||
#if !defined(LAUNCHER_PORTABLE) || defined(Q_OS_MAC)
|
||||
QDir foo(FS::PathCombine(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation), ".."));
|
||||
dataPath = foo.absolutePath();
|
||||
adjustedBy += dataPath;
|
||||
adjustedBy = "Persistent data path";
|
||||
|
||||
#ifdef Q_OS_LINUX
|
||||
// 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"));
|
||||
if (bar.exists()) {
|
||||
dataPath = bar.absolutePath();
|
||||
adjustedBy += "Legacy data path " + dataPath;
|
||||
adjustedBy = "Legacy data path";
|
||||
}
|
||||
#endif
|
||||
#else
|
||||
dataPath = applicationDirPath();
|
||||
adjustedBy += "Fallback to binary path " + dataPath;
|
||||
|
||||
#ifndef Q_OS_MACOS
|
||||
if (QFile::exists(FS::PathCombine(m_rootPath, "portable.txt"))) {
|
||||
dataPath = m_rootPath;
|
||||
adjustedBy = "Portable data path";
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -500,24 +558,7 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv)
|
||||
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() << "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("ApplicationTheme", QString("system"));
|
||||
|
||||
// Notifications
|
||||
m_settings->registerSetting("ShownNotifications", QString());
|
||||
|
||||
// Remembered state
|
||||
m_settings->registerSetting("LastUsedGroupForNewInstance", QString());
|
||||
|
||||
m_settings->registerSetting("MenuBarInsteadOfToolBar", false);
|
||||
|
||||
QString defaultMonospace;
|
||||
int defaultSize = 11;
|
||||
#ifdef Q_OS_WIN32
|
||||
@ -650,6 +690,7 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv)
|
||||
m_settings->registerSetting("JavaVendor", "");
|
||||
m_settings->registerSetting("LastHostname", "");
|
||||
m_settings->registerSetting("JvmArgs", "");
|
||||
m_settings->registerSetting("IgnoreJavaCompatibility", false);
|
||||
|
||||
// Native library workarounds
|
||||
m_settings->registerSetting("UseNativeOpenAL", false);
|
||||
@ -663,6 +704,9 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv)
|
||||
// Minecraft launch method
|
||||
m_settings->registerSetting("MCLaunchMethod", "LauncherPart");
|
||||
|
||||
// Minecraft offline player name
|
||||
m_settings->registerSetting("LastOfflinePlayerName", "");
|
||||
|
||||
// Wrapper command for launch
|
||||
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("CloseAfterLaunch", false);
|
||||
m_settings->registerSetting("QuitAfterGameStop", false);
|
||||
|
||||
// Custom MSA credentials
|
||||
m_settings->registerSetting("MSAClientIDOverride", "");
|
||||
@ -1107,6 +1152,15 @@ std::vector<ITheme *> Application::getValidApplicationThemes()
|
||||
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)
|
||||
{
|
||||
auto systemPalette = qApp->palette();
|
||||
@ -1222,6 +1276,12 @@ bool Application::kill(InstancePtr instance)
|
||||
return true;
|
||||
}
|
||||
|
||||
void Application::closeCurrentWindow()
|
||||
{
|
||||
if (focusWindow())
|
||||
focusWindow()->close();
|
||||
}
|
||||
|
||||
void Application::addRunningInstance()
|
||||
{
|
||||
m_runningInstances ++;
|
||||
@ -1494,10 +1554,10 @@ QString Application::getJarsPath()
|
||||
{
|
||||
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();
|
||||
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
|
||||
|
||||
#include <QApplication>
|
||||
@ -69,6 +104,8 @@ public:
|
||||
|
||||
QIcon getThemedIcon(const QString& name);
|
||||
|
||||
bool isFlatpak();
|
||||
|
||||
void setIconTheme(const QString& name);
|
||||
|
||||
std::vector<ITheme *> getValidApplicationThemes();
|
||||
@ -152,6 +189,7 @@ public slots:
|
||||
MinecraftAccountPtr accountToUse = nullptr
|
||||
);
|
||||
bool kill(InstancePtr instance);
|
||||
void closeCurrentWindow();
|
||||
|
||||
private slots:
|
||||
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");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* 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.
|
||||
*
|
||||
* 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
|
||||
* 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.
|
||||
* 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 "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");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* 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.
|
||||
*
|
||||
* 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
|
||||
* 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.
|
||||
* 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
|
||||
|
@ -144,6 +144,8 @@ set(LAUNCH_SOURCES
|
||||
launch/steps/TextPrint.h
|
||||
launch/steps/Update.cpp
|
||||
launch/steps/Update.h
|
||||
launch/steps/QuitAfterGameStop.cpp
|
||||
launch/steps/QuitAfterGameStop.h
|
||||
launch/LaunchStep.cpp
|
||||
launch/LaunchStep.h
|
||||
launch/LaunchTask.cpp
|
||||
@ -174,13 +176,6 @@ add_unit_test(DownloadTask
|
||||
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.
|
||||
set(NEWS_SOURCES
|
||||
# News System
|
||||
@ -240,6 +235,8 @@ set(MINECRAFT_SOURCES
|
||||
minecraft/auth/steps/MigrationEligibilityStep.h
|
||||
minecraft/auth/steps/MinecraftProfileStep.cpp
|
||||
minecraft/auth/steps/MinecraftProfileStep.h
|
||||
minecraft/auth/steps/MinecraftProfileStepMojang.cpp
|
||||
minecraft/auth/steps/MinecraftProfileStepMojang.h
|
||||
minecraft/auth/steps/MSAStep.cpp
|
||||
minecraft/auth/steps/MSAStep.h
|
||||
minecraft/auth/steps/XboxAuthorizationStep.cpp
|
||||
@ -353,28 +350,30 @@ set(MINECRAFT_SOURCES
|
||||
|
||||
mojang/PackageManifest.h
|
||||
mojang/PackageManifest.cpp
|
||||
)
|
||||
minecraft/Agent.h)
|
||||
|
||||
add_unit_test(GradleSpecifier
|
||||
SOURCES minecraft/GradleSpecifier_test.cpp
|
||||
LIBS Launcher_logic
|
||||
)
|
||||
|
||||
add_executable(PackageManifest
|
||||
mojang/PackageManifest_test.cpp
|
||||
)
|
||||
target_link_libraries(PackageManifest
|
||||
Launcher_logic
|
||||
Qt5::Test
|
||||
)
|
||||
target_include_directories(PackageManifest
|
||||
PRIVATE ../cmake/UnitTest/
|
||||
)
|
||||
add_test(
|
||||
NAME PackageManifest
|
||||
COMMAND PackageManifest
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
)
|
||||
if(BUILD_TESTING)
|
||||
add_executable(PackageManifest
|
||||
mojang/PackageManifest_test.cpp
|
||||
)
|
||||
target_link_libraries(PackageManifest
|
||||
Launcher_logic
|
||||
Qt5::Test
|
||||
)
|
||||
target_include_directories(PackageManifest
|
||||
PRIVATE ../cmake/UnitTest/
|
||||
)
|
||||
add_test(
|
||||
NAME PackageManifest
|
||||
COMMAND PackageManifest
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
)
|
||||
endif()
|
||||
|
||||
add_unit_test(MojangVersionFormat
|
||||
SOURCES minecraft/MojangVersionFormat_test.cpp
|
||||
@ -416,6 +415,11 @@ set(TASKS_SOURCES
|
||||
tasks/SequentialTask.cpp
|
||||
)
|
||||
|
||||
add_unit_test(Task
|
||||
SOURCES tasks/Task_test.cpp
|
||||
LIBS Launcher_logic
|
||||
)
|
||||
|
||||
set(SETTINGS_SOURCES
|
||||
# Settings
|
||||
settings/INIFile.cpp
|
||||
@ -492,6 +496,16 @@ set(META_SOURCES
|
||||
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
|
||||
modplatform/legacy_ftb/PackFetchTask.h
|
||||
modplatform/legacy_ftb/PackFetchTask.cpp
|
||||
@ -532,6 +546,8 @@ set(TECHNIC_SOURCES
|
||||
modplatform/technic/SingleZipPackInstallTask.cpp
|
||||
modplatform/technic/SolderPackInstallTask.h
|
||||
modplatform/technic/SolderPackInstallTask.cpp
|
||||
modplatform/technic/SolderPackManifest.h
|
||||
modplatform/technic/SolderPackManifest.cpp
|
||||
modplatform/technic/TechnicPackProcessor.h
|
||||
modplatform/technic/TechnicPackProcessor.cpp
|
||||
)
|
||||
@ -561,7 +577,6 @@ set(LOGIC_SOURCES
|
||||
${NET_SOURCES}
|
||||
${LAUNCH_SOURCES}
|
||||
${UPDATE_SOURCES}
|
||||
${NOTIFICATIONS_SOURCES}
|
||||
${NEWS_SOURCES}
|
||||
${MINECRAFT_SOURCES}
|
||||
${SCREENSHOTS_SOURCES}
|
||||
@ -572,6 +587,7 @@ set(LOGIC_SOURCES
|
||||
${TOOLS_SOURCES}
|
||||
${META_SOURCES}
|
||||
${ICONS_SOURCES}
|
||||
${API_SOURCES}
|
||||
${FTB_SOURCES}
|
||||
${FLAME_SOURCES}
|
||||
${MODRINTH_SOURCES}
|
||||
@ -721,6 +737,11 @@ SET(LAUNCHER_SOURCES
|
||||
ui/pages/modplatform/VanillaPage.cpp
|
||||
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.h
|
||||
ui/pages/modplatform/atlauncher/AtlListModel.cpp
|
||||
@ -791,12 +812,12 @@ SET(LAUNCHER_SOURCES
|
||||
ui/dialogs/NewComponentDialog.h
|
||||
ui/dialogs/NewInstanceDialog.cpp
|
||||
ui/dialogs/NewInstanceDialog.h
|
||||
ui/dialogs/NotificationDialog.cpp
|
||||
ui/dialogs/NotificationDialog.h
|
||||
ui/pagedialog/PageDialog.cpp
|
||||
ui/pagedialog/PageDialog.h
|
||||
ui/dialogs/ProgressDialog.cpp
|
||||
ui/dialogs/ProgressDialog.h
|
||||
ui/dialogs/ReviewMessageBox.cpp
|
||||
ui/dialogs/ReviewMessageBox.h
|
||||
ui/dialogs/UpdateDialog.cpp
|
||||
ui/dialogs/UpdateDialog.h
|
||||
ui/dialogs/VersionSelectDialog.cpp
|
||||
@ -806,7 +827,6 @@ SET(LAUNCHER_SOURCES
|
||||
ui/dialogs/ModDownloadDialog.cpp
|
||||
ui/dialogs/ModDownloadDialog.h
|
||||
|
||||
|
||||
# GUI - widgets
|
||||
ui/widgets/Common.cpp
|
||||
ui/widgets/Common.h
|
||||
@ -830,6 +850,8 @@ SET(LAUNCHER_SOURCES
|
||||
ui/widgets/LogView.h
|
||||
ui/widgets/MCModInfoFrame.cpp
|
||||
ui/widgets/MCModInfoFrame.h
|
||||
ui/widgets/ModFilterWidget.cpp
|
||||
ui/widgets/ModFilterWidget.h
|
||||
ui/widgets/ModListView.cpp
|
||||
ui/widgets/ModListView.h
|
||||
ui/widgets/PageContainer.cpp
|
||||
@ -879,21 +901,20 @@ qt5_wrap_ui(LAUNCHER_UI
|
||||
ui/pages/modplatform/atlauncher/AtlOptionalModDialog.ui
|
||||
ui/pages/modplatform/atlauncher/AtlPage.ui
|
||||
ui/pages/modplatform/VanillaPage.ui
|
||||
ui/pages/modplatform/ModPage.ui
|
||||
ui/pages/modplatform/flame/FlamePage.ui
|
||||
ui/pages/modplatform/flame/FlameModPage.ui
|
||||
ui/pages/modplatform/legacy_ftb/Page.ui
|
||||
ui/pages/modplatform/ImportPage.ui
|
||||
ui/pages/modplatform/ftb/FtbPage.ui
|
||||
ui/pages/modplatform/technic/TechnicPage.ui
|
||||
ui/pages/modplatform/modrinth/ModrinthPage.ui
|
||||
ui/widgets/InstanceCardWidget.ui
|
||||
ui/widgets/CustomCommands.ui
|
||||
ui/widgets/MCModInfoFrame.ui
|
||||
ui/widgets/ModFilterWidget.ui
|
||||
ui/dialogs/CopyInstanceDialog.ui
|
||||
ui/dialogs/ProfileSetupDialog.ui
|
||||
ui/dialogs/ProgressDialog.ui
|
||||
ui/dialogs/NewInstanceDialog.ui
|
||||
ui/dialogs/NotificationDialog.ui
|
||||
ui/dialogs/UpdateDialog.ui
|
||||
ui/dialogs/NewComponentDialog.ui
|
||||
ui/dialogs/ProfileSelectDialog.ui
|
||||
@ -905,6 +926,7 @@ qt5_wrap_ui(LAUNCHER_UI
|
||||
ui/dialogs/AboutDialog.ui
|
||||
ui/dialogs/LoginDialog.ui
|
||||
ui/dialogs/EditAccountDialog.ui
|
||||
ui/dialogs/ReviewMessageBox.ui
|
||||
)
|
||||
|
||||
qt5_add_resources(LAUNCHER_RESOURCES
|
||||
@ -949,8 +971,8 @@ target_link_libraries(Launcher_logic
|
||||
Launcher_iconfix
|
||||
QuaZip::QuaZip
|
||||
hoedown
|
||||
PolyMC_rainbow
|
||||
LocalPeer
|
||||
Launcher_rainbow
|
||||
)
|
||||
|
||||
target_link_libraries(Launcher_logic)
|
||||
@ -971,7 +993,7 @@ if(DEFINED Launcher_APP_BINARY_DEFS)
|
||||
endif()
|
||||
|
||||
install(TARGETS ${Launcher_Name}
|
||||
BUNDLE DESTINATION ${BUNDLE_DEST_DIR} COMPONENT Runtime
|
||||
BUNDLE DESTINATION "." COMPONENT Runtime
|
||||
LIBRARY DESTINATION ${LIBRARY_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"
|
||||
DESTINATION ${PLUGIN_DEST_DIR}
|
||||
COMPONENT Runtime
|
||||
REGEX "tga|tiff|mng|webp" EXCLUDE
|
||||
REGEX "tga|tiff|mng" EXCLUDE
|
||||
)
|
||||
# Icon engines
|
||||
install(
|
||||
@ -1022,7 +1044,7 @@ if(INSTALL_BUNDLE STREQUAL "full")
|
||||
DIRECTORY "${QT_PLUGINS_DIR}/imageformats"
|
||||
DESTINATION ${PLUGIN_DEST_DIR}
|
||||
COMPONENT Runtime
|
||||
REGEX "tga|tiff|mng|webp" EXCLUDE
|
||||
REGEX "tga|tiff|mng" EXCLUDE
|
||||
REGEX "d\\." EXCLUDE
|
||||
REGEX "_debug\\." EXCLUDE
|
||||
REGEX "\\.dSYM" EXCLUDE
|
||||
|
@ -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 <QDir>
|
||||
#include <QDesktopServices>
|
||||
#include <QProcess>
|
||||
#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.
|
||||
@ -84,7 +119,14 @@ bool openDirectory(const QString &path, bool ensureExists)
|
||||
return QDesktopServices::openUrl(QUrl::fromLocalFile(dir.absolutePath()));
|
||||
};
|
||||
#if defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD)
|
||||
return IndirectOpen(f);
|
||||
if(!APPLICATION->isFlatpak())
|
||||
{
|
||||
return IndirectOpen(f);
|
||||
}
|
||||
else
|
||||
{
|
||||
return f();
|
||||
}
|
||||
#else
|
||||
return f();
|
||||
#endif
|
||||
@ -98,7 +140,14 @@ bool openFile(const QString &path)
|
||||
return QDesktopServices::openUrl(QUrl::fromLocalFile(path));
|
||||
};
|
||||
#if defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD)
|
||||
return IndirectOpen(f);
|
||||
if(!APPLICATION->isFlatpak())
|
||||
{
|
||||
return IndirectOpen(f);
|
||||
}
|
||||
else
|
||||
{
|
||||
return f();
|
||||
}
|
||||
#else
|
||||
return f();
|
||||
#endif
|
||||
@ -109,10 +158,17 @@ bool openFile(const QString &application, const QString &path, const QString &wo
|
||||
qDebug() << "Opening file" << path << "using" << application;
|
||||
#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
|
||||
return IndirectOpen([&]()
|
||||
if(!APPLICATION->isFlatpak())
|
||||
{
|
||||
return QProcess::startDetached(application, QStringList() << path, workingDirectory);
|
||||
}, pid);
|
||||
return IndirectOpen([&]()
|
||||
{
|
||||
return QProcess::startDetached(application, QStringList() << path, workingDirectory);
|
||||
}, pid);
|
||||
}
|
||||
else
|
||||
{
|
||||
return QProcess::startDetached(application, QStringList() << path, workingDirectory, pid);
|
||||
}
|
||||
#else
|
||||
return QProcess::startDetached(application, QStringList() << path, workingDirectory, pid);
|
||||
#endif
|
||||
@ -122,11 +178,18 @@ bool run(const QString &application, const QStringList &args, const QString &wor
|
||||
{
|
||||
qDebug() << "Running" << application << "with args" << args.join(' ');
|
||||
#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
|
||||
return IndirectOpen([&]()
|
||||
{
|
||||
return QProcess::startDetached(application, args, workingDirectory);
|
||||
}, pid);
|
||||
}
|
||||
else
|
||||
{
|
||||
return QProcess::startDetached(application, args, workingDirectory, pid);
|
||||
}
|
||||
#else
|
||||
return QProcess::startDetached(application, args, workingDirectory, pid);
|
||||
#endif
|
||||
@ -140,7 +203,14 @@ bool openUrl(const QUrl &url)
|
||||
return QDesktopServices::openUrl(url);
|
||||
};
|
||||
#if defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD)
|
||||
return IndirectOpen(f);
|
||||
if(!APPLICATION->isFlatpak())
|
||||
{
|
||||
return IndirectOpen(f);
|
||||
}
|
||||
else
|
||||
{
|
||||
return f();
|
||||
}
|
||||
#else
|
||||
return f();
|
||||
#endif
|
||||
|
@ -9,6 +9,15 @@
|
||||
InstanceCreationTask::InstanceCreationTask(BaseVersionPtr 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()
|
||||
@ -21,6 +30,8 @@ void InstanceCreationTask::executeTask()
|
||||
auto components = inst.getPackProfile();
|
||||
components->buildingFromScratch();
|
||||
components->setComponentVersion("net.minecraft", m_version->descriptor(), true);
|
||||
if(m_usingLoader)
|
||||
components->setComponentVersion(m_loader, m_loaderVersion->descriptor());
|
||||
inst.setName(m_instName);
|
||||
inst.setIconKey(m_instIcon);
|
||||
instanceSettings->resumeSave();
|
||||
|
@ -12,6 +12,7 @@ class InstanceCreationTask : public InstanceTask
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit InstanceCreationTask(BaseVersionPtr version);
|
||||
explicit InstanceCreationTask(BaseVersionPtr version, QString loader, BaseVersionPtr loaderVersion);
|
||||
|
||||
protected:
|
||||
//! Entry point for tasks.
|
||||
@ -19,4 +20,7 @@ protected:
|
||||
|
||||
private: /* data */
|
||||
BaseVersionPtr m_version;
|
||||
bool m_usingLoader;
|
||||
QString m_loader;
|
||||
BaseVersionPtr m_loaderVersion;
|
||||
};
|
||||
|
@ -40,6 +40,14 @@ InstanceImportTask::InstanceImportTask(const QUrl sourceUrl)
|
||||
m_sourceUrl = sourceUrl;
|
||||
}
|
||||
|
||||
bool InstanceImportTask::abort()
|
||||
{
|
||||
m_filesNetJob->abort();
|
||||
m_extractFuture.cancel();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void InstanceImportTask::executeTask()
|
||||
{
|
||||
if (m_sourceUrl.isLocalFile())
|
||||
@ -241,6 +249,7 @@ void InstanceImportTask::processFlame()
|
||||
|
||||
QString forgeVersion;
|
||||
QString fabricVersion;
|
||||
// TODO: is Quilt relevant here?
|
||||
for(auto &loader: pack.minecraft.modLoaders)
|
||||
{
|
||||
auto id = loader.id;
|
||||
@ -283,7 +292,7 @@ void InstanceImportTask::processFlame()
|
||||
}
|
||||
else
|
||||
{
|
||||
logWarning(tr("Could not map recommended forge version for Minecraft %1").arg(mcVersion));
|
||||
logWarning(tr("Could not map recommended Forge version for Minecraft %1").arg(mcVersion));
|
||||
}
|
||||
}
|
||||
components->setComponentVersion("net.minecraftforge", forgeVersion);
|
||||
|
@ -37,6 +37,9 @@ class InstanceImportTask : public InstanceTask
|
||||
public:
|
||||
explicit InstanceImportTask(const QUrl sourceUrl);
|
||||
|
||||
bool canAbort() const override { return true; }
|
||||
bool abort() override;
|
||||
|
||||
protected:
|
||||
//! Entry point for tasks.
|
||||
virtual void executeTask() override;
|
||||
|
@ -8,7 +8,7 @@ bool JavaCommon::checkJVMArgs(QString jvmargs, QWidget *parent)
|
||||
|| jvmargs.contains("-XX-MaxHeapSize") || jvmargs.contains("-XX:InitialHeapSize"))
|
||||
{
|
||||
auto warnStr = QObject::tr(
|
||||
"You tried to manually set a JVM memory option (using \"-XX:PermSize\", \"-XX-MaxHeapSize\", \"-XX:InitialHeapSize\", \"-Xmx\" 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"
|
||||
"This message will be displayed until you remove them from the JVM arguments.");
|
||||
CustomMessageBox::selectable(
|
||||
@ -17,6 +17,17 @@ bool JavaCommon::checkJVMArgs(QString jvmargs, QWidget *parent)
|
||||
QMessageBox::Warning)->exec();
|
||||
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;
|
||||
}
|
||||
|
||||
@ -40,7 +51,7 @@ void JavaCommon::javaArgsWereBad(QWidget *parent, JavaCheckResult result)
|
||||
auto htmlError = result.errorLog;
|
||||
QString text;
|
||||
htmlError.replace('\n', "<br />");
|
||||
text += QObject::tr("The specified java binary didn't work with the arguments you provided:<br />");
|
||||
text += QObject::tr("The specified Java binary didn't work with the arguments you provided:<br />");
|
||||
text += QString("<font color=\"red\">%1</font>").arg(htmlError);
|
||||
CustomMessageBox::selectable(parent, QObject::tr("Java test failure"), text, QMessageBox::Warning)->show();
|
||||
}
|
||||
@ -49,8 +60,8 @@ void JavaCommon::javaBinaryWasBad(QWidget *parent, JavaCheckResult result)
|
||||
{
|
||||
QString text;
|
||||
text += QObject::tr(
|
||||
"The specified java binary didn't work.<br />You should use the auto-detect feature, "
|
||||
"or set the path to the java executable.<br />");
|
||||
"The specified Java binary didn't work.<br />You should use the auto-detect feature, "
|
||||
"or set the path to the Java executable.<br />");
|
||||
CustomMessageBox::selectable(parent, QObject::tr("Java test failure"), text, QMessageBox::Warning)->show();
|
||||
}
|
||||
|
||||
|
@ -1,3 +1,38 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
/*
|
||||
* PolyMC - Minecraft Launcher
|
||||
* Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, version 3.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* This file incorporates work covered by the following copyright and
|
||||
* permission notice:
|
||||
*
|
||||
* Copyright 2013-2021 MultiMC Contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "LaunchController.h"
|
||||
#include "minecraft/auth/AccountList.h"
|
||||
#include "Application.h"
|
||||
@ -36,7 +71,10 @@ void LaunchController::executeTask()
|
||||
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();
|
||||
}
|
||||
@ -131,13 +169,14 @@ void LaunchController::login() {
|
||||
if(!m_session->wants_online) {
|
||||
// we ask the user for a player name
|
||||
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(
|
||||
m_parentWidget,
|
||||
tr("Player name"),
|
||||
tr("Choose your offline mode player name."),
|
||||
QLineEdit::Normal,
|
||||
m_session->player_name,
|
||||
usedname,
|
||||
&ok
|
||||
);
|
||||
if (!ok)
|
||||
@ -148,6 +187,7 @@ void LaunchController::login() {
|
||||
if (name.length())
|
||||
{
|
||||
usedname = name;
|
||||
APPLICATION->settings()->set("LastOfflinePlayerName", usedname);
|
||||
}
|
||||
m_session->MakeOffline(usedname);
|
||||
// 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
|
||||
#include <QObject>
|
||||
#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
|
||||
export GAME_LIBRARY_PATH=${GAME_LIBRARY_PATH-${LD_LIBRARY_PATH}}
|
||||
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 QT_PLUGIN_PATH="${LAUNCHER_DIR}/plugins"
|
||||
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");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* 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.
|
||||
*
|
||||
* 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
|
||||
* 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.
|
||||
* 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 <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");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* 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.
|
||||
*
|
||||
* 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
|
||||
* 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.
|
||||
* 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
|
||||
|
@ -129,7 +129,7 @@ void JavaChecker::finished(int exitcode, QProcess::ExitStatus status)
|
||||
auto os_arch = results["os.arch"];
|
||||
auto java_version = results["java.version"];
|
||||
auto java_vendor = results["java.vendor"];
|
||||
bool is_64 = os_arch == "x86_64" || os_arch == "amd64";
|
||||
bool is_64 = os_arch == "x86_64" || os_arch == "amd64" || os_arch == "aarch64" || os_arch == "arm64";
|
||||
|
||||
|
||||
result.validity = JavaCheckResult::Validity::Valid;
|
||||
|
@ -183,7 +183,7 @@ void JavaListLoadTask::javaCheckerFinished()
|
||||
JavaInstallPtr javaVersion(new JavaInstall());
|
||||
|
||||
javaVersion->id = result.javaVersion;
|
||||
javaVersion->arch = result.mojangPlatform;
|
||||
javaVersion->arch = result.realPlatform;
|
||||
javaVersion->path = result.path;
|
||||
candidates.append(javaVersion);
|
||||
|
||||
|
@ -153,7 +153,7 @@ QStringList addJavasFromEnv(QList<QString> javas)
|
||||
{
|
||||
QByteArray env = qgetenv("POLYMC_JAVA_PATHS");
|
||||
#if defined(Q_OS_WIN32)
|
||||
QList<QString> javaPaths = QString::fromLocal8Bit(env).split(QLatin1String(";"));
|
||||
QList<QString> javaPaths = QString::fromLocal8Bit(env).replace("\\", "/").split(QLatin1String(";"));
|
||||
#else
|
||||
QList<QString> javaPaths = QString::fromLocal8Bit(env).split(QLatin1String(":"));
|
||||
#endif
|
||||
@ -355,7 +355,7 @@ QList<QString> JavaUtils::FindJavaPaths()
|
||||
}
|
||||
}
|
||||
|
||||
return candidates;
|
||||
return addJavasFromEnv(candidates);
|
||||
}
|
||||
|
||||
#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");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* 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.
|
||||
*
|
||||
* 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
|
||||
* 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.
|
||||
* This file incorporates work covered by the following copyright and
|
||||
* permission notice:
|
||||
*
|
||||
* Copyright 2013-2021 MultiMC Contributors
|
||||
*
|
||||
* 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"
|
||||
@ -212,7 +232,7 @@ shared_qobject_ptr<LogModel> LaunchTask::getLogModel()
|
||||
m_logModel->setMaxLines(m_instance->getConsoleMaxLines());
|
||||
m_logModel->setStopOnOverflow(m_instance->shouldStopOnConsoleOverflow());
|
||||
// FIXME: should this really be here?
|
||||
m_logModel->setOverflowMessage(tr("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"
|
||||
" 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");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* 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.
|
||||
*
|
||||
* 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
|
||||
* 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.
|
||||
* 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 "CheckJava.h"
|
||||
@ -87,14 +107,14 @@ void CheckJava::checkJavaFinished(JavaCheckResult result)
|
||||
// Error message displayed if java can't start
|
||||
emit logLine(QString("Could not start java:"), MessageLevel::Error);
|
||||
emit logLines(result.errorLog.split('\n'), MessageLevel::Error);
|
||||
emit logLine("\nCheck your PolyMC Java settings.", MessageLevel::Launcher);
|
||||
emit logLine(QString("\nCheck your Java settings."), MessageLevel::Launcher);
|
||||
printSystemInfo(false, false);
|
||||
emitFailed(QString("Could not start java!"));
|
||||
return;
|
||||
}
|
||||
case JavaCheckResult::Validity::ReturnedInvalidData:
|
||||
{
|
||||
emit logLine(QString("Java checker returned some invalid data 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 logLine("\nMinecraft might not start properly.", MessageLevel::Launcher);
|
||||
printSystemInfo(false, false);
|
||||
@ -104,7 +124,8 @@ void CheckJava::checkJavaFinished(JavaCheckResult result)
|
||||
case JavaCheckResult::Validity::Valid:
|
||||
{
|
||||
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("JavaArchitecture", result.mojangPlatform);
|
||||
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)
|
||||
{
|
||||
emit logLine(QString("Java is version %1, using %2-bit architecture, from %3.\n\n").arg(version, architecture, vendor), MessageLevel::Launcher);
|
||||
printSystemInfo(true, architecture == "64");
|
||||
emit logLine(QString("Java is version %1, using %2 architecture, from %3.\n\n").arg(version, architecture, vendor), MessageLevel::Launcher);
|
||||
}
|
||||
|
||||
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);
|
||||
#endif
|
||||
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0))
|
||||
QApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::PassThrough);
|
||||
#endif
|
||||
|
||||
// initialize Qt
|
||||
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";
|
||||
}
|
||||
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){
|
||||
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 <Version.h>
|
||||
|
||||
@ -7,11 +42,13 @@ void LaunchProfile::clear()
|
||||
m_minecraftVersionType.clear();
|
||||
m_minecraftAssets.reset();
|
||||
m_minecraftArguments.clear();
|
||||
m_addnJvmArguments.clear();
|
||||
m_tweakers.clear();
|
||||
m_mainClass.clear();
|
||||
m_appletClass.clear();
|
||||
m_libraries.clear();
|
||||
m_mavenFiles.clear();
|
||||
m_agents.clear();
|
||||
m_traits.clear();
|
||||
m_jarMods.clear();
|
||||
m_mainJar.reset();
|
||||
@ -45,6 +82,11 @@ void LaunchProfile::applyMinecraftArguments(const QString& minecraftArguments)
|
||||
applyString(minecraftArguments, this->m_minecraftArguments);
|
||||
}
|
||||
|
||||
void LaunchProfile::applyAddnJvmArguments(const QStringList& addnJvmArguments)
|
||||
{
|
||||
this->m_addnJvmArguments.append(addnJvmArguments);
|
||||
}
|
||||
|
||||
void LaunchProfile::applyMinecraftVersionType(const QString& type)
|
||||
{
|
||||
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)
|
||||
{
|
||||
if(!library->isActive())
|
||||
@ -174,6 +221,22 @@ void LaunchProfile::applyMavenFile(LibraryPtr 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
|
||||
{
|
||||
return m_mainJar;
|
||||
@ -255,6 +318,11 @@ QString LaunchProfile::getMinecraftArguments() const
|
||||
return m_minecraftArguments;
|
||||
}
|
||||
|
||||
const QStringList & LaunchProfile::getAddnJvmArguments() const
|
||||
{
|
||||
return m_addnJvmArguments;
|
||||
}
|
||||
|
||||
const QList<LibraryPtr> & LaunchProfile::getJarMods() const
|
||||
{
|
||||
return m_jarMods;
|
||||
@ -275,6 +343,16 @@ const QList<LibraryPtr> & LaunchProfile::getMavenFiles() const
|
||||
return m_mavenFiles;
|
||||
}
|
||||
|
||||
const QList<AgentPtr> & LaunchProfile::getAgents() const
|
||||
{
|
||||
return m_agents;
|
||||
}
|
||||
|
||||
const QList<int> & LaunchProfile::getCompatibleJavaMajors() const
|
||||
{
|
||||
return m_compatibleJavaMajors;
|
||||
}
|
||||
|
||||
void LaunchProfile::getLibraryFiles(
|
||||
const QString& architecture,
|
||||
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
|
||||
#include <QString>
|
||||
#include "Library.h"
|
||||
#include "Agent.h"
|
||||
#include <ProblemProvider.h>
|
||||
|
||||
class LaunchProfile: public ProblemProvider
|
||||
@ -13,6 +49,7 @@ public: /* application of profile variables from patches */
|
||||
void applyMainClass(const QString& mainClass);
|
||||
void applyAppletClass(const QString& appletClass);
|
||||
void applyMinecraftArguments(const QString& minecraftArguments);
|
||||
void applyAddnJvmArguments(const QStringList& minecraftArguments);
|
||||
void applyMinecraftVersionType(const QString& type);
|
||||
void applyMinecraftAssets(MojangAssetIndexInfo::Ptr assets);
|
||||
void applyTraits(const QSet<QString> &traits);
|
||||
@ -21,6 +58,8 @@ public: /* application of profile variables from patches */
|
||||
void applyMods(const QList<LibraryPtr> &jarMods);
|
||||
void applyLibrary(LibraryPtr library);
|
||||
void applyMavenFile(LibraryPtr library);
|
||||
void applyAgent(AgentPtr agent);
|
||||
void applyCompatibleJavaMajors(QList<int>& javaMajor);
|
||||
void applyMainJar(LibraryPtr jar);
|
||||
void applyProblemSeverity(ProblemSeverity severity);
|
||||
/// clear the profile
|
||||
@ -33,12 +72,15 @@ public: /* getters for profile variables */
|
||||
QString getMinecraftVersionType() const;
|
||||
MojangAssetIndexInfo::Ptr getMinecraftAssets() const;
|
||||
QString getMinecraftArguments() const;
|
||||
const QStringList & getAddnJvmArguments() const;
|
||||
const QSet<QString> & getTraits() const;
|
||||
const QStringList & getTweakers() const;
|
||||
const QList<LibraryPtr> & getJarMods() const;
|
||||
const QList<LibraryPtr> & getLibraries() const;
|
||||
const QList<LibraryPtr> & getNativeLibraries() const;
|
||||
const QList<LibraryPtr> & getMavenFiles() const;
|
||||
const QList<AgentPtr> & getAgents() const;
|
||||
const QList<int> & getCompatibleJavaMajors() const;
|
||||
const LibraryPtr getMainJar() const;
|
||||
void getLibraryFiles(
|
||||
const QString & architecture,
|
||||
@ -69,6 +111,12 @@ private:
|
||||
*/
|
||||
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
|
||||
QStringList m_tweakers;
|
||||
|
||||
@ -84,6 +132,9 @@ private:
|
||||
/// the list of maven files to be placed in the libraries folder, but not acted upon
|
||||
QList<LibraryPtr> m_mavenFiles;
|
||||
|
||||
/// the list of java agents to add to JVM arguments
|
||||
QList<AgentPtr> m_agents;
|
||||
|
||||
/// the main jar
|
||||
LibraryPtr m_mainJar;
|
||||
|
||||
@ -99,6 +150,9 @@ private:
|
||||
/// the list of mods
|
||||
QList<LibraryPtr> m_mods;
|
||||
|
||||
/// compatible java major versions
|
||||
QList<int> m_compatibleJavaMajors;
|
||||
|
||||
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 "BuildConfig.h"
|
||||
#include "minecraft/launch/CreateGameFolders.h"
|
||||
#include "minecraft/launch/ExtractNatives.h"
|
||||
#include "minecraft/launch/PrintInstanceInfo.h"
|
||||
@ -20,6 +56,7 @@
|
||||
#include "launch/steps/PreLaunchCommand.h"
|
||||
#include "launch/steps/TextPrint.h"
|
||||
#include "launch/steps/CheckJava.h"
|
||||
#include "launch/steps/QuitAfterGameStop.h"
|
||||
|
||||
#include "minecraft/launch/LauncherPartLaunch.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("JvmArgs"), javaOrArgs);
|
||||
m_settings->registerOverride(globalSettings->getSetting("IgnoreJavaCompatibility"), javaOrLocation);
|
||||
|
||||
// special!
|
||||
m_settings->registerPassthrough(globalSettings->getSetting("JavaTimestamp"), javaOrLocation);
|
||||
@ -292,6 +330,17 @@ QStringList MinecraftInstance::extraArguments() const
|
||||
list.append({"-Dfml.ignoreInvalidMinecraftCertificates=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;
|
||||
}
|
||||
|
||||
@ -434,7 +483,7 @@ QStringList MinecraftInstance::processMinecraftArgs(
|
||||
}
|
||||
|
||||
// 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();
|
||||
|
||||
@ -935,6 +984,11 @@ shared_qobject_ptr<LaunchTask> MinecraftInstance::createLaunchTask(AuthSessionPt
|
||||
{
|
||||
process->setCensorFilter(createCensorFilterFromSession(session));
|
||||
}
|
||||
if(APPLICATION->settings()->get("QuitAfterGameStop").toBool())
|
||||
{
|
||||
auto step = new QuitAfterGameStop(pptr);
|
||||
process->appendStep(step);
|
||||
}
|
||||
m_launchProcess = process;
|
||||
emit launchTaskChanged(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 "OneSixVersionFormat.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"))
|
||||
{
|
||||
auto downloadsObj = requireObject(in, "downloads");
|
||||
|
@ -1,5 +1,6 @@
|
||||
#include "OneSixVersionFormat.h"
|
||||
#include <Json.h>
|
||||
#include "minecraft/Agent.h"
|
||||
#include "minecraft/ParseUtils.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"))
|
||||
{
|
||||
@ -176,6 +185,21 @@ VersionFilePtr OneSixVersionFormat::versionFileFromJson(const QJsonDocument &doc
|
||||
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(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 "MojangDownloadInfo.h"
|
||||
#include "net/Mode.h"
|
||||
#include "modplatform/ModAPI.h"
|
||||
|
||||
class MinecraftInstance;
|
||||
struct PackProfileData;
|
||||
@ -117,6 +118,8 @@ public:
|
||||
// todo(merged): is this the best approach
|
||||
void appendComponent(ComponentPtr component);
|
||||
|
||||
ModAPI::ModLoaderType getModLoader();
|
||||
|
||||
private:
|
||||
void scheduleSave();
|
||||
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 <QJsonDocument>
|
||||
|
||||
@ -32,10 +67,12 @@ void VersionFile::applyTo(LaunchProfile *profile)
|
||||
profile->applyMainClass(mainClass);
|
||||
profile->applyAppletClass(appletClass);
|
||||
profile->applyMinecraftArguments(minecraftArguments);
|
||||
profile->applyAddnJvmArguments(addnJvmArguments);
|
||||
profile->applyTweakers(addTweakers);
|
||||
profile->applyJarMods(jarMods);
|
||||
profile->applyMods(mods);
|
||||
profile->applyTraits(traits);
|
||||
profile->applyCompatibleJavaMajors(compatibleJavaMajors);
|
||||
|
||||
for (auto library : libraries)
|
||||
{
|
||||
@ -45,6 +82,10 @@ void VersionFile::applyTo(LaunchProfile *profile)
|
||||
{
|
||||
profile->applyMavenFile(mavenFile);
|
||||
}
|
||||
for (auto agent : agents)
|
||||
{
|
||||
profile->applyAgent(agent);
|
||||
}
|
||||
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
|
||||
|
||||
#include <QString>
|
||||
@ -10,6 +45,7 @@
|
||||
#include "minecraft/Rule.h"
|
||||
#include "ProblemProvider.h"
|
||||
#include "Library.h"
|
||||
#include "Agent.h"
|
||||
#include <meta/JsonFormat.h>
|
||||
|
||||
class PackProfile;
|
||||
@ -57,6 +93,12 @@ public: /* data */
|
||||
/// Mojang: Minecraft launch arguments (may contain placeholders for variable substitution)
|
||||
QString minecraftArguments;
|
||||
|
||||
/// PolyMC: Additional JVM launch arguments
|
||||
QStringList addnJvmArguments;
|
||||
|
||||
/// Mojang: list of compatible java majors
|
||||
QList<int> compatibleJavaMajors;
|
||||
|
||||
/// Mojang: type of the Minecraft version
|
||||
QString type;
|
||||
|
||||
@ -78,6 +120,9 @@ public: /* data */
|
||||
/// PolyMC: list of maven files to put in the libraries folder, but not in classpath
|
||||
QList<LibraryPtr> mavenFiles;
|
||||
|
||||
/// PolyMC: list of agents to add to JVM arguments
|
||||
QList<AgentPtr> agents;
|
||||
|
||||
/// The main jar (Minecraft version library, normally)
|
||||
LibraryPtr mainJar;
|
||||
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include <QString>
|
||||
#include <QDebug>
|
||||
#include <QSaveFile>
|
||||
#include <QDirIterator>
|
||||
#include "World.h"
|
||||
|
||||
#include "GZip.h"
|
||||
@ -187,6 +188,26 @@ bool putLevelDatDataToFS(const QFileInfo &file, QByteArray & data)
|
||||
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)
|
||||
{
|
||||
repath(file);
|
||||
@ -196,6 +217,7 @@ void World::repath(const QFileInfo &file)
|
||||
{
|
||||
m_containerFile = file;
|
||||
m_folderName = file.fileName();
|
||||
m_size = calculateWorldSize(file);
|
||||
if(file.isFile() && file.suffix() == "zip")
|
||||
{
|
||||
m_iconFile = QString();
|
||||
@ -482,6 +504,7 @@ void World::loadFromLevelDat(QByteArray data)
|
||||
if(randomSeed) {
|
||||
qDebug() << "Seed:" << *randomSeed;
|
||||
}
|
||||
qDebug() << "Size:" << m_size;
|
||||
qDebug() << "GameType:" << m_gameType.toLogString();
|
||||
}
|
||||
|
||||
|
@ -52,6 +52,10 @@ public:
|
||||
{
|
||||
return m_iconFile;
|
||||
}
|
||||
int64_t bytes() const
|
||||
{
|
||||
return m_size;
|
||||
}
|
||||
QDateTime lastPlayed() const
|
||||
{
|
||||
return m_lastPlayed;
|
||||
@ -105,6 +109,7 @@ protected:
|
||||
QString m_iconFile;
|
||||
QDateTime levelDatTime;
|
||||
QDateTime m_lastPlayed;
|
||||
int64_t m_size;
|
||||
int64_t m_randomSeed = 0;
|
||||
GameType m_gameType;
|
||||
bool is_valid = false;
|
||||
|
@ -14,7 +14,10 @@
|
||||
*/
|
||||
|
||||
#include "WorldList.h"
|
||||
|
||||
#include "Application.h"
|
||||
#include <FileSystem.h>
|
||||
#include <Qt>
|
||||
#include <QMimeData>
|
||||
#include <QUrl>
|
||||
#include <QUuid>
|
||||
@ -150,7 +153,7 @@ bool WorldList::resetIcon(int row)
|
||||
|
||||
int WorldList::columnCount(const QModelIndex &parent) const
|
||||
{
|
||||
return 3;
|
||||
return 4;
|
||||
}
|
||||
|
||||
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())
|
||||
return QVariant();
|
||||
|
||||
QLocale locale;
|
||||
|
||||
auto & world = worlds[row];
|
||||
switch (role)
|
||||
{
|
||||
@ -179,10 +184,23 @@ QVariant WorldList::data(const QModelIndex &index, int role) const
|
||||
case LastPlayedColumn:
|
||||
return world.lastPlayed();
|
||||
|
||||
case SizeColumn:
|
||||
return locale.formattedDataSize(world.bytes());
|
||||
|
||||
default:
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
case Qt::UserRole:
|
||||
switch (column)
|
||||
{
|
||||
case SizeColumn:
|
||||
return qVariantFromValue<qlonglong>(world.bytes());
|
||||
|
||||
default:
|
||||
return data(index, Qt::DisplayRole);
|
||||
}
|
||||
|
||||
case Qt::ToolTipRole:
|
||||
{
|
||||
return world.folderName();
|
||||
@ -207,6 +225,10 @@ QVariant WorldList::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
return world.lastPlayed();
|
||||
}
|
||||
case SizeRole:
|
||||
{
|
||||
return qVariantFromValue<qlonglong>(world.bytes());
|
||||
}
|
||||
case IconFileRole:
|
||||
{
|
||||
return world.iconFile();
|
||||
@ -229,6 +251,9 @@ QVariant WorldList::headerData(int section, Qt::Orientation orientation, int rol
|
||||
return tr("Game Mode");
|
||||
case LastPlayedColumn:
|
||||
return tr("Last Played");
|
||||
case SizeColumn:
|
||||
//: World size on disk
|
||||
return tr("Size");
|
||||
default:
|
||||
return QVariant();
|
||||
}
|
||||
@ -242,6 +267,8 @@ QVariant WorldList::headerData(int section, Qt::Orientation orientation, int rol
|
||||
return tr("Game mode of the world.");
|
||||
case LastPlayedColumn:
|
||||
return tr("Date and time the world was last played.");
|
||||
case SizeColumn:
|
||||
return tr("Size of the world on disk.");
|
||||
default:
|
||||
return QVariant();
|
||||
}
|
||||
|
@ -32,7 +32,8 @@ public:
|
||||
{
|
||||
NameColumn,
|
||||
GameModeColumn,
|
||||
LastPlayedColumn
|
||||
LastPlayedColumn,
|
||||
SizeColumn
|
||||
};
|
||||
|
||||
enum Roles
|
||||
@ -43,6 +44,7 @@ public:
|
||||
NameRole,
|
||||
GameModeRole,
|
||||
LastPlayedRole,
|
||||
SizeRole,
|
||||
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 <QJsonDocument>
|
||||
#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
|
||||
#include <QString>
|
||||
#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");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* 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.
|
||||
*
|
||||
* 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
|
||||
* 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.
|
||||
* 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 "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");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* 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.
|
||||
*
|
||||
* 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
|
||||
* 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.
|
||||
* 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
|
||||
|
@ -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");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* 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.
|
||||
*
|
||||
* 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
|
||||
* 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.
|
||||
* 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 "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");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* 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.
|
||||
*
|
||||
* 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
|
||||
* 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.
|
||||
* 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
|
||||
|
@ -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");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* 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.
|
||||
*
|
||||
* 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
|
||||
* 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.
|
||||
* This file incorporates work covered by the following copyright and
|
||||
* permission notice:
|
||||
*
|
||||
* Copyright 2013-2021 MultiMC Contributors
|
||||
*
|
||||
* 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"
|
||||
|
@ -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");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* 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.
|
||||
*
|
||||
* 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
|
||||
* 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.
|
||||
* 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
|
||||
|
@ -1,4 +1,5 @@
|
||||
#include "Parsers.h"
|
||||
#include "Json.h"
|
||||
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonArray>
|
||||
@ -212,6 +213,180 @@ bool parseMinecraftProfile(QByteArray & data, MinecraftProfile &output) {
|
||||
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) {
|
||||
qDebug() << "Parsing Minecraft entitlements...";
|
||||
#ifndef NDEBUG
|
||||
|
@ -14,6 +14,7 @@ namespace Parsers
|
||||
bool parseMojangResponse(QByteArray &data, Katabasis::Token &output);
|
||||
|
||||
bool parseMinecraftProfile(QByteArray &data, MinecraftProfile &output);
|
||||
bool parseMinecraftProfileMojang(QByteArray &data, MinecraftProfile &output);
|
||||
bool parseMinecraftEntitlements(QByteArray &data, MinecraftEntitlement &output);
|
||||
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.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 succeeded.
|
||||
qDebug() << "Finished reading authentication response.";
|
||||
|
@ -1,7 +1,7 @@
|
||||
#include "Mojang.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/GetSkinStep.h"
|
||||
|
||||
@ -10,7 +10,7 @@ MojangRefresh::MojangRefresh(
|
||||
QObject *parent
|
||||
) : AuthFlow(data, parent) {
|
||||
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 GetSkinStep(m_data));
|
||||
}
|
||||
@ -21,7 +21,7 @@ MojangLogin::MojangLogin(
|
||||
QObject *parent
|
||||
): AuthFlow(data, parent), m_password(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 GetSkinStep(m_data));
|
||||
}
|
||||
|
@ -50,7 +50,9 @@ void LauncherLoginStep::onRequestDone(
|
||||
auto requestor = qobject_cast<AuthRequest *>(QObject::sender());
|
||||
requestor->deleteLater();
|
||||
|
||||
#ifndef NDEBUG
|
||||
qDebug() << data;
|
||||
#endif
|
||||
if (error != QNetworkReply::NoError) {
|
||||
qWarning() << "Reply error:" << error;
|
||||
#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 <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
|
||||
#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)) {
|
||||
emit finished(
|
||||
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;
|
||||
|
@ -88,7 +88,7 @@ void DirectJavaLaunch::on_state(LoggedProcess::State state)
|
||||
case LoggedProcess::FailedToStart:
|
||||
{
|
||||
//: Error message displayed if instance can't start
|
||||
const char *reason = QT_TR_NOOP("Could not launch minecraft!");
|
||||
const char *reason = QT_TR_NOOP("Could not launch Minecraft!");
|
||||
emit logLine(reason, MessageLevel::Fatal);
|
||||
emitFailed(tr(reason));
|
||||
return;
|
||||
|
@ -154,7 +154,7 @@ void LauncherPartLaunch::on_state(LoggedProcess::State state)
|
||||
case LoggedProcess::FailedToStart:
|
||||
{
|
||||
//: Error message displayed if instace can't start
|
||||
const char *reason = QT_TR_NOOP("Could not launch minecraft!");
|
||||
const char *reason = QT_TR_NOOP("Could not launch Minecraft!");
|
||||
emit logLine(reason, MessageLevel::Fatal);
|
||||
emitFailed(tr(reason));
|
||||
return;
|
||||
@ -170,6 +170,7 @@ void LauncherPartLaunch::on_state(LoggedProcess::State state)
|
||||
{
|
||||
if (APPLICATION->settings()->get("CloseAfterLaunch").toBool())
|
||||
APPLICATION->showMainWindow();
|
||||
|
||||
m_parent->setPid(-1);
|
||||
// if the exit code wasn't 0, report this as a crash
|
||||
auto exitCode = m_process.exitCode();
|
||||
|
@ -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 <launch/LaunchTask.h>
|
||||
#include <minecraft/MinecraftInstance.h>
|
||||
#include <minecraft/PackProfile.h>
|
||||
#include <minecraft/VersionFilterData.h>
|
||||
|
||||
#ifdef major
|
||||
#undef major
|
||||
#endif
|
||||
#ifdef minor
|
||||
#undef minor
|
||||
#endif
|
||||
#include "java/JavaVersion.h"
|
||||
#include "minecraft/PackProfile.h"
|
||||
#include "minecraft/MinecraftInstance.h"
|
||||
|
||||
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 minecraftComponent = m_inst->getPackProfile()->getComponent("net.minecraft");
|
||||
auto compatibleMajors = packProfile->getProfile()->getCompatibleJavaMajors();
|
||||
|
||||
// Java 17 requirement
|
||||
if (minecraftComponent->getReleaseDateTime() >= g_VersionFilterData.java17BeginsDate) {
|
||||
if (javaVersion.major() < 17) {
|
||||
emit logLine("Minecraft 1.18 Pre Release 2 and above require the use of Java 17",
|
||||
MessageLevel::Fatal);
|
||||
emitFailed(tr("Minecraft 1.18 Pre Release 2 and above require the use of Java 17"));
|
||||
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;
|
||||
}
|
||||
JavaVersion javaVersion(storedVersion);
|
||||
|
||||
if (compatibleMajors.isEmpty() || compatibleMajors.contains(javaVersion.major()))
|
||||
{
|
||||
emitSucceeded();
|
||||
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
|
||||
|
||||
#include <launch/LaunchStep.h>
|
||||
#include <launch/LaunchTask.h>
|
||||
|
||||
class VerifyJavaInstall : public LaunchStep {
|
||||
Q_OBJECT
|
||||
|
@ -391,7 +391,7 @@ void LocalModParseTask::processAsZip()
|
||||
zip.close();
|
||||
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))
|
||||
{
|
||||
|
@ -14,7 +14,7 @@ void FoldersTask::executeTask()
|
||||
QDir mcDir(m_inst->gameRoot());
|
||||
if (!mcDir.exists() && !mcDir.mkpath("."))
|
||||
{
|
||||
emitFailed(tr("Failed to create folder for minecraft binaries."));
|
||||
emitFailed(tr("Failed to create folder for Minecraft binaries."));
|
||||
return;
|
||||
}
|
||||
emitSucceeded();
|
||||
|
@ -48,6 +48,10 @@ void LibrariesTask::executeTask()
|
||||
libArtifactPool.append(profile->getLibraries());
|
||||
libArtifactPool.append(profile->getNativeLibraries());
|
||||
libArtifactPool.append(profile->getMavenFiles());
|
||||
for (auto agent : profile->getAgents())
|
||||
{
|
||||
libArtifactPool.append(agent->library());
|
||||
}
|
||||
libArtifactPool.append(profile->getMainJar());
|
||||
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 "Json.h"
|
||||
|
||||
namespace {
|
||||
const char * metabase = "https://cursemeta.dries007.net";
|
||||
}
|
||||
|
||||
Flame::FileResolvingTask::FileResolvingTask(shared_qobject_ptr<QNetworkAccessManager> network, Flame::Manifest& toProcess)
|
||||
: m_network(network), m_toProcess(toProcess)
|
||||
{
|
||||
}
|
||||
{}
|
||||
|
||||
void Flame::FileResolvingTask::executeTask()
|
||||
{
|
||||
@ -17,14 +12,13 @@ void Flame::FileResolvingTask::executeTask()
|
||||
m_dljob = new NetJob("Mod id resolver", m_network);
|
||||
results.resize(m_toProcess.files.size());
|
||||
int index = 0;
|
||||
for(auto & file: m_toProcess.files)
|
||||
{
|
||||
for (auto& file : m_toProcess.files) {
|
||||
auto projectIdStr = QString::number(file.projectId);
|
||||
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]);
|
||||
m_dljob->addNetAction(dl);
|
||||
index ++;
|
||||
index++;
|
||||
}
|
||||
connect(m_dljob.get(), &NetJob::finished, this, &Flame::FileResolvingTask::netJobFinished);
|
||||
m_dljob->start();
|
||||
@ -34,16 +28,11 @@ void Flame::FileResolvingTask::netJobFinished()
|
||||
{
|
||||
bool failed = false;
|
||||
int index = 0;
|
||||
for(auto & bytes: results)
|
||||
{
|
||||
auto & out = m_toProcess.files[index];
|
||||
try
|
||||
{
|
||||
for (auto& bytes : results) {
|
||||
auto& out = m_toProcess.files[index];
|
||||
try {
|
||||
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() << e.cause();
|
||||
qCritical() << "JSON:";
|
||||
@ -52,12 +41,9 @@ void Flame::FileResolvingTask::netJobFinished()
|
||||
}
|
||||
index++;
|
||||
}
|
||||
if(!failed)
|
||||
{
|
||||
if (!failed) {
|
||||
emitSucceeded();
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
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 "Json.h"
|
||||
#include "net/NetJob.h"
|
||||
#include "BaseInstance.h"
|
||||
#include "minecraft/MinecraftInstance.h"
|
||||
#include "minecraft/PackProfile.h"
|
||||
#include "modplatform/flame/FlameAPI.h"
|
||||
#include "net/NetJob.h"
|
||||
|
||||
|
||||
void FlameMod::loadIndexedPack(FlameMod::IndexedPack & pack, QJsonObject & obj)
|
||||
void FlameMod::loadIndexedPack(ModPlatform::IndexedPack& pack, QJsonObject& obj)
|
||||
{
|
||||
pack.addonId = Json::requireInteger(obj, "id");
|
||||
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", "");
|
||||
|
||||
bool thumbnailFound = false;
|
||||
auto attachments = Json::requireArray(obj, "attachments");
|
||||
for(auto attachmentRaw: attachments) {
|
||||
auto attachmentObj = Json::requireObject(attachmentRaw);
|
||||
bool isDefault = attachmentObj.value("isDefault").toBool(false);
|
||||
if(isDefault) {
|
||||
thumbnailFound = true;
|
||||
pack.logoName = Json::requireString(attachmentObj, "title");
|
||||
pack.logoUrl = Json::requireString(attachmentObj, "thumbnailUrl");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(!thumbnailFound) {
|
||||
throw JSONValidationError(QString("Pack without an icon, skipping: %1").arg(pack.name));
|
||||
}
|
||||
|
||||
QJsonObject logo = Json::requireObject(obj, "logo");
|
||||
pack.logoName = Json::requireString(logo, "title");
|
||||
pack.logoUrl = Json::requireString(logo, "thumbnailUrl");
|
||||
|
||||
auto authors = Json::requireArray(obj, "authors");
|
||||
for(auto authorIter: authors) {
|
||||
for (auto authorIter : authors) {
|
||||
auto author = Json::requireObject(authorIter);
|
||||
FlameMod::ModpackAuthor packAuthor;
|
||||
ModPlatform::ModpackAuthor packAuthor;
|
||||
packAuthor.name = Json::requireString(author, "name");
|
||||
packAuthor.url = Json::requireString(author, "url");
|
||||
pack.authors.append(packAuthor);
|
||||
}
|
||||
}
|
||||
|
||||
void FlameMod::loadIndexedPackVersions(FlameMod::IndexedPack & pack, QJsonArray & arr, const shared_qobject_ptr<QNetworkAccessManager>& network, BaseInstance * inst)
|
||||
void FlameMod::loadIndexedPackVersions(ModPlatform::IndexedPack& pack,
|
||||
QJsonArray& arr,
|
||||
const shared_qobject_ptr<QNetworkAccessManager>& network,
|
||||
BaseInstance* inst)
|
||||
{
|
||||
QVector<FlameMod::IndexedVersion> unsortedVersions;
|
||||
bool hasFabric = !((MinecraftInstance *)inst)->getPackProfile()->getComponentVersion("net.fabricmc.fabric-loader").isEmpty();
|
||||
QString mcVersion = ((MinecraftInstance *)inst)->getPackProfile()->getComponentVersion("net.minecraft");
|
||||
QVector<ModPlatform::IndexedVersion> unsortedVersions;
|
||||
auto profile = (dynamic_cast<MinecraftInstance*>(inst))->getPackProfile();
|
||||
QString mcVersion = profile->getComponentVersion("net.minecraft");
|
||||
|
||||
for(auto versionIter: arr) {
|
||||
for (auto versionIter : arr) {
|
||||
auto obj = versionIter.toObject();
|
||||
|
||||
auto versionArray = Json::requireArray(obj, "gameVersion");
|
||||
auto versionArray = Json::requireArray(obj, "gameVersions");
|
||||
if (versionArray.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
FlameMod::IndexedVersion file;
|
||||
for(auto mcVer : versionArray){
|
||||
file.mcVersion.append(mcVer.toString());
|
||||
ModPlatform::IndexedVersion file;
|
||||
for (auto mcVer : versionArray) {
|
||||
auto str = mcVer.toString();
|
||||
|
||||
if (str.contains('.'))
|
||||
file.mcVersion.append(str);
|
||||
}
|
||||
|
||||
file.addonId = pack.addonId;
|
||||
@ -68,31 +59,11 @@ void FlameMod::loadIndexedPackVersions(FlameMod::IndexedPack & pack, QJsonArray
|
||||
file.downloadUrl = Json::requireString(obj, "downloadUrl");
|
||||
file.fileName = Json::requireString(obj, "fileName");
|
||||
|
||||
auto modules = Json::requireArray(obj, "modules");
|
||||
bool is_valid_fabric_version = false;
|
||||
for(auto m : modules){
|
||||
auto fname = Json::requireString(m.toObject(),"foldername");
|
||||
// FIXME: This does not work properly when a mod supports more than one mod loader, since
|
||||
// they bundle the meta files for all of them in the same arquive, even when that version
|
||||
// doesn't support the given mod loader.
|
||||
if(hasFabric){
|
||||
if(fname == "fabric.mod.json"){
|
||||
is_valid_fabric_version = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else break;
|
||||
// NOTE: Since we're not validating forge versions, we can just skip this loop.
|
||||
}
|
||||
|
||||
if(hasFabric && !is_valid_fabric_version)
|
||||
continue;
|
||||
|
||||
unsortedVersions.append(file);
|
||||
}
|
||||
auto orderSortPredicate = [](const IndexedVersion & a, const IndexedVersion & b) -> bool
|
||||
{
|
||||
//dates are in RFC 3339 format
|
||||
|
||||
auto orderSortPredicate = [](const ModPlatform::IndexedVersion& a, const ModPlatform::IndexedVersion& b) -> bool {
|
||||
// dates are in RFC 3339 format
|
||||
return a.date > b.date;
|
||||
};
|
||||
std::sort(unsortedVersions.begin(), unsortedVersions.end(), orderSortPredicate);
|
||||
|
@ -3,48 +3,18 @@
|
||||
//
|
||||
|
||||
#pragma once
|
||||
#include <QList>
|
||||
#include <QMetaType>
|
||||
#include <QString>
|
||||
#include <QVector>
|
||||
#include <QNetworkAccessManager>
|
||||
#include <QObjectPtr.h>
|
||||
#include "net/NetJob.h"
|
||||
|
||||
#include "modplatform/ModIndex.h"
|
||||
|
||||
#include "BaseInstance.h"
|
||||
#include <QNetworkAccessManager>
|
||||
|
||||
namespace FlameMod {
|
||||
struct ModpackAuthor {
|
||||
QString name;
|
||||
QString url;
|
||||
};
|
||||
|
||||
struct IndexedVersion {
|
||||
int addonId;
|
||||
int fileId;
|
||||
QString version;
|
||||
QVector<QString> mcVersion;
|
||||
QString downloadUrl;
|
||||
QString date;
|
||||
QString fileName;
|
||||
};
|
||||
void loadIndexedPack(ModPlatform::IndexedPack& m, QJsonObject& obj);
|
||||
void loadIndexedPackVersions(ModPlatform::IndexedPack& pack,
|
||||
QJsonArray& arr,
|
||||
const shared_qobject_ptr<QNetworkAccessManager>& network,
|
||||
BaseInstance* inst);
|
||||
|
||||
struct IndexedPack
|
||||
{
|
||||
int addonId;
|
||||
QString name;
|
||||
QString description;
|
||||
QList<ModpackAuthor> authors;
|
||||
QString logoName;
|
||||
QString logoUrl;
|
||||
QString websiteUrl;
|
||||
|
||||
bool versionsLoaded = false;
|
||||
QVector<IndexedVersion> versions;
|
||||
};
|
||||
|
||||
void loadIndexedPack(IndexedPack & m, QJsonObject & obj);
|
||||
void loadIndexedPackVersions(IndexedPack &pack, QJsonArray &arr, const shared_qobject_ptr<QNetworkAccessManager> &network, BaseInstance *inst);
|
||||
|
||||
}
|
||||
|
||||
Q_DECLARE_METATYPE(FlameMod::IndexedPack)
|
||||
} // namespace FlameMod
|
||||
|
@ -2,76 +2,63 @@
|
||||
|
||||
#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.name = Json::requireString(obj, "name");
|
||||
pack.websiteUrl = Json::ensureString(obj, "websiteUrl", "");
|
||||
pack.description = Json::ensureString(obj, "summary", "");
|
||||
|
||||
bool thumbnailFound = false;
|
||||
auto attachments = Json::requireArray(obj, "attachments");
|
||||
for(auto attachmentRaw: attachments) {
|
||||
auto attachmentObj = Json::requireObject(attachmentRaw);
|
||||
bool isDefault = attachmentObj.value("isDefault").toBool(false);
|
||||
if(isDefault) {
|
||||
thumbnailFound = true;
|
||||
pack.logoName = Json::requireString(attachmentObj, "title");
|
||||
pack.logoUrl = Json::requireString(attachmentObj, "thumbnailUrl");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(!thumbnailFound) {
|
||||
throw JSONValidationError(QString("Pack without an icon, skipping: %1").arg(pack.name));
|
||||
}
|
||||
auto logo = Json::requireObject(obj, "logo");
|
||||
pack.logoName = Json::requireString(logo, "title");
|
||||
pack.logoUrl = Json::requireString(logo, "thumbnailUrl");
|
||||
|
||||
auto authors = Json::requireArray(obj, "authors");
|
||||
for(auto authorIter: authors) {
|
||||
for (auto authorIter : authors) {
|
||||
auto author = Json::requireObject(authorIter);
|
||||
Flame::ModpackAuthor packAuthor;
|
||||
packAuthor.name = Json::requireString(author, "name");
|
||||
packAuthor.url = Json::requireString(author, "url");
|
||||
pack.authors.append(packAuthor);
|
||||
}
|
||||
int defaultFileId = Json::requireInteger(obj, "defaultFileId");
|
||||
int defaultFileId = Json::requireInteger(obj, "mainFileId");
|
||||
|
||||
bool found = false;
|
||||
// check if there are some files before adding the pack
|
||||
auto files = Json::requireArray(obj, "latestFiles");
|
||||
for(auto fileIter: files) {
|
||||
for (auto fileIter : files) {
|
||||
auto file = Json::requireObject(fileIter);
|
||||
int id = Json::requireInteger(file, "id");
|
||||
|
||||
// NOTE: for now, ignore everything that's not the default...
|
||||
if(id != defaultFileId) {
|
||||
if (id != defaultFileId) {
|
||||
continue;
|
||||
}
|
||||
|
||||
auto versionArray = Json::requireArray(file, "gameVersion");
|
||||
if(versionArray.size() < 1) {
|
||||
auto versionArray = Json::requireArray(file, "gameVersions");
|
||||
if (versionArray.size() < 1) {
|
||||
continue;
|
||||
}
|
||||
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
if(!found) {
|
||||
if (!found) {
|
||||
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;
|
||||
for(auto versionIter: arr) {
|
||||
for (auto versionIter : arr) {
|
||||
auto version = Json::requireObject(versionIter);
|
||||
Flame::IndexedVersion file;
|
||||
Flame::IndexedVersion file;
|
||||
|
||||
file.addonId = pack.addonId;
|
||||
file.fileId = Json::requireInteger(version, "id");
|
||||
auto versionArray = Json::requireArray(version, "gameVersion");
|
||||
if(versionArray.size() < 1) {
|
||||
auto versionArray = Json::requireArray(version, "gameVersions");
|
||||
if (versionArray.size() < 1) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -82,10 +69,7 @@ void Flame::loadIndexedPackVersions(Flame::IndexedPack & pack, QJsonArray & arr)
|
||||
unsortedVersions.append(file);
|
||||
}
|
||||
|
||||
auto orderSortPredicate = [](const IndexedVersion & a, const IndexedVersion & b) -> bool
|
||||
{
|
||||
return a.fileId > b.fileId;
|
||||
};
|
||||
auto orderSortPredicate = [](const IndexedVersion& a, const IndexedVersion& b) -> bool { return a.fileId > b.fileId; };
|
||||
std::sort(unsortedVersions.begin(), unsortedVersions.end(), orderSortPredicate);
|
||||
pack.versions = unsortedVersions;
|
||||
pack.versionsLoaded = true;
|
||||
|
@ -1,28 +1,27 @@
|
||||
#include "PackManifest.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.fileId = Json::requireInteger(file, "fileID");
|
||||
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.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");
|
||||
// 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
|
||||
m.libraries = Json::ensureString(minecraft, QString("libraries"), QString());
|
||||
auto arr = Json::ensureArray(minecraft, "modLoaders", QJsonArray());
|
||||
for (QJsonValueRef item : arr)
|
||||
{
|
||||
for (QJsonValueRef item : arr) {
|
||||
auto obj = Json::requireObject(item);
|
||||
Flame::Modloader loader;
|
||||
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");
|
||||
loadMinecraftV1(m.minecraft, mc);
|
||||
m.name = Json::ensureString(manifest, QString("name"), "Unnamed");
|
||||
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());
|
||||
for (QJsonValueRef item : arr)
|
||||
{
|
||||
for (QJsonValueRef item : arr) {
|
||||
auto obj = Json::requireObject(item);
|
||||
Flame::File file;
|
||||
loadFileV1(file, obj);
|
||||
@ -48,18 +46,16 @@ static void loadManifestV1(Flame::Manifest & m, QJsonObject & manifest)
|
||||
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 obj = Json::requireObject(doc);
|
||||
m.manifestType = Json::requireString(obj, "manifestType");
|
||||
if(m.manifestType != "minecraftModpack")
|
||||
{
|
||||
if (m.manifestType != "minecraftModpack") {
|
||||
throw JSONValidationError("Not a modpack manifest!");
|
||||
}
|
||||
m.manifestVersion = Json::requireInteger(obj, "manifestVersion");
|
||||
if(m.manifestVersion != 1)
|
||||
{
|
||||
if (m.manifestVersion != 1) {
|
||||
throw JSONValidationError(QString("Unknown manifest version (%1)").arg(m.manifestVersion));
|
||||
}
|
||||
loadManifestV1(m, obj);
|
||||
@ -68,59 +64,30 @@ void Flame::loadManifest(Flame::Manifest & m, const QString &filepath)
|
||||
bool Flame::File::parseFromBytes(const QByteArray& bytes)
|
||||
{
|
||||
auto doc = Json::requireDocument(bytes);
|
||||
auto obj = Json::requireObject(doc);
|
||||
// result code signifies true failure.
|
||||
if(obj.contains("code"))
|
||||
{
|
||||
qCritical() << "Resolving of" << projectId << fileId << "failed because of a negative result:";
|
||||
qCritical() << bytes;
|
||||
return false;
|
||||
if (!doc.isObject()) {
|
||||
throw JSONValidationError(QString("data is not an object? that's not supposed to happen"));
|
||||
}
|
||||
fileName = Json::requireString(obj, "FileNameOnDisk");
|
||||
QString rawUrl = Json::requireString(obj, "DownloadURL");
|
||||
auto obj = Json::ensureObject(doc.object(), "data");
|
||||
|
||||
fileName = Json::requireString(obj, "fileName");
|
||||
|
||||
QString rawUrl = Json::requireString(obj, "downloadUrl");
|
||||
url = QUrl(rawUrl, QUrl::TolerantMode);
|
||||
if(!url.isValid())
|
||||
{
|
||||
if (!url.isValid()) {
|
||||
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
|
||||
// It is also optional
|
||||
QJsonObject projObj = Json::ensureObject(obj, "_Project", {});
|
||||
if(!projObj.isEmpty())
|
||||
{
|
||||
QString strType = Json::ensureString(projObj, "PackageType", "mod").toLower();
|
||||
if(strType == "singlefile")
|
||||
{
|
||||
type = File::Type::SingleFile;
|
||||
}
|
||||
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");
|
||||
type = File::Type::SingleFile;
|
||||
|
||||
if (fileName.endsWith(".zip")) {
|
||||
// this is probably a resource pack
|
||||
targetFolder = "resourcepacks";
|
||||
} else {
|
||||
// this is probably a mod, dunno what else could modpacks download
|
||||
targetFolder = "mods";
|
||||
}
|
||||
|
||||
resolved = 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
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
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 "ModrinthAPI.h"
|
||||
|
||||
#include "Json.h"
|
||||
#include "net/NetJob.h"
|
||||
#include "BaseInstance.h"
|
||||
#include "minecraft/MinecraftInstance.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.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.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.url = "https://modrinth.com/user/"+modAuthor.name;
|
||||
pack.author = modAuthor;
|
||||
modAuthor.url = api.getAuthorURL(modAuthor.name);
|
||||
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;
|
||||
bool hasFabric = !((MinecraftInstance *)inst)->getPackProfile()->getComponentVersion("net.fabricmc.fabric-loader").isEmpty();
|
||||
QString mcVersion = ((MinecraftInstance *)inst)->getPackProfile()->getComponentVersion("net.minecraft");
|
||||
QVector<ModPlatform::IndexedVersion> unsortedVersions;
|
||||
QString mcVersion = (static_cast<MinecraftInstance*>(inst))->getPackProfile()->getComponentVersion("net.minecraft");
|
||||
|
||||
for(auto versionIter: arr) {
|
||||
for (auto versionIter : arr) {
|
||||
auto obj = versionIter.toObject();
|
||||
Modrinth::IndexedVersion file;
|
||||
file.addonId = Json::requireString(obj,"project_id") ;
|
||||
ModPlatform::IndexedVersion file;
|
||||
file.addonId = Json::requireString(obj, "project_id");
|
||||
file.fileId = Json::requireString(obj, "id");
|
||||
file.date = Json::requireString(obj, "date_published");
|
||||
auto versionArray = Json::requireArray(obj, "game_versions");
|
||||
if (versionArray.empty()) {
|
||||
continue;
|
||||
}
|
||||
for(auto mcVer : versionArray){
|
||||
if (versionArray.empty()) { continue; }
|
||||
for (auto mcVer : versionArray) {
|
||||
file.mcVersion.append(mcVer.toString());
|
||||
}
|
||||
auto loaders = Json::requireArray(obj,"loaders");
|
||||
for(auto loader : loaders){
|
||||
auto loaders = Json::requireArray(obj, "loaders");
|
||||
for (auto loader : loaders) {
|
||||
file.loaders.append(loader.toString());
|
||||
}
|
||||
file.version = Json::requireString(obj, "name");
|
||||
|
||||
auto files = Json::requireArray(obj, "files");
|
||||
int i = 0;
|
||||
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 fileName = Json::requireString(parent, "filename");
|
||||
//avoid grabbing "dev" files
|
||||
if(fileName.contains("javadocs",Qt::CaseInsensitive) || fileName.contains("sources",Qt::CaseInsensitive)){
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
//grab the correct mod loader
|
||||
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;
|
||||
|
||||
// Grab the primary file, if available
|
||||
if(Json::requireBoolean(parent, "primary"))
|
||||
break;
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
auto parent = files[i].toObject();
|
||||
if(parent.contains("url")) {
|
||||
if (parent.contains("url")) {
|
||||
file.downloadUrl = Json::requireString(parent, "url");
|
||||
file.fileName = Json::requireString(parent, "filename");
|
||||
|
||||
unsortedVersions.append(file);
|
||||
}
|
||||
}
|
||||
auto orderSortPredicate = [](const IndexedVersion & a, const IndexedVersion & b) -> bool
|
||||
{
|
||||
//dates are in RFC 3339 format
|
||||
auto orderSortPredicate = [](const ModPlatform::IndexedVersion& a, const ModPlatform::IndexedVersion& b) -> bool {
|
||||
// dates are in RFC 3339 format
|
||||
return a.date > b.date;
|
||||
};
|
||||
std::sort(unsortedVersions.begin(), unsortedVersions.end(), orderSortPredicate);
|
||||
|
@ -1,48 +1,16 @@
|
||||
#pragma once
|
||||
|
||||
#include <QList>
|
||||
#include <QMetaType>
|
||||
#include <QString>
|
||||
#include <QVector>
|
||||
#include <QNetworkAccessManager>
|
||||
#include <QObjectPtr.h>
|
||||
#include "net/NetJob.h"
|
||||
#include "modplatform/ModIndex.h"
|
||||
|
||||
#include "BaseInstance.h"
|
||||
#include <QNetworkAccessManager>
|
||||
|
||||
namespace Modrinth {
|
||||
|
||||
struct ModpackAuthor {
|
||||
QString name;
|
||||
QString url;
|
||||
};
|
||||
void loadIndexedPack(ModPlatform::IndexedPack& m, QJsonObject& obj);
|
||||
void loadIndexedPackVersions(ModPlatform::IndexedPack& pack,
|
||||
QJsonArray& arr,
|
||||
const shared_qobject_ptr<QNetworkAccessManager>& network,
|
||||
BaseInstance* inst);
|
||||
|
||||
struct IndexedVersion {
|
||||
QString addonId;
|
||||
QString fileId;
|
||||
QString version;
|
||||
QVector<QString> mcVersion;
|
||||
QString downloadUrl;
|
||||
QString date;
|
||||
QString fileName;
|
||||
QVector<QString> loaders;
|
||||
};
|
||||
|
||||
struct IndexedPack
|
||||
{
|
||||
QString addonId;
|
||||
QString name;
|
||||
QString description;
|
||||
ModpackAuthor author;
|
||||
QString logoName;
|
||||
QString logoUrl;
|
||||
QString websiteUrl;
|
||||
|
||||
bool versionsLoaded = false;
|
||||
QVector<IndexedVersion> versions;
|
||||
};
|
||||
|
||||
void loadIndexedPack(IndexedPack & m, QJsonObject & obj);
|
||||
void loadIndexedPackVersions(IndexedPack &pack, QJsonArray &arr, const shared_qobject_ptr<QNetworkAccessManager> &network, BaseInstance *inst);
|
||||
}
|
||||
|
||||
Q_DECLARE_METATYPE(Modrinth::IndexedPack)
|
||||
} // namespace Modrinth
|
||||
|
@ -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");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* 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.
|
||||
*
|
||||
* 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
|
||||
* 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.
|
||||
* 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 "SolderPackInstallTask.h"
|
||||
@ -19,16 +39,23 @@
|
||||
#include <Json.h>
|
||||
#include <QtConcurrentRun>
|
||||
#include <MMCZip.h>
|
||||
|
||||
#include "TechnicPackProcessor.h"
|
||||
#include "SolderPackManifest.h"
|
||||
#include "net/ChecksumValidator.h"
|
||||
|
||||
Technic::SolderPackInstallTask::SolderPackInstallTask(
|
||||
shared_qobject_ptr<QNetworkAccessManager> network,
|
||||
const QUrl &sourceUrl,
|
||||
const QUrl &solderUrl,
|
||||
const QString &pack,
|
||||
const QString &version,
|
||||
const QString &minecraftVersion
|
||||
) {
|
||||
m_sourceUrl = sourceUrl;
|
||||
m_minecraftVersion = minecraftVersion;
|
||||
m_solderUrl = solderUrl;
|
||||
m_pack = pack;
|
||||
m_version = version;
|
||||
m_network = network;
|
||||
m_minecraftVersion = minecraftVersion;
|
||||
}
|
||||
|
||||
bool Technic::SolderPackInstallTask::abort() {
|
||||
@ -41,34 +68,12 @@ bool Technic::SolderPackInstallTask::abort() {
|
||||
|
||||
void Technic::SolderPackInstallTask::executeTask()
|
||||
{
|
||||
setStatus(tr("Finding recommended version:\n%1").arg(m_sourceUrl.toString()));
|
||||
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();
|
||||
}
|
||||
setStatus(tr("Resolving modpack files"));
|
||||
|
||||
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->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();
|
||||
connect(job, &NetJob::succeeded, this, &Technic::SolderPackInstallTask::fileListSucceeded);
|
||||
connect(job, &NetJob::failed, this, &Technic::SolderPackInstallTask::downloadFailed);
|
||||
@ -77,38 +82,47 @@ void Technic::SolderPackInstallTask::versionSucceeded()
|
||||
|
||||
void Technic::SolderPackInstallTask::fileListSucceeded()
|
||||
{
|
||||
setStatus(tr("Downloading modpack:"));
|
||||
QStringList modUrls;
|
||||
try
|
||||
{
|
||||
QJsonDocument doc = Json::requireDocument(m_response);
|
||||
QJsonObject obj = Json::requireObject(doc);
|
||||
QString minecraftVersion = Json::ensureString(obj, "minecraft", QString(), "__placeholder__");
|
||||
if (!minecraftVersion.isEmpty())
|
||||
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'"));
|
||||
}
|
||||
setStatus(tr("Downloading modpack"));
|
||||
|
||||
QJsonParseError parse_error {};
|
||||
QJsonDocument doc = QJsonDocument::fromJson(m_response, &parse_error);
|
||||
if (parse_error.error != QJsonParseError::NoError) {
|
||||
qWarning() << "Error while parsing JSON response from Solder at " << parse_error.offset << " reason: " << parse_error.errorString();
|
||||
qWarning() << m_response;
|
||||
return;
|
||||
}
|
||||
catch (const JSONValidationError &e)
|
||||
{
|
||||
emitFailed(e.cause());
|
||||
auto obj = doc.object();
|
||||
|
||||
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();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!build.minecraft.isEmpty())
|
||||
m_minecraftVersion = build.minecraft;
|
||||
|
||||
m_filesNetJob = new NetJob(tr("Downloading modpack"), m_network);
|
||||
|
||||
int i = 0;
|
||||
for (auto &modUrl: modUrls)
|
||||
{
|
||||
for (const auto &mod : build.mods) {
|
||||
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++;
|
||||
}
|
||||
|
||||
m_modCount = modUrls.size();
|
||||
m_modCount = build.mods.size();
|
||||
|
||||
connect(m_filesNetJob.get(), &NetJob::succeeded, this, &Technic::SolderPackInstallTask::downloadSucceeded);
|
||||
connect(m_filesNetJob.get(), &NetJob::progress, this, &Technic::SolderPackInstallTask::downloadProgressChanged);
|
||||
@ -206,6 +220,5 @@ void Technic::SolderPackInstallTask::extractFinished()
|
||||
void Technic::SolderPackInstallTask::extractAborted()
|
||||
{
|
||||
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");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* 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.
|
||||
*
|
||||
* 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
|
||||
* 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.
|
||||
* 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
|
||||
@ -27,7 +47,7 @@ namespace Technic
|
||||
{
|
||||
Q_OBJECT
|
||||
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 abort() override;
|
||||
@ -37,7 +57,6 @@ namespace Technic
|
||||
virtual void executeTask() override;
|
||||
|
||||
private slots:
|
||||
void versionSucceeded();
|
||||
void fileListSucceeded();
|
||||
void downloadSucceeded();
|
||||
void downloadFailed(QString reason);
|
||||
@ -51,7 +70,9 @@ namespace Technic
|
||||
shared_qobject_ptr<QNetworkAccessManager> m_network;
|
||||
|
||||
NetJob::Ptr m_filesNetJob;
|
||||
QUrl m_sourceUrl;
|
||||
QUrl m_solderUrl;
|
||||
QString m_pack;
|
||||
QString m_version;
|
||||
QString m_minecraftVersion;
|
||||
QByteArray m_response;
|
||||
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