Merge pull request #2887 from Trial97/filters_modpack

Add filters for modpack search
This commit is contained in:
Alexandru Ionut Tripon
2024-10-12 00:07:14 +03:00
committed by GitHub
25 changed files with 394 additions and 150 deletions

View File

@ -35,7 +35,7 @@ Q_DECLARE_FLAGS(ModLoaderTypes, ModLoaderType)
enum class ResourceProvider { MODRINTH, FLAME };
enum class ResourceType { MOD, RESOURCE_PACK, SHADER_PACK };
enum class ResourceType { MOD, RESOURCE_PACK, SHADER_PACK, MODPACK };
enum class DependencyType { REQUIRED, OPTIONAL, INCOMPATIBLE, EMBEDDED, TOOL, INCLUDE, UNKNOWN };

View File

@ -221,14 +221,20 @@ QList<ResourceAPI::SortingMethod> FlameAPI::getSortingMethods() const
{ 8, "GameVersion", QObject::tr("Sort by Game Version") } };
}
Task::Ptr FlameAPI::getModCategories(std::shared_ptr<QByteArray> response)
Task::Ptr FlameAPI::getCategories(std::shared_ptr<QByteArray> response, ModPlatform::ResourceType type)
{
auto netJob = makeShared<NetJob>(QString("Flame::GetCategories"), APPLICATION->network());
netJob->addNetAction(Net::ApiDownload::makeByteArray(QUrl("https://api.curseforge.com/v1/categories?gameId=432&classId=6"), response));
netJob->addNetAction(Net::ApiDownload::makeByteArray(
QUrl(QString("https://api.curseforge.com/v1/categories?gameId=432&classId=%1").arg(getClassId(type))), response));
QObject::connect(netJob.get(), &Task::failed, [](QString msg) { qDebug() << "Flame failed to get categories:" << msg; });
return netJob;
}
Task::Ptr FlameAPI::getModCategories(std::shared_ptr<QByteArray> response)
{
return getCategories(response, ModPlatform::ResourceType::MOD);
}
QList<ModPlatform::Category> FlameAPI::loadModCategories(std::shared_ptr<QByteArray> response)
{
QList<ModPlatform::Category> categories;

View File

@ -25,6 +25,7 @@ class FlameAPI : public NetworkResourceAPI {
Task::Ptr getFiles(const QStringList& fileIds, std::shared_ptr<QByteArray> response) const;
Task::Ptr getFile(const QString& addonId, const QString& fileId, std::shared_ptr<QByteArray> response) const;
static Task::Ptr getCategories(std::shared_ptr<QByteArray> response, ModPlatform::ResourceType type);
static Task::Ptr getModCategories(std::shared_ptr<QByteArray> response);
static QList<ModPlatform::Category> loadModCategories(std::shared_ptr<QByteArray> response);
@ -46,6 +47,8 @@ class FlameAPI : public NetworkResourceAPI {
return 12;
case ModPlatform::ResourceType::SHADER_PACK:
return 6552;
case ModPlatform::ResourceType::MODPACK:
return 4471;
}
}
@ -82,12 +85,9 @@ class FlameAPI : public NetworkResourceAPI {
static const QString getModLoaderFilters(ModPlatform::ModLoaderTypes types) { return "[" + getModLoaderStrings(types).join(',') + "]"; }
private:
public:
[[nodiscard]] std::optional<QString> getSearchURL(SearchArgs const& args) const override
{
auto gameVersionStr =
args.versions.has_value() ? QString("gameVersion=%1").arg(args.versions.value().front().toString()) : QString();
QStringList get_arguments;
get_arguments.append(QString("classId=%1").arg(getClassId(args.type)));
get_arguments.append(QString("index=%1").arg(args.offset));
@ -97,20 +97,22 @@ class FlameAPI : public NetworkResourceAPI {
if (args.sorting.has_value())
get_arguments.append(QString("sortField=%1").arg(args.sorting.value().index));
get_arguments.append("sortOrder=desc");
if (args.loaders.has_value())
if (args.loaders.has_value() && args.loaders.value() != 0)
get_arguments.append(QString("modLoaderTypes=%1").arg(getModLoaderFilters(args.loaders.value())));
if (args.categoryIds.has_value() && !args.categoryIds->empty())
get_arguments.append(QString("categoryIds=[%1]").arg(args.categoryIds->join(",")));
get_arguments.append(gameVersionStr);
if (args.versions.has_value() && !args.versions.value().empty())
get_arguments.append(QString("gameVersion=%1").arg(args.versions.value().front().toString()));
return "https://api.curseforge.com/v1/mods/search?gameId=432&" + get_arguments.join('&');
};
}
private:
[[nodiscard]] std::optional<QString> getInfoURL(QString const& id) const override
{
return QString("https://api.curseforge.com/v1/mods/%1").arg(id);
};
}
[[nodiscard]] std::optional<QString> getVersionsURL(VersionSearchArgs const& args) const override
{
@ -125,7 +127,7 @@ class FlameAPI : public NetworkResourceAPI {
url += QString("&modLoaderType=%1").arg(mappedModLoader);
}
return url;
};
}
[[nodiscard]] std::optional<QString> getDependencyURL(DependencySearchArgs const& args) const override
{
@ -137,5 +139,5 @@ class FlameAPI : public NetworkResourceAPI {
url += QString("&modLoaderType=%1").arg(mappedModLoader);
}
return url;
};
}
};

View File

@ -3,6 +3,7 @@
#include <QUrl>
#include "Json.h"
#include "modplatform/ModIndex.h"
void Flame::loadIndexedPack(Flame::IndexedPack& pack, QJsonObject& obj)
{
@ -88,8 +89,27 @@ void Flame::loadIndexedPackVersions(Flame::IndexedPack& pack, QJsonArray& arr)
continue;
}
for (auto mcVer : versionArray) {
auto str = mcVer.toString();
if (str.contains('.'))
file.mcVersion.append(str);
if (auto loader = str.toLower(); loader == "neoforge")
file.loaders |= ModPlatform::NeoForge;
else if (loader == "forge")
file.loaders |= ModPlatform::Forge;
else if (loader == "cauldron")
file.loaders |= ModPlatform::Cauldron;
else if (loader == "liteloader")
file.loaders |= ModPlatform::LiteLoader;
else if (loader == "fabric")
file.loaders |= ModPlatform::Fabric;
else if (loader == "quilt")
file.loaders |= ModPlatform::Quilt;
}
// pick the latest version supported
file.mcVersion = versionArray[0].toString();
file.version = Json::requireString(version, "displayName");
ModPlatform::IndexedVersionType::VersionType ver_type;

View File

@ -18,6 +18,7 @@ struct IndexedVersion {
int fileId;
QString version;
ModPlatform::IndexedVersionType version_type;
ModPlatform::ModLoaderTypes loaders = {};
QString mcVersion;
QString downloadUrl;
};

View File

@ -129,7 +129,7 @@ Task::Ptr ModrinthAPI::getModCategories(std::shared_ptr<QByteArray> response)
return netJob;
}
QList<ModPlatform::Category> ModrinthAPI::loadModCategories(std::shared_ptr<QByteArray> response)
QList<ModPlatform::Category> ModrinthAPI::loadCategories(std::shared_ptr<QByteArray> response, QString projectType)
{
QList<ModPlatform::Category> categories;
QJsonParseError parse_error{};
@ -147,7 +147,7 @@ QList<ModPlatform::Category> ModrinthAPI::loadModCategories(std::shared_ptr<QByt
for (auto val : arr) {
auto cat = Json::requireObject(val);
auto name = Json::requireString(cat, "name");
if (Json::ensureString(cat, "project_type", "") == "mod")
if (Json::ensureString(cat, "project_type", "") == projectType)
categories.push_back({ name, name });
}
@ -157,4 +157,9 @@ QList<ModPlatform::Category> ModrinthAPI::loadModCategories(std::shared_ptr<QByt
qDebug() << doc;
}
return categories;
};
}
QList<ModPlatform::Category> ModrinthAPI::loadModCategories(std::shared_ptr<QByteArray> response)
{
return loadCategories(response, "mod");
};

View File

@ -31,6 +31,7 @@ class ModrinthAPI : public NetworkResourceAPI {
Task::Ptr getProjects(QStringList addonIds, std::shared_ptr<QByteArray> response) const override;
static Task::Ptr getModCategories(std::shared_ptr<QByteArray> response);
static QList<ModPlatform::Category> loadCategories(std::shared_ptr<QByteArray> response, QString projectType);
static QList<ModPlatform::Category> loadModCategories(std::shared_ptr<QByteArray> response);
public:
@ -90,6 +91,8 @@ class ModrinthAPI : public NetworkResourceAPI {
return "resourcepack";
case ModPlatform::ResourceType::SHADER_PACK:
return "shader";
case ModPlatform::ResourceType::MODPACK:
return "modpack";
default:
qWarning() << "Invalid resource type for Modrinth API!";
break;
@ -102,9 +105,9 @@ class ModrinthAPI : public NetworkResourceAPI {
{
QStringList facets_list;
if (args.loaders.has_value())
if (args.loaders.has_value() && args.loaders.value() != 0)
facets_list.append(QString("[%1]").arg(getModLoaderFilters(args.loaders.value())));
if (args.versions.has_value())
if (args.versions.has_value() && !args.versions.value().empty())
facets_list.append(QString("[%1]").arg(getGameVersionsArray(args.versions.value())));
if (args.side.has_value()) {
auto side = getSideFilters(args.side.value());
@ -122,7 +125,7 @@ class ModrinthAPI : public NetworkResourceAPI {
public:
[[nodiscard]] inline auto getSearchURL(SearchArgs const& args) const -> std::optional<QString> override
{
if (args.loaders.has_value()) {
if (args.loaders.has_value() && args.loaders.value() != 0) {
if (!validateModLoaders(args.loaders.value())) {
qWarning() << "Modrinth - or our interface - does not support any the provided mod loaders!";
return {};
@ -163,7 +166,7 @@ class ModrinthAPI : public NetworkResourceAPI {
.arg(BuildConfig.MODRINTH_PROD_URL, args.pack.addonId.toString(), get_arguments.isEmpty() ? "" : "?", get_arguments.join('&'));
};
auto getGameVersionsArray(std::list<Version> mcVersions) const -> QString
QString getGameVersionsArray(std::list<Version> mcVersions) const
{
QString s;
for (auto& ver : mcVersions) {

View File

@ -135,6 +135,21 @@ auto loadIndexedVersion(QJsonObject& obj) -> ModpackVersion
if (!gameVersions.isEmpty()) {
file.gameVersion = Json::ensureString(gameVersions[0]);
}
auto loaders = Json::requireArray(obj, "loaders");
for (auto loader : loaders) {
if (loader == "neoforge")
file.loaders |= ModPlatform::NeoForge;
else if (loader == "forge")
file.loaders |= ModPlatform::Forge;
else if (loader == "cauldron")
file.loaders |= ModPlatform::Cauldron;
else if (loader == "liteloader")
file.loaders |= ModPlatform::LiteLoader;
else if (loader == "fabric")
file.loaders |= ModPlatform::Fabric;
else if (loader == "quilt")
file.loaders |= ModPlatform::Quilt;
}
file.version_type = ModPlatform::IndexedVersionType(Json::requireString(obj, "version_type"));
file.changelog = Json::ensureString(obj, "changelog");

View File

@ -87,6 +87,7 @@ struct ModpackVersion {
QString gameVersion;
ModPlatform::IndexedVersionType version_type;
QString changelog;
ModPlatform::ModLoaderTypes loaders = {};
QString id;
QString project_id;