From b30b88716e67de93ea1c97d9dfd02a41af5428f3 Mon Sep 17 00:00:00 2001 From: flow Date: Wed, 13 Apr 2022 19:16:36 -0300 Subject: feat: add very early mod.toml packwiz support Also use it as a on-disk format for storing mod metadata. This will be used later on to make better mod managment. --- launcher/modplatform/packwiz/Packwiz.cpp | 60 ++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 launcher/modplatform/packwiz/Packwiz.cpp (limited to 'launcher/modplatform/packwiz/Packwiz.cpp') diff --git a/launcher/modplatform/packwiz/Packwiz.cpp b/launcher/modplatform/packwiz/Packwiz.cpp new file mode 100644 index 00000000..ff86a8a9 --- /dev/null +++ b/launcher/modplatform/packwiz/Packwiz.cpp @@ -0,0 +1,60 @@ +#include "Packwiz.h" + +#include "modplatform/ModIndex.h" + +#include +#include +#include + +auto Packwiz::createModFormat(QDir& index_dir, ModPlatform::IndexedPack& mod_pack, ModPlatform::IndexedVersion& mod_version) -> Mod +{ + Mod mod; + + mod.name = mod_pack.name; + mod.filename = mod_version.fileName; + + mod.url = mod_version.downloadUrl; + mod.hash_format = ModPlatform::ProviderCapabilities::hashType(mod_pack.provider); + mod.hash = ""; // FIXME + + mod.provider = mod_pack.provider; + mod.file_id = mod_pack.addonId; + mod.project_id = mod_version.fileId; + + return mod; +} + +void Packwiz::updateModIndex(QDir& index_dir, Mod& mod) +{ + // Ensure the corresponding mod's info exists, and create it if not + auto index_file_name = QString("%1.toml").arg(mod.name); + QFile index_file(index_dir.absoluteFilePath(index_file_name)); + + // There's already data on there! + if (index_file.exists()) { index_file.remove(); } + + if (!index_file.open(QIODevice::ReadWrite)) { + qCritical() << "Could not open file " << index_file_name << "!"; + return; + } + + // Put TOML data into the file + QTextStream in_stream(&index_file); + auto addToStream = [&in_stream](QString&& key, QString value) { in_stream << QString("%1 = \"%2\"\n").arg(key, value); }; + + { + addToStream("name", mod.name); + addToStream("filename", mod.filename); + addToStream("side", mod.side); + + in_stream << QString("\n[download]\n"); + addToStream("url", mod.url.toString()); + addToStream("hash-format", mod.hash_format); + addToStream("hash", mod.hash); + + in_stream << QString("\n[update]\n"); + in_stream << QString("[update.%1]\n").arg(ModPlatform::ProviderCapabilities::providerName(mod.provider)); + addToStream("file-id", mod.file_id.toString()); + addToStream("project-id", mod.project_id.toString()); + } +} -- cgit From 8e4438b375ee904aa8225b569899355372e5987c Mon Sep 17 00:00:00 2001 From: flow Date: Wed, 13 Apr 2022 21:25:08 -0300 Subject: feat: add parser for current impl of packwiz mod.toml This reads a local mod.toml file and extract information from it. Using C libs in C++ is kind of a pain tho :( --- launcher/modplatform/ModIndex.h | 2 +- launcher/modplatform/packwiz/Packwiz.cpp | 90 ++++++++++++++++++++++++++++++++ launcher/modplatform/packwiz/Packwiz.h | 5 ++ 3 files changed, 96 insertions(+), 1 deletion(-) (limited to 'launcher/modplatform/packwiz/Packwiz.cpp') diff --git a/launcher/modplatform/ModIndex.h b/launcher/modplatform/ModIndex.h index 9c9ba99f..c5329772 100644 --- a/launcher/modplatform/ModIndex.h +++ b/launcher/modplatform/ModIndex.h @@ -25,7 +25,7 @@ class ProviderCapabilities { } return ""; } - static QString providerName(Provider p) + static const char* providerName(Provider p) { switch(p){ case Provider::MODRINTH: diff --git a/launcher/modplatform/packwiz/Packwiz.cpp b/launcher/modplatform/packwiz/Packwiz.cpp index ff86a8a9..58bead82 100644 --- a/launcher/modplatform/packwiz/Packwiz.cpp +++ b/launcher/modplatform/packwiz/Packwiz.cpp @@ -1,6 +1,7 @@ #include "Packwiz.h" #include "modplatform/ModIndex.h" +#include "toml.h" #include #include @@ -58,3 +59,92 @@ void Packwiz::updateModIndex(QDir& index_dir, Mod& mod) addToStream("project-id", mod.project_id.toString()); } } + +auto Packwiz::getIndexForMod(QDir& index_dir, QString mod_name) -> Mod +{ + Mod mod; + + auto index_file_name = QString("%1.toml").arg(mod_name); + QFile index_file(index_dir.absoluteFilePath(index_file_name)); + + if (!index_file.exists()) { return mod; } + if (!index_file.open(QIODevice::ReadOnly)) { return mod; } + + toml_table_t* table; + + char errbuf[200]; + table = toml_parse(index_file.readAll().data(), errbuf, sizeof(errbuf)); + + index_file.close(); + + if (!table) { + qCritical() << QString("Could not open file %1").arg(index_file_name); + return mod; + } + + // Helper function for extracting data from the TOML file + auto stringEntry = [&](toml_table_t* parent, const char* entry_name) -> QString { + toml_datum_t var = toml_string_in(parent, entry_name); + if (!var.ok) { + qCritical() << QString("Failed to read property '%1' in mod metadata.").arg(entry_name); + return {}; + } + + QString tmp = var.u.s; + free(var.u.s); + + return tmp; + }; + + { // Basic info + mod.name = stringEntry(table, "name"); + // Basic sanity check + if (mod.name != mod_name) { + qCritical() << QString("Name mismatch in mod metadata:\nExpected:%1\nGot:%2").arg(mod_name, mod.name); + return {}; + } + + mod.filename = stringEntry(table, "filename"); + mod.side = stringEntry(table, "side"); + } + + { // [download] info + toml_table_t* download_table = toml_table_in(table, "download"); + if (!download_table) { + qCritical() << QString("No [download] section found on mod metadata!"); + return {}; + } + + mod.url = stringEntry(download_table, "url"); + mod.hash_format = stringEntry(download_table, "hash-format"); + mod.hash = stringEntry(download_table, "hash"); + } + + { // [update] info + using ProviderCaps = ModPlatform::ProviderCapabilities; + using Provider = ModPlatform::Provider; + + toml_table_t* update_table = toml_table_in(table, "update"); + if (!update_table) { + qCritical() << QString("No [update] section found on mod metadata!"); + return {}; + } + + toml_table_t* mod_provider_table; + if ((mod_provider_table = toml_table_in(update_table, ProviderCaps::providerName(Provider::FLAME)))) { + mod.provider = Provider::FLAME; + } else if ((mod_provider_table = toml_table_in(update_table, ProviderCaps::providerName(Provider::MODRINTH)))) { + mod.provider = Provider::MODRINTH; + } else { + qCritical() << "No mod provider on mod metadata!"; + return {}; + } + + mod.file_id = stringEntry(mod_provider_table, "file-id"); + mod.project_id = stringEntry(mod_provider_table, "project-id"); + } + + toml_free(table); + + return mod; +} diff --git a/launcher/modplatform/packwiz/Packwiz.h b/launcher/modplatform/packwiz/Packwiz.h index 9c90f7de..08edaab9 100644 --- a/launcher/modplatform/packwiz/Packwiz.h +++ b/launcher/modplatform/packwiz/Packwiz.h @@ -39,4 +39,9 @@ class Packwiz { * TODO: Ask the user if they want to override, and delete the old mod's files, or keep the old one. * */ static void updateModIndex(QDir& index_dir, Mod& mod); + + /* Gets the metadata for a mod with a particular name. + * If the mod doesn't have a metadata, it simply returns an empty Mod object. + * */ + static auto getIndexForMod(QDir& index_dir, QString mod_name) -> Mod; }; -- cgit From e93b9560b5137a5ee7acdc34c0f74992aa02aad6 Mon Sep 17 00:00:00 2001 From: flow Date: Thu, 14 Apr 2022 22:02:41 -0300 Subject: feat: add method to delete mod metadata Also moves indexDir setting from LocalModUpdateTask -> ModFolderModel --- launcher/ModDownloadTask.cpp | 2 +- launcher/minecraft/mod/LocalModUpdateTask.cpp | 7 ++--- launcher/minecraft/mod/ModFolderModel.h | 7 ++++- launcher/modplatform/packwiz/Packwiz.cpp | 44 +++++++++++++++++++++------ launcher/modplatform/packwiz/Packwiz.h | 5 ++- 5 files changed, 48 insertions(+), 17 deletions(-) (limited to 'launcher/modplatform/packwiz/Packwiz.cpp') diff --git a/launcher/ModDownloadTask.cpp b/launcher/ModDownloadTask.cpp index e5766435..ad1e64e3 100644 --- a/launcher/ModDownloadTask.cpp +++ b/launcher/ModDownloadTask.cpp @@ -5,7 +5,7 @@ ModDownloadTask::ModDownloadTask(ModPlatform::IndexedPack mod, ModPlatform::IndexedVersion version, const std::shared_ptr mods) : m_mod(mod), m_mod_version(version), mods(mods) { - m_update_task.reset(new LocalModUpdateTask(mods->dir(), m_mod, m_mod_version)); + m_update_task.reset(new LocalModUpdateTask(mods->indexDir(), m_mod, m_mod_version)); addTask(m_update_task); diff --git a/launcher/minecraft/mod/LocalModUpdateTask.cpp b/launcher/minecraft/mod/LocalModUpdateTask.cpp index 0f48217b..63f5cf9a 100644 --- a/launcher/minecraft/mod/LocalModUpdateTask.cpp +++ b/launcher/minecraft/mod/LocalModUpdateTask.cpp @@ -5,12 +5,11 @@ #include "FileSystem.h" #include "modplatform/packwiz/Packwiz.h" -LocalModUpdateTask::LocalModUpdateTask(QDir mods_dir, ModPlatform::IndexedPack& mod, ModPlatform::IndexedVersion& mod_version) - : m_mod(mod), m_mod_version(mod_version) +LocalModUpdateTask::LocalModUpdateTask(QDir index_dir, ModPlatform::IndexedPack& mod, ModPlatform::IndexedVersion& mod_version) + : m_index_dir(index_dir), m_mod(mod), m_mod_version(mod_version) { // Ensure a '.index' folder exists in the mods folder, and create it if it does not - m_index_dir = { QString("%1/.index").arg(mods_dir.absolutePath()) }; - if (!FS::ensureFolderPathExists(m_index_dir.path())) { + if (!FS::ensureFolderPathExists(index_dir.path())) { emitFailed(QString("Unable to create index for mod %1!").arg(m_mod.name)); } } diff --git a/launcher/minecraft/mod/ModFolderModel.h b/launcher/minecraft/mod/ModFolderModel.h index 62c504df..f8ad4ca8 100644 --- a/launcher/minecraft/mod/ModFolderModel.h +++ b/launcher/minecraft/mod/ModFolderModel.h @@ -108,11 +108,16 @@ public: bool isValid(); - QDir dir() + QDir& dir() { return m_dir; } + QDir indexDir() + { + return { QString("%1/.index").arg(dir().absolutePath()) }; + } + const QList & allMods() { return mods; diff --git a/launcher/modplatform/packwiz/Packwiz.cpp b/launcher/modplatform/packwiz/Packwiz.cpp index 58bead82..bfadf7cb 100644 --- a/launcher/modplatform/packwiz/Packwiz.cpp +++ b/launcher/modplatform/packwiz/Packwiz.cpp @@ -7,6 +7,12 @@ #include #include +// Helpers +static inline QString indexFileName(QString const& mod_name) +{ + return QString("%1.toml").arg(mod_name); +} + auto Packwiz::createModFormat(QDir& index_dir, ModPlatform::IndexedPack& mod_pack, ModPlatform::IndexedVersion& mod_version) -> Mod { Mod mod; @@ -28,14 +34,13 @@ auto Packwiz::createModFormat(QDir& index_dir, ModPlatform::IndexedPack& mod_pac void Packwiz::updateModIndex(QDir& index_dir, Mod& mod) { // Ensure the corresponding mod's info exists, and create it if not - auto index_file_name = QString("%1.toml").arg(mod.name); - QFile index_file(index_dir.absoluteFilePath(index_file_name)); + QFile index_file(index_dir.absoluteFilePath(indexFileName(mod.name))); // There's already data on there! if (index_file.exists()) { index_file.remove(); } if (!index_file.open(QIODevice::ReadWrite)) { - qCritical() << "Could not open file " << index_file_name << "!"; + qCritical() << QString("Could not open file %1!").arg(indexFileName(mod.name)); return; } @@ -60,15 +65,34 @@ void Packwiz::updateModIndex(QDir& index_dir, Mod& mod) } } -auto Packwiz::getIndexForMod(QDir& index_dir, QString mod_name) -> Mod +void Packwiz::deleteModIndex(QDir& index_dir, QString& mod_name) +{ + QFile index_file(index_dir.absoluteFilePath(indexFileName(mod_name))); + + if(!index_file.exists()){ + qWarning() << QString("Tried to delete non-existent mod metadata for %1!").arg(mod_name); + return; + } + + if(!index_file.remove()){ + qWarning() << QString("Failed to remove metadata for mod %1!").arg(mod_name); + } +} + +auto Packwiz::getIndexForMod(QDir& index_dir, QString& mod_name) -> Mod { Mod mod; - auto index_file_name = QString("%1.toml").arg(mod_name); - QFile index_file(index_dir.absoluteFilePath(index_file_name)); + QFile index_file(index_dir.absoluteFilePath(indexFileName(mod_name))); - if (!index_file.exists()) { return mod; } - if (!index_file.open(QIODevice::ReadOnly)) { return mod; } + if (!index_file.exists()) { + qWarning() << QString("Tried to get a non-existent mod metadata for %1").arg(mod_name); + return mod; + } + if (!index_file.open(QIODevice::ReadOnly)) { + qWarning() << QString("Failed to open mod metadata for %1").arg(mod_name); + return mod; + } toml_table_t* table; @@ -78,7 +102,7 @@ auto Packwiz::getIndexForMod(QDir& index_dir, QString mod_name) -> Mod index_file.close(); if (!table) { - qCritical() << QString("Could not open file %1").arg(index_file_name); + qCritical() << QString("Could not open file %1!").arg(indexFileName(mod.name)); return mod; } @@ -136,7 +160,7 @@ auto Packwiz::getIndexForMod(QDir& index_dir, QString mod_name) -> Mod } else if ((mod_provider_table = toml_table_in(update_table, ProviderCaps::providerName(Provider::MODRINTH)))) { mod.provider = Provider::MODRINTH; } else { - qCritical() << "No mod provider on mod metadata!"; + qCritical() << QString("No mod provider on mod metadata!"); return {}; } diff --git a/launcher/modplatform/packwiz/Packwiz.h b/launcher/modplatform/packwiz/Packwiz.h index 08edaab9..541059d0 100644 --- a/launcher/modplatform/packwiz/Packwiz.h +++ b/launcher/modplatform/packwiz/Packwiz.h @@ -40,8 +40,11 @@ class Packwiz { * */ static void updateModIndex(QDir& index_dir, Mod& mod); + /* Deletes the metadata for the mod with the given name. If the metadata doesn't exist, it does nothing. */ + static void deleteModIndex(QDir& index_dir, QString& mod_name); + /* Gets the metadata for a mod with a particular name. * If the mod doesn't have a metadata, it simply returns an empty Mod object. * */ - static auto getIndexForMod(QDir& index_dir, QString mod_name) -> Mod; + static auto getIndexForMod(QDir& index_dir, QString& mod_name) -> Mod; }; -- cgit From 092d2f8917271264871d69239ecb8836b34d0994 Mon Sep 17 00:00:00 2001 From: flow Date: Fri, 15 Apr 2022 22:37:10 -0300 Subject: feat: add support for converting builtin -> packwiz mod formats Also adds more documentation. --- launcher/modplatform/packwiz/Packwiz.cpp | 41 +++++++++++++++++++++++++++----- launcher/modplatform/packwiz/Packwiz.h | 36 ++++++++++++++++++---------- 2 files changed, 58 insertions(+), 19 deletions(-) (limited to 'launcher/modplatform/packwiz/Packwiz.cpp') diff --git a/launcher/modplatform/packwiz/Packwiz.cpp b/launcher/modplatform/packwiz/Packwiz.cpp index bfadf7cb..445d64fb 100644 --- a/launcher/modplatform/packwiz/Packwiz.cpp +++ b/launcher/modplatform/packwiz/Packwiz.cpp @@ -1,12 +1,14 @@ #include "Packwiz.h" -#include "modplatform/ModIndex.h" -#include "toml.h" - #include #include #include +#include "toml.h" + +#include "modplatform/ModIndex.h" +#include "minecraft/mod/Mod.h" + // Helpers static inline QString indexFileName(QString const& mod_name) { @@ -31,12 +33,39 @@ auto Packwiz::createModFormat(QDir& index_dir, ModPlatform::IndexedPack& mod_pac return mod; } +auto Packwiz::createModFormat(QDir& index_dir, ::Mod& internal_mod) -> Mod +{ + auto mod_name = internal_mod.name(); + + // Try getting metadata if it exists + Mod mod { getIndexForMod(index_dir, mod_name) }; + if(mod.isValid()) + return mod; + + // Manually construct packwiz mod + mod.name = internal_mod.name(); + mod.filename = internal_mod.filename().fileName(); + + // TODO: Have a mechanism for telling the UI subsystem that we want to gather user information + // (i.e. which mod provider we want to use). Maybe an object parameter with a signal for that? + + return mod; +} + void Packwiz::updateModIndex(QDir& index_dir, Mod& mod) { + if(!mod.isValid()){ + qCritical() << QString("Tried to update metadata of an invalid mod!"); + return; + } + // Ensure the corresponding mod's info exists, and create it if not QFile index_file(index_dir.absoluteFilePath(indexFileName(mod.name))); // There's already data on there! + // TODO: We should do more stuff here, as the user is likely trying to + // override a file. In this case, check versions and ask the user what + // they want to do! if (index_file.exists()) { index_file.remove(); } if (!index_file.open(QIODevice::ReadWrite)) { @@ -87,11 +116,11 @@ auto Packwiz::getIndexForMod(QDir& index_dir, QString& mod_name) -> Mod if (!index_file.exists()) { qWarning() << QString("Tried to get a non-existent mod metadata for %1").arg(mod_name); - return mod; + return {}; } if (!index_file.open(QIODevice::ReadOnly)) { qWarning() << QString("Failed to open mod metadata for %1").arg(mod_name); - return mod; + return {}; } toml_table_t* table; @@ -103,7 +132,7 @@ auto Packwiz::getIndexForMod(QDir& index_dir, QString& mod_name) -> Mod if (!table) { qCritical() << QString("Could not open file %1!").arg(indexFileName(mod.name)); - return mod; + return {}; } // Helper function for extracting data from the TOML file diff --git a/launcher/modplatform/packwiz/Packwiz.h b/launcher/modplatform/packwiz/Packwiz.h index 541059d0..457d268a 100644 --- a/launcher/modplatform/packwiz/Packwiz.h +++ b/launcher/modplatform/packwiz/Packwiz.h @@ -6,33 +6,43 @@ #include #include -namespace ModPlatform { -} // namespace ModPlatform - class QDir; +// Mod from launcher/minecraft/mod/Mod.h +class Mod; + class Packwiz { public: struct Mod { - QString name; - QString filename; + QString name {}; + QString filename {}; // FIXME: make side an enum - QString side = "both"; + QString side {"both"}; // [download] - QUrl url; + QUrl url {}; // FIXME: make hash-format an enum - QString hash_format; - QString hash; + QString hash_format {}; + QString hash {}; // [update] - ModPlatform::Provider provider; - QVariant file_id; - QVariant project_id; + ModPlatform::Provider provider {}; + QVariant file_id {}; + QVariant project_id {}; + + public: + // This is a heuristic, but should work for now. + auto isValid() const -> bool { return !name.isEmpty(); } }; - /* Generates the object representing the information in a mod.toml file via its common representation in the launcher */ + /* Generates the object representing the information in a mod.toml file via + * its common representation in the launcher, when downloading mods. + * */ static auto createModFormat(QDir& index_dir, ModPlatform::IndexedPack& mod_pack, ModPlatform::IndexedVersion& mod_version) -> Mod; + /* Generates the object representing the information in a mod.toml file via + * its common representation in the launcher. + * */ + static auto createModFormat(QDir& index_dir, ::Mod& internal_mod) -> Mod; /* Updates the mod index for the provided mod. * This creates a new index if one does not exist already -- cgit From fab4a7a6029beb60bade312ee89e649202d178de Mon Sep 17 00:00:00 2001 From: flow Date: Sat, 16 Apr 2022 13:27:29 -0300 Subject: refactor: abstract metadata handling and clarify names --- launcher/CMakeLists.txt | 1 + launcher/MMCZip.cpp | 14 ++++---- launcher/minecraft/MinecraftInstance.cpp | 10 +++--- launcher/minecraft/mod/MetadataHandler.h | 41 ++++++++++++++++++++++ launcher/minecraft/mod/Mod.cpp | 6 ++-- launcher/minecraft/mod/Mod.h | 7 ++-- launcher/minecraft/mod/ModFolderModel.cpp | 2 +- .../minecraft/mod/tasks/LocalModUpdateTask.cpp | 6 ++-- launcher/minecraft/mod/tasks/ModFolderLoadTask.cpp | 4 +-- launcher/modplatform/packwiz/Packwiz.cpp | 16 +++++---- launcher/modplatform/packwiz/Packwiz.h | 6 +++- 11 files changed, 82 insertions(+), 31 deletions(-) create mode 100644 launcher/minecraft/mod/MetadataHandler.h (limited to 'launcher/modplatform/packwiz/Packwiz.cpp') diff --git a/launcher/CMakeLists.txt b/launcher/CMakeLists.txt index b6df2851..03d68e66 100644 --- a/launcher/CMakeLists.txt +++ b/launcher/CMakeLists.txt @@ -322,6 +322,7 @@ 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 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/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..26b1f799 --- /dev/null +++ b/launcher/minecraft/mod/MetadataHandler.h @@ -0,0 +1,41 @@ +#pragma once + +#include + +#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 64c9ffb5..5b35156d 100644 --- a/launcher/minecraft/mod/Mod.cpp +++ b/launcher/minecraft/mod/Mod.cpp @@ -20,6 +20,7 @@ #include #include +#include "MetadataHandler.h" namespace { @@ -33,7 +34,7 @@ Mod::Mod(const QFileInfo& file) m_changedDateTime = file.lastModified(); } -Mod::Mod(const QDir& mods_dir, const Packwiz::Mod& metadata) +Mod::Mod(const QDir& mods_dir, const Metadata::ModStruct& metadata) : m_file(mods_dir.absoluteFilePath(metadata.filename)) // It is weird, but name is not reliable for comparing with the JAR files name // FIXME: Maybe use hash when implemented? @@ -121,8 +122,7 @@ bool Mod::enable(bool value) bool Mod::destroy(QDir& index_dir) { - // Delete metadata - Packwiz::deleteModIndex(index_dir, m_name); + Metadata::remove(index_dir, m_name); m_type = MOD_UNKNOWN; return FS::deletePath(m_file.filePath()); diff --git a/launcher/minecraft/mod/Mod.h b/launcher/minecraft/mod/Mod.h index 46bb1a59..fef8cbe4 100644 --- a/launcher/minecraft/mod/Mod.h +++ b/launcher/minecraft/mod/Mod.h @@ -21,7 +21,7 @@ #include #include "ModDetails.h" -#include "modplatform/packwiz/Packwiz.h" +#include "minecraft/mod/MetadataHandler.h" class Mod { @@ -37,9 +37,9 @@ public: Mod() = default; Mod(const QFileInfo &file); - explicit Mod(const QDir& mods_dir, const Packwiz::Mod& metadata); + explicit Mod(const QDir& mods_dir, const Metadata::ModStruct& metadata); - QFileInfo filename() const { return m_file; } + QFileInfo fileinfo() const { return m_file; } QDateTime dateTimeChanged() const { return m_changedDateTime; } QString internal_id() const { return m_internal_id; } ModType type() const { return m_type; } @@ -82,6 +82,7 @@ protected: QDateTime m_changedDateTime; QString m_internal_id; + /* Name as reported via the file name */ QString m_name; ModType m_type = MOD_UNKNOWN; bool m_from_metadata = false; diff --git a/launcher/minecraft/mod/ModFolderModel.cpp b/launcher/minecraft/mod/ModFolderModel.cpp index e2e041eb..e034e35e 100644 --- a/launcher/minecraft/mod/ModFolderModel.cpp +++ b/launcher/minecraft/mod/ModFolderModel.cpp @@ -180,7 +180,7 @@ void ModFolderModel::resolveMod(Mod& m) return; } - auto task = new LocalModParseTask(nextResolutionTicket, m.type(), m.filename()); + auto task = new LocalModParseTask(nextResolutionTicket, m.type(), m.fileinfo()); auto result = task->result(); result->id = m.internal_id(); activeTickets.insert(nextResolutionTicket, result); diff --git a/launcher/minecraft/mod/tasks/LocalModUpdateTask.cpp b/launcher/minecraft/mod/tasks/LocalModUpdateTask.cpp index 63f5cf9a..8b6e8ec7 100644 --- a/launcher/minecraft/mod/tasks/LocalModUpdateTask.cpp +++ b/launcher/minecraft/mod/tasks/LocalModUpdateTask.cpp @@ -3,7 +3,7 @@ #include #include "FileSystem.h" -#include "modplatform/packwiz/Packwiz.h" +#include "minecraft/mod/MetadataHandler.h" LocalModUpdateTask::LocalModUpdateTask(QDir index_dir, ModPlatform::IndexedPack& mod, ModPlatform::IndexedVersion& mod_version) : m_index_dir(index_dir), m_mod(mod), m_mod_version(mod_version) @@ -18,8 +18,8 @@ void LocalModUpdateTask::executeTask() { setStatus(tr("Updating index for mod:\n%1").arg(m_mod.name)); - auto pw_mod = Packwiz::createModFormat(m_index_dir, m_mod, m_mod_version); - Packwiz::updateModIndex(m_index_dir, pw_mod); + auto pw_mod = Metadata::create(m_index_dir, m_mod, m_mod_version); + Metadata::update(m_index_dir, pw_mod); emitSucceeded(); } diff --git a/launcher/minecraft/mod/tasks/ModFolderLoadTask.cpp b/launcher/minecraft/mod/tasks/ModFolderLoadTask.cpp index bf7b28d6..e94bdee9 100644 --- a/launcher/minecraft/mod/tasks/ModFolderLoadTask.cpp +++ b/launcher/minecraft/mod/tasks/ModFolderLoadTask.cpp @@ -1,7 +1,7 @@ #include "ModFolderLoadTask.h" #include -#include "modplatform/packwiz/Packwiz.h" +#include "minecraft/mod/MetadataHandler.h" ModFolderLoadTask::ModFolderLoadTask(QDir& mods_dir, QDir& index_dir) : m_mods_dir(mods_dir), m_index_dir(index_dir), m_result(new Result()) @@ -17,7 +17,7 @@ void ModFolderLoadTask::run() continue; entry.chop(5); // Remove .toml at the end - Mod mod(m_mods_dir, Packwiz::getIndexForMod(m_index_dir, entry)); + Mod mod(m_mods_dir, Metadata::get(m_index_dir, entry)); m_result->mods[mod.internal_id()] = mod; } diff --git a/launcher/modplatform/packwiz/Packwiz.cpp b/launcher/modplatform/packwiz/Packwiz.cpp index 445d64fb..27339c2d 100644 --- a/launcher/modplatform/packwiz/Packwiz.cpp +++ b/launcher/modplatform/packwiz/Packwiz.cpp @@ -9,13 +9,15 @@ #include "modplatform/ModIndex.h" #include "minecraft/mod/Mod.h" +namespace Packwiz { + // Helpers static inline QString indexFileName(QString const& mod_name) { return QString("%1.toml").arg(mod_name); } -auto Packwiz::createModFormat(QDir& index_dir, ModPlatform::IndexedPack& mod_pack, ModPlatform::IndexedVersion& mod_version) -> Mod +auto V1::createModFormat(QDir& index_dir, ModPlatform::IndexedPack& mod_pack, ModPlatform::IndexedVersion& mod_version) -> Mod { Mod mod; @@ -33,7 +35,7 @@ auto Packwiz::createModFormat(QDir& index_dir, ModPlatform::IndexedPack& mod_pac return mod; } -auto Packwiz::createModFormat(QDir& index_dir, ::Mod& internal_mod) -> Mod +auto V1::createModFormat(QDir& index_dir, ::Mod& internal_mod) -> Mod { auto mod_name = internal_mod.name(); @@ -44,7 +46,7 @@ auto Packwiz::createModFormat(QDir& index_dir, ::Mod& internal_mod) -> Mod // Manually construct packwiz mod mod.name = internal_mod.name(); - mod.filename = internal_mod.filename().fileName(); + mod.filename = internal_mod.fileinfo().fileName(); // TODO: Have a mechanism for telling the UI subsystem that we want to gather user information // (i.e. which mod provider we want to use). Maybe an object parameter with a signal for that? @@ -52,7 +54,7 @@ auto Packwiz::createModFormat(QDir& index_dir, ::Mod& internal_mod) -> Mod return mod; } -void Packwiz::updateModIndex(QDir& index_dir, Mod& mod) +void V1::updateModIndex(QDir& index_dir, Mod& mod) { if(!mod.isValid()){ qCritical() << QString("Tried to update metadata of an invalid mod!"); @@ -94,7 +96,7 @@ void Packwiz::updateModIndex(QDir& index_dir, Mod& mod) } } -void Packwiz::deleteModIndex(QDir& index_dir, QString& mod_name) +void V1::deleteModIndex(QDir& index_dir, QString& mod_name) { QFile index_file(index_dir.absoluteFilePath(indexFileName(mod_name))); @@ -108,7 +110,7 @@ void Packwiz::deleteModIndex(QDir& index_dir, QString& mod_name) } } -auto Packwiz::getIndexForMod(QDir& index_dir, QString& mod_name) -> Mod +auto V1::getIndexForMod(QDir& index_dir, QString& mod_name) -> Mod { Mod mod; @@ -201,3 +203,5 @@ auto Packwiz::getIndexForMod(QDir& index_dir, QString& mod_name) -> Mod return mod; } + +} // namespace Packwiz diff --git a/launcher/modplatform/packwiz/Packwiz.h b/launcher/modplatform/packwiz/Packwiz.h index 457d268a..777a365f 100644 --- a/launcher/modplatform/packwiz/Packwiz.h +++ b/launcher/modplatform/packwiz/Packwiz.h @@ -11,7 +11,9 @@ class QDir; // Mod from launcher/minecraft/mod/Mod.h class Mod; -class Packwiz { +namespace Packwiz { + +class V1 { public: struct Mod { QString name {}; @@ -58,3 +60,5 @@ class Packwiz { * */ static auto getIndexForMod(QDir& index_dir, QString& mod_name) -> Mod; }; + +} // namespace Packwiz -- cgit From d7f6b3699074b268fd554bd1eb9da68f1e533355 Mon Sep 17 00:00:00 2001 From: flow Date: Sun, 17 Apr 2022 11:40:41 -0300 Subject: test+fix: add basic tests and fix issues with it --- launcher/CMakeLists.txt | 6 ++ launcher/minecraft/mod/Mod.cpp | 7 +- launcher/minecraft/mod/Mod.h | 1 - launcher/minecraft/mod/tasks/ModFolderLoadTask.cpp | 10 ++- launcher/modplatform/ModIndex.h | 2 +- launcher/modplatform/packwiz/Packwiz.cpp | 76 +++++++++++++--------- launcher/modplatform/packwiz/Packwiz.h | 11 +++- launcher/modplatform/packwiz/Packwiz_test.cpp | 68 +++++++++++++++++++ .../packwiz/testdata/borderless-mining.toml | 13 ++++ .../testdata/screenshot-to-clipboard-fabric.toml | 13 ++++ 10 files changed, 168 insertions(+), 39 deletions(-) create mode 100644 launcher/modplatform/packwiz/Packwiz_test.cpp create mode 100644 launcher/modplatform/packwiz/testdata/borderless-mining.toml create mode 100644 launcher/modplatform/packwiz/testdata/screenshot-to-clipboard-fabric.toml (limited to 'launcher/modplatform/packwiz/Packwiz.cpp') diff --git a/launcher/CMakeLists.txt b/launcher/CMakeLists.txt index 03d68e66..6c7b5e43 100644 --- a/launcher/CMakeLists.txt +++ b/launcher/CMakeLists.txt @@ -551,6 +551,12 @@ set(PACKWIZ_SOURCES 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 diff --git a/launcher/minecraft/mod/Mod.cpp b/launcher/minecraft/mod/Mod.cpp index 7b560845..ef3699e8 100644 --- a/launcher/minecraft/mod/Mod.cpp +++ b/launcher/minecraft/mod/Mod.cpp @@ -20,6 +20,8 @@ #include #include + +#include "Application.h" #include "MetadataHandler.h" namespace { @@ -174,8 +176,7 @@ void Mod::finishResolvingWithDetails(std::shared_ptr details) m_resolved = true; m_localDetails = details; - if (fromMetadata() && m_temp_metadata->isValid()) { - m_localDetails->metadata = m_temp_metadata; - m_temp_metadata.reset(); + if (fromMetadata() && m_temp_metadata->isValid() && m_localDetails.get()) { + m_localDetails->metadata.swap(m_temp_metadata); } } diff --git a/launcher/minecraft/mod/Mod.h b/launcher/minecraft/mod/Mod.h index 0d49d94b..1e7ed1ed 100644 --- a/launcher/minecraft/mod/Mod.h +++ b/launcher/minecraft/mod/Mod.h @@ -20,7 +20,6 @@ #include #include "ModDetails.h" -#include "minecraft/mod/MetadataHandler.h" class Mod { diff --git a/launcher/minecraft/mod/tasks/ModFolderLoadTask.cpp b/launcher/minecraft/mod/tasks/ModFolderLoadTask.cpp index 5afbb08a..03a17461 100644 --- a/launcher/minecraft/mod/tasks/ModFolderLoadTask.cpp +++ b/launcher/minecraft/mod/tasks/ModFolderLoadTask.cpp @@ -34,8 +34,14 @@ void ModFolderLoadTask::getFromMetadata() if (entry == "." || entry == "..") continue; - entry.chop(5); // Remove .toml at the end - Mod mod(m_mods_dir, Metadata::get(m_index_dir, entry)); + auto metadata = Metadata::get(m_index_dir, entry); + // TODO: Don't simply return. Instead, show to the user that the metadata is there, but + // it's not currently 'installed' (i.e. there's no JAR file yet). + if(!metadata.isValid()){ + return; + } + + Mod mod(m_mods_dir, metadata); m_result->mods[mod.internal_id()] = mod; } } diff --git a/launcher/modplatform/ModIndex.h b/launcher/modplatform/ModIndex.h index c5329772..ee623b78 100644 --- a/launcher/modplatform/ModIndex.h +++ b/launcher/modplatform/ModIndex.h @@ -19,7 +19,7 @@ class ProviderCapabilities { { switch(p){ case Provider::MODRINTH: - return "sha256"; + return "sha512"; case Provider::FLAME: return "murmur2"; } diff --git a/launcher/modplatform/packwiz/Packwiz.cpp b/launcher/modplatform/packwiz/Packwiz.cpp index 27339c2d..8fd74a3e 100644 --- a/launcher/modplatform/packwiz/Packwiz.cpp +++ b/launcher/modplatform/packwiz/Packwiz.cpp @@ -14,6 +14,8 @@ namespace Packwiz { // Helpers static inline QString indexFileName(QString const& mod_name) { + if(mod_name.endsWith(".toml")) + return mod_name; return QString("%1.toml").arg(mod_name); } @@ -91,8 +93,16 @@ void V1::updateModIndex(QDir& index_dir, Mod& mod) in_stream << QString("\n[update]\n"); in_stream << QString("[update.%1]\n").arg(ModPlatform::ProviderCapabilities::providerName(mod.provider)); - addToStream("file-id", mod.file_id.toString()); - addToStream("project-id", mod.project_id.toString()); + switch(mod.provider){ + case(ModPlatform::Provider::FLAME): + in_stream << QString("file-id = %1\n").arg(mod.file_id.toString()); + in_stream << QString("project-id = %1\n").arg(mod.project_id.toString()); + break; + case(ModPlatform::Provider::MODRINTH): + addToStream("mod-id", mod.mod_id().toString()); + addToStream("version", mod.version().toString()); + break; + } } } @@ -110,18 +120,44 @@ void V1::deleteModIndex(QDir& index_dir, QString& mod_name) } } -auto V1::getIndexForMod(QDir& index_dir, QString& mod_name) -> Mod +// Helper functions for extracting data from the TOML file +static auto stringEntry(toml_table_t* parent, const char* entry_name) -> QString +{ + toml_datum_t var = toml_string_in(parent, entry_name); + if (!var.ok) { + qCritical() << QString("Failed to read str property '%1' in mod metadata.").arg(entry_name); + return {}; + } + + QString tmp = var.u.s; + free(var.u.s); + + return tmp; +} + +static auto intEntry(toml_table_t* parent, const char* entry_name) -> int +{ + toml_datum_t var = toml_int_in(parent, entry_name); + if (!var.ok) { + qCritical() << QString("Failed to read int property '%1' in mod metadata.").arg(entry_name); + return {}; + } + + return var.u.i; +} + +auto V1::getIndexForMod(QDir& index_dir, QString& index_file_name) -> Mod { Mod mod; - QFile index_file(index_dir.absoluteFilePath(indexFileName(mod_name))); + QFile index_file(index_dir.absoluteFilePath(indexFileName(index_file_name))); if (!index_file.exists()) { - qWarning() << QString("Tried to get a non-existent mod metadata for %1").arg(mod_name); + qWarning() << QString("Tried to get a non-existent mod metadata for %1").arg(index_file_name); return {}; } if (!index_file.open(QIODevice::ReadOnly)) { - qWarning() << QString("Failed to open mod metadata for %1").arg(mod_name); + qWarning() << QString("Failed to open mod metadata for %1").arg(index_file_name); return {}; } @@ -136,29 +172,9 @@ auto V1::getIndexForMod(QDir& index_dir, QString& mod_name) -> Mod qCritical() << QString("Could not open file %1!").arg(indexFileName(mod.name)); return {}; } - - // Helper function for extracting data from the TOML file - auto stringEntry = [&](toml_table_t* parent, const char* entry_name) -> QString { - toml_datum_t var = toml_string_in(parent, entry_name); - if (!var.ok) { - qCritical() << QString("Failed to read property '%1' in mod metadata.").arg(entry_name); - return {}; - } - - QString tmp = var.u.s; - free(var.u.s); - - return tmp; - }; - + { // Basic info mod.name = stringEntry(table, "name"); - // Basic sanity check - if (mod.name != mod_name) { - qCritical() << QString("Name mismatch in mod metadata:\nExpected:%1\nGot:%2").arg(mod_name, mod.name); - return {}; - } - mod.filename = stringEntry(table, "filename"); mod.side = stringEntry(table, "side"); } @@ -188,15 +204,17 @@ auto V1::getIndexForMod(QDir& index_dir, QString& mod_name) -> Mod toml_table_t* mod_provider_table; if ((mod_provider_table = toml_table_in(update_table, ProviderCaps::providerName(Provider::FLAME)))) { mod.provider = Provider::FLAME; + mod.file_id = intEntry(mod_provider_table, "file-id"); + mod.project_id = intEntry(mod_provider_table, "project-id"); } else if ((mod_provider_table = toml_table_in(update_table, ProviderCaps::providerName(Provider::MODRINTH)))) { mod.provider = Provider::MODRINTH; + mod.mod_id() = stringEntry(mod_provider_table, "mod-id"); + mod.version() = stringEntry(mod_provider_table, "version"); } else { qCritical() << QString("No mod provider on mod metadata!"); return {}; } - mod.file_id = stringEntry(mod_provider_table, "file-id"); - mod.project_id = stringEntry(mod_provider_table, "project-id"); } toml_free(table); diff --git a/launcher/modplatform/packwiz/Packwiz.h b/launcher/modplatform/packwiz/Packwiz.h index 777a365f..69125dbc 100644 --- a/launcher/modplatform/packwiz/Packwiz.h +++ b/launcher/modplatform/packwiz/Packwiz.h @@ -33,8 +33,13 @@ class V1 { QVariant project_id {}; public: - // This is a heuristic, but should work for now. - auto isValid() const -> bool { return !name.isEmpty(); } + // This is a totally heuristic, but should work for now. + auto isValid() const -> bool { return !name.isEmpty() && !project_id.isNull(); } + + // Different providers can use different names for the same thing + // Modrinth-specific + auto mod_id() -> QVariant& { return project_id; } + auto version() -> QVariant& { return file_id; } }; /* Generates the object representing the information in a mod.toml file via @@ -58,7 +63,7 @@ class V1 { /* Gets the metadata for a mod with a particular name. * If the mod doesn't have a metadata, it simply returns an empty Mod object. * */ - static auto getIndexForMod(QDir& index_dir, QString& mod_name) -> Mod; + static auto getIndexForMod(QDir& index_dir, QString& index_file_name) -> Mod; }; } // namespace Packwiz diff --git a/launcher/modplatform/packwiz/Packwiz_test.cpp b/launcher/modplatform/packwiz/Packwiz_test.cpp new file mode 100644 index 00000000..2e61c167 --- /dev/null +++ b/launcher/modplatform/packwiz/Packwiz_test.cpp @@ -0,0 +1,68 @@ +#include +#include + +#include "TestUtil.h" +#include "Packwiz.h" + +class PackwizTest : public QObject { + Q_OBJECT + + private slots: + // Files taken from https://github.com/packwiz/packwiz-example-pack + void loadFromFile_Modrinth() + { + QString source = QFINDTESTDATA("testdata"); + + QDir index_dir(source); + QString name_mod("borderless-mining.toml"); + QVERIFY(index_dir.entryList().contains(name_mod)); + + auto metadata = Packwiz::V1::getIndexForMod(index_dir, name_mod); + + QVERIFY(metadata.isValid()); + + QCOMPARE(metadata.name, "Borderless Mining"); + QCOMPARE(metadata.filename, "borderless-mining-1.1.1+1.18.jar"); + QCOMPARE(metadata.side, "client"); + + QCOMPARE(metadata.url, QUrl("https://cdn.modrinth.com/data/kYq5qkSL/versions/1.1.1+1.18/borderless-mining-1.1.1+1.18.jar")); + QCOMPARE(metadata.hash_format, "sha512"); + QCOMPARE(metadata.hash, "c8fe6e15ddea32668822dddb26e1851e5f03834be4bcb2eff9c0da7fdc086a9b6cead78e31a44d3bc66335cba11144ee0337c6d5346f1ba63623064499b3188d"); + + QCOMPARE(metadata.provider, ModPlatform::Provider::MODRINTH); + QCOMPARE(metadata.version(), "ug2qKTPR"); + QCOMPARE(metadata.mod_id(), "kYq5qkSL"); + } + + void loadFromFile_Curseforge() + { + QString source = QFINDTESTDATA("testdata"); + + QDir index_dir(source); + QString name_mod("screenshot-to-clipboard-fabric.toml"); + QVERIFY(index_dir.entryList().contains(name_mod)); + + // Try without the .toml at the end + name_mod.chop(5); + + auto metadata = Packwiz::V1::getIndexForMod(index_dir, name_mod); + + QVERIFY(metadata.isValid()); + + QCOMPARE(metadata.name, "Screenshot to Clipboard (Fabric)"); + QCOMPARE(metadata.filename, "screenshot-to-clipboard-1.0.7-fabric.jar"); + QCOMPARE(metadata.side, "both"); + + QCOMPARE(metadata.url, QUrl("https://edge.forgecdn.net/files/3509/43/screenshot-to-clipboard-1.0.7-fabric.jar")); + QCOMPARE(metadata.hash_format, "murmur2"); + QCOMPARE(metadata.hash, "1781245820"); + + QCOMPARE(metadata.provider, ModPlatform::Provider::FLAME); + QCOMPARE(metadata.file_id, 3509043); + QCOMPARE(metadata.project_id, 327154); + } +}; + +QTEST_GUILESS_MAIN(PackwizTest) + +#include "Packwiz_test.moc" diff --git a/launcher/modplatform/packwiz/testdata/borderless-mining.toml b/launcher/modplatform/packwiz/testdata/borderless-mining.toml new file mode 100644 index 00000000..16545fd4 --- /dev/null +++ b/launcher/modplatform/packwiz/testdata/borderless-mining.toml @@ -0,0 +1,13 @@ +name = "Borderless Mining" +filename = "borderless-mining-1.1.1+1.18.jar" +side = "client" + +[download] +url = "https://cdn.modrinth.com/data/kYq5qkSL/versions/1.1.1+1.18/borderless-mining-1.1.1+1.18.jar" +hash-format = "sha512" +hash = "c8fe6e15ddea32668822dddb26e1851e5f03834be4bcb2eff9c0da7fdc086a9b6cead78e31a44d3bc66335cba11144ee0337c6d5346f1ba63623064499b3188d" + +[update] +[update.modrinth] +mod-id = "kYq5qkSL" +version = "ug2qKTPR" diff --git a/launcher/modplatform/packwiz/testdata/screenshot-to-clipboard-fabric.toml b/launcher/modplatform/packwiz/testdata/screenshot-to-clipboard-fabric.toml new file mode 100644 index 00000000..87d70ada --- /dev/null +++ b/launcher/modplatform/packwiz/testdata/screenshot-to-clipboard-fabric.toml @@ -0,0 +1,13 @@ +name = "Screenshot to Clipboard (Fabric)" +filename = "screenshot-to-clipboard-1.0.7-fabric.jar" +side = "both" + +[download] +url = "https://edge.forgecdn.net/files/3509/43/screenshot-to-clipboard-1.0.7-fabric.jar" +hash-format = "murmur2" +hash = "1781245820" + +[update] +[update.curseforge] +file-id = 3509043 +project-id = 327154 -- cgit From ba50765c306d2907e411bc0ed9a10d990cf42fd3 Mon Sep 17 00:00:00 2001 From: flow Date: Tue, 19 Apr 2022 20:19:51 -0300 Subject: tidy: apply clang-tidy to some files Mostly the ones created in this PR + Mod.h / Mod.cpp / ModDetails.h --- launcher/minecraft/mod/Mod.cpp | 16 ++++----- launcher/minecraft/mod/Mod.h | 40 +++++++++++----------- .../minecraft/mod/tasks/LocalModUpdateTask.cpp | 2 +- launcher/minecraft/mod/tasks/LocalModUpdateTask.h | 6 ++-- launcher/modplatform/packwiz/Packwiz.cpp | 9 ++--- launcher/modplatform/packwiz/Packwiz_test.cpp | 2 +- 6 files changed, 38 insertions(+), 37 deletions(-) (limited to 'launcher/modplatform/packwiz/Packwiz.cpp') diff --git a/launcher/minecraft/mod/Mod.cpp b/launcher/minecraft/mod/Mod.cpp index ef3699e8..992b91dc 100644 --- a/launcher/minecraft/mod/Mod.cpp +++ b/launcher/minecraft/mod/Mod.cpp @@ -93,7 +93,7 @@ void Mod::repath(const QFileInfo& file) } } -bool Mod::enable(bool value) +auto Mod::enable(bool value) -> bool { if (m_type == Mod::MOD_UNKNOWN || m_type == Mod::MOD_FOLDER) return false; @@ -124,7 +124,7 @@ bool Mod::enable(bool value) return true; } -bool Mod::destroy(QDir& index_dir) +auto Mod::destroy(QDir& index_dir) -> bool { auto n = name(); // FIXME: This can fail to remove the metadata if the @@ -136,12 +136,12 @@ bool Mod::destroy(QDir& index_dir) return FS::deletePath(m_file.filePath()); } -const ModDetails& Mod::details() const +auto Mod::details() const -> const ModDetails& { return m_localDetails ? *m_localDetails : invalidDetails; } -QString Mod::name() const +auto Mod::name() const -> QString { auto d_name = details().name; if (!d_name.isEmpty()) { @@ -150,22 +150,22 @@ QString Mod::name() const return m_name; } -QString Mod::version() const +auto Mod::version() const -> QString { return details().version; } -QString Mod::homeurl() const +auto Mod::homeurl() const -> QString { return details().homeurl; } -QString Mod::description() const +auto Mod::description() const -> QString { return details().description; } -QStringList Mod::authors() const +auto Mod::authors() const -> QStringList { return details().authors; } diff --git a/launcher/minecraft/mod/Mod.h b/launcher/minecraft/mod/Mod.h index 1e7ed1ed..3a0ccfa6 100644 --- a/launcher/minecraft/mod/Mod.h +++ b/launcher/minecraft/mod/Mod.h @@ -37,36 +37,36 @@ public: Mod(const QFileInfo &file); explicit Mod(const QDir& mods_dir, const Metadata::ModStruct& metadata); - QFileInfo fileinfo() const { return m_file; } - QDateTime dateTimeChanged() const { return m_changedDateTime; } - QString internal_id() const { return m_internal_id; } - ModType type() const { return m_type; } - bool fromMetadata() const { return m_from_metadata; } - bool enabled() const { return m_enabled; } + auto fileinfo() const -> QFileInfo { return m_file; } + auto dateTimeChanged() const -> QDateTime { return m_changedDateTime; } + auto internal_id() const -> QString { return m_internal_id; } + auto type() const -> ModType { return m_type; } + auto fromMetadata() const -> bool { return m_from_metadata; } + auto enabled() const -> bool { return m_enabled; } - bool valid() const { return m_type != MOD_UNKNOWN; } + auto valid() const -> bool { return m_type != MOD_UNKNOWN; } - const ModDetails& details() const; - QString name() const; - QString version() const; - QString homeurl() const; - QString description() const; - QStringList authors() const; + auto details() const -> const ModDetails&; + auto name() const -> QString; + auto version() const -> QString; + auto homeurl() const -> QString; + auto description() const -> QString; + auto authors() const -> QStringList; - const std::shared_ptr metadata() const { return details().metadata; }; - std::shared_ptr metadata() { return m_localDetails->metadata; }; + auto metadata() const -> const std::shared_ptr { return details().metadata; }; + auto metadata() -> std::shared_ptr { return m_localDetails->metadata; }; - bool enable(bool value); + auto enable(bool value) -> bool; // delete all the files of this mod - bool destroy(QDir& index_dir); + auto destroy(QDir& index_dir) -> bool; // change the mod's filesystem path (used by mod lists for *MAGIC* purposes) void repath(const QFileInfo &file); - bool shouldResolve() const { return !m_resolving && !m_resolved; } - bool isResolving() const { return m_resolving; } - int resolutionTicket() const { return m_resolutionTicket; } + auto shouldResolve() const -> bool { return !m_resolving && !m_resolved; } + auto isResolving() const -> bool { return m_resolving; } + auto resolutionTicket() const -> int { return m_resolutionTicket; } void setResolving(bool resolving, int resolutionTicket) { m_resolving = resolving; diff --git a/launcher/minecraft/mod/tasks/LocalModUpdateTask.cpp b/launcher/minecraft/mod/tasks/LocalModUpdateTask.cpp index 3c9b76a8..47207ada 100644 --- a/launcher/minecraft/mod/tasks/LocalModUpdateTask.cpp +++ b/launcher/minecraft/mod/tasks/LocalModUpdateTask.cpp @@ -30,7 +30,7 @@ void LocalModUpdateTask::executeTask() emitSucceeded(); } -bool LocalModUpdateTask::abort() +auto LocalModUpdateTask::abort() -> bool { emitAborted(); return true; diff --git a/launcher/minecraft/mod/tasks/LocalModUpdateTask.h b/launcher/minecraft/mod/tasks/LocalModUpdateTask.h index 866089e9..15591b21 100644 --- a/launcher/minecraft/mod/tasks/LocalModUpdateTask.h +++ b/launcher/minecraft/mod/tasks/LocalModUpdateTask.h @@ -2,8 +2,8 @@ #include -#include "tasks/Task.h" #include "modplatform/ModIndex.h" +#include "tasks/Task.h" class LocalModUpdateTask : public Task { Q_OBJECT @@ -12,8 +12,8 @@ class LocalModUpdateTask : public Task { explicit LocalModUpdateTask(QDir mods_dir, ModPlatform::IndexedPack& mod, ModPlatform::IndexedVersion& mod_version); - bool canAbort() const override { return true; } - bool abort() override; + auto canAbort() const -> bool override { return true; } + auto abort() -> bool override; protected slots: //! Entry point for tasks. diff --git a/launcher/modplatform/packwiz/Packwiz.cpp b/launcher/modplatform/packwiz/Packwiz.cpp index 8fd74a3e..978be462 100644 --- a/launcher/modplatform/packwiz/Packwiz.cpp +++ b/launcher/modplatform/packwiz/Packwiz.cpp @@ -6,13 +6,13 @@ #include "toml.h" -#include "modplatform/ModIndex.h" #include "minecraft/mod/Mod.h" +#include "modplatform/ModIndex.h" namespace Packwiz { // Helpers -static inline QString indexFileName(QString const& mod_name) +static inline auto indexFileName(QString const& mod_name) -> QString { if(mod_name.endsWith(".toml")) return mod_name; @@ -161,8 +161,9 @@ auto V1::getIndexForMod(QDir& index_dir, QString& index_file_name) -> Mod return {}; } - toml_table_t* table; + toml_table_t* table = nullptr; + // NOLINTNEXTLINE(modernize-avoid-c-arrays) char errbuf[200]; table = toml_parse(index_file.readAll().data(), errbuf, sizeof(errbuf)); @@ -201,7 +202,7 @@ auto V1::getIndexForMod(QDir& index_dir, QString& index_file_name) -> Mod return {}; } - toml_table_t* mod_provider_table; + toml_table_t* mod_provider_table = nullptr; if ((mod_provider_table = toml_table_in(update_table, ProviderCaps::providerName(Provider::FLAME)))) { mod.provider = Provider::FLAME; mod.file_id = intEntry(mod_provider_table, "file-id"); diff --git a/launcher/modplatform/packwiz/Packwiz_test.cpp b/launcher/modplatform/packwiz/Packwiz_test.cpp index 2e61c167..08de332d 100644 --- a/launcher/modplatform/packwiz/Packwiz_test.cpp +++ b/launcher/modplatform/packwiz/Packwiz_test.cpp @@ -1,8 +1,8 @@ #include #include -#include "TestUtil.h" #include "Packwiz.h" +#include "TestUtil.h" class PackwizTest : public QObject { Q_OBJECT -- cgit From a99858c64d275303a9f91912a2732746ef6a3c8a Mon Sep 17 00:00:00 2001 From: flow Date: Tue, 19 Apr 2022 21:10:12 -0300 Subject: refactor: move code out of ModIndex.h Now it's in ModIndex.cpp --- launcher/CMakeLists.txt | 3 +++ launcher/modplatform/ModIndex.cpp | 24 ++++++++++++++++++++++++ launcher/modplatform/ModIndex.h | 22 ++-------------------- launcher/modplatform/flame/FlameAPI.h | 1 + launcher/modplatform/modrinth/ModrinthAPI.h | 1 + launcher/modplatform/packwiz/Packwiz.cpp | 11 ++++++----- 6 files changed, 37 insertions(+), 25 deletions(-) create mode 100644 launcher/modplatform/ModIndex.cpp (limited to 'launcher/modplatform/packwiz/Packwiz.cpp') diff --git a/launcher/CMakeLists.txt b/launcher/CMakeLists.txt index 6c7b5e43..1bab7ecb 100644 --- a/launcher/CMakeLists.txt +++ b/launcher/CMakeLists.txt @@ -500,6 +500,9 @@ set(META_SOURCES ) set(API_SOURCES + modplatform/ModIndex.h + modplatform/ModIndex.cpp + modplatform/ModAPI.h modplatform/flame/FlameAPI.h diff --git a/launcher/modplatform/ModIndex.cpp b/launcher/modplatform/ModIndex.cpp new file mode 100644 index 00000000..eb8be992 --- /dev/null +++ b/launcher/modplatform/ModIndex.cpp @@ -0,0 +1,24 @@ +#include "modplatform/ModIndex.h" + +namespace ModPlatform{ + +auto ProviderCapabilities::name(Provider p) -> const char* +{ + switch(p){ + case Provider::MODRINTH: + return "modrinth"; + case Provider::FLAME: + return "curseforge"; + } +} +auto ProviderCapabilities::hashType(Provider p) -> QString +{ + switch(p){ + case Provider::MODRINTH: + return "sha512"; + case Provider::FLAME: + return "murmur2"; + } +} + +} // namespace ModPlatform diff --git a/launcher/modplatform/ModIndex.h b/launcher/modplatform/ModIndex.h index ee623b78..bb5c7c9d 100644 --- a/launcher/modplatform/ModIndex.h +++ b/launcher/modplatform/ModIndex.h @@ -15,26 +15,8 @@ enum class Provider{ class ProviderCapabilities { public: - static QString hashType(Provider p) - { - switch(p){ - case Provider::MODRINTH: - return "sha512"; - case Provider::FLAME: - return "murmur2"; - } - return ""; - } - static const char* providerName(Provider p) - { - switch(p){ - case Provider::MODRINTH: - return "modrinth"; - case Provider::FLAME: - return "curseforge"; - } - return ""; - } + auto name(Provider) -> const char*; + auto hashType(Provider) -> QString; }; struct ModpackAuthor { diff --git a/launcher/modplatform/flame/FlameAPI.h b/launcher/modplatform/flame/FlameAPI.h index 8bb33d47..e31cf0a1 100644 --- a/launcher/modplatform/flame/FlameAPI.h +++ b/launcher/modplatform/flame/FlameAPI.h @@ -1,5 +1,6 @@ #pragma once +#include "modplatform/ModIndex.h" #include "modplatform/helpers/NetworkModAPI.h" class FlameAPI : public NetworkModAPI { diff --git a/launcher/modplatform/modrinth/ModrinthAPI.h b/launcher/modplatform/modrinth/ModrinthAPI.h index 79bc5175..f9d35fcd 100644 --- a/launcher/modplatform/modrinth/ModrinthAPI.h +++ b/launcher/modplatform/modrinth/ModrinthAPI.h @@ -20,6 +20,7 @@ #include "BuildConfig.h" #include "modplatform/ModAPI.h" +#include "modplatform/ModIndex.h" #include "modplatform/helpers/NetworkModAPI.h" #include diff --git a/launcher/modplatform/packwiz/Packwiz.cpp b/launcher/modplatform/packwiz/Packwiz.cpp index 978be462..872da9b1 100644 --- a/launcher/modplatform/packwiz/Packwiz.cpp +++ b/launcher/modplatform/packwiz/Packwiz.cpp @@ -19,6 +19,8 @@ static inline auto indexFileName(QString const& mod_name) -> QString return QString("%1.toml").arg(mod_name); } +static ModPlatform::ProviderCapabilities ProviderCaps; + auto V1::createModFormat(QDir& index_dir, ModPlatform::IndexedPack& mod_pack, ModPlatform::IndexedVersion& mod_version) -> Mod { Mod mod; @@ -27,7 +29,7 @@ auto V1::createModFormat(QDir& index_dir, ModPlatform::IndexedPack& mod_pack, Mo mod.filename = mod_version.fileName; mod.url = mod_version.downloadUrl; - mod.hash_format = ModPlatform::ProviderCapabilities::hashType(mod_pack.provider); + mod.hash_format = ProviderCaps.hashType(mod_pack.provider); mod.hash = ""; // FIXME mod.provider = mod_pack.provider; @@ -92,7 +94,7 @@ void V1::updateModIndex(QDir& index_dir, Mod& mod) addToStream("hash", mod.hash); in_stream << QString("\n[update]\n"); - in_stream << QString("[update.%1]\n").arg(ModPlatform::ProviderCapabilities::providerName(mod.provider)); + in_stream << QString("[update.%1]\n").arg(ProviderCaps.name(mod.provider)); switch(mod.provider){ case(ModPlatform::Provider::FLAME): in_stream << QString("file-id = %1\n").arg(mod.file_id.toString()); @@ -193,7 +195,6 @@ auto V1::getIndexForMod(QDir& index_dir, QString& index_file_name) -> Mod } { // [update] info - using ProviderCaps = ModPlatform::ProviderCapabilities; using Provider = ModPlatform::Provider; toml_table_t* update_table = toml_table_in(table, "update"); @@ -203,11 +204,11 @@ auto V1::getIndexForMod(QDir& index_dir, QString& index_file_name) -> Mod } toml_table_t* mod_provider_table = nullptr; - if ((mod_provider_table = toml_table_in(update_table, ProviderCaps::providerName(Provider::FLAME)))) { + if ((mod_provider_table = toml_table_in(update_table, ProviderCaps.name(Provider::FLAME)))) { mod.provider = Provider::FLAME; mod.file_id = intEntry(mod_provider_table, "file-id"); mod.project_id = intEntry(mod_provider_table, "project-id"); - } else if ((mod_provider_table = toml_table_in(update_table, ProviderCaps::providerName(Provider::MODRINTH)))) { + } else if ((mod_provider_table = toml_table_in(update_table, ProviderCaps.name(Provider::MODRINTH)))) { mod.provider = Provider::MODRINTH; mod.mod_id() = stringEntry(mod_provider_table, "mod-id"); mod.version() = stringEntry(mod_provider_table, "version"); -- cgit From 96e36f060443cbfa6d58df2adca3c8605851b4a3 Mon Sep 17 00:00:00 2001 From: flow Date: Wed, 20 Apr 2022 18:45:39 -0300 Subject: refactor: make mod metadata presence (or lack of) easier to find out --- launcher/minecraft/mod/Mod.cpp | 28 +++++++++++++++++++--- launcher/minecraft/mod/Mod.h | 6 +++-- launcher/minecraft/mod/ModDetails.h | 9 +++++++ launcher/minecraft/mod/tasks/ModFolderLoadTask.cpp | 8 ++++++- launcher/modplatform/ModIndex.cpp | 2 ++ launcher/modplatform/packwiz/Packwiz.cpp | 9 ++----- 6 files changed, 49 insertions(+), 13 deletions(-) (limited to 'launcher/modplatform/packwiz/Packwiz.cpp') diff --git a/launcher/minecraft/mod/Mod.cpp b/launcher/minecraft/mod/Mod.cpp index 992b91dc..261ae9d2 100644 --- a/launcher/minecraft/mod/Mod.cpp +++ b/launcher/minecraft/mod/Mod.cpp @@ -54,7 +54,6 @@ Mod::Mod(const QDir& mods_dir, const Metadata::ModStruct& metadata) m_type = MOD_SINGLEFILE; } - m_from_metadata = true; m_enabled = true; m_changedDateTime = m_file.lastModified(); @@ -117,13 +116,27 @@ auto Mod::enable(bool value) -> bool return false; } - if (!fromMetadata()) + if (status() == ModStatus::NoMetadata) repath(QFileInfo(path)); m_enabled = value; return true; } +void Mod::setStatus(ModStatus status) +{ + if(m_localDetails.get()) + m_localDetails->status = status; +} +void Mod::setMetadata(Metadata::ModStruct* metadata) +{ + if(status() == ModStatus::NoMetadata) + setStatus(ModStatus::Installed); + + if(m_localDetails.get()) + m_localDetails->metadata.reset(metadata); +} + auto Mod::destroy(QDir& index_dir) -> bool { auto n = name(); @@ -170,13 +183,22 @@ auto Mod::authors() const -> QStringList return details().authors; } +auto Mod::status() const -> ModStatus +{ + return details().status; +} + void Mod::finishResolvingWithDetails(std::shared_ptr details) { m_resolving = false; m_resolved = true; m_localDetails = details; - if (fromMetadata() && m_temp_metadata->isValid() && m_localDetails.get()) { + if (status() != ModStatus::NoMetadata + && m_temp_metadata.get() + && m_temp_metadata->isValid() && + m_localDetails.get()) { + m_localDetails->metadata.swap(m_temp_metadata); } } diff --git a/launcher/minecraft/mod/Mod.h b/launcher/minecraft/mod/Mod.h index 3a0ccfa6..58c7a80f 100644 --- a/launcher/minecraft/mod/Mod.h +++ b/launcher/minecraft/mod/Mod.h @@ -41,7 +41,6 @@ public: auto dateTimeChanged() const -> QDateTime { return m_changedDateTime; } auto internal_id() const -> QString { return m_internal_id; } auto type() const -> ModType { return m_type; } - auto fromMetadata() const -> bool { return m_from_metadata; } auto enabled() const -> bool { return m_enabled; } auto valid() const -> bool { return m_type != MOD_UNKNOWN; } @@ -52,10 +51,14 @@ public: auto homeurl() const -> QString; auto description() const -> QString; auto authors() const -> QStringList; + auto status() const -> ModStatus; auto metadata() const -> const std::shared_ptr { return details().metadata; }; auto metadata() -> std::shared_ptr { return m_localDetails->metadata; }; + void setStatus(ModStatus status); + void setMetadata(Metadata::ModStruct* metadata); + auto enable(bool value) -> bool; // delete all the files of this mod @@ -82,7 +85,6 @@ protected: /* Name as reported via the file name */ QString m_name; ModType m_type = MOD_UNKNOWN; - bool m_from_metadata = false; /* If the mod has metadata, this will be filled in the constructor, and passed to * the ModDetails when calling finishResolvingWithDetails */ diff --git a/launcher/minecraft/mod/ModDetails.h b/launcher/minecraft/mod/ModDetails.h index f9973fc2..75ffea32 100644 --- a/launcher/minecraft/mod/ModDetails.h +++ b/launcher/minecraft/mod/ModDetails.h @@ -7,6 +7,12 @@ #include "minecraft/mod/MetadataHandler.h" +enum class ModStatus { + Installed, // Both JAR and Metadata are present + NotInstalled, // Only the Metadata is present + NoMetadata, // Only the JAR is present +}; + struct ModDetails { /* Mod ID as defined in the ModLoader-specific metadata */ @@ -30,6 +36,9 @@ struct ModDetails /* List of the author's names */ QStringList authors; + /* Installation status of the mod */ + ModStatus status; + /* Metadata information, if any */ std::shared_ptr metadata; }; diff --git a/launcher/minecraft/mod/tasks/ModFolderLoadTask.cpp b/launcher/minecraft/mod/tasks/ModFolderLoadTask.cpp index 03a17461..addb0dd8 100644 --- a/launcher/minecraft/mod/tasks/ModFolderLoadTask.cpp +++ b/launcher/minecraft/mod/tasks/ModFolderLoadTask.cpp @@ -19,8 +19,13 @@ void ModFolderLoadTask::run() m_mods_dir.refresh(); for (auto entry : m_mods_dir.entryInfoList()) { Mod mod(entry); - if (!m_result->mods.contains(mod.internal_id())) + if(m_result->mods.contains(mod.internal_id())){ + m_result->mods[mod.internal_id()].setStatus(ModStatus::Installed); + } + else { m_result->mods[mod.internal_id()] = mod; + m_result->mods[mod.internal_id()].setStatus(ModStatus::NoMetadata); + } } emit succeeded(); @@ -42,6 +47,7 @@ void ModFolderLoadTask::getFromMetadata() } Mod mod(m_mods_dir, metadata); + mod.setStatus(ModStatus::NotInstalled); m_result->mods[mod.internal_id()] = mod; } } diff --git a/launcher/modplatform/ModIndex.cpp b/launcher/modplatform/ModIndex.cpp index eb8be992..b3c057fb 100644 --- a/launcher/modplatform/ModIndex.cpp +++ b/launcher/modplatform/ModIndex.cpp @@ -10,6 +10,7 @@ auto ProviderCapabilities::name(Provider p) -> const char* case Provider::FLAME: return "curseforge"; } + return {}; } auto ProviderCapabilities::hashType(Provider p) -> QString { @@ -19,6 +20,7 @@ auto ProviderCapabilities::hashType(Provider p) -> QString case Provider::FLAME: return "murmur2"; } + return {}; } } // namespace ModPlatform diff --git a/launcher/modplatform/packwiz/Packwiz.cpp b/launcher/modplatform/packwiz/Packwiz.cpp index 872da9b1..50f87c24 100644 --- a/launcher/modplatform/packwiz/Packwiz.cpp +++ b/launcher/modplatform/packwiz/Packwiz.cpp @@ -48,14 +48,9 @@ auto V1::createModFormat(QDir& index_dir, ::Mod& internal_mod) -> Mod if(mod.isValid()) return mod; - // Manually construct packwiz mod - mod.name = internal_mod.name(); - mod.filename = internal_mod.fileinfo().fileName(); + qWarning() << QString("Tried to create mod metadata with a Mod without metadata!"); - // TODO: Have a mechanism for telling the UI subsystem that we want to gather user information - // (i.e. which mod provider we want to use). Maybe an object parameter with a signal for that? - - return mod; + return {}; } void V1::updateModIndex(QDir& index_dir, Mod& mod) -- cgit From e17b6804a7424dd5161662c4ef92972f3311675c Mon Sep 17 00:00:00 2001 From: flow Date: Thu, 21 Apr 2022 15:45:20 -0300 Subject: fix: implement PR suggestions Some stylistic changes, and get hashes from the mod providers when building the metadata. --- launcher/Application.cpp | 2 +- launcher/minecraft/mod/tasks/ModFolderLoadTask.cpp | 11 +++-------- launcher/modplatform/ModIndex.h | 3 ++- launcher/modplatform/flame/FlameModIndex.cpp | 8 ++++++++ launcher/modplatform/modrinth/ModrinthPackIndex.cpp | 4 ++++ launcher/modplatform/packwiz/Packwiz.cpp | 2 +- launcher/ui/pages/global/LauncherPage.cpp | 2 +- 7 files changed, 20 insertions(+), 12 deletions(-) (limited to 'launcher/modplatform/packwiz/Packwiz.cpp') diff --git a/launcher/Application.cpp b/launcher/Application.cpp index ae4cbcf8..99e3d4c5 100644 --- a/launcher/Application.cpp +++ b/launcher/Application.cpp @@ -644,7 +644,7 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv) m_settings->registerSetting("MCLaunchMethod", "LauncherPart"); // Minecraft mods - m_settings->registerSetting("DontUseModMetadata", false); + m_settings->registerSetting("ModMetadataDisabled", false); // Minecraft offline player name m_settings->registerSetting("LastOfflinePlayerName", ""); diff --git a/launcher/minecraft/mod/tasks/ModFolderLoadTask.cpp b/launcher/minecraft/mod/tasks/ModFolderLoadTask.cpp index addb0dd8..fe807a29 100644 --- a/launcher/minecraft/mod/tasks/ModFolderLoadTask.cpp +++ b/launcher/minecraft/mod/tasks/ModFolderLoadTask.cpp @@ -10,7 +10,7 @@ ModFolderLoadTask::ModFolderLoadTask(QDir& mods_dir, QDir& index_dir) void ModFolderLoadTask::run() { - if (!APPLICATION->settings()->get("DontUseModMetadata").toBool()) { + if (!APPLICATION->settings()->get("ModMetadataDisabled").toBool()) { // Read metadata first getFromMetadata(); } @@ -34,14 +34,9 @@ void ModFolderLoadTask::run() void ModFolderLoadTask::getFromMetadata() { m_index_dir.refresh(); - for (auto entry : m_index_dir.entryList()) { - // QDir::Filter::NoDotAndDotDot seems to exclude all files for some reason... - if (entry == "." || entry == "..") - continue; - + for (auto entry : m_index_dir.entryList(QDir::Files)) { auto metadata = Metadata::get(m_index_dir, entry); - // TODO: Don't simply return. Instead, show to the user that the metadata is there, but - // it's not currently 'installed' (i.e. there's no JAR file yet). + if(!metadata.isValid()){ return; } diff --git a/launcher/modplatform/ModIndex.h b/launcher/modplatform/ModIndex.h index bb5c7c9d..2137f616 100644 --- a/launcher/modplatform/ModIndex.h +++ b/launcher/modplatform/ModIndex.h @@ -8,7 +8,7 @@ namespace ModPlatform { -enum class Provider{ +enum class Provider { MODRINTH, FLAME }; @@ -33,6 +33,7 @@ struct IndexedVersion { QString date; QString fileName; QVector loaders = {}; + QString hash; }; struct IndexedPack { diff --git a/launcher/modplatform/flame/FlameModIndex.cpp b/launcher/modplatform/flame/FlameModIndex.cpp index 45f02b71..4b172c13 100644 --- a/launcher/modplatform/flame/FlameModIndex.cpp +++ b/launcher/modplatform/flame/FlameModIndex.cpp @@ -6,6 +6,8 @@ #include "modplatform/flame/FlameAPI.h" #include "net/NetJob.h" +static ModPlatform::ProviderCapabilities ProviderCaps; + void FlameMod::loadIndexedPack(ModPlatform::IndexedPack& pack, QJsonObject& obj) { pack.addonId = Json::requireInteger(obj, "id"); @@ -60,6 +62,12 @@ void FlameMod::loadIndexedPackVersions(ModPlatform::IndexedPack& pack, file.downloadUrl = Json::requireString(obj, "downloadUrl"); file.fileName = Json::requireString(obj, "fileName"); + auto hash_list = Json::ensureArray(obj, "hashes"); + if(!hash_list.isEmpty()){ + if(hash_list.contains(ProviderCaps.hashType(ModPlatform::Provider::FLAME))) + file.hash = Json::requireString(hash_list, "value"); + } + unsortedVersions.append(file); } diff --git a/launcher/modplatform/modrinth/ModrinthPackIndex.cpp b/launcher/modplatform/modrinth/ModrinthPackIndex.cpp index 6c8659dc..8b750740 100644 --- a/launcher/modplatform/modrinth/ModrinthPackIndex.cpp +++ b/launcher/modplatform/modrinth/ModrinthPackIndex.cpp @@ -24,6 +24,7 @@ #include "net/NetJob.h" static ModrinthAPI api; +static ModPlatform::ProviderCapabilities ProviderCaps; void Modrinth::loadIndexedPack(ModPlatform::IndexedPack& pack, QJsonObject& obj) { @@ -95,6 +96,9 @@ void Modrinth::loadIndexedPackVersions(ModPlatform::IndexedPack& pack, if (parent.contains("url")) { file.downloadUrl = Json::requireString(parent, "url"); file.fileName = Json::requireString(parent, "filename"); + auto hash_list = Json::requireObject(parent, "hashes"); + if(hash_list.contains(ProviderCaps.hashType(ModPlatform::Provider::MODRINTH))) + file.hash = Json::requireString(hash_list, ProviderCaps.hashType(ModPlatform::Provider::MODRINTH)); unsortedVersions.append(file); } diff --git a/launcher/modplatform/packwiz/Packwiz.cpp b/launcher/modplatform/packwiz/Packwiz.cpp index 50f87c24..70efc6bd 100644 --- a/launcher/modplatform/packwiz/Packwiz.cpp +++ b/launcher/modplatform/packwiz/Packwiz.cpp @@ -30,7 +30,7 @@ auto V1::createModFormat(QDir& index_dir, ModPlatform::IndexedPack& mod_pack, Mo mod.url = mod_version.downloadUrl; mod.hash_format = ProviderCaps.hashType(mod_pack.provider); - mod.hash = ""; // FIXME + mod.hash = mod_version.hash; mod.provider = mod_pack.provider; mod.file_id = mod_pack.addonId; diff --git a/launcher/ui/pages/global/LauncherPage.cpp b/launcher/ui/pages/global/LauncherPage.cpp index 8754c0ec..faf9272d 100644 --- a/launcher/ui/pages/global/LauncherPage.cpp +++ b/launcher/ui/pages/global/LauncherPage.cpp @@ -345,7 +345,7 @@ void LauncherPage::applySettings() } // Mods - s->set("DontUseModMetadata", ui->metadataDisableBtn->isChecked()); + s->set("ModMetadataDisabled", ui->metadataDisableBtn->isChecked()); } void LauncherPage::loadSettings() { -- cgit From 67e0214fa5c1ff36d3718c3fb68107bf0dfe7e5d Mon Sep 17 00:00:00 2001 From: flow Date: Thu, 21 Apr 2022 15:47:46 -0300 Subject: fix: don't try to delete mods multiple times Shows a more helpful message if there's a parsing error when reading the index file. Also fixes a clazy warning with using the `.data()` method in a temporary QByteArray object. --- launcher/minecraft/mod/ModFolderModel.cpp | 3 +++ launcher/modplatform/packwiz/Packwiz.cpp | 6 ++++-- 2 files changed, 7 insertions(+), 2 deletions(-) (limited to 'launcher/modplatform/packwiz/Packwiz.cpp') diff --git a/launcher/minecraft/mod/ModFolderModel.cpp b/launcher/minecraft/mod/ModFolderModel.cpp index e034e35e..b2d8f03e 100644 --- a/launcher/minecraft/mod/ModFolderModel.cpp +++ b/launcher/minecraft/mod/ModFolderModel.cpp @@ -339,6 +339,9 @@ bool ModFolderModel::deleteMods(const QModelIndexList& indexes) for (auto i: indexes) { + if(i.column() != 0) { + continue; + } Mod &m = mods[i.row()]; auto index_dir = indexDir(); m.destroy(index_dir); diff --git a/launcher/modplatform/packwiz/Packwiz.cpp b/launcher/modplatform/packwiz/Packwiz.cpp index 70efc6bd..4fe4398a 100644 --- a/launcher/modplatform/packwiz/Packwiz.cpp +++ b/launcher/modplatform/packwiz/Packwiz.cpp @@ -162,12 +162,14 @@ auto V1::getIndexForMod(QDir& index_dir, QString& index_file_name) -> Mod // NOLINTNEXTLINE(modernize-avoid-c-arrays) char errbuf[200]; - table = toml_parse(index_file.readAll().data(), errbuf, sizeof(errbuf)); + auto file_bytearray = index_file.readAll(); + table = toml_parse(file_bytearray.data(), errbuf, sizeof(errbuf)); index_file.close(); if (!table) { - qCritical() << QString("Could not open file %1!").arg(indexFileName(mod.name)); + qWarning() << QString("Could not open file %1!").arg(indexFileName(index_file_name)); + qWarning() << "Reason: " << QString(errbuf); return {}; } -- cgit From 59d628208b403bfb2442291cbca139cbdfcd325f Mon Sep 17 00:00:00 2001 From: flow Date: Fri, 6 May 2022 12:42:01 -0300 Subject: feat: allow trying to use multiple hash types --- launcher/modplatform/ModIndex.cpp | 60 +++++++++++++++++----- launcher/modplatform/ModIndex.h | 5 +- launcher/modplatform/flame/FlameModIndex.cpp | 10 +++- .../modplatform/modrinth/ModrinthPackIndex.cpp | 10 +++- launcher/modplatform/packwiz/Packwiz.cpp | 2 +- 5 files changed, 68 insertions(+), 19 deletions(-) (limited to 'launcher/modplatform/packwiz/Packwiz.cpp') diff --git a/launcher/modplatform/ModIndex.cpp b/launcher/modplatform/ModIndex.cpp index b3c057fb..f6e134e0 100644 --- a/launcher/modplatform/ModIndex.cpp +++ b/launcher/modplatform/ModIndex.cpp @@ -1,26 +1,60 @@ #include "modplatform/ModIndex.h" -namespace ModPlatform{ +#include + +namespace ModPlatform { auto ProviderCapabilities::name(Provider p) -> const char* { - switch(p){ - case Provider::MODRINTH: - return "modrinth"; - case Provider::FLAME: - return "curseforge"; + switch (p) { + case Provider::MODRINTH: + return "modrinth"; + case Provider::FLAME: + return "curseforge"; + } + return {}; +} +auto ProviderCapabilities::readableName(Provider p) -> QString +{ + switch (p) { + case Provider::MODRINTH: + return "Modrinth"; + case Provider::FLAME: + return "CurseForge"; } return {}; } -auto ProviderCapabilities::hashType(Provider p) -> QString +auto ProviderCapabilities::hashType(Provider p) -> QStringList { - switch(p){ - case Provider::MODRINTH: - return "sha512"; - case Provider::FLAME: - return "murmur2"; + switch (p) { + case Provider::MODRINTH: + return { "sha512", "sha1" }; + case Provider::FLAME: + return { "murmur2" }; + } + return {}; +} +auto ProviderCapabilities::hash(Provider p, QByteArray& data, QString type) -> QByteArray +{ + switch (p) { + case Provider::MODRINTH: { + // NOTE: Data is the result of reading the entire JAR file! + + // If 'type' was specified, we use that + if (!type.isEmpty() && hashType(p).contains(type)) { + if (type == "sha512") + return QCryptographicHash::hash(data, QCryptographicHash::Sha512); + else if (type == "sha1") + return QCryptographicHash::hash(data, QCryptographicHash::Sha1); + } + + return QCryptographicHash::hash(data, QCryptographicHash::Sha512); + } + case Provider::FLAME: + // TODO + break; } return {}; } -} // namespace ModPlatform +} // namespace ModPlatform diff --git a/launcher/modplatform/ModIndex.h b/launcher/modplatform/ModIndex.h index 2137f616..8ada1fc6 100644 --- a/launcher/modplatform/ModIndex.h +++ b/launcher/modplatform/ModIndex.h @@ -16,7 +16,9 @@ enum class Provider { class ProviderCapabilities { public: auto name(Provider) -> const char*; - auto hashType(Provider) -> QString; + auto readableName(Provider) -> QString; + auto hashType(Provider) -> QStringList; + auto hash(Provider, QByteArray&, QString type = "") -> QByteArray; }; struct ModpackAuthor { @@ -33,6 +35,7 @@ struct IndexedVersion { QString date; QString fileName; QVector loaders = {}; + QString hash_type; QString hash; }; diff --git a/launcher/modplatform/flame/FlameModIndex.cpp b/launcher/modplatform/flame/FlameModIndex.cpp index 4b172c13..63411275 100644 --- a/launcher/modplatform/flame/FlameModIndex.cpp +++ b/launcher/modplatform/flame/FlameModIndex.cpp @@ -64,8 +64,14 @@ void FlameMod::loadIndexedPackVersions(ModPlatform::IndexedPack& pack, auto hash_list = Json::ensureArray(obj, "hashes"); if(!hash_list.isEmpty()){ - if(hash_list.contains(ProviderCaps.hashType(ModPlatform::Provider::FLAME))) - file.hash = Json::requireString(hash_list, "value"); + auto hash_types = ProviderCaps.hashType(ModPlatform::Provider::FLAME); + for(auto& hash_type : hash_types) { + if(hash_list.contains(hash_type)) { + file.hash = Json::requireString(hash_list, "value"); + file.hash_type = hash_type; + break; + } + } } unsortedVersions.append(file); diff --git a/launcher/modplatform/modrinth/ModrinthPackIndex.cpp b/launcher/modplatform/modrinth/ModrinthPackIndex.cpp index aa798381..30693a82 100644 --- a/launcher/modplatform/modrinth/ModrinthPackIndex.cpp +++ b/launcher/modplatform/modrinth/ModrinthPackIndex.cpp @@ -116,8 +116,14 @@ auto Modrinth::loadIndexedPackVersion(QJsonObject &obj) -> ModPlatform::IndexedV file.downloadUrl = Json::requireString(parent, "url"); file.fileName = Json::requireString(parent, "filename"); auto hash_list = Json::requireObject(parent, "hashes"); - if (hash_list.contains(ProviderCaps.hashType(ModPlatform::Provider::MODRINTH))) - file.hash = Json::requireString(hash_list, ProviderCaps.hashType(ModPlatform::Provider::MODRINTH)); + auto hash_types = ProviderCaps.hashType(ModPlatform::Provider::MODRINTH); + for (auto& hash_type : hash_types) { + if (hash_list.contains(hash_type)) { + file.hash = Json::requireString(hash_list, hash_type); + file.hash_type = hash_type; + break; + } + } return file; } diff --git a/launcher/modplatform/packwiz/Packwiz.cpp b/launcher/modplatform/packwiz/Packwiz.cpp index 4fe4398a..cb430c1f 100644 --- a/launcher/modplatform/packwiz/Packwiz.cpp +++ b/launcher/modplatform/packwiz/Packwiz.cpp @@ -29,7 +29,7 @@ auto V1::createModFormat(QDir& index_dir, ModPlatform::IndexedPack& mod_pack, Mo mod.filename = mod_version.fileName; mod.url = mod_version.downloadUrl; - mod.hash_format = ProviderCaps.hashType(mod_pack.provider); + mod.hash_format = mod_version.hash_type; mod.hash = mod_version.hash; mod.provider = mod_pack.provider; -- cgit From 0985adfd74758891c2e61c2de7f930119cab1386 Mon Sep 17 00:00:00 2001 From: flow Date: Sat, 7 May 2022 19:39:00 -0300 Subject: change: support newest changes with packwiz regarding CF --- launcher/modplatform/ModIndex.cpp | 12 +++++++++-- launcher/modplatform/flame/FlameModIndex.cpp | 25 ++++++++++++++++------ launcher/modplatform/packwiz/Packwiz.cpp | 15 ++++++++++--- launcher/modplatform/packwiz/Packwiz.h | 6 +++--- launcher/modplatform/packwiz/Packwiz_test.cpp | 6 +++--- .../packwiz/testdata/borderless-mining.pw.toml | 13 +++++++++++ .../packwiz/testdata/borderless-mining.toml | 13 ----------- .../screenshot-to-clipboard-fabric.pw.toml | 13 +++++++++++ .../testdata/screenshot-to-clipboard-fabric.toml | 13 ----------- 9 files changed, 72 insertions(+), 44 deletions(-) create mode 100644 launcher/modplatform/packwiz/testdata/borderless-mining.pw.toml delete mode 100644 launcher/modplatform/packwiz/testdata/borderless-mining.toml create mode 100644 launcher/modplatform/packwiz/testdata/screenshot-to-clipboard-fabric.pw.toml delete mode 100644 launcher/modplatform/packwiz/testdata/screenshot-to-clipboard-fabric.toml (limited to 'launcher/modplatform/packwiz/Packwiz.cpp') diff --git a/launcher/modplatform/ModIndex.cpp b/launcher/modplatform/ModIndex.cpp index f6e134e0..6027c4f3 100644 --- a/launcher/modplatform/ModIndex.cpp +++ b/launcher/modplatform/ModIndex.cpp @@ -30,7 +30,8 @@ auto ProviderCapabilities::hashType(Provider p) -> QStringList case Provider::MODRINTH: return { "sha512", "sha1" }; case Provider::FLAME: - return { "murmur2" }; + // Try newer formats first, fall back to old format + return { "sha1", "md5", "murmur2" }; } return {}; } @@ -51,7 +52,14 @@ auto ProviderCapabilities::hash(Provider p, QByteArray& data, QString type) -> Q return QCryptographicHash::hash(data, QCryptographicHash::Sha512); } case Provider::FLAME: - // TODO + // If 'type' was specified, we use that + if (!type.isEmpty() && hashType(p).contains(type)) { + if(type == "sha1") + return QCryptographicHash::hash(data, QCryptographicHash::Sha1); + else if (type == "md5") + return QCryptographicHash::hash(data, QCryptographicHash::Md5); + } + break; } return {}; diff --git a/launcher/modplatform/flame/FlameModIndex.cpp b/launcher/modplatform/flame/FlameModIndex.cpp index 63411275..00dac411 100644 --- a/launcher/modplatform/flame/FlameModIndex.cpp +++ b/launcher/modplatform/flame/FlameModIndex.cpp @@ -30,6 +30,17 @@ void FlameMod::loadIndexedPack(ModPlatform::IndexedPack& pack, QJsonObject& obj) } } +static QString enumToString(int hash_algorithm) +{ + switch(hash_algorithm){ + default: + case 1: + return "sha1"; + case 2: + return "md5"; + } +} + void FlameMod::loadIndexedPackVersions(ModPlatform::IndexedPack& pack, QJsonArray& arr, const shared_qobject_ptr& network, @@ -63,14 +74,14 @@ void FlameMod::loadIndexedPackVersions(ModPlatform::IndexedPack& pack, file.fileName = Json::requireString(obj, "fileName"); auto hash_list = Json::ensureArray(obj, "hashes"); - if(!hash_list.isEmpty()){ + for(auto h : hash_list){ + auto hash_entry = Json::ensureObject(h); auto hash_types = ProviderCaps.hashType(ModPlatform::Provider::FLAME); - for(auto& hash_type : hash_types) { - if(hash_list.contains(hash_type)) { - file.hash = Json::requireString(hash_list, "value"); - file.hash_type = hash_type; - break; - } + auto hash_algo = enumToString(Json::ensureInteger(hash_entry, "algo", 1, "algorithm")); + if(hash_types.contains(hash_algo)){ + file.hash = Json::requireString(hash_entry, "value"); + file.hash_type = hash_algo; + break; } } diff --git a/launcher/modplatform/packwiz/Packwiz.cpp b/launcher/modplatform/packwiz/Packwiz.cpp index cb430c1f..1ad6d75b 100644 --- a/launcher/modplatform/packwiz/Packwiz.cpp +++ b/launcher/modplatform/packwiz/Packwiz.cpp @@ -14,9 +14,9 @@ namespace Packwiz { // Helpers static inline auto indexFileName(QString const& mod_name) -> QString { - if(mod_name.endsWith(".toml")) + if(mod_name.endsWith(".pw.toml")) return mod_name; - return QString("%1.toml").arg(mod_name); + return QString("%1.pw.toml").arg(mod_name); } static ModPlatform::ProviderCapabilities ProviderCaps; @@ -28,7 +28,14 @@ auto V1::createModFormat(QDir& index_dir, ModPlatform::IndexedPack& mod_pack, Mo mod.name = mod_pack.name; mod.filename = mod_version.fileName; - mod.url = mod_version.downloadUrl; + if(mod_pack.provider == ModPlatform::Provider::FLAME){ + mod.mode = "metadata:curseforge"; + } + else { + mod.mode = "url"; + mod.url = mod_version.downloadUrl; + } + mod.hash_format = mod_version.hash_type; mod.hash = mod_version.hash; @@ -84,6 +91,7 @@ void V1::updateModIndex(QDir& index_dir, Mod& mod) addToStream("side", mod.side); in_stream << QString("\n[download]\n"); + addToStream("mode", mod.mode); addToStream("url", mod.url.toString()); addToStream("hash-format", mod.hash_format); addToStream("hash", mod.hash); @@ -186,6 +194,7 @@ auto V1::getIndexForMod(QDir& index_dir, QString& index_file_name) -> Mod return {}; } + mod.mode = stringEntry(download_table, "mode"); mod.url = stringEntry(download_table, "url"); mod.hash_format = stringEntry(download_table, "hash-format"); mod.hash = stringEntry(download_table, "hash"); diff --git a/launcher/modplatform/packwiz/Packwiz.h b/launcher/modplatform/packwiz/Packwiz.h index 69125dbc..e66d0030 100644 --- a/launcher/modplatform/packwiz/Packwiz.h +++ b/launcher/modplatform/packwiz/Packwiz.h @@ -22,8 +22,8 @@ class V1 { QString side {"both"}; // [download] + QString mode {}; QUrl url {}; - // FIXME: make hash-format an enum QString hash_format {}; QString hash {}; @@ -42,11 +42,11 @@ class V1 { auto version() -> QVariant& { return file_id; } }; - /* Generates the object representing the information in a mod.toml file via + /* Generates the object representing the information in a mod.pw.toml file via * its common representation in the launcher, when downloading mods. * */ static auto createModFormat(QDir& index_dir, ModPlatform::IndexedPack& mod_pack, ModPlatform::IndexedVersion& mod_version) -> Mod; - /* Generates the object representing the information in a mod.toml file via + /* Generates the object representing the information in a mod.pw.toml file via * its common representation in the launcher. * */ static auto createModFormat(QDir& index_dir, ::Mod& internal_mod) -> Mod; diff --git a/launcher/modplatform/packwiz/Packwiz_test.cpp b/launcher/modplatform/packwiz/Packwiz_test.cpp index 08de332d..9f3c486e 100644 --- a/launcher/modplatform/packwiz/Packwiz_test.cpp +++ b/launcher/modplatform/packwiz/Packwiz_test.cpp @@ -14,7 +14,7 @@ class PackwizTest : public QObject { QString source = QFINDTESTDATA("testdata"); QDir index_dir(source); - QString name_mod("borderless-mining.toml"); + QString name_mod("borderless-mining.pw.toml"); QVERIFY(index_dir.entryList().contains(name_mod)); auto metadata = Packwiz::V1::getIndexForMod(index_dir, name_mod); @@ -39,10 +39,10 @@ class PackwizTest : public QObject { QString source = QFINDTESTDATA("testdata"); QDir index_dir(source); - QString name_mod("screenshot-to-clipboard-fabric.toml"); + QString name_mod("screenshot-to-clipboard-fabric.pw.toml"); QVERIFY(index_dir.entryList().contains(name_mod)); - // Try without the .toml at the end + // Try without the .pw.toml at the end name_mod.chop(5); auto metadata = Packwiz::V1::getIndexForMod(index_dir, name_mod); diff --git a/launcher/modplatform/packwiz/testdata/borderless-mining.pw.toml b/launcher/modplatform/packwiz/testdata/borderless-mining.pw.toml new file mode 100644 index 00000000..16545fd4 --- /dev/null +++ b/launcher/modplatform/packwiz/testdata/borderless-mining.pw.toml @@ -0,0 +1,13 @@ +name = "Borderless Mining" +filename = "borderless-mining-1.1.1+1.18.jar" +side = "client" + +[download] +url = "https://cdn.modrinth.com/data/kYq5qkSL/versions/1.1.1+1.18/borderless-mining-1.1.1+1.18.jar" +hash-format = "sha512" +hash = "c8fe6e15ddea32668822dddb26e1851e5f03834be4bcb2eff9c0da7fdc086a9b6cead78e31a44d3bc66335cba11144ee0337c6d5346f1ba63623064499b3188d" + +[update] +[update.modrinth] +mod-id = "kYq5qkSL" +version = "ug2qKTPR" diff --git a/launcher/modplatform/packwiz/testdata/borderless-mining.toml b/launcher/modplatform/packwiz/testdata/borderless-mining.toml deleted file mode 100644 index 16545fd4..00000000 --- a/launcher/modplatform/packwiz/testdata/borderless-mining.toml +++ /dev/null @@ -1,13 +0,0 @@ -name = "Borderless Mining" -filename = "borderless-mining-1.1.1+1.18.jar" -side = "client" - -[download] -url = "https://cdn.modrinth.com/data/kYq5qkSL/versions/1.1.1+1.18/borderless-mining-1.1.1+1.18.jar" -hash-format = "sha512" -hash = "c8fe6e15ddea32668822dddb26e1851e5f03834be4bcb2eff9c0da7fdc086a9b6cead78e31a44d3bc66335cba11144ee0337c6d5346f1ba63623064499b3188d" - -[update] -[update.modrinth] -mod-id = "kYq5qkSL" -version = "ug2qKTPR" diff --git a/launcher/modplatform/packwiz/testdata/screenshot-to-clipboard-fabric.pw.toml b/launcher/modplatform/packwiz/testdata/screenshot-to-clipboard-fabric.pw.toml new file mode 100644 index 00000000..87d70ada --- /dev/null +++ b/launcher/modplatform/packwiz/testdata/screenshot-to-clipboard-fabric.pw.toml @@ -0,0 +1,13 @@ +name = "Screenshot to Clipboard (Fabric)" +filename = "screenshot-to-clipboard-1.0.7-fabric.jar" +side = "both" + +[download] +url = "https://edge.forgecdn.net/files/3509/43/screenshot-to-clipboard-1.0.7-fabric.jar" +hash-format = "murmur2" +hash = "1781245820" + +[update] +[update.curseforge] +file-id = 3509043 +project-id = 327154 diff --git a/launcher/modplatform/packwiz/testdata/screenshot-to-clipboard-fabric.toml b/launcher/modplatform/packwiz/testdata/screenshot-to-clipboard-fabric.toml deleted file mode 100644 index 87d70ada..00000000 --- a/launcher/modplatform/packwiz/testdata/screenshot-to-clipboard-fabric.toml +++ /dev/null @@ -1,13 +0,0 @@ -name = "Screenshot to Clipboard (Fabric)" -filename = "screenshot-to-clipboard-1.0.7-fabric.jar" -side = "both" - -[download] -url = "https://edge.forgecdn.net/files/3509/43/screenshot-to-clipboard-1.0.7-fabric.jar" -hash-format = "murmur2" -hash = "1781245820" - -[update] -[update.curseforge] -file-id = 3509043 -project-id = 327154 -- cgit From 2fc1b999117ceebc3ebf05d96b0a749e3a0f9e98 Mon Sep 17 00:00:00 2001 From: flow Date: Tue, 10 May 2022 19:57:47 -0300 Subject: chore: add license headers Prevents a massive inload of Scrumplex ditto's :) I didn't add it to every file modified in this PR because the other changes are pretty minor, and would explode the diff of the PR. I hope that's not a problem O_O --- launcher/ModDownloadTask.cpp | 20 ++++++++- launcher/ModDownloadTask.h | 27 +++++++++--- launcher/minecraft/mod/MetadataHandler.h | 18 ++++++++ launcher/minecraft/mod/Mod.cpp | 48 +++++++++++++++------- launcher/minecraft/mod/Mod.h | 48 +++++++++++++++------- launcher/minecraft/mod/ModDetails.h | 35 ++++++++++++++++ .../minecraft/mod/tasks/LocalModUpdateTask.cpp | 20 ++++++++- launcher/minecraft/mod/tasks/LocalModUpdateTask.h | 18 ++++++++ launcher/minecraft/mod/tasks/ModFolderLoadTask.cpp | 36 +++++++++++++++- launcher/minecraft/mod/tasks/ModFolderLoadTask.h | 35 ++++++++++++++++ launcher/modplatform/ModIndex.cpp | 18 ++++++++ launcher/modplatform/ModIndex.h | 18 ++++++++ .../modplatform/modrinth/ModrinthPackIndex.cpp | 29 ++++++------- launcher/modplatform/packwiz/Packwiz.cpp | 18 ++++++++ launcher/modplatform/packwiz/Packwiz.h | 18 ++++++++ launcher/modplatform/packwiz/Packwiz_test.cpp | 18 ++++++++ 16 files changed, 373 insertions(+), 51 deletions(-) (limited to 'launcher/modplatform/packwiz/Packwiz.cpp') diff --git a/launcher/ModDownloadTask.cpp b/launcher/ModDownloadTask.cpp index 52de9c94..301b6637 100644 --- a/launcher/ModDownloadTask.cpp +++ b/launcher/ModDownloadTask.cpp @@ -1,7 +1,25 @@ +// SPDX-License-Identifier: GPL-3.0-only +/* +* PolyMC - Minecraft Launcher +* Copyright (c) 2022 flowln +* +* 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 . +*/ + #include "ModDownloadTask.h" #include "Application.h" -#include "minecraft/mod/tasks/LocalModUpdateTask.h" +#include "minecraft/mod/ModFolderModel.h" ModDownloadTask::ModDownloadTask(ModPlatform::IndexedPack mod, ModPlatform::IndexedVersion version, const std::shared_ptr mods) : m_mod(mod), m_mod_version(version), mods(mods) diff --git a/launcher/ModDownloadTask.h b/launcher/ModDownloadTask.h index 5eaee187..f4438a8d 100644 --- a/launcher/ModDownloadTask.h +++ b/launcher/ModDownloadTask.h @@ -1,14 +1,31 @@ +// SPDX-License-Identifier: GPL-3.0-only +/* +* PolyMC - Minecraft Launcher +* Copyright (c) 2022 flowln +* +* 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 . +*/ + #pragma once -#include -#include "QObjectPtr.h" -#include "minecraft/mod/ModFolderModel.h" -#include "modplatform/ModIndex.h" #include "net/NetJob.h" - #include "tasks/SequentialTask.h" + +#include "modplatform/ModIndex.h" #include "minecraft/mod/tasks/LocalModUpdateTask.h" +class ModFolderModel; + class ModDownloadTask : public SequentialTask { Q_OBJECT public: diff --git a/launcher/minecraft/mod/MetadataHandler.h b/launcher/minecraft/mod/MetadataHandler.h index 26b1f799..56962818 100644 --- a/launcher/minecraft/mod/MetadataHandler.h +++ b/launcher/minecraft/mod/MetadataHandler.h @@ -1,3 +1,21 @@ +// SPDX-License-Identifier: GPL-3.0-only +/* +* PolyMC - Minecraft Launcher +* Copyright (c) 2022 flowln +* +* 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 . +*/ + #pragma once #include diff --git a/launcher/minecraft/mod/Mod.cpp b/launcher/minecraft/mod/Mod.cpp index 261ae9d2..71a32d32 100644 --- a/launcher/minecraft/mod/Mod.cpp +++ b/launcher/minecraft/mod/Mod.cpp @@ -1,17 +1,37 @@ -/* 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 +* +* 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 . +* +* 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" diff --git a/launcher/minecraft/mod/Mod.h b/launcher/minecraft/mod/Mod.h index 58c7a80f..96d471b4 100644 --- a/launcher/minecraft/mod/Mod.h +++ b/launcher/minecraft/mod/Mod.h @@ -1,17 +1,37 @@ -/* 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 +* +* 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 . +* +* 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. +*/ #pragma once diff --git a/launcher/minecraft/mod/ModDetails.h b/launcher/minecraft/mod/ModDetails.h index 75ffea32..3e0a7ab0 100644 --- a/launcher/minecraft/mod/ModDetails.h +++ b/launcher/minecraft/mod/ModDetails.h @@ -1,3 +1,38 @@ +// SPDX-License-Identifier: GPL-3.0-only +/* +* PolyMC - Minecraft Launcher +* Copyright (c) 2022 flowln +* +* 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 . +* +* 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. +*/ + #pragma once #include diff --git a/launcher/minecraft/mod/tasks/LocalModUpdateTask.cpp b/launcher/minecraft/mod/tasks/LocalModUpdateTask.cpp index 47207ada..cbe16567 100644 --- a/launcher/minecraft/mod/tasks/LocalModUpdateTask.cpp +++ b/launcher/minecraft/mod/tasks/LocalModUpdateTask.cpp @@ -1,6 +1,22 @@ -#include "LocalModUpdateTask.h" +// SPDX-License-Identifier: GPL-3.0-only +/* +* PolyMC - Minecraft Launcher +* Copyright (c) 2022 flowln +* +* 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 . +*/ -#include +#include "LocalModUpdateTask.h" #include "Application.h" #include "FileSystem.h" diff --git a/launcher/minecraft/mod/tasks/LocalModUpdateTask.h b/launcher/minecraft/mod/tasks/LocalModUpdateTask.h index f21c0b06..2db183e0 100644 --- a/launcher/minecraft/mod/tasks/LocalModUpdateTask.h +++ b/launcher/minecraft/mod/tasks/LocalModUpdateTask.h @@ -1,3 +1,21 @@ +// SPDX-License-Identifier: GPL-3.0-only +/* +* PolyMC - Minecraft Launcher +* Copyright (c) 2022 flowln +* +* 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 . +*/ + #pragma once #include diff --git a/launcher/minecraft/mod/tasks/ModFolderLoadTask.cpp b/launcher/minecraft/mod/tasks/ModFolderLoadTask.cpp index fe807a29..62d856f6 100644 --- a/launcher/minecraft/mod/tasks/ModFolderLoadTask.cpp +++ b/launcher/minecraft/mod/tasks/ModFolderLoadTask.cpp @@ -1,5 +1,39 @@ +// SPDX-License-Identifier: GPL-3.0-only +/* +* PolyMC - Minecraft Launcher +* Copyright (c) 2022 flowln +* +* 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 . +* +* 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 "ModFolderLoadTask.h" -#include #include "Application.h" #include "minecraft/mod/MetadataHandler.h" diff --git a/launcher/minecraft/mod/tasks/ModFolderLoadTask.h b/launcher/minecraft/mod/tasks/ModFolderLoadTask.h index ba997874..89a0f84e 100644 --- a/launcher/minecraft/mod/tasks/ModFolderLoadTask.h +++ b/launcher/minecraft/mod/tasks/ModFolderLoadTask.h @@ -1,3 +1,38 @@ +// SPDX-License-Identifier: GPL-3.0-only +/* +* PolyMC - Minecraft Launcher +* Copyright (c) 2022 flowln +* +* 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 . +* +* 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. +*/ + #pragma once #include diff --git a/launcher/modplatform/ModIndex.cpp b/launcher/modplatform/ModIndex.cpp index 6027c4f3..3c4b7887 100644 --- a/launcher/modplatform/ModIndex.cpp +++ b/launcher/modplatform/ModIndex.cpp @@ -1,3 +1,21 @@ +// SPDX-License-Identifier: GPL-3.0-only +/* +* PolyMC - Minecraft Launcher +* Copyright (c) 2022 flowln +* +* 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 . +*/ + #include "modplatform/ModIndex.h" #include diff --git a/launcher/modplatform/ModIndex.h b/launcher/modplatform/ModIndex.h index 8ada1fc6..04dd2dac 100644 --- a/launcher/modplatform/ModIndex.h +++ b/launcher/modplatform/ModIndex.h @@ -1,3 +1,21 @@ +// SPDX-License-Identifier: GPL-3.0-only +/* +* PolyMC - Minecraft Launcher +* Copyright (c) 2022 flowln +* +* 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 . +*/ + #pragma once #include diff --git a/launcher/modplatform/modrinth/ModrinthPackIndex.cpp b/launcher/modplatform/modrinth/ModrinthPackIndex.cpp index 30693a82..fdce71c3 100644 --- a/launcher/modplatform/modrinth/ModrinthPackIndex.cpp +++ b/launcher/modplatform/modrinth/ModrinthPackIndex.cpp @@ -1,19 +1,20 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher - * - * 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 . - */ +* PolyMC - Minecraft Launcher +* Copyright (c) 2022 flowln +* +* 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 . +*/ #include "ModrinthPackIndex.h" #include "ModrinthAPI.h" diff --git a/launcher/modplatform/packwiz/Packwiz.cpp b/launcher/modplatform/packwiz/Packwiz.cpp index 1ad6d75b..91a5f9c6 100644 --- a/launcher/modplatform/packwiz/Packwiz.cpp +++ b/launcher/modplatform/packwiz/Packwiz.cpp @@ -1,3 +1,21 @@ +// SPDX-License-Identifier: GPL-3.0-only +/* +* PolyMC - Minecraft Launcher +* Copyright (c) 2022 flowln +* +* 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 . +*/ + #include "Packwiz.h" #include diff --git a/launcher/modplatform/packwiz/Packwiz.h b/launcher/modplatform/packwiz/Packwiz.h index e66d0030..58b86484 100644 --- a/launcher/modplatform/packwiz/Packwiz.h +++ b/launcher/modplatform/packwiz/Packwiz.h @@ -1,3 +1,21 @@ +// SPDX-License-Identifier: GPL-3.0-only +/* +* PolyMC - Minecraft Launcher +* Copyright (c) 2022 flowln +* +* 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 . +*/ + #pragma once #include "modplatform/ModIndex.h" diff --git a/launcher/modplatform/packwiz/Packwiz_test.cpp b/launcher/modplatform/packwiz/Packwiz_test.cpp index 9f3c486e..023b990e 100644 --- a/launcher/modplatform/packwiz/Packwiz_test.cpp +++ b/launcher/modplatform/packwiz/Packwiz_test.cpp @@ -1,3 +1,21 @@ +// SPDX-License-Identifier: GPL-3.0-only +/* +* PolyMC - Minecraft Launcher +* Copyright (c) 2022 flowln +* +* 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 . +*/ + #include #include -- cgit From 42f8ec5b1489c2073adf9d3526080c434dbddd90 Mon Sep 17 00:00:00 2001 From: flow Date: Fri, 13 May 2022 11:42:08 -0300 Subject: fix: do modrinth changes on flame too Also fix a dumb moment --- launcher/modplatform/flame/FlameModIndex.cpp | 75 ++++++++++++++++------------ launcher/modplatform/flame/FlameModIndex.h | 1 + launcher/modplatform/packwiz/Packwiz.cpp | 4 +- 3 files changed, 45 insertions(+), 35 deletions(-) (limited to 'launcher/modplatform/packwiz/Packwiz.cpp') diff --git a/launcher/modplatform/flame/FlameModIndex.cpp b/launcher/modplatform/flame/FlameModIndex.cpp index 00dac411..ed6d64c3 100644 --- a/launcher/modplatform/flame/FlameModIndex.cpp +++ b/launcher/modplatform/flame/FlameModIndex.cpp @@ -52,40 +52,13 @@ void FlameMod::loadIndexedPackVersions(ModPlatform::IndexedPack& pack, for (auto versionIter : arr) { auto obj = versionIter.toObject(); + + auto file = loadIndexedPackVersion(obj); + if(!file.addonId.isValid()) + file.addonId = pack.addonId; - auto versionArray = Json::requireArray(obj, "gameVersions"); - if (versionArray.isEmpty()) { - continue; - } - - ModPlatform::IndexedVersion file; - for (auto mcVer : versionArray) { - auto str = mcVer.toString(); - - if (str.contains('.')) - file.mcVersion.append(str); - } - - file.addonId = pack.addonId; - file.fileId = Json::requireInteger(obj, "id"); - file.date = Json::requireString(obj, "fileDate"); - file.version = Json::requireString(obj, "displayName"); - file.downloadUrl = Json::requireString(obj, "downloadUrl"); - file.fileName = Json::requireString(obj, "fileName"); - - auto hash_list = Json::ensureArray(obj, "hashes"); - for(auto h : hash_list){ - auto hash_entry = Json::ensureObject(h); - auto hash_types = ProviderCaps.hashType(ModPlatform::Provider::FLAME); - auto hash_algo = enumToString(Json::ensureInteger(hash_entry, "algo", 1, "algorithm")); - if(hash_types.contains(hash_algo)){ - file.hash = Json::requireString(hash_entry, "value"); - file.hash_type = hash_algo; - break; - } - } - - unsortedVersions.append(file); + if(file.fileId.isValid()) // Heuristic to check if the returned value is valid + unsortedVersions.append(file); } auto orderSortPredicate = [](const ModPlatform::IndexedVersion& a, const ModPlatform::IndexedVersion& b) -> bool { @@ -96,3 +69,39 @@ void FlameMod::loadIndexedPackVersions(ModPlatform::IndexedPack& pack, pack.versions = unsortedVersions; pack.versionsLoaded = true; } + +auto FlameMod::loadIndexedPackVersion(QJsonObject& obj) -> ModPlatform::IndexedVersion +{ + auto versionArray = Json::requireArray(obj, "gameVersions"); + if (versionArray.isEmpty()) { + return {}; + } + + ModPlatform::IndexedVersion file; + for (auto mcVer : versionArray) { + auto str = mcVer.toString(); + + if (str.contains('.')) + file.mcVersion.append(str); + } + + file.addonId = Json::requireInteger(obj, "modId"); + file.fileId = Json::requireInteger(obj, "id"); + file.date = Json::requireString(obj, "fileDate"); + file.version = Json::requireString(obj, "displayName"); + file.downloadUrl = Json::requireString(obj, "downloadUrl"); + file.fileName = Json::requireString(obj, "fileName"); + + auto hash_list = Json::ensureArray(obj, "hashes"); + for (auto h : hash_list) { + auto hash_entry = Json::ensureObject(h); + auto hash_types = ProviderCaps.hashType(ModPlatform::Provider::FLAME); + auto hash_algo = enumToString(Json::ensureInteger(hash_entry, "algo", 1, "algorithm")); + if (hash_types.contains(hash_algo)) { + file.hash = Json::requireString(hash_entry, "value"); + file.hash_type = hash_algo; + break; + } + } + return file; +} diff --git a/launcher/modplatform/flame/FlameModIndex.h b/launcher/modplatform/flame/FlameModIndex.h index d3171d94..2e0f2e86 100644 --- a/launcher/modplatform/flame/FlameModIndex.h +++ b/launcher/modplatform/flame/FlameModIndex.h @@ -16,5 +16,6 @@ void loadIndexedPackVersions(ModPlatform::IndexedPack& pack, QJsonArray& arr, const shared_qobject_ptr& network, BaseInstance* inst); +auto loadIndexedPackVersion(QJsonObject& obj) -> ModPlatform::IndexedVersion; } // namespace FlameMod diff --git a/launcher/modplatform/packwiz/Packwiz.cpp b/launcher/modplatform/packwiz/Packwiz.cpp index 91a5f9c6..ee82f8a0 100644 --- a/launcher/modplatform/packwiz/Packwiz.cpp +++ b/launcher/modplatform/packwiz/Packwiz.cpp @@ -58,8 +58,8 @@ auto V1::createModFormat(QDir& index_dir, ModPlatform::IndexedPack& mod_pack, Mo mod.hash = mod_version.hash; mod.provider = mod_pack.provider; - mod.file_id = mod_pack.addonId; - mod.project_id = mod_version.fileId; + mod.file_id = mod_version.fileId; + mod.project_id = mod_pack.addonId; return mod; } -- cgit From 5a1de15332bcfbeafff7d0c678d7286ca85cfe18 Mon Sep 17 00:00:00 2001 From: flow Date: Wed, 18 May 2022 05:46:07 -0300 Subject: fix: use a more robust method of finding metadata indexes Often times, mods can have their name in different forms, changing one letter to caps or the other way (e.g. JourneyMaps -> Journeymaps). This makes it possible to find those as well, which is not perfect by any means, but should suffice for the majority of cases. --- launcher/modplatform/packwiz/Packwiz.cpp | 110 +++++++++++++++++++++---------- launcher/modplatform/packwiz/Packwiz.h | 6 ++ 2 files changed, 80 insertions(+), 36 deletions(-) (limited to 'launcher/modplatform/packwiz/Packwiz.cpp') diff --git a/launcher/modplatform/packwiz/Packwiz.cpp b/launcher/modplatform/packwiz/Packwiz.cpp index ee82f8a0..0782b9f4 100644 --- a/launcher/modplatform/packwiz/Packwiz.cpp +++ b/launcher/modplatform/packwiz/Packwiz.cpp @@ -23,12 +23,37 @@ #include #include "toml.h" +#include "FileSystem.h" #include "minecraft/mod/Mod.h" #include "modplatform/ModIndex.h" namespace Packwiz { +auto getRealIndexName(QDir& index_dir, QString normalized_fname, bool should_find_match) -> QString +{ + QFile index_file(index_dir.absoluteFilePath(normalized_fname)); + + QString real_fname = normalized_fname; + if (!index_file.exists()) { + // Tries to get similar entries + for (auto& file_name : index_dir.entryList(QDir::Filter::Files)) { + if (!QString::compare(normalized_fname, file_name, Qt::CaseInsensitive)) { + real_fname = file_name; + break; + } + } + + if(should_find_match && !QString::compare(normalized_fname, real_fname, Qt::CaseSensitive)){ + qCritical() << "Could not find a match for a valid metadata file!"; + qCritical() << "File: " << normalized_fname; + return {}; + } + } + + return real_fname; +} + // Helpers static inline auto indexFileName(QString const& mod_name) -> QString { @@ -39,6 +64,33 @@ static inline auto indexFileName(QString const& mod_name) -> QString static ModPlatform::ProviderCapabilities ProviderCaps; +// Helper functions for extracting data from the TOML file +auto stringEntry(toml_table_t* parent, const char* entry_name) -> QString +{ + toml_datum_t var = toml_string_in(parent, entry_name); + if (!var.ok) { + qCritical() << QString("Failed to read str property '%1' in mod metadata.").arg(entry_name); + return {}; + } + + QString tmp = var.u.s; + free(var.u.s); + + return tmp; +} + +auto intEntry(toml_table_t* parent, const char* entry_name) -> int +{ + toml_datum_t var = toml_int_in(parent, entry_name); + if (!var.ok) { + qCritical() << QString("Failed to read int property '%1' in mod metadata.").arg(entry_name); + return {}; + } + + return var.u.i; +} + + auto V1::createModFormat(QDir& index_dir, ModPlatform::IndexedPack& mod_pack, ModPlatform::IndexedVersion& mod_version) -> Mod { Mod mod; @@ -86,7 +138,11 @@ void V1::updateModIndex(QDir& index_dir, Mod& mod) } // Ensure the corresponding mod's info exists, and create it if not - QFile index_file(index_dir.absoluteFilePath(indexFileName(mod.name))); + + auto normalized_fname = indexFileName(mod.name); + auto real_fname = getRealIndexName(index_dir, normalized_fname); + + QFile index_file(index_dir.absoluteFilePath(real_fname)); // There's already data on there! // TODO: We should do more stuff here, as the user is likely trying to @@ -127,11 +183,18 @@ void V1::updateModIndex(QDir& index_dir, Mod& mod) break; } } + + index_file.close(); } void V1::deleteModIndex(QDir& index_dir, QString& mod_name) { - QFile index_file(index_dir.absoluteFilePath(indexFileName(mod_name))); + auto normalized_fname = indexFileName(mod_name); + auto real_fname = getRealIndexName(index_dir, normalized_fname); + if (real_fname.isEmpty()) + return; + + QFile index_file(index_dir.absoluteFilePath(real_fname)); if(!index_file.exists()){ qWarning() << QString("Tried to delete non-existent mod metadata for %1!").arg(mod_name); @@ -143,42 +206,17 @@ void V1::deleteModIndex(QDir& index_dir, QString& mod_name) } } -// Helper functions for extracting data from the TOML file -static auto stringEntry(toml_table_t* parent, const char* entry_name) -> QString -{ - toml_datum_t var = toml_string_in(parent, entry_name); - if (!var.ok) { - qCritical() << QString("Failed to read str property '%1' in mod metadata.").arg(entry_name); - return {}; - } - - QString tmp = var.u.s; - free(var.u.s); - - return tmp; -} - -static auto intEntry(toml_table_t* parent, const char* entry_name) -> int -{ - toml_datum_t var = toml_int_in(parent, entry_name); - if (!var.ok) { - qCritical() << QString("Failed to read int property '%1' in mod metadata.").arg(entry_name); - return {}; - } - - return var.u.i; -} - auto V1::getIndexForMod(QDir& index_dir, QString& index_file_name) -> Mod { Mod mod; - QFile index_file(index_dir.absoluteFilePath(indexFileName(index_file_name))); - - if (!index_file.exists()) { - qWarning() << QString("Tried to get a non-existent mod metadata for %1").arg(index_file_name); + auto normalized_fname = indexFileName(index_file_name); + auto real_fname = getRealIndexName(index_dir, normalized_fname, true); + if (real_fname.isEmpty()) return {}; - } + + QFile index_file(index_dir.absoluteFilePath(real_fname)); + if (!index_file.open(QIODevice::ReadOnly)) { qWarning() << QString("Failed to open mod metadata for %1").arg(index_file_name); return {}; @@ -198,14 +236,14 @@ auto V1::getIndexForMod(QDir& index_dir, QString& index_file_name) -> Mod qWarning() << "Reason: " << QString(errbuf); return {}; } - - { // Basic info + + { // Basic info mod.name = stringEntry(table, "name"); mod.filename = stringEntry(table, "filename"); mod.side = stringEntry(table, "side"); } - { // [download] info + { // [download] info toml_table_t* download_table = toml_table_in(table, "download"); if (!download_table) { qCritical() << QString("No [download] section found on mod metadata!"); diff --git a/launcher/modplatform/packwiz/Packwiz.h b/launcher/modplatform/packwiz/Packwiz.h index 58b86484..3c99769c 100644 --- a/launcher/modplatform/packwiz/Packwiz.h +++ b/launcher/modplatform/packwiz/Packwiz.h @@ -24,6 +24,7 @@ #include #include +struct toml_table_t; class QDir; // Mod from launcher/minecraft/mod/Mod.h @@ -31,6 +32,11 @@ class Mod; namespace Packwiz { +auto getRealIndexName(QDir& index_dir, QString normalized_index_name, bool should_match = false) -> QString; + +auto stringEntry(toml_table_t* parent, const char* entry_name) -> QString; +auto intEntry(toml_table_t* parent, const char* entry_name) -> int; + class V1 { public: struct Mod { -- cgit