diff options
-rw-r--r-- | .github/workflows/build.yml | 43 | ||||
-rw-r--r-- | .github/workflows/trigger_release.yml | 4 | ||||
-rw-r--r-- | flake.lock | 16 | ||||
-rw-r--r-- | flake.nix | 2 | ||||
-rw-r--r-- | launcher/CMakeLists.txt | 1 | ||||
-rw-r--r-- | launcher/java/JavaUtils.cpp | 9 | ||||
-rw-r--r-- | launcher/minecraft/MinecraftInstance.cpp | 6 | ||||
-rw-r--r-- | launcher/minecraft/auth/steps/LauncherLoginStep.cpp | 17 | ||||
-rw-r--r-- | launcher/minecraft/auth/steps/MinecraftProfileStep.cpp | 17 | ||||
-rw-r--r-- | launcher/minecraft/auth/steps/MinecraftProfileStepMojang.cpp | 17 | ||||
-rw-r--r-- | launcher/minecraft/auth/steps/XboxAuthorizationStep.cpp | 21 | ||||
-rw-r--r-- | launcher/minecraft/auth/steps/XboxProfileStep.cpp | 17 | ||||
-rw-r--r-- | launcher/minecraft/auth/steps/XboxUserStep.cpp | 13 | ||||
-rw-r--r-- | launcher/modplatform/flame/FlameCheckUpdate.cpp | 4 | ||||
-rw-r--r-- | launcher/net/NetUtils.h | 44 | ||||
-rw-r--r-- | launcher/ui/dialogs/ModUpdateDialog.cpp | 13 | ||||
-rw-r--r-- | launcher/ui/pages/instance/ExternalResourcesPage.ui | 2 | ||||
-rw-r--r-- | launcher/ui/pages/instance/ModFolderPage.cpp | 15 | ||||
-rw-r--r-- | nix/default.nix | 2 |
19 files changed, 197 insertions, 66 deletions
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 1108fed6..0599c1d9 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -23,10 +23,9 @@ jobs: qt_ver: 5 - os: ubuntu-20.04 - appimage: true qt_ver: 6 qt_host: linux - qt_version: '6.3.1' + qt_version: '6.2.4' qt_modules: 'qt5compat qtimageformats' qt_path: /home/runner/work/PolyMC/Qt @@ -92,7 +91,7 @@ jobs: if: runner.os != 'Windows' && inputs.build_type == 'Debug' uses: hendrikmuhs/ccache-action@v1.2.1 with: - key: ${{ matrix.os }}-${{ matrix.appimage }} + key: ${{ matrix.os }}-qt${{ matrix.qt_ver }} - name: Setup ccache (Windows) if: runner.os == 'Windows' && inputs.build_type == 'Debug' @@ -115,9 +114,9 @@ jobs: uses: actions/cache@v3.0.2 with: path: '${{ github.workspace }}\.ccache' - key: ${{ matrix.os }}--qt${{ matrix.qt_ver }} + key: ${{ matrix.os }}-qt${{ matrix.qt_ver }} restore-keys: | - ${{ matrix.os }}--qt${{ matrix.qt_ver }} + ${{ matrix.os }}-qt${{ matrix.qt_ver }} - name: Set short version shell: bash @@ -138,7 +137,7 @@ jobs: brew install ninja extra-cmake-modules - name: Install Qt (Linux) - if: runner.os == 'Linux' && matrix.appimage != true + if: runner.os == 'Linux' && matrix.qt_ver != 6 run: | sudo apt-get -y install qtbase5-dev qtchooser qt5-qmake qtbase5-dev-tools libqt5core5a libqt5network5 libqt5gui5 @@ -162,7 +161,7 @@ jobs: aqtversion: ==2.1.* - name: Prepare AppImage (Linux) - if: runner.os == 'Linux' && matrix.appimage == true + if: runner.os == 'Linux' && matrix.qt_ver != 5 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" @@ -281,7 +280,7 @@ jobs: makensis -NOCD "${{ github.workspace }}/${{ env.BUILD_DIR }}/program_info/win_install.nsi" - name: Package (Linux) - if: runner.os == 'Linux' && matrix.appimage != true + if: runner.os == 'Linux' run: | cmake --install ${{ env.BUILD_DIR }} --prefix ${{ env.INSTALL_DIR }} @@ -289,7 +288,7 @@ jobs: tar --owner root --group root -czf ../PolyMC.tar.gz * - name: Package (Linux, portable) - if: runner.os == 'Linux' && matrix.appimage != true + if: runner.os == 'Linux' run: | cmake --install ${{ env.BUILD_DIR }} --prefix ${{ env.INSTALL_PORTABLE_DIR }} cmake --install ${{ env.BUILD_DIR }} --prefix ${{ env.INSTALL_PORTABLE_DIR }} --component portable @@ -298,7 +297,7 @@ jobs: tar -czf ../PolyMC-portable.tar.gz * - name: Package AppImage (Linux) - if: runner.os == 'Linux' && matrix.appimage == true + if: runner.os == 'Linux' && matrix.qt_ver != 5 shell: bash run: | cmake --install ${{ env.BUILD_DIR }} --prefix ${{ env.INSTALL_APPIMAGE_DIR }}/usr @@ -357,22 +356,36 @@ jobs: name: PolyMC-${{ matrix.name }}-Setup-${{ env.VERSION }}-${{ inputs.build_type }} path: PolyMC-Setup.exe - - name: Upload binary tarball (Linux) - if: runner.os == 'Linux' && matrix.appimage != true + - name: Upload binary tarball (Linux, Qt 5) + if: runner.os == 'Linux' && matrix.qt_ver != 6 uses: actions/upload-artifact@v3 with: name: PolyMC-${{ runner.os }}-${{ env.VERSION }}-${{ inputs.build_type }} path: PolyMC.tar.gz - - name: Upload binary tarball (Linux, portable) - if: runner.os == 'Linux' && matrix.appimage != true + - name: Upload binary tarball (Linux, portable, Qt 5) + if: runner.os == 'Linux' && matrix.qt_ver != 6 uses: actions/upload-artifact@v3 with: name: PolyMC-${{ runner.os }}-Portable-${{ env.VERSION }}-${{ inputs.build_type }} path: PolyMC-portable.tar.gz + - name: Upload binary tarball (Linux, Qt 6) + if: runner.os == 'Linux' && matrix.qt_ver !=5 + uses: actions/upload-artifact@v3 + with: + name: PolyMC-${{ runner.os }}-Qt6-${{ env.VERSION }}-${{ inputs.build_type }} + path: PolyMC.tar.gz + + - name: Upload binary tarball (Linux, portable, Qt 6) + if: runner.os == 'Linux' && matrix.qt_ver != 5 + uses: actions/upload-artifact@v3 + with: + name: PolyMC-${{ runner.os }}-Qt6-Portable-${{ env.VERSION }}-${{ inputs.build_type }} + path: PolyMC-portable.tar.gz + - name: Upload AppImage (Linux) - if: runner.os == 'Linux' && matrix.appimage == true + if: runner.os == 'Linux' && matrix.qt_ver != 5 uses: actions/upload-artifact@v3 with: name: PolyMC-${{ runner.os }}-${{ env.VERSION }}-${{ inputs.build_type }}-x86_64.AppImage diff --git a/.github/workflows/trigger_release.yml b/.github/workflows/trigger_release.yml index af4a5f03..45ef7281 100644 --- a/.github/workflows/trigger_release.yml +++ b/.github/workflows/trigger_release.yml @@ -35,6 +35,8 @@ jobs: - name: Package artifacts properly run: | mv ${{ github.workspace }}/PolyMC-source PolyMC-${{ env.VERSION }} + mv PolyMC-Linux-Qt6-Portable*/PolyMC-portable.tar.gz PolyMC-Linux-Qt6-Portable-${{ env.VERSION }}.tar.gz + mv PolyMC-Linux-Qt6*/PolyMC.tar.gz PolyMC-Linux-Qt6-${{ env.VERSION }}.tar.gz mv PolyMC-Linux-Portable*/PolyMC-portable.tar.gz PolyMC-Linux-Portable-${{ env.VERSION }}.tar.gz mv PolyMC-Linux*/PolyMC.tar.gz PolyMC-Linux-${{ env.VERSION }}.tar.gz mv PolyMC-*.AppImage/PolyMC-*.AppImage PolyMC-Linux-${{ env.VERSION }}-x86_64.AppImage @@ -70,6 +72,8 @@ jobs: PolyMC-Linux-Portable-${{ env.VERSION }}.tar.gz PolyMC-Linux-${{ env.VERSION }}-x86_64.AppImage PolyMC-Windows-Legacy-${{ env.VERSION }}.zip + PolyMC-Linux-Qt6-${{ env.VERSION }}.tar.gz + PolyMC-Linux-Qt6-Portable-${{ env.VERSION }}.tar.gz PolyMC-Windows-Legacy-Portable-${{ env.VERSION }}.zip PolyMC-Windows-Legacy-Setup-${{ env.VERSION }}.exe PolyMC-Windows-${{ env.VERSION }}.zip @@ -19,26 +19,26 @@ "libnbtplusplus": { "flake": false, "locked": { - "lastModified": 1591558203, - "narHash": "sha256-QgvNvaoFflCXEPCCFBCeZvYTpuiwScBG7EosUgFwFNQ=", - "owner": "multimc", + "lastModified": 1650031308, + "narHash": "sha256-TvVOjkUobYJD9itQYueELJX3wmecvEdCbJ0FinW2mL4=", + "owner": "PolyMC", "repo": "libnbtplusplus", - "rev": "dc72a20b7efd304d12af2025223fad07b4b78464", + "rev": "2203af7eeb48c45398139b583615134efd8d407f", "type": "github" }, "original": { - "owner": "multimc", + "owner": "PolyMC", "repo": "libnbtplusplus", "type": "github" } }, "nixpkgs": { "locked": { - "lastModified": 1654665288, - "narHash": "sha256-7blJpfoZEu7GKb84uh3io/5eSJNdaagXD9d15P9iQMs=", + "lastModified": 1658119717, + "narHash": "sha256-4upOZIQQ7Bc4CprqnHsKnqYfw+arJeAuU+QcpjYBXW0=", "owner": "nixos", "repo": "nixpkgs", - "rev": "43ecbe7840d155fa933ee8a500fb00dbbc651fc8", + "rev": "9eb60f25aff0d2218c848dd4574a0ab5e296cabe", "type": "github" }, "original": { @@ -4,7 +4,7 @@ inputs = { nixpkgs.url = "github:nixos/nixpkgs/nixpkgs-unstable"; flake-compat = { url = "github:edolstra/flake-compat"; flake = false; }; - libnbtplusplus = { url = "github:multimc/libnbtplusplus"; flake = false; }; + libnbtplusplus = { url = "github:PolyMC/libnbtplusplus"; flake = false; }; }; outputs = { self, nixpkgs, libnbtplusplus, ... }: diff --git a/launcher/CMakeLists.txt b/launcher/CMakeLists.txt index 3c9aee6a..a4a1315d 100644 --- a/launcher/CMakeLists.txt +++ b/launcher/CMakeLists.txt @@ -117,6 +117,7 @@ set(NET_SOURCES net/NetAction.h net/NetJob.cpp net/NetJob.h + net/NetUtils.h net/PasteUpload.cpp net/PasteUpload.h net/Sink.h diff --git a/launcher/java/JavaUtils.cpp b/launcher/java/JavaUtils.cpp index 51d5b89d..2b19fca0 100644 --- a/launcher/java/JavaUtils.cpp +++ b/launcher/java/JavaUtils.cpp @@ -205,7 +205,7 @@ QList<JavaInstallPtr> JavaUtils::FindJavaFromRegistryKey(DWORD keyType, QString // Read the current type version from the registry. // This will be used to find any key that contains the JavaHome value. - TCHAR subKeyName[255]; + WCHAR subKeyName[255]; DWORD subKeyNameSize, numSubKeys, retCode; // Get the number of subkeys @@ -231,12 +231,11 @@ QList<JavaInstallPtr> JavaUtils::FindJavaFromRegistryKey(DWORD keyType, QString KEY_READ | KEY_WOW64_64KEY, &newKey) == ERROR_SUCCESS) { // Read the JavaHome value to find where Java is installed. - TCHAR *value = NULL; DWORD valueSz = 0; - if (RegQueryValueExW(newKey, keyJavaDir.toStdWString().c_str(), NULL, NULL, (BYTE *)value, - &valueSz) == ERROR_MORE_DATA) + if (RegQueryValueExW(newKey, keyJavaDir.toStdWString().c_str(), NULL, NULL, NULL, + &valueSz) == ERROR_SUCCESS) { - value = new TCHAR[valueSz]; + WCHAR *value = new WCHAR[valueSz]; RegQueryValueExW(newKey, keyJavaDir.toStdWString().c_str(), NULL, NULL, (BYTE *)value, &valueSz); diff --git a/launcher/minecraft/MinecraftInstance.cpp b/launcher/minecraft/MinecraftInstance.cpp index 360e754d..5a6f8de0 100644 --- a/launcher/minecraft/MinecraftInstance.cpp +++ b/launcher/minecraft/MinecraftInstance.cpp @@ -709,15 +709,15 @@ QStringList MinecraftInstance::verboseDescription(AuthSessionPtr session, Minecr { if(mod->type() == Mod::MOD_FOLDER) { - out << u8" [📁] " + mod->fileinfo().completeBaseName() + " (folder)"; + out << u8" [🖿] " + mod->fileinfo().completeBaseName() + " (folder)"; continue; } if(mod->enabled()) { - out << u8" [✔️]" + mod->fileinfo().completeBaseName(); + out << u8" [✔] " + mod->fileinfo().completeBaseName(); } else { - out << u8" [❌] " + mod->fileinfo().completeBaseName() + " (disabled)"; + out << u8" [✘] " + mod->fileinfo().completeBaseName() + " (disabled)"; } } diff --git a/launcher/minecraft/auth/steps/LauncherLoginStep.cpp b/launcher/minecraft/auth/steps/LauncherLoginStep.cpp index f5697223..8c53f037 100644 --- a/launcher/minecraft/auth/steps/LauncherLoginStep.cpp +++ b/launcher/minecraft/auth/steps/LauncherLoginStep.cpp @@ -5,6 +5,7 @@ #include "minecraft/auth/AuthRequest.h" #include "minecraft/auth/Parsers.h" #include "minecraft/auth/AccountTask.h" +#include "net/NetUtils.h" LauncherLoginStep::LauncherLoginStep(AccountData* data) : AuthStep(data) { @@ -58,10 +59,18 @@ void LauncherLoginStep::onRequestDone( #ifndef NDEBUG qDebug() << data; #endif - emit finished( - AccountTaskState::STATE_FAILED_SOFT, - tr("Failed to get Minecraft access token: %1").arg(requestor->errorString_) - ); + if (Net::isApplicationError(error)) { + emit finished( + AccountTaskState::STATE_FAILED_SOFT, + tr("Failed to get Minecraft access token: %1").arg(requestor->errorString_) + ); + } + else { + emit finished( + AccountTaskState::STATE_OFFLINE, + tr("Failed to get Minecraft access token: %1").arg(requestor->errorString_) + ); + } return; } diff --git a/launcher/minecraft/auth/steps/MinecraftProfileStep.cpp b/launcher/minecraft/auth/steps/MinecraftProfileStep.cpp index add91659..b39b9326 100644 --- a/launcher/minecraft/auth/steps/MinecraftProfileStep.cpp +++ b/launcher/minecraft/auth/steps/MinecraftProfileStep.cpp @@ -4,6 +4,7 @@ #include "minecraft/auth/AuthRequest.h" #include "minecraft/auth/Parsers.h" +#include "net/NetUtils.h" MinecraftProfileStep::MinecraftProfileStep(AccountData* data) : AuthStep(data) { @@ -64,10 +65,18 @@ void MinecraftProfileStep::onRequestDone( qWarning() << " Response:"; qWarning() << QString::fromUtf8(data); - emit finished( - AccountTaskState::STATE_FAILED_SOFT, - tr("Minecraft Java profile acquisition failed.") - ); + if (Net::isApplicationError(error)) { + emit finished( + AccountTaskState::STATE_FAILED_SOFT, + tr("Minecraft Java profile acquisition failed: %1").arg(requestor->errorString_) + ); + } + else { + emit finished( + AccountTaskState::STATE_OFFLINE, + tr("Minecraft Java profile acquisition failed: %1").arg(requestor->errorString_) + ); + } return; } if(!Parsers::parseMinecraftProfile(data, m_data->minecraftProfile)) { diff --git a/launcher/minecraft/auth/steps/MinecraftProfileStepMojang.cpp b/launcher/minecraft/auth/steps/MinecraftProfileStepMojang.cpp index d3035272..6a1eb7a0 100644 --- a/launcher/minecraft/auth/steps/MinecraftProfileStepMojang.cpp +++ b/launcher/minecraft/auth/steps/MinecraftProfileStepMojang.cpp @@ -4,6 +4,7 @@ #include "minecraft/auth/AuthRequest.h" #include "minecraft/auth/Parsers.h" +#include "net/NetUtils.h" MinecraftProfileStepMojang::MinecraftProfileStepMojang(AccountData* data) : AuthStep(data) { @@ -67,10 +68,18 @@ void MinecraftProfileStepMojang::onRequestDone( qWarning() << " Response:"; qWarning() << QString::fromUtf8(data); - emit finished( - AccountTaskState::STATE_FAILED_SOFT, - tr("Minecraft Java profile acquisition failed.") - ); + if (Net::isApplicationError(error)) { + emit finished( + AccountTaskState::STATE_FAILED_SOFT, + tr("Minecraft Java profile acquisition failed: %1").arg(requestor->errorString_) + ); + } + else { + emit finished( + AccountTaskState::STATE_OFFLINE, + tr("Minecraft Java profile acquisition failed: %1").arg(requestor->errorString_) + ); + } return; } if(!Parsers::parseMinecraftProfileMojang(data, m_data->minecraftProfile)) { diff --git a/launcher/minecraft/auth/steps/XboxAuthorizationStep.cpp b/launcher/minecraft/auth/steps/XboxAuthorizationStep.cpp index 589768e3..14bde47e 100644 --- a/launcher/minecraft/auth/steps/XboxAuthorizationStep.cpp +++ b/launcher/minecraft/auth/steps/XboxAuthorizationStep.cpp @@ -6,6 +6,7 @@ #include "minecraft/auth/AuthRequest.h" #include "minecraft/auth/Parsers.h" +#include "net/NetUtils.h" XboxAuthorizationStep::XboxAuthorizationStep(AccountData* data, Katabasis::Token *token, QString relyingParty, QString authorizationKind): AuthStep(data), @@ -62,10 +63,24 @@ void XboxAuthorizationStep::onRequestDone( #endif if (error != QNetworkReply::NoError) { qWarning() << "Reply error:" << error; - if(!processSTSError(error, data, headers)) { + if (Net::isApplicationError(error)) { + if(!processSTSError(error, data, headers)) { + emit finished( + AccountTaskState::STATE_FAILED_SOFT, + tr("Failed to get authorization for %1 services. Error %2.").arg(m_authorizationKind, error) + ); + } + else { + emit finished( + AccountTaskState::STATE_FAILED_SOFT, + tr("Unknown STS error for %1 services: %2").arg(m_authorizationKind, requestor->errorString_) + ); + } + } + else { emit finished( - AccountTaskState::STATE_FAILED_SOFT, - tr("Failed to get authorization for %1 services. Error %2.").arg(m_authorizationKind, error) + AccountTaskState::STATE_OFFLINE, + tr("Failed to get authorization for %1 services: %2").arg(m_authorizationKind, requestor->errorString_) ); } return; diff --git a/launcher/minecraft/auth/steps/XboxProfileStep.cpp b/launcher/minecraft/auth/steps/XboxProfileStep.cpp index 9f50138e..738fe1db 100644 --- a/launcher/minecraft/auth/steps/XboxProfileStep.cpp +++ b/launcher/minecraft/auth/steps/XboxProfileStep.cpp @@ -6,6 +6,7 @@ #include "minecraft/auth/AuthRequest.h" #include "minecraft/auth/Parsers.h" +#include "net/NetUtils.h" XboxProfileStep::XboxProfileStep(AccountData* data) : AuthStep(data) { @@ -58,10 +59,18 @@ void XboxProfileStep::onRequestDone( #ifndef NDEBUG qDebug() << data; #endif - finished( - AccountTaskState::STATE_FAILED_SOFT, - tr("Failed to retrieve the Xbox profile.") - ); + if (Net::isApplicationError(error)) { + emit finished( + AccountTaskState::STATE_FAILED_SOFT, + tr("Failed to retrieve the Xbox profile: %1").arg(requestor->errorString_) + ); + } + else { + emit finished( + AccountTaskState::STATE_OFFLINE, + tr("Failed to retrieve the Xbox profile: %1").arg(requestor->errorString_) + ); + } return; } diff --git a/launcher/minecraft/auth/steps/XboxUserStep.cpp b/launcher/minecraft/auth/steps/XboxUserStep.cpp index a38a28e4..53069597 100644 --- a/launcher/minecraft/auth/steps/XboxUserStep.cpp +++ b/launcher/minecraft/auth/steps/XboxUserStep.cpp @@ -4,6 +4,7 @@ #include "minecraft/auth/AuthRequest.h" #include "minecraft/auth/Parsers.h" +#include "net/NetUtils.h" XboxUserStep::XboxUserStep(AccountData* data) : AuthStep(data) { @@ -53,7 +54,17 @@ void XboxUserStep::onRequestDone( if (error != QNetworkReply::NoError) { qWarning() << "Reply error:" << error; - emit finished(AccountTaskState::STATE_FAILED_SOFT, tr("XBox user authentication failed.")); + if (Net::isApplicationError(error)) { + emit finished(AccountTaskState::STATE_FAILED_SOFT, + tr("XBox user authentication failed: %1").arg(requestor->errorString_) + ); + } + else { + emit finished( + AccountTaskState::STATE_OFFLINE, + tr("XBox user authentication failed: %1").arg(requestor->errorString_) + ); + } return; } diff --git a/launcher/modplatform/flame/FlameCheckUpdate.cpp b/launcher/modplatform/flame/FlameCheckUpdate.cpp index 68a4589b..8dd3a846 100644 --- a/launcher/modplatform/flame/FlameCheckUpdate.cpp +++ b/launcher/modplatform/flame/FlameCheckUpdate.cpp @@ -123,7 +123,7 @@ void FlameCheckUpdate::executeTask() continue; } - setStatus(tr("Getting API response from CurseForge for '%1'").arg(mod->name())); + setStatus(tr("Getting API response from CurseForge for '%1'...").arg(mod->name())); setProgress(i++, m_mods.size()); auto latest_ver = api.getLatestVersion({ mod->metadata()->project_id.toString(), m_game_versions, m_loaders }); @@ -145,7 +145,7 @@ void FlameCheckUpdate::executeTask() if (latest_ver.downloadUrl.isEmpty() && latest_ver.fileId != mod->metadata()->file_id) { auto pack = getProjectInfo(latest_ver); auto recover_url = QString("%1/download/%2").arg(pack.websiteUrl, latest_ver.fileId.toString()); - emit checkFailed(mod, tr("Mod has a new update available, but is opted-out on CurseForge"), recover_url); + emit checkFailed(mod, tr("Mod has a new update available, but is not downloadable using CurseForge."), recover_url); continue; } diff --git a/launcher/net/NetUtils.h b/launcher/net/NetUtils.h new file mode 100644 index 00000000..fa3bd8c0 --- /dev/null +++ b/launcher/net/NetUtils.h @@ -0,0 +1,44 @@ +// SPDX-License-Identifier: GPL-3.0-only +/* + * PolyMC - Minecraft Launcher + * Copyright (c) 2022 Sefa Eyeoglu <contact@scrumplex.net> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#pragma once + +#include <QNetworkReply> +#include <QSet> + +namespace Net { + inline bool isApplicationError(QNetworkReply::NetworkError x) { + // Mainly taken from https://github.com/qt/qtbase/blob/dev/src/network/access/qhttpthreaddelegate.cpp + static QSet<QNetworkReply::NetworkError> errors = { + QNetworkReply::ProtocolInvalidOperationError, + QNetworkReply::AuthenticationRequiredError, + QNetworkReply::ContentAccessDenied, + QNetworkReply::ContentNotFoundError, + QNetworkReply::ContentOperationNotPermittedError, + QNetworkReply::ProxyAuthenticationRequiredError, + QNetworkReply::ContentConflictError, + QNetworkReply::ContentGoneError, + QNetworkReply::InternalServerError, + QNetworkReply::OperationNotImplementedError, + QNetworkReply::ServiceUnavailableError, + QNetworkReply::UnknownServerError, + QNetworkReply::UnknownContentError + }; + return errors.contains(x); + } +} // namespace Net diff --git a/launcher/ui/dialogs/ModUpdateDialog.cpp b/launcher/ui/dialogs/ModUpdateDialog.cpp index b6e76ff1..d73c8ebb 100644 --- a/launcher/ui/dialogs/ModUpdateDialog.cpp +++ b/launcher/ui/dialogs/ModUpdateDialog.cpp @@ -158,8 +158,9 @@ void ModUpdateDialog::checkCandidates() if (!reason.isEmpty()) text += tr("Reason: %1").arg(reason) + "<br>"; if (!recover_url.isEmpty()) - text += tr("Possible solution: ") + tr("Getting the latest version manually:") + "<br>" + - QString("<a href='%1'>").arg(recover_url.toString()) + recover_url.toString() + "</a><br>"; + //: %1 is the link to download it manually + text += tr("Possible solution: Getting the latest version manually:<br>%1<br>") + .arg(QString("<a href='%1'>%1</a>").arg(recover_url.toString())); text += "<br>"; } @@ -241,9 +242,9 @@ auto ModUpdateDialog::ensureMetadata() -> bool } ChooseProviderDialog chooser(this); - chooser.setDescription(tr("This mod (%1) does not have a metadata yet. We need to create one in order to keep relevant " - "information on how to update this " - "mod. To do this, please select a mod provider from which we can search for updates for %1.") + chooser.setDescription(tr("The mod '%1' does not have a metadata yet. We need to generate it in order to track relevant " + "information on how to update this mod. " + "To do this, please select a mod provider which we can use to check for updates for this mod.") .arg(candidate->name())); auto confirmed = chooser.exec() == QDialog::DialogCode::Accepted; @@ -330,7 +331,7 @@ void ModUpdateDialog::onMetadataFailed(Mod* mod, bool try_others, ModPlatform::P m_second_try_metadata->addTask(task); } else { - QString reason{ tr("Didn't find a valid version on the selected mod provider(s)") }; + QString reason{ tr("Couldn't find a valid version on the selected mod provider(s)") }; m_failed_metadata.append({mod, reason}); } diff --git a/launcher/ui/pages/instance/ExternalResourcesPage.ui b/launcher/ui/pages/instance/ExternalResourcesPage.ui index 8edcfd64..a13666b2 100644 --- a/launcher/ui/pages/instance/ExternalResourcesPage.ui +++ b/launcher/ui/pages/instance/ExternalResourcesPage.ui @@ -155,7 +155,7 @@ <string>Check for &Updates</string> </property> <property name="toolTip"> - <string>"Tries to find / update all selected resources (all resources if none is selected)"</string> + <string>Try to check or update all selected resources (all resources if none are selected)</string> </property> </action> </widget> diff --git a/launcher/ui/pages/instance/ModFolderPage.cpp b/launcher/ui/pages/instance/ModFolderPage.cpp index b190e51a..14e1f1e5 100644 --- a/launcher/ui/pages/instance/ModFolderPage.cpp +++ b/launcher/ui/pages/instance/ModFolderPage.cpp @@ -80,7 +80,7 @@ ModFolderPage::ModFolderPage(BaseInstance* inst, std::shared_ptr<ModFolderModel> connect(ui->actionDownloadItem, &QAction::triggered, this, &ModFolderPage::installMods); - ui->actionUpdateItem->setToolTip(tr("Tries to find / update all selected mods (all mods if none is selected)")); + ui->actionUpdateItem->setToolTip(tr("Try to check or update all selected mods (all mods if none are selected)")); ui->actionsToolbar->insertActionAfter(ui->actionAddItem, ui->actionUpdateItem); connect(ui->actionUpdateItem, &QAction::triggered, this, &ModFolderPage::updateMods); @@ -190,10 +190,15 @@ void ModFolderPage::updateMods() return; } if (update_dialog.noUpdates()) { - CustomMessageBox::selectable(this, tr("Update checker"), - (mods_list.size() == 1) - ? tr("'%1' is up-to-date! :)").arg(mods_list.front()->name()) - : tr("All %1mods are up-to-date! :)").arg(use_all ? "" : (tr("selected") + " "))) + QString message{ tr("'%1' is up-to-date! :)").arg(mods_list.front()->name()) }; + if (mods_list.size() > 1) { + if (use_all) { + message = tr("All mods are up-to-date! :)"); + } else { + message = tr("All selected mods are up-to-date! :)"); + } + } + CustomMessageBox::selectable(this, tr("Update checker"), message) ->exec(); return; } diff --git a/nix/default.nix b/nix/default.nix index 40a9a587..42ddda18 100644 --- a/nix/default.nix +++ b/nix/default.nix @@ -79,6 +79,8 @@ stdenv.mkDerivation rec { meta = with lib; { homepage = "https://polymc.org/"; + downloadPage = "https://polymc.org/download/"; + changelog = "https://github.com/PolyMC/PolyMC/releases"; description = "A free, open source launcher for Minecraft"; longDescription = '' Allows you to have multiple, separate instances of Minecraft (each with |