aboutsummaryrefslogtreecommitdiff
path: root/launcher
diff options
context:
space:
mode:
Diffstat (limited to 'launcher')
-rw-r--r--launcher/CMakeLists.txt20
-rw-r--r--launcher/MMCZip.cpp30
-rw-r--r--launcher/MMCZip.h2
-rw-r--r--launcher/ModDownloadTask.cpp14
-rw-r--r--launcher/ModDownloadTask.h7
-rw-r--r--launcher/minecraft/MinecraftInstance.cpp24
-rw-r--r--launcher/minecraft/MinecraftInstance.h2
-rw-r--r--launcher/minecraft/mod/MetadataHandler.h22
-rw-r--r--launcher/minecraft/mod/Mod.cpp39
-rw-r--r--launcher/minecraft/mod/Mod.h12
-rw-r--r--launcher/minecraft/mod/ModFolderModel.cpp124
-rw-r--r--launcher/minecraft/mod/ModFolderModel.h18
-rw-r--r--launcher/minecraft/mod/tasks/LocalModParseTask.cpp9
-rw-r--r--launcher/minecraft/mod/tasks/LocalModUpdateTask.cpp17
-rw-r--r--launcher/minecraft/mod/tasks/LocalModUpdateTask.h3
-rw-r--r--launcher/minecraft/mod/tasks/ModFolderLoadTask.cpp33
-rw-r--r--launcher/minecraft/mod/tasks/ModFolderLoadTask.h2
-rw-r--r--launcher/modplatform/CheckUpdateTask.h51
-rw-r--r--launcher/modplatform/EnsureMetadataTask.cpp534
-rw-r--r--launcher/modplatform/EnsureMetadataTask.h54
-rw-r--r--launcher/modplatform/ModAPI.h4
-rw-r--r--launcher/modplatform/ModIndex.h8
-rw-r--r--launcher/modplatform/flame/FlameAPI.cpp148
-rw-r--r--launcher/modplatform/flame/FlameAPI.h8
-rw-r--r--launcher/modplatform/flame/FlameCheckUpdate.cpp179
-rw-r--r--launcher/modplatform/flame/FlameCheckUpdate.h25
-rw-r--r--launcher/modplatform/flame/FlameModIndex.cpp18
-rw-r--r--launcher/modplatform/flame/FlameModIndex.h2
-rw-r--r--launcher/modplatform/helpers/NetworkModAPI.cpp29
-rw-r--r--launcher/modplatform/helpers/NetworkModAPI.h2
-rw-r--r--launcher/modplatform/modrinth/ModrinthAPI.cpp108
-rw-r--r--launcher/modplatform/modrinth/ModrinthAPI.h28
-rw-r--r--launcher/modplatform/modrinth/ModrinthCheckUpdate.cpp174
-rw-r--r--launcher/modplatform/modrinth/ModrinthCheckUpdate.h23
-rw-r--r--launcher/modplatform/modrinth/ModrinthPackIndex.cpp41
-rw-r--r--launcher/modplatform/modrinth/ModrinthPackIndex.h2
-rw-r--r--launcher/modplatform/packwiz/Packwiz.cpp69
-rw-r--r--launcher/modplatform/packwiz/Packwiz.h23
-rw-r--r--launcher/modplatform/packwiz/Packwiz_test.cpp7
-rw-r--r--launcher/net/Upload.cpp10
-rw-r--r--launcher/net/Upload.h2
-rw-r--r--launcher/tasks/MultipleOptionsTask.cpp48
-rw-r--r--launcher/tasks/MultipleOptionsTask.h19
-rw-r--r--launcher/tasks/SequentialTask.cpp20
-rw-r--r--launcher/tasks/SequentialTask.h16
-rw-r--r--launcher/ui/dialogs/ChooseProviderDialog.cpp96
-rw-r--r--launcher/ui/dialogs/ChooseProviderDialog.h56
-rw-r--r--launcher/ui/dialogs/ChooseProviderDialog.ui89
-rw-r--r--launcher/ui/dialogs/ModUpdateDialog.cpp408
-rw-r--r--launcher/ui/dialogs/ModUpdateDialog.h62
-rw-r--r--launcher/ui/dialogs/ProgressDialog.cpp34
-rw-r--r--launcher/ui/dialogs/ReviewMessageBox.cpp2
-rw-r--r--launcher/ui/dialogs/ScrollMessageBox.ui2
-rw-r--r--launcher/ui/dialogs/SkinUploadDialog.cpp90
-rw-r--r--launcher/ui/dialogs/SkinUploadDialog.ui6
-rw-r--r--launcher/ui/pages/instance/ExternalResourcesPage.ui11
-rw-r--r--launcher/ui/pages/instance/ModFolderPage.cpp78
-rw-r--r--launcher/ui/pages/instance/ModFolderPage.h1
-rw-r--r--launcher/ui/pages/modplatform/flame/FlameModPage.cpp2
-rw-r--r--launcher/ui/widgets/WideBar.cpp49
-rw-r--r--launcher/ui/widgets/WideBar.h31
61 files changed, 2751 insertions, 296 deletions
diff --git a/launcher/CMakeLists.txt b/launcher/CMakeLists.txt
index a970581f..cb509a00 100644
--- a/launcher/CMakeLists.txt
+++ b/launcher/CMakeLists.txt
@@ -397,6 +397,8 @@ set(TASKS_SOURCES
tasks/ConcurrentTask.cpp
tasks/SequentialTask.h
tasks/SequentialTask.cpp
+ tasks/MultipleOptionsTask.h
+ tasks/MultipleOptionsTask.cpp
)
ecm_add_test(tasks/Task_test.cpp LINK_LIBRARIES Launcher_logic Qt${QT_VERSION_MAJOR}::Test
@@ -480,9 +482,15 @@ set(API_SOURCES
modplatform/ModAPI.h
+ modplatform/EnsureMetadataTask.h
+ modplatform/EnsureMetadataTask.cpp
+
+ modplatform/CheckUpdateTask.h
+
modplatform/flame/FlameAPI.h
+ modplatform/flame/FlameAPI.cpp
modplatform/modrinth/ModrinthAPI.h
-
+ modplatform/modrinth/ModrinthAPI.cpp
modplatform/helpers/NetworkModAPI.h
modplatform/helpers/NetworkModAPI.cpp
)
@@ -508,6 +516,8 @@ set(FLAME_SOURCES
modplatform/flame/PackManifest.cpp
modplatform/flame/FileResolvingTask.h
modplatform/flame/FileResolvingTask.cpp
+ modplatform/flame/FlameCheckUpdate.cpp
+ modplatform/flame/FlameCheckUpdate.h
)
set(MODRINTH_SOURCES
@@ -515,6 +525,8 @@ set(MODRINTH_SOURCES
modplatform/modrinth/ModrinthPackIndex.h
modplatform/modrinth/ModrinthPackManifest.cpp
modplatform/modrinth/ModrinthPackManifest.h
+ modplatform/modrinth/ModrinthCheckUpdate.cpp
+ modplatform/modrinth/ModrinthCheckUpdate.h
)
set(MODPACKSCH_SOURCES
@@ -838,6 +850,10 @@ SET(LAUNCHER_SOURCES
ui/dialogs/ScrollMessageBox.h
ui/dialogs/BlockedModsDialog.cpp
ui/dialogs/BlockedModsDialog.h
+ ui/dialogs/ChooseProviderDialog.h
+ ui/dialogs/ChooseProviderDialog.cpp
+ ui/dialogs/ModUpdateDialog.cpp
+ ui/dialogs/ModUpdateDialog.h
# GUI - widgets
ui/widgets/Common.cpp
@@ -944,6 +960,7 @@ qt_wrap_ui(LAUNCHER_UI
ui/dialogs/ReviewMessageBox.ui
ui/dialogs/ScrollMessageBox.ui
ui/dialogs/BlockedModsDialog.ui
+ ui/dialogs/ChooseProviderDialog.ui
)
qt_add_resources(LAUNCHER_RESOURCES
@@ -970,6 +987,7 @@ add_library(Launcher_logic STATIC ${LOGIC_SOURCES} ${LAUNCHER_SOURCES} ${LAUNCHE
target_link_libraries(Launcher_logic
systeminfo
Launcher_classparser
+ Launcher_murmur2
nbt++
${ZLIB_LIBRARIES}
optional-bare
diff --git a/launcher/MMCZip.cpp b/launcher/MMCZip.cpp
index f20d6dff..1627ee07 100644
--- a/launcher/MMCZip.cpp
+++ b/launcher/MMCZip.cpp
@@ -127,7 +127,7 @@ bool MMCZip::compressDirFiles(QString fileCompressed, QString dir, QFileInfoList
}
// ours
-bool MMCZip::createModdedJar(QString sourceJarPath, QString targetJarPath, const QList<Mod>& mods)
+bool MMCZip::createModdedJar(QString sourceJarPath, QString targetJarPath, const QList<Mod*>& mods)
{
QuaZip zipOut(targetJarPath);
if (!zipOut.open(QuaZip::mdCreate))
@@ -141,42 +141,40 @@ bool MMCZip::createModdedJar(QString sourceJarPath, QString targetJarPath, const
QSet<QString> addedFiles;
// Modify the jar
- QListIterator<Mod> i(mods);
- i.toBack();
- while (i.hasPrevious())
+ for (auto i = mods.constEnd(); i != mods.constBegin(); --i)
{
- const Mod &mod = i.previous();
+ const Mod* mod = *i;
// do not merge disabled mods.
- if (!mod.enabled())
+ if (!mod->enabled())
continue;
- if (mod.type() == Mod::MOD_ZIPFILE)
+ if (mod->type() == Mod::MOD_ZIPFILE)
{
- if (!mergeZipFiles(&zipOut, mod.fileinfo(), addedFiles))
+ if (!mergeZipFiles(&zipOut, mod->fileinfo(), addedFiles))
{
zipOut.close();
QFile::remove(targetJarPath);
- qCritical() << "Failed to add" << mod.fileinfo().fileName() << "to the jar.";
+ qCritical() << "Failed to add" << mod->fileinfo().fileName() << "to the jar.";
return false;
}
}
- else if (mod.type() == Mod::MOD_SINGLEFILE)
+ else if (mod->type() == Mod::MOD_SINGLEFILE)
{
// FIXME: buggy - does not work with addedFiles
- auto filename = mod.fileinfo();
+ auto filename = mod->fileinfo();
if (!JlCompress::compressFile(&zipOut, filename.absoluteFilePath(), filename.fileName()))
{
zipOut.close();
QFile::remove(targetJarPath);
- qCritical() << "Failed to add" << mod.fileinfo().fileName() << "to the jar.";
+ qCritical() << "Failed to add" << mod->fileinfo().fileName() << "to the jar.";
return false;
}
addedFiles.insert(filename.fileName());
}
- else if (mod.type() == Mod::MOD_FOLDER)
+ else if (mod->type() == Mod::MOD_FOLDER)
{
// untested, but seems to be unused / not possible to reach
// FIXME: buggy - does not work with addedFiles
- auto filename = mod.fileinfo();
+ auto filename = mod->fileinfo();
QString what_to_zip = filename.absoluteFilePath();
QDir dir(what_to_zip);
dir.cdUp();
@@ -193,7 +191,7 @@ bool MMCZip::createModdedJar(QString sourceJarPath, QString targetJarPath, const
{
zipOut.close();
QFile::remove(targetJarPath);
- qCritical() << "Failed to add" << mod.fileinfo().fileName() << "to the jar.";
+ qCritical() << "Failed to add" << mod->fileinfo().fileName() << "to the jar.";
return false;
}
qDebug() << "Adding folder " << filename.fileName() << " from "
@@ -204,7 +202,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.fileinfo().fileName() << "to the jar.";
+ qCritical() << "Failed to add unknown mod type" << mod->fileinfo().fileName() << "to the jar.";
return false;
}
}
diff --git a/launcher/MMCZip.h b/launcher/MMCZip.h
index bf90cd0b..7f43d158 100644
--- a/launcher/MMCZip.h
+++ b/launcher/MMCZip.h
@@ -75,7 +75,7 @@ namespace MMCZip
/**
* take a source jar, add mods to it, resulting in target jar
*/
- bool createModdedJar(QString sourceJarPath, QString targetJarPath, const QList<Mod>& mods);
+ bool createModdedJar(QString sourceJarPath, QString targetJarPath, const QList<Mod*>& mods);
/**
* Find a single file in archive by file name (not path)
diff --git a/launcher/ModDownloadTask.cpp b/launcher/ModDownloadTask.cpp
index 41856fb5..2b0343f4 100644
--- a/launcher/ModDownloadTask.cpp
+++ b/launcher/ModDownloadTask.cpp
@@ -27,6 +27,7 @@ ModDownloadTask::ModDownloadTask(ModPlatform::IndexedPack mod, ModPlatform::Inde
{
if (is_indexed) {
m_update_task.reset(new LocalModUpdateTask(mods->indexDir(), m_mod, m_mod_version));
+ connect(m_update_task.get(), &LocalModUpdateTask::hasOldMod, this, &ModDownloadTask::hasOldMod);
addTask(m_update_task);
}
@@ -40,12 +41,16 @@ ModDownloadTask::ModDownloadTask(ModPlatform::IndexedPack mod, ModPlatform::Inde
connect(m_filesNetJob.get(), &NetJob::failed, this, &ModDownloadTask::downloadFailed);
addTask(m_filesNetJob);
-
}
void ModDownloadTask::downloadSucceeded()
{
m_filesNetJob.reset();
+ auto name = std::get<0>(to_delete);
+ auto filename = std::get<1>(to_delete);
+ if (!name.isEmpty() && filename != m_mod_version.fileName) {
+ mods->uninstallMod(filename, true);
+ }
}
void ModDownloadTask::downloadFailed(QString reason)
@@ -58,3 +63,10 @@ void ModDownloadTask::downloadProgressChanged(qint64 current, qint64 total)
{
emit progress(current, total);
}
+
+// This indirection is done so that we don't delete a mod before being sure it was
+// downloaded successfully!
+void ModDownloadTask::hasOldMod(QString name, QString filename)
+{
+ to_delete = {name, filename};
+}
diff --git a/launcher/ModDownloadTask.h b/launcher/ModDownloadTask.h
index b3c25909..95020470 100644
--- a/launcher/ModDownloadTask.h
+++ b/launcher/ModDownloadTask.h
@@ -30,7 +30,7 @@ class ModFolderModel;
class ModDownloadTask : public SequentialTask {
Q_OBJECT
public:
- explicit ModDownloadTask(ModPlatform::IndexedPack mod, ModPlatform::IndexedVersion version, const std::shared_ptr<ModFolderModel> mods, bool is_indexed);
+ explicit ModDownloadTask(ModPlatform::IndexedPack mod, ModPlatform::IndexedVersion version, const std::shared_ptr<ModFolderModel> mods, bool is_indexed = true);
const QString& getFilename() const { return m_mod_version.fileName; }
private:
@@ -46,6 +46,11 @@ private:
void downloadFailed(QString reason);
void downloadSucceeded();
+
+ std::tuple<QString, QString> to_delete {"", ""};
+
+private slots:
+ void hasOldMod(QString name, QString filename);
};
diff --git a/launcher/minecraft/MinecraftInstance.cpp b/launcher/minecraft/MinecraftInstance.cpp
index abc022b6..360e754d 100644
--- a/launcher/minecraft/MinecraftInstance.cpp
+++ b/launcher/minecraft/MinecraftInstance.cpp
@@ -700,24 +700,24 @@ 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.fileinfo().completeBaseName();
- auto bName = b.fileinfo().completeBaseName();
+ std::sort(modList.begin(), modList.end(), [](Mod::Ptr a, Mod::Ptr b) {
+ auto aName = a->fileinfo().completeBaseName();
+ auto bName = b->fileinfo().completeBaseName();
return aName.localeAwareCompare(bName) < 0;
});
- for(auto & mod: modList)
+ for(auto mod: modList)
{
- if(mod.type() == Mod::MOD_FOLDER)
+ 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();
+ if(mod->enabled()) {
+ out << u8" [✔️]" + mod->fileinfo().completeBaseName();
}
else {
- out << u8" [❌] " + mod.fileinfo().completeBaseName() + " (disabled)";
+ out << u8" [❌] " + mod->fileinfo().completeBaseName() + " (disabled)";
}
}
@@ -1136,16 +1136,16 @@ std::shared_ptr<GameOptions> MinecraftInstance::gameOptionsModel() const
return m_game_options;
}
-QList< Mod > MinecraftInstance::getJarMods() const
+QList<Mod*> MinecraftInstance::getJarMods() const
{
auto profile = m_components->getProfile();
- QList<Mod> mods;
+ QList<Mod*> mods;
for (auto jarmod : profile->getJarMods())
{
QStringList jar, temp1, temp2, temp3;
jarmod->getApplicableFiles(currentSystem, jar, temp1, temp2, temp3, jarmodsPath().absolutePath());
// QString filePath = jarmodsPath().absoluteFilePath(jarmod->filename(currentSystem));
- mods.push_back(Mod(QFileInfo(jar[0])));
+ mods.push_back(new Mod(QFileInfo(jar[0])));
}
return mods;
}
diff --git a/launcher/minecraft/MinecraftInstance.h b/launcher/minecraft/MinecraftInstance.h
index 05450d41..8e1c67f2 100644
--- a/launcher/minecraft/MinecraftInstance.h
+++ b/launcher/minecraft/MinecraftInstance.h
@@ -81,7 +81,7 @@ public:
shared_qobject_ptr<LaunchTask> createLaunchTask(AuthSessionPtr account, MinecraftServerTargetPtr serverToJoin) override;
QStringList extraArguments() const override;
QStringList verboseDescription(AuthSessionPtr session, MinecraftServerTargetPtr serverToJoin) override;
- QList<Mod> getJarMods() const;
+ QList<Mod*> getJarMods() const;
QString createLaunchScript(AuthSessionPtr session, MinecraftServerTargetPtr serverToJoin);
/// get arguments passed to java
QStringList javaArguments() const;
diff --git a/launcher/minecraft/mod/MetadataHandler.h b/launcher/minecraft/mod/MetadataHandler.h
index 56962818..39723b49 100644
--- a/launcher/minecraft/mod/MetadataHandler.h
+++ b/launcher/minecraft/mod/MetadataHandler.h
@@ -37,9 +37,9 @@ class Metadata {
return Packwiz::V1::createModFormat(index_dir, mod_pack, mod_version);
}
- static auto create(QDir& index_dir, Mod& internal_mod) -> ModStruct
+ static auto create(QDir& index_dir, Mod& internal_mod, QString mod_slug) -> ModStruct
{
- return Packwiz::V1::createModFormat(index_dir, internal_mod);
+ return Packwiz::V1::createModFormat(index_dir, internal_mod, mod_slug);
}
static void update(QDir& index_dir, ModStruct& mod)
@@ -47,13 +47,23 @@ class Metadata {
Packwiz::V1::updateModIndex(index_dir, mod);
}
- static void remove(QDir& index_dir, QString& mod_name)
+ static void remove(QDir& index_dir, QString mod_slug)
{
- Packwiz::V1::deleteModIndex(index_dir, mod_name);
+ Packwiz::V1::deleteModIndex(index_dir, mod_slug);
}
- static auto get(QDir& index_dir, QString& mod_name) -> ModStruct
+ static void remove(QDir& index_dir, QVariant& mod_id)
{
- return Packwiz::V1::getIndexForMod(index_dir, mod_name);
+ Packwiz::V1::deleteModIndex(index_dir, mod_id);
+ }
+
+ static auto get(QDir& index_dir, QString mod_slug) -> ModStruct
+ {
+ return Packwiz::V1::getIndexForMod(index_dir, mod_slug);
+ }
+
+ static auto get(QDir& index_dir, QVariant& mod_id) -> ModStruct
+ {
+ return Packwiz::V1::getIndexForMod(index_dir, mod_id);
}
};
diff --git a/launcher/minecraft/mod/Mod.cpp b/launcher/minecraft/mod/Mod.cpp
index 742709e3..588d76e3 100644
--- a/launcher/minecraft/mod/Mod.cpp
+++ b/launcher/minecraft/mod/Mod.cpp
@@ -150,25 +150,30 @@ void Mod::setStatus(ModStatus status)
m_temp_status = status;
}
}
-void Mod::setMetadata(Metadata::ModStruct* metadata)
+void Mod::setMetadata(const Metadata::ModStruct& metadata)
{
if (status() == ModStatus::NoMetadata)
setStatus(ModStatus::Installed);
if (m_localDetails) {
- m_localDetails->metadata.reset(metadata);
+ m_localDetails->metadata = std::make_shared<Metadata::ModStruct>(std::move(metadata));
} else {
- m_temp_metadata.reset(metadata);
+ m_temp_metadata = std::make_shared<Metadata::ModStruct>(std::move(metadata));
}
}
-auto Mod::destroy(QDir& index_dir) -> bool
+auto Mod::destroy(QDir& index_dir, bool preserve_metadata) -> bool
{
- auto n = name();
- // FIXME: This can fail to remove the metadata if the
- // "ModMetadataDisabled" setting is on, since there could
- // be a name mismatch!
- Metadata::remove(index_dir, n);
+ if (!preserve_metadata) {
+ qDebug() << QString("Destroying metadata for '%1' on purpose").arg(name());
+
+ if (metadata()) {
+ Metadata::remove(index_dir, metadata()->slug);
+ } else {
+ auto n = name();
+ Metadata::remove(index_dir, n);
+ }
+ }
m_type = MOD_UNKNOWN;
return FS::deletePath(m_file.filePath());
@@ -182,9 +187,12 @@ auto Mod::details() const -> const ModDetails&
auto Mod::name() const -> QString
{
auto d_name = details().name;
- if (!d_name.isEmpty()) {
+ if (!d_name.isEmpty())
return d_name;
- }
+
+ if (metadata())
+ return metadata()->name;
+
return m_name;
}
@@ -235,11 +243,10 @@ void Mod::finishResolvingWithDetails(std::shared_ptr<ModDetails> details)
m_resolved = true;
m_localDetails = details;
+ setStatus(m_temp_status);
+
if (m_localDetails && m_temp_metadata && m_temp_metadata->isValid()) {
- m_localDetails->metadata = m_temp_metadata;
- if (status() == ModStatus::NoMetadata)
- setStatus(ModStatus::Installed);
+ setMetadata(*m_temp_metadata);
+ m_temp_metadata.reset();
}
-
- setStatus(m_temp_status);
}
diff --git a/launcher/minecraft/mod/Mod.h b/launcher/minecraft/mod/Mod.h
index 5f9c4684..7a13e44b 100644
--- a/launcher/minecraft/mod/Mod.h
+++ b/launcher/minecraft/mod/Mod.h
@@ -39,10 +39,12 @@
#include <QFileInfo>
#include <QList>
+#include "QObjectPtr.h"
#include "ModDetails.h"
-class Mod
+class Mod : public QObject
{
+ Q_OBJECT
public:
enum ModType
{
@@ -53,6 +55,8 @@ public:
MOD_LITEMOD, //!< The mod is a litemod
};
+ using Ptr = shared_qobject_ptr<Mod>;
+
Mod() = default;
Mod(const QFileInfo &file);
explicit Mod(const QDir& mods_dir, const Met