diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml
deleted file mode 100644
index 247675fc..00000000
--- a/.github/FUNDING.yml
+++ /dev/null
@@ -1 +0,0 @@
-open_collective: polymc
diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml
index ab3c8a29..24ae5b7a 100644
--- a/.github/ISSUE_TEMPLATE/bug_report.yml
+++ b/.github/ISSUE_TEMPLATE/bug_report.yml
@@ -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 [PolyMC wiki](https://polymc.org/wiki/) and it has not answered your question.
* Your bug is not caused by Minecraft or any mods you have installed.
@@ -25,15 +23,15 @@ body:
- Other
- type: textarea
attributes:
- label: Version of PolyMC
- description: The version of PolyMC used in the bug report.
- placeholder: PolyMC 1.4.1
+ label: Version of PollyMC
+ description: The version of PollyMC used in the bug report.
+ placeholder: PollyMC 1.4.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 PolyMC -> 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
diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml
index 932d0c8f..0086358d 100644
--- a/.github/ISSUE_TEMPLATE/config.yml
+++ b/.github/ISSUE_TEMPLATE/config.yml
@@ -1,5 +1 @@
blank_issues_enabled: true
-contact_links:
- - name: PolyMC Matrix Support Room
- url: https://matrix.to/#/#support:polymc.org
- about: Please ask for support here before opening an issue.
diff --git a/.github/ISSUE_TEMPLATE/rfc.yml b/.github/ISSUE_TEMPLATE/rfc.yml
index 0a40d01d..323aa9b3 100644
--- a/.github/ISSUE_TEMPLATE/rfc.yml
+++ b/.github/ISSUE_TEMPLATE/rfc.yml
@@ -6,38 +6,38 @@ body:
- type: markdown
attributes:
value: |
- ### Use this form to suggest a larger change for PolyMC.
+ ### 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 PolyMC, 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
diff --git a/.github/ISSUE_TEMPLATE/suggestion.yml b/.github/ISSUE_TEMPLATE/suggestion.yml
index 48f157b3..69d34ea9 100644
--- a/.github/ISSUE_TEMPLATE/suggestion.yml
+++ b/.github/ISSUE_TEMPLATE/suggestion.yml
@@ -5,26 +5,26 @@ body:
- type: markdown
attributes:
value: |
- ### Use this form to suggest a feature for PolyMC.
+ ### Use this form to suggest a feature for PollyMC.
- type: input
attributes:
label: Role
- description: In what way do you use PolyMC 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 PolyMC 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 PolyMC 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
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 434c5775..e47eb983 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -219,9 +219,9 @@ jobs:
cmake --install ${{ env.BUILD_DIR }}
cd ${{ env.INSTALL_DIR }}
- chmod +x "PolyMC.app/Contents/MacOS/polymc"
- sudo codesign --sign - --deep --force --entitlements "../program_info/App.entitlements" --options runtime "PolyMC.app/Contents/MacOS/polymc"
- tar -czf ../PolyMC.tar.gz *
+ 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: runner.os == 'macOS'
@@ -229,7 +229,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 }}/PolyMC.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:
@@ -273,7 +273,7 @@ jobs:
cmake --install ${{ env.BUILD_DIR }} --prefix ${{ env.INSTALL_DIR }}
cd ${{ env.INSTALL_DIR }}
- tar --owner root --group root -czf ../PolyMC.tar.gz *
+ tar --owner root --group root -czf ../PollyMC.tar.gz *
- name: Package (Linux, portable)
if: runner.os == 'Linux'
@@ -282,7 +282,7 @@ jobs:
cmake --install ${{ env.BUILD_DIR }} --prefix ${{ env.INSTALL_PORTABLE_DIR }} --component portable
cd ${{ env.INSTALL_PORTABLE_DIR }}
- tar -czf ../PolyMC-portable.tar.gz *
+ tar -czf ../PollyMC-portable.tar.gz *
- name: Package AppImage (Linux)
if: runner.os == 'Linux' && matrix.qt_ver != 5
@@ -290,7 +290,7 @@ jobs:
run: |
cmake --install ${{ env.BUILD_DIR }} --prefix ${{ env.INSTALL_APPIMAGE_DIR }}/usr
- export OUTPUT="PolyMC-${{ runner.os }}-${{ env.VERSION }}-${{ inputs.build_type }}-x86_64.AppImage"
+ export OUTPUT="PollyMC-${{ runner.os }}-${{ env.VERSION }}-${{ inputs.build_type }}-x86_64.AppImage"
chmod +x linuxdeploy-*.AppImage
@@ -301,7 +301,7 @@ jobs:
cp -r ${{ github.workspace }}/JREs/jre17/* ${{ env.INSTALL_APPIMAGE_DIR }}/usr/lib/jvm/java-17-openjdk
- cp -r /home/runner/work/PolyMC/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/
@@ -313,7 +313,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.polymc.PolyMC.svg
+ ./linuxdeploy-x86_64.AppImage --appdir ${{ env.INSTALL_APPIMAGE_DIR }} --output appimage --plugin qt -i ${{ env.INSTALL_APPIMAGE_DIR }}/usr/share/icons/hicolor/scalable/apps/org.fn2006.PollyMC.svg
##
# UPLOAD BUILDS
@@ -323,63 +323,63 @@ jobs:
if: runner.os == 'macOS'
uses: actions/upload-artifact@v3
with:
- name: PolyMC-${{ runner.os }}-${{ env.VERSION }}-${{ inputs.build_type }}
- path: PolyMC.tar.gz
+ name: PollyMC-${{ runner.os }}-${{ 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: PolyMC-${{ 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: PolyMC-${{ 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: PolyMC-${{ matrix.name }}-Setup-${{ env.VERSION }}-${{ inputs.build_type }}
- path: PolyMC-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: PolyMC-${{ runner.os }}-${{ env.VERSION }}-${{ inputs.build_type }}
- path: PolyMC.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: PolyMC-${{ runner.os }}-Portable-${{ env.VERSION }}-${{ inputs.build_type }}
- path: PolyMC-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: PolyMC-${{ runner.os }}-Qt6-${{ env.VERSION }}-${{ inputs.build_type }}
- path: PolyMC.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: PolyMC-${{ runner.os }}-Qt6-Portable-${{ env.VERSION }}-${{ inputs.build_type }}
- path: PolyMC-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: PolyMC-${{ runner.os }}-${{ env.VERSION }}-${{ inputs.build_type }}-x86_64.AppImage
- path: PolyMC-${{ 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
diff --git a/.github/workflows/trigger_builds.yml b/.github/workflows/trigger_builds.yml
index 55b4fdd4..ee9eb4ea 100644
--- a/.github/workflows/trigger_builds.yml
+++ b/.github/workflows/trigger_builds.yml
@@ -11,7 +11,6 @@ on:
- '**.nix'
- 'packages/**'
- '.github/ISSUE_TEMPLATE/**'
- - '.markdownlint**'
pull_request:
paths-ignore:
- '**.md'
@@ -20,7 +19,6 @@ on:
- '**.nix'
- 'packages/**'
- '.github/ISSUE_TEMPLATE/**'
- - '.markdownlint**'
workflow_dispatch:
jobs:
diff --git a/.github/workflows/trigger_release.yml b/.github/workflows/trigger_release.yml
index 45ef7281..af5c2137 100644
--- a/.github/workflows/trigger_release.yml
+++ b/.github/workflows/trigger_release.yml
@@ -25,7 +25,7 @@ jobs:
uses: actions/checkout@v3
with:
submodules: 'true'
- path: 'PolyMC-source'
+ path: 'PollyMC-source'
- name: Download artifacts
uses: actions/download-artifact@v3
- name: Grab and store version
@@ -34,25 +34,25 @@ jobs:
echo "VERSION=$tag_name" >> $GITHUB_ENV
- name: Package artifacts properly
run: |
- mv ${{ github.workspace }}/PolyMC-source PolyMC-${{ env.VERSION }}
- mv PolyMC-Linux-Qt6-Portable*/PolyMC-portable.tar.gz PolyMC-Linux-Qt6-Portable-${{ env.VERSION }}.tar.gz
- mv PolyMC-Linux-Qt6*/PolyMC.tar.gz PolyMC-Linux-Qt6-${{ env.VERSION }}.tar.gz
- mv PolyMC-Linux-Portable*/PolyMC-portable.tar.gz PolyMC-Linux-Portable-${{ env.VERSION }}.tar.gz
- mv PolyMC-Linux*/PolyMC.tar.gz PolyMC-Linux-${{ env.VERSION }}.tar.gz
- mv PolyMC-*.AppImage/PolyMC-*.AppImage PolyMC-Linux-${{ env.VERSION }}-x86_64.AppImage
- mv PolyMC-macOS*/PolyMC.tar.gz PolyMC-macOS-${{ env.VERSION }}.tar.gz
+ 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*/PollyMC.tar.gz PollyMC-macOS-${{ env.VERSION }}.tar.gz
- tar -czf PolyMC-${{ env.VERSION }}.tar.gz PolyMC-${{ env.VERSION }}
+ tar -czf PollyMC-${{ env.VERSION }}.tar.gz PollyMC-${{ env.VERSION }}
- for d in PolyMC-Windows-*; do
+ for d in PollyMC-Windows-*; do
cd "${d}" || continue
LEGACY="$(echo -n ${d} | grep -o Legacy || true)"
INST="$(echo -n ${d} | grep -o Setup || true)"
PORT="$(echo -n ${d} | grep -o Portable || true)"
- NAME="PolyMC-Windows"
+ NAME="PollyMC-Windows"
test -z "${LEGACY}" || NAME="${NAME}-Legacy"
test -z "${PORT}" || NAME="${NAME}-Portable"
- test -z "${INST}" || mv PolyMC-*.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
@@ -64,20 +64,20 @@ jobs:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag_name: ${{ github.ref }}
- name: PolyMC ${{ env.VERSION }}
+ name: PollyMC ${{ env.VERSION }}
draft: true
prerelease: false
files: |
- PolyMC-Linux-${{ env.VERSION }}.tar.gz
- PolyMC-Linux-Portable-${{ env.VERSION }}.tar.gz
- PolyMC-Linux-${{ env.VERSION }}-x86_64.AppImage
- PolyMC-Windows-Legacy-${{ env.VERSION }}.zip
- PolyMC-Linux-Qt6-${{ env.VERSION }}.tar.gz
- PolyMC-Linux-Qt6-Portable-${{ env.VERSION }}.tar.gz
- PolyMC-Windows-Legacy-Portable-${{ env.VERSION }}.zip
- PolyMC-Windows-Legacy-Setup-${{ env.VERSION }}.exe
- PolyMC-Windows-${{ env.VERSION }}.zip
- PolyMC-Windows-Portable-${{ env.VERSION }}.zip
- PolyMC-Windows-Setup-${{ env.VERSION }}.exe
- PolyMC-macOS-${{ env.VERSION }}.tar.gz
- PolyMC-${{ 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-Windows-Legacy-${{ env.VERSION }}.zip
+ PollyMC-Linux-Qt6-${{ env.VERSION }}.tar.gz
+ PollyMC-Linux-Qt6-Portable-${{ env.VERSION }}.tar.gz
+ PollyMC-Windows-Legacy-Portable-${{ env.VERSION }}.zip
+ PollyMC-Windows-Legacy-Setup-${{ env.VERSION }}.exe
+ PollyMC-Windows-${{ env.VERSION }}.zip
+ PollyMC-Windows-Portable-${{ env.VERSION }}.zip
+ PollyMC-Windows-Setup-${{ env.VERSION }}.exe
+ PollyMC-macOS-${{ env.VERSION }}.tar.gz
+ PollyMC-${{ env.VERSION }}.tar.gz
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 7100ab1b..e9f838a9 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -99,19 +99,19 @@ set(Launcher_META_URL "https://meta.polymc.org/v1/" CACHE STRING "URL to fetch L
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/PolyMC/PolyMC/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/polymc/polymc/" CACHE STRING "URL for the translations platform.")
# Matrix Space
-set(Launcher_MATRIX_URL "https://matrix.to/#/#polymc:matrix.org" CACHE STRING "URL to the Matrix Space")
+set(Launcher_MATRIX_URL "" CACHE STRING "URL to the Matrix Space")
# Discord URL
-set(Launcher_DISCORD_URL "https://discord.gg/Z52pwxWCHP" 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://www.reddit.com/r/PolyMCLauncher/" 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")
@@ -126,12 +126,12 @@ set(Launcher_QT_VERSION_MAJOR "5" 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 "549033b2-1532-4d4e-ae77-1bbaa46f9d74" CACHE STRING "Client ID you can get from Microsoft Identity Platform when you register an application")
+set(Launcher_MSA_CLIENT_ID "" 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.
-set(Launcher_CURSEFORGE_API_KEY "$2a$10$1Oqr2MX3O4n/ilhFGc597u8tfI3L2Hyr9/rtWDAMRjghSQV2QUuxq" CACHE STRING "API key for the CurseForge platform")
+set(Launcher_CURSEFORGE_API_KEY "" CACHE STRING "API key for the CurseForge platform")
#### Check the current Git commit and branch
@@ -194,7 +194,7 @@ endif()
####################################### Program Info #######################################
-set(Launcher_APP_BINARY_NAME "polymc" 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 #######################################
diff --git a/README.md b/README.md
index 6ff868e0..8e270d7a 100644
--- a/README.md
+++ b/README.md
@@ -1,100 +1,13 @@
-
-
+
+
-PolyMC is a custom launcher for Minecraft that focuses on predictability, long term stability and simplicity.
+PollyMC is a **fork** of PolyMC and is not endorsed by or affiliated with the PolyMC project.
+If you have any problems open an issue here, do not bug the PolyMC maintainers.
-This is a **fork** of the MultiMC Launcher and not endorsed by MultiMC.
-If you want to read about why this fork was created, check out [our FAQ page](https://polymc.org/wiki/overview/faq/).
-
+Binaries can be found in releases.
-# Installation
+Workaround for downloading from CurseForge and FTB not working [here](https://github.com/fn2006/PollyMC/wiki/CurseForge-Workaround).
-- All downloads and instructions for PolyMC can be found [here](https://polymc.org/download/)
-- Last build status:
-
-## Development Builds
-
-There are per-commit development builds available [here](https://github.com/PolyMC/PolyMC/actions). These have debug information in the binaries, so their file sizes are relatively larger.
-Portable builds are provided for AppImage on Linux, Windows, and macOS.
-
-For Debian and Arch, you can use these packages for the latest development versions:
-[![polymc-git](https://img.shields.io/badge/aur-polymc--git-blue)](https://aur.archlinux.org/packages/polymc-git/)
-[![polymc-git](https://img.shields.io/badge/mpr-polymc--git-orange)](https://mpr.makedeb.org/packages/polymc-git)
-For flatpak, you can use [flathub-beta](https://discourse.flathub.org/t/how-to-use-flathub-beta/2111)
-
-# Help & Support
-
-Feel free to create an issue if you need help. However, you might find it easier to ask in the Discord server.
-
-[![PolyMC Discord](https://img.shields.io/discord/923671181020766230?label=PolyMC%20Discord)](https://discord.gg/xq7fxrgtMP)
-
-For people who don't want to use Discord, we have a Matrix Space which is bridged to the Discord server:
-
-[![PolyMC Space](https://img.shields.io/matrix/polymc:matrix.org?label=PolyMC%20space)](https://matrix.to/#/#polymc:matrix.org)
-
-If there are any issues with the space or you are using a client that does not support the feature here are the individual rooms:
-
-[![Development](https://img.shields.io/matrix/polymc-development:matrix.org?label=PolyMC%20Development)](https://matrix.to/#/#polymc-development:matrix.org)
-[![Discussion](https://img.shields.io/matrix/polymc-discussion:matrix.org?label=PolyMC%20Discussion)](https://matrix.to/#/#polymc-discussion:matrix.org)
-[![Github](https://img.shields.io/matrix/polymc-github:matrix.org?label=PolyMC%20Github)](https://matrix.to/#/#polymc-github:matrix.org)
-[![Maintainers](https://img.shields.io/matrix/polymc-maintainers:matrix.org?label=PolyMC%20Maintainers)](https://matrix.to/#/#polymc-maintainers:matrix.org)
-[![News](https://img.shields.io/matrix/polymc-news:matrix.org?label=PolyMC%20News)](https://matrix.to/#/#polymc-news:matrix.org)
-[![Offtopic](https://img.shields.io/matrix/polymc-offtopic:matrix.org?label=PolyMC%20Offtopic)](https://matrix.to/#/#polymc-offtopic:matrix.org)
-[![Support](https://img.shields.io/matrix/polymc-support:matrix.org?label=PolyMC%20Support)](https://matrix.to/#/#polymc-support:matrix.org)
-[![Voice](https://img.shields.io/matrix/polymc-voice:matrix.org?label=PolyMC%20Voice)](https://matrix.to/#/#polymc-voice:matrix.org)
-
-We also have a subreddit you can post your issues and suggestions on:
-
-[r/PolyMCLauncher](https://www.reddit.com/r/PolyMCLauncher/)
-
-# Development
-
-If you want to contribute to PolyMC you might find it useful to join our Discord Server or Matrix Space.
-
-## Building
-
-If you want to build PolyMC yourself, check [Build Instructions](https://polymc.org/wiki/development/build-instructions/) for build instructions.
-
-## Translations
-
-The translation effort for PolyMC is hosted on [Weblate](https://hosted.weblate.org/projects/polymc/polymc/) and information about translating PolyMC is available at
-
-## Download information
-
-To modify download information or change packaging information send a pull request or issue to the website [here](https://github.com/PolyMC/polymc.github.io/tree/master/src/download).
-
-## 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 PolyMC and is not endorsed by or affiliated with the PolyMC project ().
-- Go through [CMakeLists.txt](CMakeLists.txt) and change PolyMC'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 (`""`).
-
-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.
-
-## Sponsors
-
-Thank you to all our generous backers over at Open Collective! Support PolyMC by [becoming a backer](https://opencollective.com/polymc).
-
-[![OpenCollective Backers](https://opencollective.com/polymc/backers.svg?width=890&limit=1000)](https://opencollective.com/polymc#backers)
-
-Also, 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/)
-
-Additionally, thanks to the awesome people over at [MacStadium](https://www.macstadium.com/), for providing M1-Macs for development purposes!
-
-
+To build this yourself, follow the instructions on the PolyMC website but clone this repo instead.
diff --git a/launcher/Application.cpp b/launcher/Application.cpp
index c4179b49..cb3f6c8c 100644
--- a/launcher/Application.cpp
+++ b/launcher/Application.cpp
@@ -881,6 +881,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.";
}
@@ -1223,7 +1224,8 @@ void Application::setIconTheme(const QString& name)
QIcon Application::getThemedIcon(const QString& name)
{
if(name == "logo") {
- return QIcon(":/org.polymc.PolyMC.svg");
+ // why is this hardcoded lol
+ return QIcon(":/org.fn2006.PollyMC.svg");
}
return QIcon::fromTheme(name);
}
diff --git a/launcher/CMakeLists.txt b/launcher/CMakeLists.txt
index e44b98eb..360209b5 100644
--- a/launcher/CMakeLists.txt
+++ b/launcher/CMakeLists.txt
@@ -206,11 +206,15 @@ 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/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/GetSkinStep.cpp
minecraft/auth/steps/GetSkinStep.h
minecraft/auth/steps/LauncherLoginStep.cpp
@@ -223,6 +227,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
@@ -258,6 +264,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
@@ -774,6 +782,8 @@ SET(LAUNCHER_SOURCES
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/IconPickerDialog.cpp
@@ -924,6 +934,7 @@ qt_wrap_ui(LAUNCHER_UI
ui/dialogs/IconPickerDialog.ui
ui/dialogs/MSALoginDialog.ui
ui/dialogs/OfflineLoginDialog.ui
+ ui/dialogs/ElybyLoginDialog.ui
ui/dialogs/AboutDialog.ui
ui/dialogs/LoginDialog.ui
ui/dialogs/EditAccountDialog.ui
diff --git a/launcher/minecraft/MinecraftInstance.cpp b/launcher/minecraft/MinecraftInstance.cpp
index 9478b1b8..ef1fbfef 100644
--- a/launcher/minecraft/MinecraftInstance.cpp
+++ b/launcher/minecraft/MinecraftInstance.cpp
@@ -356,6 +356,7 @@ QStringList MinecraftInstance::extraArguments()
if (!addn.isEmpty()) {
list.append(addn);
}
+
auto agents = m_components->getProfile()->getAgents();
for (auto agent : agents)
{
@@ -363,6 +364,13 @@ QStringList MinecraftInstance::extraArguments()
agent->library()->getApplicableFiles(currentSystem, 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;
}
@@ -978,7 +986,14 @@ shared_qobject_ptr MinecraftInstance::createLaunchTask(AuthSessionPt
if(!session->demo) {
process->appendStep(new ClaimAccount(pptr, session));
}
+
+ // authlib patch
+ if (session->user_type == "elyby")
+ {
+ process->appendStep(new InjectAuthlib(pptr, &m_injector));
+ }
process->appendStep(new Update(pptr, Net::Mode::Online));
+
}
else
{
diff --git a/launcher/minecraft/MinecraftInstance.h b/launcher/minecraft/MinecraftInstance.h
index d62ac655..c3c2d850 100644
--- a/launcher/minecraft/MinecraftInstance.h
+++ b/launcher/minecraft/MinecraftInstance.h
@@ -5,6 +5,7 @@
#include
#include
#include "minecraft/launch/MinecraftServerTarget.h"
+#include "minecraft/launch/InjectAuthlib.h"
class ModFolderModel;
class ResourceFolderModel;
@@ -134,6 +135,7 @@ protected: // data
mutable std::shared_ptr m_texture_pack_list;
mutable std::shared_ptr m_world_list;
mutable std::shared_ptr m_game_options;
+ mutable std::shared_ptr m_injector;
};
typedef std::shared_ptr MinecraftInstancePtr;
diff --git a/launcher/minecraft/auth/AccountData.cpp b/launcher/minecraft/auth/AccountData.cpp
index 44f7e256..50ca155f 100644
--- a/launcher/minecraft/auth/AccountData.cpp
+++ b/launcher/minecraft/auth/AccountData.cpp
@@ -352,6 +352,8 @@ bool AccountData::resumeStateFromV3(QJsonObject data) {
type = AccountType::Mojang;
} else if (typeS == "Offline") {
type = AccountType::Offline;
+ } else if (typeS == "Elyby") {
+ type = AccountType::Elyby;
} else {
qWarning() << "Failed to parse account data: type is not recognized.";
return false;
@@ -409,6 +411,9 @@ QJsonObject AccountData::saveState() const {
else if (type == AccountType::Offline) {
output["type"] = "Offline";
}
+ else if (type == AccountType::Elyby) {
+ output["type"] = "Elyby";
+ }
tokenToJSONV3(output, yggdrasilToken, "ygg");
profileToJSONV3(output, minecraftProfile, "profile");
@@ -428,14 +433,14 @@ QString AccountData::accessToken() const {
}
QString AccountData::clientToken() const {
- if(type != AccountType::Mojang) {
+ if(type != AccountType::Mojang && type != AccountType::Elyby) {
return QString();
}
return yggdrasilToken.extra["clientToken"].toString();
}
void AccountData::setClientToken(QString clientToken) {
- if(type != AccountType::Mojang) {
+ if(type != AccountType::Mojang && type != AccountType::Elyby) {
return;
}
yggdrasilToken.extra["clientToken"] = clientToken;
@@ -449,7 +454,7 @@ void AccountData::generateClientTokenIfMissing() {
}
void AccountData::invalidateClientToken() {
- if(type != AccountType::Mojang) {
+ if(type != AccountType::Mojang && type != AccountType::Elyby) {
return;
}
yggdrasilToken.extra["clientToken"] = QUuid::createUuid().toString().remove(QRegularExpression("[{-}]"));
@@ -473,6 +478,9 @@ QString AccountData::accountDisplayString() const {
case AccountType::Mojang: {
return userName();
}
+ case AccountType::Elyby: {
+ return userName();
+ }
case AccountType::Offline: {
return QObject::tr("");
}
diff --git a/launcher/minecraft/auth/AccountData.h b/launcher/minecraft/auth/AccountData.h
index 092e1691..c11aa146 100644
--- a/launcher/minecraft/auth/AccountData.h
+++ b/launcher/minecraft/auth/AccountData.h
@@ -74,7 +74,8 @@ struct MinecraftProfile {
enum class AccountType {
MSA,
Mojang,
- Offline
+ Offline,
+ Elyby
};
enum class AccountState {
diff --git a/launcher/minecraft/auth/AccountList.cpp b/launcher/minecraft/auth/AccountList.cpp
index b3b57c74..4f7f0a12 100644
--- a/launcher/minecraft/auth/AccountList.cpp
+++ b/launcher/minecraft/auth/AccountList.cpp
@@ -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()) {
diff --git a/launcher/minecraft/auth/MinecraftAccount.cpp b/launcher/minecraft/auth/MinecraftAccount.cpp
index 73d570f1..86b5c80e 100644
--- a/launcher/minecraft/auth/MinecraftAccount.cpp
+++ b/launcher/minecraft/auth/MinecraftAccount.cpp
@@ -51,6 +51,7 @@
#include "flows/MSA.h"
#include "flows/Mojang.h"
#include "flows/Offline.h"
+#include "flows/Elyby.h"
MinecraftAccount::MinecraftAccount(QObject* parent) : QObject(parent) {
data.internalId = QUuid::createUuid().toString().remove(QRegularExpression("[{}-]"));
@@ -106,6 +107,17 @@ MinecraftAccountPtr MinecraftAccount::createOffline(const QString &username)
return account;
}
+MinecraftAccountPtr MinecraftAccount::createElyby(const QString &username)
+{
+ MinecraftAccountPtr account = new 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;
+}
+
QJsonObject MinecraftAccount::saveToJson() const
{
@@ -162,6 +174,17 @@ shared_qobject_ptr MinecraftAccount::loginOffline() {
return m_currentTask;
}
+shared_qobject_ptr 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 MinecraftAccount::refresh() {
if(m_currentTask) {
return m_currentTask;
@@ -173,6 +196,9 @@ shared_qobject_ptr 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 {
m_currentTask.reset(new MojangRefresh(&data));
}
diff --git a/launcher/minecraft/auth/MinecraftAccount.h b/launcher/minecraft/auth/MinecraftAccount.h
index 7777f846..923df0f5 100644
--- a/launcher/minecraft/auth/MinecraftAccount.h
+++ b/launcher/minecraft/auth/MinecraftAccount.h
@@ -95,6 +95,8 @@ public: /* construction */
static MinecraftAccountPtr createOffline(const QString &username);
+ static MinecraftAccountPtr createElyby(const QString &username);
+
static MinecraftAccountPtr loadFromJsonV2(const QJsonObject &json);
static MinecraftAccountPtr loadFromJsonV3(const QJsonObject &json);
@@ -113,6 +115,8 @@ public: /* manipulation */
shared_qobject_ptr loginOffline();
+ shared_qobject_ptr loginElyby(QString password);
+
shared_qobject_ptr refresh();
shared_qobject_ptr currentTask();
@@ -152,10 +156,18 @@ 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 ownsMinecraft() const {
return data.minecraftEntitlement.ownsMinecraft;
}
@@ -180,6 +192,9 @@ public: /* queries */
case AccountType::Offline: {
return "offline";
}
+ case AccountType::Elyby: {
+ return "elyby";
+ }
break;
default: {
return "unknown";
diff --git a/launcher/minecraft/auth/Yggdrasil.cpp b/launcher/minecraft/auth/Yggdrasil.cpp
index 29978411..acc026be 100644
--- a/launcher/minecraft/auth/Yggdrasil.cpp
+++ b/launcher/minecraft/auth/Yggdrasil.cpp
@@ -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,7 @@ void Yggdrasil::login(QString password) {
QJsonDocument doc(req);
- QUrl reqUrl("https://authserver.mojang.com/authenticate");
+ QUrl reqUrl(baseUrl + "authenticate");
QNetworkRequest netRequest(reqUrl);
QByteArray requestData = doc.toJson();
diff --git a/launcher/minecraft/auth/Yggdrasil.h b/launcher/minecraft/auth/Yggdrasil.h
index 4f52a04c..34eb18b2 100644
--- a/launcher/minecraft/auth/Yggdrasil.h
+++ b/launcher/minecraft/auth/Yggdrasil.h
@@ -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
{
diff --git a/launcher/minecraft/auth/flows/Elyby.cpp b/launcher/minecraft/auth/flows/Elyby.cpp
new file mode 100644
index 00000000..72c10472
--- /dev/null
+++ b/launcher/minecraft/auth/flows/Elyby.cpp
@@ -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(new ElybyStep(m_data, QString()));
+ m_steps.append(new ElybyProfileStep(m_data));
+ m_steps.append(new GetSkinStep(m_data));
+}
+
+ElybyLogin::ElybyLogin(
+ AccountData *data,
+ QString password,
+ QObject *parent
+): AuthFlow(data, parent), m_password(password) {
+ m_steps.append(new ElybyStep(m_data, m_password));
+ m_steps.append(new ElybyProfileStep(m_data));
+ m_steps.append(new GetSkinStep(m_data));
+}
diff --git a/launcher/minecraft/auth/flows/Elyby.h b/launcher/minecraft/auth/flows/Elyby.h
new file mode 100644
index 00000000..beec3e62
--- /dev/null
+++ b/launcher/minecraft/auth/flows/Elyby.h
@@ -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;
+};
diff --git a/launcher/minecraft/auth/steps/ElybyProfileStep.cpp b/launcher/minecraft/auth/steps/ElybyProfileStep.cpp
new file mode 100644
index 00000000..8cd34ffa
--- /dev/null
+++ b/launcher/minecraft/auth/steps/ElybyProfileStep.cpp
@@ -0,0 +1,93 @@
+#include "ElybyProfileStep.h"
+
+#include
+
+#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 headers
+) {
+ auto requestor = qobject_cast(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.")
+ );
+}
diff --git a/launcher/minecraft/auth/steps/ElybyProfileStep.h b/launcher/minecraft/auth/steps/ElybyProfileStep.h
new file mode 100644
index 00000000..765d79e9
--- /dev/null
+++ b/launcher/minecraft/auth/steps/ElybyProfileStep.h
@@ -0,0 +1,22 @@
+#pragma once
+#include
+
+#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);
+};
diff --git a/launcher/minecraft/auth/steps/ElybyStep.cpp b/launcher/minecraft/auth/steps/ElybyStep.cpp
new file mode 100644
index 00000000..e81ebb09
--- /dev/null
+++ b/launcher/minecraft/auth/steps/ElybyStep.cpp
@@ -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.");
+ }
+ emit finished(state, errorMessage);
+}
diff --git a/launcher/minecraft/auth/steps/ElybyStep.h b/launcher/minecraft/auth/steps/ElybyStep.h
new file mode 100644
index 00000000..5bf8f52c
--- /dev/null
+++ b/launcher/minecraft/auth/steps/ElybyStep.h
@@ -0,0 +1,28 @@
+#pragma once
+#include
+
+#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;
+};
diff --git a/launcher/minecraft/auth/steps/YggdrasilStep.cpp b/launcher/minecraft/auth/steps/YggdrasilStep.cpp
index e1d33172..d46dce9b 100644
--- a/launcher/minecraft/auth/steps/YggdrasilStep.cpp
+++ b/launcher/minecraft/auth/steps/YggdrasilStep.cpp
@@ -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/");
}
}
diff --git a/launcher/minecraft/launch/InjectAuthlib.cpp b/launcher/minecraft/launch/InjectAuthlib.cpp
new file mode 100644
index 00000000..51bc3834
--- /dev/null
+++ b/launcher/minecraft/launch/InjectAuthlib.cpp
@@ -0,0 +1,173 @@
+/* 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
+#include
+#include
+#include
+#include
+
+InjectAuthlib::InjectAuthlib(LaunchTask *parent, AuthlibInjectorPtr* injector) : LaunchStep(parent)
+{
+ m_injector = injector;
+}
+
+void InjectAuthlib::executeTask()
+{
+ if (m_aborted)
+ {
+ emitFailed(tr("Task aborted."));
+ return;
+ }
+
+ auto latestVersionInfo = QString("https://authlib-injector.yushi.moe/artifact/latest.json");
+ auto netJob = new 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, &NetJob::succeeded, this, &InjectAuthlib::onVersionDownloadSucceeded);
+ QObject::connect(netJob, &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 = new 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, &NetJob::succeeded, this, &InjectAuthlib::onDownloadSucceeded);
+ QObject::connect(netJob, &NetJob::failed, this, &InjectAuthlib::onDownloadFailed);
+ jobPtr->start();
+ }
+ else
+ {
+ onDownloadSucceeded();
+ }
+}
+
+void InjectAuthlib::onDownloadSucceeded()
+{
+ QString injector = QString("%1=%2").arg(QDir("injectors").absoluteFilePath(m_versionName)).arg("ely.by");
+
+ 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;
+}
diff --git a/launcher/minecraft/launch/InjectAuthlib.h b/launcher/minecraft/launch/InjectAuthlib.h
new file mode 100644
index 00000000..5274f55d
--- /dev/null
+++ b/launcher/minecraft/launch/InjectAuthlib.h
@@ -0,0 +1,75 @@
+/* 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
+#include
+#include
+#include
+#include
+#include
+
+struct AuthlibInjector
+{
+ QString javaArg;
+
+ AuthlibInjector(const QString arg)
+ {
+ javaArg = std::move(arg);
+ qDebug() << "NEW INJECTOR" << javaArg;
+ }
+};
+
+typedef std::shared_ptr 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);
+ 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 jobPtr;
+ bool m_aborted = false;
+
+ bool m_offlineMode;
+ QString m_versionName;
+ QString m_authServer;
+ AuthlibInjectorPtr *m_injector;
+};
diff --git a/launcher/resources/OSX/scalable/launcher.svg b/launcher/resources/OSX/scalable/launcher.svg
index c192d503..64c6d335 100644
--- a/launcher/resources/OSX/scalable/launcher.svg
+++ b/launcher/resources/OSX/scalable/launcher.svg
@@ -1,21 +1,99 @@
-
+
-