aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.github/ISSUE_TEMPLATE/rfc.yml69
-rw-r--r--.github/workflows/build.yml73
-rw-r--r--.github/workflows/trigger_builds.yml22
-rw-r--r--.github/workflows/trigger_release.yml99
-rw-r--r--CMakeLists.txt2
-rw-r--r--CODE_OF_CONDUCT.md136
-rw-r--r--README.md50
-rw-r--r--flake.nix12
-rw-r--r--launcher/Application.cpp67
-rw-r--r--launcher/BaseInstance.cpp1
-rw-r--r--launcher/CMakeLists.txt10
-rw-r--r--launcher/InstanceCopyTask.cpp1
-rw-r--r--launcher/InstanceCreationTask.cpp2
-rw-r--r--launcher/InstanceImportTask.cpp3
-rw-r--r--launcher/InstanceList.cpp7
-rw-r--r--launcher/InstancePageProvider.h41
-rw-r--r--launcher/LaunchController.cpp12
-rw-r--r--launcher/minecraft/MinecraftInstance.cpp11
-rw-r--r--launcher/minecraft/PackProfile.cpp254
-rw-r--r--launcher/minecraft/PackProfile.h2
-rw-r--r--launcher/minecraft/PackProfile_p.h12
-rw-r--r--launcher/minecraft/auth/AccountData.cpp5
-rw-r--r--launcher/minecraft/auth/AccountData.h2
-rw-r--r--launcher/minecraft/auth/AccountList.cpp3
-rw-r--r--launcher/minecraft/auth/AccountTask.cpp8
-rw-r--r--launcher/minecraft/auth/AccountTask.h1
-rw-r--r--launcher/minecraft/auth/MinecraftAccount.cpp3
-rw-r--r--launcher/minecraft/auth/steps/MSAStep.cpp8
-rw-r--r--launcher/minecraft/auth/steps/MSAStep.h1
-rw-r--r--launcher/minecraft/legacy/LegacyInstance.cpp256
-rw-r--r--launcher/minecraft/legacy/LegacyInstance.h142
-rw-r--r--launcher/minecraft/legacy/LegacyModList.cpp136
-rw-r--r--launcher/minecraft/legacy/LegacyModList.h47
-rw-r--r--launcher/minecraft/legacy/LegacyUpgradeTask.cpp138
-rw-r--r--launcher/minecraft/legacy/LegacyUpgradeTask.h29
-rw-r--r--launcher/modplatform/atlauncher/ATLPackInstallTask.cpp2
-rw-r--r--launcher/modplatform/legacy_ftb/PackInstallTask.cpp2
-rw-r--r--launcher/modplatform/modpacksch/FTBPackInstallTask.cpp2
-rw-r--r--launcher/modplatform/technic/TechnicPackProcessor.cpp2
-rw-r--r--launcher/ui/MainWindow.cpp2
-rw-r--r--launcher/ui/pages/instance/LegacyUpgradePage.cpp51
-rw-r--r--launcher/ui/pages/instance/LegacyUpgradePage.h64
-rw-r--r--launcher/ui/pages/instance/LegacyUpgradePage.ui54
-rw-r--r--packages/nix/polymc/default.nix13
44 files changed, 506 insertions, 1351 deletions
diff --git a/.github/ISSUE_TEMPLATE/rfc.yml b/.github/ISSUE_TEMPLATE/rfc.yml
new file mode 100644
index 00000000..664430fe
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/rfc.yml
@@ -0,0 +1,69 @@
+# Template based on https://gitlab.archlinux.org/archlinux/rfcs/-/blob/0ba3b61e987e197f8d1901709409b8564958f78a/rfcs/0000-template.rst
+name: Request for Comment (RFC)
+description: Propose a larger change and start a discussion.
+labels: [RFC]
+body:
+- type: markdown
+ attributes:
+ value: |
+ ### Use this form to suggest a larger change for PolyMC.
+- type: textarea
+ attributes:
+ label: Goal
+ description: Short description, 1-2 sentences.
+ placeholder: Remove the cat from the launcher.
+ validations:
+ required: true
+- type: textarea
+ attributes:
+ label: Motivation
+ description: |
+ Introduce the topic. If this is a not-well-known section of PolyMC, a detailed explanation of the background is recommended.
+ Some example points of discussion:
+ - What specific problems are you facing right now that you're trying to address?
+ - Are there any previous discussions? Link to them and summarize them (don't
+ - force your readers to read them though!).
+ - Is there any precedent set by other software? If so, link to resources.
+ placeholder: I don't like cats. I think many users also don't like cats.
+ validations:
+ required: true
+- type: textarea
+ attributes:
+ label: Specification
+ description: A concrete, thorough explanation of what is being planned.
+ placeholder: Remove the cat button and all references to the cat from the codebase. Including resource files.
+ validations:
+ required: true
+- type: textarea
+ attributes:
+ label: Drawbacks
+ description: Carefully consider every possible objection and issue with your proposal. This section should be updated as feedback comes in from discussion.
+ placeholder: Some users might like cats.
+ validations:
+ required: true
+- type: textarea
+ attributes:
+ label: Unresolved Questions
+ description: |
+ Are there any portions of your proposal which need to be discussed with the community before the RFC can proceed?
+ Be careful here -- an RFC with a lot of remaining questions is likely to be stalled.
+ If your RFC is mostly unresolved questions and not too much substance, it may not be ready.
+ placeholder: Do a lot of users care about the cat?
+ validations:
+ required: true
+- type: textarea
+ attributes:
+ label: Alternatives Considered
+ description: A list of alternatives, that have been considered and offer equal or similar features to the proposed change.
+ placeholder: Maybe the cat could be replaced with an axolotl?
+ validations:
+ required: true
+- type: checkboxes
+ attributes:
+ label: This suggestion is unique
+ options:
+ - label: I have searched the issue tracker and did not find an issue describing my suggestion, especially not one that has been rejected.
+ required: true
+- type: textarea
+ attributes:
+ label: You may use the editor below to elaborate further.
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index d2ccc59e..793b081e 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -1,7 +1,12 @@
-name: build_portable
+name: Build
on:
- [push, pull_request, workflow_dispatch]
+ workflow_call:
+ inputs:
+ build_type:
+ description: Type of build (Debug, Release, RelWithDebInfo, MinSizeRel)
+ type: string
+ default: Debug
jobs:
build:
@@ -11,8 +16,13 @@ jobs:
include:
- os: ubuntu-20.04
+ qt_version: 5.12.8
+ qt_host: linux
+
+ - os: ubuntu-20.04
qt_version: 5.15.2
qt_host: linux
+ app_image: true
- os: windows-2022
qt_version: 5.15.2
@@ -59,6 +69,12 @@ jobs:
copy "${{ github.workspace }}\Qt\Tools\OpenSSL\Win_x86\bin\libssl-1_1.dll" "${{ github.workspace }}\${{ env.INSTALL_DIR }}\"
copy "${{ github.workspace }}\Qt\Tools\OpenSSL\Win_x86\bin\libcrypto-1_1.dll" "${{ github.workspace }}\${{ env.INSTALL_DIR }}\"
+ - name: Set short version
+ shell: bash
+ run: |
+ ver_short=`git rev-parse --short HEAD`
+ echo "VERSION=$ver_short" >> $GITHUB_ENV
+
- name: Install OpenJDK
uses: AdoptOpenJDK/install-jdk@v1
with:
@@ -72,6 +88,7 @@ jobs:
key: ${{ runner.os }}-${{ matrix.qt_version }}-${{ matrix.qt_arch }}-qt_cache
- name: Install Qt
+ if: runner.os != 'Linux' || matrix.app_image == true
uses: jurplel/install-qt-action@v2
with:
version: ${{ matrix.qt_version }}
@@ -80,18 +97,23 @@ jobs:
cached: ${{ steps.cache-qt.outputs.cache-hit }}
dir: "${{ github.workspace }}/Qt/"
+ - name: Install System Qt on Linux
+ if: runner.os == 'Linux' && matrix.app_image != true
+ run: |
+ sudo apt-get -y install qtbase5-dev qtchooser qt5-qmake qtbase5-dev-tools libqt5core5a libqt5network5 libqt5gui5
+
- name: Install Ninja
uses: urkle/action-get-ninja@v1
- - name: Download linuxdeploy family
- if: runner.os == 'Linux'
+ - name: Download linuxdeploy family for AppImage on Linux
+ if: matrix.app_image == true
run: |
wget "https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-x86_64.AppImage"
wget "https://github.com/linuxdeploy/linuxdeploy-plugin-appimage/releases/download/continuous/linuxdeploy-plugin-appimage-x86_64.AppImage"
wget "https://github.com/linuxdeploy/linuxdeploy-plugin-qt/releases/download/continuous/linuxdeploy-plugin-qt-x86_64.AppImage"
- name: Download JREs for AppImage on Linux
- if: runner.os == 'Linux'
+ if: matrix.app_image == true
shell: bash
run: |
${{ github.workspace }}/.github/scripts/prepare_JREs.sh
@@ -99,12 +121,12 @@ jobs:
- name: Configure CMake
if: runner.os != 'Linux'
run: |
- cmake -S . -B ${{ env.BUILD_DIR }} -DCMAKE_INSTALL_PREFIX=${{ env.INSTALL_DIR }} -DCMAKE_BUILD_TYPE=Debug -G Ninja
+ cmake -S . -B ${{ env.BUILD_DIR }} -DCMAKE_INSTALL_PREFIX=${{ env.INSTALL_DIR }} -DCMAKE_BUILD_TYPE=${{ inputs.build_type }} -G Ninja
- name: Configure CMake on Linux
if: runner.os == 'Linux'
run: |
- cmake -S . -B ${{ env.BUILD_DIR }} -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_BUILD_TYPE=Debug -DLauncher_LAYOUT=lin-system -G Ninja
+ cmake -S . -B ${{ env.BUILD_DIR }} -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_BUILD_TYPE=${{ inputs.build_type }} -DLauncher_LAYOUT=lin-system -G Ninja
- name: Build
run: |
@@ -115,16 +137,16 @@ jobs:
run: |
cmake --install ${{ env.BUILD_DIR }}
- - name: Install for AppImage on Linux
+ - name: Install on Linux
if: runner.os == 'Linux'
run: |
DESTDIR=${{ env.INSTALL_DIR }} cmake --install ${{ env.BUILD_DIR }}
- name: Bundle AppImage
- if: runner.os == 'Linux'
+ if: matrix.app_image == true
shell: bash
run: |
- export OUTPUT="PolyMC-${{ github.sha }}-x86_64.AppImage"
+ export OUTPUT="PolyMC-${{ runner.os }}-${{ env.VERSION }}-${{ inputs.build_type }}-x86_64.AppImage"
chmod +x linuxdeploy-*.AppImage
@@ -145,13 +167,13 @@ jobs:
- name: Run windeployqt
if: runner.os == 'Windows'
run: |
- windeployqt --no-translations "${{ env.INSTALL_DIR }}/polymc.exe"
+ windeployqt --no-translations --no-system-d3d-compiler --no-opengl-sw "${{ env.INSTALL_DIR }}/polymc.exe"
- name: Run macdeployqt
if: runner.os == 'macOS'
run: |
cd ${{ env.INSTALL_DIR }}
- macdeployqt "PolyMC.app" -executable="PolyMC.app/Contents/MacOS/polymc" -always-overwrite -use-debug-libs
+ macdeployqt "PolyMC.app" -executable="PolyMC.app/Contents/MacOS/polymc" -always-overwrite
- name: chmod binary on macOS
if: runner.os == 'macOS'
@@ -162,25 +184,38 @@ jobs:
if: runner.os == 'macOS'
run: |
cd ${{ env.INSTALL_DIR }}
- tar -czf ../polymc.tar.gz *
+ tar -czf ../PolyMC.tar.gz *
+
+ - name: tar on Linux
+ if: runner.os == 'Linux' && matrix.app_image != true
+ run: |
+ cd ${{ env.INSTALL_DIR }}
+ tar -czf ../PolyMC.tar.gz *
+
+ - name: Upload Linux tar.gz
+ if: runner.os == 'Linux' && matrix.app_image != true
+ uses: actions/upload-artifact@v2
+ with:
+ name: PolyMC-${{ runner.os }}-${{ env.VERSION }}-${{ inputs.build_type }}
+ path: PolyMC.tar.gz
- name: Upload AppImage for Linux
- if: runner.os == 'Linux'
+ if: matrix.app_image == true
uses: actions/upload-artifact@v2
with:
- name: PolyMC-${{ github.sha }}-x86_64.AppImage
- path: PolyMC-${{ github.sha }}-x86_64.AppImage
+ name: PolyMC-${{ runner.os }}-${{ env.VERSION }}-${{ inputs.build_type }}-x86_64.AppImage
+ path: PolyMC-${{ runner.os }}-${{ env.VERSION }}-${{ inputs.build_type }}-x86_64.AppImage
- name: Upload package for Windows
if: runner.os == 'Windows'
uses: actions/upload-artifact@v2
with:
- name: polymc-${{ runner.os }}-${{ github.sha }}-portable
+ name: PolyMC-${{ runner.os }}-${{ env.VERSION }}-${{ inputs.build_type }}
path: ${{ env.INSTALL_DIR }}/**
- name: Upload package for macOS
if: runner.os == 'macOS'
uses: actions/upload-artifact@v2
with:
- name: polymc-${{ runner.os }}-${{ github.sha }}-portable
- path: polymc.tar.gz
+ name: PolyMC-${{ runner.os }}-${{ env.VERSION }}-${{ inputs.build_type }}
+ path: PolyMC.tar.gz
diff --git a/.github/workflows/trigger_builds.yml b/.github/workflows/trigger_builds.yml
new file mode 100644
index 00000000..1dfc728e
--- /dev/null
+++ b/.github/workflows/trigger_builds.yml
@@ -0,0 +1,22 @@
+name: Build Application
+
+on:
+ push:
+ branches-ignore:
+ - 'stable'
+ pull_request:
+ workflow_dispatch:
+
+jobs:
+
+ build_debug:
+ name: Build Debug
+ uses: ./.github/workflows/build.yml
+ with:
+ build_type: Debug
+
+ build_release:
+ name: Build Release
+ uses: ./.github/workflows/build.yml
+ with:
+ build_type: Release
diff --git a/.github/workflows/trigger_release.yml b/.github/workflows/trigger_release.yml
new file mode 100644
index 00000000..b487e731
--- /dev/null
+++ b/.github/workflows/trigger_release.yml
@@ -0,0 +1,99 @@
+name: Build Application and Make Release
+
+on:
+ push:
+ tags:
+ - '*'
+
+jobs:
+
+ build_release:
+ name: Build Release
+ uses: ./.github/workflows/build.yml
+ with:
+ build_type: Release
+
+ create_release:
+ needs: build_release
+ runs-on: ubuntu-latest
+ outputs:
+ upload_url: ${{ steps.create_release.outputs.upload_url }}
+ steps:
+ - name: Grab and store version
+ run: |
+ tag_name=$(echo ${{ github.ref }} | grep -oE "[^/]+$")
+ echo "VERSION=$tag_name" >> $GITHUB_ENV
+ - name: Create release
+ id: create_release
+ uses: softprops/action-gh-release@v1
+ env:
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ with:
+ tag_name: ${{ github.ref }}
+ name: PolyMC ${{ env.VERSION }}
+ draft: true
+ prerelease: false
+
+ upload_release:
+ needs: create_release
+ runs-on: ubuntu-latest
+ steps:
+
+ - name: Download artifacts
+ uses: actions/download-artifact@v2
+
+ - name: Grab and store version
+ run: |
+ tag_name=$(echo ${{ github.ref }} | grep -oE "[^/]+$")
+ echo "VERSION=$tag_name" >> $GITHUB_ENV
+
+ - name: Package artifacts properly
+ run: |
+ mv PolyMC-Linux*/PolyMC.tar.gz PolyMC-Linux-${{ env.VERSION }}.tar.gz
+ mv PolyMC-*.AppImage/PolyMC-*.AppImage PolyMC-Linux-${{ env.VERSION }}-x86_64.AppImage
+ mv PolyMC-Windows* PolyMC-Windows-${{ env.VERSION }}
+ mv PolyMC-macOS*/PolyMC.tar.gz PolyMC-macOS-${{ env.VERSION }}.tar.gz
+
+ cd PolyMC-Windows-${{ env.VERSION }}
+ zip -r -9 ../PolyMC-Windows-${{ env.VERSION }}.zip *
+ cd ..
+
+ - name: Upload Linux asset
+ uses: actions/upload-release-asset@v1
+ env:
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ with:
+ upload_url: ${{ needs.create_release.outputs.upload_url }}
+ asset_name: PolyMC-Linux-${{ env.VERSION }}.tar.gz
+ asset_path: PolyMC-Linux-${{ env.VERSION }}.tar.gz
+ asset_content_type: application/gzip
+
+ - name: Upload Linux AppImage asset
+ uses: actions/upload-release-asset@v1
+ env:
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ with:
+ upload_url: ${{ needs.create_release.outputs.upload_url }}
+ asset_name: PolyMC-Linux-${{ env.VERSION }}-x86_64.AppImage
+ asset_path: PolyMC-Linux-${{ env.VERSION }}-x86_64.AppImage
+ asset_content_type: application/x-executable
+
+ - name: Upload Windows asset
+ uses: actions/upload-release-asset@v1
+ env:
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ with:
+ upload_url: ${{ needs.create_release.outputs.upload_url }}
+ asset_name: PolyMC-Windows-${{ env.VERSION }}.zip
+ asset_path: PolyMC-Windows-${{ env.VERSION }}.zip
+ asset_content_type: application/zip
+
+ - name: Upload macOS asset
+ uses: actions/upload-release-asset@v1
+ env:
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ with:
+ upload_url: ${{ needs.create_release.outputs.upload_url }}
+ asset_name: PolyMC-macOS-${{ env.VERSION }}.tar.gz
+ asset_path: PolyMC-macOS-${{ env.VERSION }}.tar.gz
+ asset_content_type: application/gzip
diff --git a/CMakeLists.txt b/CMakeLists.txt
index d4a27260..003aa65d 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -73,7 +73,7 @@ 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")
# MSA Client ID
-set(Launcher_MSA_CLIENT_ID "17b47edd-c884-4997-926d-9e7f9a6b4647" CACHE STRING "Client ID you can get from Microsoft Identity Platform when you register an application")
+set(Launcher_MSA_CLIENT_ID "549033b2-1532-4d4e-ae77-1bbaa46f9d74" CACHE STRING "Client ID you can get from Microsoft Identity Platform when you register an application")
# Bug tracker URL
set(Launcher_BUG_TRACKER_URL "https://github.com/PolyMC/PolyMC/issues" CACHE STRING "URL for the bug tracker.")
diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md
new file mode 100644
index 00000000..52a9f30a
--- /dev/null
+++ b/CODE_OF_CONDUCT.md
@@ -0,0 +1,136 @@
+# Contributor Covenant Code of Conduct
+This is a modified version of the Contributor Covenant.
+See commit history to see our changes.
+
+## Our Pledge
+
+We as members, contributors, and leaders pledge to make participation in our
+community a harassment-free experience for everyone, regardless of age, body
+size, visible or invisible disability, ethnicity, sex characteristics, gender
+identity and expression, level of experience, education, socio-economic status,
+nationality, personal appearance, race, caste, color, religion, or sexual
+identity and orientation.
+
+We pledge to act and interact in ways that contribute to an open, welcoming,
+diverse, inclusive, and healthy community.
+
+## Our Standards
+
+Examples of behavior that contributes to a positive environment for our
+community include:
+
+* Demonstrating empathy and kindness toward other people
+* Being respectful of differing opinions, viewpoints, and experiences
+* Giving and gracefully accepting constructive feedback
+* Accepting responsibility and apologizing to those affected by our mistakes,
+ and learning from the experience
+* Focusing on what is best not just for us as individuals, but for the overall
+ community
+
+Examples of unacceptable behavior include:
+
+* The use of sexualized language or imagery, and sexual attention or advances of
+ any kind
+* Trolling (antagonistic, inflammatory, insincere behaviour), insulting or derogatory comments, and personal or political attacks
+* Public or private harassment
+* Publishing others' private information, such as a physical or email address,
+ without their explicit permission
+* Other conduct which could reasonably be considered inappropriate in a
+ professional setting
+
+## Enforcement Responsibilities
+
+Community leaders are responsible for clarifying and enforcing our standards of
+acceptable behavior and will take appropriate and fair corrective action in
+response to any behavior that they deem inappropriate, threatening, offensive,
+or harmful.
+
+Community leaders have the right and responsibility to remove, edit, or reject
+comments, commits, code, wiki edits, issues, and other contributions that are
+not aligned to this Code of Conduct, and will communicate reasons for moderation
+decisions when appropriate.
+
+## Scope
+
+This Code of Conduct applies within all community spaces, and also applies when
+an individual is officially representing the community in public spaces.
+Examples of representing our community include using an official e-mail address,
+posting via an official social media account, or acting as an appointed
+representative at an online or offline event.
+
+## Enforcement
+
+Instances of abusive, harassing, or otherwise unacceptable behavior may be
+reported to the community leaders responsible for enforcement via email at
+[polymc-enforcement@scrumplex.net](mailto:polymc-enforcement@scrumplex.net) (Email
+address subject to change).
+All complaints will be reviewed and investigated promptly and fairly.
+
+All community leaders are obligated to respect the privacy and security of the
+reporter of any incident.
+
+## Enforcement Guidelines
+
+Community leaders will follow these Community Impact Guidelines in determining
+the consequences for any action they deem in violation of this Code of Conduct:
+
+### 1. Correction
+
+**Community Impact**: Use of inappropriate language or other behavior deemed
+unprofessional or unwelcome in the community.
+
+**Consequence**: A private, written warning from community leaders, providing
+clarity around the nature of the violation and an explanation of why the
+behavior was inappropriate. A public apology may be requested.
+
+### 2. Warning
+
+**Community Impact**: A violation through a single incident or series of
+actions.
+
+**Consequence**: A warning with consequences for continued behavior. No
+interaction with the people involved, including unsolicited interaction with
+those enforcing the Code of Conduct, for a specified period of time. This
+includes avoiding interactions in community spaces as well as external channels
+like social media. Violating these terms may lead to a temporary or permanent
+ban.
+
+### 3. Temporary Ban
+
+**Community Impact**: A serious violation of community standards, including
+sustained inappropriate behavior.
+
+**Consequence**: A temporary ban from any sort of interaction or public
+communication with the community for a specified period of time. No public or
+private interaction with the people involved, including unsolicited interaction
+with those enforcing the Code of Conduct, is allowed during this period.
+Violating these terms may lead to a permanent ban.
+
+### 4. Permanent Ban
+
+**Community Impact**: Demonstrating a pattern of violation of community
+standards, including sustained inappropriate behavior, harassment of an
+individual, or aggression toward or disparagement of classes of individuals.
+
+**Consequence**: A permanent ban from any sort of public interaction within the
+community.
+
+## Attribution
+
+This Code of Conduct is adapted from the [Contributor Covenant][homepage],
+version 2.1, available at
+[https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1].
+
+Community Impact Guidelines were inspired by
+[Mozilla's code of conduct enforcement ladder][Mozilla CoC].
+
+For answers to common questions about this code of conduct, see the FAQ at
+[https://www.contributor-covenant.org/faq][FAQ]. Translations are available at
+[https://www.contributor-covenant.org/translations][translations].
+
+[homepage]: https://www.contributor-covenant.org
+[v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html
+[Mozilla CoC]: https://github.com/mozilla/diversity
+[FAQ]: https://www.contributor-covenant.org/faq
+[translations]: https://www.contributor-covenant.org/translations
+
diff --git a/README.md b/README.md
index b7df751c..50bd88b9 100644
--- a/README.md
+++ b/README.md
@@ -10,7 +10,8 @@ This is a **fork** of the MultiMC Launcher and not endorsed by MultiMC. The Poly
<br>
# Installation
-- All packages (archived by version) can be found [here](https://packages.polymc.org/) ([latest](https://packages.polymc.org/latest)).
+
+- All packages (archived by version) can be found [here](https://packages.polymc.org/) ([latest](https://packages.polymc.org/latest))
- Last build status: https://jenkins.polymc.org/job/PolyMC/lastBuild/
## 🐧 Linux
@@ -29,33 +30,27 @@ There are several AUR packages available:
[![polymc](https://img.shields.io/badge/aur-polymc-blue)](https://aur.archlinux.org/packages/polymc/)
[![polymc-bin](https://img.shields.io/badge/aur-polymc--bin-blue)](https://aur.archlinux.org/packages/polymc-bin/)
-[![polymc-git](https://img.shields.io/badge/aur-polymc--git-blue)](https://aur.archlinux.org/packages/polymc-git/)
```sh
-# stable source package:
+# source package:
yay -S polymc
-# stable binary package:
+# binary package:
yay -S polymc-bin
-# latest git package:
-yay -S polymc-git
```
-### <img src="https://www.vectorlogo.zone/logos/debian/debian-icon.svg" height="20" /> Debian
+### <img src="https://www.vectorlogo.zone/logos/debian/debian-icon.svg" height="20" /> Debian and <img src="https://www.vectorlogo.zone/logos/ubuntu/ubuntu-icon.svg" height="20" /> Ubuntu
We use [makedeb](https://docs.makedeb.org/) for our Debian packages.
Several MPR packages are available:
[![polymc](https://img.shields.io/badge/mpr-polymc-orange)](https://mpr.makedeb.org/packages/polymc)
[![polymc-bin](https://img.shields.io/badge/mpr-polymc--bin-orange)](https://mpr.makedeb.org/packages/polymc-bin)
-[![polymc-git](https://img.shields.io/badge/mpr-polymc--git-orange)](https://mpr.makedeb.org/packages/polymc-git)
```sh
-# stable source package:
+# source package:
sudo tap install polymc
-# stable binary package:
+# binary package:
sudo tap install polymc-bin
-# latest git package:
-sudo tap install polymc-git
```
### <img src="https://www.vectorlogo.zone/logos/nixos/nixos-icon.svg" height="20" /> Nix
@@ -85,13 +80,6 @@ sudo dnf copr enable polymc/polymc
sudo dnf install polymc
```
-Alternatively, a COPR maintained by a PolyMC user (instead of Jenkins' automated builds) is available [here](https://copr.fedorainfracloud.org/coprs/sentry/polymc).
-
-```sh
-sudo dnf copr enable sentry/polymc
-sudo dnf install polymc
-```
-
### <img src="https://lotar.altervista.org/wiki/_media/news/slackware-logo.png" height="20" /> Slackware
[A SlackBuild](https://codeberg.org/glowiak/SlackBuilds/src/branch/master/repository/polymc.md) is available. You will need [qt5](http://slackbuilds.org/repository/14.2/libraries/qt5/) (on 15.0 installed by default), [a JDK](https://codeberg.org/glowiak/SlackBuilds/src/branch/master/repository/adoptium-jdk8.md), and if you're on 14.2, you need to compile newer CMake version manually. To build, type in extracted directory with all dependiences met:
@@ -99,7 +87,7 @@ sudo dnf install polymc
sudo ./polymc.SlackBuild
sudo installpkg /tmp/polymc-version-arch-1_SBo.tgz
-If you are too lazy to do all these steps, you can just download [a prebuild x86_64 package](http://glowiak.github.io/file/polymc-latest-slackware) and install it with /sbin/installpkg:
+You can also download a community-maintained [prebuilt x86_64 package](http://glowiak.github.io/file/polymc-latest-slackware) and install it with /sbin/installpkg:
sudo /sbin/installpkg ~/Downloads/polymc-version-x86_64-1_SBo.tgz
@@ -109,28 +97,37 @@ If you are too lazy to do all these steps, you can just download [a prebuild x86
## <img src="https://www.vectorlogo.zone/logos/apple/apple-tile.svg" height="20" /> MacOS
-MacOS currently does not have any packages. We are still working on setting up MacOS packaging. Meanwhile, you can [build](https://github.com/PolyMC/PolyMC/blob/develop/BUILD.md#macos) it for yourself.
+MacOS has experimental development builds available [here](https://github.com/PolyMC/PolyMC/actions)
## <img src="https://www.vectorlogo.zone/logos/freebsd/freebsd-icon.svg" height="20" /> FreeBSD
-For FreeBSD available are:
+There are community-maintained binary packages available:
- [AppBSD Image](http://glowiak.github.io/file/polymc-latest-fbsd64-appbsd) - a portable application, requires [AppBSD](https://codeberg.org/glowiak/appbsd/) to be installed.
- [Gzipped binaries](http://glowiak.github.io/file/polymc-latest-fbsd64-raw) - traditional way to distribute, unpack and run.
-In both cases you need X11, Qt5 and Java installed. Both files are 64bit only.
+In both cases you need X11, Qt5 and Java installed. Both files are 64bit only.
+You can build from source - see [BUILD.md](./BUILD.md)
## <img src="https://raw.githubusercontent.com/AliasIO/wappalyzer/master/src/drivers/webextension/images/icons/OpenBSD%20httpd.svg" height="20" /> OpenBSD
-For OpenBSD available are [gzipped 32-bit binaries](http://glowiak.github.io/file/polymc-latest-obsd32-raw), download, unpack and run.
+There are community-maintained binary packages available:
+
+- [gzipped 32-bit binaries](http://glowiak.github.io/file/polymc-latest-obsd32-raw), download, unpack and run.
-You need X11, Qt5 and Java installed.
+You need X11, Qt5 and Java installed.
+You can build from source - see [BUILD.md](./BUILD.md)
## 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.
-Builds are provided for Linux, AppImage on Linux, Windows, and macOS.
+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
@@ -158,6 +155,7 @@ If you want to contribute to PolyMC you might find it useful to join our Discord
If you want to build PolyMC yourself, check [BUILD.md](BUILD.md) for build instructions.
## Code formatting
+
Just follow the existing formatting.
In general, in order of importance:
diff --git a/flake.nix b/flake.nix
index d809066a..5f95b4e6 100644
--- a/flake.nix
+++ b/flake.nix
@@ -16,11 +16,19 @@
};
outputs = args@{ self, nixpkgs, flake-utils, libnbtplusplus, quazip, ... }:
- {
+ let
+ systems = [
+ "aarch64-linux"
+ # "aarch64-darwin" # qtbase is currently broken
+ "i686-linux"
+ "x86_64-darwin"
+ "x86_64-linux"
+ ];
+ in {
overlay = final: prev: {
inherit (self.packages.${final.system}) polymc;
};
- } // flake-utils.lib.eachDefaultSystem (system:
+ } // flake-utils.lib.eachSystem systems (system:
let pkgs = import nixpkgs { inherit system; };
in {
packages = {
diff --git a/launcher/Application.cpp b/launcher/Application.cpp
index a3d6216e..e33df252 100644
--- a/launcher/Application.cpp
+++ b/launcher/Application.cpp
@@ -192,27 +192,6 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv)
#endif
startTime = QDateTime::currentDateTime();
-#ifdef Q_OS_LINUX
- {
- QFile osrelease("/proc/sys/kernel/osrelease");
- if (osrelease.open(QFile::ReadOnly | QFile::Text)) {
- QTextStream in(&osrelease);
- auto contents = in.readAll();
- if(
- contents.contains("WSL", Qt::CaseInsensitive) ||
- contents.contains("Microsoft", Qt::CaseInsensitive)
- ) {
- showFatalErrorMessage(
- "Unsupported system detected!",
- "Linux-on-Windows distributions are not supported.\n\n"
- "Please use the Windows binary when playing on Windows."
- );
- return;
- }
- }
- }
-#endif
-
// Don't quit on hiding the last window
this->setQuitOnLastWindowClosed(false);
@@ -285,12 +264,21 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv)
return;
}
}
+
m_instanceIdToLaunch = args["launch"].toString();
m_serverToJoin = args["server"].toString();
m_profileToUse = args["profile"].toString();
m_liveCheck = args["alive"].toBool();
m_zipToImport = args["import"].toUrl();
+ // error if --launch is missing with --server or --profile
+ if((!m_serverToJoin.isEmpty() || !m_profileToUse.isEmpty()) && m_instanceIdToLaunch.isEmpty())
+ {
+ std::cerr << "--server and --profile can only be used in combination with --launch!" << std::endl;
+ m_status = Application::Failed;
+ return;
+ }
+
QString origcwdPath = QDir::currentPath();
QString binPath = applicationDirPath();
QString adjustedBy;
@@ -359,20 +347,6 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv)
return;
}
- if(m_instanceIdToLaunch.isEmpty() && !m_serverToJoin.isEmpty())
- {
- std::cerr << "--server can only be used in combination with --launch!" << std::endl;
- m_status = Application::Failed;
- return;
- }
-
- if(m_instanceIdToLaunch.isEmpty() && !m_profileToUse.isEmpty())
- {
- std::cerr << "--account can only be used in combination with --launch!" << std::endl;
- m_status = Application::Failed;
- return;
- }
-
#if defined(Q_OS_MAC)
// move user data to new location if on macOS and it still exists in Contents/MacOS
QDir fi(applicationDirPath());
@@ -566,26 +540,23 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv)
qDebug() << "<> Paths set.";
}
- do // once
+ if(m_liveCheck)
{
- if(m_liveCheck)
+ QFile check(liveCheckFile);
+ if(check.open(QIODevice::WriteOnly | QIODevice::Truncate))
{
- QFile check(liveCheckFile);
- if(!check.open(QIODevice::WriteOnly | QIODevice::Truncate))
- {
- qWarning() << "Could not open" << liveCheckFile << "for writing!";
- break;
- }
auto payload = appID.toString().toUtf8();
- if(check.write(payload) != payload.size())
+ if(check.write(payload) == payload.size())
{
+ check.close();
+ } else {
qWarning() << "Could not write into" << liveCheckFile << "!";
- check.remove();
- break;
+ check.remove(); // also closes file!
}
- check.close();
+ } else {
+ qWarning() << "Could not open" << liveCheckFile << "for writing!";
}
- } while(false);
+ }
// Initialize application settings
{
diff --git a/launcher/BaseInstance.cpp b/launcher/BaseInstance.cpp
index 374d4a29..1bff9e1d 100644
--- a/launcher/BaseInstance.cpp
+++ b/launcher/BaseInstance.cpp
@@ -39,6 +39,7 @@ BaseInstance::BaseInstance(SettingsObjectPtr globalSettings, SettingsObjectPtr s
m_settings->registerSetting("lastLaunchTime", 0);
m_settings->registerSetting("totalTimePlayed", 0);
m_settings->registerSetting("lastTimePlayed", 0);
+ m_settings->registerSetting("InstanceType", "OneSix");
// Custom Commands
auto commandSetting = m_settings->registerSetting({"OverrideCommands","OverrideLaunchCmd"}, false);
diff --git a/launcher/CMakeLists.txt b/launcher/CMakeLists.txt
index 90149c3b..86c05651 100644
--- a/launcher/CMakeLists.txt
+++ b/launcher/CMakeLists.txt
@@ -286,13 +286,6 @@ set(MINECRAFT_SOURCES
minecraft/launch/VerifyJavaInstall.cpp
minecraft/launch/VerifyJavaInstall.h
- minecraft/legacy/LegacyModList.h
- minecraft/legacy/LegacyModList.cpp
- minecraft/legacy/LegacyInstance.h
- minecraft/legacy/LegacyInstance.cpp
- minecraft/legacy/LegacyUpgradeTask.h
- minecraft/legacy/LegacyUpgradeTask.cpp
-
minecraft/GradleSpecifier.h
minecraft/MinecraftInstance.cpp
minecraft/MinecraftInstance.h
@@ -701,8 +694,6 @@ SET(LAUNCHER_SOURCES
ui/pages/instance/OtherLogsPage.h
ui/pages/instance/ServersPage.cpp
ui/pages/instance/ServersPage.h
- ui/pages/instance/LegacyUpgradePage.cpp
- ui/pages/instance/LegacyUpgradePage.h
ui/pages/instance/WorldListPage.cpp
ui/pages/instance/WorldListPage.h
@@ -884,7 +875,6 @@ qt5_wrap_ui(LAUNCHER_UI
ui/pages/instance/InstanceSettingsPage.ui
ui/pages/instance/VersionPage.ui
ui/pages/instance/WorldListPage.ui
- ui/pages/instance/LegacyUpgradePage.ui
ui/pages/instance/ScreenshotsPage.ui
ui/pages/modplatform/atlauncher/AtlOptionalModDialog.ui
ui/pages/modplatform/atlauncher/AtlPage.ui
diff --git a/launcher/InstanceCopyTask.cpp b/launcher/InstanceCopyTask.cpp
index 35adeaf9..c2bfe839 100644
--- a/launcher/InstanceCopyTask.cpp
+++ b/launcher/InstanceCopyTask.cpp
@@ -42,7 +42,6 @@ void InstanceCopyTask::copyFinished()
}
// FIXME: shouldn't this be able to report errors?
auto instanceSettings = std::make_shared<INISettingsObject>(FS::PathCombine(m_stagingPath, "instance.cfg"));
- instanceSettings->registerSetting("InstanceType", "Legacy");
InstancePtr inst(new NullInstance(m_globalSettings, instanceSettings, m_stagingPath));
inst->setName(m_instName);
diff --git a/launcher/InstanceCreationTask.cpp b/launcher/InstanceCreationTask.cpp
index eafc5126..4c37bd7f 100644
--- a/launcher/InstanceCreationTask.cpp
+++ b/launcher/InstanceCreationTask.cpp
@@ -17,8 +17,6 @@ void InstanceCreationTask::executeTask()
{
auto instanceSettings = std::make_shared<INISettingsObject>(FS::PathCombine(m_stagingPath, "instance.cfg"));
instanceSettings->suspendSave();
- instanceSettings->registerSetting("InstanceType", "Legacy");
- instanceSettings->set("InstanceType", "OneSix");
MinecraftInstance inst(m_globalSettings, instanceSettings, m_stagingPath);
auto components = inst.getPackProfile();
components->buildingFromScratch();
diff --git a/launcher/InstanceImportTask.cpp b/launcher/InstanceImportTask.cpp
index ec378538..6dd615c7 100644
--- a/launcher/InstanceImportTask.cpp
+++ b/launcher/InstanceImportTask.cpp
@@ -261,8 +261,6 @@ void InstanceImportTask::processFlame()
QString configPath = FS::PathCombine(m_stagingPath, "instance.cfg");
auto instanceSettings = std::make_shared<INISettingsObject>(configPath);
- instanceSettings->registerSetting("InstanceType", "Legacy");
- instanceSettings->set("InstanceType", "OneSix");
MinecraftInstance instance(m_globalSettings, instanceSettings, m_stagingPath);
auto mcVersion = pack.minecraft.version;
// Hack to correct some 'special sauce'...
@@ -422,7 +420,6 @@ void InstanceImportTask::processMultiMC()
{
QString configPath = FS::PathCombine(m_stagingPath, "instance.cfg");
auto instanceSettings = std::make_shared<INISettingsObject>(configPath);
- instanceSettings->registerSetting("InstanceType", "Legacy");
NullInstance instance(m_globalSettings, instanceSettings, m_stagingPath);
diff --git a/launcher/InstanceList.cpp b/launcher/InstanceList.cpp
index ad18740b..04b86f6b 100644
--- a/launcher/InstanceList.cpp
+++ b/launcher/InstanceList.cpp
@@ -32,7 +32,6 @@
#include "BaseInstance.h"
#include "InstanceTask.h"
#include "settings/INISettingsObject.h"
-#include "minecraft/legacy/LegacyInstance.h"
#include "NullInstance.h"
#include "minecraft/MinecraftInstance.h"
#include "FileSystem.h"
@@ -545,7 +544,7 @@ InstancePtr InstanceList::loadInstance(const InstanceId& id)
auto instanceSettings = std::make_shared<INISettingsObject>(FS::PathCombine(instanceRoot, "instance.cfg"));
InstancePtr inst;
- instanceSettings->registerSetting("InstanceType", "Legacy");
+ instanceSettings->registerSetting("InstanceType", "Legacy"); // intentionally Legacy. We don't support it.
QString inst_type = instanceSettings->get("InstanceType").toString();
@@ -553,10 +552,6 @@ InstancePtr InstanceList::loadInstance(const InstanceId& id)
{
inst.reset(new MinecraftInstance(m_globalSettings, instanceSettings, instanceRoot));
}
- else if (inst_type == "Legacy")
- {
- inst.reset(new LegacyInstance(m_globalSettings, instanceSettings, instanceRoot));
- }
else
{
inst.reset(new NullInstance(m_globalSettings, instanceSettings, instanceRoot));
diff --git a/launcher/InstancePageProvider.h b/launcher/InstancePageProvider.h
index 97eeab8c..357157d0 100644
--- a/launcher/InstancePageProvider.h
+++ b/launcher/InstancePageProvider.h
@@ -1,6 +1,5 @@
#pragma once
#include "minecraft/MinecraftInstance.h"
-#include "minecraft/legacy/LegacyInstance.h"
#include <FileSystem.h>
#include "ui/pages/BasePage.h"
#include "ui/pages/BasePageProvider.h"
@@ -14,7 +13,6 @@
#include "ui/pages/instance/ScreenshotsPage.h"
#include "ui/pages/instance/InstanceSettingsPage.h"
#include "ui/pages/instance/OtherLogsPage.h"
-#include "ui/pages/instance/LegacyUpgradePage.h"
#include "ui/pages/instance/WorldListPage.h"
#include "ui/pages/instance/ServersPage.h"
#include "ui/pages/instance/GameOptionsPage.h"
@@ -34,31 +32,20 @@ public:
QList<BasePage *> values;
values.append(new LogPage(inst));
std::shared_ptr<MinecraftInstance> onesix = std::dynamic_pointer_cast<MinecraftInstance>(inst);
- if(onesix)
- {
- values.append(new VersionPage(onesix.get()));
- auto modsPage = new ModFolderPage(onesix.get(), onesix->loaderModList(), "mods", "loadermods", tr("Mods"), "Loader-mods");
- modsPage->setFilter("%1 (*.zip *.jar *.litemod)");
- values.append(modsPage);
- values.append(new CoreModFolderPage(onesix.get(), onesix->coreModList(), "coremods", "coremods", tr("Core mods"), "Core-mods"));
- values.append(new ResourcePackPage(onesix.get()));
- values.append(new TexturePackPage(onesix.get()));
- values.append(new ShaderPackPage(onesix.get()));
- values.append(new NotesPage(onesix.get()));
- values.append(new WorldListPage(onesix.get(), onesix->worldList()));
- values.append(new ServersPage(onesix));
- // values.append(new GameOptionsPage(onesix.get()));
- values.append(new ScreenshotsPage(FS::PathCombine(onesix->gameRoot(), "screenshots")));
- values.append(new InstanceSettingsPage(onesix.get()));
- }
- std::shared_ptr<LegacyInstance> legacy = std::dynamic_pointer_cast<LegacyInstance>(inst);
- if(legacy)
- {
- values.append(new LegacyUpgradePage(legacy));
- values.append(new NotesPage(legacy.get()));
- values.append(new WorldListPage(legacy.get(), legacy->worldList()));
- values.append(new ScreenshotsPage(FS::PathCombine(legacy->gameRoot(), "screenshots")));
- }
+ values.append(new VersionPage(onesix.get()));
+ auto modsPage = new ModFolderPage(onesix.get(), onesix->loaderModList(), "mods", "loadermods", tr("Mods"), "Loader-mods");
+ modsPage->setFilter("%1 (*.zip *.jar *.litemod)");
+ values.append(modsPage);
+ values.append(new CoreModFolderPage(onesix.get(), onesix->coreModList(), "coremods", "coremods", tr("Core mods"), "Core-mods"));
+ values.append(new ResourcePackPage(onesix.get()));
+ values.append(new TexturePackPage(onesix.get()));
+ values.append(new ShaderPackPage(onesix.get()));
+ values.append(new NotesPage(onesix.get()));
+ values.append(new WorldListPage(onesix.get(), onesix->worldList()));
+ values.append(new ServersPage(onesix));
+ // values.append(new GameOptionsPage(onesix.get()));
+ values.append(new ScreenshotsPage(FS::PathCombine(onesix->gameRoot(), "screenshots")));
+ values.append(new InstanceSettingsPage(onesix.get()));
auto logMatcher = inst->getLogFileMatcher();
if(logMatcher)
{
diff --git a/launcher/LaunchController.cpp b/launcher/LaunchController.cpp
index 32fc99cb..40178b70 100644
--- a/launcher/LaunchController.cpp
+++ b/launcher/LaunchController.cpp
@@ -228,6 +228,18 @@ void LaunchController::login() {
emitFailed(errorString);
return;
}
+ case AccountState::Disabled: {
+ auto errorString = tr("The launcher's client identification has changed. Please remove this account and add it again.");
+ QMessageBox::warning(
+ m_parentWidget,
+ tr("Client identification changed"),
+ errorString,
+ QMessageBox::StandardButton::Ok,
+ QMessageBox::StandardButton::Ok
+ );
+ emitFailed(errorString);
+ return;
+ }
case AccountState::Gone: {
auto errorString = tr("The account no longer exists on the servers. It may have been migrated, in which case please add the new account you migrated this one to.");
QMessageBox::warning(
diff --git a/launcher/minecraft/MinecraftInstance.cpp b/launcher/minecraft/MinecraftInstance.cpp
index 7327f9d5..6db12c42 100644
--- a/launcher/minecraft/MinecraftInstance.cpp
+++ b/launcher/minecraft/MinecraftInstance.cpp
@@ -124,18 +124,7 @@ MinecraftInstance::MinecraftInstance(SettingsObjectPtr globalSettings, SettingsO
m_settings->registerSetting("JoinServerOnLaunch", false);
m_settings->registerSetting("JoinServerOnLaunchAddress", "");
- // DEPRECATED: Read what versions the user configuration thinks should be used
- m_settings->registerSetting({"IntendedVersion", "MinecraftVersion"}, "");
- m_settings->registerSetting("LWJGLVersion", "");
- m_settings->registerSetting("ForgeVersion", "");
- m_settings->registerSetting("LiteloaderVersion", "");
-
m_components.reset(new PackProfile(this));
- m_components->setOldConfigVersion("net.minecraft", m_settings->get("IntendedVersion").toString());
- auto setting = m_settings->getSetting("LWJGLVersion");
- m_components->setOldConfigVersion("org.lwjgl", m_settings->get("LWJGLVersion").toString());
- m_components->setOldConfigVersion("net.minecraftforge", m_settings->get("ForgeVersion").toString());
- m_components->setOldConfigVersion("com.mumfrey.liteloader", m_settings->get("LiteloaderVersion").toString());
}
void MinecraftInstance::saveNow()
diff --git a/launcher/minecraft/PackProfile.cpp b/launcher/minecraft/PackProfile.cpp
index 59a8f133..d516e555 100644
--- a/launcher/minecraft/PackProfile.cpp
+++ b/launcher/minecraft/PackProfile.cpp
@@ -272,18 +272,6 @@ void PackProfile::save_internal()
bool PackProfile::load()
{
auto filename = componentsFilePath();
- QFile componentsFile(filename);
-
- // migrate old config to new one, if needed
- if(!componentsFile.exists())
- {
- if(!migratePreComponentConfig())
- {
- // FIXME: the user should be notified...
- qCritical() << "Failed to convert old pre-component config for instance" << d->m_instance->name();
- return false;
- }
- }
// load the new component list and swap it with the current one...
ComponentContainer newComponents;
@@ -369,239 +357,6 @@ void PackProfile::updateFailed(const QString& error)
invalidateLaunchProfile();
}
-// NOTE this is really old stuff, and only needs to be used when loading the old hardcoded component-unaware format (loadPreComponentConfig).
-static void upgradeDeprecatedFiles(QString root, QString instanceName)
-{
- auto versionJsonPath = FS::PathCombine(root, "version.json");
- auto customJsonPath = FS::PathCombine(root, "custom.json");
- auto mcJson = FS::PathCombine(root, "patches" , "net.minecraft.json");
-
- QString sourceFile;
- QString renameFile;
-
- // convert old crap.
- if(QFile::exists(customJsonPath))
- {
- sourceFile = customJsonPath;
- renameFile = versionJsonPath;
- }
- else if(QFile::exists(versionJsonPath))
- {
- sourceFile = versionJsonPath;
- }
- if(!sourceFile.isEmpty() && !QFile::exists(mcJson))
- {
- if(!FS::ensureFilePathExists(mcJson))
- {
- qWarning() << "Couldn't create patches folder for" << instanceName;
- return;
- }
- if(!renameFile.isEmpty() && QFile::exists(renameFile))
- {
- if(!QFile::rename(renameFile, renameFile + ".old"))
- {
- qWarning() << "Couldn't rename" << renameFile << "to" << renameFile + ".old" << "in" << instanceName;
- return;
- }
- }
- auto file = ProfileUtils::parseJsonFile(QFileInfo(sourceFile), false);
- ProfileUtils::removeLwjglFromPatch(file);
- file->uid = "net.minecraft";
- file->version = file->minecraftVersion;
- file->name = "Minecraft";
-
- Meta::Require needsLwjgl;
- needsLwjgl.uid = "org.lwjgl";
- file->requires.insert(needsLwjgl);
-
- if(!ProfileUtils::saveJsonFile(OneSixVersionFormat::versionFileToJson(file), mcJson))
- {
- return;
- }
- if(!QFile::rename(sourceFile, sourceFile + ".old"))
- {
- qWarning() << "Couldn't rename" << sourceFile << "to" << sourceFile + ".old" << "in" << instanceName;
- return;
- }
- }
-}
-
-/*
- * Migrate old layout to the component based one...
- * - Part of the version information is taken from `instance.cfg` (fed to this class from outside).
- * - Part is taken from the old order.json file.
- * - Part is loaded from loose json files in the instance's `patches` directory.
- */
-bool PackProfile::migratePreComponentConfig()
-{
- // upgrade the very old files from the beginnings of MultiMC 5
- upgradeDeprecatedFiles(d->m_instance->instanceRoot(), d->m_instance->name());
-
- QList<ComponentPtr> components;
- QSet<QString> loaded;
-
- auto addBuiltinPatch = [&](const QString &uid, bool asDependency, const QString & emptyVersion, const Meta::Require & req, const Meta::Require & conflict)
- {
- auto jsonFilePath = FS::PathCombine(d->m_instance->instanceRoot(), "patches" , uid + ".json");
- auto intendedVersion = d->getOldConfigVersion(uid);
- // load up the base minecraft patch
- ComponentPtr component;
- if(QFile::exists(jsonFilePath))
- {
- if(intendedVersion.isEmpty())
- {
- intendedVersion = emptyVersion;
- }
- auto file = ProfileUtils::parseJsonFile(QFileInfo(jsonFilePath), false);
- // fix uid
- file->uid = uid;
- // if version is missing, add it from the outside.
- if(file->version.isEmpty())
- {
- file->version = intendedVersion;
- }
- // if this is a dependency (LWJGL), mark it also as volatile
- if(asDependency)
- {
- file->m_volatile = true;
- }
- // insert requirements if needed
- if(!req.uid.isEmpty())
- {
- file->requires.insert(req);
- }
- // insert conflicts if needed
- if(!conflict.uid.isEmpty())
- {
- file->conflicts.insert(conflict);
- }
- // FIXME: @QUALITY do not ignore return value
- ProfileUtils::saveJsonFile(OneSixVersionFormat::versionFileToJson(file), jsonFilePath);
- component = new Component(this, uid, file);
- component->m_version = intendedVersion;
- }
- else if(!intendedVersion.isEmpty())
- {
- auto metaVersion = APPLICATION->metadataIndex()->get(uid, intendedVersion);
- component = new Component(this, metaVersion);
- }
- else
- {
- return;
- }
- component->m_dependencyOnly = asDependency;
- component->m_important = !asDependency;
- components.append(component);
- };
- // TODO: insert depends and conflicts here if these are customized files...
- Meta::Require reqLwjgl;
- reqLwjgl.uid = "org.lwjgl";
- reqLwjgl.suggests = "2.9.1";
- Meta::Require conflictLwjgl3;
- conflictLwjgl3.uid = "org.lwjgl3";
- Meta::Require nullReq;
- addBuiltinPatch("org.lwjgl", true, "2.9.1", nullReq, conflictLwjgl3);
- addBuiltinPatch("net.minecraft", false, QString(), reqLwjgl, nullReq);
-
- // first, collect all other file-based patches and load them
- QMap<QString, ComponentPtr> loadedComponents;
- QDir patchesDir(FS::PathCombine(d->m_instance->instanceRoot(),"patches"));
- for (auto info : patchesDir.entryInfoList(QStringList() << "*.json", QDir::Files))
- {
- // parse the file
- qDebug() << "Reading" << info.fileName();
- auto file = ProfileUtils::parseJsonFile(info, true);
-
- // correct missing or wrong uid based on the file name
- QString uid = info.completeBaseName();
-
- // ignore builtins, they've been handled already
- if (uid == "net.minecraft")
- continue;
- if (uid == "org.lwjgl")
- continue;
-
- // handle horrible corner cases
- if(uid.isEmpty())
- {
- // if you have a file named '.json', make it just go away.
- // FIXME: @QUALITY do not ignore return value
- QFile::remove(info.absoluteFilePath());
- continue;
- }
- file->uid = uid;
- // FIXME: @QUALITY do not ignore return value
- ProfileUtils::saveJsonFile(OneSixVersionFormat::versionFileToJson(file), info.absoluteFilePath());
-
- auto component = new Component(this, file->uid, file);
- auto version = d->getOldConfigVersion(file->uid);
- if(!version.isEmpty())
- {
- component->m_version = version;
- }
- loadedComponents[file->uid] = component;
- }
- // try to load the other 'hardcoded' patches (forge, liteloader), if they weren't loaded from files
- auto loadSpecial = [&](const QString & uid, int order)
- {
- auto patchVersion = d->getOldConfigVersion(uid);
- if(!patchVersion.isEmpty() && !loadedComponents.contains(uid))
- {
- auto patch = new Component(this, APPLICATION->metadataIndex()->get(uid, patchVersion));
- patch->setOrder(order);
- loadedComponents[uid] = patch;
- }
- };
- loadSpecial("net.minecraftforge", 5);
- loadSpecial("com.mumfrey.liteloader", 10);
-
- // load the old order.json file, if present
- ProfileUtils::PatchOrder userOrder;
- ProfileUtils::readOverrideOrders(FS::PathCombine(d->m_instance->instanceRoot(), "order.json"), userOrder);
-
- // now add all the patches by user sort order
- for (auto uid : userOrder)
- {
- // ignore builtins
- if (uid == "net.minecraft")
- continue;
- if (uid == "org.lwjgl")
- continue;
- // ordering has a patch that is gone?
- if(!loadedComponents.contains(uid))
- {
- continue;
- }
- components.append(loadedComponents.take(uid));
- }
-
- // is there anything left to sort? - this is used when there are leftover components that aren't part of the order.json
- if(!loadedComponents.isEmpty())
- {
- // inserting into multimap by order number as key sorts the patches and detects duplicates
- QMultiMap<int, ComponentPtr> files;
- auto iter = loadedComponents.begin();
- while(iter != loadedComponents.end())
- {
- files.insert((*iter)->getOrder(), *iter);
- iter++;
- }
-
- // then just extract the patches and put them in the list
- for (auto order : files.keys())
- {
- const auto &values = files.values(order);
- for(auto &value: values)
- {
- // TODO: put back the insertion of problem messages here, so the user knows about the id duplication
- components.append(value);
- }
- }
- }
- // new we have a complete list of components...
- return savePackProfile(componentsFilePath(), components);
-}
-
// END: save/load
void PackProfile::appendComponent(ComponentPtr component)
@@ -1169,15 +924,6 @@ std::shared_ptr<LaunchProfile> PackProfile::getProfile() const
return d->m_profile;
}
-void PackProfile::setOldConfigVersion(const QString& uid, const QString& version)
-{
- if(version.isEmpty())
- {
- return;
- }
- d->m_oldConfigVersions[uid] = version;
-}
-
bool PackProfile::setComponentVersion(const QString& uid, const QString& version, bool important)
{
auto iter = d->componentIndex.find(uid);
diff --git a/launcher/minecraft/PackProfile.h b/launcher/minecraft/PackProfile.h
index f30deb5a..989d1c6a 100644
--- a/launcher/minecraft/PackProfile.h
+++ b/launcher/minecraft/PackProfile.h
@@ -143,8 +143,6 @@ private:
bool installCustomJar_internal(QString filepath);
bool removeComponent_internal(ComponentPtr patch);
- bool migratePreComponentConfig();
-
private: /* data */
std::unique_ptr<PackProfileData> d;
diff --git a/launcher/minecraft/PackProfile_p.h b/launcher/minecraft/PackProfile_p.h
index fce921bb..715e0460 100644
--- a/launcher/minecraft/PackProfile_p.h
+++ b/launcher/minecraft/PackProfile_p.h
@@ -18,18 +18,6 @@ struct PackProfileData
// the launch profile (volatile, temporary thing created on demand)
std::shared_ptr<LaunchProfile> m_profile;
- // version information migrated from instance.cfg file. Single use on migration!
- std::map<QString, QString> m_oldConfigVersions;
- QString getOldConfigVersion(const QString& uid) const
- {
- const auto iter = m_oldConfigVersions.find(uid);
- if(iter != m_oldConfigVersions.cend())
- {
- return (*iter).second;
- }
- return QString();
- }
-
// persistent list of components and related machinery
ComponentContainer components;
ComponentIndex componentIndex;
diff --git a/launcher/minecraft/auth/AccountData.cpp b/launcher/minecraft/auth/AccountData.cpp
index 9b84fe1a..f791db14 100644
--- a/launcher/minecraft/auth/AccountData.cpp
+++ b/launcher/minecraft/auth/AccountData.cpp
@@ -327,6 +327,10 @@ bool AccountData::resumeStateFromV3(QJsonObject data) {
}
if(type == AccountType::MSA) {
+ auto clientIDV = data.value("msa-client-id");
+ if (clientIDV.isString()) {
+ msaClientID = clientIDV.toString();
+ } // leave msaClientID empty if it doesn't exist or isn't a string
msaToken = tokenFromJSONV3(data, "msa");
userToken = tokenFromJSONV3(data, "utoken");
xboxApiToken = tokenFromJSONV3(data, "xrp-main");
@@ -360,6 +364,7 @@ QJsonObject AccountData::saveState() const {
}
else if (type == AccountType::MSA) {
output["type"] = "MSA";
+ output["msa-client-id"] = msaClientID;
tokenToJSONV3(output, msaToken, "msa");
tokenToJSONV3(output, userToken, "utoken");
tokenToJSONV3(output, xboxApiToken, "xrp-main");
diff --git a/launcher/minecraft/auth/AccountData.h b/launcher/minecraft/auth/AccountData.h
index 606c1ad1..6749a471 100644
--- a/launcher/minecraft/auth/AccountData.h
+++ b/launcher/minecraft/auth/AccountData.h
@@ -47,6 +47,7 @@ enum class AccountState {
Offline,
Working,
Online,
+ Disabled,
Errored,
Expired,
Gone
@@ -81,6 +82,7 @@ struct AccountData {
bool legacy = false;
bool canMigrateToMSA = false;
+ QString msaClientID;
Katabasis::Token msaToken;
Katabasis::Token userToken;
Katabasis::Token xboxApiToken;
diff --git a/launcher/minecraft/auth/AccountList.cpp b/launcher/minecraft/auth/AccountList.cpp
index 04470e1c..e404cdda 100644
--- a/launcher/minecraft/auth/AccountList.cpp
+++ b/launcher/minecraft/auth/AccountList.cpp
@@ -291,6 +291,9 @@ QVariant AccountList::data(const QModelIndex &index, int role) const
case AccountState::Expired: {
return tr("Expired", "Account status");
}
+ case AccountState::Disabled: {
+ return tr("Disabled", "Account status");
+ }
case AccountState::Gone: {
return tr("Gone", "Account status");
}
diff --git a/launcher/minecraft/auth/AccountTask.cpp b/launcher/minecraft/auth/AccountTask.cpp
index 98d8d94d..321b350f 100644
--- a/launcher/minecraft/auth/AccountTask.cpp
+++ b/launcher/minecraft/auth/AccountTask.cpp
@@ -43,6 +43,8 @@ QString AccountTask::getStateMessage() const
return tr("Authentication task succeeded.");
case AccountTaskState::STATE_OFFLINE:
return tr("Failed to contact the authentication server.");
+ case AccountTaskState::STATE_DISABLED:
+ return tr("Client ID has changed. New session needs to be created.");
case AccountTaskState::STATE_FAILED_SOFT:
return tr("Encountered an error during authentication.");
case AccountTaskState::STATE_FAILED_HARD:
@@ -78,6 +80,12 @@ bool AccountTask::changeState(AccountTaskState newState, QString reason)
emitFailed(reason);
return false;
}
+ case AccountTaskState::STATE_DISABLED: {
+ m_data->errorString = reason;
+ m_data->accountState = AccountState::Disabled;
+ emitFailed(reason);
+ return false;
+ }
case AccountTaskState::STATE_FAILED_SOFT: {
m_data->errorString = reason;
m_data->accountState = AccountState::Errored;
diff --git a/launcher/minecraft/auth/AccountTask.h b/launcher/minecraft/auth/AccountTask.h
index dac3f1b5..c2a5d86c 100644
--- a/launcher/minecraft/auth/AccountTask.h
+++ b/launcher/minecraft/auth/AccountTask.h
@@ -35,6 +35,7 @@ enum class AccountTaskState
STATE_CREATED,
STATE_WORKING,
STATE_SUCCEEDED,
+ STATE_DISABLED, //!< MSA Client ID has changed. Tell user to reloginn
STATE_FAILED_SOFT, //!< soft failure. authentication went through partially
STATE_FAILED_HARD, //!< hard failure. main tokens are invalid
STATE_FAILED_GONE, //!< hard failure. main tokens are invalid, and the account no longer exists
diff --git a/launcher/minecraft/auth/MinecraftAccount.cpp b/launcher/minecraft/auth/MinecraftAccount.cpp
index ffc81ed8..a604cadf 100644
--- a/launcher/minecraft/auth/MinecraftAccount.cpp
+++ b/launcher/minecraft/auth/MinecraftAccount.cpp
@@ -176,6 +176,9 @@ void MinecraftAccount::authFailed(QString reason)
{
switch (m_currentTask->taskState()) {
case AccountTaskState::STATE_OFFLINE:
+ case AccountTaskState::STATE_DISABLED: {
+ // NOTE: user will need to fix this themselves.
+ }
case AccountTaskState::STATE_FAILED_SOFT: {
// NOTE: this doesn't do much. There was an error of some sort.
}
diff --git a/launcher/minecraft/auth/steps/MSAStep.cpp b/launcher/minecraft/auth/steps/MSAStep.cpp
index 779aee43..207d9373 100644
--- a/launcher/minecraft/auth/steps/MSAStep.cpp
+++ b/launcher/minecraft/auth/steps/MSAStep.cpp
@@ -12,9 +12,10 @@ using OAuth2 = Katabasis::DeviceFlow;
using Activity = Katabasis::Activity;
MSAStep::MSAStep(AccountData* data, Action action) : AuthStep(data), m_action(action) {
+ m_clientId = APPLICATION->getMSAClientID();
OAuth2::Options opts;
opts.scope = "XboxLive.signin offline_access";
- opts.clientIdentifier = APPLICATION->getMSAClientID();
+ opts.clientIdentifier = m_clientId;
opts.authorizationUrl = "https://login.microsoftonline.com/consumers/oauth2/v2.0/devicecode";
opts.accessTokenUrl = "https://login.microsoftonline.com/consumers/oauth2/v2.0/token";
@@ -48,6 +49,10 @@ void MSAStep::rehydrate() {
void MSAStep::perform() {
switch(m_action) {
case Refresh: {
+ if (m_data->msaClientID != m_clientId) {
+ emit hideVerificationUriAndCode();
+ emit finished(AccountTaskState::STATE_DISABLED, tr("Microsoft user authentication failed - client identification has changed."));
+ }
m_oauth2->refresh();
return;
}
@@ -57,6 +62,7 @@ void MSAStep::perform() {
m_oauth2->setExtraRequestParams(extraOpts);
*m_data = AccountData();
+ m_data->msaClientID = m_clientId;
m_oauth2->login();
return;
}
diff --git a/launcher/minecraft/auth/steps/MSAStep.h b/launcher/minecraft/auth/steps/MSAStep.h
index 49ba3542..301e1465 100644
--- a/launcher/minecraft/auth/steps/MSAStep.h
+++ b/launcher/minecraft/auth/steps/MSAStep.h
@@ -29,4 +29,5 @@ private slots:
private:
Katabasis::DeviceFlow *m_oauth2 = nullptr;
Action m_action;
+ QString m_clientId;
};
diff --git a/launcher/minecraft/legacy/LegacyInstance.cpp b/launcher/minecraft/legacy/LegacyInstance.cpp
deleted file mode 100644
index f467ec06..00000000
--- a/launcher/minecraft/legacy/LegacyInstance.cpp
+++ /dev/null
@@ -1,256 +0,0 @@
-/* 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 <QFileInfo>
-#include <minecraft/launch/LauncherPartLaunch.h>
-#include <QDir>
-#include <settings/Setting.h>
-
-#include "LegacyInstance.h"
-
-#include "minecraft/legacy/LegacyModList.h"
-#include "minecraft/WorldList.h"
-#include <MMCZip.h>
-#include <FileSystem.h>
-
-LegacyInstance::LegacyInstance(SettingsObjectPtr globalSettings, SettingsObjectPtr settings, const QString &rootDir)
- : BaseInstance(globalSettings, settings, rootDir)
-{
- settings->registerSetting("NeedsRebuild", true);
- settings->registerSetting("ShouldUpdate", false);
- settings->registerSetting("JarVersion", QString());
- settings->registerSetting("IntendedJarVersion", QString());
- /*
- * custom base jar has no default. it is determined in code... see the accessor methods for
- *it
- *
- * for instances that DO NOT have the CustomBaseJar setting (legacy instances),
- * [.]minecraft/bin/mcbackup.jar is the default base jar
- */
- settings->registerSetting("UseCustomBaseJar", true);
- settings->registerSetting("CustomBaseJar", "");
-}
-
-QString LegacyInstance::mainJarToPreserve() const
-{
- bool customJar = m_settings->get("UseCustomBaseJar").toBool();
- if(customJar)
- {
- auto base = baseJar();
- if(QFile::exists(base))
- {
- return base;
- }
- }
- auto runnable = runnableJar();
- if(QFile::exists(runnable))
- {
- return runnable;
- }
- return QString();
-}
-
-
-QString LegacyInstance::baseJar() const
-{
- bool customJar = m_settings->get("UseCustomBaseJar").toBool();
- if (customJar)
- {
- return customBaseJar();
- }
- else
- return defaultBaseJar();
-}
-
-QString LegacyInstance::customBaseJar() const
-{
- QString value = m_settings->get("CustomBaseJar").toString();
- if (value.isNull() || value.isEmpty())
- {
- return defaultCustomBaseJar();
- }
- return value;
-}
-
-bool LegacyInstance::shouldUseCustomBaseJar() const
-{
- return m_settings->get("UseCustomBaseJar").toBool();
-}
-
-
-Task::Ptr LegacyInstance::createUpdateTask(Net::Mode)
-{
- return nullptr;
-}
-
-std::shared_ptr<LegacyModList> LegacyInstance::jarModList() const
-{
- if (!jar_mod_list)
- {
- auto list = new LegacyModList(jarModsDir(), modListFile());
- jar_mod_list.reset(list);
- }
- jar_mod_list->update();
- return jar_mod_list;
-}
-
-QString LegacyInstance::gameRoot() const
-{
- QFileInfo mcDir(FS::PathCombine(instanceRoot(), "minecraft"));
- QFileInfo dotMCDir(FS::PathCombine(instanceRoot(), ".minecraft"));
-
- if (mcDir.exists() && !dotMCDir.exists())
- return mcDir.filePath();
- else
- return dotMCDir.filePath();
-}
-
-QString LegacyInstance::binRoot() const
-{
- return FS::PathCombine(gameRoot(), "bin");
-}
-
-QString LegacyInstance::modsRoot() const {
- return FS::PathCombine(gameRoot(), "mods");
-}
-
-
-QString LegacyInstance::jarModsDir() const
-{
- return FS::PathCombine(instanceRoot(), "instMods");
-}
-
-QString LegacyInstance::libDir() const
-{
- return FS::PathCombine(gameRoot(), "lib");
-}
-
-QString LegacyInstance::savesDir() const
-{
- return FS::PathCombine(gameRoot(), "saves");
-}
-
-QString LegacyInstance::coreModsDir() const
-{
- return FS::PathCombine(gameRoot(), "coremods");
-}
-
-QString LegacyInstance::resourceDir() const
-{
- return FS::PathCombine(gameRoot(), "resources");
-}
-QString LegacyInstance::texturePacksDir() const
-{
- return FS::PathCombine(gameRoot(), "texturepacks");
-}
-
-QString LegacyInstance::runnableJar() const
-{
- return FS::PathCombine(binRoot(), "minecraft.jar");
-}
-
-QString LegacyInstance::modListFile() const
-{
- return FS::PathCombine(instanceRoot(), "modlist");
-}
-
-QString LegacyInstance::instanceConfigFolder() const
-{
- return FS::PathCombine(gameRoot(), "config");
-}
-
-bool LegacyInstance::shouldRebuild() const
-{
- return m_settings->get("NeedsRebuild").toBool();
-}
-
-QString LegacyInstance::currentVersionId() const
-{
- return m_settings->get("JarVersion").toString();
-}
-
-QString LegacyInstance::intendedVersionId() const
-{
- return m_settings->get("IntendedJarVersion").toString();
-}
-
-bool LegacyInstance::shouldUpdate() const
-{
- QVariant var = settings()->get("ShouldUpdate");
- if (!var.isValid() || var.toBool() == false)
- {
- return intendedVersionId() != currentVersionId();
- }
- return true;
-}
-
-QString LegacyInstance::defaultBaseJar() const
-{
- return "versions/" + intendedVersionId() + "/" + intendedVersionId() + ".jar";
-}
-
-QString LegacyInstance::defaultCustomBaseJar() const
-{
- return FS::PathCombine(binRoot(), "mcbackup.jar");
-}
-
-std::shared_ptr<WorldList> LegacyInstance::worldList() const
-{
- if (!m_world_list)
- {
- m_world_list.reset(new WorldList(savesDir()));
- }
- return m_world_list;
-}
-
-QString LegacyInstance::typeName() const
-{
- return tr("Legacy");
-}
-
-QString LegacyInstance::getStatusbarDescription()
-{
- return tr("Instance from previous versions.");
-}
-
-QStringList LegacyInstance::verboseDescription(AuthSessionPtr session, MinecraftServerTargetPtr serverToJoin)
-{
- QStringList out;
-
- auto alltraits = traits();
- if(alltraits.size())
- {
- out << "Traits:";
- for (auto trait : alltraits)
- {
- out << " " + trait;
- }
- out << "";
- }
-
- QString windowParams;
- if (settings()->get("LaunchMaximized").toBool())
- {
- out << "Window size: max (if available)";
- }
- else
- {
- auto width = settings()->get("MinecraftWinWidth").toInt();
- auto height = settings()->get("MinecraftWinHeight").toInt();
- out << "Window size: " + QString::number(width) + " x " + QString::number(height);
- }
- out << "";
- return out;
-}
diff --git a/launcher/minecraft/legacy/LegacyInstance.h b/launcher/minecraft/legacy/LegacyInstance.h
deleted file mode 100644
index 298543f7..00000000
--- a/launcher/minecraft/legacy/LegacyInstance.h
+++ /dev/null
@@ -1,142 +0,0 @@
-/* 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 "BaseInstance.h"
-#include "launch/LaunchTask.h"
-
-class ModFolderModel;
-class LegacyModList;
-class WorldList;
-class Task;
-/*
- * WHY: Legacy instances - from MultiMC 3 and 4 - are here only to provide a way to upgrade them to the current format.
- */
-class LegacyInstance : public BaseInstance
-{
- Q_OBJECT
-public:
-
- explicit LegacyInstance(SettingsObjectPtr globalSettings, SettingsObjectPtr settings, const QString &rootDir);
-
- virtual void saveNow() override {}
-
- /// Path to the instance's minecraft.jar
- QString runnableJar() const;
-
- //! Path to the instance's modlist file.
- QString modListFile() const;
-
- ////// Directories //////
- QString libDir() const;
- QString savesDir() const;
- QString texturePacksDir() const;
- QString jarModsDir() const;
- QString coreModsDir() const;
- QString resourceDir() const;
-
- QString instanceConfigFolder() const override;
-
- QString gameRoot() const override; // Path to the instance's minecraft directory.
- QString modsRoot() const override; // Path to the instance's minecraft directory.
- QString binRoot() const; // Path to the instance's minecraft bin directory.
-
- /// Get the curent base jar of this instance. By default, it's the
- /// versions/$version/$version.jar
- QString baseJar() const;
-
- /// the default base jar of this instance
- QString defaultBaseJar() const;
- /// the default custom base jar of this instance
- QString defaultCustomBaseJar() const;
-
- // the main jar that we actually want to keep when migrating the instance
- QString mainJarToPreserve() const;
-
- /*!
- * Whether or not custom base jar is used
- */
- bool shouldUseCustomBaseJar() const;
-
- /*!
- * The value of the custom base jar
- */
- QString customBaseJar() const;
-
- std::shared_ptr<LegacyModList> jarModList() const;
- std::shared_ptr<WorldList> worldList() const;
-
- /*!
- * Whether or not the instance's minecraft.jar needs to be rebuilt.
- * If this is true, when the instance launches, its jar mods will be
- * re-added to a fresh minecraft.jar file.
- */
- bool shouldRebuild() const;
-
- QString currentVersionId() const;
- QString intendedVersionId() const;
-
- QSet<QString> traits() const override
- {
- return {"legacy-instance", "texturepacks"};
- };
-
- virtual bool shouldUpdate() const;
- virtual Task::Ptr createUpdateTask(Net::Mode mode) override;
-
- virtual QString typeName() const override;
-
- bool canLaunch() const override
- {
- return false;
- }
- bool canEdit() const override
- {
- return true;
- }
- bool canExport() const override
- {
- return false;
- }
- shared_qobject_ptr<LaunchTask> createLaunchTask(
- AuthSessionPtr account, MinecraftServerTargetPtr serverToJoin) override
- {
- return nullptr;
- }
- IPathMatcher::Ptr getLogFileMatcher() override
- {
- return nullptr;
- }
- QString getLogFileRoot() override
- {
- return gameRoot();
- }
-
- QString getStatusbarDescription() override;
- QStringList verboseDescription(AuthSessionPtr session, MinecraftServerTargetPtr serverToJoin) override;
-
- QProcessEnvironment createEnvironment() override
- {
- return QProcessEnvironment();
- }
- QMap<QString, QString> getVariables() const override
- {
- return {};
- }
-protected:
- mutable std::shared_ptr<LegacyModList> jar_mod_list;
- mutable std::shared_ptr<WorldList> m_world_list;
-};
diff --git a/launcher/minecraft/legacy/LegacyModList.cpp b/launcher/minecraft/legacy/LegacyModList.cpp
deleted file mode 100644
index e9948ab1..00000000
--- a/launcher/minecraft/legacy/LegacyModList.cpp
+++ /dev/null
@@ -1,136 +0,0 @@
-/* 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 "LegacyModList.h"
-#include <FileSystem.h>
-#include <QString>
-#include <QDebug>
-
-LegacyModList::LegacyModList(const QString &dir, const QString &list_file)
- : m_dir(dir), m_list_file(list_file)
-{
- FS::ensureFolderPathExists(m_dir.absolutePath());
- m_dir.setFilter(QDir::Readable | QDir::NoDotAndDotDot | QDir::Files | QDir::Dirs);
- m_dir.setSorting(QDir::Name | QDir::IgnoreCase | QDir::LocaleAware);
-}
-
- struct OrderItem
- {
- QString id;
- bool enabled = false;
- };
- typedef QList<OrderItem> OrderList;
-
-static void internalSort(QList<LegacyModList::Mod> &what)
-{
- auto predicate = [](const LegacyModList::Mod &left, const LegacyModList::Mod &right)
- {
- return left.fileName().localeAwareCompare(right.fileName()) < 0;
- };
- std::sort(what.begin(), what.end(), predicate);
-}
-
-static OrderList readListFile(const QString &m_list_file)
-{
- OrderList itemList;
- if (m_list_file.isNull() || m_list_file.isEmpty())
- return itemList;
-
- QFile textFile(m_list_file);
- if (!textFile.open(QIODevice::ReadOnly | QIODevice::Text))
- return OrderList();
-
- QTextStream textStream;
- textStream.setAutoDetectUnicode(true);
- textStream.setDevice(&textFile);
- while (true)
- {
- QString line = textStream.readLine();
- if (line.isNull() || line.isEmpty())
- break;
- else
- {
- OrderItem it;
- it.enabled = !line.endsWith(".disabled");
- if (!it.enabled)
- {
- line.chop(9);
- }
- it.id = line;
- itemList.append(it);
- }
- }
- textFile.close();
- return itemList;
-}
-
-bool LegacyModList::update()
-{
- if (!m_dir.exists() || !m_dir.isReadable())
- return false;
-
- QList<Mod> orderedMods;
- QList<Mod> newMods;
- m_dir.refresh();
- auto folderContents = m_dir.entryInfoList();
-
- // first, process the ordered items (if any)
- OrderList listOrder = readListFile(m_list_file);
- for (auto item : listOrder)
- {
- QFileInfo infoEnabled(m_dir.filePath(item.id));
- QFileInfo infoDisabled(m_dir.filePath(item.id + ".disabled"));
- int idxEnabled = folderContents.indexOf(infoEnabled);
- int idxDisabled = folderContents.indexOf(infoDisabled);
- bool isEnabled;
- // if both enabled and disabled versions are present, it's a special case...
- if (idxEnabled >= 0 && idxDisabled >= 0)
- {
- // we only process the one we actually have in the order file.
- // and exactly as we have it.
- // THIS IS A CORNER CASE
- isEnabled = item.enabled;
- }
- else
- {
- // only one is present.
- // we pick the one that we found.
- // we assume the mod was enabled/disabled by external means
- isEnabled = idxEnabled >= 0;
- }
- int idx = isEnabled ? idxEnabled : idxDisabled;
- QFileInfo &info = isEnabled ? infoEnabled : infoDisabled;
- // if the file from the index file exists
- if (idx != -1)
- {
- // remove from the actual folder contents list
- folderContents.takeAt(idx);
- // append the new mod
- orderedMods.append(info);
- }
- }
- // if there are any untracked files... append them sorted at the end
- if (folderContents.size())
- {
- for (auto entry : folderContents)
- {
- newMods.append(entry);
- }
- internalSort(newMods);
- orderedMods.append(newMods);
- }
- mods.swap(orderedMods);
- return true;
-}
diff --git a/launcher/minecraft/legacy/LegacyModList.h b/launcher/minecraft/legacy/LegacyModList.h
deleted file mode 100644
index fade736e..00000000
--- a/launcher/minecraft/legacy/LegacyModList.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/* 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 <QList>
-#include <QString>
-#include <QDir>
-
-class LegacyModList
-{
-public:
-
- using Mod = QFileInfo;
-
- LegacyModList(const QString &dir, const QString &list_file = QString());
-
- /// Reloads the mod list and returns true if the list changed.
- bool update();
-
- QDir dir()
- {
- return m_dir;
- }
-
- const QList<Mod> & allMods()
- {
- return mods;
- }
-
-protected:
- QDir m_dir;
- QString m_list_file;
- QList<Mod> mods;
-};
diff --git a/launcher/minecraft/legacy/LegacyUpgradeTask.cpp b/launcher/minecraft/legacy/LegacyUpgradeTask.cpp
deleted file mode 100644
index a4ea60cd..00000000
--- a/launcher/minecraft/legacy/LegacyUpgradeTask.cpp
+++ /dev/null
@@ -1,138 +0,0 @@
-#include "LegacyUpgradeTask.h"
-#include "settings/INISettingsObject.h"
-#include "FileSystem.h"
-#include "NullInstance.h"
-#include "pathmatcher/RegexpMatcher.h"
-#include <QtConcurrentRun>
-#include "LegacyInstance.h"
-#include "minecraft/MinecraftInstance.h"
-#include "minecraft/PackProfile.h"
-#include "LegacyModList.h"
-#include "classparser.h"
-
-LegacyUpgradeTask::LegacyUpgradeTask(InstancePtr origInstance)
-{
- m_origInstance = origInstance;
-}
-
-void LegacyUpgradeTask::executeTask()
-{
- setStatus(tr("Copying instance %1").arg(m_origInstance->name()));
-
- FS::copy folderCopy(m_origInstance->instanceRoot(), m_stagingPath);
- folderCopy.followSymlinks(true);
-
- m_copyFuture = QtConcurrent::run(QThreadPool::globalInstance(), folderCopy);
- connect(&m_copyFutureWatcher, &QFutureWatcher<bool>::finished, this, &LegacyUpgradeTask::copyFinished);
- connect(&m_copyFutureWatcher, &QFutureWatcher<bool>::canceled, this, &LegacyUpgradeTask::copyAborted);
- m_copyFutureWatcher.setFuture(m_copyFuture);
-}
-
-static QString decideVersion(const QString& currentVersion, const QString& intendedVersion)
-{
- if(intendedVersion != currentVersion)
- {
- if(!intendedVersion.isEmpty())
- {
- return intendedVersion;
- }
- else if(!currentVersion.isEmpty())
- {
- return currentVersion;
- }
- }
- else
- {
- if(!intendedVersion.isEmpty())
- {
- return intendedVersion;
- }
- }
- return QString();
-}
-
-void LegacyUpgradeTask::copyFinished()
-{
- auto successful = m_copyFuture.result();
- if(!successful)
- {
- emitFailed(tr("Instance folder copy failed."));
- return;
- }
- auto legacyInst = std::dynamic_pointer_cast<LegacyInstance>(m_origInstance);
-
- auto instanceSettings = std::make_shared<INISettingsObject>(FS::PathCombine(m_stagingPath, "instance.cfg"));
- instanceSettings->registerSetting("InstanceType", "Legacy");
- instanceSettings->set("InstanceType", "OneSix");
- // NOTE: this scope ensures the instance is fully saved before we emitSucceeded
- {
- MinecraftInstance inst(m_globalSettings, instanceSettings, m_stagingPath);
- inst.setName(m_instName);
-
- QString preferredVersionNumber = decideVersion(legacyInst->currentVersionId(), legacyInst->intendedVersionId());
- if(preferredVersionNumber.isNull())
- {
- // try to decide version based on the jar(s?)
- preferredVersionNumber = classparser::GetMinecraftJarVersion(legacyInst->baseJar());
- if(preferredVersionNumber.isNull())
- {
- preferredVersionNumber = classparser::GetMinecraftJarVersion(legacyInst->runnableJar());
- if(preferredVersionNumber.isNull())
- {
- emitFailed(tr("Could not decide Minecraft version."));
- return;
- }
- }
- }
- auto components = inst.getPackProfile();
- components->buildingFromScratch();
- components->setComponentVersion("net.minecraft", preferredVersionNumber, true);
-
- QString jarPath = legacyInst->mainJarToPreserve();
- if(!jarPath.isNull())
- {
- qDebug() << "Preserving base jar! : " << jarPath;
- // FIXME: handle case when the jar is unreadable?
- // TODO: check the hash, if it's the same as the upstream jar, do not do this
- components->installCustomJar(jarPath);
- }
-
- auto jarMods = legacyInst->jarModList()->allMods();
- for(auto & jarMod: jarMods)
- {
- QString modPath = jarMod.absoluteFilePath();
- qDebug() << "jarMod: " << modPath;
- components->installJarMods({modPath});
- }
-
- // remove all the extra garbage we no longer need
- auto removeAll = [&](const QString &root, const QStringList &things)
- {
- for(auto &thing : things)
- {
- auto removePath = FS::PathCombine(root, thing);
- QFileInfo stat(removePath);
- if(stat.isDir())
- {
- FS::deletePath(removePath);
- }
- else
- {
- QFile::remove(removePath);
- }
- }
- };
- QStringList rootRemovables = {"modlist", "version", "instMods"};
- QStringList mcRemovables = {"bin", "MultiMCLauncher.jar", "icon.png"};
- removeAll(inst.instanceRoot(), rootRemovables);
- removeAll(inst.gameRoot(), mcRemovables);
- }
- emitSucceeded();
-}
-
-void LegacyUpgradeTask::copyAborted()
-{
- emitFailed(tr("Instance folder copy has been aborted."));
- return;
-}
-
diff --git a/launcher/minecraft/legacy/LegacyUpgradeTask.h b/launcher/minecraft/legacy/LegacyUpgradeTask.h
deleted file mode 100644
index 542e17b8..00000000
--- a/launcher/minecraft/legacy/LegacyUpgradeTask.h
+++ /dev/null
@@ -1,29 +0,0 @@
-#pragma once
-
-#include "InstanceTask.h"
-#include "net/NetJob.h"
-#include <QUrl>
-#include <QFuture>
-#include <QFutureWatcher>
-#include "settings/SettingsObject.h"
-#include "BaseVersion.h"
-#include "BaseInstance.h"
-
-
-class LegacyUpgradeTask : public InstanceTask
-{
- Q_OBJECT
-public:
- explicit LegacyUpgradeTask(InstancePtr origInstance);
-
-protected:
- //! Entry point for tasks.
- virtual void executeTask() override;
- void copyFinished();
- void copyAborted();
-
-private: /* data */
- InstancePtr m_origInstance;
- QFuture<bool> m_copyFuture;
- QFutureWatcher<bool> m_copyFutureWatcher;
-};
diff --git a/launcher/modplatform/atlauncher/ATLPackInstallTask.cpp b/launcher/modplatform/atlauncher/ATLPackInstallTask.cpp
index 8de5fc9f..9dcb3504 100644
--- a/launcher/modplatform/atlauncher/ATLPackInstallTask.cpp
+++ b/launcher/modplatform/atlauncher/ATLPackInstallTask.cpp
@@ -720,8 +720,6 @@ void PackInstallTask::install()
auto instanceConfigPath = FS::PathCombine(m_stagingPath, "instance.cfg");
auto instanceSettings = std::make_shared<INISettingsObject>(instanceConfigPath);
instanceSettings->suspendSave();
- instanceSettings->registerSetting("InstanceType", "Legacy");
- instanceSettings->set("InstanceType", "OneSix");
MinecraftInstance instance(m_globalSettings, instanceSettings, m_stagingPath);
auto components = instance.getPackProfile();
diff --git a/launcher/modplatform/legacy_ftb/PackInstallTask.cpp b/launcher/modplatform/legacy_ftb/PackInstallTask.cpp
index 1d300192..f655a066 100644
--- a/launcher/modplatform/legacy_ftb/PackInstallTask.cpp
+++ b/launcher/modplatform/legacy_ftb/PackInstallTask.cpp
@@ -122,8 +122,6 @@ void PackInstallTask::install()
QString instanceConfigPath = FS::PathCombine(m_stagingPath, "instance.cfg");
auto instanceSettings = std::make_shared<INISettingsObject>(instanceConfigPath);
instanceSettings->suspendSave();
- instanceSettings->registerSetting("InstanceType", "Legacy");
- instanceSettings->set("InstanceType", "OneSix");
MinecraftInstance instance(m_globalSettings, instanceSettings, m_stagingPath);
auto components = instance.getPackProfile();
diff --git a/launcher/modplatform/modpacksch/FTBPackInstallTask.cpp b/launcher/modplatform/modpacksch/FTBPackInstallTask.cpp
index 03570226..33df6fa4 100644
--- a/launcher/modplatform/modpacksch/FTBPackInstallTask.cpp
+++ b/launcher/modplatform/modpacksch/FTBPackInstallTask.cpp
@@ -181,8 +181,6 @@ void PackInstallTask::install()
auto instanceConfigPath = FS::PathCombine(m_stagingPath, "instance.cfg");
auto instanceSettings = std::make_shared<INISettingsObject>(instanceConfigPath);
instanceSettings->suspendSave();
- instanceSettings->registerSetting("InstanceType", "Legacy");
- instanceSettings->set("InstanceType", "OneSix");
MinecraftInstance instance(m_globalSettings, instanceSettings, m_stagingPath);
auto components = instance.getPackProfile();
diff --git a/launcher/modplatform/technic/TechnicPackProcessor.cpp b/launcher/modplatform/technic/TechnicPackProcessor.cpp
index c45061ac..156a295a 100644
--- a/launcher/modplatform/technic/TechnicPackProcessor.cpp
+++ b/launcher/modplatform/technic/TechnicPackProcessor.cpp
@@ -31,8 +31,6 @@ void Technic::TechnicPackProcessor::run(SettingsObjectPtr globalSettings, const
QString minecraftPath = FS::PathCombine(stagingPath, ".minecraft");
QString configPath = FS::PathCombine(stagingPath, "instance.cfg");
auto instanceSettings = std::make_shared<INISettingsObject>(configPath);
- instanceSettings->registerSetting("InstanceType", "Legacy");
- instanceSettings->set("InstanceType", "OneSix");
MinecraftInstance instance(globalSettings, instanceSettings, stagingPath);
instance.setName(instName);
diff --git a/launcher/ui/MainWindow.cpp b/launcher/ui/MainWindow.cpp
index 32b27afb..ad7227cc 100644
--- a/launcher/ui/MainWindow.cpp
+++ b/launcher/ui/MainWindow.cpp
@@ -588,7 +588,7 @@ public:
actionExportInstance = TranslatedAction(MainWindow);
actionExportInstance->setObjectName(QStringLiteral("actionExportInstance"));
actionExportInstance.setTextId(QT_TRANSLATE_NOOP("MainWindow", "Export Instance"));
- // FIXME: missing tooltip
+ actionExportInstance.setTooltipId(QT_TRANSLATE_NOOP("MainWindow", "Export the selected instance as a zip file."));
all_actions.append(&actionExportInstance);
instanceToolBar->addAction(actionExportInstance);
diff --git a/launcher/ui/pages/instance/LegacyUpgradePage.cpp b/launcher/ui/pages/instance/LegacyUpgradePage.cpp
deleted file mode 100644
index cb78af02..00000000
--- a/launcher/ui/pages/instance/LegacyUpgradePage.cpp
+++ /dev/null
@@ -1,51 +0,0 @@
-#include "LegacyUpgradePage.h"
-#include "ui_LegacyUpgradePage.h"
-
-#include "InstanceList.h"
-#include "minecraft/legacy/LegacyInstance.h"
-#include "minecraft/legacy/LegacyUpgradeTask.h"
-#include "Application.h"
-
-#include "ui/dialogs/CustomMessageBox.h"
-#include "ui/dialogs/ProgressDialog.h"
-
-LegacyUpgradePage::LegacyUpgradePage(InstancePtr inst, QWidget *parent)
- : QWidget(parent), ui(new Ui::LegacyUpgradePage), m_inst(inst)
-{
- ui->setupUi(this);
-}
-
-LegacyUpgradePage::~LegacyUpgradePage()
-{
- delete ui;
-}
-
-void LegacyUpgradePage::runModalTask(Task *task)
-{
- connect(task, &Task::failed, [this](QString reason)
- {
- CustomMessageBox::selectable(this, tr("Error"), reason, QMessageBox::Warning)->show();
- });
- ProgressDialog loadDialog(this);
- loadDialog.setSkipButton(true, tr("Abort"));
- if(loadDialog.execWithTask(task) == QDialog::Accepted)
- {
- m_container->requestClose();
- }
-}
-
-void LegacyUpgradePage::on_upgradeButton_clicked()
-{
- QString newName = tr("%1 (Migrated)").arg(m_inst->name());
- auto upgradeTask = new LegacyUpgradeTask(m_inst);
- upgradeTask->setName(newName);
- upgradeTask->setGroup(APPLICATION->instances()->getInstanceGroup(m_inst->id()));
- upgradeTask->setIcon(m_inst->iconKey());
- unique_qobject_ptr<Task> task(APPLICATION->instances()->wrapInstanceTask(upgradeTask));
- runModalTask(task.get());
-}
-
-bool LegacyUpgradePage::shouldDisplay() const
-{
- return !m_inst->isRunning();
-}
diff --git a/launcher/ui/pages/instance/LegacyUpgradePage.h b/launcher/ui/pages/instance/LegacyUpgradePage.h
deleted file mode 100644
index 7c51956b..00000000
--- a/launcher/ui/pages/instance/LegacyUpgradePage.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/* 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 <QWidget>
-
-#include "minecraft/legacy/LegacyInstance.h"
-#include "ui/pages/BasePage.h"
-#include <Application.h>
-#include "tasks/Task.h"
-
-namespace Ui
-{
-class LegacyUpgradePage;
-}
-
-class LegacyUpgradePage : public QWidget, public BasePage
-{
- Q_OBJECT
-
-public:
- explicit LegacyUpgradePage(InstancePtr inst, QWidget *parent = 0);
- virtual ~LegacyUpgradePage();
- virtual QString displayName() const override
- {
- return tr("Upgrade");
- }
- virtual QIcon icon() const override
- {
- return APPLICATION->getThemedIcon("checkupdate");
- }
- virtual QString id() const override
- {
- return "upgrade";
- }
- virtual QString helpPage() const override
- {
- return "Legacy-upgrade";
- }
- virtual bool shouldDisplay() const override;
-
-private slots:
- void on_upgradeButton_clicked();
-
-private:
- void runModalTask(Task *task);
-
-private:
- Ui::LegacyUpgradePage *ui;
- InstancePtr m_inst;
-};
diff --git a/launcher/ui/pages/instance/LegacyUpgradePage.ui b/launcher/ui/pages/instance/LegacyUpgradePage.ui
deleted file mode 100644
index b22c03e5..00000000
--- a/launcher/ui/pages/instance/LegacyUpgradePage.ui
+++ /dev/null
@@ -1,54 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<ui version="4.0">
- <class>LegacyUpgradePage</class>
- <widget class="QWidget" name="LegacyUpgradePage">
- <property name="geometry">
- <rect>
- <x>0</x>
- <y>0</y>
- <width>546</width>
- <height>405</height>
- </rect>
- </property>
- <layout class="QVBoxLayout" name="verticalLayout_5">
- <property name="leftMargin">
- <number>0</number>
- </property>
- <property name="topMargin">
- <number>0</number>
- </property>
- <property name="rightMargin">
- <number>0</number>
- </property>
- <property name="bottomMargin">
- <number>0</number>
- </property>
- <item>
- <widget class="QTextBrowser" name="textBrowser">
- <property name="html">
- <string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
-&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
-p, li { white-space: pre-wrap; }
-&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'Noto Sans'; font-size:11pt; font-weight:400; font-style:normal;&quot;&gt;
-&lt;h1 style=&quot; margin-top:18px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:xx-large; font-weight:600;&quot;&gt;Upgrade is required&lt;/span&gt;&lt;/h1&gt;
-&lt;p style=&quot; margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;PolyMC now supports old Minecraft versions and all the required features in the new (OneSix) instance format. As a consequence, the old (Legacy) format has been entirely disabled and old instances need to be upgraded.&lt;/p&gt;
-&lt;p style=&quot; margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;The upgrade will create a new instance with the same contents as the current one, in the new format. The original instance will remain untouched, in case anything goes wrong in the process.&lt;/p&gt;
-&lt;p style=&quot; margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;Please report any issues on our &lt;a href=&quot;https://github.com/PolyMC/PolyMC/issues&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#3584e4;&quot;&gt;github issues page&lt;/span&gt;&lt;/a&gt;.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
- </property>
- <property name="openExternalLinks">
- <bool>true</bool>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QCommandLinkButton" name="upgradeButton">
- <property name="text">
- <string>Upgrade the instance</string>
- </property>
- </widget>
- </item>
- </layout>
- </widget>
- <resources/>
- <connections/>
-</ui>
diff --git a/packages/nix/polymc/default.nix b/packages/nix/polymc/default.nix
index e65a7e34..a9610017 100644
--- a/packages/nix/polymc/default.nix
+++ b/packages/nix/polymc/default.nix
@@ -79,4 +79,17 @@ mkDerivation rec {
--set GAME_LIBRARY_PATH ${gameLibraryPath} \
--prefix PATH : ${lib.makeBinPath [ xorg.xrandr ]}
'';
+
+ meta = with lib; {
+ homepage = "https://polymc.org/";
+ description = "A free, open source launcher for Minecraft";
+ longDescription = ''
+ Allows you to have multiple, separate instances of Minecraft (each with
+ their own mods, texture packs, saves, etc) and helps you manage them and
+ their associated options with a simple interface.
+ '';
+ platforms = platforms.unix;
+ license = licenses.gpl3Plus;
+ maintainers = with maintainers; [ starcraft66 kloenk ];
+ };
}