Compare commits
94 Commits
7fb4c8358b
...
ebbfaf8713
Author | SHA1 | Date | |
---|---|---|---|
ebbfaf8713 | |||
8e6c20dc99 | |||
daa73a756a | |||
94f3d61302 | |||
|
b2c9183c41 | ||
|
a3e64b6f1b | ||
|
a13d3f4a38 | ||
|
392822ec7a | ||
|
cc85b44ff2 | ||
|
bfe7e3afed | ||
|
75b1eaed0c | ||
|
51adc79fe1 | ||
|
c00f476312 | ||
|
ca4f8ac546 | ||
|
17eca6d497 | ||
|
ffbb8aba85 | ||
|
d61ebca9bc | ||
|
a951bd1c3e | ||
|
eb03d0a2a2 | ||
|
ca635f7d3d | ||
|
c11f5e990e | ||
|
6bfa4b1e0f | ||
|
1821081521 | ||
|
1ff4c683b2 | ||
|
d02847271e | ||
|
876f12f71b | ||
|
979d33ab83 | ||
|
e71284c812 | ||
|
64b7562919 | ||
|
ef713cf414 | ||
|
413dd73a73 | ||
|
53e1f96bea | ||
|
66a98380d0 | ||
|
466f9c3ec7 | ||
|
d53a539764 | ||
|
37fc2d5d79 | ||
|
e6253c8091 | ||
|
44a5130926 | ||
|
d8044ababe | ||
|
32b526b729 | ||
|
7f6515dbe4 | ||
|
a39390b8b4 | ||
|
63a3dd1919 | ||
|
7a5a4de6ea | ||
|
664d4e701e | ||
|
a4ba8d8288 | ||
|
392bf7a97b | ||
|
34687049b1 | ||
|
0f581efda5 | ||
|
9337ec6706 | ||
|
5bcb6962c4 | ||
|
0617b43190 | ||
|
ed28234cfb | ||
|
9c4455ca03 | ||
|
9ec7837275 | ||
|
549b5a6488 | ||
|
2652f37453 | ||
|
0eaff22145 | ||
|
2f5393b9d0 | ||
|
e28480a8e4 | ||
|
fcef6321fc | ||
|
35e792c5de | ||
|
c08b632b51 | ||
|
cac800bfd8 | ||
|
2eb8173951 | ||
|
75abf2c124 | ||
|
d40a18d6c5 | ||
|
a74fdc588c | ||
|
25b0ec6eff | ||
|
04e8982d33 | ||
|
58bd449db8 | ||
|
c984e9b5d6 | ||
|
ddd319369a | ||
|
de3c336213 | ||
|
6e94e9bff1 | ||
|
93b8d9e454 | ||
|
6d46081864 | ||
|
765fb42a7e | ||
|
ecade0f510 | ||
|
23e5773094 | ||
|
1b9b1ccf31 | ||
|
121f6b2a4e | ||
|
7403918c89 | ||
|
ba6a8d1469 | ||
|
11f97a78fe | ||
|
761f20a3e2 | ||
|
a6f2136940 | ||
|
763627ee65 | ||
|
31652097e0 | ||
|
2782588af7 | ||
|
03923c9e87 | ||
|
4cfaaefca4 | ||
|
0170e8b177 | ||
|
050ee33132 |
1
.github/FUNDING.yml
vendored
@ -1 +0,0 @@
|
||||
open_collective: prismlauncher
|
14
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
@ -5,8 +5,6 @@ body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
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 [Prism Launcher wiki](https://prismlauncher.org/wiki/) and it has not answered your question.
|
||||
* Your bug is not caused by Minecraft or any mods you have installed.
|
||||
@ -25,15 +23,15 @@ body:
|
||||
- Other
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Version of Prism Launcher
|
||||
description: The version of Prism Launcher used in the bug report.
|
||||
placeholder: Prism Launcher 5.0
|
||||
label: Version of PollyMC
|
||||
description: The version of PollyMC used in the bug report.
|
||||
placeholder: PollyMC 5.1
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Version of Qt
|
||||
description: The version of Qt used in the bug report. You can find it in Help -> About Prism Launcher -> About Qt.
|
||||
description: The version of Qt used in the bug report. You can find it in Help -> About PollyMC -> About Qt.
|
||||
placeholder: Qt 6.3.0
|
||||
validations:
|
||||
required: true
|
||||
@ -41,14 +39,14 @@ body:
|
||||
attributes:
|
||||
label: Description of bug
|
||||
description: What did you expect to happen, what happened, and why is it incorrect?
|
||||
placeholder: The cat button should show a cat, but it showed a dog instead!
|
||||
placeholder: The parrot button should show a parrot, but it showed a cat instead!
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Steps to reproduce
|
||||
description: A bulleted list, or an exported instance if relevant.
|
||||
placeholder: "* Press the cat button"
|
||||
placeholder: "* Press the parrot button"
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
|
4
.github/ISSUE_TEMPLATE/config.yml
vendored
@ -1,5 +1 @@
|
||||
blank_issues_enabled: true
|
||||
contact_links:
|
||||
- name: Prism Launcher Matrix Support Room
|
||||
url: https://matrix.to/#/#prism-support:matrix.org
|
||||
about: Please ask for support here before opening an issue.
|
||||
|
16
.github/ISSUE_TEMPLATE/rfc.yml
vendored
@ -6,38 +6,38 @@ body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
### Use this form to suggest a larger change for Prism Launcher.
|
||||
### Use this form to suggest a larger change for PollyMC.
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Goal
|
||||
description: Short description, 1-2 sentences.
|
||||
placeholder: Remove the cat from the launcher.
|
||||
placeholder: Remove the parrot from the launcher.
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Motivation
|
||||
description: |
|
||||
Introduce the topic. If this is a not-well-known section of Prism Launcher, a detailed explanation of the background is recommended.
|
||||
Introduce the topic. If this is a not-well-known section of PollyMC, a detailed explanation of the background is recommended.
|
||||
Some example points of discussion:
|
||||
- What specific problems are you facing right now that you're trying to address?
|
||||
- Are there any previous discussions? Link to them and summarize them (don't force your readers to read them though!).
|
||||
- Is there any precedent set by other software? If so, link to resources.
|
||||
placeholder: I don't like cats. I think many users also don't like cats.
|
||||
placeholder: I don't like parrots. I think many users also don't like parrots.
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Specification
|
||||
description: A concrete, thorough explanation of what is being planned.
|
||||
placeholder: Remove the cat button and all references to the cat from the codebase. Including resource files.
|
||||
placeholder: Remove the parrot button and all references to the parrot from the codebase. Including resource files.
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Drawbacks
|
||||
description: Carefully consider every possible objection and issue with your proposal. This section should be updated as feedback comes in from discussion.
|
||||
placeholder: Some users might like cats.
|
||||
placeholder: Some users might like parrots.
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
@ -47,14 +47,14 @@ body:
|
||||
Are there any portions of your proposal which need to be discussed with the community before the RFC can proceed?
|
||||
Be careful here -- an RFC with a lot of remaining questions is likely to be stalled.
|
||||
If your RFC is mostly unresolved questions and not too much substance, it may not be ready.
|
||||
placeholder: Do a lot of users care about the cat?
|
||||
placeholder: Do a lot of users care about the parrot?
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Alternatives Considered
|
||||
description: A list of alternatives, that have been considered and offer equal or similar features to the proposed change.
|
||||
placeholder: Maybe the cat could be replaced with an axolotl?
|
||||
placeholder: Maybe the parrot could be replaced with a dog?
|
||||
validations:
|
||||
required: true
|
||||
- type: checkboxes
|
||||
|
12
.github/ISSUE_TEMPLATE/suggestion.yml
vendored
@ -5,26 +5,26 @@ body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
### Use this form to suggest a feature for Prism Launcher.
|
||||
### Use this form to suggest a feature for PollyMC.
|
||||
- type: input
|
||||
attributes:
|
||||
label: Role
|
||||
description: In what way do you use Prism Launcher that needs this feature?
|
||||
description: In what way do you use PollyMC that needs this feature?
|
||||
placeholder: I play modded Minecraft.
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
attributes:
|
||||
label: Suggestion
|
||||
description: What do you want Prism Launcher to do?
|
||||
placeholder: I want the cat button to meow.
|
||||
description: What do you want PollyMC to do?
|
||||
placeholder: I want the parrot button to squawk.
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
attributes:
|
||||
label: Benefit
|
||||
description: Why do you need Prism Launcher to do this?
|
||||
placeholder: so that I can always hear a cat when I need to.
|
||||
description: Why do you need PollyMC to do this?
|
||||
placeholder: so that I can always hear a parrot when I need to.
|
||||
validations:
|
||||
required: true
|
||||
- type: checkboxes
|
||||
|
103
.github/workflows/build.yml
vendored
@ -86,7 +86,7 @@ jobs:
|
||||
|
||||
- os: macos-12
|
||||
name: macOS
|
||||
macosx_deployment_target: 10.15
|
||||
macosx_deployment_target: 11.0
|
||||
qt_ver: 6
|
||||
qt_host: mac
|
||||
qt_arch: ''
|
||||
@ -346,10 +346,9 @@ jobs:
|
||||
cmake --install ${{ env.BUILD_DIR }}
|
||||
|
||||
cd ${{ env.INSTALL_DIR }}
|
||||
chmod +x "PrismLauncher.app/Contents/MacOS/prismlauncher"
|
||||
sudo codesign --sign - --deep --force --entitlements "../program_info/App.entitlements" --options runtime "PrismLauncher.app/Contents/MacOS/prismlauncher"
|
||||
mv "PrismLauncher.app" "Prism Launcher.app"
|
||||
tar -czf ../PrismLauncher.tar.gz *
|
||||
chmod +x "PollyMC.app/Contents/MacOS/pollymc"
|
||||
sudo codesign --sign - --deep --force --entitlements "../program_info/App.entitlements" --options runtime "PollyMC.app/Contents/MacOS/pollymc"
|
||||
tar -czf ../PollyMC.tar.gz *
|
||||
|
||||
- name: Make Sparkle signature (macOS)
|
||||
if: matrix.name == 'macOS'
|
||||
@ -357,7 +356,7 @@ jobs:
|
||||
if [ '${{ secrets.SPARKLE_ED25519_KEY }}' != '' ]; then
|
||||
brew install openssl@3
|
||||
echo '${{ secrets.SPARKLE_ED25519_KEY }}' > ed25519-priv.pem
|
||||
signature=$(/usr/local/opt/openssl@3/bin/openssl pkeyutl -sign -rawin -in ${{ github.workspace }}/PrismLauncher.tar.gz -inkey ed25519-priv.pem | openssl base64 | tr -d \\n)
|
||||
signature=$(/usr/local/opt/openssl@3/bin/openssl pkeyutl -sign -rawin -in ${{ github.workspace }}/PollyMC.tar.gz -inkey ed25519-priv.pem | openssl base64 | tr -d \\n)
|
||||
rm ed25519-priv.pem
|
||||
cat >> $GITHUB_STEP_SUMMARY << EOF
|
||||
### Artifact Information :information_source:
|
||||
@ -386,8 +385,8 @@ jobs:
|
||||
cd ${{ env.INSTALL_DIR }}
|
||||
if ("${{ matrix.qt_ver }}" -eq "5")
|
||||
{
|
||||
Copy-Item D:/a/PrismLauncher/Qt/Tools/OpenSSL/Win_x86/bin/libcrypto-1_1.dll -Destination libcrypto-1_1.dll
|
||||
Copy-Item D:/a/PrismLauncher/Qt/Tools/OpenSSL/Win_x86/bin/libssl-1_1.dll -Destination libssl-1_1.dll
|
||||
Copy-Item D:/a/PollyMC/Qt/Tools/OpenSSL/Win_x86/bin/libcrypto-1_1.dll -Destination libcrypto-1_1.dll
|
||||
Copy-Item D:/a/PollyMC/Qt/Tools/OpenSSL/Win_x86/bin/libssl-1_1.dll -Destination libssl-1_1.dll
|
||||
}
|
||||
cd ${{ github.workspace }}
|
||||
|
||||
@ -406,7 +405,7 @@ jobs:
|
||||
if (Get-Content ./codesign.pfx){
|
||||
cd ${{ env.INSTALL_DIR }}
|
||||
# We ship the exact same executable for portable and non-portable editions, so signing just once is fine
|
||||
SignTool sign /fd sha256 /td sha256 /f ../codesign.pfx /p '${{ secrets.WINDOWS_CODESIGN_PASSWORD }}' /tr http://timestamp.digicert.com prismlauncher.exe prismlauncher_filelink.exe
|
||||
SignTool sign /fd sha256 /td sha256 /f ../codesign.pfx /p '${{ secrets.WINDOWS_CODESIGN_PASSWORD }}' /tr http://timestamp.digicert.com pollymc.exe pollymc_filelink.exe
|
||||
} else {
|
||||
":warning: Skipped code signing for Windows, as certificate was not present." >> $env:GITHUB_STEP_SUMMARY
|
||||
}
|
||||
@ -437,7 +436,7 @@ jobs:
|
||||
if: runner.os == 'Windows'
|
||||
run: |
|
||||
if (Get-Content ./codesign.pfx){
|
||||
SignTool sign /fd sha256 /td sha256 /f codesign.pfx /p '${{ secrets.WINDOWS_CODESIGN_PASSWORD }}' /tr http://timestamp.digicert.com PrismLauncher-Setup.exe
|
||||
SignTool sign /fd sha256 /td sha256 /f codesign.pfx /p '${{ secrets.WINDOWS_CODESIGN_PASSWORD }}' /tr http://timestamp.digicert.com PollyMC-Setup.exe
|
||||
} else {
|
||||
":warning: Skipped code signing for Windows, as certificate was not present." >> $env:GITHUB_STEP_SUMMARY
|
||||
}
|
||||
@ -449,7 +448,7 @@ jobs:
|
||||
for l in $(find ${{ env.INSTALL_DIR }} -type f); do l=${l#$(pwd)/}; l=${l#${{ env.INSTALL_DIR }}/}; l=${l#./}; echo $l; done > ${{ env.INSTALL_DIR }}/manifest.txt
|
||||
|
||||
cd ${{ env.INSTALL_DIR }}
|
||||
tar --owner root --group root -czf ../PrismLauncher.tar.gz *
|
||||
tar --owner root --group root -czf ../PollyMC.tar.gz *
|
||||
|
||||
- name: Package (Linux, portable)
|
||||
if: runner.os == 'Linux'
|
||||
@ -460,7 +459,7 @@ jobs:
|
||||
|
||||
|
||||
cd ${{ env.INSTALL_PORTABLE_DIR }}
|
||||
tar -czf ../PrismLauncher-portable.tar.gz *
|
||||
tar -czf ../PollyMC-portable.tar.gz *
|
||||
|
||||
- name: Package AppImage (Linux)
|
||||
if: runner.os == 'Linux' && matrix.qt_ver != 5
|
||||
@ -468,7 +467,7 @@ jobs:
|
||||
run: |
|
||||
cmake --install ${{ env.BUILD_DIR }} --prefix ${{ env.INSTALL_APPIMAGE_DIR }}/usr
|
||||
|
||||
export OUTPUT="PrismLauncher-${{ runner.os }}-${{ env.VERSION }}-${{ inputs.build_type }}-x86_64.AppImage"
|
||||
export OUTPUT="PollyMC-${{ runner.os }}-${{ env.VERSION }}-${{ inputs.build_type }}-x86_64.AppImage"
|
||||
|
||||
chmod +x linuxdeploy-*.AppImage
|
||||
|
||||
@ -479,7 +478,7 @@ jobs:
|
||||
|
||||
cp -r ${{ github.workspace }}/JREs/jre17/* ${{ env.INSTALL_APPIMAGE_DIR }}/usr/lib/jvm/java-17-openjdk
|
||||
|
||||
cp -r /home/runner/work/PrismLauncher/Qt/${{ matrix.qt_version }}/gcc_64/plugins/iconengines/* ${{ env.INSTALL_APPIMAGE_DIR }}/usr/plugins/iconengines
|
||||
cp -r /home/runner/work/PollyMC/Qt/${{ matrix.qt_version }}/gcc_64/plugins/iconengines/* ${{ env.INSTALL_APPIMAGE_DIR }}/usr/plugins/iconengines
|
||||
|
||||
cp /usr/lib/x86_64-linux-gnu/libcrypto.so.1.1 ${{ env.INSTALL_APPIMAGE_DIR }}/usr/lib/
|
||||
cp /usr/lib/x86_64-linux-gnu/libssl.so.1.1 ${{ env.INSTALL_APPIMAGE_DIR }}//usr/lib/
|
||||
@ -491,7 +490,7 @@ jobs:
|
||||
LD_LIBRARY_PATH="${LD_LIBRARY_PATH}:${{ env.INSTALL_APPIMAGE_DIR }}/usr/lib/jvm/java-17-openjdk/lib"
|
||||
export LD_LIBRARY_PATH
|
||||
|
||||
./linuxdeploy-x86_64.AppImage --appdir ${{ env.INSTALL_APPIMAGE_DIR }} --output appimage --plugin qt -i ${{ env.INSTALL_APPIMAGE_DIR }}/usr/share/icons/hicolor/scalable/apps/org.prismlauncher.PrismLauncher.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.fn2006.PollyMC.svg
|
||||
|
||||
##
|
||||
# UPLOAD BUILDS
|
||||
@ -501,64 +500,64 @@ jobs:
|
||||
if: runner.os == 'macOS'
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: PrismLauncher-${{ matrix.name }}-${{ env.VERSION }}-${{ inputs.build_type }}
|
||||
path: PrismLauncher.tar.gz
|
||||
name: PollyMC-${{ matrix.name }}-${{ env.VERSION }}-${{ inputs.build_type }}
|
||||
path: PollyMC.tar.gz
|
||||
|
||||
- name: Upload binary zip (Windows)
|
||||
if: runner.os == 'Windows'
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: PrismLauncher-${{ matrix.name }}-${{ env.VERSION }}-${{ inputs.build_type }}
|
||||
name: PollyMC-${{ 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: PrismLauncher-${{ matrix.name }}-Portable-${{ env.VERSION }}-${{ inputs.build_type }}
|
||||
name: PollyMC-${{ matrix.name }}-Portable-${{ env.VERSION }}-${{ inputs.build_type }}
|
||||
path: ${{ env.INSTALL_PORTABLE_DIR }}/**
|
||||
|
||||
- name: Upload installer (Windows)
|
||||
if: runner.os == 'Windows'
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: PrismLauncher-${{ matrix.name }}-Setup-${{ env.VERSION }}-${{ inputs.build_type }}
|
||||
path: PrismLauncher-Setup.exe
|
||||
name: PollyMC-${{ matrix.name }}-Setup-${{ env.VERSION }}-${{ inputs.build_type }}
|
||||
path: PollyMC-Setup.exe
|
||||
|
||||
- name: Upload binary tarball (Linux, Qt 5)
|
||||
if: runner.os == 'Linux' && matrix.qt_ver != 6
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: PrismLauncher-${{ runner.os }}-${{ env.VERSION }}-${{ inputs.build_type }}
|
||||
path: PrismLauncher.tar.gz
|
||||
name: PollyMC-${{ runner.os }}-${{ env.VERSION }}-${{ inputs.build_type }}
|
||||
path: PollyMC.tar.gz
|
||||
|
||||
- name: Upload binary tarball (Linux, portable, Qt 5)
|
||||
if: runner.os == 'Linux' && matrix.qt_ver != 6
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: PrismLauncher-${{ runner.os }}-Portable-${{ env.VERSION }}-${{ inputs.build_type }}
|
||||
path: PrismLauncher-portable.tar.gz
|
||||
name: PollyMC-${{ runner.os }}-Portable-${{ env.VERSION }}-${{ inputs.build_type }}
|
||||
path: PollyMC-portable.tar.gz
|
||||
|
||||
- name: Upload binary tarball (Linux, Qt 6)
|
||||
if: runner.os == 'Linux' && matrix.qt_ver !=5
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: PrismLauncher-${{ runner.os }}-Qt6-${{ env.VERSION }}-${{ inputs.build_type }}
|
||||
path: PrismLauncher.tar.gz
|
||||
name: PollyMC-${{ runner.os }}-Qt6-${{ env.VERSION }}-${{ inputs.build_type }}
|
||||
path: PollyMC.tar.gz
|
||||
|
||||
- name: Upload binary tarball (Linux, portable, Qt 6)
|
||||
if: runner.os == 'Linux' && matrix.qt_ver != 5
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: PrismLauncher-${{ runner.os }}-Qt6-Portable-${{ env.VERSION }}-${{ inputs.build_type }}
|
||||
path: PrismLauncher-portable.tar.gz
|
||||
name: PollyMC-${{ runner.os }}-Qt6-Portable-${{ env.VERSION }}-${{ inputs.build_type }}
|
||||
path: PollyMC-portable.tar.gz
|
||||
|
||||
- name: Upload AppImage (Linux)
|
||||
if: runner.os == 'Linux' && matrix.qt_ver != 5
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: PrismLauncher-${{ runner.os }}-${{ env.VERSION }}-${{ inputs.build_type }}-x86_64.AppImage
|
||||
path: PrismLauncher-${{ runner.os }}-${{ env.VERSION }}-${{ inputs.build_type }}-x86_64.AppImage
|
||||
name: PollyMC-${{ runner.os }}-${{ env.VERSION }}-${{ inputs.build_type }}-x86_64.AppImage
|
||||
path: PollyMC-${{ runner.os }}-${{ env.VERSION }}-${{ inputs.build_type }}-x86_64.AppImage
|
||||
|
||||
- name: ccache stats (Windows MinGW-w64)
|
||||
if: runner.os == 'Windows' && matrix.msystem != ''
|
||||
@ -574,42 +573,18 @@ jobs:
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
if: inputs.build_type == 'Debug'
|
||||
if: inputs.build_type == 'Release'
|
||||
with:
|
||||
submodules: 'true'
|
||||
- name: Build Flatpak (Linux)
|
||||
if: inputs.build_type == 'Debug'
|
||||
if: inputs.build_type == 'Release'
|
||||
uses: flatpak/flatpak-github-actions/flatpak-builder@v6
|
||||
with:
|
||||
bundle: "Prism Launcher.flatpak"
|
||||
manifest-path: flatpak/org.prismlauncher.PrismLauncher.yml
|
||||
|
||||
nix:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
package:
|
||||
- prismlauncher
|
||||
- prismlauncher-qt5
|
||||
steps:
|
||||
- name: Clone repository
|
||||
if: inputs.build_type == 'Debug'
|
||||
uses: actions/checkout@v3
|
||||
bundle: "PollyMC.flatpak"
|
||||
manifest-path: flatpak/org.fn2006.PollyMC.yml
|
||||
- name: Upload Flatpak (Linux)
|
||||
if: runner.os == 'Linux' && matrix.qt_ver != 5
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
submodules: 'true'
|
||||
- name: Install nix
|
||||
if: inputs.build_type == 'Debug'
|
||||
uses: cachix/install-nix-action@v21
|
||||
with:
|
||||
install_url: https://nixos.org/nix/install
|
||||
extra_nix_config: |
|
||||
auto-optimise-store = true
|
||||
experimental-features = nix-command flakes
|
||||
- uses: cachix/cachix-action@v12
|
||||
if: inputs.build_type == 'Debug'
|
||||
with:
|
||||
name: prismlauncher
|
||||
authToken: '${{ secrets.CACHIX_AUTH_TOKEN }}'
|
||||
- name: Build
|
||||
if: inputs.build_type == 'Debug'
|
||||
run: nix build .#${{ matrix.package }} --print-build-logs
|
||||
name: PollyMC-${{ env.VERSION }}-x86_64.flatpak
|
||||
path: PollyMC.flatpak
|
||||
|
2
.github/workflows/trigger_builds.yml
vendored
@ -10,7 +10,6 @@ on:
|
||||
- 'flake.lock'
|
||||
- 'packages/**'
|
||||
- '.github/ISSUE_TEMPLATE/**'
|
||||
- '.markdownlint**'
|
||||
pull_request:
|
||||
paths-ignore:
|
||||
- '**.md'
|
||||
@ -18,7 +17,6 @@ on:
|
||||
- 'flake.lock'
|
||||
- 'packages/**'
|
||||
- '.github/ISSUE_TEMPLATE/**'
|
||||
- '.markdownlint**'
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
|
75
.github/workflows/trigger_release.yml
vendored
@ -29,7 +29,7 @@ jobs:
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
submodules: 'true'
|
||||
path: 'PrismLauncher-source'
|
||||
path: 'PollyMC-source'
|
||||
- name: Download artifacts
|
||||
uses: actions/download-artifact@v3
|
||||
- name: Grab and store version
|
||||
@ -38,39 +38,39 @@ jobs:
|
||||
echo "VERSION=$tag_name" >> $GITHUB_ENV
|
||||
- name: Package artifacts properly
|
||||
run: |
|
||||
mv ${{ github.workspace }}/PrismLauncher-source PrismLauncher-${{ env.VERSION }}
|
||||
mv PrismLauncher-Linux-Qt6-Portable*/PrismLauncher-portable.tar.gz PrismLauncher-Linux-Qt6-Portable-${{ env.VERSION }}.tar.gz
|
||||
mv PrismLauncher-Linux-Qt6*/PrismLauncher.tar.gz PrismLauncher-Linux-Qt6-${{ env.VERSION }}.tar.gz
|
||||
mv PrismLauncher-Linux-Portable*/PrismLauncher-portable.tar.gz PrismLauncher-Linux-Portable-${{ env.VERSION }}.tar.gz
|
||||
mv PrismLauncher-Linux*/PrismLauncher.tar.gz PrismLauncher-Linux-${{ env.VERSION }}.tar.gz
|
||||
mv PrismLauncher-*.AppImage/PrismLauncher-*.AppImage PrismLauncher-Linux-${{ env.VERSION }}-x86_64.AppImage
|
||||
mv PrismLauncher-macOS-Legacy*/PrismLauncher.tar.gz PrismLauncher-macOS-Legacy-${{ env.VERSION }}.tar.gz
|
||||
mv PrismLauncher-macOS*/PrismLauncher.tar.gz PrismLauncher-macOS-${{ env.VERSION }}.tar.gz
|
||||
mv ${{ github.workspace }}/PollyMC-source PollyMC-${{ env.VERSION }}
|
||||
mv PollyMC-Linux-Qt6-Portable*/PollyMC-portable.tar.gz PollyMC-Linux-Qt6-Portable-${{ env.VERSION }}.tar.gz
|
||||
mv PollyMC-Linux-Qt6*/PollyMC.tar.gz PollyMC-Linux-Qt6-${{ env.VERSION }}.tar.gz
|
||||
mv PollyMC-Linux-Portable*/PollyMC-portable.tar.gz PollyMC-Linux-Portable-${{ env.VERSION }}.tar.gz
|
||||
mv PollyMC-Linux*/PollyMC.tar.gz PollyMC-Linux-${{ env.VERSION }}.tar.gz
|
||||
mv PollyMC-*.AppImage/PollyMC-*.AppImage PollyMC-Linux-${{ env.VERSION }}-x86_64.AppImage
|
||||
mv PollyMC-macOS-Legacy*/PollyMC.tar.gz PollyMC-macOS-Legacy-${{ env.VERSION }}.tar.gz
|
||||
mv PollyMC-macOS*/PollyMC.tar.gz PollyMC-macOS-${{ env.VERSION }}.tar.gz
|
||||
|
||||
tar -czf PrismLauncher-${{ env.VERSION }}.tar.gz PrismLauncher-${{ env.VERSION }}
|
||||
tar -czf PollyMC-${{ env.VERSION }}.tar.gz PollyMC-${{ env.VERSION }}
|
||||
|
||||
for d in PrismLauncher-Windows-MSVC*; do
|
||||
for d in PollyMC-Windows-MSVC*; do
|
||||
cd "${d}" || continue
|
||||
LEGACY="$(echo -n ${d} | grep -o Legacy || true)"
|
||||
ARM64="$(echo -n ${d} | grep -o arm64 || true)"
|
||||
INST="$(echo -n ${d} | grep -o Setup || true)"
|
||||
PORT="$(echo -n ${d} | grep -o Portable || true)"
|
||||
NAME="PrismLauncher-Windows-MSVC"
|
||||
NAME="PollyMC-Windows-MSVC"
|
||||
test -z "${LEGACY}" || NAME="${NAME}-Legacy"
|
||||
test -z "${ARM64}" || NAME="${NAME}-arm64"
|
||||
test -z "${PORT}" || NAME="${NAME}-Portable"
|
||||
test -z "${INST}" || mv PrismLauncher-*.exe ../${NAME}-Setup-${{ env.VERSION }}.exe
|
||||
test -z "${INST}" || mv PollyMC-*.exe ../${NAME}-Setup-${{ env.VERSION }}.exe
|
||||
test -n "${INST}" || zip -r -9 "../${NAME}-${{ env.VERSION }}.zip" *
|
||||
cd ..
|
||||
done
|
||||
|
||||
for d in PrismLauncher-Windows-MinGW-w64*; do
|
||||
for d in PollyMC-Windows-MinGW-w64*; do
|
||||
cd "${d}" || continue
|
||||
INST="$(echo -n ${d} | grep -o Setup || true)"
|
||||
PORT="$(echo -n ${d} | grep -o Portable || true)"
|
||||
NAME="PrismLauncher-Windows-MinGW-w64"
|
||||
NAME="PollyMC-Windows-MinGW-w64"
|
||||
test -z "${PORT}" || NAME="${NAME}-Portable"
|
||||
test -z "${INST}" || mv PrismLauncher-*.exe ../${NAME}-Setup-${{ env.VERSION }}.exe
|
||||
test -z "${INST}" || mv PollyMC-*.exe ../${NAME}-Setup-${{ env.VERSION }}.exe
|
||||
test -n "${INST}" || zip -r -9 "../${NAME}-${{ env.VERSION }}.zip" *
|
||||
cd ..
|
||||
done
|
||||
@ -82,27 +82,28 @@ jobs:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
tag_name: ${{ github.ref }}
|
||||
name: Prism Launcher ${{ env.VERSION }}
|
||||
name: PollyMC ${{ env.VERSION }}
|
||||
draft: true
|
||||
prerelease: false
|
||||
files: |
|
||||
PrismLauncher-Linux-${{ env.VERSION }}.tar.gz
|
||||
PrismLauncher-Linux-Portable-${{ env.VERSION }}.tar.gz
|
||||
PrismLauncher-Linux-${{ env.VERSION }}-x86_64.AppImage
|
||||
PrismLauncher-Linux-Qt6-${{ env.VERSION }}.tar.gz
|
||||
PrismLauncher-Linux-Qt6-Portable-${{ env.VERSION }}.tar.gz
|
||||
PrismLauncher-Windows-MinGW-w64-${{ env.VERSION }}.zip
|
||||
PrismLauncher-Windows-MinGW-w64-Portable-${{ env.VERSION }}.zip
|
||||
PrismLauncher-Windows-MinGW-w64-Setup-${{ env.VERSION }}.exe
|
||||
PrismLauncher-Windows-MSVC-Legacy-${{ env.VERSION }}.zip
|
||||
PrismLauncher-Windows-MSVC-Legacy-Portable-${{ env.VERSION }}.zip
|
||||
PrismLauncher-Windows-MSVC-Legacy-Setup-${{ env.VERSION }}.exe
|
||||
PrismLauncher-Windows-MSVC-arm64-${{ env.VERSION }}.zip
|
||||
PrismLauncher-Windows-MSVC-arm64-Portable-${{ env.VERSION }}.zip
|
||||
PrismLauncher-Windows-MSVC-arm64-Setup-${{ env.VERSION }}.exe
|
||||
PrismLauncher-Windows-MSVC-${{ env.VERSION }}.zip
|
||||
PrismLauncher-Windows-MSVC-Portable-${{ env.VERSION }}.zip
|
||||
PrismLauncher-Windows-MSVC-Setup-${{ env.VERSION }}.exe
|
||||
PrismLauncher-macOS-${{ env.VERSION }}.tar.gz
|
||||
PrismLauncher-macOS-Legacy-${{ env.VERSION }}.tar.gz
|
||||
PrismLauncher-${{ env.VERSION }}.tar.gz
|
||||
PollyMC-Linux-${{ env.VERSION }}.tar.gz
|
||||
PollyMC-Linux-Portable-${{ env.VERSION }}.tar.gz
|
||||
PollyMC-Linux-${{ env.VERSION }}-x86_64.AppImage
|
||||
PollyMC-Linux-Qt6-${{ env.VERSION }}.tar.gz
|
||||
PollyMC-Linux-Qt6-Portable-${{ env.VERSION }}.tar.gz
|
||||
PollyMC-Windows-MinGW-w64-${{ env.VERSION }}.zip
|
||||
PollyMC-Windows-MinGW-w64-Portable-${{ env.VERSION }}.zip
|
||||
PollyMC-Windows-MinGW-w64-Setup-${{ env.VERSION }}.exe
|
||||
PollyMC-Windows-MSVC-Legacy-${{ env.VERSION }}.zip
|
||||
PollyMC-Windows-MSVC-Legacy-Portable-${{ env.VERSION }}.zip
|
||||
PollyMC-Windows-MSVC-Legacy-Setup-${{ env.VERSION }}.exe
|
||||
PollyMC-Windows-MSVC-arm64-${{ env.VERSION }}.zip
|
||||
PollyMC-Windows-MSVC-arm64-Portable-${{ env.VERSION }}.zip
|
||||
PollyMC-Windows-MSVC-arm64-Setup-${{ env.VERSION }}.exe
|
||||
PollyMC-Windows-MSVC-${{ env.VERSION }}.zip
|
||||
PollyMC-Windows-MSVC-Portable-${{ env.VERSION }}.zip
|
||||
PollyMC-Windows-MSVC-Setup-${{ env.VERSION }}.exe
|
||||
PollyMC-macOS-${{ env.VERSION }}.tar.gz
|
||||
PollyMC-macOS-Legacy-${{ env.VERSION }}.tar.gz
|
||||
PollyMC-${{ env.VERSION }}.tar.gz
|
||||
|
||||
|
1
.gitignore
vendored
@ -8,6 +8,7 @@ resources/CMakeFiles
|
||||
html/
|
||||
|
||||
# Project Files
|
||||
*.orig
|
||||
*.pro.user
|
||||
CMakeLists.txt.user
|
||||
CMakeLists.txt.user.*
|
||||
|
@ -158,19 +158,19 @@ set(Launcher_META_URL "https://meta.prismlauncher.org/v1/" CACHE STRING "URL to
|
||||
set(Launcher_IMGUR_CLIENT_ID "5b97b0713fba4a3" CACHE STRING "Client ID you can get from Imgur when you register an application")
|
||||
|
||||
# Bug tracker URL
|
||||
set(Launcher_BUG_TRACKER_URL "https://github.com/PrismLauncher/PrismLauncher/issues" CACHE STRING "URL for the bug tracker.")
|
||||
set(Launcher_BUG_TRACKER_URL "https://github.com/fn2006/PollyMC/issues" CACHE STRING "URL for the bug tracker.")
|
||||
|
||||
# Translations Platform URL
|
||||
set(Launcher_TRANSLATIONS_URL "https://hosted.weblate.org/projects/prismlauncher/launcher/" CACHE STRING "URL for the translations platform.")
|
||||
|
||||
# Matrix Space
|
||||
set(Launcher_MATRIX_URL "https://prismlauncher.org/matrix" CACHE STRING "URL to the Matrix Space")
|
||||
set(Launcher_MATRIX_URL "" CACHE STRING "URL to the Matrix Space")
|
||||
|
||||
# Discord URL
|
||||
set(Launcher_DISCORD_URL "https://prismlauncher.org/discord" CACHE STRING "URL for the Discord guild.")
|
||||
set(Launcher_DISCORD_URL "" CACHE STRING "URL for the Discord guild.")
|
||||
|
||||
# Subreddit URL
|
||||
set(Launcher_SUBREDDIT_URL "https://prismlauncher.org/reddit" CACHE STRING "URL for the subreddit.")
|
||||
set(Launcher_SUBREDDIT_URL "" CACHE STRING "URL for the subreddit.")
|
||||
|
||||
# Builds
|
||||
set(Launcher_FORCE_BUNDLED_LIBS OFF CACHE BOOL "Prevent using system libraries, if they are available as submodules")
|
||||
@ -185,13 +185,13 @@ set(Launcher_QT_VERSION_MAJOR "6" CACHE STRING "Major Qt version to build agains
|
||||
|
||||
# By using this key in your builds you accept the terms of use laid down in
|
||||
# https://docs.microsoft.com/en-us/legal/microsoft-identity-platform/terms-of-use
|
||||
set(Launcher_MSA_CLIENT_ID "c36a9fb6-4f2a-41ff-90bd-ae7cc92031eb" CACHE STRING "Client ID you can get from Microsoft Identity Platform when you register an application")
|
||||
set(Launcher_MSA_CLIENT_ID "" CACHE STRING "Client ID you can get from Microsoft Identity Platform when you register an application")
|
||||
|
||||
# By using this key in your builds you accept the terms and conditions laid down in
|
||||
# https://support.curseforge.com/en/support/solutions/articles/9000207405-curse-forge-3rd-party-api-terms-and-conditions
|
||||
# NOTE: CurseForge requires you to change this if you make any kind of derivative work.
|
||||
# This key was issued specifically for Prism Launcher
|
||||
set(Launcher_CURSEFORGE_API_KEY "$2a$10$wuAJuNZuted3NORVmpgUC.m8sI.pv1tOPKZyBgLFGjxFp/br0lZCC" CACHE STRING "API key for the CurseForge platform")
|
||||
set(Launcher_CURSEFORGE_API_KEY "" CACHE STRING "API key for the CurseForge platform")
|
||||
set(Launcher_CURSEFORGE_API_KEY_API_URL "https://cf.polymc.org/api" CACHE STRING "URL to fetch the Curseforge API key from.")
|
||||
|
||||
|
||||
#### Check the current Git commit and branch
|
||||
@ -281,7 +281,7 @@ include(ECMQtDeclareLoggingCategory)
|
||||
|
||||
####################################### Program Info #######################################
|
||||
|
||||
set(Launcher_APP_BINARY_NAME "prismlauncher" CACHE STRING "Name of the Launcher binary")
|
||||
set(Launcher_APP_BINARY_NAME "pollymc" CACHE STRING "Name of the Launcher binary")
|
||||
add_subdirectory(program_info)
|
||||
|
||||
####################################### Install layout #######################################
|
||||
|
12
PollyMC.iml
Normal file
@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="JAVA_MODULE" version="4">
|
||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$/libraries/javacheck" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/libraries/launcher" isTestSource="false" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
</component>
|
||||
</module>
|
103
README.md
@ -1,103 +1,14 @@
|
||||
<p align="center">
|
||||
<picture>
|
||||
<source media="(prefers-color-scheme: dark)" srcset="/program_info/org.prismlauncher.PrismLauncher.logo-darkmode.svg">
|
||||
<source media="(prefers-color-scheme: light)" srcset="/program_info/org.prismlauncher.PrismLauncher.logo.svg">
|
||||
<img alt="Prism Launcher" src="/program_info/org.prismlauncher.PrismLauncher.logo.svg" width="40%">
|
||||
</picture>
|
||||
<img src="./program_info/pollymc-header-black.svg#gh-light-mode-only" alt="PollyMC logo" width="60%"/>
|
||||
<img src="./program_info/pollymc-header.svg#gh-dark-mode-only" alt="PollyMC logo" width="60%"/>
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
Prism Launcher is a custom launcher for Minecraft that allows you to easily manage multiple installations of Minecraft at once.<br />
|
||||
<br />This is a <b>fork</b> of the MultiMC Launcher and is <b>not</b> endorsed by it.
|
||||
</p>
|
||||
PollyMC is a **fork** of Prism Launcher that adds support for Ely.by accounts and allows you to play offline mode without an account
|
||||
|
||||
## Installation
|
||||
PollyMC is not endorsed by or affiliated with the Prism Launcher project.
|
||||
If you have any problems open an issue here, do not bug the Prism Launcher maintainers.
|
||||
|
||||
<a href="https://repology.org/project/prismlauncher/versions">
|
||||
<img src="https://repology.org/badge/vertical-allrepos/prismlauncher.svg" alt="Packaging status" align="right">
|
||||
</a>
|
||||
Binaries can be found in the [releases section](https://github.com/fn2006/PollyMC/releases/latest).
|
||||
|
||||
- All downloads and instructions for Prism Launcher can be found on our [Website](https://prismlauncher.org/download).
|
||||
- Last build status can be found in the [GitHub Actions](https://github.com/PrismLauncher/PrismLauncher/actions).
|
||||
To build this yourself, follow [the instructions on the Prism Launcher website](https://prismlauncher.org/wiki/development/build-instructions) but clone this repo instead.
|
||||
|
||||
### Development Builds
|
||||
|
||||
There are development builds available [here](https://github.com/PrismLauncher/PrismLauncher/actions). These have debug information in the binaries, so their file sizes are relatively larger.
|
||||
|
||||
Prebuilt Development builds are provided for **Linux**, **Windows** and **macOS**.
|
||||
|
||||
For **Arch**, **Debian**, **Fedora**, **OpenSUSE (Tumbleweed)** and **Gentoo**, respectively, you can use these packages for the latest development versions:
|
||||
|
||||
[![prismlauncher-git](https://img.shields.io/badge/aur-prismlauncher--git-1793D1?label=AUR&logo=archlinux&logoColor=white)](https://aur.archlinux.org/packages/prismlauncher-git) [![prismlauncher-git](https://img.shields.io/badge/aur-prismlauncher--qt5--git-1793D1?label=AUR&logo=archlinux&logoColor=white)](https://aur.archlinux.org/packages/prismlauncher-qt5-git) [![prismlauncher-git](https://img.shields.io/badge/mpr-prismlauncher--git-A80030?label=MPR&logo=debian&logoColor=white)](https://mpr.makedeb.org/packages/prismlauncher-git)<br />[![prismlauncher-nightly](https://img.shields.io/badge/copr-prismlauncher--nightly-51A2DA?label=COPR&logo=fedora&logoColor=white)](https://copr.fedorainfracloud.org/coprs/g3tchoo/prismlauncher/) [![prismlauncher-nightly](https://img.shields.io/badge/OBS-prismlauncher--nightly-3AB6A9?logo=opensuse&logoColor=white)](https://build.opensuse.org/project/show/home:getchoo) [![prismlauncher-9999](https://img.shields.io/badge/gentoo-prismlauncher--9999-4D4270?label=Gentoo&logo=gentoo&logoColor=white)](https://packages.gentoo.org/packages/games-action/prismlauncher)
|
||||
|
||||
These packages are also availiable to all the distributions based on the ones mentioned above.
|
||||
|
||||
## Community & Support
|
||||
|
||||
Feel free to create a GitHub issue if you find a bug or want to suggest a new feature. We have multiple community spaces where other community members can help you:
|
||||
|
||||
- **Our Discord server:**
|
||||
|
||||
[![Prism Launcher Discord server](https://discordapp.com/api/guilds/1031648380885147709/widget.png?style=banner3)](https://prismlauncher.org/discord)
|
||||
|
||||
- **Our Matrix space:**
|
||||
|
||||
[![PrismLauncher Space](https://img.shields.io/matrix/prismlauncher:matrix.org?style=for-the-badge&label=Matrix%20Space&logo=matrix&color=purple)](https://prismlauncher.org/matrix)
|
||||
|
||||
- **Our Subreddit:**
|
||||
|
||||
[![r/PrismLauncher](https://img.shields.io/reddit/subreddit-subscribers/prismlauncher?style=for-the-badge&logo=reddit)](https://prismlauncher.org/reddit)
|
||||
|
||||
## Translations
|
||||
|
||||
The translation effort for PrismLauncher is hosted on [Weblate](https://hosted.weblate.org/projects/prismlauncher/launcher/) and information about translating Prism Launcher is available at <https://github.com/PrismLauncher/Translations>
|
||||
|
||||
## Building
|
||||
|
||||
If you want to build Prism Launcher yourself, check the [Build Instructions](https://prismlauncher.org/wiki/development/build-instructions/).
|
||||
|
||||
## Sponsors & Partners
|
||||
|
||||
We thank all the wonderful backers over at Open Collective! Support Prism Launcher by [becoming a backer](https://opencollective.com/prismlauncher).
|
||||
|
||||
[![OpenCollective Backers](https://opencollective.com/prismlauncher/backers.svg?width=890&limit=1000)](https://opencollective.com/prismlauncher#backers)
|
||||
|
||||
Thanks to JetBrains for providing us a few licenses for all their products, as part of their [Open Source program](https://www.jetbrains.com/opensource/).
|
||||
|
||||
[![JetBrains](https://resources.jetbrains.com/storage/products/company/brand/logos/jb_beam.svg)](https://www.jetbrains.com/opensource/)
|
||||
|
||||
Thanks to Weblate for hosting our translation efforts.
|
||||
|
||||
<a href="https://hosted.weblate.org/engage/prismlauncher/">
|
||||
<img src="https://hosted.weblate.org/widgets/prismlauncher/-/open-graph.png" alt="Translation status" width="300" />
|
||||
</a>
|
||||
|
||||
Thanks to Netlify for providing us their excellent web services, as part of their [Open Source program](https://www.netlify.com/open-source/).
|
||||
|
||||
<a href="https://www.netlify.com"> <img src="https://www.netlify.com/v3/img/components/netlify-color-accent.svg" alt="Deploys by Netlify" /> </a>
|
||||
|
||||
Thanks to the awesome people over at [MacStadium](https://www.macstadium.com/), for providing M1-Macs for development purposes!
|
||||
|
||||
<a href="https://www.macstadium.com"><img src="https://uploads-ssl.webflow.com/5ac3c046c82724970fc60918/5c019d917bba312af7553b49_MacStadium-developerlogo.png" alt="Powered by MacStadium" width="300"></a>
|
||||
|
||||
## Forking/Redistributing/Custom builds policy
|
||||
|
||||
We don't care what you do with your fork/custom build as long as you follow the terms of the [license](LICENSE) (this is a legal responsibility), and if you made code changes rather than just packaging a custom build, please do the following as a basic courtesy:
|
||||
|
||||
- Make it clear that your fork is not PrismLauncher and is not endorsed by or affiliated with the PrismLauncher project (<https://prismlauncher.org>).
|
||||
- Go through [CMakeLists.txt](CMakeLists.txt) and change PrismLauncher's API keys to your own or set them to empty strings (`""`) to disable them (this way the program will still compile but the functionality requiring those keys will be disabled).
|
||||
|
||||
If you have any questions or want any clarification on the above conditions please make an issue and ask us.
|
||||
|
||||
Be aware that if you build this software without removing the provided API keys in [CMakeLists.txt](CMakeLists.txt) you are accepting the following terms and conditions:
|
||||
|
||||
- [Microsoft Identity Platform Terms of Use](https://docs.microsoft.com/en-us/legal/microsoft-identity-platform/terms-of-use)
|
||||
- [CurseForge 3rd Party API Terms and Conditions](https://support.curseforge.com/en/support/solutions/articles/9000207405-curse-forge-3rd-party-api-terms-and-conditions)
|
||||
|
||||
If you do not agree with these terms and conditions, then remove the associated API keys from the [CMakeLists.txt](CMakeLists.txt) file by setting them to an empty string (`""`).
|
||||
|
||||
## License [![https://github.com/PrismLauncher/PrismLauncher/blob/develop/LICENSE](https://img.shields.io/github/license/PrismLauncher/PrismLauncher?label=License&logo=gnu&color=C4282D)](LICENSE)
|
||||
|
||||
All launcher code is available under the GPL-3.0-only license.
|
||||
|
||||
The logo and related assets are under the CC BY-SA 4.0 license.
|
||||
|
@ -2,6 +2,7 @@
|
||||
/*
|
||||
* PolyMC - Minecraft Launcher
|
||||
* Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net>
|
||||
* Copyright (C) 2022 Lenny McLennington <lenny@sneed.church>
|
||||
*
|
||||
* 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
|
||||
@ -107,6 +108,7 @@ Config::Config()
|
||||
IMGUR_CLIENT_ID = "@Launcher_IMGUR_CLIENT_ID@";
|
||||
MSA_CLIENT_ID = "@Launcher_MSA_CLIENT_ID@";
|
||||
FLAME_API_KEY = "@Launcher_CURSEFORGE_API_KEY@";
|
||||
FLAME_API_KEY_API_URL = "@Launcher_CURSEFORGE_API_KEY_API_URL@";
|
||||
META_URL = "@Launcher_META_URL@";
|
||||
|
||||
BUG_TRACKER_URL = "@Launcher_BUG_TRACKER_URL@";
|
||||
|
@ -3,6 +3,7 @@
|
||||
* Prism Launcher - Minecraft Launcher
|
||||
* Copyright (c) 2022 Jamie Mansfield <jmansfield@cadixdev.org>
|
||||
* Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net>
|
||||
* Copyright (C) 2022 Lenny McLennington <lenny@sneed.church>
|
||||
* Copyright (C) 2023 TheKodeToad <TheKodeToad@proton.me>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
@ -129,6 +130,11 @@ class Config {
|
||||
*/
|
||||
QString FLAME_API_KEY;
|
||||
|
||||
/**
|
||||
* URL to fetch the Client API key for CurseForge from
|
||||
*/
|
||||
QString FLAME_API_KEY_API_URL;
|
||||
|
||||
/**
|
||||
* Metadata repository URL prefix
|
||||
*/
|
||||
|
@ -1,4 +1,4 @@
|
||||
id: org.prismlauncher.PrismLauncher
|
||||
id: org.fn2006.PollyMC
|
||||
runtime: org.kde.Platform
|
||||
runtime-version: "5.15-22.08"
|
||||
sdk: org.kde.Sdk
|
||||
@ -13,7 +13,7 @@ add-extensions:
|
||||
autodelete: false
|
||||
directory: utils/gamescope
|
||||
|
||||
command: prismlauncher
|
||||
command: pollymc
|
||||
finish-args:
|
||||
- --share=ipc
|
||||
- --socket=x11
|
||||
@ -27,11 +27,11 @@ finish-args:
|
||||
- --filesystem=xdg-download:ro
|
||||
|
||||
modules:
|
||||
- name: prismlauncher
|
||||
- name: pollymc
|
||||
buildsystem: cmake-ninja
|
||||
config-opts:
|
||||
- -DLauncher_BUILD_PLATFORM=flatpak
|
||||
- -DCMAKE_BUILD_TYPE=Debug
|
||||
- -DCMAKE_BUILD_TYPE=Release
|
||||
- -DLauncher_QT_VERSION_MAJOR=5
|
||||
build-options:
|
||||
env:
|
||||
@ -76,10 +76,10 @@ modules:
|
||||
build-commands:
|
||||
- mkdir -p /app/utils/gamescope
|
||||
- install -Dm755 prime-run /app/bin/prime-run
|
||||
- mv /app/bin/prismlauncher /app/bin/prismrun
|
||||
- install -Dm755 prismlauncher /app/bin/prismlauncher
|
||||
- mv /app/bin/pollymc /app/bin/pollyrun
|
||||
- install -Dm755 pollymc /app/bin/pollymc
|
||||
sources:
|
||||
- type: file
|
||||
path: ../flatpak/prime-run
|
||||
- type: file
|
||||
path: ../flatpak/prismlauncher
|
||||
path: ../flatpak/pollymc
|
@ -8,4 +8,4 @@ done
|
||||
export PATH="${PATH}${PATH:+:}/app/utils/gamescope/bin:/usr/lib/extensions/vulkan/MangoHud/bin"
|
||||
export LD_LIBRARY_PATH="${LD_LIBRARY_PATH}${LD_LIBRARY_PATH:+:}/usr/lib/extensions/vulkan/MangoHud/\$LIB/"
|
||||
|
||||
exec /app/bin/prismrun "$@"
|
||||
exec /app/bin/pollyrun "$@"
|
@ -104,6 +104,8 @@
|
||||
#include "icons/IconList.h"
|
||||
#include "net/HttpMetaCache.h"
|
||||
|
||||
#include "ui/GuiUtil.h"
|
||||
|
||||
#include "java/JavaUtils.h"
|
||||
|
||||
#include "updater/ExternalUpdater.h"
|
||||
@ -707,6 +709,7 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv)
|
||||
m_settings->set("FlameKeyOverride", flameKey);
|
||||
m_settings->reset("CFKeyOverride");
|
||||
}
|
||||
m_settings->registerSetting("FlameKeyShouldBeFetchedOnStartup", true);
|
||||
m_settings->registerSetting("ModrinthToken", "");
|
||||
m_settings->registerSetting("UserAgentOverride", "");
|
||||
|
||||
@ -836,6 +839,7 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv)
|
||||
m_metacache->addBase("translations", QDir("translations").absolutePath());
|
||||
m_metacache->addBase("icons", QDir("cache/icons").absolutePath());
|
||||
m_metacache->addBase("meta", QDir("meta").absolutePath());
|
||||
m_metacache->addBase("injectors", QDir("injectors").absolutePath());
|
||||
m_metacache->Load();
|
||||
qDebug() << "<> Cache initialized.";
|
||||
}
|
||||
@ -1019,6 +1023,22 @@ void Application::performMainStartupAction()
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
bool shouldFetch = m_settings->get("FlameKeyShouldBeFetchedOnStartup").toBool();
|
||||
if (!BuildConfig.FLAME_API_KEY_API_URL.isEmpty() && shouldFetch && !(capabilities() & Capability::SupportsFlame))
|
||||
{
|
||||
// don't ask, just fetch
|
||||
QString apiKey = GuiUtil::fetchFlameKey();
|
||||
if (!apiKey.isEmpty())
|
||||
{
|
||||
m_settings->set("FlameKeyOverride", apiKey);
|
||||
updateCapabilities();
|
||||
}
|
||||
m_settings->set("FlameKeyShouldBeFetchedOnStartup", false);
|
||||
}
|
||||
}
|
||||
|
||||
if(!m_mainWindow)
|
||||
{
|
||||
// normal main window
|
||||
|
@ -118,6 +118,8 @@ set(NET_SOURCES
|
||||
net/ChecksumValidator.h
|
||||
net/Download.cpp
|
||||
net/Download.h
|
||||
net/FetchFlameAPIKey.cpp
|
||||
net/FetchFlameAPIKey.h
|
||||
net/FileSink.cpp
|
||||
net/FileSink.h
|
||||
net/HttpMetaCache.cpp
|
||||
@ -218,11 +220,21 @@ set(MINECRAFT_SOURCES
|
||||
minecraft/auth/flows/MSA.h
|
||||
minecraft/auth/flows/Offline.cpp
|
||||
minecraft/auth/flows/Offline.h
|
||||
minecraft/auth/flows/Elyby.cpp
|
||||
minecraft/auth/flows/Elyby.h
|
||||
minecraft/auth/flows/Custom.cpp
|
||||
minecraft/auth/flows/Custom.h
|
||||
|
||||
minecraft/auth/steps/OfflineStep.cpp
|
||||
minecraft/auth/steps/OfflineStep.h
|
||||
minecraft/auth/steps/EntitlementsStep.cpp
|
||||
minecraft/auth/steps/EntitlementsStep.h
|
||||
minecraft/auth/steps/ElybyProfileStep.cpp
|
||||
minecraft/auth/steps/ElybyProfileStep.h
|
||||
minecraft/auth/steps/ElybyStep.cpp
|
||||
minecraft/auth/steps/ElybyStep.h
|
||||
minecraft/auth/steps/CustomProfileStep.cpp
|
||||
minecraft/auth/steps/CustomProfileStep.h
|
||||
minecraft/auth/steps/CustomStep.cpp
|
||||
minecraft/auth/steps/CustomStep.h
|
||||
minecraft/auth/steps/GetSkinStep.cpp
|
||||
minecraft/auth/steps/GetSkinStep.h
|
||||
minecraft/auth/steps/LauncherLoginStep.cpp
|
||||
@ -235,6 +247,8 @@ set(MINECRAFT_SOURCES
|
||||
minecraft/auth/steps/MinecraftProfileStepMojang.h
|
||||
minecraft/auth/steps/MSAStep.cpp
|
||||
minecraft/auth/steps/MSAStep.h
|
||||
minecraft/auth/steps/OfflineStep.cpp
|
||||
minecraft/auth/steps/OfflineStep.h
|
||||
minecraft/auth/steps/XboxAuthorizationStep.cpp
|
||||
minecraft/auth/steps/XboxAuthorizationStep.h
|
||||
minecraft/auth/steps/XboxProfileStep.cpp
|
||||
@ -270,6 +284,8 @@ set(MINECRAFT_SOURCES
|
||||
minecraft/launch/LauncherPartLaunch.h
|
||||
minecraft/launch/MinecraftServerTarget.cpp
|
||||
minecraft/launch/MinecraftServerTarget.h
|
||||
minecraft/launch/InjectAuthlib.cpp
|
||||
minecraft/launch/InjectAuthlib.h
|
||||
minecraft/launch/PrintInstanceInfo.cpp
|
||||
minecraft/launch/PrintInstanceInfo.h
|
||||
minecraft/launch/ReconstructAssets.cpp
|
||||
@ -529,6 +545,13 @@ set(MODRINTH_SOURCES
|
||||
modplatform/modrinth/ModrinthPackExportTask.h
|
||||
)
|
||||
|
||||
set(MODPACKSCH_SOURCES
|
||||
modplatform/modpacksch/FTBPackInstallTask.h
|
||||
modplatform/modpacksch/FTBPackInstallTask.cpp
|
||||
modplatform/modpacksch/FTBPackManifest.h
|
||||
modplatform/modpacksch/FTBPackManifest.cpp
|
||||
)
|
||||
|
||||
set(PACKWIZ_SOURCES
|
||||
modplatform/packwiz/Packwiz.h
|
||||
modplatform/packwiz/Packwiz.cpp
|
||||
@ -658,6 +681,7 @@ set(LOGIC_SOURCES
|
||||
${FTB_SOURCES}
|
||||
${FLAME_SOURCES}
|
||||
${MODRINTH_SOURCES}
|
||||
${MODPACKSCH_SOURCES}
|
||||
${PACKWIZ_SOURCES}
|
||||
${TECHNIC_SOURCES}
|
||||
${ATLAUNCHER_SOURCES}
|
||||
@ -859,6 +883,13 @@ SET(LAUNCHER_SOURCES
|
||||
ui/pages/modplatform/atlauncher/AtlUserInteractionSupportImpl.cpp
|
||||
ui/pages/modplatform/atlauncher/AtlUserInteractionSupportImpl.h
|
||||
|
||||
ui/pages/modplatform/ftb/FtbFilterModel.cpp
|
||||
ui/pages/modplatform/ftb/FtbFilterModel.h
|
||||
ui/pages/modplatform/ftb/FtbListModel.cpp
|
||||
ui/pages/modplatform/ftb/FtbListModel.h
|
||||
ui/pages/modplatform/ftb/FtbPage.cpp
|
||||
ui/pages/modplatform/ftb/FtbPage.h
|
||||
|
||||
ui/pages/modplatform/legacy_ftb/Page.cpp
|
||||
ui/pages/modplatform/legacy_ftb/Page.h
|
||||
ui/pages/modplatform/legacy_ftb/ListModel.h
|
||||
@ -900,10 +931,14 @@ SET(LAUNCHER_SOURCES
|
||||
ui/dialogs/ProfileSetupDialog.h
|
||||
ui/dialogs/CopyInstanceDialog.cpp
|
||||
ui/dialogs/CopyInstanceDialog.h
|
||||
ui/dialogs/CustomLoginDialog.cpp
|
||||
ui/dialogs/CustomLoginDialog.h
|
||||
ui/dialogs/CustomMessageBox.cpp
|
||||
ui/dialogs/CustomMessageBox.h
|
||||
ui/dialogs/EditAccountDialog.cpp
|
||||
ui/dialogs/EditAccountDialog.h
|
||||
ui/dialogs/ElybyLoginDialog.cpp
|
||||
ui/dialogs/ElybyLoginDialog.h
|
||||
ui/dialogs/ExportInstanceDialog.cpp
|
||||
ui/dialogs/ExportInstanceDialog.h
|
||||
ui/dialogs/ExportMrPackDialog.cpp
|
||||
@ -1037,6 +1072,7 @@ qt_wrap_ui(LAUNCHER_UI
|
||||
ui/pages/modplatform/flame/FlamePage.ui
|
||||
ui/pages/modplatform/legacy_ftb/Page.ui
|
||||
ui/pages/modplatform/ImportPage.ui
|
||||
ui/pages/modplatform/ftb/FtbPage.ui
|
||||
ui/pages/modplatform/modrinth/ModrinthPage.ui
|
||||
ui/pages/modplatform/technic/TechnicPage.ui
|
||||
ui/widgets/InstanceCardWidget.ui
|
||||
@ -1059,6 +1095,8 @@ qt_wrap_ui(LAUNCHER_UI
|
||||
ui/dialogs/ImportResourceDialog.ui
|
||||
ui/dialogs/MSALoginDialog.ui
|
||||
ui/dialogs/OfflineLoginDialog.ui
|
||||
ui/dialogs/ElybyLoginDialog.ui
|
||||
ui/dialogs/CustomLoginDialog.ui
|
||||
ui/dialogs/AboutDialog.ui
|
||||
ui/dialogs/LoginDialog.ui
|
||||
ui/dialogs/EditAccountDialog.ui
|
||||
|
@ -390,6 +390,13 @@ QStringList MinecraftInstance::extraArguments()
|
||||
agent->library()->getApplicableFiles(runtimeContext(), jar, temp1, temp2, temp3, getLocalLibraryPath());
|
||||
list.append("-javaagent:"+jar[0]+(agent->argument().isEmpty() ? "" : "="+agent->argument()));
|
||||
}
|
||||
|
||||
// TODO: figure out how polymc's javaagent system works and use it instead of this hack
|
||||
if (m_injector) {
|
||||
list.append("-javaagent:"+m_injector->javaArg);
|
||||
list.append("-Dauthlibinjector.noShowServerName");
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
@ -1021,7 +1028,17 @@ shared_qobject_ptr<LaunchTask> MinecraftInstance::createLaunchTask(AuthSessionPt
|
||||
if(!session->demo) {
|
||||
process->appendStep(makeShared<ClaimAccount>(pptr, session));
|
||||
}
|
||||
// authlib patch
|
||||
if (session->user_type == "elyby")
|
||||
{
|
||||
process->appendStep(makeShared<InjectAuthlib>(pptr, &m_injector, "ely.by"));
|
||||
}
|
||||
else if (session->user_type == "custom")
|
||||
{
|
||||
process->appendStep(makeShared<InjectAuthlib>(pptr, &m_injector, session->url));
|
||||
}
|
||||
process->appendStep(makeShared<Update>(pptr, Net::Mode::Online));
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -41,6 +41,7 @@
|
||||
#include <QProcess>
|
||||
#include <QDir>
|
||||
#include "minecraft/launch/MinecraftServerTarget.h"
|
||||
#include "minecraft/launch/InjectAuthlib.h"
|
||||
|
||||
class ModFolderModel;
|
||||
class ResourceFolderModel;
|
||||
@ -178,6 +179,7 @@ protected: // data
|
||||
mutable std::shared_ptr<TexturePackFolderModel> m_texture_pack_list;
|
||||
mutable std::shared_ptr<WorldList> m_world_list;
|
||||
mutable std::shared_ptr<GameOptions> m_game_options;
|
||||
mutable std::shared_ptr<AuthlibInjector> m_injector;
|
||||
};
|
||||
|
||||
typedef std::shared_ptr<MinecraftInstance> MinecraftInstancePtr;
|
||||
|
@ -352,6 +352,10 @@ bool AccountData::resumeStateFromV3(QJsonObject data) {
|
||||
type = AccountType::Mojang;
|
||||
} else if (typeS == "Offline") {
|
||||
type = AccountType::Offline;
|
||||
} else if (typeS == "Elyby") {
|
||||
type = AccountType::Elyby;
|
||||
} else if (typeS == "Custom") {
|
||||
type = AccountType::Custom;
|
||||
} else {
|
||||
qWarning() << "Failed to parse account data: type is not recognized.";
|
||||
return false;
|
||||
@ -373,6 +377,13 @@ bool AccountData::resumeStateFromV3(QJsonObject data) {
|
||||
mojangservicesToken = tokenFromJSONV3(data, "xrp-mc");
|
||||
}
|
||||
|
||||
if(type == AccountType::Custom) {
|
||||
auto urlV = data.value("url");
|
||||
if (urlV.isString()) {
|
||||
customUrl = urlV.toString();
|
||||
}
|
||||
}
|
||||
|
||||
yggdrasilToken = tokenFromJSONV3(data, "ygg");
|
||||
minecraftProfile = profileFromJSONV3(data, "profile");
|
||||
if(!entitlementFromJSONV3(data, minecraftEntitlement)) {
|
||||
@ -409,6 +420,13 @@ QJsonObject AccountData::saveState() const {
|
||||
else if (type == AccountType::Offline) {
|
||||
output["type"] = "Offline";
|
||||
}
|
||||
else if (type == AccountType::Elyby) {
|
||||
output["type"] = "Elyby";
|
||||
}
|
||||
else if (type == AccountType::Custom) {
|
||||
output["type"] = "Custom";
|
||||
output["url"] = customUrl;
|
||||
}
|
||||
|
||||
tokenToJSONV3(output, yggdrasilToken, "ygg");
|
||||
profileToJSONV3(output, minecraftProfile, "profile");
|
||||
@ -428,14 +446,14 @@ QString AccountData::accessToken() const {
|
||||
}
|
||||
|
||||
QString AccountData::clientToken() const {
|
||||
if(type != AccountType::Mojang) {
|
||||
if(type != AccountType::Mojang && type != AccountType::Elyby && type != AccountType::Custom) {
|
||||
return QString();
|
||||
}
|
||||
return yggdrasilToken.extra["clientToken"].toString();
|
||||
}
|
||||
|
||||
void AccountData::setClientToken(QString clientToken) {
|
||||
if(type != AccountType::Mojang) {
|
||||
if(type != AccountType::Mojang && type != AccountType::Elyby && type != AccountType::Custom) {
|
||||
return;
|
||||
}
|
||||
yggdrasilToken.extra["clientToken"] = clientToken;
|
||||
@ -449,7 +467,7 @@ void AccountData::generateClientTokenIfMissing() {
|
||||
}
|
||||
|
||||
void AccountData::invalidateClientToken() {
|
||||
if(type != AccountType::Mojang) {
|
||||
if(type != AccountType::Mojang && type != AccountType::Elyby && type != AccountType::Custom) {
|
||||
return;
|
||||
}
|
||||
yggdrasilToken.extra["clientToken"] = QUuid::createUuid().toString().remove(QRegularExpression("[{-}]"));
|
||||
@ -470,6 +488,8 @@ QString AccountData::profileName() const {
|
||||
|
||||
QString AccountData::accountDisplayString() const {
|
||||
switch(type) {
|
||||
case AccountType::Custom:
|
||||
case AccountType::Elyby:
|
||||
case AccountType::Mojang: {
|
||||
return userName();
|
||||
}
|
||||
|
@ -74,7 +74,9 @@ struct MinecraftProfile {
|
||||
enum class AccountType {
|
||||
MSA,
|
||||
Mojang,
|
||||
Offline
|
||||
Offline,
|
||||
Elyby,
|
||||
Custom
|
||||
};
|
||||
|
||||
enum class AccountState {
|
||||
@ -113,6 +115,8 @@ struct AccountData {
|
||||
|
||||
QString lastError() const;
|
||||
|
||||
QString customUrl;
|
||||
|
||||
AccountType type = AccountType::MSA;
|
||||
bool legacy = false;
|
||||
bool canMigrateToMSA = false;
|
||||
|
@ -332,7 +332,7 @@ QVariant AccountList::data(const QModelIndex &index, int role) const
|
||||
}
|
||||
|
||||
case MigrationColumn: {
|
||||
if(account->isMSA() || account->isOffline()) {
|
||||
if(!account->isMojang()) {
|
||||
return tr("N/A", "Can Migrate?");
|
||||
}
|
||||
if (account->canMigrate()) {
|
||||
|
@ -40,6 +40,8 @@ struct AuthSession
|
||||
QString uuid;
|
||||
// 'legacy' or 'mojang', depending on account type
|
||||
QString user_type;
|
||||
// Yggdrasil server url
|
||||
QString url;
|
||||
// Did the auth server reply?
|
||||
bool auth_server_online = false;
|
||||
// Did the user request online mode?
|
||||
|
@ -51,6 +51,8 @@
|
||||
#include "flows/MSA.h"
|
||||
#include "flows/Mojang.h"
|
||||
#include "flows/Offline.h"
|
||||
#include "flows/Elyby.h"
|
||||
#include "flows/Custom.h"
|
||||
|
||||
MinecraftAccount::MinecraftAccount(QObject* parent) : QObject(parent) {
|
||||
data.internalId = QUuid::createUuid().toString().remove(QRegularExpression("[{}-]"));
|
||||
@ -106,6 +108,29 @@ MinecraftAccountPtr MinecraftAccount::createOffline(const QString &username)
|
||||
return account;
|
||||
}
|
||||
|
||||
MinecraftAccountPtr MinecraftAccount::createElyby(const QString &username)
|
||||
{
|
||||
MinecraftAccountPtr account = makeShared<MinecraftAccount>();
|
||||
account->data.type = AccountType::Elyby;
|
||||
account->data.yggdrasilToken.extra["userName"] = username;
|
||||
account->data.yggdrasilToken.extra["clientToken"] = QUuid::createUuid().toString().remove(QRegularExpression("[{}-]"));
|
||||
account->data.minecraftEntitlement.ownsMinecraft = true;
|
||||
account->data.minecraftEntitlement.canPlayMinecraft = true;
|
||||
return account;
|
||||
}
|
||||
|
||||
MinecraftAccountPtr MinecraftAccount::createCustom(const QString &username, const QString &url)
|
||||
{
|
||||
MinecraftAccountPtr account = makeShared<MinecraftAccount>();
|
||||
|
||||
account->data.type = AccountType::Custom;
|
||||
account->data.yggdrasilToken.extra["userName"] = username;
|
||||
account->data.yggdrasilToken.extra["clientToken"] = QUuid::createUuid().toString().remove(QRegularExpression("[{}-]"));
|
||||
account->data.minecraftEntitlement.ownsMinecraft = true;
|
||||
account->data.minecraftEntitlement.canPlayMinecraft = true;
|
||||
account->data.customUrl = url;
|
||||
return account;
|
||||
}
|
||||
|
||||
QJsonObject MinecraftAccount::saveToJson() const
|
||||
{
|
||||
@ -162,6 +187,28 @@ shared_qobject_ptr<AccountTask> MinecraftAccount::loginOffline() {
|
||||
return m_currentTask;
|
||||
}
|
||||
|
||||
shared_qobject_ptr<AccountTask> MinecraftAccount::loginElyby(QString password) {
|
||||
Q_ASSERT(m_currentTask.get() == nullptr);
|
||||
|
||||
m_currentTask.reset(new ElybyLogin(&data, password));
|
||||
connect(m_currentTask.get(), SIGNAL(succeeded()), SLOT(authSucceeded()));
|
||||
connect(m_currentTask.get(), SIGNAL(failed(QString)), SLOT(authFailed(QString)));
|
||||
connect(m_currentTask.get(), &Task::aborted, this, [this]{ authFailed(tr("Aborted")); });
|
||||
emit activityChanged(true);
|
||||
return m_currentTask;
|
||||
}
|
||||
|
||||
shared_qobject_ptr<AccountTask> MinecraftAccount::loginCustom(QString password, QString url) {
|
||||
Q_ASSERT(m_currentTask.get() == nullptr);
|
||||
|
||||
m_currentTask.reset(new CustomLogin(&data, password, url));
|
||||
connect(m_currentTask.get(), SIGNAL(succeeded()), SLOT(authSucceeded()));
|
||||
connect(m_currentTask.get(), SIGNAL(failed(QString)), SLOT(authFailed(QString)));
|
||||
connect(m_currentTask.get(), &Task::aborted, this, [this]{ authFailed(tr("Aborted")); });
|
||||
emit activityChanged(true);
|
||||
return m_currentTask;
|
||||
}
|
||||
|
||||
shared_qobject_ptr<AccountTask> MinecraftAccount::refresh() {
|
||||
if(m_currentTask) {
|
||||
return m_currentTask;
|
||||
@ -173,6 +220,12 @@ shared_qobject_ptr<AccountTask> MinecraftAccount::refresh() {
|
||||
else if(data.type == AccountType::Offline) {
|
||||
m_currentTask.reset(new OfflineRefresh(&data));
|
||||
}
|
||||
else if(data.type == AccountType::Elyby) {
|
||||
m_currentTask.reset(new ElybyRefresh(&data));
|
||||
}
|
||||
else if (data.type == AccountType::Custom) {
|
||||
m_currentTask.reset(new CustomRefresh(&data));
|
||||
}
|
||||
else {
|
||||
m_currentTask.reset(new MojangRefresh(&data));
|
||||
}
|
||||
@ -302,6 +355,8 @@ void MinecraftAccount::fillSession(AuthSessionPtr session)
|
||||
session->uuid = data.profileId();
|
||||
// 'legacy' or 'mojang', depending on account type
|
||||
session->user_type = typeString();
|
||||
session->url = data.customUrl;
|
||||
|
||||
if (!session->access_token.isEmpty())
|
||||
{
|
||||
session->session = "token:" + data.accessToken() + ":" + data.profileId();
|
||||
|
@ -95,6 +95,10 @@ public: /* construction */
|
||||
|
||||
static MinecraftAccountPtr createOffline(const QString &username);
|
||||
|
||||
static MinecraftAccountPtr createElyby(const QString &username);
|
||||
|
||||
static MinecraftAccountPtr createCustom(const QString &username, const QString &url);
|
||||
|
||||
static MinecraftAccountPtr loadFromJsonV2(const QJsonObject &json);
|
||||
static MinecraftAccountPtr loadFromJsonV3(const QJsonObject &json);
|
||||
|
||||
@ -113,6 +117,10 @@ public: /* manipulation */
|
||||
|
||||
shared_qobject_ptr<AccountTask> loginOffline();
|
||||
|
||||
shared_qobject_ptr<AccountTask> loginElyby(QString password);
|
||||
|
||||
shared_qobject_ptr<AccountTask> loginCustom(QString password, QString url);
|
||||
|
||||
shared_qobject_ptr<AccountTask> refresh();
|
||||
|
||||
shared_qobject_ptr<AccountTask> currentTask();
|
||||
@ -142,6 +150,10 @@ public: /* queries */
|
||||
return data.profileName();
|
||||
}
|
||||
|
||||
QString customUrl() const {
|
||||
return data.customUrl;
|
||||
}
|
||||
|
||||
bool isActive() const;
|
||||
|
||||
bool canMigrate() const {
|
||||
@ -152,10 +164,22 @@ public: /* queries */
|
||||
return data.type == AccountType::MSA;
|
||||
}
|
||||
|
||||
bool isMojang() const {
|
||||
return data.type == AccountType::Mojang;
|
||||
}
|
||||
|
||||
bool isOffline() const {
|
||||
return data.type == AccountType::Offline;
|
||||
}
|
||||
|
||||
bool isElyby() const {
|
||||
return data.type == AccountType::Elyby;
|
||||
}
|
||||
|
||||
bool isCustom() const {
|
||||
return data.type == AccountType::Custom;
|
||||
}
|
||||
|
||||
bool ownsMinecraft() const {
|
||||
return data.minecraftEntitlement.ownsMinecraft;
|
||||
}
|
||||
@ -181,6 +205,14 @@ public: /* queries */
|
||||
return "offline";
|
||||
}
|
||||
break;
|
||||
case AccountType::Elyby: {
|
||||
return "elyby";
|
||||
}
|
||||
break;
|
||||
case AccountType::Custom: {
|
||||
return "custom";
|
||||
}
|
||||
break;
|
||||
default: {
|
||||
return "unknown";
|
||||
}
|
||||
|
@ -55,7 +55,7 @@ void Yggdrasil::sendRequest(QUrl endpoint, QByteArray content) {
|
||||
void Yggdrasil::executeTask() {
|
||||
}
|
||||
|
||||
void Yggdrasil::refresh() {
|
||||
void Yggdrasil::refresh(QString baseUrl) {
|
||||
start();
|
||||
/*
|
||||
* {
|
||||
@ -84,13 +84,13 @@ void Yggdrasil::refresh() {
|
||||
req.insert("requestUser", false);
|
||||
QJsonDocument doc(req);
|
||||
|
||||
QUrl reqUrl("https://authserver.mojang.com/refresh");
|
||||
QUrl reqUrl(baseUrl + "refresh");
|
||||
QByteArray requestData = doc.toJson();
|
||||
|
||||
sendRequest(reqUrl, requestData);
|
||||
}
|
||||
|
||||
void Yggdrasil::login(QString password) {
|
||||
void Yggdrasil::login(QString password, QString baseUrl) {
|
||||
start();
|
||||
/*
|
||||
* {
|
||||
@ -129,7 +129,9 @@ void Yggdrasil::login(QString password) {
|
||||
|
||||
QJsonDocument doc(req);
|
||||
|
||||
QUrl reqUrl("https://authserver.mojang.com/authenticate");
|
||||
this->customUrl = baseUrl;
|
||||
|
||||
QUrl reqUrl(baseUrl + "authenticate");
|
||||
QNetworkRequest netRequest(reqUrl);
|
||||
QByteArray requestData = doc.toJson();
|
||||
|
||||
|
@ -40,8 +40,8 @@ public:
|
||||
);
|
||||
virtual ~Yggdrasil() = default;
|
||||
|
||||
void refresh();
|
||||
void login(QString password);
|
||||
void refresh(QString baseUrl);
|
||||
void login(QString password, QString baseUrl);
|
||||
|
||||
struct Error
|
||||
{
|
||||
@ -97,6 +97,8 @@ protected:
|
||||
QTimer counter;
|
||||
int count = 0; // num msec since time reset
|
||||
|
||||
QString customUrl;
|
||||
|
||||
const int timeout_max = 30000;
|
||||
const int time_step = 50;
|
||||
};
|
||||
|
27
launcher/minecraft/auth/flows/Custom.cpp
Normal file
@ -0,0 +1,27 @@
|
||||
#include "Custom.h"
|
||||
|
||||
#include "minecraft/auth/steps/CustomStep.h"
|
||||
#include "minecraft/auth/steps/CustomProfileStep.h"
|
||||
#include "minecraft/auth/steps/GetSkinStep.h"
|
||||
|
||||
CustomRefresh::CustomRefresh(
|
||||
AccountData *data,
|
||||
QObject *parent
|
||||
) : AuthFlow(data, parent) {
|
||||
m_steps.append(makeShared<CustomStep>(m_data, QString()));
|
||||
m_steps.append(makeShared<CustomProfileStep>(m_data));
|
||||
m_steps.append(makeShared<GetSkinStep>(m_data));
|
||||
}
|
||||
|
||||
CustomLogin::CustomLogin(
|
||||
AccountData *data,
|
||||
QString password,
|
||||
QString url,
|
||||
QObject *parent
|
||||
): AuthFlow(data, parent), m_password(password) {
|
||||
auto step = makeShared<CustomStep>(m_data, m_password);
|
||||
step.get()->setUrl(url);
|
||||
m_steps.append(step);
|
||||
m_steps.append(makeShared<CustomProfileStep>(m_data));
|
||||
m_steps.append(makeShared<GetSkinStep>(m_data));
|
||||
}
|
27
launcher/minecraft/auth/flows/Custom.h
Normal file
@ -0,0 +1,27 @@
|
||||
#pragma once
|
||||
#include "AuthFlow.h"
|
||||
|
||||
class CustomRefresh : public AuthFlow
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit CustomRefresh(
|
||||
AccountData *data,
|
||||
QObject *parent = 0
|
||||
);
|
||||
};
|
||||
|
||||
class CustomLogin : public AuthFlow
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit CustomLogin(
|
||||
AccountData *data,
|
||||
QString password,
|
||||
QString url,
|
||||
QObject *parent = 0
|
||||
);
|
||||
|
||||
private:
|
||||
QString m_password;
|
||||
};
|
24
launcher/minecraft/auth/flows/Elyby.cpp
Normal file
@ -0,0 +1,24 @@
|
||||
#include "Elyby.h"
|
||||
|
||||
#include "minecraft/auth/steps/ElybyStep.h"
|
||||
#include "minecraft/auth/steps/ElybyProfileStep.h"
|
||||
#include "minecraft/auth/steps/GetSkinStep.h"
|
||||
|
||||
ElybyRefresh::ElybyRefresh(
|
||||
AccountData *data,
|
||||
QObject *parent
|
||||
) : AuthFlow(data, parent) {
|
||||
m_steps.append(makeShared<ElybyStep>(m_data, QString()));
|
||||
m_steps.append(makeShared<ElybyProfileStep>(m_data));
|
||||
m_steps.append(makeShared<GetSkinStep>(m_data));
|
||||
}
|
||||
|
||||
ElybyLogin::ElybyLogin(
|
||||
AccountData *data,
|
||||
QString password,
|
||||
QObject *parent
|
||||
): AuthFlow(data, parent), m_password(password) {
|
||||
m_steps.append(makeShared<ElybyStep>(m_data, m_password));
|
||||
m_steps.append(makeShared<ElybyProfileStep>(m_data));
|
||||
m_steps.append(makeShared<GetSkinStep>(m_data));
|
||||
}
|
26
launcher/minecraft/auth/flows/Elyby.h
Normal file
@ -0,0 +1,26 @@
|
||||
#pragma once
|
||||
#include "AuthFlow.h"
|
||||
|
||||
class ElybyRefresh : public AuthFlow
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit ElybyRefresh(
|
||||
AccountData *data,
|
||||
QObject *parent = 0
|
||||
);
|
||||
};
|
||||
|
||||
class ElybyLogin : public AuthFlow
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit ElybyLogin(
|
||||
AccountData *data,
|
||||
QString password,
|
||||
QObject *parent = 0
|
||||
);
|
||||
|
||||
private:
|
||||
QString m_password;
|
||||
};
|
96
launcher/minecraft/auth/steps/CustomProfileStep.cpp
Normal file
@ -0,0 +1,96 @@
|
||||
#include "CustomProfileStep.h"
|
||||
#include <QNetworkRequest>
|
||||
|
||||
#include "minecraft/auth/AuthRequest.h"
|
||||
#include "minecraft/auth/Parsers.h"
|
||||
#include "net/NetUtils.h"
|
||||
|
||||
CustomProfileStep::CustomProfileStep(AccountData* data) : AuthStep(data) {
|
||||
|
||||
}
|
||||
|
||||
CustomProfileStep::~CustomProfileStep() noexcept = default;
|
||||
|
||||
QString CustomProfileStep::describe() {
|
||||
return tr("Fetching the Minecraft profile.");
|
||||
}
|
||||
|
||||
|
||||
void CustomProfileStep::perform() {
|
||||
if (m_data->minecraftProfile.id.isEmpty()) {
|
||||
emit finished(AccountTaskState::STATE_FAILED_HARD, tr("A UUID is required to get the profile."));
|
||||
return;
|
||||
}
|
||||
|
||||
// m_data->
|
||||
|
||||
qWarning() << "Url: " << m_data->customUrl;
|
||||
|
||||
QUrl url = QUrl(m_data->customUrl + "/session/profile/" + m_data->minecraftProfile.id);
|
||||
QNetworkRequest req = QNetworkRequest(url);
|
||||
AuthRequest *request = new AuthRequest(this);
|
||||
connect(request, &AuthRequest::finished, this, &CustomProfileStep::onRequestDone);
|
||||
request->get(req);
|
||||
}
|
||||
|
||||
void CustomProfileStep::rehydrate() {
|
||||
// NOOP, for now. We only save bools and there's nothing to check.
|
||||
}
|
||||
|
||||
void CustomProfileStep::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.
|
||||
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);
|
||||
|
||||
if (Net::isApplicationError(error)) {
|
||||
emit finished(
|
||||
AccountTaskState::STATE_FAILED_SOFT,
|
||||
tr("Minecraft Java profile acquisition failed: %1").arg(requestor->errorString_)
|
||||
);
|
||||
}
|
||||
else {
|
||||
emit finished(
|
||||
AccountTaskState::STATE_OFFLINE,
|
||||
tr("Minecraft Java profile acquisition failed: %1").arg(requestor->errorString_)
|
||||
);
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
emit finished(
|
||||
AccountTaskState::STATE_WORKING,
|
||||
tr("Minecraft Java profile acquisition succeeded.")
|
||||
);
|
||||
}
|
22
launcher/minecraft/auth/steps/CustomProfileStep.h
Normal file
@ -0,0 +1,22 @@
|
||||
#pragma once
|
||||
#include <QObject>
|
||||
|
||||
#include "QObjectPtr.h"
|
||||
#include "minecraft/auth/AuthStep.h"
|
||||
|
||||
|
||||
class CustomProfileStep : public AuthStep {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit CustomProfileStep(AccountData *data);
|
||||
virtual ~CustomProfileStep() noexcept;
|
||||
|
||||
void perform() override;
|
||||
void rehydrate() override;
|
||||
|
||||
QString describe() override;
|
||||
|
||||
private slots:
|
||||
void onRequestDone(QNetworkReply::NetworkError, QByteArray, QList<QNetworkReply::RawHeaderPair>);
|
||||
};
|
57
launcher/minecraft/auth/steps/CustomStep.cpp
Normal file
@ -0,0 +1,57 @@
|
||||
#include "CustomStep.h"
|
||||
|
||||
#include "minecraft/auth/AuthRequest.h"
|
||||
#include "minecraft/auth/Parsers.h"
|
||||
#include "minecraft/auth/Yggdrasil.h"
|
||||
|
||||
CustomStep::CustomStep(AccountData* data, QString password) : AuthStep(data), m_password(password) {
|
||||
m_yggdrasil = new Yggdrasil(m_data, this);
|
||||
|
||||
connect(m_yggdrasil, &Task::failed, this, &CustomStep::onAuthFailed);
|
||||
connect(m_yggdrasil, &Task::succeeded, this, &CustomStep::onAuthSucceeded);
|
||||
connect(m_yggdrasil, &Task::aborted, this, &CustomStep::onAuthFailed);
|
||||
}
|
||||
|
||||
CustomStep::~CustomStep() noexcept = default;
|
||||
|
||||
QString CustomStep::describe() {
|
||||
return tr("Logging in with Custom account.");
|
||||
}
|
||||
|
||||
void CustomStep::rehydrate() {
|
||||
// NOOP, for now.
|
||||
}
|
||||
|
||||
void CustomStep::perform() {
|
||||
qWarning() << "url: " << m_url << " / " << m_data->customUrl;
|
||||
if(m_password.size()) {
|
||||
m_yggdrasil->login(m_password, m_url + "/auth/");
|
||||
}
|
||||
else {
|
||||
m_yggdrasil->refresh(m_data->customUrl + "/auth/");
|
||||
}
|
||||
}
|
||||
|
||||
void CustomStep::setUrl(QString url) {
|
||||
this->m_url = url;
|
||||
}
|
||||
|
||||
void CustomStep::onAuthSucceeded() {
|
||||
emit finished(AccountTaskState::STATE_WORKING, tr("Logged in with Custom"));
|
||||
}
|
||||
|
||||
void CustomStep::onAuthFailed() {
|
||||
// TODO: hook these in again, expand to MSA
|
||||
// m_error = m_yggdrasil->m_error;
|
||||
// m_aborted = m_yggdrasil->m_aborted;
|
||||
|
||||
auto state = m_yggdrasil->taskState();
|
||||
QString errorMessage = tr("Custom user authentication failed.");
|
||||
|
||||
// NOTE: soft error in the first step means 'offline'
|
||||
if(state == AccountTaskState::STATE_FAILED_SOFT) {
|
||||
state = AccountTaskState::STATE_OFFLINE;
|
||||
errorMessage = tr("Custom user authentication ended with a network error. Is MutliFactor Auth correct?");
|
||||
}
|
||||
emit finished(state, errorMessage);
|
||||
}
|
31
launcher/minecraft/auth/steps/CustomStep.h
Normal file
@ -0,0 +1,31 @@
|
||||
#pragma once
|
||||
#include <QObject>
|
||||
|
||||
#include "QObjectPtr.h"
|
||||
#include "minecraft/auth/AuthStep.h"
|
||||
|
||||
class Yggdrasil;
|
||||
|
||||
class CustomStep : public AuthStep {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit CustomStep(AccountData *data, QString password);
|
||||
virtual ~CustomStep() noexcept;
|
||||
|
||||
void perform() override;
|
||||
void rehydrate() override;
|
||||
|
||||
QString describe() override;
|
||||
|
||||
void setUrl(QString url);
|
||||
|
||||
private slots:
|
||||
void onAuthSucceeded();
|
||||
void onAuthFailed();
|
||||
|
||||
private:
|
||||
Yggdrasil *m_yggdrasil = nullptr;
|
||||
QString m_password;
|
||||
QString m_url;
|
||||
};
|
93
launcher/minecraft/auth/steps/ElybyProfileStep.cpp
Normal file
@ -0,0 +1,93 @@
|
||||
#include "ElybyProfileStep.h"
|
||||
|
||||
#include <QNetworkRequest>
|
||||
|
||||
#include "minecraft/auth/AuthRequest.h"
|
||||
#include "minecraft/auth/Parsers.h"
|
||||
#include "net/NetUtils.h"
|
||||
|
||||
ElybyProfileStep::ElybyProfileStep(AccountData* data) : AuthStep(data) {
|
||||
|
||||
}
|
||||
|
||||
ElybyProfileStep::~ElybyProfileStep() noexcept = default;
|
||||
|
||||
QString ElybyProfileStep::describe() {
|
||||
return tr("Fetching the Minecraft profile.");
|
||||
}
|
||||
|
||||
|
||||
void ElybyProfileStep::perform() {
|
||||
if (m_data->minecraftProfile.id.isEmpty()) {
|
||||
emit finished(AccountTaskState::STATE_FAILED_HARD, tr("A UUID is required to get the profile."));
|
||||
return;
|
||||
}
|
||||
|
||||
QUrl url = QUrl("https://authserver.ely.by/session/profile/" + m_data->minecraftProfile.id);
|
||||
QNetworkRequest req = QNetworkRequest(url);
|
||||
AuthRequest *request = new AuthRequest(this);
|
||||
connect(request, &AuthRequest::finished, this, &ElybyProfileStep::onRequestDone);
|
||||
request->get(req);
|
||||
}
|
||||
|
||||
void ElybyProfileStep::rehydrate() {
|
||||
// NOOP, for now. We only save bools and there's nothing to check.
|
||||
}
|
||||
|
||||
void ElybyProfileStep::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.
|
||||
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);
|
||||
|
||||
if (Net::isApplicationError(error)) {
|
||||
emit finished(
|
||||
AccountTaskState::STATE_FAILED_SOFT,
|
||||
tr("Minecraft Java profile acquisition failed: %1").arg(requestor->errorString_)
|
||||
);
|
||||
}
|
||||
else {
|
||||
emit finished(
|
||||
AccountTaskState::STATE_OFFLINE,
|
||||
tr("Minecraft Java profile acquisition failed: %1").arg(requestor->errorString_)
|
||||
);
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
emit finished(
|
||||
AccountTaskState::STATE_WORKING,
|
||||
tr("Minecraft Java profile acquisition succeeded.")
|
||||
);
|
||||
}
|
22
launcher/minecraft/auth/steps/ElybyProfileStep.h
Normal file
@ -0,0 +1,22 @@
|
||||
#pragma once
|
||||
#include <QObject>
|
||||
|
||||
#include "QObjectPtr.h"
|
||||
#include "minecraft/auth/AuthStep.h"
|
||||
|
||||
|
||||
class ElybyProfileStep : public AuthStep {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit ElybyProfileStep(AccountData *data);
|
||||
virtual ~ElybyProfileStep() noexcept;
|
||||
|
||||
void perform() override;
|
||||
void rehydrate() override;
|
||||
|
||||
QString describe() override;
|
||||
|
||||
private slots:
|
||||
void onRequestDone(QNetworkReply::NetworkError, QByteArray, QList<QNetworkReply::RawHeaderPair>);
|
||||
};
|
52
launcher/minecraft/auth/steps/ElybyStep.cpp
Normal file
@ -0,0 +1,52 @@
|
||||
#include "ElybyStep.h"
|
||||
|
||||
#include "minecraft/auth/AuthRequest.h"
|
||||
#include "minecraft/auth/Parsers.h"
|
||||
#include "minecraft/auth/Yggdrasil.h"
|
||||
|
||||
ElybyStep::ElybyStep(AccountData* data, QString password) : AuthStep(data), m_password(password) {
|
||||
m_yggdrasil = new Yggdrasil(m_data, this);
|
||||
|
||||
connect(m_yggdrasil, &Task::failed, this, &ElybyStep::onAuthFailed);
|
||||
connect(m_yggdrasil, &Task::succeeded, this, &ElybyStep::onAuthSucceeded);
|
||||
connect(m_yggdrasil, &Task::aborted, this, &ElybyStep::onAuthFailed);
|
||||
}
|
||||
|
||||
ElybyStep::~ElybyStep() noexcept = default;
|
||||
|
||||
QString ElybyStep::describe() {
|
||||
return tr("Logging in with Ely.by account.");
|
||||
}
|
||||
|
||||
void ElybyStep::rehydrate() {
|
||||
// NOOP, for now.
|
||||
}
|
||||
|
||||
void ElybyStep::perform() {
|
||||
if(m_password.size()) {
|
||||
m_yggdrasil->login(m_password, "https://authserver.ely.by/auth/");
|
||||
}
|
||||
else {
|
||||
m_yggdrasil->refresh("https://authserver.ely.by/auth/");
|
||||
}
|
||||
}
|
||||
|
||||
void ElybyStep::onAuthSucceeded() {
|
||||
emit finished(AccountTaskState::STATE_WORKING, tr("Logged in with Ely.by"));
|
||||
}
|
||||
|
||||
void ElybyStep::onAuthFailed() {
|
||||
// TODO: hook these in again, expand to MSA
|
||||
// m_error = m_yggdrasil->m_error;
|
||||
// m_aborted = m_yggdrasil->m_aborted;
|
||||
|
||||
auto state = m_yggdrasil->taskState();
|
||||
QString errorMessage = tr("Ely.by user authentication failed.");
|
||||
|
||||
// NOTE: soft error in the first step means 'offline'
|
||||
if(state == AccountTaskState::STATE_FAILED_SOFT) {
|
||||
state = AccountTaskState::STATE_OFFLINE;
|
||||
errorMessage = tr("Ely.by user authentication ended with a network error.\nIf you are using 2FA make sure to enter your auth code.");
|
||||
}
|
||||
emit finished(state, errorMessage);
|
||||
}
|
28
launcher/minecraft/auth/steps/ElybyStep.h
Normal file
@ -0,0 +1,28 @@
|
||||
#pragma once
|
||||
#include <QObject>
|
||||
|
||||
#include "QObjectPtr.h"
|
||||
#include "minecraft/auth/AuthStep.h"
|
||||
|
||||
class Yggdrasil;
|
||||
|
||||
class ElybyStep : public AuthStep {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit ElybyStep(AccountData *data, QString password);
|
||||
virtual ~ElybyStep() noexcept;
|
||||
|
||||
void perform() override;
|
||||
void rehydrate() override;
|
||||
|
||||
QString describe() override;
|
||||
|
||||
private slots:
|
||||
void onAuthSucceeded();
|
||||
void onAuthFailed();
|
||||
|
||||
private:
|
||||
Yggdrasil *m_yggdrasil = nullptr;
|
||||
QString m_password;
|
||||
};
|
@ -24,10 +24,10 @@ void YggdrasilStep::rehydrate() {
|
||||
|
||||
void YggdrasilStep::perform() {
|
||||
if(m_password.size()) {
|
||||
m_yggdrasil->login(m_password);
|
||||
m_yggdrasil->login(m_password, "https://authserver.mojang.com/");
|
||||
}
|
||||
else {
|
||||
m_yggdrasil->refresh();
|
||||
m_yggdrasil->refresh("https://authserver.mojang.com/");
|
||||
}
|
||||
}
|
||||
|
||||
|
175
launcher/minecraft/launch/InjectAuthlib.cpp
Normal file
@ -0,0 +1,175 @@
|
||||
/* 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 "InjectAuthlib.h"
|
||||
#include <launch/LaunchTask.h>
|
||||
#include <minecraft/MinecraftInstance.h>
|
||||
#include <FileSystem.h>
|
||||
#include <Application.h>
|
||||
#include <Json.h>
|
||||
|
||||
InjectAuthlib::InjectAuthlib(LaunchTask *parent, AuthlibInjectorPtr* injector, QString url) : LaunchStep(parent)
|
||||
{
|
||||
m_injector = injector;
|
||||
m_url = url;
|
||||
}
|
||||
|
||||
void InjectAuthlib::executeTask()
|
||||
{
|
||||
if (m_aborted)
|
||||
|
||||
{
|
||||
emitFailed(tr("Task aborted."));
|
||||
return;
|
||||
}
|
||||
|
||||
auto latestVersionInfo = QString("https://authlib-injector.yushi.moe/artifact/latest.json");
|
||||
auto netJob = makeShared<NetJob>("Injector versions info download", APPLICATION->network());
|
||||
MetaEntryPtr entry = APPLICATION->metacache()->resolveEntry("injectors", "version.json");
|
||||
if (!m_offlineMode)
|
||||
{
|
||||
entry->setStale(true);
|
||||
auto task = Net::Download::makeCached(QUrl(latestVersionInfo), entry);
|
||||
netJob->addNetAction(task);
|
||||
|
||||
jobPtr.reset(netJob);
|
||||
QObject::connect(netJob.get(), &NetJob::succeeded, this, &InjectAuthlib::onVersionDownloadSucceeded);
|
||||
QObject::connect(netJob.get(), &NetJob::failed, this, &InjectAuthlib::onDownloadFailed);
|
||||
jobPtr->start();
|
||||
}
|
||||
else
|
||||
{
|
||||
onVersionDownloadSucceeded();
|
||||
}
|
||||
}
|
||||
|
||||
void InjectAuthlib::onVersionDownloadSucceeded()
|
||||
{
|
||||
|
||||
QByteArray data;
|
||||
try
|
||||
{
|
||||
data = FS::read(QDir("injectors").absoluteFilePath("version.json"));
|
||||
}
|
||||
catch (const Exception &e)
|
||||
{
|
||||
qCritical() << "Translations Download Failed: index file not readable";
|
||||
jobPtr.reset();
|
||||
emitFailed("Error while parsing JSON response from InjectorEndpoint");
|
||||
return;
|
||||
}
|
||||
|
||||
QJsonParseError parse_error;
|
||||
QJsonDocument doc = QJsonDocument::fromJson(data, &parse_error);
|
||||
if (parse_error.error != QJsonParseError::NoError)
|
||||
{
|
||||
qCritical() << "Error while parsing JSON response from InjectorEndpoint at " << parse_error.offset << " reason: " << parse_error.errorString();
|
||||
qCritical() << data;
|
||||
jobPtr.reset();
|
||||
emitFailed("Error while parsing JSON response from InjectorEndpoint");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!doc.isObject())
|
||||
{
|
||||
qCritical() << "Error while parsing JSON response from InjectorEndpoint root is not object";
|
||||
qCritical() << data;
|
||||
jobPtr.reset();
|
||||
emitFailed("Error while parsing JSON response from InjectorEndpoint");
|
||||
return;
|
||||
}
|
||||
|
||||
QString downloadUrl;
|
||||
try
|
||||
{
|
||||
downloadUrl = Json::requireString(doc.object(), "download_url");
|
||||
}
|
||||
catch (const JSONValidationError &e)
|
||||
{
|
||||
qCritical() << "Error while parsing JSON response from InjectorEndpoint download url is not string";
|
||||
qCritical() << e.cause();
|
||||
qCritical() << data;
|
||||
jobPtr.reset();
|
||||
emitFailed("Error while parsing JSON response from InjectorEndpoint");
|
||||
return;
|
||||
}
|
||||
|
||||
QFileInfo fi(downloadUrl);
|
||||
m_versionName = fi.fileName();
|
||||
|
||||
qDebug() << "Authlib injector version:" << m_versionName;
|
||||
if (!m_offlineMode)
|
||||
{
|
||||
auto netJob = makeShared<NetJob>("Injector download", APPLICATION->network());
|
||||
MetaEntryPtr entry = APPLICATION->metacache()->resolveEntry("injectors", m_versionName);
|
||||
entry->setStale(true);
|
||||
auto task = Net::Download::makeCached(QUrl(downloadUrl), entry);
|
||||
netJob->addNetAction(task);
|
||||
|
||||
jobPtr.reset(netJob);
|
||||
QObject::connect(netJob.get(), &NetJob::succeeded, this, &InjectAuthlib::onDownloadSucceeded);
|
||||
QObject::connect(netJob.get(), &NetJob::failed, this, &InjectAuthlib::onDownloadFailed);
|
||||
jobPtr->start();
|
||||
}
|
||||
else
|
||||
{
|
||||
onDownloadSucceeded();
|
||||
}
|
||||
}
|
||||
|
||||
void InjectAuthlib::onDownloadSucceeded()
|
||||
{
|
||||
QString injector = QString("%1=%2").arg(QDir("injectors").absoluteFilePath(m_versionName)).arg(m_url);
|
||||
|
||||
qDebug()
|
||||
<< "Injecting " << injector;
|
||||
auto inj = new AuthlibInjector(injector);
|
||||
m_injector->reset(inj);
|
||||
|
||||
jobPtr.reset();
|
||||
emitSucceeded();
|
||||
}
|
||||
|
||||
void InjectAuthlib::onDownloadFailed(QString reason)
|
||||
{
|
||||
jobPtr.reset();
|
||||
emitFailed(reason);
|
||||
}
|
||||
|
||||
void InjectAuthlib::proceed()
|
||||
{
|
||||
}
|
||||
|
||||
bool InjectAuthlib::canAbort() const
|
||||
{
|
||||
if (jobPtr)
|
||||
{
|
||||
return jobPtr->canAbort();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool InjectAuthlib::abort()
|
||||
{
|
||||
m_aborted = true;
|
||||
if (jobPtr)
|
||||
{
|
||||
if (jobPtr->canAbort())
|
||||
{
|
||||
return jobPtr->abort();
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
76
launcher/minecraft/launch/InjectAuthlib.h
Normal file
@ -0,0 +1,76 @@
|
||||
/* 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 <QObjectPtr.h>
|
||||
#include <LoggedProcess.h>
|
||||
#include <java/JavaChecker.h>
|
||||
#include <net/Mode.h>
|
||||
#include <net/NetJob.h>
|
||||
|
||||
struct AuthlibInjector
|
||||
{
|
||||
QString javaArg;
|
||||
|
||||
AuthlibInjector(const QString arg)
|
||||
{
|
||||
javaArg = std::move(arg);
|
||||
qDebug() << "NEW INJECTOR" << javaArg;
|
||||
}
|
||||
};
|
||||
|
||||
typedef std::shared_ptr<AuthlibInjector> AuthlibInjectorPtr;
|
||||
|
||||
// FIXME: stupid. should be defined by the instance type? or even completely abstracted away...
|
||||
class InjectAuthlib : public LaunchStep
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
InjectAuthlib(LaunchTask *parent, AuthlibInjectorPtr *injector, QString url);
|
||||
virtual ~InjectAuthlib(){};
|
||||
|
||||
void executeTask() override;
|
||||
bool canAbort() const override;
|
||||
void proceed() override;
|
||||
|
||||
void setAuthServer(QString server)
|
||||
{
|
||||
m_authServer = server;
|
||||
};
|
||||
|
||||
void setOfflineMode(bool offline) {
|
||||
m_offlineMode = offline;
|
||||
}
|
||||
|
||||
public slots:
|
||||
bool abort() override;
|
||||
|
||||
private slots:
|
||||
void onVersionDownloadSucceeded();
|
||||
void onDownloadSucceeded();
|
||||
void onDownloadFailed(QString reason);
|
||||
|
||||
private:
|
||||
shared_qobject_ptr<NetJob> jobPtr;
|
||||
bool m_aborted = false;
|
||||
|
||||
bool m_offlineMode;
|
||||
QString m_versionName;
|
||||
QString m_authServer;
|
||||
QString m_url;
|
||||
AuthlibInjectorPtr *m_injector;
|
||||
};
|
387
launcher/modplatform/modpacksch/FTBPackInstallTask.cpp
Normal file
@ -0,0 +1,387 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
/*
|
||||
* Prism Launcher - Minecraft Launcher
|
||||
* Copyright (C) 2022 flowln <flowlnlnln@gmail.com>
|
||||
* Copyright (c) 2022 Jamie Mansfield <jmansfield@cadixdev.org>
|
||||
* 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 2020-2021 Jamie Mansfield <jmansfield@cadixdev.org>
|
||||
* Copyright 2020-2021 Petr Mrazek <peterix@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 "FTBPackInstallTask.h"
|
||||
|
||||
#include "FileSystem.h"
|
||||
#include "Json.h"
|
||||
#include "minecraft/MinecraftInstance.h"
|
||||
#include "minecraft/PackProfile.h"
|
||||
#include "modplatform/flame/PackManifest.h"
|
||||
#include "net/ChecksumValidator.h"
|
||||
#include "settings/INISettingsObject.h"
|
||||
|
||||
#include "Application.h"
|
||||
#include "BuildConfig.h"
|
||||
#include "ui/dialogs/BlockedModsDialog.h"
|
||||
|
||||
namespace ModpacksCH {
|
||||
|
||||
PackInstallTask::PackInstallTask(Modpack pack, QString version, QWidget* parent)
|
||||
: m_pack(std::move(pack)), m_version_name(std::move(version)), m_parent(parent)
|
||||
{}
|
||||
|
||||
bool PackInstallTask::abort()
|
||||
{
|
||||
if (!canAbort())
|
||||
return false;
|
||||
|
||||
bool aborted = true;
|
||||
|
||||
if (m_net_job)
|
||||
aborted &= m_net_job->abort();
|
||||
if (m_mod_id_resolver_task)
|
||||
aborted &= m_mod_id_resolver_task->abort();
|
||||
|
||||
return aborted ? InstanceTask::abort() : false;
|
||||
}
|
||||
|
||||
void PackInstallTask::executeTask()
|
||||
{
|
||||
setStatus(tr("Getting the manifest..."));
|
||||
setAbortable(false);
|
||||
|
||||
// Find pack version
|
||||
auto version_it = std::find_if(m_pack.versions.constBegin(), m_pack.versions.constEnd(),
|
||||
[this](ModpacksCH::VersionInfo const& a) { return a.name == m_version_name; });
|
||||
|
||||
if (version_it == m_pack.versions.constEnd()) {
|
||||
emitFailed(tr("Failed to find pack version %1").arg(m_version_name));
|
||||
return;
|
||||
}
|
||||
|
||||
auto version = *version_it;
|
||||
|
||||
auto netJob = makeShared<NetJob>("ModpacksCH::VersionFetch", APPLICATION->network());
|
||||
|
||||
auto searchUrl = QString(BuildConfig.MODPACKSCH_API_BASE_URL + "public/modpack/%1/%2").arg(m_pack.id).arg(version.id);
|
||||
netJob->addNetAction(Net::Download::makeByteArray(QUrl(searchUrl), &m_response));
|
||||
|
||||
QObject::connect(netJob.get(), &NetJob::succeeded, this, &PackInstallTask::onManifestDownloadSucceeded);
|
||||
QObject::connect(netJob.get(), &NetJob::failed, this, &PackInstallTask::onManifestDownloadFailed);
|
||||
QObject::connect(netJob.get(), &NetJob::aborted, this, &PackInstallTask::abort);
|
||||
QObject::connect(netJob.get(), &NetJob::progress, this, &PackInstallTask::setProgress);
|
||||
|
||||
m_net_job = netJob;
|
||||
|
||||
setAbortable(true);
|
||||
netJob->start();
|
||||
}
|
||||
|
||||
void PackInstallTask::onManifestDownloadSucceeded()
|
||||
{
|
||||
m_net_job.reset();
|
||||
|
||||
QJsonParseError parse_error{};
|
||||
QJsonDocument doc = QJsonDocument::fromJson(m_response, &parse_error);
|
||||
if (parse_error.error != QJsonParseError::NoError) {
|
||||
qWarning() << "Error while parsing JSON response from ModpacksCH at " << parse_error.offset
|
||||
<< " reason: " << parse_error.errorString();
|
||||
qWarning() << m_response;
|
||||
return;
|
||||
}
|
||||
|
||||
ModpacksCH::Version version;
|
||||
try {
|
||||
auto obj = Json::requireObject(doc);
|
||||
ModpacksCH::loadVersion(version, obj);
|
||||
} catch (const JSONValidationError& e) {
|
||||
emitFailed(tr("Could not understand pack manifest:\n") + e.cause());
|
||||
return;
|
||||
}
|
||||
|
||||
m_version = version;
|
||||
|
||||
resolveMods();
|
||||
}
|
||||
|
||||
void PackInstallTask::resolveMods()
|
||||
{
|
||||
setStatus(tr("Resolving mods..."));
|
||||
setAbortable(false);
|
||||
setProgress(0, 100);
|
||||
|
||||
m_file_id_map.clear();
|
||||
|
||||
Flame::Manifest manifest;
|
||||
int index = 0;
|
||||
|
||||
for (auto const& file : m_version.files) {
|
||||
if (!file.serverOnly && file.url.isEmpty()) {
|
||||
if (file.curseforge.file_id <= 0) {
|
||||
emitFailed(tr("Invalid manifest: There's no information available to download the file '%1'!").arg(file.name));
|
||||
return;
|
||||
}
|
||||
|
||||
Flame::File flame_file;
|
||||
flame_file.projectId = file.curseforge.project_id;
|
||||
flame_file.fileId = file.curseforge.file_id;
|
||||
flame_file.hash = file.sha1;
|
||||
|
||||
manifest.files.insert(flame_file.fileId, flame_file);
|
||||
m_file_id_map.append(flame_file.fileId);
|
||||
} else {
|
||||
m_file_id_map.append(-1);
|
||||
}
|
||||
|
||||
index++;
|
||||
}
|
||||
|
||||
m_mod_id_resolver_task.reset(new Flame::FileResolvingTask(APPLICATION->network(), manifest));
|
||||
|
||||
connect(m_mod_id_resolver_task.get(), &Flame::FileResolvingTask::succeeded, this, &PackInstallTask::onResolveModsSucceeded);
|
||||
connect(m_mod_id_resolver_task.get(), &Flame::FileResolvingTask::failed, this, &PackInstallTask::onResolveModsFailed);
|
||||
connect(m_mod_id_resolver_task.get(), &Flame::FileResolvingTask::aborted, this, &PackInstallTask::abort);
|
||||
connect(m_mod_id_resolver_task.get(), &Flame::FileResolvingTask::progress, this, &PackInstallTask::setProgress);
|
||||
|
||||
setAbortable(true);
|
||||
|
||||
m_mod_id_resolver_task->start();
|
||||
}
|
||||
|
||||
void PackInstallTask::onResolveModsSucceeded()
|
||||
{
|
||||
auto anyBlocked = false;
|
||||
|
||||
Flame::Manifest results = m_mod_id_resolver_task->getResults();
|
||||
for (int index = 0; index < m_file_id_map.size(); index++) {
|
||||
auto const file_id = m_file_id_map.at(index);
|
||||
if (file_id < 0)
|
||||
continue;
|
||||
|
||||
Flame::File results_file = results.files[file_id];
|
||||
VersionFile& local_file = m_version.files[index];
|
||||
|
||||
// First check for blocked mods
|
||||
if (!results_file.resolved || results_file.url.isEmpty()) {
|
||||
BlockedMod blocked_mod;
|
||||
blocked_mod.name = local_file.name;
|
||||
blocked_mod.websiteUrl = results_file.websiteUrl;
|
||||
blocked_mod.hash = results_file.hash;
|
||||
blocked_mod.matched = false;
|
||||
blocked_mod.localPath = "";
|
||||
blocked_mod.targetFolder = results_file.targetFolder;
|
||||
|
||||
m_blocked_mods.append(blocked_mod);
|
||||
|
||||
anyBlocked = true;
|
||||
} else {
|
||||
local_file.url = results_file.url.toString();
|
||||
}
|
||||
}
|
||||
|
||||
m_mod_id_resolver_task.reset();
|
||||
|
||||
if (anyBlocked) {
|
||||
qDebug() << "Blocked files found, displaying file list";
|
||||
|
||||
BlockedModsDialog message_dialog(m_parent, tr("Blocked files found"),
|
||||
tr("The following files are not available for download in third party launchers.<br/>"
|
||||
"You will need to manually download them and add them to the instance."),
|
||||
m_blocked_mods);
|
||||
|
||||
message_dialog.setModal(true);
|
||||
|
||||
if (message_dialog.exec() == QDialog::Accepted) {
|
||||
qDebug() << "Post dialog blocked mods list: " << m_blocked_mods;
|
||||
createInstance();
|
||||
} else {
|
||||
abort();
|
||||
}
|
||||
|
||||
} else {
|
||||
createInstance();
|
||||
}
|
||||
}
|
||||
|
||||
void PackInstallTask::createInstance()
|
||||
{
|
||||
setAbortable(false);
|
||||
|
||||
setStatus(tr("Creating the instance..."));
|
||||
QCoreApplication::processEvents();
|
||||
|
||||
auto instanceConfigPath = FS::PathCombine(m_stagingPath, "instance.cfg");
|
||||
auto instanceSettings = std::make_shared<INISettingsObject>(instanceConfigPath);
|
||||
|
||||
MinecraftInstance instance(m_globalSettings, instanceSettings, m_stagingPath);
|
||||
auto components = instance.getPackProfile();
|
||||
components->buildingFromScratch();
|
||||
|
||||
for (auto target : m_version.targets) {
|
||||
if (target.type == "game" && target.name == "minecraft") {
|
||||
components->setComponentVersion("net.minecraft", target.version, true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (auto target : m_version.targets) {
|
||||
if (target.type != "modloader")
|
||||
continue;
|
||||
|
||||
if (target.name == "forge") {
|
||||
components->setComponentVersion("net.minecraftforge", target.version);
|
||||
} else if (target.name == "fabric") {
|
||||
components->setComponentVersion("net.fabricmc.fabric-loader", target.version);
|
||||
}
|
||||
}
|
||||
|
||||
// install any jar mods
|
||||
QDir jarModsDir(FS::PathCombine(m_stagingPath, "minecraft", "jarmods"));
|
||||
if (jarModsDir.exists()) {
|
||||
QStringList jarMods;
|
||||
|
||||
for (const auto& info : jarModsDir.entryInfoList(QDir::NoDotAndDotDot | QDir::Files)) {
|
||||
jarMods.push_back(info.absoluteFilePath());
|
||||
}
|
||||
|
||||
components->installJarMods(jarMods);
|
||||
}
|
||||
|
||||
components->saveNow();
|
||||
|
||||
instance.setName(name());
|
||||
instance.setIconKey(m_instIcon);
|
||||
instance.setManagedPack("modpacksch", QString::number(m_pack.id), m_pack.name, QString::number(m_version.id), m_version.name);
|
||||
|
||||
instance.saveNow();
|
||||
|
||||
onCreateInstanceSucceeded();
|
||||
}
|
||||
|
||||
void PackInstallTask::onCreateInstanceSucceeded()
|
||||
{
|
||||
downloadPack();
|
||||
}
|
||||
|
||||
void PackInstallTask::downloadPack()
|
||||
{
|
||||
setStatus(tr("Downloading mods..."));
|
||||
setAbortable(false);
|
||||
|
||||
auto jobPtr = makeShared<NetJob>(tr("Mod download"), APPLICATION->network());
|
||||
for (auto const& file : m_version.files) {
|
||||
if (file.serverOnly || file.url.isEmpty())
|
||||
continue;
|
||||
|
||||
auto path = FS::PathCombine(m_stagingPath, ".minecraft", file.path, file.name);
|
||||
qDebug() << "Will try to download" << file.url << "to" << path;
|
||||
|
||||
QFileInfo file_info(file.name);
|
||||
|
||||
auto dl = Net::Download::makeFile(file.url, path);
|
||||
if (!file.sha1.isEmpty()) {
|
||||
auto rawSha1 = QByteArray::fromHex(file.sha1.toLatin1());
|
||||
dl->addValidator(new Net::ChecksumValidator(QCryptographicHash::Sha1, rawSha1));
|
||||
}
|
||||
|
||||
jobPtr->addNetAction(dl);
|
||||
}
|
||||
|
||||
connect(jobPtr.get(), &NetJob::succeeded, this, &PackInstallTask::onModDownloadSucceeded);
|
||||
connect(jobPtr.get(), &NetJob::failed, this, &PackInstallTask::onModDownloadFailed);
|
||||
connect(jobPtr.get(), &NetJob::aborted, this, &PackInstallTask::abort);
|
||||
connect(jobPtr.get(), &NetJob::progress, this, &PackInstallTask::setProgress);
|
||||
|
||||
m_net_job = jobPtr;
|
||||
|
||||
setAbortable(true);
|
||||
jobPtr->start();
|
||||
}
|
||||
|
||||
void PackInstallTask::onModDownloadSucceeded()
|
||||
{
|
||||
m_net_job.reset();
|
||||
if (!m_blocked_mods.isEmpty()) {
|
||||
copyBlockedMods();
|
||||
}
|
||||
emitSucceeded();
|
||||
}
|
||||
|
||||
void PackInstallTask::onManifestDownloadFailed(QString reason)
|
||||
{
|
||||
m_net_job.reset();
|
||||
emitFailed(reason);
|
||||
}
|
||||
void PackInstallTask::onResolveModsFailed(QString reason)
|
||||
{
|
||||
m_net_job.reset();
|
||||
emitFailed(reason);
|
||||
}
|
||||
void PackInstallTask::onCreateInstanceFailed(QString reason)
|
||||
{
|
||||
emitFailed(reason);
|
||||
}
|
||||
void PackInstallTask::onModDownloadFailed(QString reason)
|
||||
{
|
||||
m_net_job.reset();
|
||||
emitFailed(reason);
|
||||
}
|
||||
|
||||
/// @brief copy the matched blocked mods to the instance staging area
|
||||
void PackInstallTask::copyBlockedMods()
|
||||
{
|
||||
setStatus(tr("Copying Blocked Mods..."));
|
||||
setAbortable(false);
|
||||
int i = 0;
|
||||
int total = m_blocked_mods.length();
|
||||
setProgress(i, total);
|
||||
for (auto const& mod : m_blocked_mods) {
|
||||
if (!mod.matched) {
|
||||
qDebug() << mod.name << "was not matched to a local file, skipping copy";
|
||||
continue;
|
||||
}
|
||||
|
||||
auto dest_path = FS::PathCombine(m_stagingPath, ".minecraft", mod.targetFolder, mod.name);
|
||||
|
||||
setStatus(tr("Copying Blocked Mods (%1 out of %2 are done)").arg(QString::number(i), QString::number(total)));
|
||||
|
||||
qDebug() << "Will try to copy" << mod.localPath << "to" << dest_path;
|
||||
|
||||
if (!FS::copy(mod.localPath, dest_path)()) {
|
||||
qDebug() << "Copy of" << mod.localPath << "to" << dest_path << "Failed";
|
||||
}
|
||||
|
||||
i++;
|
||||
setProgress(i, total);
|
||||
}
|
||||
|
||||
setAbortable(true);
|
||||
}
|
||||
|
||||
} // namespace ModpacksCH
|
101
launcher/modplatform/modpacksch/FTBPackInstallTask.h
Normal file
@ -0,0 +1,101 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
/*
|
||||
* Prism Launcher - Minecraft Launcher
|
||||
* Copyright (C) 2022 flowln <flowlnlnln@gmail.com>
|
||||
* Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, version 3.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* This file incorporates work covered by the following copyright and
|
||||
* permission notice:
|
||||
*
|
||||
* Copyright 2020-2021 Jamie Mansfield <jmansfield@cadixdev.org>
|
||||
* Copyright 2020-2021 Petr Mrazek <peterix@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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "FTBPackManifest.h"
|
||||
|
||||
#include "InstanceTask.h"
|
||||
#include "QObjectPtr.h"
|
||||
#include "modplatform/flame/FileResolvingTask.h"
|
||||
#include "net/NetJob.h"
|
||||
#include "ui/dialogs/BlockedModsDialog.h"
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
namespace ModpacksCH {
|
||||
|
||||
class PackInstallTask final : public InstanceTask
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit PackInstallTask(Modpack pack, QString version, QWidget* parent = nullptr);
|
||||
~PackInstallTask() override = default;
|
||||
|
||||
bool abort() override;
|
||||
|
||||
protected:
|
||||
void executeTask() override;
|
||||
|
||||
private slots:
|
||||
void onManifestDownloadSucceeded();
|
||||
void onResolveModsSucceeded();
|
||||
void onCreateInstanceSucceeded();
|
||||
void onModDownloadSucceeded();
|
||||
|
||||
void onManifestDownloadFailed(QString reason);
|
||||
void onResolveModsFailed(QString reason);
|
||||
void onCreateInstanceFailed(QString reason);
|
||||
void onModDownloadFailed(QString reason);
|
||||
|
||||
private:
|
||||
void resolveMods();
|
||||
void createInstance();
|
||||
void downloadPack();
|
||||
void copyBlockedMods();
|
||||
|
||||
private:
|
||||
NetJob::Ptr m_net_job = nullptr;
|
||||
shared_qobject_ptr<Flame::FileResolvingTask> m_mod_id_resolver_task = nullptr;
|
||||
|
||||
QList<int> m_file_id_map;
|
||||
|
||||
QByteArray m_response;
|
||||
|
||||
Modpack m_pack;
|
||||
QString m_version_name;
|
||||
Version m_version;
|
||||
|
||||
QMap<QString, QString> m_files_to_copy;
|
||||
QList<BlockedMod> m_blocked_mods;
|
||||
|
||||
//FIXME: nuke
|
||||
QWidget* m_parent;
|
||||
};
|
||||
|
||||
}
|
195
launcher/modplatform/modpacksch/FTBPackManifest.cpp
Normal file
@ -0,0 +1,195 @@
|
||||
// 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 2020 Jamie Mansfield <jmansfield@cadixdev.org>
|
||||
* Copyright 2020-2021 Petr Mrazek <peterix@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 "FTBPackManifest.h"
|
||||
|
||||
#include "Json.h"
|
||||
|
||||
static void loadSpecs(ModpacksCH::Specs & s, QJsonObject & obj)
|
||||
{
|
||||
s.id = Json::requireInteger(obj, "id");
|
||||
s.minimum = Json::requireInteger(obj, "minimum");
|
||||
s.recommended = Json::requireInteger(obj, "recommended");
|
||||
}
|
||||
|
||||
static void loadTag(ModpacksCH::Tag & t, QJsonObject & obj)
|
||||
{
|
||||
t.id = Json::requireInteger(obj, "id");
|
||||
t.name = Json::requireString(obj, "name");
|
||||
}
|
||||
|
||||
static void loadArt(ModpacksCH::Art & a, QJsonObject & obj)
|
||||
{
|
||||
a.id = Json::requireInteger(obj, "id");
|
||||
a.url = Json::requireString(obj, "url");
|
||||
a.type = Json::requireString(obj, "type");
|
||||
a.width = Json::requireInteger(obj, "width");
|
||||
a.height = Json::requireInteger(obj, "height");
|
||||
a.compressed = Json::requireBoolean(obj, "compressed");
|
||||
a.sha1 = Json::requireString(obj, "sha1");
|
||||
a.size = Json::requireInteger(obj, "size");
|
||||
a.updated = Json::requireInteger(obj, "updated");
|
||||
}
|
||||
|
||||
static void loadAuthor(ModpacksCH::Author & a, QJsonObject & obj)
|
||||
{
|
||||
a.id = Json::requireInteger(obj, "id");
|
||||
a.name = Json::requireString(obj, "name");
|
||||
a.type = Json::requireString(obj, "type");
|
||||
a.website = Json::requireString(obj, "website");
|
||||
a.updated = Json::requireInteger(obj, "updated");
|
||||
}
|
||||
|
||||
static void loadVersionInfo(ModpacksCH::VersionInfo & v, QJsonObject & obj)
|
||||
{
|
||||
v.id = Json::requireInteger(obj, "id");
|
||||
v.name = Json::requireString(obj, "name");
|
||||
v.type = Json::requireString(obj, "type");
|
||||
v.updated = Json::requireInteger(obj, "updated");
|
||||
auto specs = Json::requireObject(obj, "specs");
|
||||
loadSpecs(v.specs, specs);
|
||||
}
|
||||
|
||||
void ModpacksCH::loadModpack(ModpacksCH::Modpack & m, QJsonObject & obj)
|
||||
{
|
||||
m.id = Json::requireInteger(obj, "id");
|
||||
m.name = Json::requireString(obj, "name");
|
||||
m.synopsis = Json::requireString(obj, "synopsis");
|
||||
m.description = Json::requireString(obj, "description");
|
||||
m.type = Json::requireString(obj, "type");
|
||||
m.featured = Json::requireBoolean(obj, "featured");
|
||||
m.installs = Json::requireInteger(obj, "installs");
|
||||
m.plays = Json::requireInteger(obj, "plays");
|
||||
m.updated = Json::requireInteger(obj, "updated");
|
||||
m.refreshed = Json::requireInteger(obj, "refreshed");
|
||||
auto artArr = Json::requireArray(obj, "art");
|
||||
for (QJsonValueRef artRaw : artArr)
|
||||
{
|
||||
auto artObj = Json::requireObject(artRaw);
|
||||
ModpacksCH::Art art;
|
||||
loadArt(art, artObj);
|
||||
m.art.append(art);
|
||||
}
|
||||
auto authorArr = Json::requireArray(obj, "authors");
|
||||
for (QJsonValueRef authorRaw : authorArr)
|
||||
{
|
||||
auto authorObj = Json::requireObject(authorRaw);
|
||||
ModpacksCH::Author author;
|
||||
loadAuthor(author, authorObj);
|
||||
m.authors.append(author);
|
||||
}
|
||||
auto versionArr = Json::requireArray(obj, "versions");
|
||||
for (QJsonValueRef versionRaw : versionArr)
|
||||
{
|
||||
auto versionObj = Json::requireObject(versionRaw);
|
||||
ModpacksCH::VersionInfo version;
|
||||
loadVersionInfo(version, versionObj);
|
||||
m.versions.append(version);
|
||||
}
|
||||
auto tagArr = Json::requireArray(obj, "tags");
|
||||
for (QJsonValueRef tagRaw : tagArr)
|
||||
{
|
||||
auto tagObj = Json::requireObject(tagRaw);
|
||||
ModpacksCH::Tag tag;
|
||||
loadTag(tag, tagObj);
|
||||
m.tags.append(tag);
|
||||
}
|
||||
m.updated = Json::requireInteger(obj, "updated");
|
||||
}
|
||||
|
||||
static void loadVersionTarget(ModpacksCH::VersionTarget & a, QJsonObject & obj)
|
||||
{
|
||||
a.id = Json::requireInteger(obj, "id");
|
||||
a.name = Json::requireString(obj, "name");
|
||||
a.type = Json::requireString(obj, "type");
|
||||
a.version = Json::requireString(obj, "version");
|
||||
a.updated = Json::requireInteger(obj, "updated");
|
||||
}
|
||||
|
||||
static void loadVersionFile(ModpacksCH::VersionFile & a, QJsonObject & obj)
|
||||
{
|
||||
a.id = Json::requireInteger(obj, "id");
|
||||
a.type = Json::requireString(obj, "type");
|
||||
a.path = Json::requireString(obj, "path");
|
||||
a.name = Json::requireString(obj, "name");
|
||||
a.version = Json::requireString(obj, "version");
|
||||
a.url = Json::ensureString(obj, "url"); // optional
|
||||
a.sha1 = Json::requireString(obj, "sha1");
|
||||
a.size = Json::requireInteger(obj, "size");
|
||||
a.clientOnly = Json::requireBoolean(obj, "clientonly");
|
||||
a.serverOnly = Json::requireBoolean(obj, "serveronly");
|
||||
a.optional = Json::requireBoolean(obj, "optional");
|
||||
a.updated = Json::requireInteger(obj, "updated");
|
||||
auto curseforgeObj = Json::ensureObject(obj, "curseforge"); // optional
|
||||
a.curseforge.project_id = Json::ensureInteger(curseforgeObj, "project");
|
||||
a.curseforge.file_id = Json::ensureInteger(curseforgeObj, "file");
|
||||
}
|
||||
|
||||
void ModpacksCH::loadVersion(ModpacksCH::Version & m, QJsonObject & obj)
|
||||
{
|
||||
m.id = Json::requireInteger(obj, "id");
|
||||
m.parent = Json::requireInteger(obj, "parent");
|
||||
m.name = Json::requireString(obj, "name");
|
||||
m.type = Json::requireString(obj, "type");
|
||||
m.installs = Json::requireInteger(obj, "installs");
|
||||
m.plays = Json::requireInteger(obj, "plays");
|
||||
m.updated = Json::requireInteger(obj, "updated");
|
||||
m.refreshed = Json::requireInteger(obj, "refreshed");
|
||||
auto specs = Json::requireObject(obj, "specs");
|
||||
loadSpecs(m.specs, specs);
|
||||
auto targetArr = Json::requireArray(obj, "targets");
|
||||
for (QJsonValueRef targetRaw : targetArr)
|
||||
{
|
||||
auto versionObj = Json::requireObject(targetRaw);
|
||||
ModpacksCH::VersionTarget target;
|
||||
loadVersionTarget(target, versionObj);
|
||||
m.targets.append(target);
|
||||
}
|
||||
auto fileArr = Json::requireArray(obj, "files");
|
||||
for (QJsonValueRef fileRaw : fileArr)
|
||||
{
|
||||
auto fileObj = Json::requireObject(fileRaw);
|
||||
ModpacksCH::VersionFile file;
|
||||
loadVersionFile(file, fileObj);
|
||||
m.files.append(file);
|
||||
}
|
||||
}
|
||||
|
||||
//static void loadVersionChangelog(ModpacksCH::VersionChangelog & m, QJsonObject & obj)
|
||||
//{
|
||||
// m.content = Json::requireString(obj, "content");
|
||||
// m.updated = Json::requireInteger(obj, "updated");
|
||||
//}
|
168
launcher/modplatform/modpacksch/FTBPackManifest.h
Normal file
@ -0,0 +1,168 @@
|
||||
// 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 2020-2021 Jamie Mansfield <jmansfield@cadixdev.org>
|
||||
* Copyright 2020 Petr Mrazek <peterix@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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QString>
|
||||
#include <QVector>
|
||||
#include <QUrl>
|
||||
#include <QJsonObject>
|
||||
#include <QMetaType>
|
||||
|
||||
namespace ModpacksCH
|
||||
{
|
||||
|
||||
struct Specs
|
||||
{
|
||||
int id;
|
||||
int minimum;
|
||||
int recommended;
|
||||
};
|
||||
|
||||
struct Tag
|
||||
{
|
||||
int id;
|
||||
QString name;
|
||||
};
|
||||
|
||||
struct Art
|
||||
{
|
||||
int id;
|
||||
QString url;
|
||||
QString type;
|
||||
int width;
|
||||
int height;
|
||||
bool compressed;
|
||||
QString sha1;
|
||||
int size;
|
||||
int64_t updated;
|
||||
};
|
||||
|
||||
struct Author
|
||||
{
|
||||
int id;
|
||||
QString name;
|
||||
QString type;
|
||||
QString website;
|
||||
int64_t updated;
|
||||
};
|
||||
|
||||
struct VersionInfo
|
||||
{
|
||||
int id;
|
||||
QString name;
|
||||
QString type;
|
||||
int64_t updated;
|
||||
Specs specs;
|
||||
};
|
||||
|
||||
struct Modpack
|
||||
{
|
||||
int id;
|
||||
QString name;
|
||||
QString synopsis;
|
||||
QString description;
|
||||
QString type;
|
||||
bool featured;
|
||||
int installs;
|
||||
int plays;
|
||||
int64_t updated;
|
||||
int64_t refreshed;
|
||||
QVector<Art> art;
|
||||
QVector<Author> authors;
|
||||
QVector<VersionInfo> versions;
|
||||
QVector<Tag> tags;
|
||||
};
|
||||
|
||||
struct VersionTarget
|
||||
{
|
||||
int id;
|
||||
QString type;
|
||||
QString name;
|
||||
QString version;
|
||||
int64_t updated;
|
||||
};
|
||||
|
||||
struct VersionFileCurseForge
|
||||
{
|
||||
int project_id;
|
||||
int file_id;
|
||||
};
|
||||
|
||||
struct VersionFile
|
||||
{
|
||||
int id;
|
||||
QString type;
|
||||
QString path;
|
||||
QString name;
|
||||
QString version;
|
||||
QString url;
|
||||
QString sha1;
|
||||
int size;
|
||||
bool clientOnly;
|
||||
bool serverOnly;
|
||||
bool optional;
|
||||
int64_t updated;
|
||||
VersionFileCurseForge curseforge;
|
||||
};
|
||||
|
||||
struct Version
|
||||
{
|
||||
int id;
|
||||
int parent;
|
||||
QString name;
|
||||
QString type;
|
||||
int installs;
|
||||
int plays;
|
||||
int64_t updated;
|
||||
int64_t refreshed;
|
||||
Specs specs;
|
||||
QVector<VersionTarget> targets;
|
||||
QVector<VersionFile> files;
|
||||
};
|
||||
|
||||
struct VersionChangelog
|
||||
{
|
||||
QString content;
|
||||
int64_t updated;
|
||||
};
|
||||
|
||||
void loadModpack(Modpack & m, QJsonObject & obj);
|
||||
|
||||
void loadVersion(Version & m, QJsonObject & obj);
|
||||
}
|
||||
|
||||
Q_DECLARE_METATYPE(ModpacksCH::Modpack)
|
81
launcher/net/FetchFlameAPIKey.cpp
Normal file
@ -0,0 +1,81 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
/*
|
||||
* PolyMC - Minecraft Launcher
|
||||
* Copyright (C) 2022 Lenny McLennington <lenny@sneed.church>
|
||||
*
|
||||
* 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 "FetchFlameAPIKey.h"
|
||||
#include "Application.h"
|
||||
#include <BuildConfig.h>
|
||||
#include <Json.h>
|
||||
|
||||
#include <ui/dialogs/ProgressDialog.h>
|
||||
#include <ui/dialogs/CustomMessageBox.h>
|
||||
|
||||
FetchFlameAPIKey::FetchFlameAPIKey(QObject *parent)
|
||||
: Task{parent}
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void FetchFlameAPIKey::executeTask()
|
||||
{
|
||||
QNetworkRequest req(BuildConfig.FLAME_API_KEY_API_URL);
|
||||
m_reply.reset(APPLICATION->network()->get(req));
|
||||
connect(m_reply.get(), &QNetworkReply::downloadProgress, this, &Task::setProgress);
|
||||
connect(m_reply.get(), &QNetworkReply::finished, this, &FetchFlameAPIKey::downloadFinished);
|
||||
connect(m_reply.get(),
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)
|
||||
&QNetworkReply::errorOccurred,
|
||||
#else
|
||||
qOverload<QNetworkReply::NetworkError>(&QNetworkReply::error),
|
||||
#endif
|
||||
this,
|
||||
[this] (QNetworkReply::NetworkError error) {
|
||||
qCritical() << "Network error: " << error;
|
||||
emitFailed(m_reply->errorString());
|
||||
});
|
||||
|
||||
setStatus(tr("Fetching Curseforge core API key"));
|
||||
}
|
||||
|
||||
void FetchFlameAPIKey::downloadFinished()
|
||||
{
|
||||
auto res = m_reply->readAll();
|
||||
auto doc = QJsonDocument::fromJson(res);
|
||||
|
||||
qDebug() << doc;
|
||||
|
||||
try {
|
||||
auto obj = Json::requireObject(doc);
|
||||
|
||||
auto success = Json::requireBoolean(obj, "ok");
|
||||
|
||||
if (success)
|
||||
{
|
||||
m_result = Json::requireString(obj, "token");
|
||||
emitSucceeded();
|
||||
}
|
||||
else
|
||||
{
|
||||
emitFailed("The API returned an output indicating failure.");
|
||||
}
|
||||
}
|
||||
catch (Json::JsonException&)
|
||||
{
|
||||
qCritical() << "Output: " << res;
|
||||
emitFailed("The API returned an unexpected JSON output.");
|
||||
}
|
||||
}
|
44
launcher/net/FetchFlameAPIKey.h
Normal file
@ -0,0 +1,44 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
/*
|
||||
* PolyMC - Minecraft Launcher
|
||||
* Copyright (C) 2022 Lenny McLennington <lenny@sneed.church>
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
#ifndef FETCHFLAMEAPIKEY_H
|
||||
#define FETCHFLAMEAPIKEY_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QNetworkReply>
|
||||
#include <tasks/Task.h>
|
||||
|
||||
class FetchFlameAPIKey : public Task
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit FetchFlameAPIKey(QObject *parent = nullptr);
|
||||
|
||||
QString m_result;
|
||||
|
||||
public slots:
|
||||
void downloadFinished();
|
||||
|
||||
protected:
|
||||
virtual void executeTask();
|
||||
|
||||
|
||||
std::shared_ptr<QNetworkReply> m_reply;
|
||||
};
|
||||
|
||||
#endif // FETCHFLAMEAPIKEY_H
|
@ -1,57 +1,96 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
<svg width="48" height="48" version="1.1" viewBox="0 0 12.7 12.7" xmlns="http://www.w3.org/2000/svg" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
|
||||
<title>Prism Launcher Logo</title>
|
||||
<g stroke-width=".26458">
|
||||
<path d="m6.35 6.35" fill="#99cd61"/>
|
||||
<path d="m6.35 0.52917-2.5208 4.3656 2.5208 1.4552 2.5203-1.4552 0.10955-3.0996c-1.1511-0.66459-2.3388-1.2661-2.6298-1.2661z" fill="#df6277"/>
|
||||
<path d="m8.9798 1.7952-2.6298 4.5548 2.5203 1.4552 2.5208-4.3656c-0.14552-0.25205-1.2601-0.97975-2.4112-1.6443z" fill="#fb9168"/>
|
||||
<path d="m11.391 3.4396-5.041 2.9104 2.5203 1.4552 2.7389-1.4552c0-1.3292-0.072554-2.6584-0.21808-2.9104z" fill="#f3db6c"/>
|
||||
<path d="m6.35 6.35v2.9104h5.041c0.14552-0.25205 0.21807-1.5812 0.21808-2.9104h-5.2591z" fill="#7ab392"/>
|
||||
<path d="m6.35 6.35v2.9104l2.6298 1.6443c1.1511-0.66459 2.2657-1.3923 2.4112-1.6443l-5.041-2.9104z" fill="#4b7cbc"/>
|
||||
<path d="m6.35 6.35-2.5208 1.4552 2.5208 4.3656c0.29104 0 1.4787-0.60148 2.6298-1.2661l-2.6298-4.5548z" fill="#6f488c"/>
|
||||
<path d="m3.8292 4.8948-2.5203 4.3656c0.29104 0.5041 4.459 2.9104 5.041 2.9104v-5.8208l-2.5208-1.4552z" fill="#4d3f33"/>
|
||||
<path d="m1.309 3.4396c-0.29104 0.5041-0.29104 5.3167 0 5.8208l5.041-2.9104v-2.9104h-5.041z" fill="#7a573b"/>
|
||||
<path d="m6.35 0.52917c-0.58208-2e-8 -4.75 2.4063-5.041 2.9104l5.041 2.9104v-5.8208z" fill="#99cd61"/>
|
||||
|
||||
<svg
|
||||
width="64"
|
||||
height="64"
|
||||
viewBox="0 0 64 64"
|
||||
version="1.1"
|
||||
id="svg99"
|
||||
inkscape:version="1.2.1 (9c6d41e410, 2022-07-14)"
|
||||
sodipodi:docname="org.fn2006.PollyMC.svg"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<sodipodi:namedview
|
||||
id="namedview101"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#000000"
|
||||
borderopacity="0.25"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
inkscape:document-units="px"
|
||||
showgrid="false"
|
||||
inkscape:zoom="12.697086"
|
||||
inkscape:cx="35.638098"
|
||||
inkscape:cy="31.345775"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="994"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="g5269" />
|
||||
<defs
|
||||
id="defs96">
|
||||
<inkscape:path-effect
|
||||
effect="powerclip"
|
||||
id="path-effect5638"
|
||||
is_visible="true"
|
||||
lpeversion="1"
|
||||
inverse="true"
|
||||
flatten="false"
|
||||
hide_clip="false"
|
||||
message="Use fill-rule evenodd on <b>fill and stroke</b> dialog if no flatten result after convert clip to paths." />
|
||||
<inkscape:path-effect
|
||||
effect="powerclip"
|
||||
id="path-effect5562"
|
||||
is_visible="true"
|
||||
lpeversion="1"
|
||||
inverse="true"
|
||||
flatten="false"
|
||||
hide_clip="false"
|
||||
message="Use fill-rule evenodd on <b>fill and stroke</b> dialog if no flatten result after convert clip to paths." />
|
||||
<inkscape:path-effect
|
||||
effect="powerclip"
|
||||
id="path-effect5535"
|
||||
is_visible="true"
|
||||
lpeversion="1"
|
||||
inverse="true"
|
||||
flatten="false"
|
||||
hide_clip="false"
|
||||
message="Use fill-rule evenodd on <b>fill and stroke</b> dialog if no flatten result after convert clip to paths." />
|
||||
</defs>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1">
|
||||
<g
|
||||
id="g5269"
|
||||
clip-path="none"
|
||||
transform="matrix(1.25,0,0,1.25,-8,-10.5)">
|
||||
<path
|
||||
id="path300"
|
||||
style="fill:#8acb01"
|
||||
d="m 8,16 c 0,12 0,24 0,36 8.010417,0 16.020833,0 24.03125,0 0,-0.8 0,-1.6 0,-2.4 3.714062,0 7.428125,0 11.142187,0 0,-0.8 0,-1.6 0,-2.4 4.275521,0 8.551042,0 12.826563,0 C 56,36.8 56,26.4 56,16 40,16 24,16 8,16 Z"
|
||||
inkscape:label="head" />
|
||||
<path
|
||||
id="rect3493"
|
||||
style="fill:#b0af8d;stroke-width:1.39562"
|
||||
inkscape:label="cheek"
|
||||
d="M 19.959999,28.879064 H 32.253197 V 52 H 19.959999 Z" />
|
||||
<path
|
||||
id="rect3491"
|
||||
inkscape:label="eye"
|
||||
d="M 19.960001,28 H 32.333299 V 40 H 19.960001 Z"
|
||||
style="stroke-width:1.00871" />
|
||||
<path
|
||||
id="path352"
|
||||
style="display:inline;fill:#3b3b3b;fill-opacity:1;stroke-width:1.00922"
|
||||
d="m 32,28 c 0,7.333333 0,14.666667 0,22 4,0 8,0 12,0 0,-0.814583 0,-1.629167 0,-2.44375 4,0 8,0 12,0 C 56,41.0375 56,34.51875 56,28 48,28 40,28 32,28 Z"
|
||||
inkscape:label="beak" />
|
||||
</g>
|
||||
<g transform="matrix(.88 0 0 .88 -10.906 -1.2421)">
|
||||
<g transform="translate(13.26 2.2776)">
|
||||
<path transform="matrix(.96975 0 0 .96975 .1921 .1921)" d="m6.3498 2.9393c-0.34105 0-2.7827 1.4099-2.9532 1.7052l2.9532 5.1157 2.9538-5.1157c-0.17052-0.29535-2.6127-1.7052-2.9538-1.7052z" fill="#fff" stroke-width=".26458"/>
|
||||
</g>
|
||||
<path d="m16.746 6.9737 2.8639 4.9609c0.33073 0 2.6991-1.3672 2.8644-1.6536 0.16536-0.28642 0.16536-3.0209 0-3.3073l-2.8644 1.6536z" fill="#dfdfdf" stroke-width=".26458"/>
|
||||
</g>
|
||||
<path d="m3.8299 4.8948c-0.14551 0.25205-0.14553 2.6584 0 2.9104 0.14553 0.25204 2.2292 1.4552 2.5203 1.4552v-2.9104z" fill="#d6d2d2" stroke-width=".26458"/>
|
||||
<metadata>
|
||||
<rdf:RDF>
|
||||
<cc:Work rdf:about="">
|
||||
<dc:title>Prism Launcher Logo</dc:title>
|
||||
<dc:date>19/10/2022</dc:date>
|
||||
<dc:creator>
|
||||
<cc:Agent>
|
||||
<dc:title>Prism Launcher</dc:title>
|
||||
</cc:Agent>
|
||||
</dc:creator>
|
||||
<dc:contributor>
|
||||
<cc:Agent>
|
||||
<dc:title>AutiOne, Boba, ely, Fulmine, gon sawa, Pankakes, tobimori, Zeke</dc:title>
|
||||
</cc:Agent>
|
||||
</dc:contributor>
|
||||
<dc:source>https://github.com/PrismLauncher/PrismLauncher</dc:source>
|
||||
<dc:publisher>
|
||||
<cc:Agent>
|
||||
<dc:title>Prism Launcher</dc:title>
|
||||
</cc:Agent>
|
||||
</dc:publisher>
|
||||
<cc:license rdf:resource="http://creativecommons.org/licenses/by-sa/4.0/"/>
|
||||
</cc:Work>
|
||||
<cc:License rdf:about="http://creativecommons.org/licenses/by-sa/4.0/">
|
||||
<cc:permits rdf:resource="http://creativecommons.org/ns#Reproduction"/>
|
||||
<cc:permits rdf:resource="http://creativecommons.org/ns#Distribution"/>
|
||||
<cc:requires rdf:resource="http://creativecommons.org/ns#Notice"/>
|
||||
<cc:requires rdf:resource="http://creativecommons.org/ns#Attribution"/>
|
||||
<cc:permits rdf:resource="http://creativecommons.org/ns#DerivativeWorks"/>
|
||||
<cc:requires rdf:resource="http://creativecommons.org/ns#ShareAlike"/>
|
||||
</cc:License>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 3.4 KiB After Width: | Height: | Size: 3.3 KiB |
@ -25,5 +25,8 @@
|
||||
<!-- https://commons.wikimedia.org/wiki/File:Teawie_Party.png -->
|
||||
<file alias="teawie-spooky">teawie-spooky.png</file>
|
||||
<!-- https://commons.wikimedia.org/wiki/File:Teawie_Halloween.png -->
|
||||
<file alias="polly">polly.png</file>
|
||||
<file alias="polly-xmas">polly-xmas.png</file>
|
||||
<file alias="polly-bday">polly-bday.png</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
6
launcher/resources/backgrounds/licenses
Normal file
@ -0,0 +1,6 @@
|
||||
licenses for images here;
|
||||
polly.png cc0
|
||||
santa-hat.png cc0
|
||||
party-hat.png Pixabay License
|
||||
polly-xmas.png cc0
|
||||
polly-bday.png Pixabay License
|
BIN
launcher/resources/backgrounds/party-hat.png
Normal file
After Width: | Height: | Size: 112 KiB |
BIN
launcher/resources/backgrounds/polly-bday.png
Normal file
After Width: | Height: | Size: 54 KiB |
BIN
launcher/resources/backgrounds/polly-xmas.png
Normal file
After Width: | Height: | Size: 85 KiB |
BIN
launcher/resources/backgrounds/polly.png
Normal file
After Width: | Height: | Size: 48 KiB |
BIN
launcher/resources/backgrounds/santa-hat.png
Normal file
After Width: | Height: | Size: 863 KiB |
@ -1,57 +1,96 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
<svg width="48" height="48" version="1.1" viewBox="0 0 12.7 12.7" xmlns="http://www.w3.org/2000/svg" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
|
||||
<title>Prism Launcher Logo</title>
|
||||
<g stroke-width=".26458">
|
||||
<path d="m6.35 6.35" fill="#99cd61"/>
|
||||
<path d="m6.35 0.52917-2.5208 4.3656 2.5208 1.4552 2.5203-1.4552 0.10955-3.0996c-1.1511-0.66459-2.3388-1.2661-2.6298-1.2661z" fill="#df6277"/>
|
||||
<path d="m8.9798 1.7952-2.6298 4.5548 2.5203 1.4552 2.5208-4.3656c-0.14552-0.25205-1.2601-0.97975-2.4112-1.6443z" fill="#fb9168"/>
|
||||
<path d="m11.391 3.4396-5.041 2.9104 2.5203 1.4552 2.7389-1.4552c0-1.3292-0.072554-2.6584-0.21808-2.9104z" fill="#f3db6c"/>
|
||||
<path d="m6.35 6.35v2.9104h5.041c0.14552-0.25205 0.21807-1.5812 0.21808-2.9104h-5.2591z" fill="#7ab392"/>
|
||||
<path d="m6.35 6.35v2.9104l2.6298 1.6443c1.1511-0.66459 2.2657-1.3923 2.4112-1.6443l-5.041-2.9104z" fill="#4b7cbc"/>
|
||||
<path d="m6.35 6.35-2.5208 1.4552 2.5208 4.3656c0.29104 0 1.4787-0.60148 2.6298-1.2661l-2.6298-4.5548z" fill="#6f488c"/>
|
||||
<path d="m3.8292 4.8948-2.5203 4.3656c0.29104 0.5041 4.459 2.9104 5.041 2.9104v-5.8208l-2.5208-1.4552z" fill="#4d3f33"/>
|
||||
<path d="m1.309 3.4396c-0.29104 0.5041-0.29104 5.3167 0 5.8208l5.041-2.9104v-2.9104h-5.041z" fill="#7a573b"/>
|
||||
<path d="m6.35 0.52917c-0.58208-2e-8 -4.75 2.4063-5.041 2.9104l5.041 2.9104v-5.8208z" fill="#99cd61"/>
|
||||
|
||||
<svg
|
||||
width="64"
|
||||
height="64"
|
||||
viewBox="0 0 64 64"
|
||||
version="1.1"
|
||||
id="svg99"
|
||||
inkscape:version="1.2.1 (9c6d41e410, 2022-07-14)"
|
||||
sodipodi:docname="org.fn2006.PollyMC.svg"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<sodipodi:namedview
|
||||
id="namedview101"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#000000"
|
||||
borderopacity="0.25"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
inkscape:document-units="px"
|
||||
showgrid="false"
|
||||
inkscape:zoom="12.697086"
|
||||
inkscape:cx="35.638098"
|
||||
inkscape:cy="31.345775"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="994"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="g5269" />
|
||||
<defs
|
||||
id="defs96">
|
||||
<inkscape:path-effect
|
||||
effect="powerclip"
|
||||
id="path-effect5638"
|
||||
is_visible="true"
|
||||
lpeversion="1"
|
||||
inverse="true"
|
||||
flatten="false"
|
||||
hide_clip="false"
|
||||
message="Use fill-rule evenodd on <b>fill and stroke</b> dialog if no flatten result after convert clip to paths." />
|
||||
<inkscape:path-effect
|
||||
effect="powerclip"
|
||||
id="path-effect5562"
|
||||
is_visible="true"
|
||||
lpeversion="1"
|
||||
inverse="true"
|
||||
flatten="false"
|
||||
hide_clip="false"
|
||||
message="Use fill-rule evenodd on <b>fill and stroke</b> dialog if no flatten result after convert clip to paths." />
|
||||
<inkscape:path-effect
|
||||
effect="powerclip"
|
||||
id="path-effect5535"
|
||||
is_visible="true"
|
||||
lpeversion="1"
|
||||
inverse="true"
|
||||
flatten="false"
|
||||
hide_clip="false"
|
||||
message="Use fill-rule evenodd on <b>fill and stroke</b> dialog if no flatten result after convert clip to paths." />
|
||||
</defs>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1">
|
||||
<g
|
||||
id="g5269"
|
||||
clip-path="none"
|
||||
transform="matrix(1.25,0,0,1.25,-8,-10.5)">
|
||||
<path
|
||||
id="path300"
|
||||
style="fill:#8acb01"
|
||||
d="m 8,16 c 0,12 0,24 0,36 8.010417,0 16.020833,0 24.03125,0 0,-0.8 0,-1.6 0,-2.4 3.714062,0 7.428125,0 11.142187,0 0,-0.8 0,-1.6 0,-2.4 4.275521,0 8.551042,0 12.826563,0 C 56,36.8 56,26.4 56,16 40,16 24,16 8,16 Z"
|
||||
inkscape:label="head" />
|
||||
<path
|
||||
id="rect3493"
|
||||
style="fill:#b0af8d;stroke-width:1.39562"
|
||||
inkscape:label="cheek"
|
||||
d="M 19.959999,28.879064 H 32.253197 V 52 H 19.959999 Z" />
|
||||
<path
|
||||
id="rect3491"
|
||||
inkscape:label="eye"
|
||||
d="M 19.960001,28 H 32.333299 V 40 H 19.960001 Z"
|
||||
style="stroke-width:1.00871" />
|
||||
<path
|
||||
id="path352"
|
||||
style="display:inline;fill:#3b3b3b;fill-opacity:1;stroke-width:1.00922"
|
||||
d="m 32,28 c 0,7.333333 0,14.666667 0,22 4,0 8,0 12,0 0,-0.814583 0,-1.629167 0,-2.44375 4,0 8,0 12,0 C 56,41.0375 56,34.51875 56,28 48,28 40,28 32,28 Z"
|
||||
inkscape:label="beak" />
|
||||
</g>
|
||||
<g transform="matrix(.88 0 0 .88 -10.906 -1.2421)">
|
||||
<g transform="translate(13.26 2.2776)">
|
||||
<path transform="matrix(.96975 0 0 .96975 .1921 .1921)" d="m6.3498 2.9393c-0.34105 0-2.7827 1.4099-2.9532 1.7052l2.9532 5.1157 2.9538-5.1157c-0.17052-0.29535-2.6127-1.7052-2.9538-1.7052z" fill="#fff" stroke-width=".26458"/>
|
||||
</g>
|
||||
<path d="m16.746 6.9737 2.8639 4.9609c0.33073 0 2.6991-1.3672 2.8644-1.6536 0.16536-0.28642 0.16536-3.0209 0-3.3073l-2.8644 1.6536z" fill="#dfdfdf" stroke-width=".26458"/>
|
||||
</g>
|
||||
<path d="m3.8299 4.8948c-0.14551 0.25205-0.14553 2.6584 0 2.9104 0.14553 0.25204 2.2292 1.4552 2.5203 1.4552v-2.9104z" fill="#d6d2d2" stroke-width=".26458"/>
|
||||
<metadata>
|
||||
<rdf:RDF>
|
||||
<cc:Work rdf:about="">
|
||||
<dc:title>Prism Launcher Logo</dc:title>
|
||||
<dc:date>19/10/2022</dc:date>
|
||||
<dc:creator>
|
||||
<cc:Agent>
|
||||
<dc:title>Prism Launcher</dc:title>
|
||||
</cc:Agent>
|
||||
</dc:creator>
|
||||
<dc:contributor>
|
||||
<cc:Agent>
|
||||
<dc:title>AutiOne, Boba, ely, Fulmine, gon sawa, Pankakes, tobimori, Zeke</dc:title>
|
||||
</cc:Agent>
|
||||
</dc:contributor>
|
||||
<dc:source>https://github.com/PrismLauncher/PrismLauncher</dc:source>
|
||||
<dc:publisher>
|
||||
<cc:Agent>
|
||||
<dc:title>Prism Launcher</dc:title>
|
||||
</cc:Agent>
|
||||
</dc:publisher>
|
||||
<cc:license rdf:resource="http://creativecommons.org/licenses/by-sa/4.0/"/>
|
||||
</cc:Work>
|
||||
<cc:License rdf:about="http://creativecommons.org/licenses/by-sa/4.0/">
|
||||
<cc:permits rdf:resource="http://creativecommons.org/ns#Reproduction"/>
|
||||
<cc:permits rdf:resource="http://creativecommons.org/ns#Distribution"/>
|
||||
<cc:requires rdf:resource="http://creativecommons.org/ns#Notice"/>
|
||||
<cc:requires rdf:resource="http://creativecommons.org/ns#Attribution"/>
|
||||
<cc:permits rdf:resource="http://creativecommons.org/ns#DerivativeWorks"/>
|
||||
<cc:requires rdf:resource="http://creativecommons.org/ns#ShareAlike"/>
|
||||
</cc:License>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 3.4 KiB After Width: | Height: | Size: 3.3 KiB |
96
launcher/resources/breeze_light/scalable/launcher.svg
Normal file
@ -0,0 +1,96 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
width="64"
|
||||
height="64"
|
||||
viewBox="0 0 64 64"
|
||||
version="1.1"
|
||||
id="svg99"
|
||||
inkscape:version="1.2.1 (9c6d41e410, 2022-07-14)"
|
||||
sodipodi:docname="org.fn2006.PollyMC.svg"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<sodipodi:namedview
|
||||
id="namedview101"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#000000"
|
||||
borderopacity="0.25"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
inkscape:document-units="px"
|
||||
showgrid="false"
|
||||
inkscape:zoom="12.697086"
|
||||
inkscape:cx="35.638098"
|
||||
inkscape:cy="31.345775"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="994"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="g5269" />
|
||||
<defs
|
||||
id="defs96">
|
||||
<inkscape:path-effect
|
||||
effect="powerclip"
|
||||
id="path-effect5638"
|
||||
is_visible="true"
|
||||
lpeversion="1"
|
||||
inverse="true"
|
||||
flatten="false"
|
||||
hide_clip="false"
|
||||
message="Use fill-rule evenodd on <b>fill and stroke</b> dialog if no flatten result after convert clip to paths." />
|
||||
<inkscape:path-effect
|
||||
effect="powerclip"
|
||||
id="path-effect5562"
|
||||
is_visible="true"
|
||||
lpeversion="1"
|
||||
inverse="true"
|
||||
flatten="false"
|
||||
hide_clip="false"
|
||||
message="Use fill-rule evenodd on <b>fill and stroke</b> dialog if no flatten result after convert clip to paths." />
|
||||
<inkscape:path-effect
|
||||
effect="powerclip"
|
||||
id="path-effect5535"
|
||||
is_visible="true"
|
||||
lpeversion="1"
|
||||
inverse="true"
|
||||
flatten="false"
|
||||
hide_clip="false"
|
||||
message="Use fill-rule evenodd on <b>fill and stroke</b> dialog if no flatten result after convert clip to paths." />
|
||||
</defs>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1">
|
||||
<g
|
||||
id="g5269"
|
||||
clip-path="none"
|
||||
transform="matrix(1.25,0,0,1.25,-8,-10.5)">
|
||||
<path
|
||||
id="path300"
|
||||
style="fill:#8acb01"
|
||||
d="m 8,16 c 0,12 0,24 0,36 8.010417,0 16.020833,0 24.03125,0 0,-0.8 0,-1.6 0,-2.4 3.714062,0 7.428125,0 11.142187,0 0,-0.8 0,-1.6 0,-2.4 4.275521,0 8.551042,0 12.826563,0 C 56,36.8 56,26.4 56,16 40,16 24,16 8,16 Z"
|
||||
inkscape:label="head" />
|
||||
<path
|
||||
id="rect3493"
|
||||
style="fill:#b0af8d;stroke-width:1.39562"
|
||||
inkscape:label="cheek"
|
||||
d="M 19.959999,28.879064 H 32.253197 V 52 H 19.959999 Z" />
|
||||
<path
|
||||
id="rect3491"
|
||||
inkscape:label="eye"
|
||||
d="M 19.960001,28 H 32.333299 V 40 H 19.960001 Z"
|
||||
style="stroke-width:1.00871" />
|
||||
<path
|
||||
id="path352"
|
||||
style="display:inline;fill:#3b3b3b;fill-opacity:1;stroke-width:1.00922"
|
||||
d="m 32,28 c 0,7.333333 0,14.666667 0,22 4,0 8,0 12,0 0,-0.814583 0,-1.629167 0,-2.44375 4,0 8,0 12,0 C 56,41.0375 56,34.51875 56,28 48,28 40,28 32,28 Z"
|
||||
inkscape:label="beak" />
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 3.3 KiB |
@ -1,57 +1,96 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
<svg width="48" height="48" version="1.1" viewBox="0 0 12.7 12.7" xmlns="http://www.w3.org/2000/svg" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
|
||||
<title>Prism Launcher Logo</title>
|
||||
<g stroke-width=".26458">
|
||||
<path d="m6.35 6.35" fill="#99cd61"/>
|
||||
<path d="m6.35 0.52917-2.5208 4.3656 2.5208 1.4552 2.5203-1.4552 0.10955-3.0996c-1.1511-0.66459-2.3388-1.2661-2.6298-1.2661z" fill="#df6277"/>
|
||||
<path d="m8.9798 1.7952-2.6298 4.5548 2.5203 1.4552 2.5208-4.3656c-0.14552-0.25205-1.2601-0.97975-2.4112-1.6443z" fill="#fb9168"/>
|
||||
<path d="m11.391 3.4396-5.041 2.9104 2.5203 1.4552 2.7389-1.4552c0-1.3292-0.072554-2.6584-0.21808-2.9104z" fill="#f3db6c"/>
|
||||
<path d="m6.35 6.35v2.9104h5.041c0.14552-0.25205 0.21807-1.5812 0.21808-2.9104h-5.2591z" fill="#7ab392"/>
|
||||
<path d="m6.35 6.35v2.9104l2.6298 1.6443c1.1511-0.66459 2.2657-1.3923 2.4112-1.6443l-5.041-2.9104z" fill="#4b7cbc"/>
|
||||
<path d="m6.35 6.35-2.5208 1.4552 2.5208 4.3656c0.29104 0 1.4787-0.60148 2.6298-1.2661l-2.6298-4.5548z" fill="#6f488c"/>
|
||||
<path d="m3.8292 4.8948-2.5203 4.3656c0.29104 0.5041 4.459 2.9104 5.041 2.9104v-5.8208l-2.5208-1.4552z" fill="#4d3f33"/>
|
||||
<path d="m1.309 3.4396c-0.29104 0.5041-0.29104 5.3167 0 5.8208l5.041-2.9104v-2.9104h-5.041z" fill="#7a573b"/>
|
||||
<path d="m6.35 0.52917c-0.58208-2e-8 -4.75 2.4063-5.041 2.9104l5.041 2.9104v-5.8208z" fill="#99cd61"/>
|
||||
|
||||
<svg
|
||||
width="64"
|
||||
height="64"
|
||||
viewBox="0 0 64 64"
|
||||
version="1.1"
|
||||
id="svg99"
|
||||
inkscape:version="1.2.1 (9c6d41e410, 2022-07-14)"
|
||||
sodipodi:docname="org.fn2006.PollyMC.svg"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<sodipodi:namedview
|
||||
id="namedview101"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#000000"
|
||||
borderopacity="0.25"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
inkscape:document-units="px"
|
||||
showgrid="false"
|
||||
inkscape:zoom="12.697086"
|
||||
inkscape:cx="35.638098"
|
||||
inkscape:cy="31.345775"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="994"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="g5269" />
|
||||
<defs
|
||||
id="defs96">
|
||||
<inkscape:path-effect
|
||||
effect="powerclip"
|
||||
id="path-effect5638"
|
||||
is_visible="true"
|
||||
lpeversion="1"
|
||||
inverse="true"
|
||||
flatten="false"
|
||||
hide_clip="false"
|
||||
message="Use fill-rule evenodd on <b>fill and stroke</b> dialog if no flatten result after convert clip to paths." />
|
||||
<inkscape:path-effect
|
||||
effect="powerclip"
|
||||
id="path-effect5562"
|
||||
is_visible="true"
|
||||
lpeversion="1"
|
||||
inverse="true"
|
||||
flatten="false"
|
||||
hide_clip="false"
|
||||
message="Use fill-rule evenodd on <b>fill and stroke</b> dialog if no flatten result after convert clip to paths." />
|
||||
<inkscape:path-effect
|
||||
effect="powerclip"
|
||||
id="path-effect5535"
|
||||
is_visible="true"
|
||||
lpeversion="1"
|
||||
inverse="true"
|
||||
flatten="false"
|
||||
hide_clip="false"
|
||||
message="Use fill-rule evenodd on <b>fill and stroke</b> dialog if no flatten result after convert clip to paths." />
|
||||
</defs>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1">
|
||||
<g
|
||||
id="g5269"
|
||||
clip-path="none"
|
||||
transform="matrix(1.25,0,0,1.25,-8,-10.5)">
|
||||
<path
|
||||
id="path300"
|
||||
style="fill:#8acb01"
|
||||
d="m 8,16 c 0,12 0,24 0,36 8.010417,0 16.020833,0 24.03125,0 0,-0.8 0,-1.6 0,-2.4 3.714062,0 7.428125,0 11.142187,0 0,-0.8 0,-1.6 0,-2.4 4.275521,0 8.551042,0 12.826563,0 C 56,36.8 56,26.4 56,16 40,16 24,16 8,16 Z"
|
||||
inkscape:label="head" />
|
||||
<path
|
||||
id="rect3493"
|
||||
style="fill:#b0af8d;stroke-width:1.39562"
|
||||
inkscape:label="cheek"
|
||||
d="M 19.959999,28.879064 H 32.253197 V 52 H 19.959999 Z" />
|
||||
<path
|
||||
id="rect3491"
|
||||
inkscape:label="eye"
|
||||
d="M 19.960001,28 H 32.333299 V 40 H 19.960001 Z"
|
||||
style="stroke-width:1.00871" />
|
||||
<path
|
||||
id="path352"
|
||||
style="display:inline;fill:#3b3b3b;fill-opacity:1;stroke-width:1.00922"
|
||||
d="m 32,28 c 0,7.333333 0,14.666667 0,22 4,0 8,0 12,0 0,-0.814583 0,-1.629167 0,-2.44375 4,0 8,0 12,0 C 56,41.0375 56,34.51875 56,28 48,28 40,28 32,28 Z"
|
||||
inkscape:label="beak" />
|
||||
</g>
|
||||
<g transform="matrix(.88 0 0 .88 -10.906 -1.2421)">
|
||||
<g transform="translate(13.26 2.2776)">
|
||||
<path transform="matrix(.96975 0 0 .96975 .1921 .1921)" d="m6.3498 2.9393c-0.34105 0-2.7827 1.4099-2.9532 1.7052l2.9532 5.1157 2.9538-5.1157c-0.17052-0.29535-2.6127-1.7052-2.9538-1.7052z" fill="#fff" stroke-width=".26458"/>
|
||||
</g>
|
||||
<path d="m16.746 6.9737 2.8639 4.9609c0.33073 0 2.6991-1.3672 2.8644-1.6536 0.16536-0.28642 0.16536-3.0209 0-3.3073l-2.8644 1.6536z" fill="#dfdfdf" stroke-width=".26458"/>
|
||||
</g>
|
||||
<path d="m3.8299 4.8948c-0.14551 0.25205-0.14553 2.6584 0 2.9104 0.14553 0.25204 2.2292 1.4552 2.5203 1.4552v-2.9104z" fill="#d6d2d2" stroke-width=".26458"/>
|
||||
<metadata>
|
||||
<rdf:RDF>
|
||||
<cc:Work rdf:about="">
|
||||
<dc:title>Prism Launcher Logo</dc:title>
|
||||
<dc:date>19/10/2022</dc:date>
|
||||
<dc:creator>
|
||||
<cc:Agent>
|
||||
<dc:title>Prism Launcher</dc:title>
|
||||
</cc:Agent>
|
||||
</dc:creator>
|
||||
<dc:contributor>
|
||||
<cc:Agent>
|
||||
<dc:title>AutiOne, Boba, ely, Fulmine, gon sawa, Pankakes, tobimori, Zeke</dc:title>
|
||||
</cc:Agent>
|
||||
</dc:contributor>
|
||||
<dc:source>https://github.com/PrismLauncher/PrismLauncher</dc:source>
|
||||
<dc:publisher>
|
||||
<cc:Agent>
|
||||
<dc:title>Prism Launcher</dc:title>
|
||||
</cc:Agent>
|
||||
</dc:publisher>
|
||||
<cc:license rdf:resource="http://creativecommons.org/licenses/by-sa/4.0/"/>
|
||||
</cc:Work>
|
||||
<cc:License rdf:about="http://creativecommons.org/licenses/by-sa/4.0/">
|
||||
<cc:permits rdf:resource="http://creativecommons.org/ns#Reproduction"/>
|
||||
<cc:permits rdf:resource="http://creativecommons.org/ns#Distribution"/>
|
||||
<cc:requires rdf:resource="http://creativecommons.org/ns#Notice"/>
|
||||
<cc:requires rdf:resource="http://creativecommons.org/ns#Attribution"/>
|
||||
<cc:permits rdf:resource="http://creativecommons.org/ns#DerivativeWorks"/>
|
||||
<cc:requires rdf:resource="http://creativecommons.org/ns#ShareAlike"/>
|
||||
</cc:License>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 3.4 KiB After Width: | Height: | Size: 3.3 KiB |
@ -1,2 +1,96 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="24" height="24" fill="#eeeeee" version="1.1" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="m20 4h-16v16h16zm0 18h-16c-1.1046 0-2-0.89543-2-2v-16c0-1.1046 0.89543-2 2-2h16c1.1046 0 2 0.89543 2 2v16c0 1.1046-0.89543 2-2 2z"/><path d="m7.2 18c-0.225 0-0.45-0.075-0.6-0.15-0.375-0.225-0.6-0.6-0.6-1.05v-9.6c0-0.45 0.225-0.825 0.6-1.05 0.225-0.15 0.375-0.15 0.6-0.15 0.15 0 0.375 0.075 0.525 0.15l9.6 4.8c0.375 0.225 0.675 0.6 0.675 1.05 0 0.45-0.225 0.9-0.675 1.05l-9.6 4.8c-0.15 0.075-0.375 0.15-0.525 0.15z" clip-rule="evenodd" fill="#eeeeee" fill-rule="evenodd" stroke-width=".99999"/></svg>
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
width="64"
|
||||
height="64"
|
||||
viewBox="0 0 64 64"
|
||||
version="1.1"
|
||||
id="svg99"
|
||||
inkscape:version="1.2.1 (9c6d41e410, 2022-07-14)"
|
||||
sodipodi:docname="org.fn2006.PollyMC.svg"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<sodipodi:namedview
|
||||
id="namedview101"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#000000"
|
||||
borderopacity="0.25"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
inkscape:document-units="px"
|
||||
showgrid="false"
|
||||
inkscape:zoom="12.697086"
|
||||
inkscape:cx="35.638098"
|
||||
inkscape:cy="31.345775"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="994"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="g5269" />
|
||||
<defs
|
||||
id="defs96">
|
||||
<inkscape:path-effect
|
||||
effect="powerclip"
|
||||
id="path-effect5638"
|
||||
is_visible="true"
|
||||
lpeversion="1"
|
||||
inverse="true"
|
||||
flatten="false"
|
||||
hide_clip="false"
|
||||
message="Use fill-rule evenodd on <b>fill and stroke</b> dialog if no flatten result after convert clip to paths." />
|
||||
<inkscape:path-effect
|
||||
effect="powerclip"
|
||||
id="path-effect5562"
|
||||
is_visible="true"
|
||||
lpeversion="1"
|
||||
inverse="true"
|
||||
flatten="false"
|
||||
hide_clip="false"
|
||||
message="Use fill-rule evenodd on <b>fill and stroke</b> dialog if no flatten result after convert clip to paths." />
|
||||
<inkscape:path-effect
|
||||
effect="powerclip"
|
||||
id="path-effect5535"
|
||||
is_visible="true"
|
||||
lpeversion="1"
|
||||
inverse="true"
|
||||
flatten="false"
|
||||
hide_clip="false"
|
||||
message="Use fill-rule evenodd on <b>fill and stroke</b> dialog if no flatten result after convert clip to paths." />
|
||||
</defs>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1">
|
||||
<g
|
||||
id="g5269"
|
||||
clip-path="none"
|
||||
transform="matrix(1.25,0,0,1.25,-8,-10.5)">
|
||||
<path
|
||||
id="path300"
|
||||
style="fill:#8acb01"
|
||||
d="m 8,16 c 0,12 0,24 0,36 8.010417,0 16.020833,0 24.03125,0 0,-0.8 0,-1.6 0,-2.4 3.714062,0 7.428125,0 11.142187,0 0,-0.8 0,-1.6 0,-2.4 4.275521,0 8.551042,0 12.826563,0 C 56,36.8 56,26.4 56,16 40,16 24,16 8,16 Z"
|
||||
inkscape:label="head" />
|
||||
<path
|
||||
id="rect3493"
|
||||
style="fill:#b0af8d;stroke-width:1.39562"
|
||||
inkscape:label="cheek"
|
||||
d="M 19.959999,28.879064 H 32.253197 V 52 H 19.959999 Z" />
|
||||
<path
|
||||
id="rect3491"
|
||||
inkscape:label="eye"
|
||||
d="M 19.960001,28 H 32.333299 V 40 H 19.960001 Z"
|
||||
style="stroke-width:1.00871" />
|
||||
<path
|
||||
id="path352"
|
||||
style="display:inline;fill:#3b3b3b;fill-opacity:1;stroke-width:1.00922"
|
||||
d="m 32,28 c 0,7.333333 0,14.666667 0,22 4,0 8,0 12,0 0,-0.814583 0,-1.629167 0,-2.44375 4,0 8,0 12,0 C 56,41.0375 56,34.51875 56,28 48,28 40,28 32,28 Z"
|
||||
inkscape:label="beak" />
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 660 B After Width: | Height: | Size: 3.3 KiB |
@ -1,57 +1,96 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
<svg width="48" height="48" version="1.1" viewBox="0 0 12.7 12.7" xmlns="http://www.w3.org/2000/svg" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
|
||||
<title>Prism Launcher Logo</title>
|
||||
<g stroke-width=".26458">
|
||||
<path d="m6.35 6.35" fill="#99cd61"/>
|
||||
<path d="m6.35 0.52917-2.5208 4.3656 2.5208 1.4552 2.5203-1.4552 0.10955-3.0996c-1.1511-0.66459-2.3388-1.2661-2.6298-1.2661z" fill="#df6277"/>
|
||||
<path d="m8.9798 1.7952-2.6298 4.5548 2.5203 1.4552 2.5208-4.3656c-0.14552-0.25205-1.2601-0.97975-2.4112-1.6443z" fill="#fb9168"/>
|
||||
<path d="m11.391 3.4396-5.041 2.9104 2.5203 1.4552 2.7389-1.4552c0-1.3292-0.072554-2.6584-0.21808-2.9104z" fill="#f3db6c"/>
|
||||
<path d="m6.35 6.35v2.9104h5.041c0.14552-0.25205 0.21807-1.5812 0.21808-2.9104h-5.2591z" fill="#7ab392"/>
|
||||
<path d="m6.35 6.35v2.9104l2.6298 1.6443c1.1511-0.66459 2.2657-1.3923 2.4112-1.6443l-5.041-2.9104z" fill="#4b7cbc"/>
|
||||
<path d="m6.35 6.35-2.5208 1.4552 2.5208 4.3656c0.29104 0 1.4787-0.60148 2.6298-1.2661l-2.6298-4.5548z" fill="#6f488c"/>
|
||||
<path d="m3.8292 4.8948-2.5203 4.3656c0.29104 0.5041 4.459 2.9104 5.041 2.9104v-5.8208l-2.5208-1.4552z" fill="#4d3f33"/>
|
||||
<path d="m1.309 3.4396c-0.29104 0.5041-0.29104 5.3167 0 5.8208l5.041-2.9104v-2.9104h-5.041z" fill="#7a573b"/>
|
||||
<path d="m6.35 0.52917c-0.58208-2e-8 -4.75 2.4063-5.041 2.9104l5.041 2.9104v-5.8208z" fill="#99cd61"/>
|
||||
|
||||
<svg
|
||||
width="64"
|
||||
height="64"
|
||||
viewBox="0 0 64 64"
|
||||
version="1.1"
|
||||
id="svg99"
|
||||
inkscape:version="1.2.1 (9c6d41e410, 2022-07-14)"
|
||||
sodipodi:docname="org.fn2006.PollyMC.svg"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<sodipodi:namedview
|
||||
id="namedview101"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#000000"
|
||||
borderopacity="0.25"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
inkscape:document-units="px"
|
||||
showgrid="false"
|
||||
inkscape:zoom="12.697086"
|
||||
inkscape:cx="35.638098"
|
||||
inkscape:cy="31.345775"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="994"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="g5269" />
|
||||
<defs
|
||||
id="defs96">
|
||||
<inkscape:path-effect
|
||||
effect="powerclip"
|
||||
id="path-effect5638"
|
||||
is_visible="true"
|
||||
lpeversion="1"
|
||||
inverse="true"
|
||||
flatten="false"
|
||||
hide_clip="false"
|
||||
message="Use fill-rule evenodd on <b>fill and stroke</b> dialog if no flatten result after convert clip to paths." />
|
||||
<inkscape:path-effect
|
||||
effect="powerclip"
|
||||
id="path-effect5562"
|
||||
is_visible="true"
|
||||
lpeversion="1"
|
||||
inverse="true"
|
||||
flatten="false"
|
||||
hide_clip="false"
|
||||
message="Use fill-rule evenodd on <b>fill and stroke</b> dialog if no flatten result after convert clip to paths." />
|
||||
<inkscape:path-effect
|
||||
effect="powerclip"
|
||||
id="path-effect5535"
|
||||
is_visible="true"
|
||||
lpeversion="1"
|
||||
inverse="true"
|
||||
flatten="false"
|
||||
hide_clip="false"
|
||||
message="Use fill-rule evenodd on <b>fill and stroke</b> dialog if no flatten result after convert clip to paths." />
|
||||
</defs>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1">
|
||||
<g
|
||||
id="g5269"
|
||||
clip-path="none"
|
||||
transform="matrix(1.25,0,0,1.25,-8,-10.5)">
|
||||
<path
|
||||
id="path300"
|
||||
style="fill:#8acb01"
|
||||
d="m 8,16 c 0,12 0,24 0,36 8.010417,0 16.020833,0 24.03125,0 0,-0.8 0,-1.6 0,-2.4 3.714062,0 7.428125,0 11.142187,0 0,-0.8 0,-1.6 0,-2.4 4.275521,0 8.551042,0 12.826563,0 C 56,36.8 56,26.4 56,16 40,16 24,16 8,16 Z"
|
||||
inkscape:label="head" />
|
||||
<path
|
||||
id="rect3493"
|
||||
style="fill:#b0af8d;stroke-width:1.39562"
|
||||
inkscape:label="cheek"
|
||||
d="M 19.959999,28.879064 H 32.253197 V 52 H 19.959999 Z" />
|
||||
<path
|
||||
id="rect3491"
|
||||
inkscape:label="eye"
|
||||
d="M 19.960001,28 H 32.333299 V 40 H 19.960001 Z"
|
||||
style="stroke-width:1.00871" />
|
||||
<path
|
||||
id="path352"
|
||||
style="display:inline;fill:#3b3b3b;fill-opacity:1;stroke-width:1.00922"
|
||||
d="m 32,28 c 0,7.333333 0,14.666667 0,22 4,0 8,0 12,0 0,-0.814583 0,-1.629167 0,-2.44375 4,0 8,0 12,0 C 56,41.0375 56,34.51875 56,28 48,28 40,28 32,28 Z"
|
||||
inkscape:label="beak" />
|
||||
</g>
|
||||
<g transform="matrix(.88 0 0 .88 -10.906 -1.2421)">
|
||||
<g transform="translate(13.26 2.2776)">
|
||||
<path transform="matrix(.96975 0 0 .96975 .1921 .1921)" d="m6.3498 2.9393c-0.34105 0-2.7827 1.4099-2.9532 1.7052l2.9532 5.1157 2.9538-5.1157c-0.17052-0.29535-2.6127-1.7052-2.9538-1.7052z" fill="#fff" stroke-width=".26458"/>
|
||||
</g>
|
||||
<path d="m16.746 6.9737 2.8639 4.9609c0.33073 0 2.6991-1.3672 2.8644-1.6536 0.16536-0.28642 0.16536-3.0209 0-3.3073l-2.8644 1.6536z" fill="#dfdfdf" stroke-width=".26458"/>
|
||||
</g>
|
||||
<path d="m3.8299 4.8948c-0.14551 0.25205-0.14553 2.6584 0 2.9104 0.14553 0.25204 2.2292 1.4552 2.5203 1.4552v-2.9104z" fill="#d6d2d2" stroke-width=".26458"/>
|
||||
<metadata>
|
||||
<rdf:RDF>
|
||||
<cc:Work rdf:about="">
|
||||
<dc:title>Prism Launcher Logo</dc:title>
|
||||
<dc:date>19/10/2022</dc:date>
|
||||
<dc:creator>
|
||||
<cc:Agent>
|
||||
<dc:title>Prism Launcher</dc:title>
|
||||
</cc:Agent>
|
||||
</dc:creator>
|
||||
<dc:contributor>
|
||||
<cc:Agent>
|
||||
<dc:title>AutiOne, Boba, ely, Fulmine, gon sawa, Pankakes, tobimori, Zeke</dc:title>
|
||||
</cc:Agent>
|
||||
</dc:contributor>
|
||||
<dc:source>https://github.com/PrismLauncher/PrismLauncher</dc:source>
|
||||
<dc:publisher>
|
||||
<cc:Agent>
|
||||
<dc:title>Prism Launcher</dc:title>
|
||||
</cc:Agent>
|
||||
</dc:publisher>
|
||||
<cc:license rdf:resource="http://creativecommons.org/licenses/by-sa/4.0/"/>
|
||||
</cc:Work>
|
||||
<cc:License rdf:about="http://creativecommons.org/licenses/by-sa/4.0/">
|
||||
<cc:permits rdf:resource="http://creativecommons.org/ns#Reproduction"/>
|
||||
<cc:permits rdf:resource="http://creativecommons.org/ns#Distribution"/>
|
||||
<cc:requires rdf:resource="http://creativecommons.org/ns#Notice"/>
|
||||
<cc:requires rdf:resource="http://creativecommons.org/ns#Attribution"/>
|
||||
<cc:permits rdf:resource="http://creativecommons.org/ns#DerivativeWorks"/>
|
||||
<cc:requires rdf:resource="http://creativecommons.org/ns#ShareAlike"/>
|
||||
</cc:License>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 3.4 KiB After Width: | Height: | Size: 3.3 KiB |
@ -1,57 +1,96 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
<svg width="48" height="48" version="1.1" viewBox="0 0 12.7 12.7" xmlns="http://www.w3.org/2000/svg" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
|
||||
<title>Prism Launcher Logo</title>
|
||||
<g stroke-width=".26458">
|
||||
<path d="m6.35 6.35" fill="#99cd61"/>
|
||||
<path d="m6.35 0.52917-2.5208 4.3656 2.5208 1.4552 2.5203-1.4552 0.10955-3.0996c-1.1511-0.66459-2.3388-1.2661-2.6298-1.2661z" fill="#df6277"/>
|
||||
<path d="m8.9798 1.7952-2.6298 4.5548 2.5203 1.4552 2.5208-4.3656c-0.14552-0.25205-1.2601-0.97975-2.4112-1.6443z" fill="#fb9168"/>
|
||||
<path d="m11.391 3.4396-5.041 2.9104 2.5203 1.4552 2.7389-1.4552c0-1.3292-0.072554-2.6584-0.21808-2.9104z" fill="#f3db6c"/>
|
||||
<path d="m6.35 6.35v2.9104h5.041c0.14552-0.25205 0.21807-1.5812 0.21808-2.9104h-5.2591z" fill="#7ab392"/>
|
||||
<path d="m6.35 6.35v2.9104l2.6298 1.6443c1.1511-0.66459 2.2657-1.3923 2.4112-1.6443l-5.041-2.9104z" fill="#4b7cbc"/>
|
||||
<path d="m6.35 6.35-2.5208 1.4552 2.5208 4.3656c0.29104 0 1.4787-0.60148 2.6298-1.2661l-2.6298-4.5548z" fill="#6f488c"/>
|
||||
<path d="m3.8292 4.8948-2.5203 4.3656c0.29104 0.5041 4.459 2.9104 5.041 2.9104v-5.8208l-2.5208-1.4552z" fill="#4d3f33"/>
|
||||
<path d="m1.309 3.4396c-0.29104 0.5041-0.29104 5.3167 0 5.8208l5.041-2.9104v-2.9104h-5.041z" fill="#7a573b"/>
|
||||
<path d="m6.35 0.52917c-0.58208-2e-8 -4.75 2.4063-5.041 2.9104l5.041 2.9104v-5.8208z" fill="#99cd61"/>
|
||||
|
||||
<svg
|
||||
width="64"
|
||||
height="64"
|
||||
viewBox="0 0 64 64"
|
||||
version="1.1"
|
||||
id="svg99"
|
||||
inkscape:version="1.2.1 (9c6d41e410, 2022-07-14)"
|
||||
sodipodi:docname="org.fn2006.PollyMC.svg"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<sodipodi:namedview
|
||||
id="namedview101"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#000000"
|
||||
borderopacity="0.25"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
inkscape:document-units="px"
|
||||
showgrid="false"
|
||||
inkscape:zoom="12.697086"
|
||||
inkscape:cx="35.638098"
|
||||
inkscape:cy="31.345775"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="994"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="g5269" />
|
||||
<defs
|
||||
id="defs96">
|
||||
<inkscape:path-effect
|
||||
effect="powerclip"
|
||||
id="path-effect5638"
|
||||
is_visible="true"
|
||||
lpeversion="1"
|
||||
inverse="true"
|
||||
flatten="false"
|
||||
hide_clip="false"
|
||||
message="Use fill-rule evenodd on <b>fill and stroke</b> dialog if no flatten result after convert clip to paths." />
|
||||
<inkscape:path-effect
|
||||
effect="powerclip"
|
||||
id="path-effect5562"
|
||||
is_visible="true"
|
||||
lpeversion="1"
|
||||
inverse="true"
|
||||
flatten="false"
|
||||
hide_clip="false"
|
||||
message="Use fill-rule evenodd on <b>fill and stroke</b> dialog if no flatten result after convert clip to paths." />
|
||||
<inkscape:path-effect
|
||||
effect="powerclip"
|
||||
id="path-effect5535"
|
||||
is_visible="true"
|
||||
lpeversion="1"
|
||||
inverse="true"
|
||||
flatten="false"
|
||||
hide_clip="false"
|
||||
message="Use fill-rule evenodd on <b>fill and stroke</b> dialog if no flatten result after convert clip to paths." />
|
||||
</defs>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1">
|
||||
<g
|
||||
id="g5269"
|
||||
clip-path="none"
|
||||
transform="matrix(1.25,0,0,1.25,-8,-10.5)">
|
||||
<path
|
||||
id="path300"
|
||||
style="fill:#8acb01"
|
||||
d="m 8,16 c 0,12 0,24 0,36 8.010417,0 16.020833,0 24.03125,0 0,-0.8 0,-1.6 0,-2.4 3.714062,0 7.428125,0 11.142187,0 0,-0.8 0,-1.6 0,-2.4 4.275521,0 8.551042,0 12.826563,0 C 56,36.8 56,26.4 56,16 40,16 24,16 8,16 Z"
|
||||
inkscape:label="head" />
|
||||
<path
|
||||
id="rect3493"
|
||||
style="fill:#b0af8d;stroke-width:1.39562"
|
||||
inkscape:label="cheek"
|
||||
d="M 19.959999,28.879064 H 32.253197 V 52 H 19.959999 Z" />
|
||||
<path
|
||||
id="rect3491"
|
||||
inkscape:label="eye"
|
||||
d="M 19.960001,28 H 32.333299 V 40 H 19.960001 Z"
|
||||
style="stroke-width:1.00871" />
|
||||
<path
|
||||
id="path352"
|
||||
style="display:inline;fill:#3b3b3b;fill-opacity:1;stroke-width:1.00922"
|
||||
d="m 32,28 c 0,7.333333 0,14.666667 0,22 4,0 8,0 12,0 0,-0.814583 0,-1.629167 0,-2.44375 4,0 8,0 12,0 C 56,41.0375 56,34.51875 56,28 48,28 40,28 32,28 Z"
|
||||
inkscape:label="beak" />
|
||||
</g>
|
||||
<g transform="matrix(.88 0 0 .88 -10.906 -1.2421)">
|
||||
<g transform="translate(13.26 2.2776)">
|
||||
<path transform="matrix(.96975 0 0 .96975 .1921 .1921)" d="m6.3498 2.9393c-0.34105 0-2.7827 1.4099-2.9532 1.7052l2.9532 5.1157 2.9538-5.1157c-0.17052-0.29535-2.6127-1.7052-2.9538-1.7052z" fill="#fff" stroke-width=".26458"/>
|
||||
</g>
|
||||
<path d="m16.746 6.9737 2.8639 4.9609c0.33073 0 2.6991-1.3672 2.8644-1.6536 0.16536-0.28642 0.16536-3.0209 0-3.3073l-2.8644 1.6536z" fill="#dfdfdf" stroke-width=".26458"/>
|
||||
</g>
|
||||
<path d="m3.8299 4.8948c-0.14551 0.25205-0.14553 2.6584 0 2.9104 0.14553 0.25204 2.2292 1.4552 2.5203 1.4552v-2.9104z" fill="#d6d2d2" stroke-width=".26458"/>
|
||||
<metadata>
|
||||
<rdf:RDF>
|
||||
<cc:Work rdf:about="">
|
||||
<dc:title>Prism Launcher Logo</dc:title>
|
||||
<dc:date>19/10/2022</dc:date>
|
||||
<dc:creator>
|
||||
<cc:Agent>
|
||||
<dc:title>Prism Launcher</dc:title>
|
||||
</cc:Agent>
|
||||
</dc:creator>
|
||||
<dc:contributor>
|
||||
<cc:Agent>
|
||||
<dc:title>AutiOne, Boba, ely, Fulmine, gon sawa, Pankakes, tobimori, Zeke</dc:title>
|
||||
</cc:Agent>
|
||||
</dc:contributor>
|
||||
<dc:source>https://github.com/PrismLauncher/PrismLauncher</dc:source>
|
||||
<dc:publisher>
|
||||
<cc:Agent>
|
||||
<dc:title>Prism Launcher</dc:title>
|
||||
</cc:Agent>
|
||||
</dc:publisher>
|
||||
<cc:license rdf:resource="http://creativecommons.org/licenses/by-sa/4.0/"/>
|
||||
</cc:Work>
|
||||
<cc:License rdf:about="http://creativecommons.org/licenses/by-sa/4.0/">
|
||||
<cc:permits rdf:resource="http://creativecommons.org/ns#Reproduction"/>
|
||||
<cc:permits rdf:resource="http://creativecommons.org/ns#Distribution"/>
|
||||
<cc:requires rdf:resource="http://creativecommons.org/ns#Notice"/>
|
||||
<cc:requires rdf:resource="http://creativecommons.org/ns#Attribution"/>
|
||||
<cc:permits rdf:resource="http://creativecommons.org/ns#DerivativeWorks"/>
|
||||
<cc:requires rdf:resource="http://creativecommons.org/ns#ShareAlike"/>
|
||||
</cc:License>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 3.4 KiB After Width: | Height: | Size: 3.3 KiB |
@ -1,57 +1,96 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
<svg width="48" height="48" version="1.1" viewBox="0 0 12.7 12.7" xmlns="http://www.w3.org/2000/svg" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
|
||||
<title>Prism Launcher Logo</title>
|
||||
<g stroke-width=".26458">
|
||||
<path d="m6.35 6.35" fill="#99cd61"/>
|
||||
<path d="m6.35 0.52917-2.5208 4.3656 2.5208 1.4552 2.5203-1.4552 0.10955-3.0996c-1.1511-0.66459-2.3388-1.2661-2.6298-1.2661z" fill="#df6277"/>
|
||||
<path d="m8.9798 1.7952-2.6298 4.5548 2.5203 1.4552 2.5208-4.3656c-0.14552-0.25205-1.2601-0.97975-2.4112-1.6443z" fill="#fb9168"/>
|
||||
<path d="m11.391 3.4396-5.041 2.9104 2.5203 1.4552 2.7389-1.4552c0-1.3292-0.072554-2.6584-0.21808-2.9104z" fill="#f3db6c"/>
|
||||
<path d="m6.35 6.35v2.9104h5.041c0.14552-0.25205 0.21807-1.5812 0.21808-2.9104h-5.2591z" fill="#7ab392"/>
|
||||
<path d="m6.35 6.35v2.9104l2.6298 1.6443c1.1511-0.66459 2.2657-1.3923 2.4112-1.6443l-5.041-2.9104z" fill="#4b7cbc"/>
|
||||
<path d="m6.35 6.35-2.5208 1.4552 2.5208 4.3656c0.29104 0 1.4787-0.60148 2.6298-1.2661l-2.6298-4.5548z" fill="#6f488c"/>
|
||||
<path d="m3.8292 4.8948-2.5203 4.3656c0.29104 0.5041 4.459 2.9104 5.041 2.9104v-5.8208l-2.5208-1.4552z" fill="#4d3f33"/>
|
||||
<path d="m1.309 3.4396c-0.29104 0.5041-0.29104 5.3167 0 5.8208l5.041-2.9104v-2.9104h-5.041z" fill="#7a573b"/>
|
||||
<path d="m6.35 0.52917c-0.58208-2e-8 -4.75 2.4063-5.041 2.9104l5.041 2.9104v-5.8208z" fill="#99cd61"/>
|
||||
|
||||
<svg
|
||||
width="64"
|
||||
height="64"
|
||||
viewBox="0 0 64 64"
|
||||
version="1.1"
|
||||
id="svg99"
|
||||
inkscape:version="1.2.1 (9c6d41e410, 2022-07-14)"
|
||||
sodipodi:docname="org.fn2006.PollyMC.svg"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<sodipodi:namedview
|
||||
id="namedview101"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#000000"
|
||||
borderopacity="0.25"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
inkscape:document-units="px"
|
||||
showgrid="false"
|
||||
inkscape:zoom="12.697086"
|
||||
inkscape:cx="35.638098"
|
||||
inkscape:cy="31.345775"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="994"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="g5269" />
|
||||
<defs
|
||||
id="defs96">
|
||||
<inkscape:path-effect
|
||||
effect="powerclip"
|
||||
id="path-effect5638"
|
||||
is_visible="true"
|
||||
lpeversion="1"
|
||||
inverse="true"
|
||||
flatten="false"
|
||||
hide_clip="false"
|
||||
message="Use fill-rule evenodd on <b>fill and stroke</b> dialog if no flatten result after convert clip to paths." />
|
||||
<inkscape:path-effect
|
||||
effect="powerclip"
|
||||
id="path-effect5562"
|
||||
is_visible="true"
|
||||
lpeversion="1"
|
||||
inverse="true"
|
||||
flatten="false"
|
||||
hide_clip="false"
|
||||
message="Use fill-rule evenodd on <b>fill and stroke</b> dialog if no flatten result after convert clip to paths." />
|
||||
<inkscape:path-effect
|
||||
effect="powerclip"
|
||||
id="path-effect5535"
|
||||
is_visible="true"
|
||||
lpeversion="1"
|
||||
inverse="true"
|
||||
flatten="false"
|
||||
hide_clip="false"
|
||||
message="Use fill-rule evenodd on <b>fill and stroke</b> dialog if no flatten result after convert clip to paths." />
|
||||
</defs>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1">
|
||||
<g
|
||||
id="g5269"
|
||||
clip-path="none"
|
||||
transform="matrix(1.25,0,0,1.25,-8,-10.5)">
|
||||
<path
|
||||
id="path300"
|
||||
style="fill:#8acb01"
|
||||
d="m 8,16 c 0,12 0,24 0,36 8.010417,0 16.020833,0 24.03125,0 0,-0.8 0,-1.6 0,-2.4 3.714062,0 7.428125,0 11.142187,0 0,-0.8 0,-1.6 0,-2.4 4.275521,0 8.551042,0 12.826563,0 C 56,36.8 56,26.4 56,16 40,16 24,16 8,16 Z"
|
||||
inkscape:label="head" />
|
||||
<path
|
||||
id="rect3493"
|
||||
style="fill:#b0af8d;stroke-width:1.39562"
|
||||
inkscape:label="cheek"
|
||||
d="M 19.959999,28.879064 H 32.253197 V 52 H 19.959999 Z" />
|
||||
<path
|
||||
id="rect3491"
|
||||
inkscape:label="eye"
|
||||
d="M 19.960001,28 H 32.333299 V 40 H 19.960001 Z"
|
||||
style="stroke-width:1.00871" />
|
||||
<path
|
||||
id="path352"
|
||||
style="display:inline;fill:#3b3b3b;fill-opacity:1;stroke-width:1.00922"
|
||||
d="m 32,28 c 0,7.333333 0,14.666667 0,22 4,0 8,0 12,0 0,-0.814583 0,-1.629167 0,-2.44375 4,0 8,0 12,0 C 56,41.0375 56,34.51875 56,28 48,28 40,28 32,28 Z"
|
||||
inkscape:label="beak" />
|
||||
</g>
|
||||
<g transform="matrix(.88 0 0 .88 -10.906 -1.2421)">
|
||||
<g transform="translate(13.26 2.2776)">
|
||||
<path transform="matrix(.96975 0 0 .96975 .1921 .1921)" d="m6.3498 2.9393c-0.34105 0-2.7827 1.4099-2.9532 1.7052l2.9532 5.1157 2.9538-5.1157c-0.17052-0.29535-2.6127-1.7052-2.9538-1.7052z" fill="#fff" stroke-width=".26458"/>
|
||||
</g>
|
||||
<path d="m16.746 6.9737 2.8639 4.9609c0.33073 0 2.6991-1.3672 2.8644-1.6536 0.16536-0.28642 0.16536-3.0209 0-3.3073l-2.8644 1.6536z" fill="#dfdfdf" stroke-width=".26458"/>
|
||||
</g>
|
||||
<path d="m3.8299 4.8948c-0.14551 0.25205-0.14553 2.6584 0 2.9104 0.14553 0.25204 2.2292 1.4552 2.5203 1.4552v-2.9104z" fill="#d6d2d2" stroke-width=".26458"/>
|
||||
<metadata>
|
||||
<rdf:RDF>
|
||||
<cc:Work rdf:about="">
|
||||
<dc:title>Prism Launcher Logo</dc:title>
|
||||
<dc:date>19/10/2022</dc:date>
|
||||
<dc:creator>
|
||||
<cc:Agent>
|
||||
<dc:title>Prism Launcher</dc:title>
|
||||
</cc:Agent>
|
||||
</dc:creator>
|
||||
<dc:contributor>
|
||||
<cc:Agent>
|
||||
<dc:title>AutiOne, Boba, ely, Fulmine, gon sawa, Pankakes, tobimori, Zeke</dc:title>
|
||||
</cc:Agent>
|
||||
</dc:contributor>
|
||||
<dc:source>https://github.com/PrismLauncher/PrismLauncher</dc:source>
|
||||
<dc:publisher>
|
||||
<cc:Agent>
|
||||
<dc:title>Prism Launcher</dc:title>
|
||||
</cc:Agent>
|
||||
</dc:publisher>
|
||||
<cc:license rdf:resource="http://creativecommons.org/licenses/by-sa/4.0/"/>
|
||||
</cc:Work>
|
||||
<cc:License rdf:about="http://creativecommons.org/licenses/by-sa/4.0/">
|
||||
<cc:permits rdf:resource="http://creativecommons.org/ns#Reproduction"/>
|
||||
<cc:permits rdf:resource="http://creativecommons.org/ns#Distribution"/>
|
||||
<cc:requires rdf:resource="http://creativecommons.org/ns#Notice"/>
|
||||
<cc:requires rdf:resource="http://creativecommons.org/ns#Attribution"/>
|
||||
<cc:permits rdf:resource="http://creativecommons.org/ns#DerivativeWorks"/>
|
||||
<cc:requires rdf:resource="http://creativecommons.org/ns#ShareAlike"/>
|
||||
</cc:License>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 3.4 KiB After Width: | Height: | Size: 3.3 KiB |
@ -1,57 +1,96 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
<svg width="48" height="48" version="1.1" viewBox="0 0 12.7 12.7" xmlns="http://www.w3.org/2000/svg" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
|
||||
<title>Prism Launcher Logo</title>
|
||||
<g stroke-width=".26458">
|
||||
<path d="m6.35 6.35" fill="#99cd61"/>
|
||||
<path d="m6.35 0.52917-2.5208 4.3656 2.5208 1.4552 2.5203-1.4552 0.10955-3.0996c-1.1511-0.66459-2.3388-1.2661-2.6298-1.2661z" fill="#df6277"/>
|
||||
<path d="m8.9798 1.7952-2.6298 4.5548 2.5203 1.4552 2.5208-4.3656c-0.14552-0.25205-1.2601-0.97975-2.4112-1.6443z" fill="#fb9168"/>
|
||||
<path d="m11.391 3.4396-5.041 2.9104 2.5203 1.4552 2.7389-1.4552c0-1.3292-0.072554-2.6584-0.21808-2.9104z" fill="#f3db6c"/>
|
||||
<path d="m6.35 6.35v2.9104h5.041c0.14552-0.25205 0.21807-1.5812 0.21808-2.9104h-5.2591z" fill="#7ab392"/>
|
||||
<path d="m6.35 6.35v2.9104l2.6298 1.6443c1.1511-0.66459 2.2657-1.3923 2.4112-1.6443l-5.041-2.9104z" fill="#4b7cbc"/>
|
||||
<path d="m6.35 6.35-2.5208 1.4552 2.5208 4.3656c0.29104 0 1.4787-0.60148 2.6298-1.2661l-2.6298-4.5548z" fill="#6f488c"/>
|
||||
<path d="m3.8292 4.8948-2.5203 4.3656c0.29104 0.5041 4.459 2.9104 5.041 2.9104v-5.8208l-2.5208-1.4552z" fill="#4d3f33"/>
|
||||
<path d="m1.309 3.4396c-0.29104 0.5041-0.29104 5.3167 0 5.8208l5.041-2.9104v-2.9104h-5.041z" fill="#7a573b"/>
|
||||
<path d="m6.35 0.52917c-0.58208-2e-8 -4.75 2.4063-5.041 2.9104l5.041 2.9104v-5.8208z" fill="#99cd61"/>
|
||||
|
||||
<svg
|
||||
width="64"
|
||||
height="64"
|
||||
viewBox="0 0 64 64"
|
||||
version="1.1"
|
||||
id="svg99"
|
||||
inkscape:version="1.2.1 (9c6d41e410, 2022-07-14)"
|
||||
sodipodi:docname="org.fn2006.PollyMC.svg"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<sodipodi:namedview
|
||||
id="namedview101"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#000000"
|
||||
borderopacity="0.25"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
inkscape:document-units="px"
|
||||
showgrid="false"
|
||||
inkscape:zoom="12.697086"
|
||||
inkscape:cx="35.638098"
|
||||
inkscape:cy="31.345775"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="994"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="g5269" />
|
||||
<defs
|
||||
id="defs96">
|
||||
<inkscape:path-effect
|
||||
effect="powerclip"
|
||||
id="path-effect5638"
|
||||
is_visible="true"
|
||||
lpeversion="1"
|
||||
inverse="true"
|
||||
flatten="false"
|
||||
hide_clip="false"
|
||||
message="Use fill-rule evenodd on <b>fill and stroke</b> dialog if no flatten result after convert clip to paths." />
|
||||
<inkscape:path-effect
|
||||
effect="powerclip"
|
||||
id="path-effect5562"
|
||||
is_visible="true"
|
||||
lpeversion="1"
|
||||
inverse="true"
|
||||
flatten="false"
|
||||
hide_clip="false"
|
||||
message="Use fill-rule evenodd on <b>fill and stroke</b> dialog if no flatten result after convert clip to paths." />
|
||||
<inkscape:path-effect
|
||||
effect="powerclip"
|
||||
id="path-effect5535"
|
||||
is_visible="true"
|
||||
lpeversion="1"
|
||||
inverse="true"
|
||||
flatten="false"
|
||||
hide_clip="false"
|
||||
message="Use fill-rule evenodd on <b>fill and stroke</b> dialog if no flatten result after convert clip to paths." />
|
||||
</defs>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1">
|
||||
<g
|
||||
id="g5269"
|
||||
clip-path="none"
|
||||
transform="matrix(1.25,0,0,1.25,-8,-10.5)">
|
||||
<path
|
||||
id="path300"
|
||||
style="fill:#8acb01"
|
||||
d="m 8,16 c 0,12 0,24 0,36 8.010417,0 16.020833,0 24.03125,0 0,-0.8 0,-1.6 0,-2.4 3.714062,0 7.428125,0 11.142187,0 0,-0.8 0,-1.6 0,-2.4 4.275521,0 8.551042,0 12.826563,0 C 56,36.8 56,26.4 56,16 40,16 24,16 8,16 Z"
|
||||
inkscape:label="head" />
|
||||
<path
|
||||
id="rect3493"
|
||||
style="fill:#b0af8d;stroke-width:1.39562"
|
||||
inkscape:label="cheek"
|
||||
d="M 19.959999,28.879064 H 32.253197 V 52 H 19.959999 Z" />
|
||||
<path
|
||||
id="rect3491"
|
||||
inkscape:label="eye"
|
||||
d="M 19.960001,28 H 32.333299 V 40 H 19.960001 Z"
|
||||
style="stroke-width:1.00871" />
|
||||
<path
|
||||
id="path352"
|
||||
style="display:inline;fill:#3b3b3b;fill-opacity:1;stroke-width:1.00922"
|
||||
d="m 32,28 c 0,7.333333 0,14.666667 0,22 4,0 8,0 12,0 0,-0.814583 0,-1.629167 0,-2.44375 4,0 8,0 12,0 C 56,41.0375 56,34.51875 56,28 48,28 40,28 32,28 Z"
|
||||
inkscape:label="beak" />
|
||||
</g>
|
||||
<g transform="matrix(.88 0 0 .88 -10.906 -1.2421)">
|
||||
<g transform="translate(13.26 2.2776)">
|
||||
<path transform="matrix(.96975 0 0 .96975 .1921 .1921)" d="m6.3498 2.9393c-0.34105 0-2.7827 1.4099-2.9532 1.7052l2.9532 5.1157 2.9538-5.1157c-0.17052-0.29535-2.6127-1.7052-2.9538-1.7052z" fill="#fff" stroke-width=".26458"/>
|
||||
</g>
|
||||
<path d="m16.746 6.9737 2.8639 4.9609c0.33073 0 2.6991-1.3672 2.8644-1.6536 0.16536-0.28642 0.16536-3.0209 0-3.3073l-2.8644 1.6536z" fill="#dfdfdf" stroke-width=".26458"/>
|
||||
</g>
|
||||
<path d="m3.8299 4.8948c-0.14551 0.25205-0.14553 2.6584 0 2.9104 0.14553 0.25204 2.2292 1.4552 2.5203 1.4552v-2.9104z" fill="#d6d2d2" stroke-width=".26458"/>
|
||||
<metadata>
|
||||
<rdf:RDF>
|
||||
<cc:Work rdf:about="">
|
||||
<dc:title>Prism Launcher Logo</dc:title>
|
||||
<dc:date>19/10/2022</dc:date>
|
||||
<dc:creator>
|
||||
<cc:Agent>
|
||||
<dc:title>Prism Launcher</dc:title>
|
||||
</cc:Agent>
|
||||
</dc:creator>
|
||||
<dc:contributor>
|
||||
<cc:Agent>
|
||||
<dc:title>AutiOne, Boba, ely, Fulmine, gon sawa, Pankakes, tobimori, Zeke</dc:title>
|
||||
</cc:Agent>
|
||||
</dc:contributor>
|
||||
<dc:source>https://github.com/PrismLauncher/PrismLauncher</dc:source>
|
||||
<dc:publisher>
|
||||
<cc:Agent>
|
||||
<dc:title>Prism Launcher</dc:title>
|
||||
</cc:Agent>
|
||||
</dc:publisher>
|
||||
<cc:license rdf:resource="http://creativecommons.org/licenses/by-sa/4.0/"/>
|
||||
</cc:Work>
|
||||
<cc:License rdf:about="http://creativecommons.org/licenses/by-sa/4.0/">
|
||||
<cc:permits rdf:resource="http://creativecommons.org/ns#Reproduction"/>
|
||||
<cc:permits rdf:resource="http://creativecommons.org/ns#Distribution"/>
|
||||
<cc:requires rdf:resource="http://creativecommons.org/ns#Notice"/>
|
||||
<cc:requires rdf:resource="http://creativecommons.org/ns#Attribution"/>
|
||||
<cc:permits rdf:resource="http://creativecommons.org/ns#DerivativeWorks"/>
|
||||
<cc:requires rdf:resource="http://creativecommons.org/ns#ShareAlike"/>
|
||||
</cc:License>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 3.4 KiB After Width: | Height: | Size: 3.3 KiB |
@ -1,57 +1,96 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
<svg width="48" height="48" version="1.1" viewBox="0 0 12.7 12.7" xmlns="http://www.w3.org/2000/svg" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
|
||||
<title>Prism Launcher Logo</title>
|
||||
<g stroke-width=".26458">
|
||||
<path d="m6.35 6.35" fill="#99cd61"/>
|
||||
<path d="m6.35 0.52917-2.5208 4.3656 2.5208 1.4552 2.5203-1.4552 0.10955-3.0996c-1.1511-0.66459-2.3388-1.2661-2.6298-1.2661z" fill="#df6277"/>
|
||||
<path d="m8.9798 1.7952-2.6298 4.5548 2.5203 1.4552 2.5208-4.3656c-0.14552-0.25205-1.2601-0.97975-2.4112-1.6443z" fill="#fb9168"/>
|
||||
<path d="m11.391 3.4396-5.041 2.9104 2.5203 1.4552 2.7389-1.4552c0-1.3292-0.072554-2.6584-0.21808-2.9104z" fill="#f3db6c"/>
|
||||
<path d="m6.35 6.35v2.9104h5.041c0.14552-0.25205 0.21807-1.5812 0.21808-2.9104h-5.2591z" fill="#7ab392"/>
|
||||
<path d="m6.35 6.35v2.9104l2.6298 1.6443c1.1511-0.66459 2.2657-1.3923 2.4112-1.6443l-5.041-2.9104z" fill="#4b7cbc"/>
|
||||
<path d="m6.35 6.35-2.5208 1.4552 2.5208 4.3656c0.29104 0 1.4787-0.60148 2.6298-1.2661l-2.6298-4.5548z" fill="#6f488c"/>
|
||||
<path d="m3.8292 4.8948-2.5203 4.3656c0.29104 0.5041 4.459 2.9104 5.041 2.9104v-5.8208l-2.5208-1.4552z" fill="#4d3f33"/>
|
||||
<path d="m1.309 3.4396c-0.29104 0.5041-0.29104 5.3167 0 5.8208l5.041-2.9104v-2.9104h-5.041z" fill="#7a573b"/>
|
||||
<path d="m6.35 0.52917c-0.58208-2e-8 -4.75 2.4063-5.041 2.9104l5.041 2.9104v-5.8208z" fill="#99cd61"/>
|
||||
|
||||
<svg
|
||||
width="64"
|
||||
height="64"
|
||||
viewBox="0 0 64 64"
|
||||
version="1.1"
|
||||
id="svg99"
|
||||
inkscape:version="1.2.1 (9c6d41e410, 2022-07-14)"
|
||||
sodipodi:docname="org.fn2006.PollyMC.svg"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<sodipodi:namedview
|
||||
id="namedview101"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#000000"
|
||||
borderopacity="0.25"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
inkscape:document-units="px"
|
||||
showgrid="false"
|
||||
inkscape:zoom="12.697086"
|
||||
inkscape:cx="35.638098"
|
||||
inkscape:cy="31.345775"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="994"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="g5269" />
|
||||
<defs
|
||||
id="defs96">
|
||||
<inkscape:path-effect
|
||||
effect="powerclip"
|
||||
id="path-effect5638"
|
||||
is_visible="true"
|
||||
lpeversion="1"
|
||||
inverse="true"
|
||||
flatten="false"
|
||||
hide_clip="false"
|
||||
message="Use fill-rule evenodd on <b>fill and stroke</b> dialog if no flatten result after convert clip to paths." />
|
||||
<inkscape:path-effect
|
||||
effect="powerclip"
|
||||
id="path-effect5562"
|
||||
is_visible="true"
|
||||
lpeversion="1"
|
||||
inverse="true"
|
||||
flatten="false"
|
||||
hide_clip="false"
|
||||
message="Use fill-rule evenodd on <b>fill and stroke</b> dialog if no flatten result after convert clip to paths." />
|
||||
<inkscape:path-effect
|
||||
effect="powerclip"
|
||||
id="path-effect5535"
|
||||
is_visible="true"
|
||||
lpeversion="1"
|
||||
inverse="true"
|
||||
flatten="false"
|
||||
hide_clip="false"
|
||||
message="Use fill-rule evenodd on <b>fill and stroke</b> dialog if no flatten result after convert clip to paths." />
|
||||
</defs>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1">
|
||||
<g
|
||||
id="g5269"
|
||||
clip-path="none"
|
||||
transform="matrix(1.25,0,0,1.25,-8,-10.5)">
|
||||
<path
|
||||
id="path300"
|
||||
style="fill:#8acb01"
|
||||
d="m 8,16 c 0,12 0,24 0,36 8.010417,0 16.020833,0 24.03125,0 0,-0.8 0,-1.6 0,-2.4 3.714062,0 7.428125,0 11.142187,0 0,-0.8 0,-1.6 0,-2.4 4.275521,0 8.551042,0 12.826563,0 C 56,36.8 56,26.4 56,16 40,16 24,16 8,16 Z"
|
||||
inkscape:label="head" />
|
||||
<path
|
||||
id="rect3493"
|
||||
style="fill:#b0af8d;stroke-width:1.39562"
|
||||
inkscape:label="cheek"
|
||||
d="M 19.959999,28.879064 H 32.253197 V 52 H 19.959999 Z" />
|
||||
<path
|
||||
id="rect3491"
|
||||
inkscape:label="eye"
|
||||
d="M 19.960001,28 H 32.333299 V 40 H 19.960001 Z"
|
||||
style="stroke-width:1.00871" />
|
||||
<path
|
||||
id="path352"
|
||||
style="display:inline;fill:#3b3b3b;fill-opacity:1;stroke-width:1.00922"
|
||||
d="m 32,28 c 0,7.333333 0,14.666667 0,22 4,0 8,0 12,0 0,-0.814583 0,-1.629167 0,-2.44375 4,0 8,0 12,0 C 56,41.0375 56,34.51875 56,28 48,28 40,28 32,28 Z"
|
||||
inkscape:label="beak" />
|
||||
</g>
|
||||
<g transform="matrix(.88 0 0 .88 -10.906 -1.2421)">
|
||||
<g transform="translate(13.26 2.2776)">
|
||||
<path transform="matrix(.96975 0 0 .96975 .1921 .1921)" d="m6.3498 2.9393c-0.34105 0-2.7827 1.4099-2.9532 1.7052l2.9532 5.1157 2.9538-5.1157c-0.17052-0.29535-2.6127-1.7052-2.9538-1.7052z" fill="#fff" stroke-width=".26458"/>
|
||||
</g>
|
||||
<path d="m16.746 6.9737 2.8639 4.9609c0.33073 0 2.6991-1.3672 2.8644-1.6536 0.16536-0.28642 0.16536-3.0209 0-3.3073l-2.8644 1.6536z" fill="#dfdfdf" stroke-width=".26458"/>
|
||||
</g>
|
||||
<path d="m3.8299 4.8948c-0.14551 0.25205-0.14553 2.6584 0 2.9104 0.14553 0.25204 2.2292 1.4552 2.5203 1.4552v-2.9104z" fill="#d6d2d2" stroke-width=".26458"/>
|
||||
<metadata>
|
||||
<rdf:RDF>
|
||||
<cc:Work rdf:about="">
|
||||
<dc:title>Prism Launcher Logo</dc:title>
|
||||
<dc:date>19/10/2022</dc:date>
|
||||
<dc:creator>
|
||||
<cc:Agent>
|
||||
<dc:title>Prism Launcher</dc:title>
|
||||
</cc:Agent>
|
||||
</dc:creator>
|
||||
<dc:contributor>
|
||||
<cc:Agent>
|
||||
<dc:title>AutiOne, Boba, ely, Fulmine, gon sawa, Pankakes, tobimori, Zeke</dc:title>
|
||||
</cc:Agent>
|
||||
</dc:contributor>
|
||||
<dc:source>https://github.com/PrismLauncher/PrismLauncher</dc:source>
|
||||
<dc:publisher>
|
||||
<cc:Agent>
|
||||
<dc:title>Prism Launcher</dc:title>
|
||||
</cc:Agent>
|
||||
</dc:publisher>
|
||||
<cc:license rdf:resource="http://creativecommons.org/licenses/by-sa/4.0/"/>
|
||||
</cc:Work>
|
||||
<cc:License rdf:about="http://creativecommons.org/licenses/by-sa/4.0/">
|
||||
<cc:permits rdf:resource="http://creativecommons.org/ns#Reproduction"/>
|
||||
<cc:permits rdf:resource="http://creativecommons.org/ns#Distribution"/>
|
||||
<cc:requires rdf:resource="http://creativecommons.org/ns#Notice"/>
|
||||
<cc:requires rdf:resource="http://creativecommons.org/ns#Attribution"/>
|
||||
<cc:permits rdf:resource="http://creativecommons.org/ns#DerivativeWorks"/>
|
||||
<cc:requires rdf:resource="http://creativecommons.org/ns#ShareAlike"/>
|
||||
</cc:License>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 3.4 KiB After Width: | Height: | Size: 3.3 KiB |
@ -1,57 +1,96 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
<svg width="48" height="48" version="1.1" viewBox="0 0 12.7 12.7" xmlns="http://www.w3.org/2000/svg" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
|
||||
<title>Prism Launcher Logo</title>
|
||||
<g stroke-width=".26458">
|
||||
<path d="m6.35 6.35" fill="#99cd61"/>
|
||||
<path d="m6.35 0.52917-2.5208 4.3656 2.5208 1.4552 2.5203-1.4552 0.10955-3.0996c-1.1511-0.66459-2.3388-1.2661-2.6298-1.2661z" fill="#df6277"/>
|
||||
<path d="m8.9798 1.7952-2.6298 4.5548 2.5203 1.4552 2.5208-4.3656c-0.14552-0.25205-1.2601-0.97975-2.4112-1.6443z" fill="#fb9168"/>
|
||||
<path d="m11.391 3.4396-5.041 2.9104 2.5203 1.4552 2.7389-1.4552c0-1.3292-0.072554-2.6584-0.21808-2.9104z" fill="#f3db6c"/>
|
||||
<path d="m6.35 6.35v2.9104h5.041c0.14552-0.25205 0.21807-1.5812 0.21808-2.9104h-5.2591z" fill="#7ab392"/>
|
||||
<path d="m6.35 6.35v2.9104l2.6298 1.6443c1.1511-0.66459 2.2657-1.3923 2.4112-1.6443l-5.041-2.9104z" fill="#4b7cbc"/>
|
||||
<path d="m6.35 6.35-2.5208 1.4552 2.5208 4.3656c0.29104 0 1.4787-0.60148 2.6298-1.2661l-2.6298-4.5548z" fill="#6f488c"/>
|
||||
<path d="m3.8292 4.8948-2.5203 4.3656c0.29104 0.5041 4.459 2.9104 5.041 2.9104v-5.8208l-2.5208-1.4552z" fill="#4d3f33"/>
|
||||
<path d="m1.309 3.4396c-0.29104 0.5041-0.29104 5.3167 0 5.8208l5.041-2.9104v-2.9104h-5.041z" fill="#7a573b"/>
|
||||
<path d="m6.35 0.52917c-0.58208-2e-8 -4.75 2.4063-5.041 2.9104l5.041 2.9104v-5.8208z" fill="#99cd61"/>
|
||||
|
||||
<svg
|
||||
width="64"
|
||||
height="64"
|
||||
viewBox="0 0 64 64"
|
||||
version="1.1"
|
||||
id="svg99"
|
||||
inkscape:version="1.2.1 (9c6d41e410, 2022-07-14)"
|
||||
sodipodi:docname="org.fn2006.PollyMC.svg"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<sodipodi:namedview
|
||||
id="namedview101"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#000000"
|
||||
borderopacity="0.25"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
inkscape:document-units="px"
|
||||
showgrid="false"
|
||||
inkscape:zoom="12.697086"
|
||||
inkscape:cx="35.638098"
|
||||
inkscape:cy="31.345775"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="994"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="g5269" />
|
||||
<defs
|
||||
id="defs96">
|
||||
<inkscape:path-effect
|
||||
effect="powerclip"
|
||||
id="path-effect5638"
|
||||
is_visible="true"
|
||||
lpeversion="1"
|
||||
inverse="true"
|
||||
flatten="false"
|
||||
hide_clip="false"
|
||||
message="Use fill-rule evenodd on <b>fill and stroke</b> dialog if no flatten result after convert clip to paths." />
|
||||
<inkscape:path-effect
|
||||
effect="powerclip"
|
||||
id="path-effect5562"
|
||||
is_visible="true"
|
||||
lpeversion="1"
|
||||
inverse="true"
|
||||
flatten="false"
|
||||
hide_clip="false"
|
||||
message="Use fill-rule evenodd on <b>fill and stroke</b> dialog if no flatten result after convert clip to paths." />
|
||||
<inkscape:path-effect
|
||||
effect="powerclip"
|
||||
id="path-effect5535"
|
||||
is_visible="true"
|
||||
lpeversion="1"
|
||||
inverse="true"
|
||||
flatten="false"
|
||||
hide_clip="false"
|
||||
message="Use fill-rule evenodd on <b>fill and stroke</b> dialog if no flatten result after convert clip to paths." />
|
||||
</defs>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1">
|
||||
<g
|
||||
id="g5269"
|
||||
clip-path="none"
|
||||
transform="matrix(1.25,0,0,1.25,-8,-10.5)">
|
||||
<path
|
||||
id="path300"
|
||||
style="fill:#8acb01"
|
||||
d="m 8,16 c 0,12 0,24 0,36 8.010417,0 16.020833,0 24.03125,0 0,-0.8 0,-1.6 0,-2.4 3.714062,0 7.428125,0 11.142187,0 0,-0.8 0,-1.6 0,-2.4 4.275521,0 8.551042,0 12.826563,0 C 56,36.8 56,26.4 56,16 40,16 24,16 8,16 Z"
|
||||
inkscape:label="head" />
|
||||
<path
|
||||
id="rect3493"
|
||||
style="fill:#b0af8d;stroke-width:1.39562"
|
||||
inkscape:label="cheek"
|
||||
d="M 19.959999,28.879064 H 32.253197 V 52 H 19.959999 Z" />
|
||||
<path
|
||||
id="rect3491"
|
||||
inkscape:label="eye"
|
||||
d="M 19.960001,28 H 32.333299 V 40 H 19.960001 Z"
|
||||
style="stroke-width:1.00871" />
|
||||
<path
|
||||
id="path352"
|
||||
style="display:inline;fill:#3b3b3b;fill-opacity:1;stroke-width:1.00922"
|
||||
d="m 32,28 c 0,7.333333 0,14.666667 0,22 4,0 8,0 12,0 0,-0.814583 0,-1.629167 0,-2.44375 4,0 8,0 12,0 C 56,41.0375 56,34.51875 56,28 48,28 40,28 32,28 Z"
|
||||
inkscape:label="beak" />
|
||||
</g>
|
||||
<g transform="matrix(.88 0 0 .88 -10.906 -1.2421)">
|
||||
<g transform="translate(13.26 2.2776)">
|
||||
<path transform="matrix(.96975 0 0 .96975 .1921 .1921)" d="m6.3498 2.9393c-0.34105 0-2.7827 1.4099-2.9532 1.7052l2.9532 5.1157 2.9538-5.1157c-0.17052-0.29535-2.6127-1.7052-2.9538-1.7052z" fill="#fff" stroke-width=".26458"/>
|
||||
</g>
|
||||
<path d="m16.746 6.9737 2.8639 4.9609c0.33073 0 2.6991-1.3672 2.8644-1.6536 0.16536-0.28642 0.16536-3.0209 0-3.3073l-2.8644 1.6536z" fill="#dfdfdf" stroke-width=".26458"/>
|
||||
</g>
|
||||
<path d="m3.8299 4.8948c-0.14551 0.25205-0.14553 2.6584 0 2.9104 0.14553 0.25204 2.2292 1.4552 2.5203 1.4552v-2.9104z" fill="#d6d2d2" stroke-width=".26458"/>
|
||||
<metadata>
|
||||
<rdf:RDF>
|
||||
<cc:Work rdf:about="">
|
||||
<dc:title>Prism Launcher Logo</dc:title>
|
||||
<dc:date>19/10/2022</dc:date>
|
||||
<dc:creator>
|
||||
<cc:Agent>
|
||||
<dc:title>Prism Launcher</dc:title>
|
||||
</cc:Agent>
|
||||
</dc:creator>
|
||||
<dc:contributor>
|
||||
<cc:Agent>
|
||||
<dc:title>AutiOne, Boba, ely, Fulmine, gon sawa, Pankakes, tobimori, Zeke</dc:title>
|
||||
</cc:Agent>
|
||||
</dc:contributor>
|
||||
<dc:source>https://github.com/PrismLauncher/PrismLauncher</dc:source>
|
||||
<dc:publisher>
|
||||
<cc:Agent>
|
||||
<dc:title>Prism Launcher</dc:title>
|
||||
</cc:Agent>
|
||||
</dc:publisher>
|
||||
<cc:license rdf:resource="http://creativecommons.org/licenses/by-sa/4.0/"/>
|
||||
</cc:Work>
|
||||
<cc:License rdf:about="http://creativecommons.org/licenses/by-sa/4.0/">
|
||||
<cc:permits rdf:resource="http://creativecommons.org/ns#Reproduction"/>
|
||||
<cc:permits rdf:resource="http://creativecommons.org/ns#Distribution"/>
|
||||
<cc:requires rdf:resource="http://creativecommons.org/ns#Notice"/>
|
||||
<cc:requires rdf:resource="http://creativecommons.org/ns#Attribution"/>
|
||||
<cc:permits rdf:resource="http://creativecommons.org/ns#DerivativeWorks"/>
|
||||
<cc:requires rdf:resource="http://creativecommons.org/ns#ShareAlike"/>
|
||||
</cc:License>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 3.4 KiB After Width: | Height: | Size: 3.3 KiB |
@ -42,6 +42,7 @@
|
||||
#include <QFileDialog>
|
||||
#include <QStandardPaths>
|
||||
|
||||
#include "net/FetchFlameAPIKey.h"
|
||||
#include "ui/dialogs/ProgressDialog.h"
|
||||
#include "ui/dialogs/CustomMessageBox.h"
|
||||
#include "net/PasteUpload.h"
|
||||
@ -51,6 +52,31 @@
|
||||
#include <DesktopServices.h>
|
||||
#include <BuildConfig.h>
|
||||
|
||||
QString GuiUtil::fetchFlameKey(QWidget *parentWidget)
|
||||
{
|
||||
if (BuildConfig.FLAME_API_KEY_API_URL.isEmpty())
|
||||
return "";
|
||||
|
||||
ProgressDialog prog(parentWidget);
|
||||
auto flameKeyTask = std::make_unique<FetchFlameAPIKey>();
|
||||
prog.execWithTask(flameKeyTask.get());
|
||||
|
||||
if (!flameKeyTask->wasSuccessful())
|
||||
{
|
||||
auto message = QObject::tr("Fetching the Curseforge API key failed. Reason: %1").arg(flameKeyTask->failReason());
|
||||
if (!(APPLICATION->capabilities() & Application::SupportsFlame))
|
||||
{
|
||||
message += "\n\n" + QObject::tr("Downloading Curseforge modpacks will not work unless you manually set a valid Curseforge Core API key in the settings.");
|
||||
}
|
||||
|
||||
CustomMessageBox::selectable(parentWidget,
|
||||
QObject::tr("Failed to fetch Curseforge API key."),
|
||||
message, QMessageBox::Critical)->exec();
|
||||
}
|
||||
|
||||
return flameKeyTask->m_result;
|
||||
}
|
||||
|
||||
std::optional<QString> GuiUtil::uploadPaste(const QString &name, const QString &text, QWidget *parentWidget)
|
||||
{
|
||||
ProgressDialog dialog(parentWidget);
|
||||
|
@ -5,6 +5,7 @@
|
||||
|
||||
namespace GuiUtil
|
||||
{
|
||||
QString fetchFlameKey(QWidget *parentWidget = nullptr);
|
||||
std::optional<QString> uploadPaste(const QString &name, const QString &text, QWidget *parentWidget);
|
||||
void setClipboardText(const QString &text);
|
||||
QStringList BrowseForFiles(QString context, QString caption, QString filter, QString defaultPath, QWidget *parentWidget);
|
||||
|
@ -70,6 +70,17 @@ QString getCreditsHtml()
|
||||
|
||||
//: %1 is the name of the launcher, determined at build time, e.g. "Prism Launcher Developers"
|
||||
stream << "<h3>" << QObject::tr("%1 Developers", "About Credits").arg(BuildConfig.LAUNCHER_DISPLAYNAME) << "</h3>\n";
|
||||
stream << QString("<p>fn2006 %1</p>\n") .arg(getGitHub("fn2006"));
|
||||
stream << "<br />\n";
|
||||
|
||||
//: %1 is the name of the launcher, determined at build time, e.g. "Prism Launcher Contributors"
|
||||
stream << "<h3>" << QObject::tr("%1 Contributors", "About Credits").arg(BuildConfig.LAUNCHER_DISPLAYNAME) << "</h3>\n";
|
||||
stream << QString("<p>anoraktrend %1</p>\n") .arg(getGitHub("anoraktrend"));
|
||||
stream << QString("<p>Emma Tebibyte %1</p>\n") .arg(getWebsite("https://tebibyte.media/"));
|
||||
stream << "<br />\n";
|
||||
|
||||
//: %1 is the name of the launcher, determined at build time, e.g. "Prism Launcher Developers"
|
||||
stream << "<h3>" << QObject::tr("%1 Developers", "About Credits").arg("Prism Launcher") << "</h3>\n";
|
||||
stream << QString("<p>Sefa Eyeoglu (Scrumplex) %1</p>\n") .arg(getWebsite("https://scrumplex.net"));
|
||||
stream << QString("<p>dada513 %1</p>\n") .arg(getGitHub("dada513"));
|
||||
stream << QString("<p>txtsd %1</p>\n") .arg(getWebsite("https://ihavea.quest"));
|
||||
@ -165,7 +176,7 @@ AboutDialog::AboutDialog(QWidget *parent) : QDialog(parent), ui(new Ui::AboutDia
|
||||
QString urlText("<html><head/><body><p><a href=\"%1\">%1</a></p></body></html>");
|
||||
ui->urlLabel->setText(urlText.arg(BuildConfig.LAUNCHER_GIT));
|
||||
|
||||
QString copyText("© 2022 %1");
|
||||
QString copyText("%1");
|
||||
ui->copyLabel->setText(copyText.arg(BuildConfig.LAUNCHER_COPYRIGHT));
|
||||
|
||||
connect(ui->closeButton, SIGNAL(clicked()), SLOT(close()));
|
||||
|
131
launcher/ui/dialogs/CustomLoginDialog.cpp
Normal file
@ -0,0 +1,131 @@
|
||||
/* 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 "CustomLoginDialog.h"
|
||||
#include "ui_CustomLoginDialog.h"
|
||||
|
||||
#include "minecraft/auth/AccountTask.h"
|
||||
|
||||
#include <QtWidgets/QPushButton>
|
||||
|
||||
CustomLoginDialog::CustomLoginDialog(QWidget *parent) : QDialog(parent), ui(new Ui::CustomLoginDialog)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
ui->progressBar->setVisible(false);
|
||||
ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false);
|
||||
|
||||
connect(ui->buttonBox, &QDialogButtonBox::accepted, this, &QDialog::accept);
|
||||
connect(ui->buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject);
|
||||
}
|
||||
|
||||
CustomLoginDialog::~CustomLoginDialog()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
// Stage 1: User interaction
|
||||
void CustomLoginDialog::accept()
|
||||
{
|
||||
setUserInputsEnabled(false);
|
||||
ui->progressBar->setVisible(true);
|
||||
|
||||
// Setup the login task and start it
|
||||
m_account = MinecraftAccount::createCustom(ui->userTextBox->text(), ui->urlTextBox->text());
|
||||
if (ui->mfaTextBox->text().length() > 0) {
|
||||
m_loginTask = m_account->loginCustom(ui->passTextBox->text() + ':' + ui->mfaTextBox->text(), ui->urlTextBox->text());
|
||||
}
|
||||
else {
|
||||
m_loginTask = m_account->loginCustom(ui->passTextBox->text(), ui->urlTextBox->text());
|
||||
}
|
||||
connect(m_loginTask.get(), &Task::failed, this, &CustomLoginDialog::onTaskFailed);
|
||||
connect(m_loginTask.get(), &Task::succeeded, this, &CustomLoginDialog::onTaskSucceeded);
|
||||
connect(m_loginTask.get(), &Task::status, this, &CustomLoginDialog::onTaskStatus);
|
||||
connect(m_loginTask.get(), &Task::progress, this, &CustomLoginDialog::onTaskProgress);
|
||||
m_loginTask->start();
|
||||
}
|
||||
|
||||
void CustomLoginDialog::setUserInputsEnabled(bool enable)
|
||||
{
|
||||
ui->userTextBox->setEnabled(enable);
|
||||
ui->passTextBox->setEnabled(enable);
|
||||
ui->urlTextBox->setEnabled(enable);
|
||||
ui->mfaTextBox->setEnabled(enable);
|
||||
ui->buttonBox->setEnabled(enable);
|
||||
}
|
||||
|
||||
// Enable the OK button only when both textboxes contain something.
|
||||
void CustomLoginDialog::on_userTextBox_textEdited(const QString &newText)
|
||||
{
|
||||
ui->buttonBox->button(QDialogButtonBox::Ok)
|
||||
->setEnabled(!newText.isEmpty() && !ui->passTextBox->text().isEmpty() && !ui->urlTextBox->text().isEmpty());
|
||||
}
|
||||
void CustomLoginDialog::on_passTextBox_textEdited(const QString &newText)
|
||||
{
|
||||
ui->buttonBox->button(QDialogButtonBox::Ok)
|
||||
->setEnabled(!newText.isEmpty() && !ui->userTextBox->text().isEmpty() && !ui->urlTextBox->text().isEmpty());
|
||||
}
|
||||
void CustomLoginDialog::on_urlTextBox_textEdited(const QString &newText)
|
||||
{
|
||||
ui->buttonBox->button(QDialogButtonBox::Ok)
|
||||
->setEnabled(!newText.isEmpty() && !ui->userTextBox->text().isEmpty() && !ui->passTextBox->text().isEmpty());
|
||||
}
|
||||
|
||||
void CustomLoginDialog::onTaskFailed(const QString &reason)
|
||||
{
|
||||
// Set message
|
||||
auto lines = reason.split('\n');
|
||||
QString processed;
|
||||
for(auto line: lines) {
|
||||
if(line.size()) {
|
||||
processed += "<font color='red'>" + line + "</font><br />";
|
||||
}
|
||||
else {
|
||||
processed += "<br />";
|
||||
}
|
||||
}
|
||||
ui->label->setText(processed);
|
||||
|
||||
// Re-enable user-interaction
|
||||
setUserInputsEnabled(true);
|
||||
ui->progressBar->setVisible(false);
|
||||
}
|
||||
|
||||
void CustomLoginDialog::onTaskSucceeded()
|
||||
{
|
||||
QDialog::accept();
|
||||
}
|
||||
|
||||
void CustomLoginDialog::onTaskStatus(const QString &status)
|
||||
{
|
||||
ui->label->setText(status);
|
||||
}
|
||||
|
||||
void CustomLoginDialog::onTaskProgress(qint64 current, qint64 total)
|
||||
{
|
||||
ui->progressBar->setMaximum(total);
|
||||
ui->progressBar->setValue(current);
|
||||
}
|
||||
|
||||
// Public interface
|
||||
MinecraftAccountPtr CustomLoginDialog::newAccount(QWidget *parent, QString msg)
|
||||
{
|
||||
CustomLoginDialog dlg(parent);
|
||||
dlg.ui->label->setText(msg);
|
||||
if (dlg.exec() == QDialog::Accepted)
|
||||
{
|
||||
return dlg.m_account;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
60
launcher/ui/dialogs/CustomLoginDialog.h
Normal file
@ -0,0 +1,60 @@
|
||||
/* 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 <QtWidgets/QDialog>
|
||||
#include <QtCore/QEventLoop>
|
||||
|
||||
#include "minecraft/auth/MinecraftAccount.h"
|
||||
#include "tasks/Task.h"
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
class CustomLoginDialog;
|
||||
}
|
||||
|
||||
class CustomLoginDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
~CustomLoginDialog();
|
||||
|
||||
static MinecraftAccountPtr newAccount(QWidget *parent, QString message);
|
||||
|
||||
private:
|
||||
explicit CustomLoginDialog(QWidget *parent = 0);
|
||||
|
||||
void setUserInputsEnabled(bool enable);
|
||||
|
||||
protected
|
||||
slots:
|
||||
void accept();
|
||||
|
||||
void onTaskFailed(const QString &reason);
|
||||
void onTaskSucceeded();
|
||||
void onTaskStatus(const QString &status);
|
||||
void onTaskProgress(qint64 current, qint64 total);
|
||||
|
||||
void on_userTextBox_textEdited(const QString &newText);
|
||||
void on_passTextBox_textEdited(const QString &newText);
|
||||
void on_urlTextBox_textEdited(const QString &newText);
|
||||
|
||||
private:
|
||||
Ui::CustomLoginDialog *ui;
|
||||
MinecraftAccountPtr m_account;
|
||||
Task::Ptr m_loginTask;
|
||||
};
|
94
launcher/ui/dialogs/CustomLoginDialog.ui
Normal file
@ -0,0 +1,94 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>CustomLoginDialog</class>
|
||||
<widget class="QDialog" name="CustomLoginDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>421</width>
|
||||
<height>198</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Add Account</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string notr="true">Message label placeholder.</string>
|
||||
</property>
|
||||
<property name="textFormat">
|
||||
<enum>Qt::RichText</enum>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::LinksAccessibleByKeyboard|Qt::LinksAccessibleByMouse|Qt::TextBrowserInteraction|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="userTextBox">
|
||||
<property name="placeholderText">
|
||||
<string>Email</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="passTextBox">
|
||||
<property name="echoMode">
|
||||
<enum>QLineEdit::Password</enum>
|
||||
</property>
|
||||
<property name="placeholderText">
|
||||
<string>Password</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="urlTextBox">
|
||||
<property name="placeholderText">
|
||||
<string>Url</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="mfaTextBox">
|
||||
<property name="echoMode">
|
||||
<enum>QLineEdit::Password</enum>
|
||||
</property>
|
||||
<property name="placeholderText">
|
||||
<string>2FA Code (Optional)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QProgressBar" name="progressBar">
|
||||
<property name="value">
|
||||
<number>24</number>
|
||||
</property>
|
||||
<property name="textVisible">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
125
launcher/ui/dialogs/ElybyLoginDialog.cpp
Normal file
@ -0,0 +1,125 @@
|
||||
/* 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 "ElybyLoginDialog.h"
|
||||
#include "ui_ElybyLoginDialog.h"
|
||||
|
||||
#include "minecraft/auth/AccountTask.h"
|
||||
|
||||
#include <QtWidgets/QPushButton>
|
||||
|
||||
ElybyLoginDialog::ElybyLoginDialog(QWidget *parent) : QDialog(parent), ui(new Ui::ElybyLoginDialog)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
ui->progressBar->setVisible(false);
|
||||
ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false);
|
||||
|
||||
connect(ui->buttonBox, &QDialogButtonBox::accepted, this, &QDialog::accept);
|
||||
connect(ui->buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject);
|
||||
}
|
||||
|
||||
ElybyLoginDialog::~ElybyLoginDialog()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
// Stage 1: User interaction
|
||||
void ElybyLoginDialog::accept()
|
||||
{
|
||||
setUserInputsEnabled(false);
|
||||
ui->progressBar->setVisible(true);
|
||||
|
||||
// Setup the login task and start it
|
||||
m_account = MinecraftAccount::createElyby(ui->userTextBox->text());
|
||||
if (ui->mfaTextBox->text().length() > 0) {
|
||||
m_loginTask = m_account->loginElyby(ui->passTextBox->text() + ':' + ui->mfaTextBox->text());
|
||||
}
|
||||
else {
|
||||
m_loginTask = m_account->loginElyby(ui->passTextBox->text());
|
||||
}
|
||||
connect(m_loginTask.get(), &Task::failed, this, &ElybyLoginDialog::onTaskFailed);
|
||||
connect(m_loginTask.get(), &Task::succeeded, this, &ElybyLoginDialog::onTaskSucceeded);
|
||||
connect(m_loginTask.get(), &Task::status, this, &ElybyLoginDialog::onTaskStatus);
|
||||
connect(m_loginTask.get(), &Task::progress, this, &ElybyLoginDialog::onTaskProgress);
|
||||
m_loginTask->start();
|
||||
}
|
||||
|
||||
void ElybyLoginDialog::setUserInputsEnabled(bool enable)
|
||||
{
|
||||
ui->userTextBox->setEnabled(enable);
|
||||
ui->passTextBox->setEnabled(enable);
|
||||
ui->mfaTextBox->setEnabled(enable);
|
||||
ui->buttonBox->setEnabled(enable);
|
||||
}
|
||||
|
||||
// Enable the OK button only when both textboxes contain something.
|
||||
void ElybyLoginDialog::on_userTextBox_textEdited(const QString &newText)
|
||||
{
|
||||
ui->buttonBox->button(QDialogButtonBox::Ok)
|
||||
->setEnabled(!newText.isEmpty() && !ui->passTextBox->text().isEmpty());
|
||||
}
|
||||
void ElybyLoginDialog::on_passTextBox_textEdited(const QString &newText)
|
||||
{
|
||||
ui->buttonBox->button(QDialogButtonBox::Ok)
|
||||
->setEnabled(!newText.isEmpty() && !ui->userTextBox->text().isEmpty());
|
||||
}
|
||||
|
||||
void ElybyLoginDialog::onTaskFailed(const QString &reason)
|
||||
{
|
||||
// Set message
|
||||
auto lines = reason.split('\n');
|
||||
QString processed;
|
||||
for(auto line: lines) {
|
||||
if(line.size()) {
|
||||
processed += "<font color='red'>" + line + "</font><br />";
|
||||
}
|
||||
else {
|
||||
processed += "<br />";
|
||||
}
|
||||
}
|
||||
ui->label->setText(processed);
|
||||
|
||||
// Re-enable user-interaction
|
||||
setUserInputsEnabled(true);
|
||||
ui->progressBar->setVisible(false);
|
||||
}
|
||||
|
||||
void ElybyLoginDialog::onTaskSucceeded()
|
||||
{
|
||||
QDialog::accept();
|
||||
}
|
||||
|
||||
void ElybyLoginDialog::onTaskStatus(const QString &status)
|
||||
{
|
||||
ui->label->setText(status);
|
||||
}
|
||||
|
||||
void ElybyLoginDialog::onTaskProgress(qint64 current, qint64 total)
|
||||
{
|
||||
ui->progressBar->setMaximum(total);
|
||||
ui->progressBar->setValue(current);
|
||||
}
|
||||
|
||||
// Public interface
|
||||
MinecraftAccountPtr ElybyLoginDialog::newAccount(QWidget *parent, QString msg)
|
||||
{
|
||||
ElybyLoginDialog dlg(parent);
|
||||
dlg.ui->label->setText(msg);
|
||||
if (dlg.exec() == QDialog::Accepted)
|
||||
{
|
||||
return dlg.m_account;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
59
launcher/ui/dialogs/ElybyLoginDialog.h
Normal file
@ -0,0 +1,59 @@
|
||||
/* 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 <QtWidgets/QDialog>
|
||||
#include <QtCore/QEventLoop>
|
||||
|
||||
#include "minecraft/auth/MinecraftAccount.h"
|
||||
#include "tasks/Task.h"
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
class ElybyLoginDialog;
|
||||
}
|
||||
|
||||
class ElybyLoginDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
~ElybyLoginDialog();
|
||||
|
||||
static MinecraftAccountPtr newAccount(QWidget *parent, QString message);
|
||||
|
||||
private:
|
||||
explicit ElybyLoginDialog(QWidget *parent = 0);
|
||||
|
||||
void setUserInputsEnabled(bool enable);
|
||||
|
||||
protected
|
||||
slots:
|
||||
void accept();
|
||||
|
||||
void onTaskFailed(const QString &reason);
|
||||
void onTaskSucceeded();
|
||||
void onTaskStatus(const QString &status);
|
||||
void onTaskProgress(qint64 current, qint64 total);
|
||||
|
||||
void on_userTextBox_textEdited(const QString &newText);
|
||||
void on_passTextBox_textEdited(const QString &newText);
|
||||
|
||||
private:
|
||||
Ui::ElybyLoginDialog *ui;
|
||||
MinecraftAccountPtr m_account;
|
||||
Task::Ptr m_loginTask;
|
||||
};
|
87
launcher/ui/dialogs/ElybyLoginDialog.ui
Normal file
@ -0,0 +1,87 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>ElybyLoginDialog</class>
|
||||
<widget class="QDialog" name="ElybyLoginDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>421</width>
|
||||
<height>198</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Add Account</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string notr="true">Message label placeholder.</string>
|
||||
</property>
|
||||
<property name="textFormat">
|
||||
<enum>Qt::RichText</enum>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::LinksAccessibleByKeyboard|Qt::LinksAccessibleByMouse|Qt::TextBrowserInteraction|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="userTextBox">
|
||||
<property name="placeholderText">
|
||||
<string>Email</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="passTextBox">
|
||||
<property name="echoMode">
|
||||
<enum>QLineEdit::Password</enum>
|
||||
</property>
|
||||
<property name="placeholderText">
|
||||
<string>Password</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="mfaTextBox">
|
||||
<property name="echoMode">
|
||||
<enum>QLineEdit::Password</enum>
|
||||
</property>
|
||||
<property name="placeholderText">
|
||||
<string>2FA Code (Optional)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QProgressBar" name="progressBar">
|
||||
<property name="value">
|
||||
<number>24</number>
|
||||
</property>
|
||||
<property name="textVisible">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
@ -56,6 +56,7 @@
|
||||
#include "ui/widgets/PageContainer.h"
|
||||
#include "ui/pages/modplatform/VanillaPage.h"
|
||||
#include "ui/pages/modplatform/atlauncher/AtlPage.h"
|
||||
#include "ui/pages/modplatform/ftb/FtbPage.h"
|
||||
#include "ui/pages/modplatform/legacy_ftb/Page.h"
|
||||
#include "ui/pages/modplatform/flame/FlamePage.h"
|
||||
#include "ui/pages/modplatform/ImportPage.h"
|
||||
@ -167,6 +168,7 @@ QList<BasePage *> NewInstanceDialog::getPages()
|
||||
pages.append(new AtlPage(this));
|
||||
if (APPLICATION->capabilities() & Application::SupportsFlame)
|
||||
pages.append(new FlamePage(this));
|
||||
pages.append(new FtbPage(this));
|
||||
pages.append(new LegacyFTB::Page(this));
|
||||
pages.append(new ModrinthPage(this));
|
||||
pages.append(new TechnicPage(this));
|
||||
|
@ -53,6 +53,8 @@
|
||||
#include "net/PasteUpload.h"
|
||||
#include "BuildConfig.h"
|
||||
|
||||
#include "ui/GuiUtil.h"
|
||||
|
||||
APIPage::APIPage(QWidget *parent) :
|
||||
QWidget(parent),
|
||||
ui(new Ui::APIPage)
|
||||
@ -88,11 +90,16 @@ APIPage::APIPage(QWidget *parent) :
|
||||
ui->metaURL->setPlaceholderText(BuildConfig.META_URL);
|
||||
ui->userAgentLineEdit->setPlaceholderText(BuildConfig.USER_AGENT);
|
||||
|
||||
if (BuildConfig.FLAME_API_KEY_API_URL.isEmpty())
|
||||
ui->fetchKeyButton->hide();
|
||||
|
||||
loadSettings();
|
||||
|
||||
resetBaseURLNote();
|
||||
connect(ui->pasteTypeComboBox, currentIndexChangedSignal, this, &APIPage::updateBaseURLNote);
|
||||
connect(ui->baseURLEntry, &QLineEdit::textEdited, this, &APIPage::resetBaseURLNote);
|
||||
|
||||
connect(ui->fetchKeyButton, &QPushButton::clicked, this, &APIPage::fetchKeyButtonPressed);
|
||||
}
|
||||
|
||||
APIPage::~APIPage()
|
||||
@ -185,6 +192,14 @@ void APIPage::applySettings()
|
||||
s->set("UserAgentOverride", ui->userAgentLineEdit->text());
|
||||
}
|
||||
|
||||
void APIPage::fetchKeyButtonPressed()
|
||||
{
|
||||
QString apiKey = GuiUtil::fetchFlameKey(parentWidget());
|
||||
|
||||
if (!apiKey.isEmpty())
|
||||
ui->flameKey->setText(apiKey);
|
||||
}
|
||||
|
||||
bool APIPage::apply()
|
||||
{
|
||||
applySettings();
|
||||
|
@ -80,6 +80,7 @@ private:
|
||||
void updateBaseURLPlaceholder(int index);
|
||||
void loadSettings();
|
||||
void applySettings();
|
||||
void fetchKeyButtonPressed();
|
||||
|
||||
private:
|
||||
Ui::APIPage *ui;
|
||||
|
@ -248,16 +248,9 @@
|
||||
<property name="title">
|
||||
<string>&CurseForge Core API</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_2">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_10">
|
||||
<property name="text">
|
||||
<string>Note: you probably don't need to set this if CurseForge already works.</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_9">
|
||||
<widget class="QLabel" name="label_7">
|
||||
<property name="text">
|
||||
<string>Enter a custom API Key for CurseForge here.</string>
|
||||
</property>
|
||||
@ -282,6 +275,29 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QPushButton" name="fetchKeyButton">
|
||||
<property name="text">
|
||||
<string>Fetch Official Launcher's Key</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0" colspan="2">
|
||||
<widget class="QLabel" name="label_8">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string><html><head/><body><p>Note: you probably don't need to set this if CurseForge already works.</p><p><span style=" font-weight:700;">Using the Official Curseforge Launcher's key may break Curseforge's Terms of service, but should allow PollyMC to download all mods in a modpack without you needing to download any of them manually.</span></p></body></html></string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
|
@ -48,6 +48,8 @@
|
||||
#include "ui/dialogs/OfflineLoginDialog.h"
|
||||
#include "ui/dialogs/LoginDialog.h"
|
||||
#include "ui/dialogs/MSALoginDialog.h"
|
||||
#include "ui/dialogs/ElybyLoginDialog.h"
|
||||
#include "ui/dialogs/CustomLoginDialog.h"
|
||||
#include "ui/dialogs/CustomMessageBox.h"
|
||||
#include "ui/dialogs/SkinUploadDialog.h"
|
||||
|
||||
@ -188,19 +190,6 @@ void AccountListPage::on_actionAddMicrosoft_triggered()
|
||||
|
||||
void AccountListPage::on_actionAddOffline_triggered()
|
||||
{
|
||||
if (!m_accounts->anyAccountIsValid()) {
|
||||
QMessageBox::warning(
|
||||
this,
|
||||
tr("Error"),
|
||||
tr(
|
||||
"You must add a Microsoft or Mojang account that owns Minecraft before you can add an offline account."
|
||||
"<br><br>"
|
||||
"If you have lost your account you can contact Microsoft for support."
|
||||
)
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
MinecraftAccountPtr account = OfflineLoginDialog::newAccount(
|
||||
this,
|
||||
tr("Please enter your desired username to add your offline account.")
|
||||
@ -215,6 +204,38 @@ void AccountListPage::on_actionAddOffline_triggered()
|
||||
}
|
||||
}
|
||||
|
||||
void AccountListPage::on_actionAddElyby_triggered()
|
||||
{
|
||||
MinecraftAccountPtr account = ElybyLoginDialog::newAccount(
|
||||
this,
|
||||
tr("Please enter your Ely.by account email and password to add your account.")
|
||||
);
|
||||
|
||||
if (account)
|
||||
{
|
||||
m_accounts->addAccount(account);
|
||||
if (m_accounts->count() == 1) {
|
||||
m_accounts->setDefaultAccount(account);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AccountListPage::on_actionAddCustom_triggered()
|
||||
{
|
||||
MinecraftAccountPtr account = CustomLoginDialog::newAccount(
|
||||
this,
|
||||
tr("Enter the custom yggdrasil server url, along with your username and password to add your account.")
|
||||
);
|
||||
|
||||
if (account)
|
||||
{
|
||||
m_accounts->addAccount(account);
|
||||
if (m_accounts->count() == 1) {
|
||||
m_accounts->setDefaultAccount(account);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AccountListPage::on_actionRemove_triggered()
|
||||
{
|
||||
QModelIndexList selection = ui->listView->selectionModel()->selectedIndexes();
|
||||
@ -258,17 +279,22 @@ void AccountListPage::updateButtonStates()
|
||||
bool hasSelection = !selection.empty();
|
||||
bool accountIsReady = false;
|
||||
bool accountIsOnline = false;
|
||||
bool accountIsElyby = false;
|
||||
bool accountIsCustom = false;
|
||||
if (hasSelection)
|
||||
{
|
||||
QModelIndex selected = selection.first();
|
||||
MinecraftAccountPtr account = selected.data(AccountList::PointerRole).value<MinecraftAccountPtr>();
|
||||
accountIsReady = !account->isActive();
|
||||
accountIsOnline = !account->isOffline();
|
||||
accountIsElyby = account->isElyby();
|
||||
accountIsCustom = account->isCustom();
|
||||
|
||||
}
|
||||
ui->actionRemove->setEnabled(accountIsReady);
|
||||
ui->actionSetDefault->setEnabled(accountIsReady);
|
||||
ui->actionUploadSkin->setEnabled(accountIsReady && accountIsOnline);
|
||||
ui->actionDeleteSkin->setEnabled(accountIsReady && accountIsOnline);
|
||||
ui->actionUploadSkin->setEnabled(accountIsReady && accountIsOnline && !accountIsElyby && !accountIsCustom);
|
||||
ui->actionDeleteSkin->setEnabled(accountIsReady && accountIsOnline && !accountIsElyby && !accountIsCustom);
|
||||
ui->actionRefresh->setEnabled(accountIsReady && accountIsOnline);
|
||||
|
||||
if(m_accounts->defaultAccount().get() == nullptr) {
|
||||
|
@ -85,6 +85,8 @@ public slots:
|
||||
void on_actionAddMojang_triggered();
|
||||
void on_actionAddMicrosoft_triggered();
|
||||
void on_actionAddOffline_triggered();
|
||||
void on_actionAddElyby_triggered();
|
||||
void on_actionAddCustom_triggered();
|
||||
void on_actionRemove_triggered();
|
||||
void on_actionRefresh_triggered();
|
||||
void on_actionSetDefault_triggered();
|
||||
|
@ -55,6 +55,8 @@
|
||||
<addaction name="actionAddMicrosoft"/>
|
||||
<addaction name="actionAddMojang"/>
|
||||
<addaction name="actionAddOffline"/>
|
||||
<addaction name="actionAddElyby"/>
|
||||
<addaction name="actionAddCustom"/>
|
||||
<addaction name="actionRefresh"/>
|
||||
<addaction name="actionRemove"/>
|
||||
<addaction name="actionSetDefault"/>
|
||||
@ -109,6 +111,16 @@
|
||||
<string>Add &Offline</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionAddElyby">
|
||||
<property name="text">
|
||||
<string>Add &Ely.by</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionAddCustom">
|
||||
<property name="text">
|
||||
<string>Add &Custom</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionRefresh">
|
||||
<property name="text">
|
||||
<string>&Refresh</string>
|
||||
|
@ -485,16 +485,6 @@ void VersionPage::on_actionChange_version_triggered()
|
||||
|
||||
void VersionPage::on_actionDownload_All_triggered()
|
||||
{
|
||||
if (!APPLICATION->accounts()->anyAccountIsValid())
|
||||
{
|
||||
CustomMessageBox::selectable(
|
||||
this, tr("Error"),
|
||||
tr("Cannot download Minecraft or update instances unless you have at least "
|
||||
"one account added.\nPlease add your Mojang or Minecraft account."),
|
||||
QMessageBox::Warning)->show();
|
||||
return;
|
||||
}
|
||||
|
||||
auto updateTask = m_inst->createUpdateTask(Net::Mode::Online);
|
||||
if (!updateTask)
|
||||
{
|
||||
|
93
launcher/ui/pages/modplatform/ftb/FtbFilterModel.cpp
Normal file
@ -0,0 +1,93 @@
|
||||
/*
|
||||
* Copyright 2020-2021 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
|
||||
*
|
||||
* 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 "FtbFilterModel.h"
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
#include "modplatform/modpacksch/FTBPackManifest.h"
|
||||
|
||||
#include "StringUtils.h"
|
||||
|
||||
namespace Ftb {
|
||||
|
||||
FilterModel::FilterModel(QObject *parent) : QSortFilterProxyModel(parent)
|
||||
{
|
||||
currentSorting = Sorting::ByPlays;
|
||||
sortings.insert(tr("Sort by Plays"), Sorting::ByPlays);
|
||||
sortings.insert(tr("Sort by Installs"), Sorting::ByInstalls);
|
||||
sortings.insert(tr("Sort by Name"), Sorting::ByName);
|
||||
}
|
||||
|
||||
const QMap<QString, FilterModel::Sorting> FilterModel::getAvailableSortings()
|
||||
{
|
||||
return sortings;
|
||||
}
|
||||
|
||||
QString FilterModel::translateCurrentSorting()
|
||||
{
|
||||
return sortings.key(currentSorting);
|
||||
}
|
||||
|
||||
void FilterModel::setSorting(Sorting sorting)
|
||||
{
|
||||
currentSorting = sorting;
|
||||
invalidate();
|
||||
}
|
||||
|
||||
FilterModel::Sorting FilterModel::getCurrentSorting()
|
||||
{
|
||||
return currentSorting;
|
||||
}
|
||||
|
||||
void FilterModel::setSearchTerm(const QString& term)
|
||||
{
|
||||
searchTerm = term.trimmed();
|
||||
invalidate();
|
||||
}
|
||||
|
||||
bool FilterModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const
|
||||
{
|
||||
if (searchTerm.isEmpty()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
auto index = sourceModel()->index(sourceRow, 0, sourceParent);
|
||||
auto pack = sourceModel()->data(index, Qt::UserRole).value<ModpacksCH::Modpack>();
|
||||
return pack.name.contains(searchTerm, Qt::CaseInsensitive);
|
||||
}
|
||||
|
||||
bool FilterModel::lessThan(const QModelIndex &left, const QModelIndex &right) const
|
||||
{
|
||||
ModpacksCH::Modpack leftPack = sourceModel()->data(left, Qt::UserRole).value<ModpacksCH::Modpack>();
|
||||
ModpacksCH::Modpack rightPack = sourceModel()->data(right, Qt::UserRole).value<ModpacksCH::Modpack>();
|
||||
|
||||
if (currentSorting == ByPlays) {
|
||||
return leftPack.plays < rightPack.plays;
|
||||
}
|
||||
else if (currentSorting == ByInstalls) {
|
||||
return leftPack.installs < rightPack.installs;
|
||||
}
|
||||
else if (currentSorting == ByName) {
|
||||
return StringUtils::naturalCompare(leftPack.name, rightPack.name, Qt::CaseSensitive) >= 0;
|
||||
}
|
||||
|
||||
// Invalid sorting set, somehow...
|
||||
qWarning() << "Invalid sorting set!";
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
51
launcher/ui/pages/modplatform/ftb/FtbFilterModel.h
Normal file
@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright 2020-2021 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
|
||||
*
|
||||
* 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 <QtCore/QSortFilterProxyModel>
|
||||
|
||||
namespace Ftb {
|
||||
|
||||
class FilterModel : public QSortFilterProxyModel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
FilterModel(QObject* parent = Q_NULLPTR);
|
||||
enum Sorting {
|
||||
ByPlays,
|
||||
ByInstalls,
|
||||
ByName,
|
||||
};
|
||||
const QMap<QString, Sorting> getAvailableSortings();
|
||||
QString translateCurrentSorting();
|
||||
void setSorting(Sorting sorting);
|
||||
Sorting getCurrentSorting();
|
||||
void setSearchTerm(const QString& term);
|
||||
|
||||
protected:
|
||||
bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const override;
|
||||
bool lessThan(const QModelIndex &left, const QModelIndex &right) const override;
|
||||
|
||||
private:
|
||||
QMap<QString, Sorting> sortings;
|
||||
Sorting currentSorting;
|
||||
QString searchTerm { "" };
|
||||
|
||||
};
|
||||
|
||||
}
|
304
launcher/ui/pages/modplatform/ftb/FtbListModel.cpp
Normal file
@ -0,0 +1,304 @@
|
||||
/*
|
||||
* Copyright 2020-2021 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
|
||||
*
|
||||
* 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 "FtbListModel.h"
|
||||
|
||||
#include "BuildConfig.h"
|
||||
#include "Application.h"
|
||||
#include "Json.h"
|
||||
|
||||
#include <QPainter>
|
||||
|
||||
namespace Ftb {
|
||||
|
||||
ListModel::ListModel(QObject *parent) : QAbstractListModel(parent)
|
||||
{
|
||||
}
|
||||
|
||||
ListModel::~ListModel()
|
||||
{
|
||||
}
|
||||
|
||||
int ListModel::rowCount(const QModelIndex &parent) const
|
||||
{
|
||||
return parent.isValid() ? 0 : modpacks.size();
|
||||
}
|
||||
|
||||
int ListModel::columnCount(const QModelIndex &parent) const
|
||||
{
|
||||
return parent.isValid() ? 0 : 1;
|
||||
}
|
||||
|
||||
QVariant ListModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
int pos = index.row();
|
||||
if(pos >= modpacks.size() || pos < 0 || !index.isValid())
|
||||
{
|
||||
return QString("INVALID INDEX %1").arg(pos);
|
||||
}
|
||||
|
||||
ModpacksCH::Modpack pack = modpacks.at(pos);
|
||||
if(role == Qt::DisplayRole)
|
||||
{
|
||||
return pack.name;
|
||||
}
|
||||
else if (role == Qt::ToolTipRole)
|
||||
{
|
||||
return pack.synopsis;
|
||||
}
|
||||
else if(role == Qt::DecorationRole)
|
||||
{
|
||||
QIcon placeholder = APPLICATION->getThemedIcon("screenshot-placeholder");
|
||||
|
||||
auto iter = m_logoMap.find(pack.name);
|
||||
if (iter != m_logoMap.end()) {
|
||||
auto & logo = *iter;
|
||||
if(!logo.result.isNull()) {
|
||||
return logo.result;
|
||||
}
|
||||
return placeholder;
|
||||
}
|
||||
|
||||
for(auto art : pack.art) {
|
||||
if(art.type == "square") {
|
||||
((ListModel *)this)->requestLogo(pack.name, art.url);
|
||||
}
|
||||
}
|
||||
return placeholder;
|
||||
}
|
||||
else if(role == Qt::UserRole)
|
||||
{
|
||||
QVariant v;
|
||||
v.setValue(pack);
|
||||
return v;
|
||||
}
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
void ListModel::getLogo(const QString &logo, const QString &logoUrl, LogoCallback callback)
|
||||
{
|
||||
if(m_logoMap.contains(logo))
|
||||
{
|
||||
callback(APPLICATION->metacache()->resolveEntry("ModpacksCHPacks", QString("logos/%1").arg(logo.section(".", 0, 0)))->getFullPath());
|
||||
}
|
||||
else
|
||||
{
|
||||
requestLogo(logo, logoUrl);
|
||||
}
|
||||
}
|
||||
|
||||
void ListModel::request()
|
||||
{
|
||||
m_aborted = false;
|
||||
|
||||
beginResetModel();
|
||||
modpacks.clear();
|
||||
endResetModel();
|
||||
|
||||
auto netJob = makeShared<NetJob>("Ftb::Request", APPLICATION->network());
|
||||
auto url = QString(BuildConfig.MODPACKSCH_API_BASE_URL + "public/modpack/all");
|
||||
netJob->addNetAction(Net::Download::makeByteArray(QUrl(url), &response));
|
||||
jobPtr = netJob;
|
||||
jobPtr->start();
|
||||
|
||||
QObject::connect(netJob.get(), &NetJob::succeeded, this, &ListModel::requestFinished);
|
||||
QObject::connect(netJob.get(), &NetJob::failed, this, &ListModel::requestFailed);
|
||||
}
|
||||
|
||||
void ListModel::abortRequest()
|
||||
{
|
||||
m_aborted = jobPtr->abort();
|
||||
jobPtr.reset();
|
||||
}
|
||||
|
||||
void ListModel::requestFinished()
|
||||
{
|
||||
jobPtr.reset();
|
||||
remainingPacks.clear();
|
||||
|
||||
QJsonParseError parse_error {};
|
||||
QJsonDocument doc = QJsonDocument::fromJson(response, &parse_error);
|
||||
if(parse_error.error != QJsonParseError::NoError) {
|
||||
qWarning() << "Error while parsing JSON response from ModpacksCH at " << parse_error.offset << " reason: " << parse_error.errorString();
|
||||
qWarning() << response;
|
||||
return;
|
||||
}
|
||||
|
||||
auto packs = doc.object().value("packs").toArray();
|
||||
for(auto pack : packs) {
|
||||
auto packId = pack.toInt();
|
||||
remainingPacks.append(packId);
|
||||
}
|
||||
|
||||
if(!remainingPacks.isEmpty()) {
|
||||
currentPack = remainingPacks.at(0);
|
||||
requestPack();
|
||||
}
|
||||
}
|
||||
|
||||
void ListModel::requestFailed(QString reason)
|
||||
{
|
||||
jobPtr.reset();
|
||||
remainingPacks.clear();
|
||||
}
|
||||
|
||||
void ListModel::requestPack()
|
||||
{
|
||||
auto netJob = makeShared<NetJob>("Ftb::Search", APPLICATION->network());
|
||||
auto searchUrl = QString(BuildConfig.MODPACKSCH_API_BASE_URL + "public/modpack/%1").arg(currentPack);
|
||||
netJob->addNetAction(Net::Download::makeByteArray(QUrl(searchUrl), &response));
|
||||
jobPtr = netJob;
|
||||
jobPtr->start();
|
||||
|
||||
QObject::connect(netJob.get(), &NetJob::succeeded, this, &ListModel::packRequestFinished);
|
||||
QObject::connect(netJob.get(), &NetJob::failed, this, &ListModel::packRequestFailed);
|
||||
}
|
||||
|
||||
void ListModel::packRequestFinished()
|
||||
{
|
||||
if (!jobPtr || m_aborted)
|
||||
return;
|
||||
|
||||
jobPtr.reset();
|
||||
remainingPacks.removeOne(currentPack);
|
||||
|
||||
QJsonParseError parse_error;
|
||||
QJsonDocument doc = QJsonDocument::fromJson(response, &parse_error);
|
||||
|
||||
if(parse_error.error != QJsonParseError::NoError) {
|
||||
qWarning() << "Error while parsing JSON response from ModpacksCH at " << parse_error.offset << " reason: " << parse_error.errorString();
|
||||
qWarning() << response;
|
||||
return;
|
||||
}
|
||||
|
||||
auto obj = doc.object();
|
||||
|
||||
ModpacksCH::Modpack pack;
|
||||
try
|
||||
{
|
||||
ModpacksCH::loadModpack(pack, obj);
|
||||
}
|
||||
catch (const JSONValidationError &e)
|
||||
{
|
||||
qDebug() << QString::fromUtf8(response);
|
||||
qWarning() << "Error while reading pack manifest from ModpacksCH: " << e.cause();
|
||||
return;
|
||||
}
|
||||
|
||||
// Since there is no guarantee that packs have a version, this will just
|
||||
// ignore those "dud" packs.
|
||||
if (pack.versions.empty())
|
||||
{
|
||||
qWarning() << "ModpacksCH Pack " << pack.id << " ignored. reason: lacking any versions";
|
||||
}
|
||||
else
|
||||
{
|
||||
beginInsertRows(QModelIndex(), modpacks.size(), modpacks.size());
|
||||
modpacks.append(pack);
|
||||
endInsertRows();
|
||||
}
|
||||
|
||||
if(!remainingPacks.isEmpty()) {
|
||||
currentPack = remainingPacks.at(0);
|
||||
requestPack();
|
||||
}
|
||||
}
|
||||
|
||||
void ListModel::packRequestFailed(QString reason)
|
||||
{
|
||||
jobPtr.reset();
|
||||
remainingPacks.removeOne(currentPack);
|
||||
}
|
||||
|
||||
void ListModel::logoLoaded(QString logo, bool stale)
|
||||
{
|
||||
auto & logoObj = m_logoMap[logo];
|
||||
logoObj.downloadJob.reset();
|
||||
QString smallPath = logoObj.fullpath + ".small";
|
||||
|
||||
QFileInfo smallInfo(smallPath);
|
||||
|
||||
if(stale || !smallInfo.exists()) {
|
||||
QImage image(logoObj.fullpath);
|
||||
if (image.isNull())
|
||||
{
|
||||
logoObj.failed = true;
|
||||
return;
|
||||
}
|
||||
QImage small;
|
||||
if (image.width() > image.height()) {
|
||||
small = image.scaledToWidth(512).scaledToWidth(256, Qt::SmoothTransformation);
|
||||
}
|
||||
else {
|
||||
small = image.scaledToHeight(512).scaledToHeight(256, Qt::SmoothTransformation);
|
||||
}
|
||||
QPoint offset((256 - small.width()) / 2, (256 - small.height()) / 2);
|
||||
QImage square(QSize(256, 256), QImage::Format_ARGB32);
|
||||
square.fill(Qt::transparent);
|
||||
|
||||
QPainter painter(&square);
|
||||
painter.drawImage(offset, small);
|
||||
painter.end();
|
||||
|
||||
square.save(logoObj.fullpath + ".small", "PNG");
|
||||
}
|
||||
|
||||
logoObj.result = QIcon(logoObj.fullpath + ".small");
|
||||
for(int i = 0; i < modpacks.size(); i++) {
|
||||
if(modpacks[i].name == logo) {
|
||||
emit dataChanged(createIndex(i, 0), createIndex(i, 0), {Qt::DecorationRole});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ListModel::logoFailed(QString logo)
|
||||
{
|
||||
m_logoMap[logo].failed = true;
|
||||
m_logoMap[logo].downloadJob.reset();
|
||||
}
|
||||
|
||||
void ListModel::requestLogo(QString logo, QString url)
|
||||
{
|
||||
if(m_logoMap.contains(logo)) {
|
||||
return;
|
||||
}
|
||||
|
||||
MetaEntryPtr entry = APPLICATION->metacache()->resolveEntry("ModpacksCHPacks", QString("logos/%1").arg(logo.section(".", 0, 0)));
|
||||
|
||||
bool stale = entry->isStale();
|
||||
|
||||
auto job = makeShared<NetJob>(QString("ModpacksCH Icon Download %1").arg(logo), APPLICATION->network());
|
||||
job->addNetAction(Net::Download::makeCached(QUrl(url), entry));
|
||||
|
||||
auto fullPath = entry->getFullPath();
|
||||
QObject::connect(job.get(), &NetJob::finished, this, [this, logo, fullPath, stale]
|
||||
{
|
||||
logoLoaded(logo, stale);
|
||||
});
|
||||
|
||||
QObject::connect(job.get(), &NetJob::failed, this, [this, logo]
|
||||
{
|
||||
logoFailed(logo);
|
||||
});
|
||||
|
||||
auto &newLogoEntry = m_logoMap[logo];
|
||||
newLogoEntry.downloadJob = job;
|
||||
newLogoEntry.fullpath = fullPath;
|
||||
job->start();
|
||||
}
|
||||
|
||||
}
|
83
launcher/ui/pages/modplatform/ftb/FtbListModel.h
Normal file
@ -0,0 +1,83 @@
|
||||
/*
|
||||
* Copyright 2020-2021 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
|
||||
*
|
||||
* 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 <QAbstractListModel>
|
||||
|
||||
#include "modplatform/modpacksch/FTBPackManifest.h"
|
||||
#include "net/NetJob.h"
|
||||
#include <QIcon>
|
||||
|
||||
namespace Ftb {
|
||||
|
||||
struct Logo {
|
||||
QString fullpath;
|
||||
NetJob::Ptr downloadJob;
|
||||
QIcon result;
|
||||
bool failed = false;
|
||||
};
|
||||
|
||||
typedef QMap<QString, Logo> LogoMap;
|
||||
typedef std::function<void(QString)> LogoCallback;
|
||||
|
||||
class ListModel : public QAbstractListModel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
ListModel(QObject *parent);
|
||||
virtual ~ListModel();
|
||||
|
||||
int rowCount(const QModelIndex &parent) const override;
|
||||
int columnCount(const QModelIndex &parent) const override;
|
||||
QVariant data(const QModelIndex &index, int role) const override;
|
||||
|
||||
void request();
|
||||
void abortRequest();
|
||||
|
||||
void getLogo(const QString &logo, const QString &logoUrl, LogoCallback callback);
|
||||
|
||||
[[nodiscard]] bool isMakingRequest() const { return jobPtr.get(); }
|
||||
[[nodiscard]] bool wasAborted() const { return m_aborted; }
|
||||
|
||||
private slots:
|
||||
void requestFinished();
|
||||
void requestFailed(QString reason);
|
||||
|
||||
void requestPack();
|
||||
void packRequestFinished();
|
||||
void packRequestFailed(QString reason);
|
||||
|
||||
void logoFailed(QString logo);
|
||||
void logoLoaded(QString logo, bool stale);
|
||||
|
||||
private:
|
||||
void requestLogo(QString file, QString url);
|
||||
|
||||
private:
|
||||
bool m_aborted = false;
|
||||
|
||||
QList<ModpacksCH::Modpack> modpacks;
|
||||
LogoMap m_logoMap;
|
||||
|
||||
NetJob::Ptr jobPtr;
|
||||
int currentPack;
|
||||
QList<int> remainingPacks;
|
||||
QByteArray response;
|
||||
};
|
||||
|
||||
}
|
199
launcher/ui/pages/modplatform/ftb/FtbPage.cpp
Normal file
@ -0,0 +1,199 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
/*
|
||||
* PolyMC - Minecraft Launcher
|
||||
* Copyright (c) 2022 Jamie Mansfield <jmansfield@cadixdev.org>
|
||||
* 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 2020-2021 Jamie Mansfield <jmansfield@cadixdev.org>
|
||||
* Copyright 2021 Philip T <me@phit.link>
|
||||
*
|
||||
* 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 "FtbPage.h"
|
||||
#include "ui_FtbPage.h"
|
||||
|
||||
#include <QKeyEvent>
|
||||
|
||||
#include "ui/dialogs/NewInstanceDialog.h"
|
||||
#include "modplatform/modpacksch/FTBPackInstallTask.h"
|
||||
|
||||
#include "Markdown.h"
|
||||
|
||||
FtbPage::FtbPage(NewInstanceDialog* dialog, QWidget *parent)
|
||||
: QWidget(parent), ui(new Ui::FtbPage), dialog(dialog)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
filterModel = new Ftb::FilterModel(this);
|
||||
listModel = new Ftb::ListModel(this);
|
||||
filterModel->setSourceModel(listModel);
|
||||
ui->packView->setModel(filterModel);
|
||||
ui->packView->setSortingEnabled(true);
|
||||
ui->packView->header()->hide();
|
||||
ui->packView->setIndentation(0);
|
||||
|
||||
ui->searchEdit->installEventFilter(this);
|
||||
|
||||
ui->versionSelectionBox->view()->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
|
||||
ui->versionSelectionBox->view()->parentWidget()->setMaximumHeight(300);
|
||||
|
||||
for(int i = 0; i < filterModel->getAvailableSortings().size(); i++)
|
||||
{
|
||||
ui->sortByBox->addItem(filterModel->getAvailableSortings().keys().at(i));
|
||||
}
|
||||
ui->sortByBox->setCurrentText(filterModel->translateCurrentSorting());
|
||||
|
||||
connect(ui->searchEdit, &QLineEdit::textChanged, this, &FtbPage::triggerSearch);
|
||||
connect(ui->sortByBox, &QComboBox::currentTextChanged, this, &FtbPage::onSortingSelectionChanged);
|
||||
connect(ui->packView->selectionModel(), &QItemSelectionModel::currentChanged, this, &FtbPage::onSelectionChanged);
|
||||
connect(ui->versionSelectionBox, &QComboBox::currentTextChanged, this, &FtbPage::onVersionSelectionChanged);
|
||||
|
||||
ui->packDescription->setMetaEntry("FTBPacks");
|
||||
}
|
||||
|
||||
FtbPage::~FtbPage()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
bool FtbPage::eventFilter(QObject* watched, QEvent* event)
|
||||
{
|
||||
if (watched == ui->searchEdit && event->type() == QEvent::KeyPress) {
|
||||
QKeyEvent* keyEvent = static_cast<QKeyEvent*>(event);
|
||||
if (keyEvent->key() == Qt::Key_Return) {
|
||||
triggerSearch();
|
||||
keyEvent->accept();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return QWidget::eventFilter(watched, event);
|
||||
}
|
||||
|
||||
bool FtbPage::shouldDisplay() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void FtbPage::retranslate()
|
||||
{
|
||||
ui->retranslateUi(this);
|
||||
}
|
||||
|
||||
void FtbPage::openedImpl()
|
||||
{
|
||||
if(!initialised || listModel->wasAborted())
|
||||
{
|
||||
listModel->request();
|
||||
initialised = true;
|
||||
}
|
||||
|
||||
suggestCurrent();
|
||||
}
|
||||
|
||||
void FtbPage::closedImpl()
|
||||
{
|
||||
if (listModel->isMakingRequest())
|
||||
listModel->abortRequest();
|
||||
}
|
||||
|
||||
void FtbPage::suggestCurrent()
|
||||
{
|
||||
if(!isOpened)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (selectedVersion.isEmpty())
|
||||
{
|
||||
dialog->setSuggestedPack();
|
||||
return;
|
||||
}
|
||||
|
||||
dialog->setSuggestedPack(selected.name, selectedVersion, new ModpacksCH::PackInstallTask(selected, selectedVersion, this));
|
||||
for(auto art : selected.art) {
|
||||
if(art.type == "square") {
|
||||
QString editedLogoName;
|
||||
editedLogoName = selected.name;
|
||||
|
||||
listModel->getLogo(selected.name, art.url, [this, editedLogoName](QString logo)
|
||||
{
|
||||
dialog->setSuggestedIconFromFile(logo + ".small", editedLogoName);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FtbPage::triggerSearch()
|
||||
{
|
||||
filterModel->setSearchTerm(ui->searchEdit->text());
|
||||
}
|
||||
|
||||
void FtbPage::onSortingSelectionChanged(QString data)
|
||||
{
|
||||
auto toSet = filterModel->getAvailableSortings().value(data);
|
||||
filterModel->setSorting(toSet);
|
||||
}
|
||||
|
||||
void FtbPage::onSelectionChanged(QModelIndex first, QModelIndex second)
|
||||
{
|
||||
ui->versionSelectionBox->clear();
|
||||
|
||||
if(!first.isValid())
|
||||
{
|
||||
if(isOpened)
|
||||
{
|
||||
dialog->setSuggestedPack();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
selected = filterModel->data(first, Qt::UserRole).value<ModpacksCH::Modpack>();
|
||||
|
||||
QString output = markdownToHTML(selected.description.toUtf8());
|
||||
ui->packDescription->setHtml(output);
|
||||
|
||||
// reverse foreach, so that the newest versions are first
|
||||
for (auto i = selected.versions.size(); i--;) {
|
||||
ui->versionSelectionBox->addItem(selected.versions.at(i).name);
|
||||
}
|
||||
|
||||
suggestCurrent();
|
||||
}
|
||||
|
||||
void FtbPage::onVersionSelectionChanged(QString data)
|
||||
{
|
||||
if(data.isNull() || data.isEmpty())
|
||||
{
|
||||
selectedVersion = "";
|
||||
return;
|
||||
}
|
||||
|
||||
selectedVersion = data;
|
||||
suggestCurrent();
|
||||
}
|
105
launcher/ui/pages/modplatform/ftb/FtbPage.h
Normal file
@ -0,0 +1,105 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
/*
|
||||
* PolyMC - Minecraft Launcher
|
||||
* Copyright (c) 2022 Jamie Mansfield <jmansfield@cadixdev.org>
|
||||
*
|
||||
* 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 "FtbFilterModel.h"
|
||||
#include "FtbListModel.h"
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
#include "Application.h"
|
||||
#include "ui/pages/BasePage.h"
|
||||
#include "tasks/Task.h"
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
class FtbPage;
|
||||
}
|
||||
|
||||
class NewInstanceDialog;
|
||||
|
||||
class FtbPage : public QWidget, public BasePage
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit FtbPage(NewInstanceDialog* dialog, QWidget *parent = 0);
|
||||
virtual ~FtbPage();
|
||||
virtual QString displayName() const override
|
||||
{
|
||||
return "FTB";
|
||||
}
|
||||
virtual QIcon icon() const override
|
||||
{
|
||||
return APPLICATION->getThemedIcon("ftb_logo");
|
||||
}
|
||||
virtual QString id() const override
|
||||
{
|
||||
return "ftb";
|
||||
}
|
||||
virtual QString helpPage() const override
|
||||
{
|
||||
return "FTB-platform";
|
||||
}
|
||||
virtual bool shouldDisplay() const override;
|
||||
void retranslate() override;
|
||||
|
||||
void openedImpl() override;
|
||||
void closedImpl() override;
|
||||
|
||||
bool eventFilter(QObject * watched, QEvent * event) override;
|
||||
|
||||
private:
|
||||
void suggestCurrent();
|
||||
|
||||
private slots:
|
||||
void triggerSearch();
|
||||
|
||||
void onSortingSelectionChanged(QString data);
|
||||
void onSelectionChanged(QModelIndex first, QModelIndex second);
|
||||
void onVersionSelectionChanged(QString data);
|
||||
|
||||
private:
|
||||
Ui::FtbPage *ui = nullptr;
|
||||
NewInstanceDialog* dialog = nullptr;
|
||||
Ftb::ListModel* listModel = nullptr;
|
||||
Ftb::FilterModel* filterModel = nullptr;
|
||||
|
||||
ModpacksCH::Modpack selected;
|
||||
QString selectedVersion;
|
||||
|
||||
bool initialised { false };
|
||||
};
|
86
launcher/ui/pages/modplatform/ftb/FtbPage.ui
Normal file
@ -0,0 +1,86 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>FtbPage</class>
|
||||
<widget class="QWidget" name="FtbPage">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>875</width>
|
||||
<height>745</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="2" column="0" colspan="2">
|
||||
<layout class="QGridLayout" name="gridLayout_4" columnstretch="0,0,0" rowminimumheight="0" columnminimumwidth="0,0,0">
|
||||
<item row="0" column="2">
|
||||
<widget class="QComboBox" name="versionSelectionBox"/>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Version selected:</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QComboBox" name="sortByBox"/>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLineEdit" name="searchEdit">
|
||||
<property name="placeholderText">
|
||||
<string>Search and filter...</string>
|
||||
</property>
|
||||
<property name="clearButtonEnabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0" colspan="2">
|
||||
<layout class="QGridLayout" name="gridLayout_3">
|
||||
<item row="0" column="0">
|
||||
<widget class="QTreeView" name="packView">
|
||||
<property name="alternatingRowColors">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="iconSize">
|
||||
<size>
|
||||
<width>48</width>
|
||||
<height>48</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="ProjectDescriptionPage" name="packDescription">
|
||||
<property name="openExternalLinks">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="openLinks">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>ProjectDescriptionPage</class>
|
||||
<extends>QTextBrowser</extends>
|
||||
<header>ui/widgets/ProjectDescriptionPage.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<tabstops>
|
||||
<tabstop>searchEdit</tabstop>
|
||||
<tabstop>versionSelectionBox</tabstop>
|
||||
</tabstops>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
@ -72,6 +72,7 @@ class ThemeCustomizationWidget : public QWidget {
|
||||
{ "kitteh", QObject::tr("Background Cat (from MultiMC)") },
|
||||
{ "rory", QObject::tr("Rory ID 11 (drawn by Ashtaka)") },
|
||||
{ "rory-flat", QObject::tr("Rory ID 11 (flat edition, drawn by Ashtaka)") },
|
||||
{ "teawie", QObject::tr("Teawie (drawn by SympathyTea)") }
|
||||
{ "teawie", QObject::tr("Teawie (drawn by SympathyTea)") },
|
||||
{ "polly", QObject::tr("Polly the Parrot (drawn by anoraktrend)") }
|
||||
};
|
||||
};
|
||||
|
32
nix/NIX.md
@ -6,29 +6,29 @@
|
||||
|
||||
#### Directly installing
|
||||
|
||||
The `prismlauncher` flake provides a package which you can install along with
|
||||
The `pollymc` flake provides a package which you can install along with
|
||||
the rest of your packages
|
||||
|
||||
```nix
|
||||
# In your flake.nix:
|
||||
{
|
||||
inputs = {
|
||||
prismlauncher.url = "github:PrismLauncher/PrismLauncher";
|
||||
pollymc.url = "github:fn2006/PollyMC";
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
```nix
|
||||
# And in your system configuration:
|
||||
environment.systemPackages = [ prismlauncher.packages.${pkgs.system}.prismlauncher ];
|
||||
environment.systemPackages = [ pollymc.packages.${pkgs.system}.pollymc ];
|
||||
|
||||
# Or in your home-manager configuration:
|
||||
home.packages = [ prismlauncher.packages.${pkgs.system}.prismlauncher ];
|
||||
home.packages = [ pollymc.packages.${pkgs.system}.pollymc ];
|
||||
```
|
||||
|
||||
#### Using the overlay
|
||||
|
||||
Alternatively, you can overlay the prismlauncher version in nixpkgs which will
|
||||
Alternatively, you can overlay the pollymc version in nixpkgs which will
|
||||
allow you to install using `pkgs` as you normally would while also using the
|
||||
latest version
|
||||
|
||||
@ -36,19 +36,19 @@ latest version
|
||||
# In your flake.nix:
|
||||
{
|
||||
inputs = {
|
||||
prismlauncher.url = "github:PrismLauncher/PrismLauncher";
|
||||
pollymc.url = "github:fn2006/PollyMC";
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
```nix
|
||||
# And in your system configuration:
|
||||
nixpkgs.overlays = [ inputs.prismlauncher.overlay ];
|
||||
environment.systemPackages = [ pkgs.prismlauncher ];
|
||||
nixpkgs.overlays = [ inputs.pollymc.overlay ];
|
||||
environment.systemPackages = [ pkgs.pollymc ];
|
||||
|
||||
# Or in your home-manager configuration:
|
||||
config.nixpkgs.overlays = [ inputs.prismlauncher.overlay ];
|
||||
home.packages = [ pkgs.prismlauncher ];
|
||||
config.nixpkgs.overlays = [ inputs.pollymc.overlay ];
|
||||
home.packages = [ pkgs.pollymc ];
|
||||
```
|
||||
|
||||
### Without flakes-enabled nix
|
||||
@ -56,9 +56,9 @@ home.packages = [ pkgs.prismlauncher ];
|
||||
#### Using channels
|
||||
|
||||
```sh
|
||||
nix-channel --add https://github.com/PrismLauncher/PrismLauncher/archive/master.tar.gz prismlauncher
|
||||
nix-channel --update prismlauncher
|
||||
nix-env -iA prismlauncher
|
||||
nix-channel --add https://github.com/fn2006/PollyMC/archive/master.tar.gz pollymc
|
||||
nix-channel --update pollymc
|
||||
nix-env -iA pollymc
|
||||
```
|
||||
|
||||
#### Using the overlay
|
||||
@ -67,10 +67,10 @@ nix-env -iA prismlauncher
|
||||
# In your configuration.nix:
|
||||
{
|
||||
nixpkgs.overlays = [
|
||||
(import (builtins.fetchTarball "https://github.com/PrismLauncher/PrismLauncher/archive/develop.tar.gz")).overlay
|
||||
(import (builtins.fetchTarball "https://github.com/fn2006/PollyMC/archive/develop.tar.gz")).overlay
|
||||
];
|
||||
|
||||
environment.systemPackages = with pkgs; [ prismlauncher ];
|
||||
environment.systemPackages = with pkgs; [ pollymc ];
|
||||
}
|
||||
```
|
||||
|
||||
@ -79,5 +79,5 @@ nix-env -iA prismlauncher
|
||||
If you're on a flakes-enabled nix you can run the launcher in one-line
|
||||
|
||||
```sh
|
||||
nix run github:PrismLauncher/PrismLauncher
|
||||
nix run github:fn2006/PollyMC
|
||||
```
|
||||
|
@ -6,8 +6,8 @@
|
||||
}: {
|
||||
perSystem = {pkgs, ...}: {
|
||||
packages = {
|
||||
inherit (pkgs) prismlauncher-qt5-unwrapped prismlauncher-qt5 prismlauncher-unwrapped prismlauncher;
|
||||
default = pkgs.prismlauncher;
|
||||
inherit (pkgs) pollymc-qt5-unwrapped pollymc-qt5 pollymc-unwrapped pollymc;
|
||||
default = pkgs.pollymc;
|
||||
};
|
||||
};
|
||||
|
||||
@ -20,10 +20,10 @@
|
||||
inherit self version;
|
||||
};
|
||||
in {
|
||||
prismlauncher-qt5-unwrapped = mkPrism final.libsForQt5;
|
||||
prismlauncher-qt5 = prev.prismlauncher-qt5.override {prismlauncher-unwrapped = final.prismlauncher-qt5-unwrapped;};
|
||||
prismlauncher-unwrapped = mkPrism final.qt6Packages;
|
||||
prismlauncher = prev.prismlauncher.override {inherit (final) prismlauncher-unwrapped;};
|
||||
pollymc-qt5-unwrapped = mkPrism final.libsForQt5;
|
||||
pollymc-qt5 = prev.pollymc-qt5.override {pollymc-unwrapped = final.pollymc-qt5-unwrapped;};
|
||||
pollymc-unwrapped = mkPrism final.qt6Packages;
|
||||
pollymc = prev.pollymc.override {inherit (final) pollymc-unwrapped;};
|
||||
};
|
||||
};
|
||||
}
|
||||
|
@ -19,7 +19,7 @@
|
||||
libnbtplusplus,
|
||||
}:
|
||||
stdenv.mkDerivation rec {
|
||||
pname = "prismlauncher-unwrapped";
|
||||
pname = "pollymc-unwrapped";
|
||||
inherit version;
|
||||
|
||||
src = lib.cleanSource self;
|
||||
@ -50,7 +50,7 @@ stdenv.mkDerivation rec {
|
||||
dontWrapQtApps = true;
|
||||
|
||||
meta = with lib; {
|
||||
homepage = "https://prismlauncher.org/";
|
||||
homepage = "https://github.com/fn2006/PollyMC";
|
||||
description = "A free, open source launcher for Minecraft";
|
||||
longDescription = ''
|
||||
Allows you to have multiple, separate instances of Minecraft (each with
|
||||
@ -58,8 +58,8 @@ stdenv.mkDerivation rec {
|
||||
their associated options with a simple interface.
|
||||
'';
|
||||
platforms = platforms.linux;
|
||||
changelog = "https://github.com/PrismLauncher/PrismLauncher/releases/tag/${version}";
|
||||
changelog = "https://github.com/fn2006/PollyMC/releases/tag/${version}";
|
||||
license = licenses.gpl3Only;
|
||||
maintainers = with maintainers; [minion3665 Scrumplex];
|
||||
maintainers = with maintainers; [fn2006];
|
||||
};
|
||||
}
|
||||
|
@ -8,49 +8,49 @@ if(UNIX)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set(Launcher_CommonName "PrismLauncher")
|
||||
set(Launcher_DisplayName "Prism Launcher")
|
||||
set(Launcher_CommonName "PollyMC")
|
||||
set(Launcher_DisplayName "PollyMC")
|
||||
|
||||
set(Launcher_Name "${Launcher_CommonName}" PARENT_SCOPE)
|
||||
set(Launcher_DisplayName "${Launcher_DisplayName}" PARENT_SCOPE)
|
||||
|
||||
set(Launcher_Copyright "Prism Launcher Contributors\\n© 2021-2022 PolyMC Contributors \\n© 2012-2021 MultiMC Contributors")
|
||||
set(Launcher_Copyright_Mac "Prism Launcher Contributors, © 2021-2022 PolyMC Contributors and © 2012-2021 MultiMC Contributors" PARENT_SCOPE)
|
||||
set(Launcher_Copyright "© 2022-2023 PollyMC Contributors\\n© 2022-2023 Prism Launcher Contributors\\n© 2021-2022 PolyMC Contributors \\n© 2012-2021 MultiMC Contributors")
|
||||
set(Launcher_Copyright_Mac "© 2022-2023 PollyMC Contributors, © 2022-2023 Prism Launcher Contributors, © 2021-2022 PolyMC Contributors and © 2012-2021 MultiMC Contributors" PARENT_SCOPE)
|
||||
set(Launcher_Copyright "${Launcher_Copyright}" PARENT_SCOPE)
|
||||
set(Launcher_Domain "prismlauncher.org" PARENT_SCOPE)
|
||||
set(Launcher_UserAgent "${Launcher_CommonName}/${Launcher_VERSION_NAME}" PARENT_SCOPE)
|
||||
set(Launcher_ConfigFile "prismlauncher.cfg" PARENT_SCOPE)
|
||||
set(Launcher_Git "https://github.com/PrismLauncher/PrismLauncher" PARENT_SCOPE)
|
||||
set(Launcher_DesktopFileName "org.prismlauncher.PrismLauncher.desktop" PARENT_SCOPE)
|
||||
set(Launcher_SVGFileName "org.prismlauncher.PrismLauncher.svg" PARENT_SCOPE)
|
||||
set(Launcher_Domain "" PARENT_SCOPE)
|
||||
set(Launcher_UserAgent "PrismLauncher/${Launcher_RELEASE_VERSION_NAME}" PARENT_SCOPE)
|
||||
set(Launcher_ConfigFile "pollymc.cfg" PARENT_SCOPE)
|
||||
set(Launcher_Git "https://github.com/fn2006/PollyMC" PARENT_SCOPE)
|
||||
set(Launcher_DesktopFileName "org.fn2006.PollyMC.desktop" PARENT_SCOPE)
|
||||
set(Launcher_SVGFileName "org.fn2006.PollyMC.svg" PARENT_SCOPE)
|
||||
|
||||
set(Launcher_Desktop "program_info/org.prismlauncher.PrismLauncher.desktop" PARENT_SCOPE)
|
||||
set(Launcher_Desktop "program_info/org.fn2006.PollyMC.desktop" PARENT_SCOPE)
|
||||
set(Launcher_mrpack_MIMEInfo "program_info/modrinth-mrpack-mime.xml" PARENT_SCOPE)
|
||||
set(Launcher_MetaInfo "program_info/org.prismlauncher.PrismLauncher.metainfo.xml" PARENT_SCOPE)
|
||||
set(Launcher_SVG "program_info/org.prismlauncher.PrismLauncher.svg" PARENT_SCOPE)
|
||||
set(Launcher_MetaInfo "program_info/org.fn2006.PollyMC.metainfo.xml" PARENT_SCOPE)
|
||||
set(Launcher_SVG "program_info/org.fn2006.PollyMC.svg" PARENT_SCOPE)
|
||||
set(Launcher_Branding_ICNS "program_info/prismlauncher.icns" PARENT_SCOPE)
|
||||
set(Launcher_Branding_ICO "program_info/prismlauncher.ico")
|
||||
set(Launcher_Branding_ICO "program_info/pollymc.ico")
|
||||
set(Launcher_Branding_ICO "${Launcher_Branding_ICO}" PARENT_SCOPE)
|
||||
set(Launcher_Branding_WindowsRC "program_info/prismlauncher.rc" PARENT_SCOPE)
|
||||
set(Launcher_Branding_WindowsRC "program_info/pollymc.rc" PARENT_SCOPE)
|
||||
set(Launcher_Branding_LogoQRC "program_info/prismlauncher.qrc" PARENT_SCOPE)
|
||||
|
||||
set(Launcher_Portable_File "program_info/portable.txt" PARENT_SCOPE)
|
||||
|
||||
configure_file(org.prismlauncher.PrismLauncher.desktop.in org.prismlauncher.PrismLauncher.desktop)
|
||||
configure_file(org.prismlauncher.PrismLauncher.metainfo.xml.in org.prismlauncher.PrismLauncher.metainfo.xml)
|
||||
configure_file(prismlauncher.rc.in prismlauncher.rc @ONLY)
|
||||
configure_file(prismlauncher.manifest.in prismlauncher.manifest @ONLY)
|
||||
configure_file(prismlauncher.ico prismlauncher.ico COPYONLY)
|
||||
configure_file(org.fn2006.PollyMC.desktop.in org.fn2006.PollyMC.desktop)
|
||||
configure_file(org.fn2006.PollyMC.metainfo.xml.in org.fn2006.PollyMC.metainfo.xml)
|
||||
configure_file(pollymc.rc.in pollymc.rc @ONLY)
|
||||
configure_file(pollymc.manifest.in pollymc.manifest @ONLY)
|
||||
configure_file(pollymc.ico pollymc.ico COPYONLY)
|
||||
configure_file(win_install.nsi.in win_install.nsi @ONLY)
|
||||
|
||||
if(SCDOC_FOUND)
|
||||
set(in_scd "${CMAKE_CURRENT_SOURCE_DIR}/prismlauncher.6.scd")
|
||||
set(out_man "${CMAKE_CURRENT_BINARY_DIR}/prismlauncher.6")
|
||||
set(in_scd "${CMAKE_CURRENT_SOURCE_DIR}/pollymc.6.scd")
|
||||
set(out_man "${CMAKE_CURRENT_BINARY_DIR}/pollymc.6")
|
||||
add_custom_command(
|
||||
DEPENDS "${in_scd}"
|
||||
OUTPUT "${out_man}"
|
||||
COMMAND ${SCDOC_SCDOC} < "${in_scd}" > "${out_man}"
|
||||
)
|
||||
add_custom_target(man ALL DEPENDS ${out_man})
|
||||
set(Launcher_ManPage "program_info/prismlauncher.6" PARENT_SCOPE)
|
||||
set(Launcher_ManPage "program_info/pollymc.6" PARENT_SCOPE)
|
||||
endif()
|
||||
|
162
program_info/org.fn2006.PollyMC Source.svg
Normal file
@ -0,0 +1,162 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
width="64"
|
||||
height="64"
|
||||
viewBox="0 0 64 64"
|
||||
version="1.1"
|
||||
id="svg99"
|
||||
inkscape:version="1.2.1 (9c6d41e410, 2022-07-14)"
|
||||
sodipodi:docname="org.fn2006.PollyMC Source.svg"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<sodipodi:namedview
|
||||
id="namedview101"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#000000"
|
||||
borderopacity="0.25"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
inkscape:document-units="px"
|
||||
showgrid="false"
|
||||
inkscape:zoom="9.4927604"
|
||||
inkscape:cx="52.355688"
|
||||
inkscape:cy="38.345011"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="994"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="layer1" />
|
||||
<defs
|
||||
id="defs96">
|
||||
<inkscape:path-effect
|
||||
effect="powerclip"
|
||||
id="path-effect5638"
|
||||
is_visible="true"
|
||||
lpeversion="1"
|
||||
inverse="true"
|
||||
flatten="false"
|
||||
hide_clip="false"
|
||||
message="Use fill-rule evenodd on <b>fill and stroke</b> dialog if no flatten result after convert clip to paths." />
|
||||
<inkscape:path-effect
|
||||
effect="powerclip"
|
||||
id="path-effect5562"
|
||||
is_visible="true"
|
||||
lpeversion="1"
|
||||
inverse="true"
|
||||
flatten="false"
|
||||
hide_clip="false"
|
||||
message="Use fill-rule evenodd on <b>fill and stroke</b> dialog if no flatten result after convert clip to paths." />
|
||||
<inkscape:path-effect
|
||||
effect="powerclip"
|
||||
id="path-effect5535"
|
||||
is_visible="true"
|
||||
lpeversion="1"
|
||||
inverse="true"
|
||||
flatten="false"
|
||||
hide_clip="false"
|
||||
message="Use fill-rule evenodd on <b>fill and stroke</b> dialog if no flatten result after convert clip to paths." />
|
||||
</defs>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1">
|
||||
<g
|
||||
id="g5269"
|
||||
clip-path="none"
|
||||
transform="matrix(1.25,0,0,1.25,-8,-10.5)">
|
||||
<g
|
||||
id="g926"
|
||||
inkscape:label="head">
|
||||
<path
|
||||
style="fill:#8acb01;fill-opacity:1"
|
||||
id="rect883"
|
||||
width="12"
|
||||
height="33.599998"
|
||||
x="31.173504"
|
||||
y="16"
|
||||
sodipodi:type="rect"
|
||||
inkscape:label="head2"
|
||||
d="m 31.173504,16 h 12 v 33.599998 h -12 z">
|
||||
<title
|
||||
id="title910">head2</title>
|
||||
</path>
|
||||
<path
|
||||
style="fill:#8acb01;fill-opacity:1"
|
||||
id="path916"
|
||||
width="25.979649"
|
||||
height="31.200001"
|
||||
x="30.020351"
|
||||
y="16"
|
||||
sodipodi:type="rect"
|
||||
inkscape:label="head1"
|
||||
d="M 30.020351,16 H 56 V 47.200001 H 30.020351 Z">
|
||||
<title
|
||||
id="title914">head1</title>
|
||||
</path>
|
||||
<path
|
||||
style="fill:#8acb01;fill-opacity:1"
|
||||
id="path352"
|
||||
width="24.03161"
|
||||
height="36"
|
||||
x="8"
|
||||
y="16"
|
||||
sodipodi:type="rect"
|
||||
inkscape:label="head"
|
||||
d="M 8,16 H 32.03161 V 52 H 8 Z">
|
||||
<title
|
||||
id="title908">head</title>
|
||||
</path>
|
||||
</g>
|
||||
<g
|
||||
id="g932"
|
||||
transform="matrix(1.0033333,0,0,1.0033333,-0.14666667,-0.09333333)"
|
||||
inkscape:label="beak">
|
||||
<path
|
||||
style="display:inline;fill:#313131;fill-opacity:1"
|
||||
id="rect1721"
|
||||
width="12"
|
||||
height="21.6"
|
||||
x="32"
|
||||
y="28"
|
||||
sodipodi:type="rect"
|
||||
d="M 32,28 H 44 V 49.6 H 32 Z" />
|
||||
<path
|
||||
style="display:inline;fill:#313131;fill-opacity:1"
|
||||
id="path928"
|
||||
width="24"
|
||||
height="19.200001"
|
||||
x="32"
|
||||
y="28"
|
||||
sodipodi:type="rect"
|
||||
d="M 32,28 H 56 V 47.200001 H 32 Z" />
|
||||
</g>
|
||||
<path
|
||||
style="fill:#000000;fill-opacity:1"
|
||||
id="rect3491"
|
||||
width="12.08"
|
||||
height="12.08"
|
||||
x="19.960001"
|
||||
y="28"
|
||||
sodipodi:type="rect"
|
||||
d="m 19.960001,28 h 12.08 v 12.08 h -12.08 z"
|
||||
inkscape:label="eye" />
|
||||
<path
|
||||
style="fill:#b0af8d;fill-opacity:1"
|
||||
id="rect3493"
|
||||
width="12.08"
|
||||
height="12.08"
|
||||
x="19.959999"
|
||||
y="40"
|
||||
sodipodi:type="rect"
|
||||
d="m 19.959999,40 h 12.08 v 12.08 h -12.08 z"
|
||||
inkscape:label="cheek" />
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 4.7 KiB |
207
program_info/org.fn2006.PollyMC.bigsur.svg
Normal file
@ -0,0 +1,207 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
width="1024"
|
||||
height="1024"
|
||||
viewBox="0 0 1024 1024"
|
||||
fill="none"
|
||||
version="1.1"
|
||||
id="svg1070"
|
||||
sodipodi:docname="org.fn2006.PollyMC.bigsur.svg"
|
||||
xml:space="preserve"
|
||||
inkscape:version="1.2.1 (9c6d41e410, 2022-07-14)"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"><sodipodi:namedview
|
||||
id="namedview1072"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#000000"
|
||||
borderopacity="0.25"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
showgrid="false"
|
||||
inkscape:zoom="0.01"
|
||||
inkscape:cx="-125500"
|
||||
inkscape:cy="-70400"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="994"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg1070" /><g
|
||||
filter="url(#filter0_d_102_69)"
|
||||
id="g998"><path
|
||||
fill-rule="evenodd"
|
||||
clip-rule="evenodd"
|
||||
d="M924 354.627C924 344.845 924.004 335.062 923.944 325.279C923.895 317.038 923.8 308.799 923.576 300.562C923.092 282.609 922.033 264.502 918.84 246.749C915.602 228.741 910.314 211.98 901.981 195.617C893.789 179.534 883.088 164.817 870.32 152.058C857.555 139.299 842.834 128.605 826.746 120.418C810.366 112.083 793.587 106.797 775.558 103.56C757.803 100.372 739.691 99.315 721.738 98.83C713.495 98.607 705.253 98.513 697.008 98.462C687.22 98.402 677.432 98.407 667.644 98.407L553.997 98H468.997L357.361 98.407C347.554 98.407 337.747 98.402 327.94 98.462C319.678 98.513 311.42 98.607 303.161 98.83C285.167 99.315 267.014 100.373 249.217 103.565C231.164 106.801 214.36 112.085 197.958 120.414C181.835 128.602 167.083 139.297 154.291 152.058C141.501 164.816 130.78 179.53 122.573 195.61C114.217 211.981 108.919 228.752 105.673 246.77C102.477 264.516 101.418 282.617 100.931 300.562C100.709 308.8 100.613 317.039 100.563 325.279C100.503 335.063 100 347.216 100 356.999L100.003 467.089L100 552.998L100.508 665.427C100.508 675.223 100.504 685.019 100.563 694.815C100.613 703.067 100.709 711.317 100.932 719.566C101.418 737.542 102.479 755.675 105.678 773.452C108.923 791.484 114.22 808.269 122.569 824.653C130.777 840.759 141.5 855.495 154.291 868.272C167.082 881.049 181.83 891.757 197.95 899.956C214.362 908.302 231.174 913.595 249.238 916.836C267.027 920.029 285.174 921.088 303.161 921.573C311.42 921.796 319.679 921.891 327.941 921.941C337.748 922.001 347.554 921.997 357.361 921.997L470.006 922H555.217L667.644 921.996C677.432 921.996 687.22 922.001 697.008 921.941C705.253 921.891 713.495 921.796 721.738 921.573C739.698 921.087 757.816 920.027 775.579 916.832C793.597 913.591 810.368 908.3 826.739 899.959C842.831 891.761 857.554 881.051 870.32 868.272C883.086 855.497 893.786 840.763 901.978 824.66C910.316 808.268 915.604 791.475 918.844 773.431C922.034 755.661 923.092 737.535 923.577 719.566C923.8 711.316 923.895 703.066 923.944 694.815C924.005 685.019 924 675.223 924 665.427C924 665.427 923.994 554.983 923.994 552.998V466.999C923.994 465.533 924 354.627 924 354.627Z"
|
||||
fill="url(#paint0_linear_102_69)"
|
||||
id="path996" /></g><mask
|
||||
id="mask0_102_69"
|
||||
style="mask-type: alpha"
|
||||
maskUnits="userSpaceOnUse"
|
||||
x="100"
|
||||
y="98"
|
||||
width="824"
|
||||
height="824"><path
|
||||
fill-rule="evenodd"
|
||||
clip-rule="evenodd"
|
||||
d="M924 354.627C924 344.845 924.004 335.062 923.944 325.279C923.895 317.038 923.8 308.799 923.576 300.562C923.092 282.609 922.033 264.502 918.84 246.749C915.602 228.741 910.314 211.98 901.981 195.617C893.789 179.534 883.088 164.817 870.32 152.058C857.555 139.299 842.834 128.605 826.746 120.418C810.366 112.083 793.587 106.797 775.558 103.56C757.803 100.372 739.691 99.315 721.738 98.83C713.495 98.607 705.253 98.513 697.008 98.462C687.22 98.402 677.432 98.407 667.644 98.407L553.997 98H468.997L357.361 98.407C347.554 98.407 337.747 98.402 327.94 98.462C319.678 98.513 311.42 98.607 303.161 98.83C285.167 99.315 267.014 100.373 249.217 103.565C231.164 106.801 214.36 112.085 197.958 120.414C181.835 128.602 167.083 139.297 154.291 152.058C141.501 164.816 130.78 179.53 122.573 195.61C114.217 211.981 108.919 228.752 105.673 246.77C102.477 264.516 101.418 282.617 100.931 300.562C100.709 308.8 100.613 317.039 100.563 325.279C100.503 335.063 100 347.216 100 356.999L100.003 467.089L100 552.998L100.508 665.427C100.508 675.223 100.504 685.019 100.563 694.815C100.613 703.067 100.709 711.317 100.932 719.566C101.418 737.542 102.479 755.675 105.678 773.452C108.923 791.484 114.22 808.269 122.569 824.653C130.777 840.759 141.5 855.495 154.291 868.272C167.082 881.049 181.83 891.757 197.95 899.956C214.362 908.302 231.174 913.595 249.238 916.836C267.027 920.029 285.174 921.088 303.161 921.573C311.42 921.796 319.679 921.891 327.941 921.941C337.748 922.001 347.554 921.997 357.361 921.997L470.006 922H555.217L667.644 921.996C677.432 921.996 687.22 922.001 697.008 921.941C705.253 921.891 713.495 921.796 721.738 921.573C739.698 921.087 757.816 920.027 775.579 916.832C793.597 913.591 810.368 908.3 826.739 899.959C842.831 891.761 857.554 881.051 870.32 868.272C883.086 855.497 893.786 840.763 901.978 824.66C910.316 808.268 915.604 791.475 918.844 773.431C922.034 755.661 923.092 737.535 923.577 719.566C923.8 711.316 923.895 703.066 923.944 694.815C924.005 685.019 924 675.223 924 665.427C924 665.427 923.994 554.983 923.994 552.998V466.999C923.994 465.533 924 354.627 924 354.627Z"
|
||||
fill="white"
|
||||
id="path1000" /></mask><g
|
||||
mask="url(#mask0_102_69)"
|
||||
id="g1009"><rect
|
||||
x="42"
|
||||
y="36"
|
||||
width="914"
|
||||
height="914"
|
||||
fill="url(#paint1_linear_102_69)"
|
||||
id="rect1003" /><g
|
||||
filter="url(#filter1_b_102_69)"
|
||||
id="g1007"><rect
|
||||
x="100"
|
||||
y="98"
|
||||
width="824"
|
||||
height="824"
|
||||
rx="126"
|
||||
fill="black"
|
||||
fill-opacity="0.01"
|
||||
id="rect1005" /></g></g><defs
|
||||
id="defs1068"><filter
|
||||
id="filter0_d_102_69"
|
||||
x="90"
|
||||
y="98"
|
||||
width="844"
|
||||
height="844"
|
||||
filterUnits="userSpaceOnUse"
|
||||
color-interpolation-filters="sRGB"><feFlood
|
||||
flood-opacity="0"
|
||||
result="BackgroundImageFix"
|
||||
id="feFlood1025" /><feColorMatrix
|
||||
in="SourceAlpha"
|
||||
type="matrix"
|
||||
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"
|
||||
result="hardAlpha"
|
||||
id="feColorMatrix1027" /><feOffset
|
||||
dy="10"
|
||||
id="feOffset1029" /><feGaussianBlur
|
||||
stdDeviation="5"
|
||||
id="feGaussianBlur1031" /><feColorMatrix
|
||||
type="matrix"
|
||||
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.3 0"
|
||||
id="feColorMatrix1033" /><feBlend
|
||||
mode="normal"
|
||||
in2="BackgroundImageFix"
|
||||
result="effect1_dropShadow_102_69"
|
||||
id="feBlend1035" /><feBlend
|
||||
mode="normal"
|
||||
in="SourceGraphic"
|
||||
in2="effect1_dropShadow_102_69"
|
||||
result="shape"
|
||||
id="feBlend1037" /></filter><filter
|
||||
id="filter1_b_102_69"
|
||||
x="89.1269"
|
||||
y="87.1269"
|
||||
width="845.746"
|
||||
height="845.746"
|
||||
filterUnits="userSpaceOnUse"
|
||||
color-interpolation-filters="sRGB"><feFlood
|
||||
flood-opacity="0"
|
||||
result="BackgroundImageFix"
|
||||
id="feFlood1040" /><feGaussianBlur
|
||||
in="BackgroundImage"
|
||||
stdDeviation="5.43656"
|
||||
id="feGaussianBlur1042" /><feComposite
|
||||
in2="SourceAlpha"
|
||||
operator="in"
|
||||
result="effect1_backgroundBlur_102_69"
|
||||
id="feComposite1044" /><feBlend
|
||||
mode="normal"
|
||||
in="SourceGraphic"
|
||||
in2="effect1_backgroundBlur_102_69"
|
||||
result="shape"
|
||||
id="feBlend1046" /></filter><linearGradient
|
||||
id="paint0_linear_102_69"
|
||||
x1="-181.14"
|
||||
y1="98"
|
||||
x2="-181.14"
|
||||
y2="1484.28"
|
||||
gradientUnits="userSpaceOnUse"><stop
|
||||
stop-color="white"
|
||||
id="stop1049" /><stop
|
||||
offset="0.489516"
|
||||
stop-color="#EFEFEF"
|
||||
id="stop1051" /><stop
|
||||
offset="1"
|
||||
stop-color="#C0C0C0"
|
||||
id="stop1053" /></linearGradient><linearGradient
|
||||
id="paint1_linear_102_69"
|
||||
x1="928.377"
|
||||
y1="992.826"
|
||||
x2="928.377"
|
||||
y2="134.072"
|
||||
gradientUnits="userSpaceOnUse"><stop
|
||||
stop-color="#F6F3F3"
|
||||
id="stop1056" /><stop
|
||||
offset="1"
|
||||
stop-color="white"
|
||||
id="stop1058" /></linearGradient><linearGradient
|
||||
id="paint2_linear_102_69"
|
||||
x1="394.815"
|
||||
y1="372.239"
|
||||
x2="629.182"
|
||||
y2="542.528"
|
||||
gradientUnits="userSpaceOnUse"><stop
|
||||
stop-color="#88B858"
|
||||
id="stop1061" /><stop
|
||||
offset="0.5"
|
||||
stop-color="#72B147"
|
||||
id="stop1063" /><stop
|
||||
offset="1"
|
||||
stop-color="#5A9A30"
|
||||
id="stop1065" /></linearGradient><inkscape:path-effect
|
||||
effect="powerclip"
|
||||
id="path-effect5638"
|
||||
is_visible="true"
|
||||
lpeversion="1"
|
||||
inverse="true"
|
||||
flatten="false"
|
||||
hide_clip="false"
|
||||
message="Use fill-rule evenodd on <b>fill and stroke</b> dialog if no flatten result after convert clip to paths." /><inkscape:path-effect
|
||||
effect="powerclip"
|
||||
id="path-effect5562"
|
||||
is_visible="true"
|
||||
lpeversion="1"
|
||||
inverse="true"
|
||||
flatten="false"
|
||||
hide_clip="false"
|
||||
message="Use fill-rule evenodd on <b>fill and stroke</b> dialog if no flatten result after convert clip to paths." /><inkscape:path-effect
|
||||
effect="powerclip"
|
||||
id="path-effect5535"
|
||||
is_visible="true"
|
||||
lpeversion="1"
|
||||
inverse="true"
|
||||
flatten="false"
|
||||
hide_clip="false"
|
||||
message="Use fill-rule evenodd on <b>fill and stroke</b> dialog if no flatten result after convert clip to paths." /></defs><g
|
||||
id="g5269"
|
||||
clip-path="none"
|
||||
transform="matrix(10,0,0,10,192.005,170.0135)"><path
|
||||
id="path352"
|
||||
style="fill:#8acb01"
|
||||
inkscape:label="head"
|
||||
d="M 8,16 H 32.03161 V 52 H 8 Z m 22.020351,0 H 56 V 47.200001 H 30.020351 Z m 1.153153,0 h 12 v 33.599998 h -12 z"><title
|
||||
id="title908">head</title></path><path
|
||||
id="rect3493"
|
||||
style="display:inline;fill:#b0af8d;stroke-width:1.39562"
|
||||
inkscape:label="cheek"
|
||||
d="M 19.959999,28.879064 H 32.253197 V 52 H 19.959999 Z" /><path
|
||||
id="rect3491"
|
||||
inkscape:label="eye"
|
||||
d="M 19.960001,28 H 32.333299 V 40 H 19.960001 Z"
|
||||
style="stroke-width:1.00871;fill:#000000;fill-opacity:1" /><path
|
||||
id="path928"
|
||||
style="display:inline;fill:#3b3b3b;fill-opacity:1;stroke-width:1.00922"
|
||||
d="M 32,27.999999 H 56 V 47.555555 H 32 Z m 0,0 h 12 v 22 H 32 Z"
|
||||
inkscape:label="beak" /></g></svg>
|
After Width: | Height: | Size: 11 KiB |
13
program_info/org.fn2006.PollyMC.desktop.in
Executable file
@ -0,0 +1,13 @@
|
||||
#!/usr/bin/env xdg-open
|
||||
[Desktop Entry]
|
||||
Version=1.0
|
||||
Name=PollyMC
|
||||
Comment=A custom launcher for Minecraft that allows you to easily manage multiple installations of Minecraft at once.
|
||||
Type=Application
|
||||
Terminal=false
|
||||
Exec=@Launcher_APP_BINARY_NAME@
|
||||
StartupNotify=true
|
||||
Icon=org.fn2006.PollyMC
|
||||
Categories=Game;
|
||||
Keywords=game;minecraft;launcher;mc;
|
||||
StartupWMClass=PollyMC
|
35
program_info/org.fn2006.PollyMC.metainfo.xml.in
Normal file
@ -0,0 +1,35 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<component type="desktop">
|
||||
<id>org.fn2006.PollyMC</id>
|
||||
<provides>
|
||||
<id>org.fn2006.PollyMC</id>
|
||||
</provides>
|
||||
<launchable type="desktop-id">org.fn2006.PollyMC.desktop</launchable>
|
||||
<name>PollyMC</name>
|
||||
<developer_name>fn2006C</developer_name>
|
||||
<summary>A custom launcher for Minecraft that allows you to easily manage multiple installations of Minecraft at once</summary>
|
||||
<metadata_license>CC0-1.0</metadata_license>
|
||||
<project_license>GPL-3.0-only</project_license>
|
||||
<url type="homepage">https://github.com/fn2006/PollyMC/</url>
|
||||
<url type="help">https://polymc.org/wiki/</url>
|
||||
<description>
|
||||
<p>PollyMC is a custom launcher for Minecraft that focuses on predictability, long term stability and simplicity.</p>
|
||||
<p>Features:</p>
|
||||
<ul>
|
||||
<li>Easily install game modifications, such as Fabric, Forge and Quilt</li>
|
||||
<li>Control your java settings</li>
|
||||
<li>Manage worlds and resource packs from the launcher</li>
|
||||
<li>See logs and other details easily</li>
|
||||
<li>Kill Minecraft in case of a crash/freeze</li>
|
||||
<li>Isolate minecraft instances to keep everything clean</li>
|
||||
<li>Install and update mods directly from the launcher</li>
|
||||
</ul>
|
||||
</description>
|
||||
<releases>
|
||||
<release version="@Launcher_VERSION_NAME@" date="@Launcher_BUILD_TIMESTAMP@"></release>
|
||||
</releases>
|
||||
<content_rating type="oars-1.1">
|
||||
<content_attribute id="violence-fantasy">moderate</content_attribute>
|
||||
<content_attribute id="social-chat">intense</content_attribute>
|
||||
</content_rating>
|
||||
</component>
|