diff options
43 files changed, 773 insertions, 702 deletions
diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index b387f46a..bac73932 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -27,7 +27,7 @@ body: attributes: label: Version of PolyMC description: The version of PolyMC used in the bug report. - placeholder: PolyMC 1.2.2 + placeholder: PolyMC 1.3.2 validations: required: true - type: textarea diff --git a/.github/workflows/backport.yml b/.github/workflows/backport.yml deleted file mode 100644 index fa287a2c..00000000 --- a/.github/workflows/backport.yml +++ /dev/null @@ -1,19 +0,0 @@ -name: Backport PR to stable -on: - pull_request: - branches: [ develop ] - types: [ closed ] -jobs: - release_pull_request: - if: github.event.pull_request.merged == true && contains(github.event.pull_request.labels.*.name, 'backport') - runs-on: ubuntu-latest - steps: - - name: checkout - uses: actions/checkout@v3 - with: - fetch-depth: 0 - - name: Backport PR by cherry-pick-ing - uses: Nathanmalnoury/gh-backport-action@master - with: - pr_branch: 'stable' - github_token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/pr-comment.yml b/.github/workflows/pr-comment.yml deleted file mode 100644 index f0f5b8cc..00000000 --- a/.github/workflows/pr-comment.yml +++ /dev/null @@ -1,61 +0,0 @@ -name: Comment on pull request -on: - workflow_run: - workflows: ['Build Application'] - types: [completed] -jobs: - pr_comment: - if: github.event.workflow_run.event == 'pull_request' && github.event.workflow_run.conclusion == 'success' - runs-on: ubuntu-latest - steps: - - uses: actions/github-script@v5 - with: - # This snippet is public-domain, taken from - # https://github.com/oprypin/nightly.link/blob/master/.github/workflows/pr-comment.yml - script: | - async function upsertComment(owner, repo, issue_number, purpose, body) { - const {data: comments} = await github.rest.issues.listComments( - {owner, repo, issue_number}); - - const marker = `<!-- bot: ${purpose} -->`; - body = marker + "\n" + body; - - const existing = comments.filter((c) => c.body.includes(marker)); - if (existing.length > 0) { - const last = existing[existing.length - 1]; - core.info(`Updating comment ${last.id}`); - await github.rest.issues.updateComment({ - owner, repo, - body, - comment_id: last.id, - }); - } else { - core.info(`Creating a comment in issue / PR #${issue_number}`); - await github.rest.issues.createComment({issue_number, body, owner, repo}); - } - } - - const {owner, repo} = context.repo; - const run_id = ${{github.event.workflow_run.id}}; - - const pull_requests = ${{ toJSON(github.event.workflow_run.pull_requests) }}; - if (!pull_requests.length) { - return core.error("This workflow doesn't match any pull requests!"); - } - - const artifacts = await github.paginate( - github.rest.actions.listWorkflowRunArtifacts, {owner, repo, run_id}); - if (!artifacts.length) { - return core.error(`No artifacts found`); - } - let body = `Download the artifacts for this pull request:\n`; - for (const art of artifacts) { - body += `\n* [${art.name}.zip](https://nightly.link/${owner}/${repo}/actions/artifacts/${art.id}.zip)`; - } - - core.info("Review thread message body:", body); - - for (const pr of pull_requests) { - await upsertComment(owner, repo, pr.number, - "nightly-link", body); - } @@ -1,33 +1,36 @@ # PolyMC - Copyright (C) 2012-2021 MultiMC Contributors - Copyright (C) 2021-2022 PolyMC Contributors + PolyMC - Minecraft Launcher + Copyright (C) 2021-2022 PolyMC Contributors - 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 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. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. + + This file incorporates work covered by the following copyright and + permission notice: - You should have received a copy of the GNU General Public License - along with this program. If not, see <https://www.gnu.org/licenses/>. + Copyright 2013-2021 MultiMC Contributors -# Launcher (https://github.com/MultiMC/Launcher) - Copyright 2012-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 + 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 + 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. + 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. # MinGW runtime (Windows) @@ -213,6 +216,57 @@ OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# launcher (`libraries/launcher`) + + PolyMC - Minecraft Launcher + Copyright (C) 2021-2022 PolyMC Contributors + + 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. + + Linking this library statically or dynamically with other modules is + making a combined work based on this library. Thus, the terms and + conditions of the GNU General Public License cover the whole + combination. + + As a special exception, the copyright holders of this library give + you permission to link this library with independent modules to + produce an executable, regardless of the license terms of these + independent modules, and to copy and distribute the resulting + executable under terms of your choice, provided that you also meet, + for each linked independent module, the terms and conditions of the + license of that module. An independent module is a module which is + not derived from or based on this library. If you modify this + library, you may extend this exception to your version of the + library, but you are not obliged to do so. If you do not wish to do + so, delete this exception statement from your version. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. + + This file incorporates work covered by the following copyright and + permission notice: + + Copyright 2013-2021 MultiMC Contributors + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + # lionshead Code has been taken from https://github.com/natefoo/lionshead and loosely @@ -1,8 +1,7 @@ -<p align="center"> - <img src="./program_info/polymc-header-black.svg#gh-light-mode-only" alt="PolyMC logo"/> - <img src="./program_info/polymc-header.svg#gh-dark-mode-only" alt="PolyMC logo"/> + <p align="center"> +<img src="./program_info/polymc-header-black.svg#gh-light-mode-only" alt="PolyMC logo" width="50%"/> +<img src="./program_info/polymc-header.svg#gh-dark-mode-only" alt="PolyMC logo" width="50%"/> </p> -<br> PolyMC is a custom launcher for Minecraft that focuses on predictability, long term stability and simplicity. @@ -80,8 +79,7 @@ To modify download information or change packaging information send a pull reque ## Forking/Redistributing/Custom builds policy -We don't care what you do with your fork/custom build as long as you do the following as a basic courtesy: -- Follow the terms of the [license](LICENSE) (not just a courtesy, but also a legal responsibility) +We don't care what you do with your fork/custom build as long as you follow the terms of the [license](LICENSE) (this is a legal responsibility), and if you made code changes rather than just packaging a custom build, please do the following as a basic courtesy: - Make it clear that your fork is not PolyMC and is not endorsed by or affiliated with the PolyMC project (https://polymc.org). - Go through [CMakeLists.txt](CMakeLists.txt) and change PolyMC's API keys to your own or set them to empty strings (`""`) to disable them (this way the program will still compile but the functionality requiring those keys will be disabled). diff --git a/launcher/Application.cpp b/launcher/Application.cpp index ab3110a3..bafb928b 100644 --- a/launcher/Application.cpp +++ b/launcher/Application.cpp @@ -226,7 +226,7 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv) setOrganizationName(BuildConfig.LAUNCHER_NAME); setOrganizationDomain(BuildConfig.LAUNCHER_DOMAIN); setApplicationName(BuildConfig.LAUNCHER_NAME); - setApplicationDisplayName(BuildConfig.LAUNCHER_DISPLAYNAME); + setApplicationDisplayName(QString("%1 %2").arg(BuildConfig.LAUNCHER_DISPLAYNAME, BuildConfig.printableVersionString())); setApplicationVersion(BuildConfig.printableVersionString()); setDesktopFileName(BuildConfig.LAUNCHER_DESKTOPFILENAME); startTime = QDateTime::currentDateTime(); @@ -626,6 +626,7 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv) m_settings->registerSetting("JavaPath", ""); m_settings->registerSetting("JavaTimestamp", 0); m_settings->registerSetting("JavaArchitecture", ""); + m_settings->registerSetting("JavaRealArchitecture", ""); m_settings->registerSetting("JavaVersion", ""); m_settings->registerSetting("JavaVendor", ""); m_settings->registerSetting("LastHostname", ""); diff --git a/launcher/CMakeLists.txt b/launcher/CMakeLists.txt index ce1b9e91..fbd49330 100644 --- a/launcher/CMakeLists.txt +++ b/launcher/CMakeLists.txt @@ -717,6 +717,8 @@ SET(LAUNCHER_SOURCES ui/pages/BasePageProvider.h # GUI - instance pages + ui/pages/instance/ExternalResourcesPage.cpp + ui/pages/instance/ExternalResourcesPage.h ui/pages/instance/GameOptionsPage.cpp ui/pages/instance/GameOptionsPage.h ui/pages/instance/VersionPage.cpp @@ -926,7 +928,7 @@ qt5_wrap_ui(LAUNCHER_UI ui/pages/global/ProxyPage.ui ui/pages/global/MinecraftPage.ui ui/pages/global/ExternalToolsPage.ui - ui/pages/instance/ModFolderPage.ui + ui/pages/instance/ExternalResourcesPage.ui ui/pages/instance/NotesPage.ui ui/pages/instance/LogPage.ui ui/pages/instance/ServersPage.ui diff --git a/launcher/InstancePageProvider.h b/launcher/InstancePageProvider.h index 357157d0..78fb7016 100644 --- a/launcher/InstancePageProvider.h +++ b/launcher/InstancePageProvider.h @@ -33,10 +33,10 @@ public: values.append(new LogPage(inst)); std::shared_ptr<MinecraftInstance> onesix = std::dynamic_pointer_cast<MinecraftInstance>(inst); values.append(new VersionPage(onesix.get())); - auto modsPage = new ModFolderPage(onesix.get(), onesix->loaderModList(), "mods", "loadermods", tr("Mods"), "Loader-mods"); + auto modsPage = new ModFolderPage(onesix.get(), onesix->loaderModList()); modsPage->setFilter("%1 (*.zip *.jar *.litemod)"); values.append(modsPage); - values.append(new CoreModFolderPage(onesix.get(), onesix->coreModList(), "coremods", "coremods", tr("Core mods"), "Core-mods")); + values.append(new CoreModFolderPage(onesix.get(), onesix->coreModList())); values.append(new ResourcePackPage(onesix.get())); values.append(new TexturePackPage(onesix.get())); values.append(new ShaderPackPage(onesix.get())); diff --git a/launcher/MMCZip.cpp b/launcher/MMCZip.cpp index 627ceaf1..d7ad4428 100644 --- a/launcher/MMCZip.cpp +++ b/launcher/MMCZip.cpp @@ -305,7 +305,7 @@ nonstd::optional<QStringList> MMCZip::extractSubDir(QuaZip *zip, const QString & QString path; if(name.contains('/') && !name.endsWith('/')){ path = name.section('/', 0, -2) + "/"; - FS::ensureFolderPathExists(path); + FS::ensureFolderPathExists(FS::PathCombine(target, path)); name = name.split('/').last(); } diff --git a/launcher/launch/steps/CheckJava.cpp b/launcher/launch/steps/CheckJava.cpp index 3226fae7..ef5db2c9 100644 --- a/launcher/launch/steps/CheckJava.cpp +++ b/launcher/launch/steps/CheckJava.cpp @@ -75,11 +75,14 @@ void CheckJava::executeTask() qlonglong javaUnixTime = javaInfo.lastModified().toMSecsSinceEpoch(); auto storedUnixTime = settings->get("JavaTimestamp").toLongLong(); auto storedArchitecture = settings->get("JavaArchitecture").toString(); + auto storedRealArchitecture = settings->get("JavaRealArchitecture").toString(); auto storedVersion = settings->get("JavaVersion").toString(); auto storedVendor = settings->get("JavaVendor").toString(); m_javaUnixTime = javaUnixTime; // if timestamps are not the same, or something is missing, check! - if (javaUnixTime != storedUnixTime || storedVersion.size() == 0 || storedArchitecture.size() == 0 || storedVendor.size() == 0) + if (javaUnixTime != storedUnixTime || storedVersion.size() == 0 + || storedArchitecture.size() == 0 || storedRealArchitecture.size() == 0 + || storedVendor.size() == 0) { m_JavaChecker = new JavaChecker(); emit logLine(QString("Checking Java version..."), MessageLevel::Launcher); @@ -92,8 +95,9 @@ void CheckJava::executeTask() { auto verString = instance->settings()->get("JavaVersion").toString(); auto archString = instance->settings()->get("JavaArchitecture").toString(); + auto realArchString = settings->get("JavaRealArchitecture").toString(); auto vendorString = instance->settings()->get("JavaVendor").toString(); - printJavaInfo(verString, archString, vendorString); + printJavaInfo(verString, archString, realArchString, vendorString); } emitSucceeded(); } @@ -124,10 +128,11 @@ void CheckJava::checkJavaFinished(JavaCheckResult result) case JavaCheckResult::Validity::Valid: { auto instance = m_parent->instance(); - printJavaInfo(result.javaVersion.toString(), result.realPlatform, result.javaVendor); + printJavaInfo(result.javaVersion.toString(), result.mojangPlatform, result.realPlatform, result.javaVendor); printSystemInfo(true, result.is_64bit); instance->settings()->set("JavaVersion", result.javaVersion.toString()); instance->settings()->set("JavaArchitecture", result.mojangPlatform); + instance->settings()->set("JavaRealArchitecture", result.realPlatform); instance->settings()->set("JavaVendor", result.javaVendor); instance->settings()->set("JavaTimestamp", m_javaUnixTime); emitSucceeded(); @@ -136,9 +141,10 @@ void CheckJava::checkJavaFinished(JavaCheckResult result) } } -void CheckJava::printJavaInfo(const QString& version, const QString& architecture, const QString & vendor) +void CheckJava::printJavaInfo(const QString& version, const QString& architecture, const QString& realArchitecture, const QString & vendor) { - emit logLine(QString("Java is version %1, using %2 architecture, from %3.\n\n").arg(version, architecture, vendor), MessageLevel::Launcher); + emit logLine(QString("Java is version %1, using %2 (%3) architecture, from %4.\n\n") + .arg(version, architecture, realArchitecture, vendor), MessageLevel::Launcher); } void CheckJava::printSystemInfo(bool javaIsKnown, bool javaIs64bit) diff --git a/launcher/launch/steps/CheckJava.h b/launcher/launch/steps/CheckJava.h index 68cd618b..d084b132 100644 --- a/launcher/launch/steps/CheckJava.h +++ b/launcher/launch/steps/CheckJava.h @@ -35,7 +35,7 @@ private slots: void checkJavaFinished(JavaCheckResult result); private: - void printJavaInfo(const QString & version, const QString & architecture, const QString & vendor); + void printJavaInfo(const QString & version, const QString & architecture, const QString & realArchitecture, const QString & vendor); void printSystemInfo(bool javaIsKnown, bool javaIs64bit); private: diff --git a/launcher/minecraft/MojangDownloadInfo.h b/launcher/minecraft/MojangDownloadInfo.h index 88f87287..13e27e15 100644 --- a/launcher/minecraft/MojangDownloadInfo.h +++ b/launcher/minecraft/MojangDownloadInfo.h @@ -65,7 +65,7 @@ struct MojangAssetIndexInfo : public MojangDownloadInfo // https://www.theregister.co.uk/2017/02/28/aws_is_awol_as_s3_goes_haywire/ if(id == "legacy") { - url = "https://launchermeta.mojang.com/mc/assets/legacy/c0fd82e8ce9fbc93119e40d96d5a4e62cfa3f729/legacy.json"; + url = "https://piston-meta.mojang.com/mc/assets/legacy/c0fd82e8ce9fbc93119e40d96d5a4e62cfa3f729/legacy.json"; } // HACK else diff --git a/launcher/minecraft/launch/LauncherPartLaunch.cpp b/launcher/minecraft/launch/LauncherPartLaunch.cpp index 427bc32b..fe8a1b1b 100644 --- a/launcher/minecraft/launch/LauncherPartLaunch.cpp +++ b/launcher/minecraft/launch/LauncherPartLaunch.cpp @@ -142,7 +142,7 @@ void LauncherPartLaunch::executeTask() #else args << classPath.join(':'); #endif - args << "org.multimc.EntryPoint"; + args << "org.polymc.EntryPoint"; qDebug() << args.join(' '); diff --git a/launcher/ui/MainWindow.cpp b/launcher/ui/MainWindow.cpp index e6058840..f68cf61a 100644 --- a/launcher/ui/MainWindow.cpp +++ b/launcher/ui/MainWindow.cpp @@ -225,6 +225,7 @@ public: TranslatedAction actionMoreNews; TranslatedAction actionManageAccounts; TranslatedAction actionLaunchInstance; + TranslatedAction actionKillInstance; TranslatedAction actionRenameInstance; TranslatedAction actionChangeInstGroup; TranslatedAction actionChangeInstIcon; @@ -283,27 +284,6 @@ public: TranslatedToolbar instanceToolBar; TranslatedToolbar newsToolBar; QVector<TranslatedToolbar *> all_toolbars; - bool m_kill = false; - - void updateLaunchAction() - { - if(m_kill) - { - actionLaunchInstance.setTextId(QT_TRANSLATE_NOOP("MainWindow", "&Kill")); - actionLaunchInstance.setTooltipId(QT_TRANSLATE_NOOP("MainWindow", "Kill the running instance")); - } - else - { - actionLaunchInstance.setTextId(QT_TRANSLATE_NOOP("MainWindow", "&Launch")); - actionLaunchInstance.setTooltipId(QT_TRANSLATE_NOOP("MainWindow", "Launch the selected instance.")); - } - actionLaunchInstance.retranslate(); - } - void setLaunchAction(bool kill) - { - m_kill = kill; - updateLaunchAction(); - } void createMainToolbarActions(QMainWindow *MainWindow) { @@ -504,9 +484,12 @@ public: menuBar->setVisible(APPLICATION->settings()->get("MenuBarInsteadOfToolBar").toBool()); fileMenu = menuBar->addMenu(tr("&File")); + // Workaround for QTBUG-94802 (https://bugreports.qt.io/browse/QTBUG-94802); also present for other menus + fileMenu->setSeparatorsCollapsible(false); fileMenu->addAction(actionAddInstance); fileMenu->addAction(actionLaunchInstance); fileMenu->addAction(actionLaunchInstanceOffline); + fileMenu->addAction(actionKillInstance); fileMenu->addAction(actionCloseWindow); fileMenu->addSeparator(); fileMenu->addAction(actionEditInstance); @@ -527,15 +510,18 @@ public: fileMenu->addAction(actionSettings); viewMenu = menuBar->addMenu(tr("&View")); + viewMenu->setSeparatorsCollapsible(false); viewMenu->addAction(actionCAT); viewMenu->addSeparator(); menuBar->addMenu(foldersMenu); profileMenu = menuBar->addMenu(tr("&Profiles")); + profileMenu->setSeparatorsCollapsible(false); profileMenu->addAction(actionManageAccounts); helpMenu = menuBar->addMenu(tr("&Help")); + helpMenu->setSeparatorsCollapsible(false); helpMenu->addAction(actionAbout); helpMenu->addAction(actionOpenWiki); helpMenu->addAction(actionNewsMenuBar); @@ -581,10 +567,9 @@ public: } // "Instance actions" are actions that require an instance to be selected (i.e. "new instance" is not here) + // Actions that also require other conditions (e.g. a running instance) won't be changed. void setInstanceActionsEnabled(bool enabled) { - actionLaunchInstance->setEnabled(enabled); - actionLaunchInstanceOffline->setEnabled(enabled); actionEditInstance->setEnabled(enabled); actionEditInstNotes->setEnabled(enabled); actionMods->setEnabled(enabled); @@ -671,6 +656,14 @@ public: actionLaunchInstanceOffline.setTooltipId(QT_TRANSLATE_NOOP("MainWindow", "Launch the selected instance in offline mode.")); all_actions.append(&actionLaunchInstanceOffline); + actionKillInstance = TranslatedAction(MainWindow); + actionKillInstance->setObjectName(QStringLiteral("actionKillInstance")); + actionKillInstance->setDisabled(true); + actionKillInstance.setTextId(QT_TRANSLATE_NOOP("MainWindow", "&Kill")); + actionKillInstance.setTooltipId(QT_TRANSLATE_NOOP("MainWindow", "Kill the running instance")); + actionKillInstance->setShortcut(QKeySequence(tr("Ctrl+K"))); + all_actions.append(&actionKillInstance); + actionEd |
