aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-x.github/scripts/prepare_JREs.sh41
-rw-r--r--.github/workflows/build.yml119
-rw-r--r--BUILD.md74
-rw-r--r--CMakeLists.txt15
-rw-r--r--README.md6
-rw-r--r--buildconfig/BuildConfig.cpp.in15
-rw-r--r--buildconfig/BuildConfig.h9
-rw-r--r--launcher/Application.cpp27
-rw-r--r--launcher/Application.h2
-rw-r--r--launcher/CMakeLists.txt19
-rw-r--r--launcher/InstancePageProvider.h3
-rw-r--r--launcher/UpdateController.cpp2
-rw-r--r--launcher/minecraft/auth/steps/MSAStep.cpp2
-rw-r--r--launcher/news/NewsChecker.cpp132
-rw-r--r--launcher/news/NewsChecker.h105
-rw-r--r--launcher/news/NewsEntry.cpp65
-rw-r--r--launcher/news/NewsEntry.h57
-rw-r--r--launcher/tools/MCEditTool.cpp2
-rw-r--r--launcher/translations/TranslationsModel.cpp2
-rw-r--r--launcher/ui/MainWindow.cpp89
-rw-r--r--launcher/ui/MainWindow.h9
-rw-r--r--launcher/ui/pages/global/APIPage.cpp (renamed from launcher/ui/pages/global/PastePage.cpp)20
-rw-r--r--launcher/ui/pages/global/APIPage.h (renamed from launcher/ui/pages/global/PastePage.h)18
-rw-r--r--launcher/ui/pages/global/APIPage.ui (renamed from launcher/ui/pages/global/PastePage.ui)60
-rw-r--r--launcher/ui/pages/global/AccountListPage.cpp5
-rw-r--r--launcher/ui/pages/instance/LegacyUpgradePage.ui9
-rw-r--r--launcher/ui/pages/modplatform/flame/FlameModPage.cpp22
-rw-r--r--launcher/ui/pages/modplatform/flame/FlameModPage.h2
-rw-r--r--launcher/ui/pages/modplatform/modrinth/ModrinthModel.cpp8
-rw-r--r--launcher/ui/pages/modplatform/modrinth/ModrinthPage.cpp23
-rw-r--r--launcher/ui/pages/modplatform/modrinth/ModrinthPage.h2
-rw-r--r--launcher/ui/widgets/LanguageSelectionWidget.cpp3
-rw-r--r--libraries/iconfix/CMakeLists.txt10
-rw-r--r--libraries/rainbow/CMakeLists.txt8
-rw-r--r--program_info/CMakeLists.txt5
-rw-r--r--program_info/LICENSE439
-rw-r--r--program_info/org.polymc.PolyMC.desktop.in (renamed from program_info/org.polymc.polymc.desktop.in)2
-rw-r--r--program_info/org.polymc.PolyMC.metainfo.xml.in50
38 files changed, 1336 insertions, 145 deletions
diff --git a/.github/scripts/prepare_JREs.sh b/.github/scripts/prepare_JREs.sh
new file mode 100755
index 00000000..b85e9c2f
--- /dev/null
+++ b/.github/scripts/prepare_JREs.sh
@@ -0,0 +1,41 @@
+#!/usr/bin/env bash
+
+URL_JDK8="https://api.adoptium.net/v3/binary/latest/8/ga/linux/x64/jre/hotspot/normal/eclipse"
+URL_JDK17="https://api.adoptium.net/v3/binary/latest/17/ga/linux/x64/jre/hotspot/normal/eclipse"
+
+mkdir -p JREs
+pushd JREs
+
+wget --content-disposition "$URL_JDK8"
+wget --content-disposition "$URL_JDK17"
+
+for file in *;
+do
+ mkdir temp
+
+ re='(OpenJDK([[:digit:]]+)U-jre_x64_linux_hotspot_([[:digit:]]+)(.*).tar.gz)'
+ if [[ $file =~ $re ]];
+ then
+ version_major=${BASH_REMATCH[2]}
+ version_trailing=${BASH_REMATCH[4]}
+
+ if [ $version_major = 17 ];
+ then
+ hyphen='-'
+ else
+ hyphen=''
+ fi
+
+ version_edit=$(echo $version_trailing | sed -e 's/_/+/g' | sed -e 's/b/-b/g')
+ dir_name=jdk$hyphen$version_major$version_edit-jre
+ mkdir jre$version_major
+ tar -xzf $file -C temp
+ pushd temp/$dir_name
+ cp -r . ../../jre$version_major
+ popd
+ fi
+
+ rm -rf temp
+done
+
+popd
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index d7eeaf1d..d2ccc59e 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -11,13 +11,13 @@ jobs:
include:
- os: ubuntu-20.04
- qt_version: 5.12.8
+ qt_version: 5.15.2
qt_host: linux
- os: windows-2022
qt_version: 5.15.2
qt_host: windows
- qt_arch: win64_mingw81
+ qt_arch: win32_mingw81
- os: macos-11
qt_version: 5.12.12
@@ -27,15 +27,38 @@ jobs:
runs-on: ${{ matrix.os }}
env:
- MACOSX_DEPLOYMENT_TARGET: ${{matrix.macosx_deployment_target}}
+ MACOSX_DEPLOYMENT_TARGET: ${{ matrix.macosx_deployment_target }}
+ INSTALL_DIR: "install"
+ BUILD_DIR: "build"
steps:
+ - name: Install 32bit mingw on Windows
+ if: runner.os == 'Windows'
+ uses: egor-tensin/setup-mingw@v2
+ with:
+ platform: x86
+
+ - name: Install 32bit zlib via Strawberry on Windows
+ if: runner.os == 'Windows'
+ run: |
+ choco install strawberryperl -y --force --x86
- name: Checkout
uses: actions/checkout@v2
with:
submodules: 'true'
+ # We need to do this here because it inexplicably fails if we split the step
+ - name: Download and install OpenSSL libs on Windows
+ if: runner.os == 'Windows'
+ run: |
+ python -m pip install --upgrade pip
+ python -m pip install aqtinstall==2.0.5
+ python -m aqt install-tool -O "${{ github.workspace }}\Qt\" windows desktop tools_openssl_x86
+ mkdir ${{ env.INSTALL_DIR }}
+ copy "${{ github.workspace }}\Qt\Tools\OpenSSL\Win_x86\bin\libssl-1_1.dll" "${{ github.workspace }}\${{ env.INSTALL_DIR }}\"
+ copy "${{ github.workspace }}\Qt\Tools\OpenSSL\Win_x86\bin\libcrypto-1_1.dll" "${{ github.workspace }}\${{ env.INSTALL_DIR }}\"
+
- name: Install OpenJDK
uses: AdoptOpenJDK/install-jdk@v1
with:
@@ -46,7 +69,7 @@ jobs:
uses: actions/cache@v2
with:
path: "${{ github.workspace }}/Qt/"
- key: ${{ runner.os }}-${{ matrix.qt_version }}-qt_cache
+ key: ${{ runner.os }}-${{ matrix.qt_version }}-${{ matrix.qt_arch }}-qt_cache
- name: Install Qt
uses: jurplel/install-qt-action@v2
@@ -60,48 +83,104 @@ jobs:
- name: Install Ninja
uses: urkle/action-get-ninja@v1
+ - name: Download linuxdeploy family
+ if: runner.os == 'Linux'
+ 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'
+ shell: bash
+ run: |
+ ${{ github.workspace }}/.github/scripts/prepare_JREs.sh
+
- name: Configure CMake
+ if: runner.os != 'Linux'
+ run: |
+ cmake -S . -B ${{ env.BUILD_DIR }} -DCMAKE_INSTALL_PREFIX=${{ env.INSTALL_DIR }} -DCMAKE_BUILD_TYPE=Debug -G Ninja
+
+ - name: Configure CMake on Linux
+ if: runner.os == 'Linux'
run: |
- cmake -S . -B build -DCMAKE_INSTALL_PREFIX=install -DCMAKE_BUILD_TYPE=Debug -G Ninja
+ cmake -S . -B ${{ env.BUILD_DIR }} -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_BUILD_TYPE=Debug -DLauncher_LAYOUT=lin-system -G Ninja
- name: Build
run: |
- cmake --build build
+ cmake --build ${{ env.BUILD_DIR }}
- name: Install
+ if: runner.os != 'Linux'
+ run: |
+ cmake --install ${{ env.BUILD_DIR }}
+
+ - name: Install for AppImage on Linux
+ if: runner.os == 'Linux'
+ run: |
+ DESTDIR=${{ env.INSTALL_DIR }} cmake --install ${{ env.BUILD_DIR }}
+
+ - name: Bundle AppImage
+ if: runner.os == 'Linux'
+ shell: bash
run: |
- cmake --install build
+ export OUTPUT="PolyMC-${{ github.sha }}-x86_64.AppImage"
+
+ chmod +x linuxdeploy-*.AppImage
+
+ mkdir -p ${{ env.INSTALL_DIR }}/usr/lib/jvm/java-{8,17}-openjdk
+
+ cp -r ${{ github.workspace }}/JREs/jre8/* ${{ env.INSTALL_DIR }}/usr/lib/jvm/java-8-openjdk
+
+ cp -r ${{ github.workspace }}/JREs/jre17/* ${{ env.INSTALL_DIR }}/usr/lib/jvm/java-17-openjdk
+
+ export LD_LIBRARY_PATH="${LD_LIBRARY_PATH}:${{ env.INSTALL_DIR }}/usr/lib"
+ LD_LIBRARY_PATH="${LD_LIBRARY_PATH}:${{ env.INSTALL_DIR }}/usr/lib/jvm/java-8-openjdk/lib/amd64/server"
+ LD_LIBRARY_PATH="${LD_LIBRARY_PATH}:${{ env.INSTALL_DIR }}/usr/lib/jvm/java-8-openjdk/lib/amd64"
+ LD_LIBRARY_PATH="${LD_LIBRARY_PATH}:${{ env.INSTALL_DIR }}/usr/lib/jvm/java-17-openjdk/lib/server"
+ LD_LIBRARY_PATH="${LD_LIBRARY_PATH}:${{ env.INSTALL_DIR }}/usr/lib/jvm/java-17-openjdk/lib"
+
+ ./linuxdeploy-x86_64.AppImage --appdir ${{ env.INSTALL_DIR }} --output appimage --plugin qt -i ${{ env.INSTALL_DIR }}/usr/share/icons/hicolor/scalable/apps/org.polymc.PolyMC.svg
- - name: Install OpenSSL libs
+ - name: Run windeployqt
if: runner.os == 'Windows'
run: |
- python -m pip install --upgrade pip
- python -m pip install aqtinstall==2.0.5
- python -m aqt install-tool -O "${{ github.workspace }}\Qt\" windows desktop tools_openssl_x64
- copy "${{ github.workspace }}\Qt\Tools\OpenSSL\Win_x64\bin\libssl-1_1-x64.dll" "${{ github.workspace }}\install\"
- copy "${{ github.workspace }}\Qt\Tools\OpenSSL\Win_x64\bin\libcrypto-1_1-x64.dll" "${{ github.workspace }}\install\"
+ windeployqt --no-translations "${{ 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
- name: chmod binary on macOS
if: runner.os == 'macOS'
run: |
- chmod +x "${{ github.workspace }}/install/PolyMC.app/Contents/MacOS/polymc"
+ chmod +x "${{ github.workspace }}/${{ env.INSTALL_DIR }}/PolyMC.app/Contents/MacOS/polymc"
- name: tar bundle on macOS
if: runner.os == 'macOS'
run: |
- cd install
+ cd ${{ env.INSTALL_DIR }}
tar -czf ../polymc.tar.gz *
- - name: Upload package for Linux and Windows
- if: runner.os != 'macOS'
+ - name: Upload AppImage for Linux
+ if: runner.os == 'Linux'
+ uses: actions/upload-artifact@v2
+ with:
+ name: PolyMC-${{ github.sha }}-x86_64.AppImage
+ path: PolyMC-${{ github.sha }}-x86_64.AppImage
+
+ - name: Upload package for Windows
+ if: runner.os == 'Windows'
uses: actions/upload-artifact@v2
with:
- name: polymc-${{ matrix.os }}-portable
- path: install/**
+ name: polymc-${{ runner.os }}-${{ github.sha }}-portable
+ path: ${{ env.INSTALL_DIR }}/**
- name: Upload package for macOS
if: runner.os == 'macOS'
uses: actions/upload-artifact@v2
with:
- name: polymc-${{ matrix.os }}-portable
+ name: polymc-${{ runner.os }}-${{ github.sha }}-portable
path: polymc.tar.gz
diff --git a/BUILD.md b/BUILD.md
index 9872e9e7..3b6e6446 100644
--- a/BUILD.md
+++ b/BUILD.md
@@ -20,9 +20,9 @@ git submodule update
The rest of the documentation assumes you have already cloned the repository.
-# Linux
+# Linux and FreeBSD
-Getting the project to build and run on Linux is easy if you use any modern and up-to-date linux distribution.
+Getting the project to build and run on Linux is easy if you use any modern and up-to-date linux distribution. If you're using FreeBSD you should use 13.0-RELEASE or newer.
## Build dependencies
- A C++ compiler capable of building C++11 code.
@@ -31,6 +31,7 @@ Getting the project to build and run on Linux is easy if you use any modern and
- zlib (`zlib1g-dev` on Debian-based system)
- Java JDK (`openjdk-17-jdk`on Debian-based system)
- GL headers (`libgl1-mesa-dev` on Debian-based system)
+- games/lwjgl port if using FreeBSD
You can use IDEs like KDevelop or QtCreator to open the CMake project if you want to work on the code.
@@ -54,7 +55,7 @@ This is the preferred method for installation, and is suitable for packages.
# configure everything
cmake -S . -B build \
  -DCMAKE_BUILD_TYPE=Release \
- -DCMAKE_INSTALL_PREFIX="/usr" \ # Use "/usr" for packages, otherwise, leave it at the default "/usr/local".
+ -DCMAKE_INSTALL_PREFIX="/usr" \ # Use "/usr" when building Linux packages. If building on FreeBSD or not for package, use "/usr/local"
-DLauncher_LAYOUT=lin-system
cd build
make -j$(nproc) install # Optionally specify DESTDIR for packages (i.e. DESTDIR=${pkgdir})
@@ -72,7 +73,7 @@ makedeb -s
The deb will be located in the directory the repo was cloned in.
-### Building a .rpm
+### Building an .rpm
Build dependencies are automatically installed using `dnf`, but you do need the `rpmdevtools` package (on Fedora)
in order to fetch sources and setup your tree.
@@ -94,6 +95,30 @@ rpmbuild -bb polymc.spec
The path to the rpm packages will be printed when the build is complete.
+### Building a Slackware package
+
+To build a Slackware package, first install [qt5 SlackBuild](http://slackbuilds.org/repository/14.2/libraries/qt5/) (on 15.0 and newer installed by defualt), then set up a [JDK](https://codeberg.org/glowiak/SlackBuilds/raw/branch/master/tgz/adoptium-jdk8.tar.gz).
+
+If you're using Slackware 14.2, update cmake with these commands:
+
+```
+mkdir -p /tmp/SBo
+cd /tmp/SBo
+wget -c https://github.com/Kitware/CMake/releases/download/v3.22.2/cmake-3.22.2.tar.gz
+tar xzvf cmake-3.22.2.tar.gz
+cd cmake-3.22.2
+./configure --prefix=/usr
+make
+sudo make install
+```
+
+Next, download the [SlackBuild](https://codeberg.org/glowiak/SlackBuilds/raw/branch/master/tgz/polymc.tar.gz), unpack it and type in extracted directory:
+
+```
+sudo ./polymc.SlackBuild # script will do everything, just sit up and wait
+sudo /sbin/installpkg /tmp/polymc-version-arch-1_SBo.tgz # install the created package
+```
+
### Building a flatpak
You don't need to clone the entire PolyMC repo for this; the flatpak file handles that.
@@ -273,3 +298,44 @@ Remember to replace `/path/to/Qt/` with the actual path. For newer Qt installati
**Note:** The final app bundle may not run due to code signing issues, which
need to be fixed with `codesign -fs -`.
+
+# OpenBSD
+
+Tested on OpenBSD 7.0-alpha i386, on older should work too
+
+## Build dependencies
+- A C++ compiler capable of building C++11 code (included in base system)
+- Qt Development tools 5.6 or newer ([meta/qt5](https://openports.se/meta/qt5))
+- cmake 3.1 or newer ([devel/cmake](https://openports.se/devel/cmake))
+- zlib (included in base system)
+- Java JDK ([devel/jdk-1.8](https://openports.se/devel/jdk/1.8))
+- GL headers (included in base system)
+- lwjgl ([games/lwjgl](https://openports.se/games/lwjgl) and [games/lwjgl3](https://openports.se/games/lwjgl3))
+
+You can use IDEs like KDevelop or QtCreator to open the CMake project if you want to work on the code.
+
+### Building a portable binary
+
+```sh
+mkdir install
+# configure the project
+cmake -S . -B build \
+ -DCMAKE_INSTALL_PREFIX=./install -DCMAKE_PREFIX_PATH=/usr/local/lib/qt5/cmake
+# build
+cd build
+make -j$(nproc) install
+```
+
+### Building & Installing to the System
+
+This is the preferred method for installation, and is suitable for packages.
+
+```sh
+# configure everything
+cmake -S . -B build \
+  -DCMAKE_BUILD_TYPE=Release \
+ -DCMAKE_INSTALL_PREFIX="/usr/local" \ # /usr/local is default in OpenBSD and FreeBSD
+ -DLauncher_LAYOUT=lin-system -DCMAKE_PREFIX_PATH=/usr/local/lib/qt5/cmake # use linux layout and point to qt5 libs
+cd build
+make -j$(nproc) install # Optionally specify DESTDIR for packages (i.e. DESTDIR=${pkgdir})
+```
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 738a1a5a..74a63614 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -45,10 +45,14 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DQT_NO_DEPRECATED_WARNINGS=Y")
##################################### Set Application options #####################################
+######## Set URLs ########
+set(Launcher_NEWS_RSS_URL "https://polymc.github.io/feed/feed.xml" CACHE STRING "URL to fetch PolyMC's news RSS feed from.")
+set(Launcher_NEWS_OPEN_URL "https://polymc.github.io/news/" CACHE STRING "URL that gets opened when the user clicks 'More News'")
+
######## Set version numbers ########
set(Launcher_VERSION_MAJOR 1)
set(Launcher_VERSION_MINOR 0)
-set(Launcher_VERSION_HOTFIX 5)
+set(Launcher_VERSION_HOTFIX 6)
# Build number
set(Launcher_VERSION_BUILD -1 CACHE STRING "Build number. -1 for no build number.")
@@ -74,6 +78,9 @@ set(Launcher_MSA_CLIENT_ID "17b47edd-c884-4997-926d-9e7f9a6b4647" CACHE STRING "
# Bug tracker URL
set(Launcher_BUG_TRACKER_URL "https://github.com/PolyMC/PolyMC/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.")
+
# Discord URL
set(Launcher_DISCORD_URL "https://discord.gg/Z52pwxWCHP" CACHE STRING "URL for the Discord guild.")
@@ -94,6 +101,8 @@ message(STATUS "Git commit: ${Launcher_GIT_COMMIT}")
message(STATUS "Git refspec: ${Launcher_GIT_REFSPEC}")
set(Launcher_RELEASE_VERSION_NAME "${Launcher_VERSION_MAJOR}.${Launcher_VERSION_MINOR}.${Launcher_VERSION_HOTFIX}")
+string(TIMESTAMP TODAY "%Y-%m-%d")
+set(Launcher_RELEASE_TIMESTAMP "${TODAY}")
#### Custom target to just print the version.
add_custom_target(version echo "Version: ${Launcher_RELEASE_VERSION_NAME}")
@@ -251,11 +260,9 @@ endif()
include(ExternalProject)
set_directory_properties(PROPERTIES EP_BASE External)
-option(NBT_BUILD_SHARED "Build NBT shared library" ON)
+option(NBT_BUILD_SHARED "Build NBT shared library" OFF)
option(NBT_USE_ZLIB "Build NBT library with zlib support" OFF)
option(NBT_BUILD_TESTS "Build NBT library tests" OFF) #FIXME: fix unit tests.
-set(NBT_NAME Launcher_nbt++)
-set(NBT_DEST_DIR ${LIBRARY_DEST_DIR})
add_subdirectory(libraries/libnbtplusplus)
add_subdirectory(libraries/systeminfo) # system information library
diff --git a/README.md b/README.md
index b6ed2176..b7df751c 100644
--- a/README.md
+++ b/README.md
@@ -6,7 +6,7 @@
PolyMC is a custom launcher for Minecraft that focuses on predictability, long term stability and simplicity.
-This is a **fork** of the MultiMC Launcher and not endorsed by MultiMC. The PolyMC community felt that the maintainer was not acting in the spirit of Free Software so this fork was made. Read "[Why was this fork made?](https://github.com/PolyMC/PolyMC/wiki/FAQ)" on the wiki for more details.
+This is a **fork** of the MultiMC Launcher and not endorsed by MultiMC. The PolyMC community felt that the maintainer was not acting in the spirit of Free Software so this fork was made.
<br>
# Installation
@@ -111,8 +111,6 @@ If you are too lazy to do all these steps, you can just download [a prebuild x86
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.
-
-
## <img src="https://www.vectorlogo.zone/logos/freebsd/freebsd-icon.svg" height="20" /> FreeBSD
For FreeBSD available are:
@@ -172,7 +170,7 @@ In general, in order of importance:
## Translations
-TODO
+The translation effort for PolyMC is hosted on [Weblate](https://hosted.weblate.org/projects/polymc/polymc/) and information about translating PolyMC is available at https://github.com/PolyMC/Translations
## Forking/Redistributing/Custom builds policy
diff --git a/buildconfig/BuildConfig.cpp.in b/buildconfig/BuildConfig.cpp.in
index 2595f78b..0ffc9326 100644
--- a/buildconfig/BuildConfig.cpp.in
+++ b/buildconfig/BuildConfig.cpp.in
@@ -12,6 +12,7 @@ Config::Config()
LAUNCHER_DOMAIN = "@Launcher_Domain@";
LAUNCHER_CONFIGFILE = "@Launcher_ConfigFile@";
LAUNCHER_GIT = "@Launcher_Git@";
+ LAUNCHER_DESKTOPFILENAME = "@Launcher_DesktopFileName@";
USER_AGENT = "@Launcher_UserAgent@";
USER_AGENT_UNCACHED = USER_AGENT + " (Uncached)";
@@ -29,24 +30,32 @@ Config::Config()
GIT_COMMIT = "@Launcher_GIT_COMMIT@";
GIT_REFSPEC = "@Launcher_GIT_REFSPEC@";
- if(GIT_REFSPEC.startsWith("refs/heads/") && !UPDATER_BASE.isEmpty() && !BUILD_PLATFORM.isEmpty() && VERSION_BUILD >= 0)
+ if(GIT_REFSPEC.startsWith("refs/heads/"))
{
VERSION_CHANNEL = GIT_REFSPEC;
VERSION_CHANNEL.remove("refs/heads/");
- UPDATER_ENABLED = true;
+ if(!UPDATER_BASE.isEmpty() && !BUILD_PLATFORM.isEmpty() && VERSION_BUILD >= 0) {
+ UPDATER_ENABLED = true;
+ }
+ }
+ else if (!GIT_COMMIT.isEmpty())
+ {
+ VERSION_CHANNEL = GIT_COMMIT.mid(0, 8);
}
else
{
- VERSION_CHANNEL = QObject::tr("custom");
+ VERSION_CHANNEL = QObject::tr("unknown");
}
VERSION_STR = "@Launcher_VERSION_STRING@";
NEWS_RSS_URL = "@Launcher_NEWS_RSS_URL@";
+ NEWS_OPEN_URL = "@Launcher_NEWS_OPEN_URL@";
IMGUR_CLIENT_ID = "@Launcher_IMGUR_CLIENT_ID@";
MSA_CLIENT_ID = "@Launcher_MSA_CLIENT_ID@";
META_URL = "@Launcher_META_URL@";
BUG_TRACKER_URL = "@Launcher_BUG_TRACKER_URL@";
+ TRANSLATIONS_URL = "@Launcher_TRANSLATIONS_URL@";
DISCORD_URL = "@Launcher_DISCORD_URL@";
SUBREDDIT_URL = "@Launcher_SUBREDDIT_URL@";
}
diff --git a/buildconfig/BuildConfig.h b/buildconfig/BuildConfig.h
index d09d5288..111381ab 100644
--- a/buildconfig/BuildConfig.h
+++ b/buildconfig/BuildConfig.h
@@ -14,6 +14,7 @@ public:
QString LAUNCHER_DOMAIN;
QString LAUNCHER_CONFIGFILE;
QString LAUNCHER_GIT;
+ QString LAUNCHER_DESKTOPFILENAME;
/// The major version number.
int VERSION_MAJOR;
@@ -68,6 +69,11 @@ public:
QString NEWS_RSS_URL;
/**
+ * URL that gets opened when the user clicks "More News"
+ */
+ QString NEWS_OPEN_URL;
+
+ /**
* Client ID you can get from Imgur when you register an application
*/
QString IMGUR_CLIENT_ID;
@@ -83,6 +89,7 @@ public:
QString META_URL;
QString BUG_TRACKER_URL;
+ QString TRANSLATIONS_URL;
QString DISCORD_URL;
QString SUBREDDIT_URL;
@@ -91,7 +98,7 @@ public:
QString AUTH_BASE = "https://authserver.mojang.com/";
QString IMGUR_BASE_URL = "https://api.imgur.com/3/";
QString FMLLIBS_BASE_URL = "https://files.multimc.org/fmllibs/";
- QString TRANSLATIONS_BASE_URL = "https://files.multimc.org/translations/";
+ QString TRANSLATIONS_BASE_URL = "https://meta.polymc.org/translations/";
QString MODPACKSCH_API_BASE_URL = "https://api.modpacks.ch/";
diff --git a/launcher/Application.cpp b/launcher/Application.cpp
index 7050e5dc..a3d6216e 100644
--- a/launcher/Application.cpp
+++ b/launcher/Application.cpp
@@ -14,7 +14,7 @@
#include "ui/pages/global/ProxyPage.h"
#include "ui/pages/global/ExternalToolsPage.h"
#include "ui/pages/global/AccountListPage.h"
-#include "ui/pages/global/PastePage.h"
+#include "ui/pages/global/APIPage.h"
#include "ui/pages/global/CustomCommandsPage.h"
#include "ui/themes/ITheme.h"
@@ -187,7 +187,9 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv)
setApplicationName(BuildConfig.LAUNCHER_NAME);
setApplicationDisplayName(BuildConfig.LAUNCHER_DISPLAYNAME);
setApplicationVersion(BuildConfig.printableVersionString());
-
+ #if (QT_VERSION >= QT_VERSION_CHECK(5,7,0))
+ setDesktopFileName(BuildConfig.LAUNCHER_DESKTOPFILENAME);
+ #endif
startTime = QDateTime::currentDateTime();
#ifdef Q_OS_LINUX
@@ -311,7 +313,7 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv)
dataPath = xdgDataHome + "/polymc";
adjustedBy += "XDG standard " + dataPath;
#elif defined(Q_OS_MAC)
- QDir foo(FS::PathCombine(applicationDirPath(), "../../Data"));
+ QDir foo(FS::PathCombine(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation), ".."));
dataPath = foo.absolutePath();
adjustedBy += "Fallback to special Mac location " + dataPath;
#else
@@ -529,10 +531,8 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv)
#elif defined(Q_OS_WIN32)
m_rootPath = binPath;
#elif defined(Q_OS_MAC)
- QDir foo(FS::PathCombine(binPath, "../.."));
+ QDir foo(FS::PathCombine(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation), ".."));
m_rootPath = foo.absolutePath();
- // on macOS, touch the root to force Finder to reload the .app metadata (and fix any icon change issues)
- FS::updateTimestamp(m_rootPath);
#endif
#ifdef MULTIMC_JARS_LOCATION
@@ -719,6 +719,9 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv)
m_settings->registerSetting("CloseAfterLaunch", false);
+ // Custom MSA credentials
+ m_settings->registerSetting("MSAClientIDOverride", "");
+
// Init page provider
{
m_globalSettingsProvider = std::make_shared<GenericPageProvider>(tr("Settings"));
@@ -730,7 +733,7 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv)
m_globalSettingsProvider->addPage<ProxyPage>();
m_globalSettingsProvider->addPage<ExternalToolsPage>();
m_globalSettingsProvider->addPage<AccountListPage>();
- m_globalSettingsProvider->addPage<PastePage>();
+ m_globalSettingsProvider->addPage<APIPage>();
}
qDebug() << "<> Settings loaded.";
}
@@ -1516,3 +1519,13 @@ QString Application::getJarsPath()
}
return m_jarsPath;
}
+
+QString Application::getMSAClientID()
+{
+ QString clientIDOverride = m_settings->get("MSAClientIDOverride").toString();
+ if (!clientIDOverride.isEmpty()) {
+ return clientIDOverride;
+ }
+
+ return BuildConfig.MSA_CLIENT_ID;
+}
diff --git a/launcher/Application.h b/launcher/Application.h
index c1cd8224..fb41d647 100644
--- a/launcher/Application.h
+++ b/launcher/Application.h
@@ -117,6 +117,8 @@ public:
QString getJarsPath();
+ QString getMSAClientID();
+
/// this is the root of the 'installation'. Used for automatic updates
const QString &root() {
return m_rootPath;
diff --git a/launcher/CMakeLists.txt b/launcher/CMakeLists.txt
index f4c3a9bc..90149c3b 100644
--- a/launcher/CMakeLists.txt
+++ b/launcher/CMakeLists.txt
@@ -181,6 +181,15 @@ set(NOTIFICATIONS_SOURCES
notifications/NotificationChecker.cpp
)
+# Backend for the news bar... there's usually no news.
+set(NEWS_SOURCES
+ # News System
+ news/NewsChecker.h
+ news/NewsChecker.cpp
+ news/NewsEntry.h
+ news/NewsEntry.cpp
+)
+
# Icon interface
set(ICONS_SOURCES
# Icons System and related code
@@ -714,8 +723,8 @@ SET(LAUNCHER_SOURCES
ui/pages/global/LauncherPage.h
ui/pages/global/ProxyPage.cpp
ui/pages/global/ProxyPage.h
- ui/pages/global/PastePage.cpp
- ui/pages/global/PastePage.h
+ ui/pages/global/APIPage.cpp
+ ui/pages/global/APIPage.h
# GUI - platform pages
ui/pages/modplatform/VanillaPage.cpp
@@ -862,7 +871,7 @@ qt5_wrap_ui(LAUNCHER_UI
ui/pages/global/AccountListPage.ui
ui/pages/global/JavaPage.ui
ui/pages/global/LauncherPage.ui
- ui/pages/global/PastePage.ui
+ ui/pages/global/APIPage.ui
ui/pages/global/ProxyPage.ui
ui/pages/global/MinecraftPage.ui
ui/pages/global/ExternalToolsPage.ui
@@ -932,7 +941,7 @@ add_library(Launcher_logic STATIC ${LOGIC_SOURCES} ${LAUNCHER_SOURCES} ${LAUNCHE
target_link_libraries(Launcher_logic
systeminfo
Launcher_classparser
- ${NBT_NAME}
+ nbt++
${ZLIB_LIBRARIES}
optional-bare
tomlc99
@@ -950,7 +959,7 @@ target_link_libraries(Launcher_logic
Launcher_iconfix
QuaZip::QuaZip
hoedown
- Launcher_rainbow
+ PolyMC_rainbow
LocalPeer
)
diff --git a/launcher/InstancePageProvider.h b/launcher/InstancePageProvider.h
index 2af90b91..97eeab8c 100644
--- a/launcher/InstancePageProvider.h
+++ b/launcher/InstancePageProvider.h
@@ -37,7 +37,7 @@ public:
if(onesix)
{
values.append(new VersionPage(onesix.get()));
- auto modsPage = new ModFolderPage(onesix.get(), onesix->loaderModList(), "mods", "loadermods", tr("Loader mods"), "Loader-mods");
+ 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"));
@@ -74,3 +74,4 @@ public:
protected:
InstancePtr inst;
};
+
diff --git a/launcher/UpdateController.cpp b/launcher/UpdateController.cpp
index f9b7d349..c02cd1e7 100644
--- a/launcher/UpdateController.cpp
+++ b/launcher/UpdateController.cpp
@@ -93,7 +93,7 @@ void UpdateController::installUpdates()
qDebug() << "Installing updates.";
#ifdef Q_OS_WIN
QString finishCmd = QApplication::applicationFilePath();
-#elif defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD)
+#elif defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD) || defined (Q_OS_OPENBSD)
QString finishCmd = FS::PathCombine(m_root, BuildConfig.LAUNCHER_NAME);
#elif defined Q_OS_MAC
QString finishCmd = QApplication::applicationFilePath();
diff --git a/launcher/minecraft/auth/steps/MSAStep.cpp b/launcher/minecraft/auth/steps/MSAStep.cpp
index bc10aa4e..779aee43 100644
--- a/launcher/minecraft/auth/steps/MSAStep.cpp
+++ b/launcher/minecraft/auth/steps/MSAStep.cpp
@@ -14,7 +14,7 @@ using Activity = Katabasis::Activity;
MSAStep::MSAStep(AccountData* data, Action action) : AuthStep(data), m_action(action) {
OAuth2::Options opts;
opts.scope = "XboxLive.signin offline_access";
- opts.clientIdentifier = BuildConfig.MSA_CLIENT_ID;
+ opts.clientIdentifier = APPLICATION->getMSAClientID();
opts.authorizationUrl = "https://login.microsoftonline.com/consumers/oauth2/v2.0/devicecode";
opts.accessTokenUrl = "https://login.microsoftonline.com/consumers/oauth2/v2.0/token";
diff --git a/launcher/news/NewsChecker.cpp b/launcher/news/NewsChecker.cpp
new file mode 100644
index 00000000..6724950f
--- /dev/null
+++ b/launcher/news/NewsChecker.cpp
@@ -0,0 +1,132 @@
+/* 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 "NewsChecker.h"
+
+#include <QByteArray>
+#include <QDomDocument>
+
+#include <QDebug>
+
+NewsChecker::NewsChecker(shared_qobject_ptr<QNetworkAccessManager> network, const QString& feedUrl)
+{
+ m_network = network;
+ m_feedUrl = feedUrl;
+}
+
+void NewsChecker::reloadNews()
+{
+ // Start a netjob to download the RSS feed and call rssDownloadFinished() when it's done.
+ if (isLoadingNews())
+ {
+ qDebug() << "Ignored request to reload news. Currently reloading already.";
+ return;
+ }
+
+ qDebug() << "Reloading news.";
+
+ NetJob* job = new NetJob("News RSS Feed", m_network);
+ job->addNetAction(Net::Download::makeByteArray(m_feedUrl, &newsData));
+ QObject::connect(job, &NetJob::succeeded, this, &NewsChecker::rssDownloadFinished);
+ QObject::connect(job, &NetJob::failed, this, &NewsChecker::rssDownloadFailed);
+ m_newsNetJob.reset(job);
+ job->start();
+}
+
+void NewsChecker::rssDownloadFinished()
+{
+ // Parse the XML file and process the RSS feed entries.
+ qDebug() << "Finished loading RSS feed.";
+
+ m_newsNetJob.reset();
+ QDomDocument doc;
+ {
+ // Stuff to store error info in.
+ QString errorMsg = "Unknown error.";
+ int errorLine = -1;
+ int errorCol = -1;
+
+ // Parse the XML.
+ if (!doc.setContent(newsData, false, &errorMsg, &errorLine, &errorCol))
+ {
+ QString fullErrorMsg = QString("Error parsing RSS feed XML. %s at %d:%d.").arg(errorMsg, errorLine, errorCol);
+ fail(fullErrorMsg);
+ newsData.clear();
+ return;
+ }
+ newsData.clear();
+ }
+
+ // If the parsing succeeded, read it.
+ QDomNodeList items = doc.elementsByTagName("entry");
+ m_newsEntries.clear();
+ for (int i = 0; i < items.length(); i++)
+ {
+ QDomElement element = items.at(i).toElement();
+ NewsEntryPtr entry;
+ entry.reset(new NewsEntry());
+ QString errorMsg = "An unknown error occurred.";
+ if (NewsEntry::fromXmlElement(element, entry.get(), &errorMsg))
+ {
+ qDebug() << "Loaded news entry" << entry->title;
+ m_newsEntries.append(entry);
+ }
+ else
+ {
+ qWarning() << "Failed to load news entry at index" << i << ":" << errorMsg;
+ }
+ }
+
+ succeed();
+}
+
+void NewsChecker::rssDownloadFailed(QString reason)
+{
+ // Set an error message and fail.
+ fail(tr("Failed to load news RSS feed:\n%1").arg(reason));
+}
+
+
+QList<NewsEntryPtr> NewsChecker::getNewsEntries() const
+{
+ return m_newsEntries;
+}
+
+bool NewsChecker::isLoadingNews() const
+{
+ return m_newsNetJob.get() != nullptr;
+}
+
+QString NewsChecker::getLastLoadErrorMsg() const
+{
+ return m_lastLoadError;
+}
+
+void NewsChecker::succeed()
+{
+ m_lastLoadError = "";
+ qDebug() << "News loading succeeded.";
+ m_newsNetJob.reset();
+ emit newsLoaded();
+}
+
+void NewsChecker::fail(const QString& errorMsg)
+{
+ m_lastLoadError = errorMsg;
+ qDebug() << "Failed to load news:" << errorMsg;
+ m_newsNetJob.reset();
+ emit newsLoadingFailed(errorMsg);
+}
+
diff --git a/launcher/news/NewsChecker.h b/launcher/news/NewsChecker.h
new file mode 100644
index 00000000..8467a541
--- /dev/null
+++ b/launcher/news/NewsChecker.h
@@ -0,0 +1,105 @@
+/* Copyright 2013-2021 MultiMC Contributors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <QObject>
+#include <QString>
+#include <QList>
+
+#include <net/NetJob.h>
+
+#include "NewsEntry.h"
+
+class NewsChecker : public QObject
+{
+ Q_OBJECT
+public:
+ /*!
+ * Constructs a news reader to read from the given RSS feed URL.
+ */
+ NewsChecker(shared_qobject_ptr<QNetworkAccessManager> network, const QString& feedUrl);
+
+ /*!
+ * Returns the error message for the last time the news was loaded.
+ * Empty string if the last load was successful.
+ */
+ QString getLastLoadErrorMsg() const;
+
+ /*!
+ * Returns true if the news has been loaded successfully.
+ */
+ bool isNewsLoaded() const;
+
+ //! True if the news is currently loading. If true, reloadNews() will do nothing.
+ bool isLoadingNews() const;
+
+ /*!
+ * Returns a list of news entries.
+ */
+ QList<NewsEntryPtr> getNewsEntries() const;
+
+ /*!
+ * Reloads the news from the website's RSS feed.
+ * If the news is already loading, this does nothing.
+ */
+ void Q_SLOT reloadNews();
+
+signals:
+ /*!
+ * Signal fired after the news has finished loading.
+ */
+ void newsLoaded();
+
+ /*!
+ * Signal fired after the news fails to load.
+ */
+ void newsLoadingFailed(QString errorMsg);
+
+protected slots:
+ void rssDownloadFinished();
+ void rssDownloadFailed(QString reason);
+
+protected: /* data */
+ //! The URL for the RSS feed to fetch.
+ QString m_feedUrl;
+
+ //! List of news entries.
+ QList<NewsEntryPtr> m_newsEntries;
+
+ //! The network job to use to load the news.
+ NetJob::Ptr m_newsNetJob;
+
+ //! True if news has been loaded.
+ bool m_loadedNews;
+
+ QByteArray newsData;
+
+ /*!
+ * Gets the error message that was given last time the news was loaded.
+ * If the last news load succeeded, this will be an empty string.
+ */
+ QString m_lastLoadError;
+
+ shared_qobject_ptr<QNetworkAccessManager> m_network;
+
+protected slots:
+ /// Emits newsLoaded() and sets m_lastLoadError to empty string.
+ void succeed();
+
+ /// Emits newsLoadingFailed() and sets m_lastLoadError to the given message.
+ void fail(const QString& errorMsg);
+};
+
diff --git a/launcher/news/NewsEntry.cpp b/launcher/news/NewsEntry.cpp
new file mode 100644
index 00000000..137703d1
--- /dev/null
+++ b/launcher/news/NewsEntry.cpp
@@ -0,0 +1,65 @@
+/* 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 "NewsEntry.h"
+
+#include <QDomNodeList>
+#include <QVariant>
+
+NewsEntry::NewsEntry(QObject* parent) :
+ QObject(parent)
+{
+ this->title = tr("Untitled");
+ this->content = tr("No content.");
+ this->link = "";
+}
+
+NewsEntry::NewsEntry(const QString& title, const QString& content, const QString& link, QObject* parent) :
+ QObject(parent)
+{
+ this->title = title;
+ this->content = content;
+ this->link = link;
+}
+
+/*!
+ * Gets the text content of the given child element as a QVariant.
+ */
+inline QString childValue(const QDomElement& element, const QString& childName, QString defaultVal="")
+{
+ QDomNodeList nodes = element.elementsByTagName(childName);
+ if (nodes.count() > 0)
+ {
+ QDomElement element = nodes.at(0).toElement();
+ return element.text();
+ }
+ else
+ {
+ return defaultVal;
+ }
+}
+
+bool NewsEntry::fromXmlElement(const QDomElement& element, NewsEntry* entry, QString* errorMsg)
+{
+ QString title = childValue(element, "title", tr("Untitled"));
+ QString content = childValue(element, "description", tr("No content."));
+ QString link = childValue(element, "id");
+
+ entry->title = title;
+ entry->content = content;
+ entry->link = link;
+ return true;
+}
+
diff --git a/launcher/news/NewsEntry.h b/launcher/news/NewsEntry.h
new file mode 100644
index 00000000..1fe95623
--- /dev/null
+++ b/launcher/news/NewsEntry.h
@@ -0,0 +1,57 @@
+/* Copyright 2013-2021 MultiMC Contributors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <QObject>
+#include <QString>
+#include <QDomElement>
+#include <memory>
+
+class NewsEntry : public QObject
+{
+ Q_OBJECT
+
+public:
+ /*!
+ * Constructs an empty news entry.
+ */
+ explicit NewsEntry(QObject* parent=0);
+
+ /*!
+ * Constructs a new news entry.
+ * Note that content may contain HTML.
+ */
+ NewsEntry(const QString& title, const QString& content, const QString& link, QObject* parent=0);
+
+ /*!
+ * Attempts to load information from the given XML element into the given news entry pointer.
+ * If this fails, the function will return false and store an error message in the errorMsg pointer.
+ */
+ static bool fromXmlElement(const QDomElement& element, NewsEntry* entry, QString* errorMsg=0);
+
+
+ //! The post title.
+ QString title;
+
+ //! The post's content. May contain HTML.
+ QString content;
+
+ //! URL to the post.
+ QString link;
+};
+
+typedef std::shared_ptr<NewsEntry> NewsEntryPtr;
+
diff --git a/launcher/tools/MCEditTool.cpp b/launcher/tools/MCEditTool.cpp
index 21e1a3b0..2c1ec613 100644
--- a/launcher/tools/MCEditTool.cpp
+++ b/launcher/tools/MCEditTool.cpp
@@ -52,7 +52,7 @@ QString MCEditTool::getProgramPath()
#else
const QString mceditPath = path();
QDir mceditDir(mceditPath);
-#if defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD)
+#if defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD) || defined(Q_OS_OPENBSD)
if (mceditDir.exists("mcedit.sh"))
{
return mceditDir.absoluteFilePath("mcedit.sh");
diff --git a/launcher/translations/TranslationsModel.cpp b/launcher/translations/TranslationsModel.cpp
index 0fa82e35..250854d3 100644
--- a/launcher/translations/TranslationsModel.cpp
+++ b/launcher/translations/TranslationsModel.cpp
@@ -620,7 +620,7 @@ void TranslationsModel::downloadIndex()
d->m_index_job = new NetJob("Translations Index", APPLICATION->network());
MetaEntryPtr entry = APPLICATION->metacache()->resolveEntry("translations", "index_v2.json");
entry->setStale(true);
- d->m_index_task = Net::Download::makeCached(QUrl("https://files.multimc.org/translations/index_v2.json"), entry);
+ d->m_index_task = Net::Download::makeCached(QUrl(BuildConfig.TRANSLATIONS_BASE_URL + "index_v2.json"), entry);
d->m_index_job->addNetAction(d->m_index_task);
connect(d->m_index_job.get(), &NetJob::failed, this, &TranslationsModel::indexFailed);
connect(d->m_index_job.get(), &NetJob::succeeded, this, &TranslationsModel::indexReceived);
diff --git a/launcher/ui/MainWindow.cpp b/launcher/ui/MainWindow.cpp
index 202924ff..32b27afb 100644
--- a/launcher/ui/MainWindow.cpp
+++ b/launcher/ui/MainWindow.cpp
@@ -58,6 +58,7 @@
#include <BuildConfig.h>
#include <net/NetJob.h>
#include <net/Download.h>
+#include <news/NewsChecker.h>
#include <notifications/NotificationChecker.h>
#include <tools/BaseProfiler.h>
#include <updater/DownloadTask.h>
@@ -200,6 +201,7 @@ public:
//TranslatedAction actionRefresh;
TranslatedAction actionCheckUpdate;
TranslatedAction actionSettings;
+ TranslatedAction actionMoreNews;
TranslatedAction actionManageAccounts;
TranslatedAction actionLaunchInstance;
TranslatedAction actionRenameInstance;
@@ -244,6 +246,7 @@ public:
TranslatedToolbar mainToolBar;
TranslatedToolbar instanceToolBar;
+ TranslatedToolbar newsToolBar;
QVector<TranslatedToolbar *> all_toolbars;
bool m_kill = false;
@@ -426,6 +429,29 @@ public:
MainWindow->setStatusBar(statusBar);
}
+ void createNewsToolbar(QMainWindow *MainWindow)
+ {
+ newsToolBar = TranslatedToolbar(MainWindow);
+ newsToolBar->setObjectName(QStringLiteral("newsToolBar"));
+ newsToolBar->setMovable(false);
+ newsToolBar->setAllowedAreas(Qt::BottomToolBarArea);
+ newsToolBar->setIconSize(QSize(16, 16));
+ newsToolBar->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
+ newsToolBar->setFloatable(false);
+ newsToolBar->setWindowTitle(QT_TRANSLATE_NOOP("MainWindow", "News Toolbar"));
+
+ actionMoreNews = TranslatedAction(MainWindow);
+ actionMoreNews->setObjectName(QStringLiteral("actionMoreNews"));
+ actionMoreNews->setIcon(APPLICATION->getThemedIcon("news"));
+ actionMoreNews.setTextId(QT_TRANSLATE_NOOP("MainWindow", "More news..."));
+ actionMoreNews.setTooltipId(QT_TRANSLATE_NOOP("MainWindow", "Open the development blog to read more news about %1."));
+ all_actions.append(&actionMoreNews);
+ newsToolBar->addAction(actionMoreNews);
+
+ all_toolbars.append(&newsToolBar);
+ MainWindow->addToolBar(Qt::BottomToolBarArea, newsToolBar);
+ }
+
void createInstanceToolbar(QMainWindow *MainWindow)
{
instanceToolBar = TranslatedToolbar(MainWindow);
@@ -610,6 +636,7 @@ public:
MainWindow->setCentralWidget(centralWidget);
createStatusBar(MainWindow);
+ createNewsToolbar(MainWindow);
createInstanceToolbar(MainWindow);
retranslateUi(MainWindow);
@@ -664,6 +691,20 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new MainWindow
connect(secretEventFilter, &KonamiCode::triggered, this, &MainWindow::konamiTriggered);
}
+ // Add the news label to the news toolbar.
+ {
+ m_newsChecker.reset(new NewsChecker(APPLICATION->network(), BuildConfig.NEWS_RSS_URL));
+ newsLabel = new QToolButton();
+ newsLabel->setIcon(APPLICATION->getThemedIcon("news"));
+ newsLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
+ newsLabel->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
+ newsLabel->setFocusPolicy(Qt::NoFocus);
+ ui->newsToolBar->insertWidget(ui->actionMoreNews, newsLabel);
+ QObject::connect(newsLabel, &QAbstractButton::clicked, this, &MainWindow::newsButtonClicked);
+ QObject::connect(m_newsChecker.get(), &NewsChecker::newsLoaded, this, &MainWindow::updateNewsLabel);
+ updateNewsLabel();
+ }
+
// Create the instance list widget
{
view = new InstanceView(ui->centralWidget);
@@ -768,6 +809,13 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new MainWindow
// TODO: refresh accounts here?
// auto accounts = APPLICATION->accounts();
+ // load the news
+ {
+ m_newsChecker->reloadNews();
+ updateNewsLabel();
+ }
+
+
if(BuildConfig.UPDATER_ENABLED)
{
bool updatesAllowed = APPLICATION->updatesAreAllowed();
@@ -1141,6 +1189,29 @@ bool MainWindow::eventFilter(QObject *obj, QEvent *ev)
return QMainWindow::eventFilter(obj, ev);
}
+void MainWindow::updateNewsLabel()
+{
+ if (m_newsChecker->isLoadingNews())
+ {
+ newsLabel->setText(tr("Loading news..."));
+ newsLabel->setEnabled(false);
+ }
+ else
+ {
+ QList<NewsEntryPtr> entries = m_newsChecker->getNewsEntries();
+ if (entries.length() > 0)
+ {
+ newsLabel->setText(entries[0]->title);
+ newsLabel->setEnabled(true);
+ }
+ else
+ {
+ newsLabel->setText(tr("No news available."));
+ newsLabel->setEnabled(false);
+ }
+ }
+}
+
void MainWindow::updateAvailable(GoUpdate::Status status)
{
if(!APPLICATION->updatesAreAllowed())
@@ -1614,6 +1685,24 @@ void MainWindow::on_actionReportBug_triggered()
DesktopServices::openUrl(QUrl(BuildConfig.BUG_TRACKER_URL));
}
+void MainWindow::on_actionMoreNews_triggered()
+{
+ DesktopServices::openUrl(QUrl(BuildConfig.NEWS_OPEN_URL));
+}
+
+void MainWindow::newsButtonClicked()
+{
+ QList<NewsEntryPtr> entries = m_newsChecker->getNewsEntries();
+ if (entries.count() > 0)
+ {
+ DesktopServices::openUrl(QUrl(entries[0]->link));
+ }
+ else
+ {
+ DesktopServices::openUrl(QUrl(BuildConfig.NEWS_OPEN_URL));
+ }
+}
+
void MainWindow::on_actionAbout_triggered()
{
AboutDialog dialog(this);
diff --git a/launcher/ui/MainWindow.h b/launcher/ui/MainWindow.h
index 38d925a9..f6940ab0 100644
--- a/launcher/ui/MainWindow.h
+++ b/launcher/ui/MainWindow.h
@@ -27,6 +27,7 @@
#include "updater/GoUpdate.h"
class LaunchController;
+class NewsChecker;
class NotificationChecker;
class QToolButton;
class InstanceProxyModel;
@@ -108,6 +109,10 @@ private slots:
void on_actionReportBug_triggered();
+ void on_actionMoreNews_triggered();
+
+ void newsButtonClicked();
+
void on_actionLaunchInstance_triggered();
void on_actionLaunchInstanceOffline_triggered();
@@ -169,6 +174,8 @@ private slots:
void repopulateAccountsMenu();
+ void updateNewsLabel();
+
/*!
* Runs the DownloadTask and installs updates.
*/
@@ -198,12 +205,14 @@ private:
// these are managed by Qt's memory management model!
InstanceView *view = nullptr;
InstanceProxyModel *proxymodel = nullptr;
+ QToolButton *newsLabel = nullptr;
QLabel *m_statusLeft = nullptr;
QLabel *m_statusCenter = nullptr;
QMenu *accountMenu = nullptr;
QToolButton *accountMenuButton = nullptr;
KonamiCode * secretEventFilter = nullptr;
+ unique_qobject_ptr<NewsChecker> m_newsChecker;
unique_qobject_ptr<NotificationChecker> m_notificationChecker;
InstancePtr m_selectedInstance;
diff --git a/launcher/ui/pages/global/PastePage.cpp b/launcher/ui/pages/global/APIPage.cpp
index 7c69e1a4..ad79e00c 100644
--- a/launcher/ui/pages/global/PastePage.cpp
+++ b/launcher/ui/pages/global/APIPage.cpp
@@ -13,8 +13,8 @@
* limitations under the License.
*/
-#include "PastePage.h"
-#include "ui_PastePage.h"
+#include "APIPage.h"
+#include "ui_APIPage.h"
#include <QMessageBox>
#include <QFileDialog>
@@ -26,9 +26,9 @@
#include "tools/BaseProfiler.h"
#include "Application.h"
-PastePage::PastePage(QWidget *parent) :
+APIPage::APIPage(QWidget *parent) :
QWidget(parent),
- ui(new Ui::PastePage)
+ ui(new Ui::APIPage)
{
static QRegularExpression validUrlRegExp("https?://.+");
ui->setupUi(this);
@@ -37,26 +37,30 @@ PastePage::PastePage(QWidget *parent) :
loadSettings();
}
-PastePage::~PastePage()
+APIPage::~APIPage()
{
delete ui;
}
-void PastePage::loadSettings()
+void APIPage::loadSettings()
{
auto s = APPLICATION->settings();
QString pastebinURL = s->get("PastebinURL").toString();
ui->urlChoices->setCurrentText(pastebinURL);
+ QString msaClientID = s->get("MSAClientIDOverride").toString();
+ ui->msaClientID->setText(msaClientID);
}
-void PastePage::applySettings()
+void APIPage::applySettings()
{
auto s = APPLICATION->settings();
QString pastebinURL = ui->urlChoices->currentText();
s->set("PastebinURL", pastebinURL);
+ QString msaClientID = ui->msaClientID->text();
+ s->set("MSAClientIDOverride", msaClientID);
}
-bool PastePage::apply()
+bool APIPage::apply()
{
applySettings();
return true;
diff --git a/launcher/ui/pages/global/PastePage.h b/launcher/ui/pages/global/APIPage.h
index d475dfd9..9474ebbb 100644
--- a/launcher/ui/pages/global/PastePage.h
+++ b/launcher/ui/pages/global/APIPage.h
@@ -21,32 +21,32 @@
#include <Application.h>
namespace Ui {
-class PastePage;
+class APIPage;
}
-class PastePage : public QWidget, public BasePage
+class APIPage : public QWidget, public BasePage
{
Q_OBJECT
public:
- explicit PastePage(QWidget *parent = 0);
- ~PastePage();
+ explicit APIPage(QWidget *parent = 0);
+ ~APIPage();
QString displayName() const override
{
- return tr("Log Upload");
+ return tr("APIs");
}
QIcon icon() const override
{
- return APPLICATION->getThemedIcon("log");
+ return APPLICATION->getThemedIcon("worlds");
}
QString id() const override
{
- return "log-upload";
+ return "apis";
}
QString helpPage() const override
{
- return "Log-Upload";
+ return "APIs";
}
virtual bool apply() override;
@@ -55,6 +55,6 @@ private:
void applySettings();
private:
- Ui::PastePage *ui;
+ Ui::APIPage *ui;
};
diff --git a/launcher/ui/pages/global/PastePage.ui b/launcher/ui/pages/global/APIPage.ui
index 2d13a765..28c53b79 100644
--- a/launcher/ui/pages/global/PastePage.ui
+++ b/launcher/ui/pages/global/APIPage.ui
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
- <class>PastePage</class>
- <widget class="QWidget" name="PastePage">
+ <class>APIPage</class>
+ <widget class="QWidget" name="APIPage">
<property name="geometry">
<rect>
<x>0</x>
@@ -34,7 +34,7 @@
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
- <widget class="QGroupBox" name="groupBox_2">
+ <widget class="QGroupBox" name="groupBox_paste">
<property name="title">
<string>Pastebin URL</string>
</property>
@@ -101,6 +101,58 @@
</widget>
</item>
<item>
+ <widget class="QGroupBox" name="groupBox_msa">
+ <property name="title">
+ <string>Microsoft Authentication</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout_4">
+ <item>
+ <widget class="Line" name="line_2">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="label_3">
+ <property name="text">
+ <string>Note: you probably don't need to set this if logging in via Microsoft Authentication already works.</string>
+ </property>
+ <property name="textFormat">
+ <enum>Qt::RichText</enum>
+ </property>
+ <property name="wordWrap">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLineEdit" name="msaClientID">
+ <property name="placeholderText">
+ <string>(Default)</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="label_4">
+ <property name="text">
+ <string>Enter a custom client ID for Microsoft Authentication here. </string>
+ </property>
+ <property name="textFormat">
+ <enum>Qt::RichText</enum>
+ </property>
+ <property name="wordWrap">
+ <bool>true</bool>
+ </property>
+ <property name="openExternalLinks">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
@@ -108,7 +160,7 @@
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
- <height>216</height>
+ <height>40</height>
</size>
</property>
</spacer>
diff --git a/launcher/ui/pages/global/AccountListPage.cpp b/launcher/ui/pages/global/AccountListPage.cpp
index 396d320f..eb1ee8d3 100644
--- a/launcher/ui/pages/global/AccountListPage.cpp
+++ b/launcher/ui/pages/global/AccountListPage.cpp
@@ -73,7 +73,10 @@ AccountListPage::AccountListPage(QWidget *parent)
updateButtonStates();
// Xbox authentication won't work without a client identifier, so disable the button if it is missing
- ui->actionAddMicrosoft->setVisible(BuildConfig.MSA_CLIENT_ID.size() != 0);
+ if (APPLICATION->getMSAClientID().isEmpty()) {
+ ui->actionAddMicrosoft->setVisible(false);
+ ui->actionAddMicrosoft->setToolTip(tr("No Microsoft Authentication client ID was set."));
+ }
}
AccountListPage::~AccountListPage()
diff --git a/launcher/ui/pages/instance/LegacyUpgradePage.ui b/launcher/ui/pages/instance/LegacyUpgradePage.ui
index 4e803358..b22c03e5 100644
--- a/launcher/ui/pages/instance/LegacyUpgradePage.ui
+++ b/launcher/ui/pages/instance/LegacyUpgradePage.ui
@@ -26,7 +26,14 @@
<item>
<widget class="QTextBrowser" name="textBrowser">
<property name="html">
- <string>&lt;html&gt;&lt;body&gt;&lt;h1&gt;Upgrade is required&lt;/h1&gt;&lt;p&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&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&gt;Please report any issues on our &lt;a href=&quot;https://github.com/PolyMC/PolyMC/issues&quot;&gt;github issues page&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;There is also a &lt;a href=&quot;https://discord.gg/GtPmv93&quot;&gt;discord channel for testing here&lt;/a&gt;.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+ <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>
diff --git a/launcher/ui/pages/modplatform/flame/FlameModPage.cpp b/launcher/ui/pages/modplatform/flame/FlameModPage.cpp
index 80f3de19..a816c681 100644
--- a/launcher/ui/pages/modplatform/flame/FlameModPage.cpp
+++ b/launcher/ui/pages/modplatform/flame/FlameModPage.cpp
@@ -140,14 +140,15 @@ void FlameModPage::onSelectionChanged(QModelIndex first, QModelIndex second)
auto packProfile = ((MinecraftInstance *)m_instance)->getPackProfile();
QString mcVersion = packProfile->getComponentVersion("net.minecraft");
QString loaderString = (packProfile->getComponentVersion("net.minecraftforge").isEmpty()) ? "fabric" : "forge";
- for(const auto& version : current.versions) {
+ for(int i = 0; i < current.versions.size(); i++) {
+ auto version = current.versions[i];
if(!version.mcVersion.contains(mcVersion)){
continue;
}
- ui->versionSelectionBox->addItem(version.version, QVariant(version.downloadUrl));
+ ui->versionSelectionBox->addItem(version.version, QVariant(i));
}
if(ui->versionSelectionBox->count() == 0){
- ui->versionSelectionBox->addItem(tr("No Valid Version found!"), QVariant(""));
+ ui->versionSelectionBox->addItem(tr("No Valid Version found!"), QVariant(-1));
}
suggestCurrent();
@@ -156,11 +157,11 @@ void FlameModPage::onSelectionChanged(QModelIndex first, QModelIndex second)
}
else
{
- for(auto version : current.versions) {
- ui->versionSelectionBox->addItem(version.version, QVariant(version.downloadUrl));
+ for(int i = 0; i < current.versions.size(); i++) {
+ ui->versionSelectionBox->addItem(current.versions[i].version, QVariant(i));
}
if(ui->versionSelectionBox->count() == 0){
- ui->versionSelectionBox->addItem(tr("No Valid Version found!"), QVariant(""));
+ ui->versionSelectionBox->addItem(tr("No Valid Version found!"), QVariant(-1));
}
suggestCurrent();
}
@@ -173,22 +174,23 @@ void FlameModPage::suggestCurrent()
return;
}
- if (selectedVersion.isEmpty())
+ if (selectedVersion == -1)
{
dialog->setSuggestedMod();
return;
}
- dialog->setSuggestedMod(current.name, new ModDownloadTask(selectedVersion, current.versions.at(0).fileName ,dialog->mods));
+ auto version = current.versions[selectedVersion];
+ dialog->setSuggestedMod(current.name, new ModDownloadTask(version.downloadUrl, version.fileName , dialog->mods));
}
void FlameModPage::onVersionSelectionChanged(QString data)
{
if(data.isNull() || data.isEmpty())
{
- selectedVersion = "";
+ selectedVersion = -1;
return;
}
- selectedVersion = ui->versionSelectionBox->currentData().toString();
+ selectedVersion = ui->versionSelectionBox->currentData().toInt();
suggestCurrent();
}
diff --git a/launcher/ui/pages/modplatform/flame/FlameModPage.h b/launcher/ui/pages/modplatform/flame/FlameModPage.h
index 85c68620..8fa3248a 100644
--- a/launcher/ui/pages/modplatform/flame/FlameModPage.h
+++ b/launcher/ui/pages/modplatform/flame/FlameModPage.h
@@ -63,5 +63,5 @@ private:
FlameMod::ListModel* listModel = nullptr;
FlameMod::IndexedPack current;
- QString selectedVersion;
+ int selectedVersion = -1;
};
diff --git a/launcher/ui/pages/modplatform/modrinth/ModrinthModel.cpp b/launcher/ui/pages/modplatform/modrinth/ModrinthModel.cpp
index 71574156..5a18830a 100644
--- a/launcher/ui/pages/modplatform/modrinth/ModrinthModel.cpp
+++ b/launcher/ui/pages/modplatform/modrinth/ModrinthModel.cpp
@@ -3,12 +3,14 @@
#include "minecraft/MinecraftInstance.h"
#include "minecraft/PackProfile.h"
#include "ModrinthPage.h"
+#include "ui/dialogs/ModDownloadDialog.h"
#include <Json.h>
#include <MMCStrings.h>
#include <Version.h>
#include <QtMath>
+#include <QMessageBox>
namespace Modrinth {
@@ -250,6 +252,12 @@ void Modrinth::ListModel::searchRequestFinished()
void Modrinth::ListModel::searchRequestFailed(QString reason)
{
+ if(jobPtr->first()->m_reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt() == 409){
+ //409 Gone, notify user to update
+ QMessageBox::critical(nullptr, tr("Error"), tr("Modrinth API version too old!\nPlease update PolyMC!"));
+ //self-destruct
+ ((ModDownloadDialog *)((ModrinthPage *)parent())->parentWidget())->reject();
+ }
jobPtr.reset();
if(searchState == ResetRequested) {
diff --git a/launcher/ui/pages/modplatform/modrinth/ModrinthPage.cpp b/launcher/ui/pages/modplatform/modrinth/ModrinthPage.cpp
index ee3c9e76..c5a54c29 100644
--- a/launcher/ui/pages/modplatform/modrinth/ModrinthPage.cpp
+++ b/launcher/ui/pages/modplatform/modrinth/ModrinthPage.cpp
@@ -125,14 +125,15 @@ void ModrinthPage::onSelectionChanged(QModelIndex first, QModelIndex second)
auto packProfile = ((MinecraftInstance *)m_instance)->getPackProfile();
QString mcVersion = packProfile->getComponentVersion("net.minecraft");
QString loaderString = (packProfile->getComponentVersion("net.minecraftforge").isEmpty()) ? "fabric" : "forge";
- for(const auto& version : current.versions) {
+ for(int i = 0; i < current.versions.size(); i++) {
+ auto version = current.versions[i];
if(!version.mcVersion.contains(mcVersion) || !version.loaders.contains(loaderString)){
continue;
}
- ui->versionSelectionBox->addItem(version.version, QVariant(version.downloadUrl));
+ ui->versionSelectionBox->addItem(version.version, QVariant(i));
}
if(ui->versionSelectionBox->count() == 0){
- ui->versionSelectionBox->addItem(tr("No Valid Version found !"), QVariant(""));
+ ui->versionSelectionBox->addItem(tr("No Valid Version found !"), QVariant(-1));
}
suggestCurrent();
@@ -141,11 +142,11 @@ void ModrinthPage::onSelectionChanged(QModelIndex first, QModelIndex second)
}
else
{
- for(auto version : current.versions) {
- ui->versionSelectionBox->addItem(version.version, QVariant(version.downloadUrl));
+ for(int i = 0; i < current.versions.size(); i++) {
+ ui->versionSelectionBox->addItem(current.versions[i].version, QVariant(i));
}
if(ui->versionSelectionBox->count() == 0){
- ui->versionSelectionBox->addItem(tr("No Valid Version found !"), QVariant(""));
+ ui->versionSelectionBox->addItem(tr("No Valid Version found !"), QVariant(-1));
}
suggestCurrent();
}
@@ -158,22 +159,22 @@ void ModrinthPage::suggestCurrent()
return;
}
- if (selectedVersion.isEmpty())
+ if (selectedVersion == -1)
{
dialog->setSuggestedMod();
return;
}
-
- dialog->setSuggestedMod(current.name, new ModDownloadTask(selectedVersion, current.versions.at(0).fileName ,dialog->mods));
+ auto version = current.versions[selectedVersion];
+ dialog->setSuggestedMod(current.name, new ModDownloadTask(version.downloadUrl, version.fileName , dialog->mods));
}
void ModrinthPage::onVersionSelectionChanged(QString data)
{
if(data.isNull() || data.isEmpty())
{
- selectedVersion = "";
+ selectedVersion = -1;
return;
}
- selectedVersion = ui->versionSelectionBox->currentData().toString();
+ selectedVersion = ui->versionSelectionBox->currentData().toInt();
suggestCurrent();
}
diff --git a/launcher/ui/pages/modplatform/modrinth/ModrinthPage.h b/launcher/ui/pages/modplatform/modrinth/ModrinthPage.h
index 3748d836..3c517069 100644
--- a/launcher/ui/pages/modplatform/modrinth/ModrinthPage.h
+++ b/launcher/ui/pages/modplatform/modrinth/ModrinthPage.h
@@ -63,5 +63,5 @@ private:
Modrinth::ListModel* listModel = nullptr;
Modrinth::IndexedPack current;
- QString selectedVersion;
+ int selectedVersion = -1;
};
diff --git a/launcher/ui/widgets/LanguageSelectionWidget.cpp b/launcher/ui/widgets/LanguageSelectionWidget.cpp
index 964d2b7c..256b09da 100644
--- a/launcher/ui/widgets/LanguageSelectionWidget.cpp
+++ b/launcher/ui/widgets/LanguageSelectionWidget.cpp
@@ -5,6 +5,7 @@
#include <QHeaderView>
#include <QLabel>
#include "Application.h"
+#include "BuildConfig.h"
#include "translations/TranslationsModel.h"
#include "settings/Setting.h"
@@ -52,7 +53,7 @@ QString LanguageSelectionWidget::getSelectedLanguageKey() const
void LanguageSelectionWidget::retranslate()
{
QString text = tr("Don't see your language or the quality is poor?<br/><a href=\"%1\">Help us with translations!</a>")
- .arg("https://github.com/MultiMC/Launcher/wiki/Translating-MultiMC");
+ .arg(BuildConfig.TRANSLATIONS_URL);
helpUsLabel->setText(text);
}
diff --git a/libraries/iconfix/CMakeLists.txt b/libraries/iconfix/CMakeLists.txt
index 52a31c68..049879c4 100644
--- a/libraries/iconfix/CMakeLists.txt
+++ b/libraries/iconfix/CMakeLists.txt
@@ -12,17 +12,9 @@ internal/qiconloader.cpp
internal/qiconloader_p.h
)
-add_library(Launcher_iconfix SHARED ${ICONFIX_SOURCES})
+add_library(Launcher_iconfix ${ICONFIX_SOURCES})
target_include_directories(Launcher_iconfix PUBLIC ${CMAKE_CURRENT_SOURCE_DIR} "${CMAKE_CURRENT_BINARY_DIR}" )
target_link_libraries(Launcher_iconfix Qt5::Core Qt5::Widgets)
-set_target_properties(Launcher_iconfix PROPERTIES CXX_VISIBILITY_PRESET hidden VISIBILITY_INLINES_HIDDEN 1)
generate_export_header(Launcher_iconfix)
-
-# Install it
-install(
- TARGETS Launcher_iconfix
- RUNTIME DESTINATION ${LIBRARY_DEST_DIR}
- LIBRARY DESTINATION ${LIBRARY_DEST_DIR}
-) \ No newline at end of file
diff --git a/libraries/rainbow/CMakeLists.txt b/libraries/rainbow/CMakeLists.txt
index 833538e3..a07135c3 100644
--- a/libraries/rainbow/CMakeLists.txt
+++ b/libraries/rainbow/CMakeLists.txt
@@ -9,14 +9,14 @@ src/rainbow.cpp
)
add_definitions(-DRAINBOW_LIBRARY)
-add_library(Launcher_rainbow SHARED ${RAINBOW_SOURCES})
-target_include_directories(Launcher_rainbow PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include")
+add_library(PolyMC_rainbow SHARED ${RAINBOW_SOURCES})
+target_include_directories(PolyMC_rainbow PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include")
-target_link_libraries(Launcher_rainbow Qt5::Core Qt5::Gui)
+target_link_libraries(PolyMC_rainbow Qt5::Core Qt5::Gui)
# Install it
install(
- TARGETS Launcher_rainbow
+ TARGETS PolyMC_rainbow
RUNTIME DESTINATION ${LIBRARY_DEST_DIR}
LIBRARY DESTINATION ${LIBRARY_DEST_DIR}
)
diff --git a/program_info/CMakeLists.txt b/program_info/CMakeLists.txt
index 0466b893..f9d7621d 100644
--- a/program_info/CMakeLists.txt
+++ b/program_info/CMakeLists.txt
@@ -7,13 +7,14 @@ set(Launcher_DisplayName "${Launcher_CommonName}" PARENT_SCOPE)
set(Launcher_UserAgent "${Launcher_CommonName}/${Launcher_RELEASE_VERSION_NAME}" PARENT_SCOPE)
set(Launcher_ConfigFile "polymc.cfg" PARENT_SCOPE)
set(Launcher_Git "https://github.com/PolyMC/PolyMC" PARENT_SCOPE)
+set(Launcher_DesktopFileName "org.polymc.PolyMC.desktop" PARENT_SCOPE)
-set(Launcher_Desktop "program_info/org.polymc.polymc.desktop" PARENT_SCOPE)
+set(Launcher_Desktop "program_info/org.polymc.PolyMC.desktop" PARENT_SCOPE)
set(Launcher_MetaInfo "program_info/org.polymc.PolyMC.metainfo.xml" PARENT_SCOPE)
set(Launcher_SVG "program_info/org.polymc.PolyMC.svg" PARENT_SCOPE)
set(Launcher_Branding_ICNS "program_info/polymc.icns" PARENT_SCOPE)
set(Launcher_Branding_WindowsRC "program_info/polymc.rc" PARENT_SCOPE)
set(Launcher_Branding_LogoQRC "program_info/polymc.qrc" PARENT_SCOPE)
-configure_file(org.polymc.polymc.desktop.in org.polymc.polymc.desktop)
+configure_file(org.polymc.PolyMC.desktop.in org.polymc.PolyMC.desktop)
configure_file(org.polymc.PolyMC.metainfo.xml.in org.polymc.PolyMC.metainfo.xml)
diff --git a/program_info/LICENSE b/program_info/LICENSE
new file mode 100644
index 00000000..40cc6059
--- /dev/null
+++ b/program_info/LICENSE
@@ -0,0 +1,439 @@
+Attribution-NonCommercial-ShareAlike 4.0 International
+
+This license only applies to the logos and branding in this folder.
+
+=======================================================================
+
+Creative Commons Corporation ("Creative Commons") is not a law firm and
+does not provide legal services or legal advice. Distribution of
+Creative Commons public licenses does not create a lawyer-client or
+other relationship. Creative Commons makes its licenses and related
+information available on an "as-is" basis. Creative Commons gives no
+warranties regarding its licenses, any material licensed under their
+terms and conditions, or any related information. Creative Commons
+disclaims all liability for damages resulting from their use to the
+fullest extent possible.
+
+Using Creative Commons Public Licenses
+
+Creative Commons public licenses provide a standard set of terms and
+conditions that creators and other rights holders may use to share
+original works of authorship and other material subject to copyright
+and certain other rights specified in the public license below. The
+following considerations are for informational purposes only, are not
+exhaustive, and do not form part of our licenses.
+
+ Considerations for licensors: Our public licenses are
+ intended for use by those authorized to give the public
+ permission to use material in ways otherwise restricted by
+ copyright and certain other rights. Our licenses are
+ irrevocable. Licensors should read and understand the terms
+ and conditions of the license they choose before applying it.
+ Licensors should also secure all rights necessary before
+ applying our licenses so that the public can reuse the
+ material as expected. Licensors should clearly mark any
+ material not subject to the license. This includes other CC-
+ licensed material, or material used under an exception or
+ limitation to copyright. More considerations for licensors:
+ wiki.creativecommons.org/Considerations_for_licensors
+
+ Considerations for the public: By using one of our public
+ licenses, a licensor grants the public permission to use the
+ licensed material under specified terms and conditions. If
+ the licensor's permission is not necessary for any reason--for
+ example, because of any applicable exception or limitation to
+ copyright--then that use is not regulated by the license. Our
+ licenses grant only permissions under copyright and certain
+ other rights that a licensor has authority to grant. Use of
+ the licensed material may still be restricted for other
+ reasons, including because others have copyright or other
+ rights in the material. A licensor may make special requests,
+ such as asking that all changes be marked or described.
+ Although not required by our licenses, you are encouraged to
+ respect those requests where reasonable. More_considerations
+ for the public:
+ wiki.creativecommons.org/Considerations_for_licensees
+
+=======================================================================
+
+Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International
+Public License
+
+By exercising the Licensed Rights (defined below), You accept and agree
+to be bound by the terms and conditions of this Creative Commons
+Attribution-NonCommercial-ShareAlike 4.0 International Public License
+("Public License"). To the extent this Public License may be
+interpreted as a contract, You are granted the Licensed Rights in
+consideration of Your acceptance of these terms and conditions, and the
+Licensor grants You such rights in consideration of benefits the
+Licensor receives from making the Licensed Material available under
+these terms and conditions.
+
+
+Section 1 -- Definitions.
+
+ a. Adapted Material means material subject to Copyright and Similar
+ Rights that is derived from or based upon the Licensed Material
+ and in which the Licensed Material is translated, altered,
+ arranged, transformed, or otherwise modified in a manner requiring
+ permission under the Copyright and Similar Rights held by the
+ Licensor. For purposes of this Public License, where the Licensed
+ Material is a musical work, performance, or sound recording,
+ Adapted Material is always produced where the Licensed Material is
+ synched in timed relation with a moving image.
+
+ b. Adapter's License means the license You apply to Your Copyright
+ and Similar Rights in Your contributions to Adapted Material in
+ accordance with the terms and conditions of this Public License.
+
+ c. BY-NC-SA Compatible License means a license listed at
+ creativecommons.org/compatiblelicenses, approved by Creative
+ Commons as essentially the equivalent of this Public License.
+
+ d. Copyright and Similar Rights means copyright and/or similar rights
+ closely related to copyright including, without limitation,
+ performance, broadcast, sound recording, and Sui Generis Database
+ Rights, without regard to how the rights are labeled or
+ categorized. For purposes of this Public License, the rights
+ specified in Section 2(b)(1)-(2) are not Copyright and Similar
+ Rights.
+
+ e. Effective Technological Measures means those measures that, in the
+ absence of proper authority, may not be circumvented under laws
+ fulfilling obligations under Article 11 of the WIPO Copyright
+ Treaty adopted on December 20, 1996, and/or similar international
+ agreements.
+
+ f. Exceptions and Limitations means fair use, fair dealing, and/or
+ any other exception or limitation to Copyright and Similar Rights
+ that applies to Your use of the Licensed Material.
+
+ g. License Elements means the license attributes listed in the name
+ of a Creative Commons Public License. The License Elements of this
+ Public License are Attribution, NonCommercial, and ShareAlike.
+
+ h. Licensed Material means the artistic or literary work, database,
+ or other material to which the Licensor applied this Public
+ License.
+
+ i. Licensed Rights means the rights granted to You subject to the
+ terms and conditions of this Public License, which are limited to
+ all Copyright and Similar Rights that apply to Your use of the
+ Licensed Material and that the Licensor has authority to license.
+
+ j. Licensor means the individual(s) or entity(ies) granting rights
+ under this Public License.
+
+ k. NonCommercial means not primarily intended for or directed towards
+ commercial advantage or monetary compensation. For purposes of
+ this Public License, the exchange of the Licensed Material for
+ other material subject to Copyright and Similar Rights by digital
+ file-sharing or similar means is NonCommercial provided there is
+ no payment of monetary compensation in connection with the
+ exchange.
+
+ l. Share means to provide material to the public by any means or
+ process that requires permission under the Licensed Rights, such
+ as reproduction, public display, public performance, distribution,
+ dissemination, communication, or importation, and to make material
+ available to the public including in ways that members of the
+ public may access the material from a place and at a time
+ individually chosen by them.
+
+ m. Sui Generis Database Rights means rights other than copyright
+ resulting from Directive 96/9/EC of the European Parliament and of
+ the Council of 11 March 1996 on the legal protection of databases,
+ as amended and/or succeeded, as well as other essentially
+ equivalent rights anywhere in the world.
+
+ n. You means the individual or entity exercising the Licensed Rights
+ under this Public License. Your has a corresponding meaning.
+
+
+Section 2 -- Scope.
+
+ a. License grant.
+
+ 1. Subject to the terms and conditions of this Public License,
+ the Licensor hereby grants You a worldwide, royalty-free,
+ non-sublicensable, non-exclusive, irrevocable license to
+ exercise the Licensed Rights in the Licensed Material to:
+
+ a. reproduce and Share the Licensed Material, in whole or
+ in part, for NonCommercial purposes only; and
+
+ b. produce, reproduce, and Share Adapted Material for
+ NonCommercial purposes only.
+
+ 2. Exceptions and Limitations. For the avoidance of doubt, where
+ Exceptions and Limitations apply to Your use, this Public
+ License does not apply, and You do not need to comply with
+ its terms and conditions.
+
+ 3. Term. The term of this Public License is specified in Section
+ 6(a).
+
+ 4. Media and formats; technical modifications allowed. The
+ Licensor authorizes You to exercise the Licensed Rights in
+ all media and formats whether now known or hereafter created,
+ and to make technical modifications necessary to do so. The
+ Licensor waives and/or agrees not to assert any right or
+ authority to forbid You from making technical modifications
+ necessary to exercise the Licensed Rights, including
+ technical modifications necessary to circumvent Effective
+ Technological Measures. For purposes of this Public License,
+ simply making modifications authorized by this Section 2(a)
+ (4) never produces Adapted Material.
+
+ 5. Downstream recipients.
+
+ a. Offer from the Licensor -- Licensed Material. Every
+ recipient of the Licensed Material automatically
+ receives an offer from the Licensor to exercise the
+ Licensed Rights under the terms and conditions of this
+ Public License.
+
+ b. Additional offer from the Licensor -- Adapted Material.
+ Every recipient of Adapted Material from You
+ automatically receives an offer from the Licensor to
+ exercise the Licensed Rights in the Adapted Material
+ under the conditions of the Adapter's License You apply.
+
+ c. No downstream restrictions. You may not offer or impose
+ any additional or different terms or conditions on, or
+ apply any Effective Technological Measures to, the
+ Licensed Material if doing so restricts exercise of the
+ Licensed Rights by any recipient of the Licensed
+ Material.
+
+ 6. No endorsement. Nothing in this Public License constitutes or
+ may be construed as permission to assert or imply that You
+ are, or that Your use of the Licensed Material is, connected
+ with, or sponsored, endorsed, or granted official status by,
+ the Licensor or others designated to receive attribution as
+ provided in Section 3(a)(1)(A)(i).
+
+ b. Other rights.
+
+ 1. Moral rights, such as the right of integrity, are not
+ licensed under this Public License, nor are publicity,
+ privacy, and/or other similar personality rights; however, to
+ the extent possible, the Licensor waives and/or agrees not to
+ assert any such rights held by the Licensor to the limited
+ extent necessary to allow You to exercise the Licensed
+ Rights, but not otherwise.
+
+ 2. Patent and trademark rights are not licensed under this
+ Public License.
+
+ 3. To the extent possible, the Licensor waives any right to
+ collect royalties from You for the exercise of the Licensed
+ Rights, whether directly or through a collecting society
+ under any voluntary or waivable statutory or compulsory
+ licensing scheme. In all other cases the Licensor expressly
+ reserves any right to collect such royalties, including when
+ the Licensed Material is used other than for NonCommercial
+ purposes.
+
+
+Section 3 -- License Conditions.
+
+Your exercise of the Licensed Rights is expressly made subject to the
+following conditions.
+
+ a. Attribution.
+
+ 1. If You Share the Licensed Material (including in modified
+ form), You must:
+
+ a. retain the following if it is supplied by the Licensor
+ with the Licensed Material:
+
+ i. identification of the creator(s) of the Licensed
+ Material and any others designated to receive
+ attribution, in any reasonable manner requested by
+ the Licensor (including by pseudonym if
+ designated);
+
+ ii. a copyright notice;
+
+ iii. a notice that refers to this Public License;
+
+ iv. a notice that refers to the disclaimer of
+ warranties;
+
+ v. a URI or hyperlink to the Licensed Material to the
+ extent reasonably practicable;
+
+ b. indicate if You modified the Licensed Material and
+ retain an indication of any previous modifications; and
+
+ c. indicate the Licensed Material is licensed under this
+ Public License, and include the text of, or the URI or
+ hyperlink to, this Public License.
+
+ 2. You may satisfy the conditions in Section 3(a)(1) in any
+ reasonable manner based on the medium, means, and context in
+ which You Share the Licensed Material. For example, it may be
+ reasonable to satisfy the conditions by providing a URI or
+ hyperlink to a resource that includes the required
+ information.
+ 3. If requested by the Licensor, You must remove any of the
+ information required by Section 3(a)(1)(A) to the extent
+ reasonably practicable.
+
+ b. ShareAlike.
+
+ In addition to the conditions in Section 3(a), if You Share
+ Adapted Material You produce, the following conditions also apply.
+
+ 1. The Adapter's License You apply must be a Creative Commons
+ license with the same License Elements, this version or
+ later, or a BY-NC-SA Compatible License.
+
+ 2. You must include the text of, or the URI or hyperlink to, the
+ Adapter's License You apply. You may satisfy this condition
+ in any reasonable manner based on the medium, means, and
+ context in which You Share Adapted Material.
+
+ 3. You may not offer or impose any additional or different terms
+ or conditions on, or apply any Effective Technological
+ Measures to, Adapted Material that restrict exercise of the
+ rights granted under the Adapter's License You apply.
+
+
+Section 4 -- Sui Generis Database Rights.
+
+Where the Licensed Rights include Sui Generis Database Rights that
+apply to Your use of the Licensed Material:
+
+ a. for the avoidance of doubt, Section 2(a)(1) grants You the right
+ to extract, reuse, reproduce, and Share all or a substantial
+ portion of the contents of the database for NonCommercial purposes
+ only;
+
+ b. if You include all or a substantial portion of the database
+ contents in a database in which You have Sui Generis Database
+ Rights, then the database in which You have Sui Generis Database
+ Rights (but not its individual contents) is Adapted Material,
+ including for purposes of Section 3(b); and
+
+ c. You must comply with the conditions in Section 3(a) if You Share
+ all or a substantial portion of the contents of the database.
+
+For the avoidance of doubt, this Section 4 supplements and does not
+replace Your obligations under this Public License where the Licensed
+Rights include other Copyright and Similar Rights.
+
+
+Section 5 -- Disclaimer of Warranties and Limitation of Liability.
+
+ a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE
+ EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS
+ AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF
+ ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS,
+ IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION,
+ WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS,
+ ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT
+ KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT
+ ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU.
+
+ b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE
+ TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION,
+ NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT,
+ INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES,
+ COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR
+ USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN
+ ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR
+ DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR
+ IN PART, THIS LIMITATION MAY NOT APPLY TO YOU.
+
+ c. The disclaimer of warranties and limitation of liability provided
+ above shall be interpreted in a manner that, to the extent
+ possible, most closely approximates an absolute disclaimer and
+ waiver of all liability.
+
+
+Section 6 -- Term and Termination.
+
+ a. This Public License applies for the term of the Copyright and
+ Similar Rights licensed here. However, if You fail to comply with
+ this Public License, then Your rights under this Public License
+ terminate automatically.
+
+ b. Where Your right to use the Licensed Material has terminated under
+ Section 6(a), it reinstates:
+
+ 1. automatically as of the date the violation is cured, provided
+ it is cured within 30 days of Your discovery of the
+ violation; or
+
+ 2. upon express reinstatement by the Licensor.
+
+ For the avoidance of doubt, this Section 6(b) does not affect any
+ right the Licensor may have to seek remedies for Your violations
+ of this Public License.
+
+ c. For the avoidance of doubt, the Licensor may also offer the
+ Licensed Material under separate terms or conditions or stop
+ distributing the Licensed Material at any time; however, doing so
+ will not terminate this Public License.
+
+ d. Sections 1, 5, 6, 7, and 8 survive termination of this Public
+ License.
+
+
+Section 7 -- Other Terms and Conditions.
+
+ a. The Licensor shall not be bound by any additional or different
+ terms or conditions communicated by You unless expressly agreed.
+
+ b. Any arrangements, understandings, or agreements regarding the
+ Licensed Material not stated herein are separate from and
+ independent of the terms and conditions of this Public License.
+
+
+Section 8 -- Interpretation.
+
+ a. For the avoidance of doubt, this Public License does not, and
+ shall not be interpreted to, reduce, limit, restrict, or impose
+ conditions on any use of the Licensed Material that could lawfully
+ be made without permission under this Public License.
+
+ b. To the extent possible, if any provision of this Public License is
+ deemed unenforceable, it shall be automatically reformed to the
+ minimum extent necessary to make it enforceable. If the provision
+ cannot be reformed, it shall be severed from this Public License
+ without affecting the enforceability of the remaining terms and
+ conditions.
+
+ c. No term or condition of this Public License will be waived and no
+ failure to comply consented to unless expressly agreed to by the
+ Licensor.
+
+ d. Nothing in this Public License constitutes or may be interpreted
+ as a limitation upon, or waiver of, any privileges and immunities
+ that apply to the Licensor or You, including from the legal
+ processes of any jurisdiction or authority.
+
+=======================================================================
+
+Creative Commons is not a party to its public
+licenses. Notwithstanding, Creative Commons may elect to apply one of
+its public licenses to material it publishes and in those instances
+will be considered the “Licensor.” The text of the Creative Commons
+public licenses is dedicated to the public domain under the CC0 Public
+Domain Dedication. Except for the limited purpose of indicating that
+material is shared under a Creative Commons public license or as
+otherwise permitted by the Creative Commons policies published at
+creativecommons.org/policies, Creative Commons does not authorize the
+use of the trademark "Creative Commons" or any other trademark or logo
+of Creative Commons without its prior written consent including,
+without limitation, in connection with any unauthorized modifications
+to any of its public licenses or any other arrangements,
+understandings, or agreements concerning use of licensed material. For
+the avoidance of doubt, this paragraph does not form part of the
+public licenses.
+
+Creative Commons may be contacted at creativecommons.org.
diff --git a/program_info/org.polymc.polymc.desktop.in b/program_info/org.polymc.PolyMC.desktop.in
index 8bbdc505..2d9e7103 100644
--- a/program_info/org.polymc.polymc.desktop.in
+++ b/program_info/org.polymc.PolyMC.desktop.in
@@ -7,6 +7,6 @@ Terminal=false
Exec=@Launcher_APP_BINARY_NAME@
StartupNotify=true
Icon=org.polymc.PolyMC
-PrefersNonDefaultGPU=true
Categories=Game;
Keywords=game;minecraft;launcher;
+StartupWMClass=PolyMC
diff --git a/program_info/org.polymc.PolyMC.metainfo.xml.in b/program_info/org.polymc.PolyMC.metainfo.xml.in
index 505ca70d..03401f3d 100644
--- a/program_info/org.polymc.PolyMC.metainfo.xml.in
+++ b/program_info/org.polymc.PolyMC.metainfo.xml.in
@@ -22,44 +22,36 @@
<li>See logs and other details easily</li>
<li>Kill Minecraft in case of a crash/freeze</li>
<li>Isolate minecraft instances to keep everything clean</li>
+ <li>Install mods directly from the launcher</li>
</ul>
- <p>For flatpak users:</p>
- <p>In flatpak, all java versions that are required by Minecraft are included.</p>
- <p>
- If using a Hybrid-Graphics device, you can use the
- prime-run
- script as a wrapper command to run Minecraft using the dedicated graphics card.
- </p>
</description>
<screenshots>
<screenshot type="default">
<caption>The main PolyMC window</caption>
- <image type="source" width="802" height="639">https://i.imgur.com/q2GcDo4.png</image>
+ <image type="source" width="1011" height="994">https://polymc.github.io/assets/img/screenshots/LauncherDark.png</image>
+ </screenshot>
+ <screenshot>
+ <caption>Modpack installation</caption>
+ <image type="source" width="911" height="682">https://polymc.github.io/assets/img/screenshots/ModpackInstallDark.png</image>
+ </screenshot>
+ <screenshot>
+ <caption>Mod installation</caption>
+ <image type="source" width="987" height="723">https://polymc.github.io/assets/img/screenshots/ModInstallDark.png</image>
+ </screenshot>
+ <screenshot>
+ <caption>Instance management</caption>
+ <image type="source" width="902" height="920">https://polymc.github.io/assets/img/screenshots/PropertiesDark.png</image>
+ </screenshot>
+ <screenshot>
+ <caption>Cat :)</caption>
+ <image type="source" width="1011" height="994">https://polymc.github.io/assets/img/screenshots/LauncherCatDark.png</image>
</screenshot>
</screenshots>
<releases>
- <release version="@Launcher_RELEASE_VERSION_NAME@" date="2022-01-01" />
+ <release version="@Launcher_RELEASE_VERSION_NAME@" date="@Launcher_RELEASE_TIMESTAMP@"></release>
</releases>
- <content_rating type="oars-1.0">
- <content_attribute id="violence-cartoon">moderate</content_attribute>
- <content_attribute id="violence-fantasy">none</content_attribute>
- <content_attribute id="violence-realistic">none</content_attribute>
- <content_attribute id="violence-bloodshed">none</content_attribute>
- <content_attribute id="violence-sexual">none</content_attribute>
- <content_attribute id="drugs-alcohol">none</content_attribute>
- <content_attribute id="drugs-narcotics">none</content_attribute>
- <content_attribute id="drugs-tobacco">none</content_attribute>
- <content_attribute id="sex-nudity">none</content_attribute>
- <content_attribute id="sex-themes">none</content_attribute>
- <content_attribute id="language-profanity">none</content_attribute>
- <content_attribute id="language-humor">none</content_attribute>
- <content_attribute id="language-discrimination">none</content_attribute>
+ <content_rating type="oars-1.1">
+ <content_attribute id="violence-fantasy">moderate</content_attribute>
<content_attribute id="social-chat">intense</content_attribute>
- <content_attribute id="social-info">none</content_attribute>
- <content_attribute id="social-audio">none</content_attribute>
- <content_attribute id="social-location">none</content_attribute>
- <content_attribute id="social-contacts">none</content_attribute>
- <content_attribute id="money-purchasing">none</content_attribute>
- <content_attribute id="money-gambling">none</content_attribute>
</content_rating>
</component>