Merge pull request #1560 from Trial97/curse_multiple_loaders2

Add suport for flame multiple loaders
This commit is contained in:
TheKodeToad 2023-08-27 18:21:14 +01:00 committed by GitHub
commit 9110fbf282
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
39 changed files with 240 additions and 209 deletions

View File

@ -2,14 +2,14 @@
#include "Component.h" #include "Component.h"
#include "ComponentUpdateTask_p.h" #include "ComponentUpdateTask_p.h"
#include "OneSixVersionFormat.h"
#include "PackProfile.h" #include "PackProfile.h"
#include "PackProfile_p.h" #include "PackProfile_p.h"
#include "Version.h" #include "Version.h"
#include "cassert" #include "cassert"
#include "meta/Index.h" #include "meta/Index.h"
#include "meta/Version.h" #include "meta/Version.h"
#include "meta/VersionList.h" #include "minecraft/OneSixVersionFormat.h"
#include "minecraft/ProfileUtils.h"
#include "net/Mode.h" #include "net/Mode.h"
#include "Application.h" #include "Application.h"

View File

@ -58,15 +58,14 @@
#include "ComponentUpdateTask.h" #include "ComponentUpdateTask.h"
#include "PackProfile.h" #include "PackProfile.h"
#include "PackProfile_p.h" #include "PackProfile_p.h"
#include "minecraft/mod/Mod.h"
#include "modplatform/ModIndex.h"
#include "Application.h" static const QMap<QString, ModPlatform::ModLoaderType> modloaderMapping{ { "net.neoforged", ModPlatform::NeoForge },
#include "modplatform/ResourceAPI.h" { "net.minecraftforge", ModPlatform::Forge },
{ "net.fabricmc.fabric-loader", ModPlatform::Fabric },
static const QMap<QString, ResourceAPI::ModLoaderType> modloaderMapping{ { "net.neoforged", ResourceAPI::NeoForge }, { "org.quiltmc.quilt-loader", ModPlatform::Quilt },
{ "net.minecraftforge", ResourceAPI::Forge }, { "com.mumfrey.liteloader", ModPlatform::LiteLoader } };
{ "net.fabricmc.fabric-loader", ResourceAPI::Fabric },
{ "org.quiltmc.quilt-loader", ResourceAPI::Quilt },
{ "com.mumfrey.liteloader", ResourceAPI::LiteLoader } };
PackProfile::PackProfile(MinecraftInstance* instance) : QAbstractListModel() PackProfile::PackProfile(MinecraftInstance* instance) : QAbstractListModel()
{ {
@ -990,12 +989,12 @@ void PackProfile::disableInteraction(bool disable)
} }
} }
std::optional<ResourceAPI::ModLoaderTypes> PackProfile::getModLoaders() std::optional<ModPlatform::ModLoaderTypes> PackProfile::getModLoaders()
{ {
ResourceAPI::ModLoaderTypes result; ModPlatform::ModLoaderTypes result;
bool has_any_loader = false; bool has_any_loader = false;
QMapIterator<QString, ResourceAPI::ModLoaderType> i(modloaderMapping); QMapIterator<QString, ModPlatform::ModLoaderType> i(modloaderMapping);
while (i.hasNext()) { while (i.hasNext()) {
i.next(); i.next();
@ -1009,3 +1008,18 @@ std::optional<ResourceAPI::ModLoaderTypes> PackProfile::getModLoaders()
return {}; return {};
return result; return result;
} }
std::optional<ModPlatform::ModLoaderTypes> PackProfile::getSupportedModLoaders()
{
auto loadersOpt = getModLoaders();
if (!loadersOpt.has_value())
return loadersOpt;
auto loaders = loadersOpt.value();
// TODO: remove this or add version condition once Quilt drops official Fabric support
if (loaders & ModPlatform::Quilt)
loaders |= ModPlatform::Fabric;
// TODO: remove this or add version condition once NeoForge drops official Forge support
if (loaders & ModPlatform::NeoForge)
loaders |= ModPlatform::Forge;
return loaders;
}

View File

@ -44,14 +44,11 @@
#include <QList> #include <QList>
#include <QString> #include <QString>
#include <memory> #include <memory>
#include <optional>
#include "BaseVersion.h"
#include "Component.h" #include "Component.h"
#include "LaunchProfile.h" #include "LaunchProfile.h"
#include "Library.h" #include "modplatform/ModIndex.h"
#include "MojangDownloadInfo.h"
#include "ProfileUtils.h"
#include "modplatform/ResourceAPI.h"
#include "net/Mode.h" #include "net/Mode.h"
class MinecraftInstance; class MinecraftInstance;
@ -146,7 +143,9 @@ class PackProfile : public QAbstractListModel {
// todo(merged): is this the best approach // todo(merged): is this the best approach
void appendComponent(ComponentPtr component); void appendComponent(ComponentPtr component);
std::optional<ResourceAPI::ModLoaderTypes> getModLoaders(); std::optional<ModPlatform::ModLoaderTypes> getModLoaders();
// this returns aditional loaders(Quilt supports fabric and NeoForge supports Forge)
std::optional<ModPlatform::ModLoaderTypes> getSupportedModLoaders();
private: private:
void scheduleSave(); void scheduleSave();

View File

@ -39,9 +39,9 @@ static Version mcVersion(BaseInstance* inst)
return static_cast<MinecraftInstance*>(inst)->getPackProfile()->getComponent("net.minecraft")->getVersion(); return static_cast<MinecraftInstance*>(inst)->getPackProfile()->getComponent("net.minecraft")->getVersion();
} }
static ResourceAPI::ModLoaderTypes mcLoaders(BaseInstance* inst) static ModPlatform::ModLoaderTypes mcLoaders(BaseInstance* inst)
{ {
return static_cast<MinecraftInstance*>(inst)->getPackProfile()->getModLoaders().value(); return static_cast<MinecraftInstance*>(inst)->getPackProfile()->getSupportedModLoaders().value();
} }
GetModDependenciesTask::GetModDependenciesTask(QObject* parent, GetModDependenciesTask::GetModDependenciesTask(QObject* parent,
@ -75,7 +75,7 @@ void GetModDependenciesTask::prepare()
ModPlatform::Dependency GetModDependenciesTask::getOverride(const ModPlatform::Dependency& dep, ModPlatform::Dependency GetModDependenciesTask::getOverride(const ModPlatform::Dependency& dep,
const ModPlatform::ResourceProvider providerName) const ModPlatform::ResourceProvider providerName)
{ {
if (auto isQuilt = m_loaderType & ResourceAPI::Quilt; isQuilt || m_loaderType & ResourceAPI::Fabric) { if (auto isQuilt = m_loaderType & ModPlatform::Quilt; isQuilt || m_loaderType & ModPlatform::Fabric) {
auto overide = ModPlatform::getOverrideDeps(); auto overide = ModPlatform::getOverrideDeps();
auto over = std::find_if(overide.cbegin(), overide.cend(), [dep, providerName, isQuilt](auto o) { auto over = std::find_if(overide.cbegin(), overide.cend(), [dep, providerName, isQuilt](auto o) {
return o.provider == providerName && dep.addonId == (isQuilt ? o.fabric : o.quilt); return o.provider == providerName && dep.addonId == (isQuilt ? o.fabric : o.quilt);
@ -191,7 +191,7 @@ Task::Ptr GetModDependenciesTask::prepareDependencyTask(const ModPlatform::Depen
} }
pDep->version = provider.mod->loadDependencyVersions(dep, arr); pDep->version = provider.mod->loadDependencyVersions(dep, arr);
if (!pDep->version.addonId.isValid()) { if (!pDep->version.addonId.isValid()) {
if (m_loaderType & ResourceAPI::Quilt) { // falback for quilt if (m_loaderType & ModPlatform::Quilt) { // falback for quilt
auto overide = ModPlatform::getOverrideDeps(); auto overide = ModPlatform::getOverrideDeps();
auto over = std::find_if(overide.cbegin(), overide.cend(), auto over = std::find_if(overide.cbegin(), overide.cend(),
[dep, provider](auto o) { return o.provider == provider.name && dep.addonId == o.quilt; }); [dep, provider](auto o) { return o.provider == provider.name && dep.addonId == o.quilt; });
@ -201,6 +201,7 @@ Task::Ptr GetModDependenciesTask::prepareDependencyTask(const ModPlatform::Depen
return; return;
} }
} }
removePack(dep.addonId);
qWarning() << "Error while reading mod version empty "; qWarning() << "Error while reading mod version empty ";
qDebug() << doc; qDebug() << doc;
return; return;

View File

@ -80,5 +80,5 @@ class GetModDependenciesTask : public SequentialTask {
Provider m_modrinth_provider; Provider m_modrinth_provider;
Version m_version; Version m_version;
ResourceAPI::ModLoaderTypes m_loaderType; ModPlatform::ModLoaderTypes m_loaderType;
}; };

View File

@ -14,7 +14,7 @@ class CheckUpdateTask : public Task {
public: public:
CheckUpdateTask(QList<Mod*>& mods, CheckUpdateTask(QList<Mod*>& mods,
std::list<Version>& mcVersions, std::list<Version>& mcVersions,
std::optional<ResourceAPI::ModLoaderTypes> loaders, std::optional<ModPlatform::ModLoaderTypes> loaders,
std::shared_ptr<ModFolderModel> mods_folder) std::shared_ptr<ModFolderModel> mods_folder)
: Task(nullptr), m_mods(mods), m_game_versions(mcVersions), m_loaders(loaders), m_mods_folder(mods_folder){}; : Task(nullptr), m_mods(mods), m_game_versions(mcVersions), m_loaders(loaders), m_mods_folder(mods_folder){};
@ -53,7 +53,7 @@ class CheckUpdateTask : public Task {
protected: protected:
QList<Mod*>& m_mods; QList<Mod*>& m_mods;
std::list<Version>& m_game_versions; std::list<Version>& m_game_versions;
std::optional<ResourceAPI::ModLoaderTypes> m_loaders; std::optional<ModPlatform::ModLoaderTypes> m_loaders;
std::shared_ptr<ModFolderModel> m_mods_folder; std::shared_ptr<ModFolderModel> m_mods_folder;
std::vector<UpdatableMod> m_updatable; std::vector<UpdatableMod> m_updatable;

View File

@ -83,4 +83,25 @@ QString getMetaURL(ResourceProvider provider, QVariant projectID)
projectID.toString(); projectID.toString();
} }
auto getModLoaderString(ModLoaderType type) -> const QString
{
switch (type) {
case NeoForge:
return "neoforge";
case Forge:
return "forge";
case Cauldron:
return "cauldron";
case LiteLoader:
return "liteloader";
case Fabric:
return "fabric";
case Quilt:
return "quilt";
default:
break;
}
return "";
}
} // namespace ModPlatform } // namespace ModPlatform

View File

@ -30,6 +30,9 @@ class QIODevice;
namespace ModPlatform { namespace ModPlatform {
enum ModLoaderType { NeoForge = 1 << 0, Forge = 1 << 1, Cauldron = 1 << 2, LiteLoader = 1 << 3, Fabric = 1 << 4, Quilt = 1 << 5 };
Q_DECLARE_FLAGS(ModLoaderTypes, ModLoaderType)
enum class ResourceProvider { MODRINTH, FLAME }; enum class ResourceProvider { MODRINTH, FLAME };
enum class ResourceType { MOD, RESOURCE_PACK, SHADER_PACK }; enum class ResourceType { MOD, RESOURCE_PACK, SHADER_PACK };
@ -70,7 +73,7 @@ struct IndexedVersion {
QString downloadUrl; QString downloadUrl;
QString date; QString date;
QString fileName; QString fileName;
QStringList loaders = {}; ModLoaderTypes loaders = {};
QString hash_type; QString hash_type;
QString hash; QString hash;
bool is_preferred = true; bool is_preferred = true;
@ -128,7 +131,6 @@ struct IndexedPack {
return std::any_of(versions.constBegin(), versions.constEnd(), [](auto const& v) { return v.is_currently_selected; }); return std::any_of(versions.constBegin(), versions.constEnd(), [](auto const& v) { return v.is_currently_selected; });
} }
}; };
QString getMetaURL(ResourceProvider provider, QVariant projectID);
struct OverrideDep { struct OverrideDep {
QString quilt; QString quilt;
@ -148,6 +150,14 @@ inline auto getOverrideDeps() -> QList<OverrideDep>
QString getMetaURL(ResourceProvider provider, QVariant projectID); QString getMetaURL(ResourceProvider provider, QVariant projectID);
auto getModLoaderString(ModLoaderType type) -> const QString;
constexpr bool hasSingleModLoaderSelected(ModLoaderTypes l) noexcept
{
auto x = static_cast<int>(l);
return x && !(x & (x - 1));
}
} // namespace ModPlatform } // namespace ModPlatform
Q_DECLARE_METATYPE(ModPlatform::IndexedPack) Q_DECLARE_METATYPE(ModPlatform::IndexedPack)

View File

@ -54,9 +54,6 @@ class ResourceAPI {
public: public:
virtual ~ResourceAPI() = default; virtual ~ResourceAPI() = default;
enum ModLoaderType { NeoForge = 1 << 0, Forge = 1 << 1, Cauldron = 1 << 2, LiteLoader = 1 << 3, Fabric = 1 << 4, Quilt = 1 << 5 };
Q_DECLARE_FLAGS(ModLoaderTypes, ModLoaderType)
struct SortingMethod { struct SortingMethod {
// The index of the sorting method. Used to allow for arbitrary ordering in the list of methods. // The index of the sorting method. Used to allow for arbitrary ordering in the list of methods.
// Used by Flame in the API request. // Used by Flame in the API request.
@ -74,7 +71,7 @@ class ResourceAPI {
std::optional<QString> search; std::optional<QString> search;
std::optional<SortingMethod> sorting; std::optional<SortingMethod> sorting;
std::optional<ModLoaderTypes> loaders; std::optional<ModPlatform::ModLoaderTypes> loaders;
std::optional<std::list<Version> > versions; std::optional<std::list<Version> > versions;
}; };
struct SearchCallbacks { struct SearchCallbacks {
@ -87,7 +84,7 @@ class ResourceAPI {
ModPlatform::IndexedPack pack; ModPlatform::IndexedPack pack;
std::optional<std::list<Version> > mcVersions; std::optional<std::list<Version> > mcVersions;
std::optional<ModLoaderTypes> loaders; std::optional<ModPlatform::ModLoaderTypes> loaders;
VersionSearchArgs(VersionSearchArgs const&) = default; VersionSearchArgs(VersionSearchArgs const&) = default;
void operator=(VersionSearchArgs other) void operator=(VersionSearchArgs other)
@ -114,7 +111,7 @@ class ResourceAPI {
struct DependencySearchArgs { struct DependencySearchArgs {
ModPlatform::Dependency dependency; ModPlatform::Dependency dependency;
Version mcVersion; Version mcVersion;
ModLoaderTypes loader; ModPlatform::ModLoaderTypes loader;
}; };
struct DependencySearchCallbacks { struct DependencySearchCallbacks {
@ -161,27 +158,6 @@ class ResourceAPI {
return nullptr; return nullptr;
} }
static auto getModLoaderString(ModLoaderType type) -> const QString
{
switch (type) {
case NeoForge:
return "neoforge";
case Forge:
return "forge";
case Cauldron:
return "cauldron";
case LiteLoader:
return "liteloader";
case Fabric:
return "fabric";
case Quilt:
return "quilt";
default:
break;
}
return "";
}
protected: protected:
[[nodiscard]] inline QString debugName() const { return "External resource API"; } [[nodiscard]] inline QString debugName() const { return "External resource API"; }

View File

@ -1,6 +1,7 @@
#include "FileResolvingTask.h" #include "FileResolvingTask.h"
#include "Json.h" #include "Json.h"
#include "modplatform/ModIndex.h"
#include "net/ApiDownload.h" #include "net/ApiDownload.h"
#include "net/ApiUpload.h" #include "net/ApiUpload.h"
#include "net/Upload.h" #include "net/Upload.h"
@ -102,7 +103,7 @@ void Flame::FileResolvingTask::netJobFinished()
auto url = QString("https://api.modrinth.com/v2/version_file/%1?algorithm=sha1").arg(hash); auto url = QString("https://api.modrinth.com/v2/version_file/%1?algorithm=sha1").arg(hash);
auto output = std::make_shared<QByteArray>(); auto output = std::make_shared<QByteArray>();
auto dl = Net::ApiDownload::makeByteArray(QUrl(url), output); auto dl = Net::ApiDownload::makeByteArray(QUrl(url), output);
QObject::connect(dl.get(), &Net::Download::succeeded, [&out]() { out.resolved = true; }); QObject::connect(dl.get(), &Net::ApiDownload::succeeded, [&out]() { out.resolved = true; });
m_checkJob->addNetAction(dl); m_checkJob->addNetAction(dl);
blockedProjects.insert(&out, output); blockedProjects.insert(&out, output);
@ -153,7 +154,7 @@ void Flame::FileResolvingTask::modrinthCheckFinished()
// If there's more than one mod loader for this version, we can't know for sure // If there's more than one mod loader for this version, we can't know for sure
// which file is relative to each loader, so it's best to not use any one and // which file is relative to each loader, so it's best to not use any one and
// let the user download it manually. // let the user download it manually.
if (file.loaders.size() <= 1) { if (!file.loaders || hasSingleModLoaderSelected(file.loaders)) {
out->url = file.downloadUrl; out->url = file.downloadUrl;
qDebug() << "Found alternative on modrinth " << out->fileName; qDebug() << "Found alternative on modrinth " << out->fileName;
} else { } else {
@ -175,7 +176,7 @@ void Flame::FileResolvingTask::modrinthCheckFinished()
auto url = QString("https://api.curseforge.com/v1/mods/%1").arg(projectId); auto url = QString("https://api.curseforge.com/v1/mods/%1").arg(projectId);
auto dl = Net::ApiDownload::makeByteArray(url, output); auto dl = Net::ApiDownload::makeByteArray(url, output);
qDebug() << "Fetching url slug for file:" << mod->fileName; qDebug() << "Fetching url slug for file:" << mod->fileName;
QObject::connect(dl.get(), &Net::Download::succeeded, [block, index, output]() { QObject::connect(dl.get(), &Net::ApiDownload::succeeded, [block, index, output]() {
auto mod = block->at(index); // use the shared_ptr so it is captured and only freed when we are done auto mod = block->at(index); // use the shared_ptr so it is captured and only freed when we are done
auto json = QJsonDocument::fromJson(*output); auto json = QJsonDocument::fromJson(*output);
auto base = auto base =

View File

@ -6,7 +6,6 @@
#include "FlameModIndex.h" #include "FlameModIndex.h"
#include "Application.h" #include "Application.h"
#include "BuildConfig.h"
#include "Json.h" #include "Json.h"
#include "net/ApiDownload.h" #include "net/ApiDownload.h"
#include "net/ApiUpload.h" #include "net/ApiUpload.h"
@ -131,19 +130,13 @@ auto FlameAPI::getLatestVersion(VersionSearchArgs&& args) -> ModPlatform::Indexe
auto obj = Json::requireObject(doc); auto obj = Json::requireObject(doc);
auto arr = Json::requireArray(obj, "data"); auto arr = Json::requireArray(obj, "data");
QJsonObject latest_file_obj;
ModPlatform::IndexedVersion ver_tmp;
for (auto file : arr) { for (auto file : arr) {
auto file_obj = Json::requireObject(file); auto file_obj = Json::requireObject(file);
auto file_tmp = FlameMod::loadIndexedPackVersion(file_obj); auto file_tmp = FlameMod::loadIndexedPackVersion(file_obj);
if (file_tmp.date > ver_tmp.date) { if (file_tmp.date > ver.date && (!args.loaders.has_value() || !file_tmp.loaders || args.loaders.value() & file_tmp.loaders))
ver_tmp = file_tmp; ver = file_tmp;
latest_file_obj = file_obj;
}
} }
ver = FlameMod::loadIndexedPackVersion(latest_file_obj);
} catch (Json::JsonException& e) { } catch (Json::JsonException& e) {
qCritical() << "Failed to parse response from a version request."; qCritical() << "Failed to parse response from a version request.";
qCritical() << e.what(); qCritical() << e.what();

View File

@ -24,7 +24,10 @@ class FlameAPI : public NetworkResourceAPI {
[[nodiscard]] auto getSortingMethods() const -> QList<ResourceAPI::SortingMethod> override; [[nodiscard]] auto getSortingMethods() const -> QList<ResourceAPI::SortingMethod> override;
static inline auto validateModLoaders(ModLoaderTypes loaders) -> bool { return loaders & (NeoForge | Forge | Fabric | Quilt); } static inline auto validateModLoaders(ModPlatform::ModLoaderTypes loaders) -> bool
{
return loaders & (ModPlatform::NeoForge | ModPlatform::Forge | ModPlatform::Fabric | ModPlatform::Quilt);
}
private: private:
static int getClassId(ModPlatform::ResourceType type) static int getClassId(ModPlatform::ResourceType type)
@ -38,22 +41,42 @@ class FlameAPI : public NetworkResourceAPI {
} }
} }
static int getMappedModLoader(ModLoaderTypes loaders) static int getMappedModLoader(ModPlatform::ModLoaderType loaders)
{ {
// https://docs.curseforge.com/?http#tocS_ModLoaderType // https://docs.curseforge.com/?http#tocS_ModLoaderType
if (loaders & Forge) switch (loaders) {
return 1; case ModPlatform::Forge:
if (loaders & Fabric) return 1;
return 4; case ModPlatform::Cauldron:
// TODO: remove this once Quilt drops official Fabric support return 2;
if (loaders & Quilt) // NOTE: Most if not all Fabric mods should work *currently* case ModPlatform::LiteLoader:
return 4; // FIXME: implement multiple loaders filter (this should be 5) return 3;
// TODO: remove this once NeoForge drops official Forge support case ModPlatform::Fabric:
if (loaders & NeoForge) // NOTE: Most if not all Forge mods should work *currently* return 4;
return 1; // FIXME: implement multiple loaders filter (this should be 6) case ModPlatform::Quilt:
return 5;
case ModPlatform::NeoForge:
return 6;
}
return 0; return 0;
} }
static auto getModLoaderStrings(const ModPlatform::ModLoaderTypes types) -> const QStringList
{
QStringList l;
for (auto loader : { ModPlatform::NeoForge, ModPlatform::Forge, ModPlatform::Fabric, ModPlatform::Quilt }) {
if (types & loader) {
l << QString::number(getMappedModLoader(loader));
}
}
return l;
}
static auto getModLoaderFilters(ModPlatform::ModLoaderTypes types) -> const QString
{
return "[" + getModLoaderStrings(types).join(',') + "]";
}
private: private:
[[nodiscard]] std::optional<QString> getSearchURL(SearchArgs const& args) const override [[nodiscard]] std::optional<QString> getSearchURL(SearchArgs const& args) const override
{ {
@ -70,7 +93,7 @@ class FlameAPI : public NetworkResourceAPI {
get_arguments.append(QString("sortField=%1").arg(args.sorting.value().index)); get_arguments.append(QString("sortField=%1").arg(args.sorting.value().index));
get_arguments.append("sortOrder=desc"); get_arguments.append("sortOrder=desc");
if (args.loaders.has_value()) if (args.loaders.has_value())
get_arguments.append(QString("modLoaderType=%1").arg(getMappedModLoader(args.loaders.value()))); get_arguments.append(QString("modLoaderTypes=%1").arg(getModLoaderFilters(args.loaders.value())));
get_arguments.append(gameVersionStr); get_arguments.append(gameVersionStr);
return "https://api.curseforge.com/v1/mods/search?gameId=432&" + get_arguments.join('&'); return "https://api.curseforge.com/v1/mods/search?gameId=432&" + get_arguments.join('&');
@ -84,47 +107,27 @@ class FlameAPI : public NetworkResourceAPI {
[[nodiscard]] std::optional<QString> getVersionsURL(VersionSearchArgs const& args) const override [[nodiscard]] std::optional<QString> getVersionsURL(VersionSearchArgs const& args) const override
{ {
auto addonId = args.pack.addonId.toString(); auto addonId = args.pack.addonId.toString();
QString url{ QString("https://api.curseforge.com/v1/mods/%1/files?pageSize=10000&").arg(addonId) }; QString url = QString("https://api.curseforge.com/v1/mods/%1/files?pageSize=10000").arg(addonId);
QStringList get_parameters;
if (args.mcVersions.has_value()) if (args.mcVersions.has_value())
get_parameters.append(QString("gameVersion=%1").arg(args.mcVersions.value().front().toString())); url += QString("&gameVersion=%1").arg(args.mcVersions.value().front().toString());
if (args.loaders.has_value()) { if (args.loaders.has_value() && ModPlatform::hasSingleModLoaderSelected(args.loaders.value())) {
int mappedModLoader = getMappedModLoader(args.loaders.value()); int mappedModLoader = getMappedModLoader(static_cast<ModPlatform::ModLoaderType>(static_cast<int>(args.loaders.value())));
url += QString("&modLoaderType=%1").arg(mappedModLoader);
if (args.loaders.value() & Quilt) {
auto overide = ModPlatform::getOverrideDeps();
auto over = std::find_if(overide.cbegin(), overide.cend(), [addonId](auto dep) {
return dep.provider == ModPlatform::ResourceProvider::FLAME && addonId == dep.quilt;
});
if (over != overide.cend()) {
mappedModLoader = 5;
}
}
get_parameters.append(QString("modLoaderType=%1").arg(mappedModLoader));
} }
return url;
return url + get_parameters.join('&');
}; };
[[nodiscard]] std::optional<QString> getDependencyURL(DependencySearchArgs const& args) const override [[nodiscard]] std::optional<QString> getDependencyURL(DependencySearchArgs const& args) const override
{ {
auto mappedModLoader = getMappedModLoader(args.loader);
auto addonId = args.dependency.addonId.toString(); auto addonId = args.dependency.addonId.toString();
if (args.loader & Quilt) { auto url =
auto overide = ModPlatform::getOverrideDeps(); QString("https://api.curseforge.com/v1/mods/%1/files?pageSize=10000&gameVersion=%2").arg(addonId, args.mcVersion.toString());
auto over = std::find_if(overide.cbegin(), overide.cend(), [addonId](auto dep) { if (args.loader && ModPlatform::hasSingleModLoaderSelected(args.loader)) {
return dep.provider == ModPlatform::ResourceProvider::FLAME && addonId == dep.quilt; int mappedModLoader = getMappedModLoader(static_cast<ModPlatform::ModLoaderType>(static_cast<int>(args.loader)));
}); url += QString("&modLoaderType=%1").arg(mappedModLoader);
if (over != overide.cend()) {
mappedModLoader = 5;
}
} }
return QString("https://api.curseforge.com/v1/mods/%1/files?pageSize=10000&gameVersion=%2&modLoaderType=%3") return url;
.arg(addonId)
.arg(args.mcVersion.toString())
.arg(mappedModLoader);
}; };
}; };

View File

@ -5,13 +5,11 @@
#include <MurmurHash2.h> #include <MurmurHash2.h>
#include <memory> #include <memory>
#include "FileSystem.h"
#include "Json.h" #include "Json.h"
#include "ResourceDownloadTask.h" #include "ResourceDownloadTask.h"
#include "minecraft/mod/ModFolderModel.h" #include "minecraft/mod/ModFolderModel.h"
#include "minecraft/mod/ResourceFolderModel.h"
#include "net/ApiDownload.h" #include "net/ApiDownload.h"

View File

@ -10,7 +10,7 @@ class FlameCheckUpdate : public CheckUpdateTask {
public: public:
FlameCheckUpdate(QList<Mod*>& mods, FlameCheckUpdate(QList<Mod*>& mods,
std::list<Version>& mcVersions, std::list<Version>& mcVersions,
std::optional<ResourceAPI::ModLoaderTypes> loaders, std::optional<ModPlatform::ModLoaderTypes> loaders,
std::shared_ptr<ModFolderModel> mods_folder) std::shared_ptr<ModFolderModel> mods_folder)
: CheckUpdateTask(mods, mcVersions, loaders, mods_folder) : CheckUpdateTask(mods, mcVersions, loaders, mods_folder)
{} {}

View File

@ -81,6 +81,7 @@ void FlameMod::loadIndexedPackVersions(ModPlatform::IndexedPack& pack,
QVector<ModPlatform::IndexedVersion> unsortedVersions; QVector<ModPlatform::IndexedVersion> unsortedVersions;
auto profile = (dynamic_cast<const MinecraftInstance*>(inst))->getPackProfile(); auto profile = (dynamic_cast<const MinecraftInstance*>(inst))->getPackProfile();
QString mcVersion = profile->getComponentVersion("net.minecraft"); QString mcVersion = profile->getComponentVersion("net.minecraft");
auto loaders = profile->getSupportedModLoaders();
for (auto versionIter : arr) { for (auto versionIter : arr) {
auto obj = versionIter.toObject(); auto obj = versionIter.toObject();
@ -89,7 +90,8 @@ void FlameMod::loadIndexedPackVersions(ModPlatform::IndexedPack& pack,
if (!file.addonId.isValid()) if (!file.addonId.isValid())
file.addonId = pack.addonId; file.addonId = pack.addonId;
if (file.fileId.isValid()) // Heuristic to check if the returned value is valid if (file.fileId.isValid() &&
(!loaders.has_value() || !file.loaders || loaders.value() & file.loaders)) // Heuristic to check if the returned value is valid
unsortedVersions.append(file); unsortedVersions.append(file);
} }
@ -115,6 +117,19 @@ auto FlameMod::loadIndexedPackVersion(QJsonObject& obj, bool load_changelog) ->
if (str.contains('.')) if (str.contains('.'))
file.mcVersion.append(str); file.mcVersion.append(str);
auto loader = str.toLower();
if (loader == "neoforge")
file.loaders |= ModPlatform::NeoForge;
if (loader == "forge")
file.loaders |= ModPlatform::Forge;
if (loader == "cauldron")
file.loaders |= ModPlatform::Cauldron;
if (loader == "liteloader")
file.loaders |= ModPlatform::LiteLoader;
if (loader == "fabric")
file.loaders |= ModPlatform::Fabric;
if (loader == "quilt")
file.loaders |= ModPlatform::Quilt;
} }
file.addonId = Json::requireInteger(obj, "modId"); file.addonId = Json::requireInteger(obj, "modId");
@ -173,8 +188,11 @@ auto FlameMod::loadIndexedPackVersion(QJsonObject& obj, bool load_changelog) ->
return file; return file;
} }
ModPlatform::IndexedVersion FlameMod::loadDependencyVersions(const ModPlatform::Dependency& m, QJsonArray& arr) ModPlatform::IndexedVersion FlameMod::loadDependencyVersions(const ModPlatform::Dependency& m, QJsonArray& arr, const BaseInstance* inst)
{ {
auto profile = (dynamic_cast<const MinecraftInstance*>(inst))->getPackProfile();
QString mcVersion = profile->getComponentVersion("net.minecraft");
auto loaders = profile->getSupportedModLoaders();
QVector<ModPlatform::IndexedVersion> versions; QVector<ModPlatform::IndexedVersion> versions;
for (auto versionIter : arr) { for (auto versionIter : arr) {
auto obj = versionIter.toObject(); auto obj = versionIter.toObject();
@ -183,7 +201,8 @@ ModPlatform::IndexedVersion FlameMod::loadDependencyVersions(const ModPlatform::
if (!file.addonId.isValid()) if (!file.addonId.isValid())
file.addonId = m.addonId; file.addonId = m.addonId;
if (file.fileId.isValid()) // Heuristic to check if the returned value is valid if (file.fileId.isValid() &&
(!loaders.has_value() || !file.loaders || loaders.value() & file.loaders)) // Heuristic to check if the returned value is valid
versions.append(file); versions.append(file);
} }
@ -192,5 +211,7 @@ ModPlatform::IndexedVersion FlameMod::loadDependencyVersions(const ModPlatform::
return a.date > b.date; return a.date > b.date;
}; };
std::sort(versions.begin(), versions.end(), orderSortPredicate); std::sort(versions.begin(), versions.end(), orderSortPredicate);
return versions.front(); if (versions.size() != 0)
return versions.front();
return {};
} }

View File

@ -19,5 +19,5 @@ void loadIndexedPackVersions(ModPlatform::IndexedPack& pack,
const shared_qobject_ptr<QNetworkAccessManager>& network, const shared_qobject_ptr<QNetworkAccessManager>& network,
const BaseInstance* inst); const BaseInstance* inst);
auto loadIndexedPackVersion(QJsonObject& obj, bool load_changelog = false) -> ModPlatform::IndexedVersion; auto loadIndexedPackVersion(QJsonObject& obj, bool load_changelog = false) -> ModPlatform::IndexedVersion;
auto loadDependencyVersions(const ModPlatform::Dependency& m, QJsonArray& arr) -> ModPlatform::IndexedVersion; auto loadDependencyVersions(const ModPlatform::Dependency& m, QJsonArray& arr, const BaseInstance* inst) -> ModPlatform::IndexedVersion;
} // namespace FlameMod } // namespace FlameMod

View File

@ -131,7 +131,7 @@ Task::Ptr NetworkResourceAPI::getDependencyVersion(DependencySearchArgs&& args,
auto netJob = makeShared<NetJob>(QString("%1::Dependency").arg(args.dependency.addonId.toString()), APPLICATION->network()); auto netJob = makeShared<NetJob>(QString("%1::Dependency").arg(args.dependency.addonId.toString()), APPLICATION->network());
auto response = std::make_shared<QByteArray>(); auto response = std::make_shared<QByteArray>();
netJob->addNetAction(Net::Download::makeByteArray(versions_url, response)); netJob->addNetAction(Net::ApiDownload::makeByteArray(versions_url, response));
QObject::connect(netJob.get(), &NetJob::succeeded, [=] { QObject::connect(netJob.get(), &NetJob::succeeded, [=] {
QJsonParseError parse_error{}; QJsonParseError parse_error{};

View File

@ -60,19 +60,19 @@ Modpack parseDirectory(QString path)
auto name = Json::requireString(obj, "name", "name"); auto name = Json::requireString(obj, "name", "name");
auto version = Json::requireString(obj, "version", "version"); auto version = Json::requireString(obj, "version", "version");
if (name == "neoforge") { if (name == "neoforge") {
modpack.loaderType = ResourceAPI::NeoForge; modpack.loaderType = ModPlatform::NeoForge;
modpack.version = version; modpack.version = version;
break; break;
} else if (name == "forge") { } else if (name == "forge") {
modpack.loaderType = ResourceAPI::Forge; modpack.loaderType = ModPlatform::Forge;
modpack.version = version; modpack.version = version;
break; break;
} else if (name == "fabric") { } else if (name == "fabric") {
modpack.loaderType = ResourceAPI::Fabric; modpack.loaderType = ModPlatform::Fabric;
modpack.version = version; modpack.version = version;
break; break;
} else if (name == "quilt") { } else if (name == "quilt") {
modpack.loaderType = ResourceAPI::Quilt; modpack.loaderType = ModPlatform::Quilt;
modpack.version = version; modpack.version = version;
break; break;
} }

View File

@ -39,7 +39,7 @@ struct Modpack {
// not needed for instance creation // not needed for instance creation
QVariant jvmArgs; QVariant jvmArgs;
std::optional<ResourceAPI::ModLoaderType> loaderType; std::optional<ModPlatform::ModLoaderType> loaderType;
QString loaderVersion; QString loaderVersion;
QIcon icon; QIcon icon;

View File

@ -68,25 +68,25 @@ void PackInstallTask::copySettings()
auto modloader = m_pack.loaderType; auto modloader = m_pack.loaderType;
if (modloader.has_value()) if (modloader.has_value())
switch (modloader.value()) { switch (modloader.value()) {
case ResourceAPI::NeoForge: { case ModPlatform::NeoForge: {
components->setComponentVersion("net.neoforged", m_pack.version, true); components->setComponentVersion("net.neoforged", m_pack.version, true);
break; break;
} }
case ResourceAPI::Forge: { case ModPlatform::Forge: {
components->setComponentVersion("net.minecraftforge", m_pack.version, true); components->setComponentVersion("net.minecraftforge", m_pack.version, true);
break; break;
} }
case ResourceAPI::Fabric: { case ModPlatform::Fabric: {
components->setComponentVersion("net.fabricmc.fabric-loader", m_pack.version, true); components->setComponentVersion("net.fabricmc.fabric-loader", m_pack.version, true);
break; break;
} }
case ResourceAPI::Quilt: { case ModPlatform::Quilt: {
components->setComponentVersion("org.quiltmc.quilt-loader", m_pack.version, true); components->setComponentVersion("org.quiltmc.quilt-loader", m_pack.version, true);
break; break;
} }
case ResourceAPI::Cauldron: case ModPlatform::Cauldron:
break; break;
case ResourceAPI::LiteLoader: case ModPlatform::LiteLoader:
break; break;
} }
components->saveNow(); components->saveNow();

View File

@ -41,7 +41,7 @@ Task::Ptr ModrinthAPI::currentVersions(const QStringList& hashes, QString hash_f
Task::Ptr ModrinthAPI::latestVersion(QString hash, Task::Ptr ModrinthAPI::latestVersion(QString hash,
QString hash_format, QString hash_format,
std::optional<std::list<Version>> mcVersions, std::optional<std::list<Version>> mcVersions,
std::optional<ModLoaderTypes> loaders, std::optional<ModPlatform::ModLoaderTypes> loaders,
std::shared_ptr<QByteArray> response) std::shared_ptr<QByteArray> response)
{ {
auto netJob = makeShared<NetJob>(QString("Modrinth::GetLatestVersion"), APPLICATION->network()); auto netJob = makeShared<NetJob>(QString("Modrinth::GetLatestVersion"), APPLICATION->network());
@ -71,7 +71,7 @@ Task::Ptr ModrinthAPI::latestVersion(QString hash,
Task::Ptr ModrinthAPI::latestVersions(const QStringList& hashes, Task::Ptr ModrinthAPI::latestVersions(const QStringList& hashes,
QString hash_format, QString hash_format,
std::optional<std::list<Version>> mcVersions, std::optional<std::list<Version>> mcVersions,
std::optional<ModLoaderTypes> loaders, std::optional<ModPlatform::ModLoaderTypes> loaders,
std::shared_ptr<QByteArray> response) std::shared_ptr<QByteArray> response)
{ {
auto netJob = makeShared<NetJob>(QString("Modrinth::GetLatestVersions"), APPLICATION->network()); auto netJob = makeShared<NetJob>(QString("Modrinth::GetLatestVersions"), APPLICATION->network());

View File

@ -19,13 +19,13 @@ class ModrinthAPI : public NetworkResourceAPI {
auto latestVersion(QString hash, auto latestVersion(QString hash,
QString hash_format, QString hash_format,
std::optional<std::list<Version>> mcVersions, std::optional<std::list<Version>> mcVersions,
std::optional<ModLoaderTypes> loaders, std::optional<ModPlatform::ModLoaderTypes> loaders,
std::shared_ptr<QByteArray> response) -> Task::Ptr; std::shared_ptr<QByteArray> response) -> Task::Ptr;
auto latestVersions(const QStringList& hashes, auto latestVersions(const QStringList& hashes,
QString hash_format, QString hash_format,
std::optional<std::list<Version>> mcVersions, std::optional<std::list<Version>> mcVersions,
std::optional<ModLoaderTypes> loaders, std::optional<ModPlatform::ModLoaderTypes> loaders,
std::shared_ptr<QByteArray> response) -> Task::Ptr; std::shared_ptr<QByteArray> response) -> Task::Ptr;
Task::Ptr getProjects(QStringList addonIds, std::shared_ptr<QByteArray> response) const override; Task::Ptr getProjects(QStringList addonIds, std::shared_ptr<QByteArray> response) const override;
@ -35,22 +35,19 @@ class ModrinthAPI : public NetworkResourceAPI {
inline auto getAuthorURL(const QString& name) const -> QString { return "https://modrinth.com/user/" + name; }; inline auto getAuthorURL(const QString& name) const -> QString { return "https://modrinth.com/user/" + name; };
static auto getModLoaderStrings(const ModLoaderTypes types) -> const QStringList static auto getModLoaderStrings(const ModPlatform::ModLoaderTypes types) -> const QStringList
{ {
QStringList l; QStringList l;
for (auto loader : { NeoForge, Forge, Fabric, Quilt, LiteLoader }) { for (auto loader :
{ ModPlatform::NeoForge, ModPlatform::Forge, ModPlatform::Fabric, ModPlatform::Quilt, ModPlatform::LiteLoader }) {
if (types & loader) { if (types & loader) {
l << getModLoaderString(loader); l << getModLoaderString(loader);
} }
} }
if ((types & NeoForge) && (~types & Forge)) // Add Forge if NeoForge is in use, if Forge isn't already there
l << getModLoaderString(Forge);
if ((types & Quilt) && (~types & Fabric)) // Add Fabric if Quilt is in use, if Fabric isn't already there
l << getModLoaderString(Fabric);
return l; return l;
} }
static auto getModLoaderFilters(ModLoaderTypes types) -> const QString static auto getModLoaderFilters(ModPlatform::ModLoaderTypes types) -> const QString
{ {
QStringList l; QStringList l;
for (auto loader : getModLoaderStrings(types)) { for (auto loader : getModLoaderStrings(types)) {
@ -143,9 +140,9 @@ class ModrinthAPI : public NetworkResourceAPI {
return s.isEmpty() ? QString() : s; return s.isEmpty() ? QString() : s;
} }
static inline auto validateModLoaders(ModLoaderTypes loaders) -> bool static inline auto validateModLoaders(ModPlatform::ModLoaderTypes loaders) -> bool
{ {
return loaders & (NeoForge | Forge | Fabric | Quilt | LiteLoader); return loaders & (ModPlatform::NeoForge | ModPlatform::Forge | ModPlatform::Fabric | ModPlatform::Quilt | ModPlatform::LiteLoader);
} }
[[nodiscard]] std::optional<QString> getDependencyURL(DependencySearchArgs const& args) const override [[nodiscard]] std::optional<QString> getDependencyURL(DependencySearchArgs const& args) const override

View File

@ -11,7 +11,6 @@
#include "tasks/ConcurrentTask.h" #include "tasks/ConcurrentTask.h"
#include "minecraft/mod/ModFolderModel.h" #include "minecraft/mod/ModFolderModel.h"
#include "minecraft/mod/ResourceFolderModel.h"
static ModrinthAPI api; static ModrinthAPI api;
static ModPlatform::ProviderCapabilities ProviderCaps; static ModPlatform::ProviderCapabilities ProviderCaps;
@ -111,11 +110,11 @@ void ModrinthCheckUpdate::executeTask()
// so we may want to filter it // so we may want to filter it
QString loader_filter; QString loader_filter;
if (m_loaders.has_value()) { if (m_loaders.has_value()) {
static auto flags = { ResourceAPI::ModLoaderType::NeoForge, ResourceAPI::ModLoaderType::Forge, static auto flags = { ModPlatform::ModLoaderType::NeoForge, ModPlatform::ModLoaderType::Forge,
ResourceAPI::ModLoaderType::Fabric, ResourceAPI::ModLoaderType::Quilt }; ModPlatform::ModLoaderType::Fabric, ModPlatform::ModLoaderType::Quilt };
for (auto flag : flags) { for (auto flag : flags) {
if (m_loaders.value().testFlag(flag)) { if (m_loaders.value().testFlag(flag)) {
loader_filter = api.getModLoaderString(flag); loader_filter = ModPlatform::getModLoaderString(flag);
break; break;
} }
} }

View File

@ -10,7 +10,7 @@ class ModrinthCheckUpdate : public CheckUpdateTask {
public: public:
ModrinthCheckUpdate(QList<Mod*>& mods, ModrinthCheckUpdate(QList<Mod*>& mods,
std::list<Version>& mcVersions, std::list<Version>& mcVersions,
std::optional<ResourceAPI::ModLoaderTypes> loaders, std::optional<ModPlatform::ModLoaderTypes> loaders,
std::shared_ptr<ModFolderModel> mods_folder) std::shared_ptr<ModFolderModel> mods_folder)
: CheckUpdateTask(mods, mcVersions, loaders, mods_folder) : CheckUpdateTask(mods, mcVersions, loaders, mods_folder)
{} {}

View File

@ -93,19 +93,19 @@ void Modrinth::loadExtraPackData(ModPlatform::IndexedPack& pack, QJsonObject& ob
pack.extraDataLoaded = true; pack.extraDataLoaded = true;
} }
void Modrinth::loadIndexedPackVersions(ModPlatform::IndexedPack& pack, void Modrinth::loadIndexedPackVersions(ModPlatform::IndexedPack& pack, QJsonArray& arr, const BaseInstance* inst)
QJsonArray& arr,
[[maybe_unused]] const shared_qobject_ptr<QNetworkAccessManager>& network,
const BaseInstance* inst)
{ {
QVector<ModPlatform::IndexedVersion> unsortedVersions; QVector<ModPlatform::IndexedVersion> unsortedVersions;
QString mcVersion = (static_cast<const MinecraftInstance*>(inst))->getPackProfile()->getComponentVersion("net.minecraft"); auto profile = (dynamic_cast<const MinecraftInstance*>(inst))->getPackProfile();
QString mcVersion = profile->getComponentVersion("net.minecraft");
auto loaders = profile->getSupportedModLoaders();
for (auto versionIter : arr) { for (auto versionIter : arr) {
auto obj = versionIter.toObject(); auto obj = versionIter.toObject();
auto file = loadIndexedPackVersion(obj); auto file = loadIndexedPackVersion(obj);
if (file.fileId.isValid()) // Heuristic to check if the returned value is valid if (file.fileId.isValid() &&
(!loaders.has_value() || !file.loaders || loaders.value() & file.loaders)) // Heuristic to check if the returned value is valid
unsortedVersions.append(file); unsortedVersions.append(file);
} }
auto orderSortPredicate = [](const ModPlatform::IndexedVersion& a, const ModPlatform::IndexedVersion& b) -> bool { auto orderSortPredicate = [](const ModPlatform::IndexedVersion& a, const ModPlatform::IndexedVersion& b) -> bool {
@ -134,7 +134,18 @@ auto Modrinth::loadIndexedPackVersion(QJsonObject& obj, QString preferred_hash_t
} }
auto loaders = Json::requireArray(obj, "loaders"); auto loaders = Json::requireArray(obj, "loaders");
for (auto loader : loaders) { for (auto loader : loaders) {
file.loaders.append(loader.toString()); if (loader == "neoforge")
file.loaders |= ModPlatform::NeoForge;
if (loader == "forge")
file.loaders |= ModPlatform::Forge;
if (loader == "cauldron")
file.loaders |= ModPlatform::Cauldron;
if (loader == "liteloader")
file.loaders |= ModPlatform::LiteLoader;
if (loader == "fabric")
file.loaders |= ModPlatform::Fabric;
if (loader == "quilt")
file.loaders |= ModPlatform::Quilt;
} }
file.version = Json::requireString(obj, "name"); file.version = Json::requireString(obj, "name");
file.version_number = Json::requireString(obj, "version_number"); file.version_number = Json::requireString(obj, "version_number");
@ -218,15 +229,20 @@ auto Modrinth::loadIndexedPackVersion(QJsonObject& obj, QString preferred_hash_t
return {}; return {};
} }
auto Modrinth::loadDependencyVersions([[maybe_unused]] const ModPlatform::Dependency& m, QJsonArray& arr) -> ModPlatform::IndexedVersion auto Modrinth::loadDependencyVersions([[maybe_unused]] const ModPlatform::Dependency& m, QJsonArray& arr, const BaseInstance* inst)
-> ModPlatform::IndexedVersion
{ {
QVector<ModPlatform::IndexedVersion> versions; auto profile = (dynamic_cast<const MinecraftInstance*>(inst))->getPackProfile();
QString mcVersion = profile->getComponentVersion("net.minecraft");
auto loaders = profile->getSupportedModLoaders();
QVector<ModPlatform::IndexedVersion> versions;
for (auto versionIter : arr) { for (auto versionIter : arr) {
auto obj = versionIter.toObject(); auto obj = versionIter.toObject();
auto file = loadIndexedPackVersion(obj); auto file = loadIndexedPackVersion(obj);
if (file.fileId.isValid()) // Heuristic to check if the returned value is valid if (file.fileId.isValid() &&
(!loaders.has_value() || !file.loaders || loaders.value() & file.loaders)) // Heuristic to check if the returned value is valid
versions.append(file); versions.append(file);
} }
auto orderSortPredicate = [](const ModPlatform::IndexedVersion& a, const ModPlatform::IndexedVersion& b) -> bool { auto orderSortPredicate = [](const ModPlatform::IndexedVersion& a, const ModPlatform::IndexedVersion& b) -> bool {

View File

@ -26,11 +26,8 @@ namespace Modrinth {
void loadIndexedPack(ModPlatform::IndexedPack& m, QJsonObject& obj); void loadIndexedPack(ModPlatform::IndexedPack& m, QJsonObject& obj);
void loadExtraPackData(ModPlatform::IndexedPack& m, QJsonObject& obj); void loadExtraPackData(ModPlatform::IndexedPack& m, QJsonObject& obj);
void loadIndexedPackVersions(ModPlatform::IndexedPack& pack, void loadIndexedPackVersions(ModPlatform::IndexedPack& pack, QJsonArray& arr, const BaseInstance* inst);
QJsonArray& arr,
const shared_qobject_ptr<QNetworkAccessManager>& network,
const BaseInstance* inst);
auto loadIndexedPackVersion(QJsonObject& obj, QString hash_type = "sha512", QString filename_prefer = "") -> ModPlatform::IndexedVersion; auto loadIndexedPackVersion(QJsonObject& obj, QString hash_type = "sha512", QString filename_prefer = "") -> ModPlatform::IndexedVersion;
auto loadDependencyVersions(const ModPlatform::Dependency& m, QJsonArray& arr) -> ModPlatform::IndexedVersion; auto loadDependencyVersions(const ModPlatform::Dependency& m, QJsonArray& arr, const BaseInstance* inst) -> ModPlatform::IndexedVersion;
} // namespace Modrinth } // namespace Modrinth

View File

@ -43,9 +43,6 @@
#include "FileSystem.h" #include "FileSystem.h"
#include "MainWindow.h" #include "MainWindow.h"
#include "modplatform/ModIndex.h"
#include "modplatform/flame/FlameModIndex.h"
#include "ui/dialogs/ExportToModListDialog.h"
#include "ui_MainWindow.h" #include "ui_MainWindow.h"
#include <QDir> #include <QDir>
@ -92,17 +89,14 @@
#include <news/NewsChecker.h> #include <news/NewsChecker.h>
#include <tools/BaseProfiler.h> #include <tools/BaseProfiler.h>
#include <updater/ExternalUpdater.h> #include <updater/ExternalUpdater.h>
#include "InstancePageProvider.h"
#include "InstanceWindow.h" #include "InstanceWindow.h"
#include "JavaCommon.h"
#include "LaunchController.h"
#include "ui/dialogs/AboutDialog.h" #include "ui/dialogs/AboutDialog.h"
#include "ui/dialogs/CopyInstanceDialog.h" #include "ui/dialogs/CopyInstanceDialog.h"
#include "ui/dialogs/CustomMessageBox.h" #include "ui/dialogs/CustomMessageBox.h"
#include "ui/dialogs/EditAccountDialog.h"
#include "ui/dialogs/ExportInstanceDialog.h" #include "ui/dialogs/ExportInstanceDialog.h"
#include "ui/dialogs/ExportPackDialog.h" #include "ui/dialogs/ExportPackDialog.h"
#include "ui/dialogs/ExportToModListDialog.h"
#include "ui/dialogs/IconPickerDialog.h" #include "ui/dialogs/IconPickerDialog.h"
#include "ui/dialogs/ImportResourceDialog.h" #include "ui/dialogs/ImportResourceDialog.h"
#include "ui/dialogs/NewInstanceDialog.h" #include "ui/dialogs/NewInstanceDialog.h"
@ -115,17 +109,22 @@
#include "ui/themes/ThemeManager.h" #include "ui/themes/ThemeManager.h"
#include "ui/widgets/LabeledToolButton.h" #include "ui/widgets/LabeledToolButton.h"
#include "minecraft/PackProfile.h"
#include "minecraft/VersionFile.h"
#include "minecraft/WorldList.h" #include "minecraft/WorldList.h"
#include "minecraft/mod/ModFolderModel.h" #include "minecraft/mod/ModFolderModel.h"
#include "minecraft/mod/ResourcePackFolderModel.h"
#include "minecraft/mod/ShaderPackFolderModel.h" #include "minecraft/mod/ShaderPackFolderModel.h"
#include "minecraft/mod/TexturePackFolderModel.h"
#include "minecraft/mod/tasks/LocalResourceParse.h" #include "minecraft/mod/tasks/LocalResourceParse.h"
#include "modplatform/ModIndex.h"
#include "modplatform/flame/FlameAPI.h" #include "modplatform/flame/FlameAPI.h"
#include "modplatform/flame/FlameModIndex.h"
#include "KonamiCode.h" #include "KonamiCode.h"
#include "InstanceCopyTask.h" #include "InstanceCopyTask.h"
#include "InstanceImportTask.h"
#include "Json.h" #include "Json.h"

View File

@ -5,8 +5,6 @@
#include "ScrollMessageBox.h" #include "ScrollMessageBox.h"
#include "ui_ReviewMessageBox.h" #include "ui_ReviewMessageBox.h"
#include "FileSystem.h"
#include "Json.h"
#include "Markdown.h" #include "Markdown.h"
#include "tasks/ConcurrentTask.h" #include "tasks/ConcurrentTask.h"
@ -30,9 +28,9 @@ static std::list<Version> mcVersions(BaseInstance* inst)
return { static_cast<MinecraftInstance*>(inst)->getPackProfile()->getComponent("net.minecraft")->getVersion() }; return { static_cast<MinecraftInstance*>(inst)->getPackProfile()->getComponent("net.minecraft")->getVersion() };
} }
static std::optional<ResourceAPI::ModLoaderTypes> mcLoaders(BaseInstance* inst) static std::optional<ModPlatform::ModLoaderTypes> mcLoaders(BaseInstance* inst)
{ {
return { static_cast<MinecraftInstance*>(inst)->getPackProfile()->getModLoaders() }; return { static_cast<MinecraftInstance*>(inst)->getPackProfile()->getSupportedModLoaders() };
} }
ModUpdateDialog::ModUpdateDialog(QWidget* parent, ModUpdateDialog::ModUpdateDialog(QWidget* parent,

View File

@ -279,7 +279,7 @@ QList<BasePage*> ModDownloadDialog::getPages()
{ {
QList<BasePage*> pages; QList<BasePage*> pages;
auto loaders = static_cast<MinecraftInstance*>(m_instance)->getPackProfile()->getModLoaders().value(); auto loaders = static_cast<MinecraftInstance*>(m_instance)->getPackProfile()->getSupportedModLoaders().value();
if (ModrinthAPI::validateModLoaders(loaders)) if (ModrinthAPI::validateModLoaders(loaders))
pages.append(ModrinthModPage::create(this, *m_instance)); pages.append(ModrinthModPage::create(this, *m_instance));

View File

@ -33,7 +33,7 @@ ResourceAPI::SearchArgs ModModel::createSearchArguments()
auto sort = getCurrentSortingMethodByIndex(); auto sort = getCurrentSortingMethodByIndex();
return { ModPlatform::ResourceType::MOD, m_next_search_offset, m_search_term, sort, profile->getModLoaders(), versions }; return { ModPlatform::ResourceType::MOD, m_next_search_offset, m_search_term, sort, profile->getSupportedModLoaders(), versions };
} }
ResourceAPI::VersionSearchArgs ModModel::createVersionsArguments(QModelIndex& entry) ResourceAPI::VersionSearchArgs ModModel::createVersionsArguments(QModelIndex& entry)
@ -48,7 +48,7 @@ ResourceAPI::VersionSearchArgs ModModel::createVersionsArguments(QModelIndex& en
if (!m_filter->versions.empty()) if (!m_filter->versions.empty())
versions = m_filter->versions; versions = m_filter->versions;
return { pack, versions, profile->getModLoaders() }; return { pack, versions, profile->getSupportedModLoaders() };
} }
ResourceAPI::ProjectInfoArgs ModModel::createInfoArguments(QModelIndex& entry) ResourceAPI::ProjectInfoArgs ModModel::createInfoArguments(QModelIndex& entry)

View File

@ -124,8 +124,7 @@ void ModPage::updateVersionList()
auto version = current_pack->versions[i]; auto version = current_pack->versions[i];
bool valid = false; bool valid = false;
for (auto& mcVer : m_filter->versions) { for (auto& mcVer : m_filter->versions) {
// NOTE: Flame doesn't care about loader, so passing it changes nothing. if (validateVersion(version, mcVer.toString(), packProfile->getSupportedModLoaders())) {
if (validateVersion(version, mcVer.toString(), packProfile->getModLoaders())) {
valid = true; valid = true;
break; break;
} }

View File

@ -55,7 +55,7 @@ class ModPage : public ResourcePage {
virtual auto validateVersion(ModPlatform::IndexedVersion& ver, virtual auto validateVersion(ModPlatform::IndexedVersion& ver,
QString mineVer, QString mineVer,
std::optional<ResourceAPI::ModLoaderTypes> loaders = {}) const -> bool = 0; std::optional<ModPlatform::ModLoaderTypes> loaders = {}) const -> bool = 0;
[[nodiscard]] bool supportsFiltering() const override { return true; }; [[nodiscard]] bool supportsFiltering() const override { return true; };
auto getFilter() const -> const std::shared_ptr<ModFilterWidget::Filter> { return m_filter; } auto getFilter() const -> const std::shared_ptr<ModFilterWidget::Filter> { return m_filter; }

View File

@ -3,6 +3,7 @@
// SPDX-License-Identifier: GPL-3.0-only // SPDX-License-Identifier: GPL-3.0-only
#include "ShaderPackPage.h" #include "ShaderPackPage.h"
#include "modplatform/ModIndex.h"
#include "ui_ResourcePage.h" #include "ui_ResourcePage.h"
#include "ShaderPackModel.h" #include "ShaderPackModel.h"
@ -48,7 +49,7 @@ void ShaderPackResourcePage::addResourceToPage(ModPlatform::IndexedPack::Ptr pac
const std::shared_ptr<ResourceFolderModel> base_model) const std::shared_ptr<ResourceFolderModel> base_model)
{ {
QString custom_target_folder; QString custom_target_folder;
if (version.loaders.contains(QStringLiteral("canvas"))) if (version.loaders & ModPlatform::Cauldron)
custom_target_folder = QStringLiteral("resourcepacks"); custom_target_folder = QStringLiteral("resourcepacks");
m_model->addPack(pack, version, base_model, false, custom_target_folder); m_model->addPack(pack, version, base_model, false, custom_target_folder);
} }

View File

@ -31,7 +31,7 @@ void FlameModModel::loadIndexedPackVersions(ModPlatform::IndexedPack& m, QJsonAr
auto FlameModModel::loadDependencyVersions(const ModPlatform::Dependency& m, QJsonArray& arr) -> ModPlatform::IndexedVersion auto FlameModModel::loadDependencyVersions(const ModPlatform::Dependency& m, QJsonArray& arr) -> ModPlatform::IndexedVersion
{ {
return FlameMod::loadDependencyVersions(m, arr); return FlameMod::loadDependencyVersions(m, arr, &m_base_instance);
} }
auto FlameModModel::documentToArray(QJsonDocument& obj) const -> QJsonArray auto FlameModModel::documentToArray(QJsonDocument& obj) const -> QJsonArray

View File

@ -68,10 +68,10 @@ FlameModPage::FlameModPage(ModDownloadDialog* dialog, BaseInstance& instance) :
auto FlameModPage::validateVersion(ModPlatform::IndexedVersion& ver, auto FlameModPage::validateVersion(ModPlatform::IndexedVersion& ver,
QString mineVer, QString mineVer,
std::optional<ResourceAPI::ModLoaderTypes> loaders) const -> bool std::optional<ModPlatform::ModLoaderTypes> loaders) const -> bool
{ {
Q_UNUSED(loaders); return ver.mcVersion.contains(mineVer) && !ver.downloadUrl.isEmpty() &&
return ver.mcVersion.contains(mineVer) && !ver.downloadUrl.isEmpty(); (!loaders.has_value() || !ver.loaders || loaders.value() & ver.loaders);
} }
bool FlameModPage::optedOut(ModPlatform::IndexedVersion& ver) const bool FlameModPage::optedOut(ModPlatform::IndexedVersion& ver) const

View File

@ -95,7 +95,7 @@ class FlameModPage : public ModPage {
bool validateVersion(ModPlatform::IndexedVersion& ver, bool validateVersion(ModPlatform::IndexedVersion& ver,
QString mineVer, QString mineVer,
std::optional<ResourceAPI::ModLoaderTypes> loaders = {}) const override; std::optional<ModPlatform::ModLoaderTypes> loaders = {}) const override;
bool optedOut(ModPlatform::IndexedVersion& ver) const override; bool optedOut(ModPlatform::IndexedVersion& ver) const override;
void openUrl(const QUrl& url) override; void openUrl(const QUrl& url) override;

View File

@ -39,12 +39,12 @@ void ModrinthModModel::loadExtraPackInfo(ModPlatform::IndexedPack& m, QJsonObjec
void ModrinthModModel::loadIndexedPackVersions(ModPlatform::IndexedPack& m, QJsonArray& arr) void ModrinthModModel::loadIndexedPackVersions(ModPlatform::IndexedPack& m, QJsonArray& arr)
{ {
::Modrinth::loadIndexedPackVersions(m, arr, APPLICATION->network(), &m_base_instance); ::Modrinth::loadIndexedPackVersions(m, arr, &m_base_instance);
} }
auto ModrinthModModel::loadDependencyVersions(const ModPlatform::Dependency& m, QJsonArray& arr) -> ModPlatform::IndexedVersion auto ModrinthModModel::loadDependencyVersions(const ModPlatform::Dependency& m, QJsonArray& arr) -> ModPlatform::IndexedVersion
{ {
return ::Modrinth::loadDependencyVersions(m, arr); return ::Modrinth::loadDependencyVersions(m, arr, &m_base_instance);
} }
auto ModrinthModModel::documentToArray(QJsonDocument& obj) const -> QJsonArray auto ModrinthModModel::documentToArray(QJsonDocument& obj) const -> QJsonArray
@ -66,7 +66,7 @@ void ModrinthResourcePackModel::loadExtraPackInfo(ModPlatform::IndexedPack& m, Q
void ModrinthResourcePackModel::loadIndexedPackVersions(ModPlatform::IndexedPack& m, QJsonArray& arr) void ModrinthResourcePackModel::loadIndexedPackVersions(ModPlatform::IndexedPack& m, QJsonArray& arr)
{ {
::Modrinth::loadIndexedPackVersions(m, arr, APPLICATION->network(), &m_base_instance); ::Modrinth::loadIndexedPackVersions(m, arr, &m_base_instance);
} }
auto ModrinthResourcePackModel::documentToArray(QJsonDocument& obj) const -> QJsonArray auto ModrinthResourcePackModel::documentToArray(QJsonDocument& obj) const -> QJsonArray
@ -88,7 +88,7 @@ void ModrinthTexturePackModel::loadExtraPackInfo(ModPlatform::IndexedPack& m, QJ
void ModrinthTexturePackModel::loadIndexedPackVersions(ModPlatform::IndexedPack& m, QJsonArray& arr) void ModrinthTexturePackModel::loadIndexedPackVersions(ModPlatform::IndexedPack& m, QJsonArray& arr)
{ {
::Modrinth::loadIndexedPackVersions(m, arr, APPLICATION->network(), &m_base_instance); ::Modrinth::loadIndexedPackVersions(m, arr, &m_base_instance);
} }
auto ModrinthTexturePackModel::documentToArray(QJsonDocument& obj) const -> QJsonArray auto ModrinthTexturePackModel::documentToArray(QJsonDocument& obj) const -> QJsonArray
@ -110,7 +110,7 @@ void ModrinthShaderPackModel::loadExtraPackInfo(ModPlatform::IndexedPack& m, QJs
void ModrinthShaderPackModel::loadIndexedPackVersions(ModPlatform::IndexedPack& m, QJsonArray& arr) void ModrinthShaderPackModel::loadIndexedPackVersions(ModPlatform::IndexedPack& m, QJsonArray& arr)
{ {
::Modrinth::loadIndexedPackVersions(m, arr, APPLICATION->network(), &m_base_instance); ::Modrinth::loadIndexedPackVersions(m, arr, &m_base_instance);
} }
auto ModrinthShaderPackModel::documentToArray(QJsonDocument& obj) const -> QJsonArray auto ModrinthShaderPackModel::documentToArray(QJsonDocument& obj) const -> QJsonArray

View File

@ -65,21 +65,9 @@ ModrinthModPage::ModrinthModPage(ModDownloadDialog* dialog, BaseInstance& instan
auto ModrinthModPage::validateVersion(ModPlatform::IndexedVersion& ver, auto ModrinthModPage::validateVersion(ModPlatform::IndexedVersion& ver,
QString mineVer, QString mineVer,
std::optional<ResourceAPI::ModLoaderTypes> loaders) const -> bool std::optional<ModPlatform::ModLoaderTypes> loaders) const -> bool
{ {
auto loaderCompatible = !loaders.has_value(); return ver.mcVersion.contains(mineVer) && (!loaders.has_value() || !ver.loaders || loaders.value() & ver.loaders);
if (!loaderCompatible) {
auto loaderStrings = ModrinthAPI::getModLoaderStrings(loaders.value());
for (auto remoteLoader : ver.loaders) {
if (loaderStrings.contains(remoteLoader)) {
loaderCompatible = true;
break;
}
}
}
return ver.mcVersion.contains(mineVer) && loaderCompatible;
} }
ModrinthResourcePackPage::ModrinthResourcePackPage(ResourcePackDownloadDialog* dialog, BaseInstance& instance) ModrinthResourcePackPage::ModrinthResourcePackPage(ResourcePackDownloadDialog* dialog, BaseInstance& instance)

View File

@ -93,7 +93,7 @@ class ModrinthModPage : public ModPage {
[[nodiscard]] inline auto helpPage() const -> QString override { return "Mod-platform"; } [[nodiscard]] inline auto helpPage() const -> QString override { return "Mod-platform"; }
auto validateVersion(ModPlatform::IndexedVersion& ver, QString mineVer, std::optional<ResourceAPI::ModLoaderTypes> loaders = {}) const auto validateVersion(ModPlatform::IndexedVersion& ver, QString mineVer, std::optional<ModPlatform::ModLoaderTypes> loaders = {}) const
-> bool override; -> bool override;
}; };