aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md2
-rw-r--r--flake.lock6
-rw-r--r--flake.nix10
-rw-r--r--launcher/Application.cpp3
-rw-r--r--launcher/CMakeLists.txt26
-rw-r--r--launcher/LaunchController.cpp5
-rw-r--r--launcher/MMCZip.cpp14
-rw-r--r--launcher/ModDownloadTask.cpp44
-rw-r--r--launcher/ModDownloadTask.h48
-rw-r--r--launcher/UpdateController.cpp2
-rw-r--r--launcher/main.cpp4
-rw-r--r--launcher/minecraft/MinecraftInstance.cpp10
-rw-r--r--launcher/minecraft/mod/MetadataHandler.h59
-rw-r--r--launcher/minecraft/mod/Mod.cpp205
-rw-r--r--launcher/minecraft/mod/Mod.h141
-rw-r--r--launcher/minecraft/mod/ModDetails.h66
-rw-r--r--launcher/minecraft/mod/ModFolderLoadTask.cpp18
-rw-r--r--launcher/minecraft/mod/ModFolderLoadTask.h29
-rw-r--r--launcher/minecraft/mod/ModFolderModel.cpp38
-rw-r--r--launcher/minecraft/mod/ModFolderModel.h11
-rw-r--r--launcher/minecraft/mod/tasks/LocalModParseTask.cpp (renamed from launcher/minecraft/mod/LocalModParseTask.cpp)22
-rw-r--r--launcher/minecraft/mod/tasks/LocalModParseTask.h (renamed from launcher/minecraft/mod/LocalModParseTask.h)8
-rw-r--r--launcher/minecraft/mod/tasks/LocalModUpdateTask.cpp53
-rw-r--r--launcher/minecraft/mod/tasks/LocalModUpdateTask.h44
-rw-r--r--launcher/minecraft/mod/tasks/ModFolderLoadTask.cpp82
-rw-r--r--launcher/minecraft/mod/tasks/ModFolderLoadTask.h69
-rw-r--r--launcher/modplatform/ModIndex.cpp86
-rw-r--r--launcher/modplatform/ModIndex.h35
-rw-r--r--launcher/modplatform/flame/FlameAPI.h1
-rw-r--r--launcher/modplatform/flame/FlameModIndex.cpp77
-rw-r--r--launcher/modplatform/flame/FlameModIndex.h1
-rw-r--r--launcher/modplatform/modrinth/ModrinthAPI.h1
-rw-r--r--launcher/modplatform/modrinth/ModrinthPackIndex.cpp129
-rw-r--r--launcher/modplatform/modrinth/ModrinthPackIndex.h1
-rw-r--r--launcher/modplatform/packwiz/Packwiz.cpp289
-rw-r--r--launcher/modplatform/packwiz/Packwiz.h93
-rw-r--r--launcher/modplatform/packwiz/Packwiz_test.cpp86
-rw-r--r--launcher/modplatform/packwiz/testdata/borderless-mining.pw.toml13
-rw-r--r--launcher/modplatform/packwiz/testdata/screenshot-to-clipboard-fabric.pw.toml13
-rw-r--r--launcher/modplatform/technic/TechnicPackProcessor.cpp21
-rw-r--r--launcher/tasks/SequentialTask.cpp10
-rw-r--r--launcher/tasks/SequentialTask.h9
-rw-r--r--launcher/tasks/Task.h1
-rw-r--r--launcher/tools/MCEditTool.cpp2
-rw-r--r--launcher/ui/pages/global/LauncherPage.cpp12
-rw-r--r--launcher/ui/pages/global/LauncherPage.h1
-rw-r--r--launcher/ui/pages/global/LauncherPage.ui75
-rw-r--r--launcher/ui/pages/modplatform/ModPage.cpp2
-rw-r--r--launcher/ui/widgets/MCModInfoFrame.cpp2
-rw-r--r--nix/default.nix5
-rw-r--r--program_info/org.polymc.PolyMC.desktop.in2
51 files changed, 1588 insertions, 398 deletions
diff --git a/README.md b/README.md
index a5cc154f..3dbc19c1 100644
--- a/README.md
+++ b/README.md
@@ -47,7 +47,7 @@ If there are any issues with the space or you are using a client that does not s
[![Support](https://img.shields.io/matrix/polymc-support:matrix.org?label=PolyMC%20Support)](https://matrix.to/#/#polymc-support:matrix.org)
[![Voice](https://img.shields.io/matrix/polymc-voice:matrix.org?label=PolyMC%20Voice)](https://matrix.to/#/#polymc-voice:matrix.org)
-we also have a subreddit you can post your issues and suggestions on:
+We also have a subreddit you can post your issues and suggestions on:
[r/PolyMCLauncher](https://www.reddit.com/r/PolyMCLauncher/)
diff --git a/flake.lock b/flake.lock
index ccdd51da..120b11c5 100644
--- a/flake.lock
+++ b/flake.lock
@@ -34,11 +34,11 @@
},
"nixpkgs": {
"locked": {
- "lastModified": 1653326962,
- "narHash": "sha256-W8feCYqKTsMre4nAEpv5Kx1PVFC+hao/LwqtB2Wci/8=",
+ "lastModified": 1654665288,
+ "narHash": "sha256-7blJpfoZEu7GKb84uh3io/5eSJNdaagXD9d15P9iQMs=",
"owner": "nixos",
"repo": "nixpkgs",
- "rev": "41cc1d5d9584103be4108c1815c350e07c807036",
+ "rev": "43ecbe7840d155fa933ee8a500fb00dbbc651fc8",
"type": "github"
},
"original": {
diff --git a/flake.nix b/flake.nix
index f2247bed..b378fbb0 100644
--- a/flake.nix
+++ b/flake.nix
@@ -22,15 +22,17 @@
pkgs = forAllSystems (system: nixpkgs.legacyPackages.${system});
in
{
- packages = forAllSystems (system: {
+ packages = forAllSystems (system: rec {
polymc = pkgs.${system}.libsForQt5.callPackage ./nix { inherit version self libnbtplusplus; };
polymc-qt6 = pkgs.${system}.qt6Packages.callPackage ./nix { inherit version self libnbtplusplus; };
+
+ default = polymc;
});
- defaultPackage = forAllSystems (system: self.packages.${system}.polymc);
+ defaultPackage = forAllSystems (system: self.packages.${system}.default);
- apps = forAllSystems (system: { polymc = { type = "app"; program = "${self.defaultPackage.${system}}/bin/polymc"; }; });
- defaultApp = forAllSystems (system: self.apps.${system}.polymc);
+ apps = forAllSystems (system: rec { polymc = { type = "app"; program = "${self.defaultPackage.${system}}/bin/polymc"; }; default = polymc; });
+ defaultApp = forAllSystems (system: self.apps.${system}.default);
overlay = final: prev: { polymc = self.defaultPackage.${final.system}; };
};
diff --git a/launcher/Application.cpp b/launcher/Application.cpp
index 542b4d14..a4525d83 100644
--- a/launcher/Application.cpp
+++ b/launcher/Application.cpp
@@ -643,6 +643,9 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv)
// Minecraft launch method
m_settings->registerSetting("MCLaunchMethod", "LauncherPart");
+ // Minecraft mods
+ m_settings->registerSetting("ModMetadataDisabled", false);
+
// Minecraft offline player name
m_settings->registerSetting("LastOfflinePlayerName", "");
diff --git a/launcher/CMakeLists.txt b/launcher/CMakeLists.txt
index bbf80185..5397a988 100644
--- a/launcher/CMakeLists.txt
+++ b/launcher/CMakeLists.txt
@@ -324,19 +324,22 @@ set(MINECRAFT_SOURCES
minecraft/WorldList.h
minecraft/WorldList.cpp
+ minecraft/mod/MetadataHandler.h
minecraft/mod/Mod.h
minecraft/mod/Mod.cpp
minecraft/mod/ModDetails.h
minecraft/mod/ModFolderModel.h
minecraft/mod/ModFolderModel.cpp
- minecraft/mod/ModFolderLoadTask.h
- minecraft/mod/ModFolderLoadTask.cpp
- minecraft/mod/LocalModParseTask.h
- minecraft/mod/LocalModParseTask.cpp
minecraft/mod/ResourcePackFolderModel.h
minecraft/mod/ResourcePackFolderModel.cpp
minecraft/mod/TexturePackFolderModel.h
minecraft/mod/TexturePackFolderModel.cpp
+ minecraft/mod/tasks/ModFolderLoadTask.h
+ minecraft/mod/tasks/ModFolderLoadTask.cpp
+ minecraft/mod/tasks/LocalModParseTask.h
+ minecraft/mod/tasks/LocalModParseTask.cpp
+ minecraft/mod/tasks/LocalModUpdateTask.h
+ minecraft/mod/tasks/LocalModUpdateTask.cpp
# Assets
minecraft/AssetsUtils.h
@@ -499,6 +502,9 @@ set(META_SOURCES
)
set(API_SOURCES
+ modplatform/ModIndex.h
+ modplatform/ModIndex.cpp
+
modplatform/ModAPI.h
modplatform/flame/FlameAPI.h
@@ -545,6 +551,17 @@ set(MODPACKSCH_SOURCES
modplatform/modpacksch/FTBPackManifest.cpp
)
+set(PACKWIZ_SOURCES
+ modplatform/packwiz/Packwiz.h
+ modplatform/packwiz/Packwiz.cpp
+)
+
+add_unit_test(Packwiz
+ SOURCES modplatform/packwiz/Packwiz_test.cpp
+ DATA modplatform/packwiz/testdata
+ LIBS Launcher_logic
+ )
+
set(TECHNIC_SOURCES
modplatform/technic/SingleZipPackInstallTask.h
modplatform/technic/SingleZipPackInstallTask.cpp
@@ -598,6 +615,7 @@ set(LOGIC_SOURCES
${FLAME_SOURCES}
${MODRINTH_SOURCES}
${MODPACKSCH_SOURCES}
+ ${PACKWIZ_SOURCES}
${TECHNIC_SOURCES}
${ATLAUNCHER_SOURCES}
)
diff --git a/launcher/LaunchController.cpp b/launcher/LaunchController.cpp
index 002c08b9..d36ee3fe 100644
--- a/launcher/LaunchController.cpp
+++ b/launcher/LaunchController.cpp
@@ -105,6 +105,11 @@ void LaunchController::decideAccount()
// Open the account manager.
APPLICATION->ShowGlobalSettings(m_parentWidget, "accounts");
}
+ else if (reply == QMessageBox::No)
+ {
+ // Do not open "profile select" dialog.
+ return;
+ }
}
m_accountToUse = accounts->defaultAccount();
diff --git a/launcher/MMCZip.cpp b/launcher/MMCZip.cpp
index 8591fcc0..627ceaf1 100644
--- a/launcher/MMCZip.cpp
+++ b/launcher/MMCZip.cpp
@@ -151,23 +151,23 @@ bool MMCZip::createModdedJar(QString sourceJarPath, QString targetJarPath, const
continue;
if (mod.type() == Mod::MOD_ZIPFILE)
{
- if (!mergeZipFiles(&zipOut, mod.filename(), addedFiles))
+ if (!mergeZipFiles(&zipOut, mod.fileinfo(), addedFiles))
{
zipOut.close();
QFile::remove(targetJarPath);
- qCritical() << "Failed to add" << mod.filename().fileName() << "to the jar.";
+ qCritical() << "Failed to add" << mod.fileinfo().fileName() << "to the jar.";
return false;
}
}
else if (mod.type() == Mod::MOD_SINGLEFILE)
{
// FIXME: buggy - does not work with addedFiles
- auto filename = mod.filename();
+ auto filename = mod.fileinfo();
if (!JlCompress::compressFile(&zipOut, filename.absoluteFilePath(), filename.fileName()))
{
zipOut.close();
QFile::remove(targetJarPath);
- qCritical() << "Failed to add" << mod.filename().fileName() << "to the jar.";
+ qCritical() << "Failed to add" << mod.fileinfo().fileName() << "to the jar.";
return false;
}
addedFiles.insert(filename.fileName());
@@ -176,7 +176,7 @@ bool MMCZip::createModdedJar(QString sourceJarPath, QString targetJarPath, const
{
// untested, but seems to be unused / not possible to reach
// FIXME: buggy - does not work with addedFiles
- auto filename = mod.filename();
+ auto filename = mod.fileinfo();
QString what_to_zip = filename.absoluteFilePath();
QDir dir(what_to_zip);
dir.cdUp();
@@ -193,7 +193,7 @@ bool MMCZip::createModdedJar(QString sourceJarPath, QString targetJarPath, const
{
zipOut.close();
QFile::remove(targetJarPath);
- qCritical() << "Failed to add" << mod.filename().fileName() << "to the jar.";
+ qCritical() << "Failed to add" << mod.fileinfo().fileName() << "to the jar.";
return false;
}
qDebug() << "Adding folder " << filename.fileName() << " from "
@@ -204,7 +204,7 @@ bool MMCZip::createModdedJar(QString sourceJarPath, QString targetJarPath, const
// Make sure we do not continue launching when something is missing or undefined...
zipOut.close();
QFile::remove(targetJarPath);
- qCritical() << "Failed to add unknown mod type" << mod.filename().fileName() << "to the jar.";
+ qCritical() << "Failed to add unknown mod type" << mod.fileinfo().fileName() << "to the jar.";
return false;
}
}
diff --git a/launcher/ModDownloadTask.cpp b/launcher/ModDownloadTask.cpp
index 08a02d29..301b6637 100644
--- a/launcher/ModDownloadTask.cpp
+++ b/launcher/ModDownloadTask.cpp
@@ -1,24 +1,47 @@
+// SPDX-License-Identifier: GPL-3.0-only
+/*
+* PolyMC - Minecraft Launcher
+* Copyright (c) 2022 flowln <flowlnlnln@gmail.com>
+*
+* 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/>.
+*/
+
#include "ModDownloadTask.h"
+
#include "Application.h"
+#include "minecraft/mod/ModFolderModel.h"
-ModDownloadTask::ModDownloadTask(const QUrl sourceUrl,const QString filename, const std::shared_ptr<ModFolderModel> mods)
-: m_sourceUrl(sourceUrl), mods(mods), filename(filename) {
-}
+ModDownloadTask::ModDownloadTask(ModPlatform::IndexedPack mod, ModPlatform::IndexedVersion version, const std::shared_ptr<ModFolderModel> mods)
+ : m_mod(mod), m_mod_version(version), mods(mods)
+{
+ m_update_task.reset(new LocalModUpdateTask(mods->indexDir(), m_mod, m_mod_version));
-void ModDownloadTask::executeTask() {
- setStatus(tr("Downloading mod:\n%1").arg(m_sourceUrl.toString()));
+ addTask(m_update_task);
m_filesNetJob.reset(new NetJob(tr("Mod download"), APPLICATION->network()));
- m_filesNetJob->addNetAction(Net::Download::makeFile(m_sourceUrl, mods->dir().absoluteFilePath(filename)));
+ m_filesNetJob->setStatus(tr("Downloading mod:\n%1").arg(m_mod_version.downloadUrl));
+
+ m_filesNetJob->addNetAction(Net::Download::makeFile(m_mod_version.downloadUrl, mods->dir().absoluteFilePath(getFilename())));
connect(m_filesNetJob.get(), &NetJob::succeeded, this, &ModDownloadTask::downloadSucceeded);
connect(m_filesNetJob.get(), &NetJob::progress, this, &ModDownloadTask::downloadProgressChanged);
connect(m_filesNetJob.get(), &NetJob::failed, this, &ModDownloadTask::downloadFailed);
- m_filesNetJob->start();
+
+ addTask(m_filesNetJob);
+
}
void ModDownloadTask::downloadSucceeded()
{
- emitSucceeded();
m_filesNetJob.reset();
}
@@ -32,8 +55,3 @@ void ModDownloadTask::downloadProgressChanged(qint64 current, qint64 total)
{
emit progress(current, total);
}
-
-bool ModDownloadTask::abort() {
- return m_filesNetJob->abort();
-}
-
diff --git a/launcher/ModDownloadTask.h b/launcher/ModDownloadTask.h
index ddada5a2..f4438a8d 100644
--- a/launcher/ModDownloadTask.h
+++ b/launcher/ModDownloadTask.h
@@ -1,28 +1,44 @@
+// SPDX-License-Identifier: GPL-3.0-only
+/*
+* PolyMC - Minecraft Launcher
+* Copyright (c) 2022 flowln <flowlnlnln@gmail.com>
+*
+* 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 "QObjectPtr.h"
-#include "tasks/Task.h"
-#include "minecraft/mod/ModFolderModel.h"
+
#include "net/NetJob.h"
-#include <QUrl>
+#include "tasks/SequentialTask.h"
+#include "modplatform/ModIndex.h"
+#include "minecraft/mod/tasks/LocalModUpdateTask.h"
-class ModDownloadTask : public Task {
+class ModFolderModel;
+
+class ModDownloadTask : public SequentialTask {
Q_OBJECT
public:
- explicit ModDownloadTask(const QUrl sourceUrl, const QString filename, const std::shared_ptr<ModFolderModel> mods);
- const QString& getFilename() const { return filename; }
-
-public slots:
- bool abort() override;
-protected:
- //! Entry point for tasks.
- void executeTask() override;
+ explicit ModDownloadTask(ModPlatform::IndexedPack mod, ModPlatform::IndexedVersion version, const std::shared_ptr<ModFolderModel> mods);
+ const QString& getFilename() const { return m_mod_version.fileName; }
private:
- QUrl m_sourceUrl;
- NetJob::Ptr m_filesNetJob;
+ ModPlatform::IndexedPack m_mod;
+ ModPlatform::IndexedVersion m_mod_version;
const std::shared_ptr<ModFolderModel> mods;
- const QString filename;
+
+ NetJob::Ptr m_filesNetJob;
+ LocalModUpdateTask::Ptr m_update_task;
void downloadProgressChanged(qint64 current, qint64 total);
diff --git a/launcher/UpdateController.cpp b/launcher/UpdateController.cpp
index 646f8e57..c27fe772 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) || defined (Q_OS_OPENBSD)
+#elif defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD)
QString finishCmd = FS::PathCombine(m_root, BuildConfig.LAUNCHER_NAME);
#elif defined Q_OS_MAC
QString finishCmd = QApplication::applicationFilePath();
diff --git a/launcher/main.cpp b/launcher/main.cpp
index 85c5fdee..3d25b4ff 100644
--- a/launcher/main.cpp
+++ b/launcher/main.cpp
@@ -27,10 +27,6 @@ int main(int argc, char *argv[])
QApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);
-#if (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0))
- QApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::PassThrough);
-#endif
-
// initialize Qt
Application app(argc, argv);
diff --git a/launcher/minecraft/MinecraftInstance.cpp b/launcher/minecraft/MinecraftInstance.cpp
index 61326fac..2f339014 100644
--- a/launcher/minecraft/MinecraftInstance.cpp
+++ b/launcher/minecraft/MinecraftInstance.cpp
@@ -659,23 +659,23 @@ QStringList MinecraftInstance::verboseDescription(AuthSessionPtr session, Minecr
out << QString("%1:").arg(label);
auto modList = model.allMods();
std::sort(modList.begin(), modList.end(), [](Mod &a, Mod &b) {
- auto aName = a.filename().completeBaseName();
- auto bName = b.filename().completeBaseName();
+ auto aName = a.fileinfo().completeBaseName();
+ auto bName = b.fileinfo().completeBaseName();
return aName.localeAwareCompare(bName) < 0;
});
for(auto & mod: modList)
{
if(mod.type() == Mod::MOD_FOLDER)
{
- out << u8" [📁] " + mod.filename().completeBaseName() + " (folder)";
+ out << u8" [📁] " + mod.fileinfo().completeBaseName() + " (folder)";
continue;
}
if(mod.enabled()) {
- out << u8" [✔️] " + mod.filename().completeBaseName();
+ out << u8" [✔️] " + mod.fileinfo().completeBaseName();
}
else {
- out << u8" [❌] " + mod.filename().completeBaseName() + " (disabled)";
+ out << u8" [❌] " + mod.fileinfo().completeBaseName() + " (disabled)";
}
}
diff --git a/launcher/minecraft/mod/MetadataHandler.h b/launcher/minecraft/mod/MetadataHandler.h
new file mode 100644
index 00000000..56962818
--- /dev/null
+++ b/launcher/minecraft/mod/MetadataHandler.h
@@ -0,0 +1,59 @@
+// SPDX-License-Identifier: GPL-3.0-only
+/*
+* PolyMC - Minecraft Launcher
+* Copyright (c) 2022 flowln <flowlnlnln@gmail.com>
+*
+* 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 <memory>
+
+#include "modplatform/packwiz/Packwiz.h"
+
+// launcher/minecraft/mod/Mod.h
+class Mod;
+
+/* Abstraction file for easily changing the way metadata is stored / handled
+ * Needs to be a class because of -Wunused-function and no C++17 [[maybe_unused]]
+ * */
+class Metadata {
+ public:
+ using ModStruct = Packwiz::V1::Mod;
+
+ static auto create(QDir& index_dir, ModPlatform::IndexedPack& mod_pack, ModPlatform::IndexedVersion& mod_version) -> ModStruct
+ {
+ return Packwiz::V1::createModFormat(index_dir, mod_pack, mod_version);
+ }
+
+ static auto create(QDir& index_dir, Mod& internal_mod) -> ModStruct
+ {
+ return Packwiz::V1::createModFormat(index_dir, internal_mod);
+ }
+
+ static void update(QDir& index_dir, ModStruct& mod)
+ {
+ Packwiz::V1::updateModIndex(index_dir, mod);
+ }
+
+ static void remove(QDir& index_dir, QString& mod_name)
+ {
+ Packwiz::V1::deleteModIndex(index_dir, mod_name);
+ }
+
+ static auto get(QDir& index_dir, QString& mod_name) -> ModStruct
+ {
+ return Packwiz::V1::getIndexForMod(index_dir, mod_name);
+ }
+};
diff --git a/launcher/minecraft/mod/Mod.cpp b/launcher/minecraft/mod/Mod.cpp
index b6bff29b..71a32d32 100644
--- a/launcher/minecraft/mod/Mod.cpp
+++ b/launcher/minecraft/mod/Mod.cpp
@@ -1,24 +1,48 @@
-/* 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.
- */
+// SPDX-License-Identifier: GPL-3.0-only
+/*
+* PolyMC - Minecraft Launcher
+* Copyright (c) 2022 flowln <flowlnlnln@gmail.com>
+*
+* 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/>.
+*
+* 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.
+*/
+
+#include "Mod.h"