aboutsummaryrefslogtreecommitdiff
path: root/launcher/modplatform
diff options
context:
space:
mode:
authorSefa Eyeoglu <contact@scrumplex.net>2023-01-23 23:58:52 +0100
committerGitHub <noreply@github.com>2023-01-23 23:58:52 +0100
commit16477a8f6c1fc646208b41b76598ce8e7a60369e (patch)
tree782055d4c36affd2b9bd84905805c94f04134590 /launcher/modplatform
parent04e4900415aa102f3ad2f40375e3b59bfc7ee9ba (diff)
parentea5020e188d7cb6d4c8dcf7f953161759ed17899 (diff)
downloadPrismLauncher-16477a8f6c1fc646208b41b76598ce8e7a60369e.tar.gz
PrismLauncher-16477a8f6c1fc646208b41b76598ce8e7a60369e.tar.bz2
PrismLauncher-16477a8f6c1fc646208b41b76598ce8e7a60369e.zip
Merge pull request #675 from flowln/generalize_mod_model
Diffstat (limited to 'launcher/modplatform')
-rw-r--r--launcher/modplatform/CheckUpdateTask.h14
-rw-r--r--launcher/modplatform/EnsureMetadataTask.cpp94
-rw-r--r--launcher/modplatform/EnsureMetadataTask.h16
-rw-r--r--launcher/modplatform/ModAPI.h118
-rw-r--r--launcher/modplatform/ModIndex.cpp24
-rw-r--r--launcher/modplatform/ModIndex.h40
-rw-r--r--launcher/modplatform/ResourceAPI.h177
-rw-r--r--launcher/modplatform/flame/FlameAPI.cpp39
-rw-r--r--launcher/modplatform/flame/FlameAPI.h110
-rw-r--r--launcher/modplatform/flame/FlameCheckUpdate.cpp14
-rw-r--r--launcher/modplatform/flame/FlameCheckUpdate.h2
-rw-r--r--launcher/modplatform/flame/FlameInstanceCreationTask.cpp4
-rw-r--r--launcher/modplatform/flame/FlameInstanceCreationTask.h2
-rw-r--r--launcher/modplatform/flame/FlameModIndex.cpp8
-rw-r--r--launcher/modplatform/flame/FlameModIndex.h2
-rw-r--r--launcher/modplatform/helpers/HashUtils.cpp16
-rw-r--r--launcher/modplatform/helpers/HashUtils.h10
-rw-r--r--launcher/modplatform/helpers/NetworkModAPI.cpp97
-rw-r--r--launcher/modplatform/helpers/NetworkModAPI.h17
-rw-r--r--launcher/modplatform/helpers/NetworkResourceAPI.cpp128
-rw-r--r--launcher/modplatform/helpers/NetworkResourceAPI.h22
-rw-r--r--launcher/modplatform/modrinth/ModrinthAPI.cpp73
-rw-r--r--launcher/modplatform/modrinth/ModrinthAPI.h134
-rw-r--r--launcher/modplatform/modrinth/ModrinthCheckUpdate.cpp27
-rw-r--r--launcher/modplatform/modrinth/ModrinthCheckUpdate.h4
-rw-r--r--launcher/modplatform/modrinth/ModrinthPackIndex.cpp11
-rw-r--r--launcher/modplatform/modrinth/ModrinthPackIndex.h2
-rw-r--r--launcher/modplatform/packwiz/Packwiz.cpp8
-rw-r--r--launcher/modplatform/packwiz/Packwiz.h2
29 files changed, 705 insertions, 510 deletions
diff --git a/launcher/modplatform/CheckUpdateTask.h b/launcher/modplatform/CheckUpdateTask.h
index 91922034..932a62d9 100644
--- a/launcher/modplatform/CheckUpdateTask.h
+++ b/launcher/modplatform/CheckUpdateTask.h
@@ -1,18 +1,18 @@
#pragma once
#include "minecraft/mod/Mod.h"
-#include "modplatform/ModAPI.h"
+#include "modplatform/ResourceAPI.h"
#include "modplatform/ModIndex.h"
#include "tasks/Task.h"
-class ModDownloadTask;
+class ResourceDownloadTask;
class ModFolderModel;
class CheckUpdateTask : public Task {
Q_OBJECT
public:
- CheckUpdateTask(QList<Mod*>& mods, std::list<Version>& mcVersions, ModAPI::ModLoaderTypes loaders, std::shared_ptr<ModFolderModel> mods_folder)
+ CheckUpdateTask(QList<Mod*>& mods, std::list<Version>& mcVersions, std::optional<ResourceAPI::ModLoaderTypes> loaders, std::shared_ptr<ModFolderModel> mods_folder)
: Task(nullptr), m_mods(mods), m_game_versions(mcVersions), m_loaders(loaders), m_mods_folder(mods_folder) {};
struct UpdatableMod {
@@ -21,11 +21,11 @@ class CheckUpdateTask : public Task {
QString old_version;
QString new_version;
QString changelog;
- ModPlatform::Provider provider;
- ModDownloadTask* download;
+ ModPlatform::ResourceProvider provider;
+ ResourceDownloadTask* download;
public:
- UpdatableMod(QString name, QString old_h, QString old_v, QString new_v, QString changelog, ModPlatform::Provider p, ModDownloadTask* t)
+ UpdatableMod(QString name, QString old_h, QString old_v, QString new_v, QString changelog, ModPlatform::ResourceProvider p, ResourceDownloadTask* t)
: name(name), old_hash(old_h), old_version(old_v), new_version(new_v), changelog(changelog), provider(p), download(t)
{}
};
@@ -44,7 +44,7 @@ class CheckUpdateTask : public Task {
protected:
QList<Mod*>& m_mods;
std::list<Version>& m_game_versions;
- ModAPI::ModLoaderTypes m_loaders;
+ std::optional<ResourceAPI::ModLoaderTypes> m_loaders;
std::shared_ptr<ModFolderModel> m_mods_folder;
std::vector<UpdatableMod> m_updatable;
diff --git a/launcher/modplatform/EnsureMetadataTask.cpp b/launcher/modplatform/EnsureMetadataTask.cpp
index 234330a7..d9523052 100644
--- a/launcher/modplatform/EnsureMetadataTask.cpp
+++ b/launcher/modplatform/EnsureMetadataTask.cpp
@@ -13,14 +13,12 @@
#include "modplatform/modrinth/ModrinthAPI.h"
#include "modplatform/modrinth/ModrinthPackIndex.h"
-#include "net/NetJob.h"
-
static ModPlatform::ProviderCapabilities ProviderCaps;
static ModrinthAPI modrinth_api;
static FlameAPI flame_api;
-EnsureMetadataTask::EnsureMetadataTask(Mod* mod, QDir dir, ModPlatform::Provider prov)
+EnsureMetadataTask::EnsureMetadataTask(Mod* mod, QDir dir, ModPlatform::ResourceProvider prov)
: Task(nullptr), m_index_dir(dir), m_provider(prov), m_hashing_task(nullptr), m_current_task(nullptr)
{
auto hash_task = createNewHash(mod);
@@ -31,7 +29,7 @@ EnsureMetadataTask::EnsureMetadataTask(Mod* mod, QDir dir, ModPlatform::Provider
hash_task->start();
}
-EnsureMetadataTask::EnsureMetadataTask(QList<Mod*>& mods, QDir dir, ModPlatform::Provider prov)
+EnsureMetadataTask::EnsureMetadataTask(QList<Mod*>& mods, QDir dir, ModPlatform::ResourceProvider prov)
: Task(nullptr), m_index_dir(dir), m_provider(prov), m_current_task(nullptr)
{
m_hashing_task = new ConcurrentTask(this, "MakeHashesTask", 10);
@@ -107,13 +105,13 @@ void EnsureMetadataTask::executeTask()
}
}
- NetJob::Ptr version_task;
+ Task::Ptr version_task;
switch (m_provider) {
- case (ModPlatform::Provider::MODRINTH):
+ case (ModPlatform::ResourceProvider::MODRINTH):
version_task = modrinthVersionsTask();
break;
- case (ModPlatform::Provider::FLAME):
+ case (ModPlatform::ResourceProvider::FLAME):
version_task = flameVersionsTask();
break;
}
@@ -127,13 +125,13 @@ void EnsureMetadataTask::executeTask()
};
connect(version_task.get(), &Task::finished, this, [this, invalidade_leftover] {
- NetJob::Ptr project_task;
+ Task::Ptr project_task;
switch (m_provider) {
- case (ModPlatform::Provider::MODRINTH):
+ case (ModPlatform::ResourceProvider::MODRINTH):
project_task = modrinthProjectsTask();
break;
- case (ModPlatform::Provider::FLAME):
+ case (ModPlatform::ResourceProvider::FLAME):
project_task = flameProjectsTask();
break;
}
@@ -149,7 +147,7 @@ void EnsureMetadataTask::executeTask()
m_current_task = nullptr;
});
- m_current_task = project_task.get();
+ m_current_task = project_task;
project_task->start();
});
@@ -164,7 +162,7 @@ void EnsureMetadataTask::executeTask()
setStatus(tr("Requesting metadata information from %1 for '%2'...")
.arg(ProviderCaps.readableName(m_provider), m_mods.begin().value()->name()));
- m_current_task = version_task.get();
+ m_current_task = version_task;
version_task->start();
}
@@ -210,9 +208,9 @@ void EnsureMetadataTask::emitFail(Mod* m, QString key, RemoveFromList remove)
// Modrinth
-NetJob::Ptr EnsureMetadataTask::modrinthVersionsTask()
+Task::Ptr EnsureMetadataTask::modrinthVersionsTask()
{
- auto hash_type = ProviderCaps.hashType(ModPlatform::Provider::MODRINTH).first();
+ auto hash_type = ProviderCaps.hashType(ModPlatform::ResourceProvider::MODRINTH).first();
auto* response = new QByteArray();
auto ver_task = modrinth_api.currentVersions(m_mods.keys(), hash_type, response);
@@ -221,7 +219,7 @@ NetJob::Ptr EnsureMetadataTask::modrinthVersionsTask()
if (!ver_task)
return {};
- connect(ver_task.get(), &NetJob::succeeded, this, [this, response] {
+ connect(ver_task.get(), &Task::succeeded, this, [this, response] {
QJsonParseError parse_error{};
QJsonDocument doc = QJsonDocument::fromJson(*response, &parse_error);
if (parse_error.error != QJsonParseError::NoError) {
@@ -260,14 +258,14 @@ NetJob::Ptr EnsureMetadataTask::modrinthVersionsTask()
return ver_task;
}
-NetJob::Ptr EnsureMetadataTask::modrinthProjectsTask()
+Task::Ptr EnsureMetadataTask::modrinthProjectsTask()
{
QHash<QString, QString> addonIds;
for (auto const& data : m_temp_versions)
addonIds.insert(data.addonId.toString(), data.hash);
auto response = new QByteArray();
- NetJob::Ptr proj_task;
+ Task::Ptr proj_task;
if (addonIds.isEmpty()) {
qWarning() << "No addonId found!";
@@ -281,7 +279,7 @@ NetJob::Ptr EnsureMetadataTask::modrinthProjectsTask()
if (!proj_task)
return {};
- connect(proj_task.get(), &NetJob::succeeded, this, [this, response, addonIds] {
+ connect(proj_task.get(), &Task::succeeded, this, [this, response, addonIds] {
QJsonParseError parse_error{};
auto doc = QJsonDocument::fromJson(*response, &parse_error);
if (parse_error.error != QJsonParseError::NoError) {
@@ -291,43 +289,53 @@ NetJob::Ptr EnsureMetadataTask::modrinthProjectsTask()
return;
}
+ QJsonArray entries;
+
try {
- QJsonArray entries;
if (addonIds.size() == 1)
entries = { doc.object() };
else
entries = Json::requireArray(doc);
+ } catch (Json::JsonException& e) {
+ qDebug() << e.cause();
+ qDebug() << doc;
+ }
- for (auto entry : entries) {
+ for (auto entry : entries) {
+ ModPlatform::IndexedPack pack;
+
+ try {
auto entry_obj = Json::requireObject(entry);
- ModPlatform::IndexedPack pack;
Modrinth::loadIndexedPack(pack, entry_obj);
+ } catch (Json::JsonException& e) {
+ qDebug() << e.cause();
+ qDebug() << doc;
- auto hash = addonIds.find(pack.addonId.toString()).value();
+ // Skip this entry, since it has problems
+ continue;
+ }
- auto mod_iter = m_mods.find(hash);
- if (mod_iter == m_mods.end()) {
- qWarning() << "Invalid project id from the API response.";
- continue;
- }
+ auto hash = addonIds.find(pack.addonId.toString()).value();
- auto* mod = mod_iter.value();
+ auto mod_iter = m_mods.find(hash);
+ if (mod_iter == m_mods.end()) {
+ qWarning() << "Invalid project id from the API response.";
+ continue;
+ }
- try {
- setStatus(tr("Parsing API response from Modrinth for '%1'...").arg(mod->name()));
+ auto* mod = mod_iter.value();
- modrinthCallback(pack, m_temp_versions.find(hash).value(), mod);
- } catch (Json::JsonException& e) {
- qDebug() << e.cause();
- qDebug() << entries;
+ try {
+ setStatus(tr("Parsing API response from Modrinth for '%1'...").arg(mod->name()));
- emitFail(mod);
- }
+ modrinthCallback(pack, m_temp_versions.find(hash).value(), mod);
+ } catch (Json::JsonException& e) {
+ qDebug() << e.cause();
+ qDebug() << entries;
+
+ emitFail(mod);
}
- } catch (Json::JsonException& e) {
- qDebug() << e.cause();
- qDebug() << doc;
}
});
@@ -335,7 +343,7 @@ NetJob::Ptr EnsureMetadataTask::modrinthProjectsTask()
}
// Flame
-NetJob::Ptr EnsureMetadataTask::flameVersionsTask()
+Task::Ptr EnsureMetadataTask::flameVersionsTask()
{
auto* response = new QByteArray();
@@ -400,7 +408,7 @@ NetJob::Ptr EnsureMetadataTask::flameVersionsTask()
return ver_task;
}
-NetJob::Ptr EnsureMetadataTask::flameProjectsTask()
+Task::Ptr EnsureMetadataTask::flameProjectsTask()
{
QHash<QString, QString> addonIds;
for (auto const& hash : m_mods.keys()) {
@@ -414,7 +422,7 @@ NetJob::Ptr EnsureMetadataTask::flameProjectsTask()
}
auto response = new QByteArray();
- NetJob::Ptr proj_task;
+ Task::Ptr proj_task;
if (addonIds.isEmpty()) {
qWarning() << "No addonId found!";
@@ -428,7 +436,7 @@ NetJob::Ptr EnsureMetadataTask::flameProjectsTask()
if (!proj_task)
return {};
- connect(proj_task.get(), &NetJob::succeeded, this, [this, response, addonIds] {
+ connect(proj_task.get(), &Task::succeeded, this, [this, response, addonIds] {
QJsonParseError parse_error{};
auto doc = QJsonDocument::fromJson(*response, &parse_error);
if (parse_error.error != QJsonParseError::NoError) {
diff --git a/launcher/modplatform/EnsureMetadataTask.h b/launcher/modplatform/EnsureMetadataTask.h
index a8b0851e..635f4a2b 100644
--- a/launcher/modplatform/EnsureMetadataTask.h
+++ b/launcher/modplatform/EnsureMetadataTask.h
@@ -14,8 +14,8 @@ class EnsureMetadataTask : public Task {
Q_OBJECT
public:
- EnsureMetadataTask(Mod*, QDir, ModPlatform::Provider = ModPlatform::Provider::MODRINTH);
- EnsureMetadataTask(QList<Mod*>&, QDir, ModPlatform::Provider = ModPlatform::Provider::MODRINTH);
+ EnsureMetadataTask(Mod*, QDir, ModPlatform::ResourceProvider = ModPlatform::ResourceProvider::MODRINTH);
+ EnsureMetadataTask(QList<Mod*>&, QDir, ModPlatform::ResourceProvider = ModPlatform::ResourceProvider::MODRINTH);
~EnsureMetadataTask() = default;
@@ -28,11 +28,11 @@ class EnsureMetadataTask : public Task {
private:
// FIXME: Move to their own namespace
- auto modrinthVersionsTask() -> NetJob::Ptr;
- auto modrinthProjectsTask() -> NetJob::Ptr;
+ auto modrinthVersionsTask() -> Task::Ptr;
+ auto modrinthProjectsTask() -> Task::Ptr;
- auto flameVersionsTask() -> NetJob::Ptr;
- auto flameProjectsTask() -> NetJob::Ptr;
+ auto flameVersionsTask() -> Task::Ptr;
+ auto flameProjectsTask() -> Task::Ptr;
// Helpers
enum class RemoveFromList {
@@ -57,9 +57,9 @@ class EnsureMetadataTask : public Task {
private:
QHash<QString, Mod*> m_mods;
QDir m_index_dir;
- ModPlatform::Provider m_provider;
+ ModPlatform::ResourceProvider m_provider;
QHash<QString, ModPlatform::IndexedVersion> m_temp_versions;
ConcurrentTask* m_hashing_task;
- NetJob* m_current_task;
+ Task::Ptr m_current_task;
};
diff --git a/launcher/modplatform/ModAPI.h b/launcher/modplatform/ModAPI.h
deleted file mode 100644
index 703de143..00000000
--- a/launcher/modplatform/ModAPI.h
+++ /dev/null
@@ -1,118 +0,0 @@
-// SPDX-License-Identifier: GPL-3.0-only
-/*
- * PolyMC - Minecraft Launcher
- * Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net>
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, version 3.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <https://www.gnu.org/licenses/>.
- *
- * This file incorporates work covered by the following copyright and
- * permission notice:
- *
- * Copyright 2013-2021 MultiMC Contributors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#pragma once
-
-#include <QString>
-#include <QList>
-#include <list>
-
-#include "../Version.h"
-#include "net/NetJob.h"
-
-namespace ModPlatform {
-class ListModel;
-struct IndexedPack;
-}
-
-class ModAPI {
- protected:
- using CallerType = ModPlatform::ListModel;
-
- public:
- virtual ~ModAPI() = default;
-
- enum ModLoaderType {
- Unspecified = 0,
- Forge = 1 << 0,
- Cauldron = 1 << 1,
- LiteLoader = 1 << 2,
- Fabric = 1 << 3,
- Quilt = 1 << 4
- };
- Q_DECLARE_FLAGS(ModLoaderTypes, ModLoaderType)
-
- struct SearchArgs {
- int offset;
- QString search;
- QString sorting;
- ModLoaderTypes loaders;
- std::list<Version> versions;
- };
-
- virtual void searchMods(CallerType* caller, SearchArgs&& args) const = 0;
- virtual void getModInfo(ModPlatform::IndexedPack& pack, std::function<void(QJsonDocument&, ModPlatform::IndexedPack&)> callback) = 0;
-
- virtual auto getProject(QString addonId, QByteArray* response) const -> NetJob* = 0;
- virtual auto getProjects(QStringList addonIds, QByteArray* response) const -> NetJob* = 0;
-
-
- struct VersionSearchArgs {
- QString addonId;
- std::list<Version> mcVersions;
- ModLoaderTypes loaders;
- };
-
- virtual void getVersions(VersionSearchArgs&& args, std::function<void(QJsonDocument&, QString)> callback) const = 0;
-
- static auto getModLoaderString(ModLoaderType type) -> const QString {
- switch (type) {
- case Unspecified:
- break;
- case Forge:
- return "forge";
- case Cauldron:
- return "cauldron";
- case LiteLoader:
- return "liteloader";
- case Fabric:
- return "fabric";
- case Quilt:
- return "quilt";
- }
- return "";
- }
-
- protected:
- inline auto getGameVersionsString(std::list<Version> mcVersions) const -> QString
- {
- QString s;
- for(auto& ver : mcVersions){
- s += QString("\"%1\",").arg(ver.toString());
- }
- s.remove(s.length() - 1, 1); //remove last comma
- return s;
- }
-};
diff --git a/launcher/modplatform/ModIndex.cpp b/launcher/modplatform/ModIndex.cpp
index 34fd9f30..6a507caf 100644
--- a/launcher/modplatform/ModIndex.cpp
+++ b/launcher/modplatform/ModIndex.cpp
@@ -24,47 +24,47 @@
namespace ModPlatform {
-auto ProviderCapabilities::name(Provider p) -> const char*
+auto ProviderCapabilities::name(ResourceProvider p) -> const char*
{
switch (p) {
- case Provider::MODRINTH:
+ case ResourceProvider::MODRINTH:
return "modrinth";
- case Provider::FLAME:
+ case ResourceProvider::FLAME:
return "curseforge";
}
return {};
}
-auto ProviderCapabilities::readableName(Provider p) -> QString
+auto ProviderCapabilities::readableName(ResourceProvider p) -> QString
{
switch (p) {
- case Provider::MODRINTH:
+ case ResourceProvider::MODRINTH:
return "Modrinth";
- case Provider::FLAME:
+ case ResourceProvider::FLAME:
return "CurseForge";
}
return {};
}
-auto ProviderCapabilities::hashType(Provider p) -> QStringList
+auto ProviderCapabilities::hashType(ResourceProvider p) -> QStringList
{
switch (p) {
- case Provider::MODRINTH:
+ case ResourceProvider::MODRINTH:
return { "sha512", "sha1" };
- case Provider::FLAME:
+ case ResourceProvider::FLAME:
// Try newer formats first, fall back to old format
return { "sha1", "md5", "murmur2" };
}
return {};
}
-auto ProviderCapabilities::hash(Provider p, QIODevice* device, QString type) -> QString
+auto ProviderCapabilities::hash(ResourceProvider p, QIODevice* device, QString type) -> QString
{
QCryptographicHash::Algorithm algo = QCryptographicHash::Sha1;
switch (p) {
- case Provider::MODRINTH: {
+ case ResourceProvider::MODRINTH: {
algo = (type == "sha1") ? QCryptographicHash::Sha1 : QCryptographicHash::Sha512;
break;
}
- case Provider::FLAME:
+ case ResourceProvider::FLAME:
algo = (type == "sha1") ? QCryptographicHash::Sha1 : QCryptographicHash::Md5;
break;
}
diff --git a/launcher/modplatform/ModIndex.h b/launcher/modplatform/ModIndex.h
index 518fed7c..b1f8050d 100644
--- a/launcher/modplatform/ModIndex.h
+++ b/launcher/modplatform/ModIndex.h
@@ -28,17 +28,16 @@ class QIODevice;
namespace ModPlatform {
-enum class Provider {
- MODRINTH,
- FLAME
-};
+enum class ResourceProvider { MODRINTH, FLAME };
+
+enum class ResourceType { MOD, RESOURCE_PACK };
class ProviderCapabilities {
public:
- auto name(Provider) -> const char*;
- auto readableName(Provider) -> QString;
- auto hashType(Provider) -> QStringList;
- auto hash(Provider, QIODevice*, QString type = "") -> QString;
+ auto name(ResourceProvider) -> const char*;
+ auto readableName(ResourceProvider) -> QString;
+ auto hashType(ResourceProvider) -> QStringList;
+ auto hash(ResourceProvider, QIODevice*, QString type = "") -> QString;
};
struct ModpackAuthor {
@@ -66,6 +65,10 @@ struct IndexedVersion {
QString hash;
bool is_preferred = true;
QString changelog;
+
+ // For internal use, not provided by APIs
+ bool is_currently_selected = false;
+ QString custom_target_folder;
};
struct ExtraPackData {
@@ -81,7 +84,7 @@ struct ExtraPackData {
struct IndexedPack {
QVariant addonId;
- Provider provider;
+ ResourceProvider provider;
QString name;
QString slug;
QString description;
@@ -96,9 +99,26 @@ struct IndexedPack {
// Don't load by default, since some modplatform don't have that info
bool extraDataLoaded = true;
ExtraPackData extraData;
+
+ // For internal use, not provided by APIs
+ [[nodiscard]] bool isVersionSelected(size_t index) const
+ {
+ if (!versionsLoaded)
+ return false;
+
+ return versions.at(index).is_currently_selected;
+ }
+ [[nodiscard]] bool isAnyVersionSelected() const
+ {
+ if (!versionsLoaded)
+ return false;
+
+ return std::any_of(versions.constBegin(), versions.constEnd(),
+ [](auto const& v) { return v.is_currently_selected; });
+ }
};
} // namespace ModPlatform
Q_DECLARE_METATYPE(ModPlatform::IndexedPack)
-Q_DECLARE_METATYPE(ModPlatform::Provider)
+Q_DECLARE_METATYPE(ModPlatform::ResourceProvider)
diff --git a/launcher/modplatform/ResourceAPI.h b/launcher/modplatform/ResourceAPI.h
new file mode 100644
index 00000000..34f33779
--- /dev/null
+++ b/launcher/modplatform/ResourceAPI.h
@@ -0,0 +1,177 @@
+// SPDX-FileCopyrightText: 2023 flowln <flowlnlnln@gmail.com>
+//
+// SPDX-License-Identifier: GPL-3.0-only AND Apache-2.0
+/*
+ * PolyMC - Minecraft Launcher
+ * Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ *
+ * This file incorporates work covered by the following copyright and
+ * permission notice:
+ *
+ * Copyright 2013-2021 MultiMC Contributors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <QDebug>
+#include <QList>
+#include <QString>
+
+#include <list>
+#include <optional>
+
+#include "../Version.h"
+
+#include "modplatform/ModIndex.h"
+#include "tasks/Task.h"
+
+/* Simple class with a common interface for interacting with APIs */
+class ResourceAPI {
+ public:
+ virtual ~ResourceAPI() = default;
+
+ enum ModLoaderType { Forge = 1 << 0, Cauldron = 1 << 1, LiteLoader = 1 << 2, Fabric = 1 << 3, Quilt = 1 << 4 };
+ Q_DECLARE_FLAGS(ModLoaderTypes, ModLoaderType)
+
+ struct SortingMethod {
+ // The index of the sorting method. Used to allow for arbitrary ordering in the list of methods.
+ // Used by Flame in the API request.
+ unsigned int index;
+ // The real name of the sorting, as used in the respective API specification.
+ // Used by Modrinth in the API request.
+ QString name;
+ // The human-readable name of the sorting, used for display in the UI.
+ QString readable_name;
+ };
+
+ struct SearchArgs {
+ ModPlatform::ResourceType type{};
+ int offset = 0;
+
+ std::optional<QString> search;
+ std::optional<SortingMethod> sorting;
+ std::optional<ModLoaderTypes> loaders;
+ std::optional<std::list<Version> > versions;
+ };
+ struct SearchCallbacks {
+ std::function<void(QJsonDocument&)> on_succeed;
+ std::function<void(QString const& reason, int network_error_code)> on_fail;
+ std::function<void()> on_abort;
+ };
+
+ struct VersionSearchArgs {
+ ModPlatform::IndexedPack pack;
+
+ std::optional<std::list<Version> > mcVersions;
+ std::optional<ModLoaderTypes> loaders;
+
+ VersionSearchArgs(VersionSearchArgs const&) = default;
+ void operator=(VersionSearchArgs other)
+ {
+ pack = other.pack;
+ mcVersions = other.mcVersions;
+ loaders = other.loaders;
+ }
+ };
+ struct VersionSearchCallbacks {
+ std::function<void(QJsonDocument&, ModPlatform::IndexedPack)> on_succeed;
+ };
+
+ struct ProjectInfoArgs {
+ ModPlatform::IndexedPack pack;
+
+ ProjectInfoArgs(ProjectInfoArgs const&) = default;
+ void operator=(ProjectInfoArgs other) { pack = other.pack; }
+ };
+ struct ProjectInfoCallbacks {
+ std::function<void(QJsonDocument&, ModPlatform::IndexedPack)> on_succeed;
+ };
+
+ public:
+ /** Gets a list of available sorting methods for this API. */
+ [[nodiscard]] virtual auto getSortingMethods() const -> QList<SortingMethod> = 0;
+
+ public slots:
+ [[nodiscard]] virtual Task::Ptr searchProjects(SearchArgs&&, SearchCallbacks&&) const
+ {
+ qWarning() << "TODO";
+ return nullptr;
+ }
+ [[nodiscard]] virtual Task::Ptr getProject(QString addonId, QByteArray* response) const
+ {
+ qWarning() << "TODO";
+ return nullptr;
+ }
+ [[nodiscard]] virtual Task::Ptr getProjects(QStringList addonIds, QByteArray* response) const
+ {
+ qWarning() << "TODO";
+ return nullptr;
+ }
+
+ [[nodiscard]] virtual Task::Ptr getProjectInfo(ProjectInfoArgs&&, ProjectInfoCallbacks&&) const
+ {
+ qWarning() << "TODO";
+ return nullptr;
+ }
+ [[nodiscard]] virtual Task::Ptr getProjectVersions(VersionSearchArgs&&, VersionSearchCallbacks&&) const
+ {
+ qWarning() << "TODO";
+ return nullptr;
+ }
+
+ static auto getModLoaderString(ModLoaderType type) -> const Q