aboutsummaryrefslogtreecommitdiff
path: root/launcher
diff options
context:
space:
mode:
authorRyan Cao <70191398+ryanccn@users.noreply.github.com>2022-06-01 00:12:14 +0800
committerGitHub <noreply@github.com>2022-06-01 00:12:14 +0800
commite06bf17d13b991fea5e49ff23b6fe9c8f5540e02 (patch)
tree3456de4848d8ef68f954a1fe5c288e62a075d789 /launcher
parent9673dac22b0ff81a54847d5db5438c099a6df587 (diff)
parent04a3669fc470130a5d7f2dfd32f06a3f2aceb165 (diff)
downloadPrismLauncher-e06bf17d13b991fea5e49ff23b6fe9c8f5540e02.tar.gz
PrismLauncher-e06bf17d13b991fea5e49ff23b6fe9c8f5540e02.tar.bz2
PrismLauncher-e06bf17d13b991fea5e49ff23b6fe9c8f5540e02.zip
Merge branch 'PolyMC:develop' into macos-app-heuristic
Diffstat (limited to 'launcher')
-rw-r--r--launcher/CMakeLists.txt7
-rw-r--r--launcher/InstanceImportTask.cpp268
-rw-r--r--launcher/InstanceImportTask.h6
-rw-r--r--launcher/icons/IconList.cpp4
-rw-r--r--launcher/modplatform/ModAPI.h2
-rw-r--r--launcher/modplatform/atlauncher/ATLPackInstallTask.cpp43
-rw-r--r--launcher/modplatform/atlauncher/ATLPackManifest.cpp16
-rw-r--r--launcher/modplatform/atlauncher/ATLPackManifest.h16
-rw-r--r--launcher/modplatform/flame/FileResolvingTask.cpp124
-rw-r--r--launcher/modplatform/flame/FileResolvingTask.h8
-rw-r--r--launcher/modplatform/flame/FlamePackIndex.cpp12
-rw-r--r--launcher/modplatform/flame/FlamePackIndex.h1
-rw-r--r--launcher/modplatform/flame/PackManifest.cpp35
-rw-r--r--launcher/modplatform/flame/PackManifest.h10
-rw-r--r--launcher/modplatform/modrinth/ModrinthAPI.h8
-rw-r--r--launcher/modplatform/modrinth/ModrinthPackManifest.cpp22
-rw-r--r--launcher/net/Upload.cpp199
-rw-r--r--launcher/net/Upload.h31
-rw-r--r--launcher/tasks/SequentialTask.cpp19
-rw-r--r--launcher/ui/dialogs/ModDownloadDialog.cpp24
-rw-r--r--launcher/ui/dialogs/ModDownloadDialog.h3
-rw-r--r--launcher/ui/dialogs/ProgressDialog.cpp91
-rw-r--r--launcher/ui/dialogs/ProgressDialog.ui6
-rw-r--r--launcher/ui/dialogs/ReviewMessageBox.cpp27
-rw-r--r--launcher/ui/dialogs/ReviewMessageBox.h12
-rw-r--r--launcher/ui/dialogs/ReviewMessageBox.ui81
-rw-r--r--launcher/ui/dialogs/ScrollMessageBox.cpp15
-rw-r--r--launcher/ui/dialogs/ScrollMessageBox.h20
-rw-r--r--launcher/ui/dialogs/ScrollMessageBox.ui84
-rw-r--r--launcher/ui/pages/global/APIPage.cpp3
-rw-r--r--launcher/ui/pages/global/APIPage.ui14
-rw-r--r--launcher/ui/pages/global/JavaPage.cpp6
-rw-r--r--launcher/ui/pages/global/JavaPage.ui69
-rw-r--r--launcher/ui/pages/instance/ModFolderPage.cpp5
-rw-r--r--launcher/ui/pages/modplatform/ImportPage.cpp4
-rw-r--r--launcher/ui/pages/modplatform/ModModel.cpp55
-rw-r--r--launcher/ui/pages/modplatform/ModPage.h1
-rw-r--r--launcher/ui/pages/modplatform/flame/FlamePage.cpp2
-rw-r--r--launcher/ui/pages/modplatform/legacy_ftb/Page.cpp2
39 files changed, 1014 insertions, 341 deletions
diff --git a/launcher/CMakeLists.txt b/launcher/CMakeLists.txt
index 15534c71..bbf80185 100644
--- a/launcher/CMakeLists.txt
+++ b/launcher/CMakeLists.txt
@@ -128,6 +128,8 @@ set(NET_SOURCES
net/PasteUpload.h
net/Sink.h
net/Validator.h
+ net/Upload.cpp
+ net/Upload.h
)
# Game launch logic
@@ -837,6 +839,8 @@ SET(LAUNCHER_SOURCES
ui/dialogs/SkinUploadDialog.h
ui/dialogs/ModDownloadDialog.cpp
ui/dialogs/ModDownloadDialog.h
+ ui/dialogs/ScrollMessageBox.cpp
+ ui/dialogs/ScrollMessageBox.h
# GUI - widgets
ui/widgets/Common.cpp
@@ -940,6 +944,7 @@ qt5_wrap_ui(LAUNCHER_UI
ui/dialogs/LoginDialog.ui
ui/dialogs/EditAccountDialog.ui
ui/dialogs/ReviewMessageBox.ui
+ ui/dialogs/ScrollMessageBox.ui
)
qt5_add_resources(LAUNCHER_RESOURCES
@@ -958,7 +963,7 @@ qt5_add_resources(LAUNCHER_RESOURCES
######## Windows resource files ########
if(WIN32)
- set(LAUNCHER_RCS ../${Launcher_Branding_WindowsRC})
+ set(LAUNCHER_RCS ${CMAKE_CURRENT_BINARY_DIR}/../${Launcher_Branding_WindowsRC})
endif()
# Add executable
diff --git a/launcher/InstanceImportTask.cpp b/launcher/InstanceImportTask.cpp
index 4bad7251..09c2a333 100644
--- a/launcher/InstanceImportTask.cpp
+++ b/launcher/InstanceImportTask.cpp
@@ -60,9 +60,9 @@
#include "net/ChecksumValidator.h"
#include "ui/dialogs/CustomMessageBox.h"
+#include "ui/dialogs/ScrollMessageBox.h"
#include <algorithm>
-#include <iterator>
InstanceImportTask::InstanceImportTask(const QUrl sourceUrl, QWidget* parent)
{
@@ -72,7 +72,8 @@ InstanceImportTask::InstanceImportTask(const QUrl sourceUrl, QWidget* parent)
bool InstanceImportTask::abort()
{
- m_filesNetJob->abort();
+ if (m_filesNetJob)
+ m_filesNetJob->abort();
m_extractFuture.cancel();
return false;
@@ -135,18 +136,20 @@ void InstanceImportTask::processZipPack()
return;
}
- QStringList blacklist = {"instance.cfg", "manifest.json"};
- QString mmcFound = MMCZip::findFolderOfFileInZip(m_packZip.get(), "instance.cfg");
- bool technicFound = QuaZipDir(m_packZip.get()).exists("/bin/modpack.jar") || QuaZipDir(m_packZip.get()).exists("/bin/version.json");
- QString flameFound = MMCZip::findFolderOfFileInZip(m_packZip.get(), "manifest.json");
- QString modrinthFound = MMCZip::findFolderOfFileInZip(m_packZip.get(), "modrinth.index.json");
+ QuaZipDir packZipDir(m_packZip.get());
+
+ // https://docs.modrinth.com/docs/modpacks/format_definition/#storage
+ bool modrinthFound = packZipDir.exists("/modrinth.index.json");
+ bool technicFound = packZipDir.exists("/bin/modpack.jar") || packZipDir.exists("/bin/version.json");
QString root;
- if(!mmcFound.isNull())
+
+ // NOTE: Prioritize modpack platforms that aren't searched for recursively.
+ // Especially Flame has a very common filename for its manifest, which may appear inside overrides for example
+ if(modrinthFound)
{
- // process as MultiMC instance/pack
- qDebug() << "MultiMC:" << mmcFound;
- root = mmcFound;
- m_modpackType = ModpackType::MultiMC;
+ // process as Modrinth pack
+ qDebug() << "Modrinth:" << modrinthFound;
+ m_modpackType = ModpackType::Modrinth;
}
else if (technicFound)
{
@@ -156,19 +159,25 @@ void InstanceImportTask::processZipPack()
extractDir.cd(".minecraft");
m_modpackType = ModpackType::Technic;
}
- else if(!flameFound.isNull())
- {
- // process as Flame pack
- qDebug() << "Flame:" << flameFound;
- root = flameFound;
- m_modpackType = ModpackType::Flame;
- }
- else if(!modrinthFound.isNull())
+ else
{
- // process as Modrinth pack
- qDebug() << "Modrinth:" << modrinthFound;
- root = modrinthFound;
- m_modpackType = ModpackType::Modrinth;
+ QString mmcRoot = MMCZip::findFolderOfFileInZip(m_packZip.get(), "instance.cfg");
+ QString flameRoot = MMCZip::findFolderOfFileInZip(m_packZip.get(), "manifest.json");
+
+ if (!mmcRoot.isNull())
+ {
+ // process as MultiMC instance/pack
+ qDebug() << "MultiMC:" << mmcRoot;
+ root = mmcRoot;
+ m_modpackType = ModpackType::MultiMC;
+ }
+ else if(!flameRoot.isNull())
+ {
+ // process as Flame pack
+ qDebug() << "Flame:" << flameRoot;
+ root = flameRoot;
+ m_modpackType = ModpackType::Flame;
+ }
}
if(m_modpackType == ModpackType::Unknown)
{
@@ -385,61 +394,136 @@ void InstanceImportTask::processFlame()
connect(m_modIdResolver.get(), &Flame::FileResolvingTask::succeeded, [&]()
{
auto results = m_modIdResolver->getResults();
- m_filesNetJob = new NetJob(tr("Mod download"), APPLICATION->network());
- for(auto result: results.files)
- {
- QString filename = result.fileName;
- if(!result.required)
- {
- filename += ".disabled";
+ //first check for blocked mods
+ QString text;
+ auto anyBlocked = false;
+ for(const auto& result: results.files.values()) {
+ if (!result.resolved || result.url.isEmpty()) {
+ text += QString("%1: <a href='%2'>%2</a><br/>").arg(result.fileName, result.websiteUrl);
+ anyBlocked = true;
}
+ }
+ if(anyBlocked) {
+ qWarning() << "Blocked mods found, displaying mod list";
+
+ auto message_dialog = new ScrollMessageBox(m_parent,
+ tr("Blocked mods found"),
+ tr("The following mods were blocked on third party launchers.<br/>"
+ "You will need to manually download them and add them to the modpack"),
+ text);
+ message_dialog->setModal(true);
+ message_dialog->show();
+ connect(message_dialog, &QDialog::rejected, [&]() {
+ m_modIdResolver.reset();
+ emitFailed("Canceled");
+ });
+ connect(message_dialog, &QDialog::accepted, [&]() {
+ m_filesNetJob = new NetJob(tr("Mod download"), APPLICATION->network());
+ for (const auto &result: m_modIdResolver->getResults().files) {
+ QString filename = result.fileName;
+ if (!result.required) {
+ filename += ".disabled";
+ }
- auto relpath = FS::PathCombine("minecraft", result.targetFolder, filename);
- auto path = FS::PathCombine(m_stagingPath , relpath);
+ auto relpath = FS::PathCombine("minecraft", result.targetFolder, filename);
+ auto path = FS::PathCombine(m_stagingPath, relpath);
- switch(result.type)
- {
- case Flame::File::Type::Folder:
- {
- logWarning(tr("This 'Folder' may need extracting: %1").arg(relpath));
- // fall-through intentional, we treat these as plain old mods and dump them wherever.
+ switch (result.type) {
+ case Flame::File::Type::Folder: {
+ logWarning(tr("This 'Folder' may need extracting: %1").arg(relpath));
+ // fall-through intentional, we treat these as plain old mods and dump them wherever.
+ }
+ case Flame::File::Type::SingleFile:
+ case Flame::File::Type::Mod: {
+ if (!result.url.isEmpty()) {
+ qDebug() << "Will download" << result.url << "to" << path;
+ auto dl = Net::Download::makeFile(result.url, path);
+ m_filesNetJob->addNetAction(dl);
+ }
+ break;
+ }
+ case Flame::File::Type::Modpack:
+ logWarning(
+ tr("Nesting modpacks in modpacks is not implemented, nothing was downloaded: %1").arg(
+ relpath));
+ break;
+ case Flame::File::Type::Cmod2:
+ case Flame::File::Type::Ctoc:
+ case Flame::File::Type::Unknown:
+ logWarning(tr("Unrecognized/unhandled PackageType for: %1").arg(relpath));
+ break;
+ }
}
- case Flame::File::Type::SingleFile:
- case Flame::File::Type::Mod:
- {
- qDebug() << "Will download" << result.url << "to" << path;
- auto dl = Net::Download::makeFile(result.url, path);
- m_filesNetJob->addNetAction(dl);
- break;
+ m_modIdResolver.reset();
+ connect(m_filesNetJob.get(), &NetJob::succeeded, this, [&]() {
+ m_filesNetJob.reset();
+ emitSucceeded();
+ }
+ );
+ connect(m_filesNetJob.get(), &NetJob::failed, [&](QString reason) {
+ m_filesNetJob.reset();
+ emitFailed(reason);
+ });
+ connect(m_filesNetJob.get(), &NetJob::progress, [&](qint64 current, qint64 total) {
+ setProgress(current, total);
+ });
+ setStatus(tr("Downloading mods..."));
+ m_filesNetJob->start();
+ });
+ }else{
+ //TODO extract to function ?
+ m_filesNetJob = new NetJob(tr("Mod download"), APPLICATION->network());
+ for (const auto &result: m_modIdResolver->getResults().files) {
+ QString filename = result.fileName;
+ if (!result.required) {
+ filename += ".disabled";
+ }
+
+ auto relpath = FS::PathCombine("minecraft", result.targetFolder, filename);
+ auto path = FS::PathCombine(m_stagingPath, relpath);
+
+ switch (result.type) {
+ case Flame::File::Type::Folder: {
+ logWarning(tr("This 'Folder' may need extracting: %1").arg(relpath));
+ // fall-through intentional, we treat these as plain old mods and dump them wherever.
+ }
+ case Flame::File::Type::SingleFile:
+ case Flame::File::Type::Mod: {
+ if (!result.url.isEmpty()) {
+ qDebug() << "Will download" << result.url << "to" << path;
+ auto dl = Net::Download::makeFile(result.url, path);
+ m_filesNetJob->addNetAction(dl);
+ }
+ break;
+ }
+ case Flame::File::Type::Modpack:
+ logWarning(
+ tr("Nesting modpacks in modpacks is not implemented, nothing was downloaded: %1").arg(
+ relpath));
+ break;
+ case Flame::File::Type::Cmod2:
+ case Flame::File::Type::Ctoc:
+ case Flame::File::Type::Unknown:
+ logWarning(tr("Unrecognized/unhandled PackageType for: %1").arg(relpath));
+ break;
}
- case Flame::File::Type::Modpack:
- logWarning(tr("Nesting modpacks in modpacks is not implemented, nothing was downloaded: %1").arg(relpath));
- break;
- case Flame::File::Type::Cmod2:
- case Flame::File::Type::Ctoc:
- case Flame::File::Type::Unknown:
- logWarning(tr("Unrecognized/unhandled PackageType for: %1").arg(relpath));
- break;
}
+ m_modIdResolver.reset();
+ connect(m_filesNetJob.get(), &NetJob::succeeded, this, [&]() {
+ m_filesNetJob.reset();
+ emitSucceeded();
+ }
+ );
+ connect(m_filesNetJob.get(), &NetJob::failed, [&](QString reason) {
+ m_filesNetJob.reset();
+ emitFailed(reason);
+ });
+ connect(m_filesNetJob.get(), &NetJob::progress, [&](qint64 current, qint64 total) {
+ setProgress(current, total);
+ });
+ setStatus(tr("Downloading mods..."));
+ m_filesNetJob->start();
}
- m_modIdResolver.reset();
- connect(m_filesNetJob.get(), &NetJob::succeeded, this, [&]()
- {
- m_filesNetJob.reset();
- emitSucceeded();
- }
- );
- connect(m_filesNetJob.get(), &NetJob::failed, [&](QString reason)
- {
- m_filesNetJob.reset();
- emitFailed(reason);
- });
- connect(m_filesNetJob.get(), &NetJob::progress, [&](qint64 current, qint64 total)
- {
- setProgress(current, total);
- });
- setStatus(tr("Downloading mods..."));
- m_filesNetJob->start();
}
);
connect(m_modIdResolver.get(), &Flame::FileResolvingTask::failed, [&](QString reason)
@@ -501,6 +585,7 @@ void InstanceImportTask::processMultiMC()
void InstanceImportTask::processModrinth()
{
std::vector<Modrinth::File> files;
+ std::vector<Modrinth::File> non_whitelisted_files;
QString minecraftVersion, fabricVersion, quiltVersion, forgeVersion;
try {
QString indexPath = FS::PathCombine(m_stagingPath, "modrinth.index.json");
@@ -515,11 +600,11 @@ void InstanceImportTask::processModrinth()
auto jsonFiles = Json::requireIsArrayOf<QJsonObject>(obj, "files", "modrinth.index.json");
bool had_optional = false;
- for (auto& obj : jsonFiles) {
+ for (auto& modInfo : jsonFiles) {
Modrinth::File file;
- file.path = Json::requireString(obj, "path");
+ file.path = Json::requireString(modInfo, "path");
- auto env = Json::ensureObject(obj, "env");
+ auto env = Json::ensureObject(modInfo, "env");
QString support = Json::ensureString(env, "client", "unsupported");
if (support == "unsupported") {
continue;
@@ -537,7 +622,7 @@ void InstanceImportTask::processModrinth()
file.path += ".disabled";
}
- QJsonObject hashes = Json::requireObject(obj, "hashes");
+ QJsonObject hashes = Json::requireObject(modInfo, "hashes");
QString hash;
QCryptographicHash::Algorithm hashAlgorithm;
hash = Json::ensureString(hashes, "sha1");
@@ -557,13 +642,38 @@ void InstanceImportTask::processModrinth()
file.hashAlgorithm = hashAlgorithm;
// Do not use requireUrl, which uses StrictMode, instead use QUrl's default TolerantMode
// (as Modrinth seems to incorrectly handle spaces)
- file.download = Json::requireString(Json::ensureArray(obj, "downloads").first(), "Download URL for " + file.path);
- if (!file.download.isValid() || !Modrinth::validateDownloadUrl(file.download)) {
- throw JSONValidationError("Download URL for " + file.path + " is not a correctly formatted URL");
+
+ file.download = Json::requireString(Json::ensureArray(modInfo, "downloads").first(), "Download URL for " + file.path);
+
+ if (!file.download.isValid()) {
+ qDebug() << QString("Download URL (%1) for %2 is not a correctly formatted URL").arg(file.download.toString(), file.path);
+ throw JSONValidationError(tr("Download URL for %1 is not a correctly formatted URL").arg(file.path));
+ }
+ else if (!Modrinth::validateDownloadUrl(file.download)) {
+ qDebug() << QString("Download URL (%1) for %2 is from a non-whitelisted by Modrinth domain").arg(file.download.toString(), file.path);
+ non_whitelisted_files.push_back(file);
}
+
files.push_back(file);
}
+ if (!non_whitelisted_files.empty()) {
+ QString text;
+ for (const auto& file : non_whitelisted_files) {
+ text += tr("Filepath: %1<br>URL: <a href='%2'>%2</a><br>").arg(file.path, file.download.toString());
+ }
+
+ auto message_dialog = new ScrollMessageBox(m_parent, tr("Non-whitelisted mods found"),
+ tr("The following mods have URLs that are not whitelisted by Modrinth.\n"
+ "Proceed with caution!"),
+ text);
+ message_dialog->setModal(true);
+ if (message_dialog->exec() == QDialog::Rejected) {
+ emitFailed("Aborted");
+ return;
+ }
+ }
+
auto dependencies = Json::requireObject(obj, "dependencies", "modrinth.index.json");
for (auto it = dependencies.begin(), end = dependencies.end(); it != end; ++it) {
QString name = it.key();
diff --git a/launcher/InstanceImportTask.h b/launcher/InstanceImportTask.h
index 5e4d3235..b67d48f3 100644
--- a/launcher/InstanceImportTask.h
+++ b/launcher/InstanceImportTask.h
@@ -42,6 +42,7 @@
#include <QFutureWatcher>
#include "settings/SettingsObject.h"
#include "QObjectPtr.h"
+#include "modplatform/flame/PackManifest.h"
#include <nonstd/optional>
@@ -59,6 +60,10 @@ public:
bool canAbort() const override { return true; }
bool abort() override;
+ const QVector<Flame::File> &getBlockedFiles() const
+ {
+ return m_blockedMods;
+ }
protected:
//! Entry point for tasks.
@@ -87,6 +92,7 @@ private: /* data */
std::unique_ptr<QuaZip> m_packZip;
QFuture<nonstd::optional<QStringList>> m_extractFuture;
QFutureWatcher<nonstd::optional<QStringList>> m_extractFutureWatcher;
+ QVector<Flame::File> m_blockedMods;
enum class ModpackType{
Unknown,
MultiMC,
diff --git a/launcher/icons/IconList.cpp b/launcher/icons/IconList.cpp
index c269d10a..0ddfae55 100644
--- a/launcher/icons/IconList.cpp
+++ b/launcher/icons/IconList.cpp
@@ -273,7 +273,7 @@ void IconList::installIcons(const QStringList &iconFiles)
QFileInfo fileinfo(file);
if (!fileinfo.isReadable() || !fileinfo.isFile())
continue;
- QString target = FS::PathCombine(m_dir.dirName(), fileinfo.fileName());
+ QString target = FS::PathCombine(getDirectory(), fileinfo.fileName());
QString suffix = fileinfo.suffix();
if (suffix != "jpeg" && suffix != "png" && suffix != "jpg" && suffix != "ico" && suffix != "svg" && suffix != "gif")
@@ -290,7 +290,7 @@ void IconList::installIcon(const QString &file, const QString &name)
if(!fileinfo.isReadable() || !fileinfo.isFile())
return;
- QString target = FS::PathCombine(m_dir.dirName(), name);
+ QString target = FS::PathCombine(getDirectory(), name);
QFile::copy(file, target);
}
diff --git a/launcher/modplatform/ModAPI.h b/launcher/modplatform/ModAPI.h
index 4230df0b..eb0de3f0 100644
--- a/launcher/modplatform/ModAPI.h
+++ b/launcher/modplatform/ModAPI.h
@@ -68,7 +68,7 @@ class ModAPI {
{
QString s;
for(auto& ver : mcVersions){
- s += QString("%1,").arg(ver.toString());
+ s += QString("\"%1\",").arg(ver.toString());
}
s.remove(s.length() - 1, 1); //remove last comma
return s;
diff --git a/launcher/modplatform/atlauncher/ATLPackInstallTask.cpp b/launcher/modplatform/atlauncher/ATLPackInstallTask.cpp
index 9b14f355..62c7bf6d 100644
--- a/launcher/modplatform/atlauncher/ATLPackInstallTask.cpp
+++ b/launcher/modplatform/atlauncher/ATLPackInstallTask.cpp
@@ -414,7 +414,31 @@ bool PackInstallTask::createLibrariesComponent(QString instanceRoot, std::shared
bool PackInstallTask::createPackComponent(QString instanceRoot, std::shared_ptr<PackProfile> profile)
{
- if(m_version.mainClass == QString() && m_version.extraArguments == QString()) {
+ if (m_version.mainClass.mainClass.isEmpty() && m_version.extraArguments.arguments.isEmpty()) {
+ return true;
+ }
+
+ auto mainClass = m_version.mainClass.mainClass;
+ auto extraArguments = m_version.extraArguments.arguments;
+
+ auto hasMainClassDepends = !m_version.mainClass.depends.isEmpty();
+ auto hasExtraArgumentsDepends = !m_version.extraArguments.depends.isEmpty();
+ if (hasMainClassDepends || hasExtraArgumentsDepends) {
+ QSet<QString> mods;
+ for (const auto& item : m_version.mods) {
+ mods.insert(item.name);
+ }
+
+ if (hasMainClassDepends && !mods.contains(m_version.mainClass.depends)) {
+ mainClass = "";
+ }
+
+ if (hasExtraArgumentsDepends && !mods.contains(m_version.extraArguments.depends)) {
+ extraArguments = "";
+ }
+ }
+
+ if (mainClass.isEmpty() && extraArguments.isEmpty()) {
return true;
}
@@ -442,12 +466,12 @@ bool PackInstallTask::createPackComponent(QString instanceRoot, std::shared_ptr<
auto f = std::make_shared<VersionFile>();
f->name = m_pack + " " + m_version_name;
- if(m_version.mainClass != QString() && !mainClasses.contains(m_version.mainClass)) {
- f->mainClass = m_version.mainClass;
+ if (!mainClass.isEmpty() && !mainClasses.contains(mainClass)) {
+ f->mainClass = mainClass;
}
// Parse out tweakers
- auto args = m_version.extraArguments.split(" ");
+ auto args = extraArguments.split(" ");
QString previous;
for(auto arg : args) {
if(arg.startsWith("--tweakClass=") || previous == "--tweakClass") {
@@ -757,6 +781,17 @@ bool PackInstallTask::extractMods(
for (auto iter = toCopy.begin(); iter != toCopy.end(); iter++) {
auto &from = iter.key();
auto &to = iter.value();
+
+ // If the file already exists, assume the mod is the correct copy - and remove
+ // the copy from the Configs.zip
+ QFileInfo fileInfo(to);
+ if (fileInfo.exists()) {
+ if (!QFile::remove(to)) {
+ qWarning() << "Failed to delete" << to;
+ return false;
+ }
+ }
+
FS::copy fileCopyOperation(from, to);
if(!fileCopyOperation()) {
qWarning() << "Failed to copy" << from << "to" << to;
diff --git a/launcher/modplatform/atlauncher/ATLPackManifest.cpp b/launcher/modplatform/atlauncher/ATLPackManifest.cpp
index d01ec32c..3af02a09 100644
--- a/launcher/modplatform/atlauncher/ATLPackManifest.cpp
+++ b/launcher/modplatform/atlauncher/ATLPackManifest.cpp
@@ -212,6 +212,18 @@ static void loadVersionMessages(ATLauncher::VersionMessages& m, QJsonObject& obj
m.update = Json::ensureString(obj, "update", "");
}
+static void loadVersionMainClass(ATLauncher::PackVersionMainClass& m, QJsonObject& obj)
+{
+ m.mainClass = Json::ensureString(obj, "mainClass", "");
+ m.depends = Json::ensureString(obj, "depends", "");
+}
+
+static void loadVersionExtraArguments(ATLauncher::PackVersionExtraArguments& a, QJsonObject& obj)
+{
+ a.arguments = Json::ensureString(obj, "arguments", "");
+ a.depends = Json::ensureString(obj, "depends", "");
+}
+
void ATLauncher::loadVersion(PackVersion & v, QJsonObject & obj)
{
v.version = Json::requireString(obj, "version");
@@ -220,12 +232,12 @@ void ATLauncher::loadVersion(PackVersion & v, QJsonObject & obj)
if(obj.contains("mainClass")) {
auto main = Json::requireObject(obj, "mainClass");
- v.mainClass = Json::ensureString(main, "mainClass", "");
+ loadVersionMainClass(v.mainClass, main);
}
if(obj.contains("extraArguments")) {
auto arguments = Json::requireObject(obj, "extraArguments");
- v.extraArguments = Json::ensureString(arguments, "arguments", "");
+ loadVersionExtraArguments(v.extraArguments, arguments);
}
if(obj.contains("loader")) {
diff --git a/launcher/modplatform/atlauncher/ATLPackManifest.h b/launcher/modplatform/atlauncher/ATLPackManifest.h
index 23e162e3..43510c50 100644
--- a/launcher/modplatform/atlauncher/ATLPackManifest.h
+++ b/launcher/modplatform/atlauncher/ATLPackManifest.h
@@ -150,13 +150,25 @@ struct VersionMessages
QString update;
};
+struct PackVersionMainClass
+{
+ QString mainClass;
+ QString depends;
+};
+
+struct PackVersionExtraArguments
+{
+ QString arguments;
+ QString depends;
+};
+
struct PackVersion
{
QString version;
QString minecraft;
bool noConfigs;