Merge branch 'develop' of https://github.com/PrismLauncher/PrismLauncher into feat/launcher-updater

This commit is contained in:
Trial97
2023-10-09 19:58:43 +03:00
79 changed files with 434 additions and 1382 deletions

View File

@ -1,6 +1,7 @@
#pragma once
#include "minecraft/mod/Mod.h"
#include "minecraft/mod/tasks/GetModDependenciesTask.h"
#include "modplatform/ModIndex.h"
#include "modplatform/ResourceAPI.h"
#include "tasks/Task.h"
@ -23,6 +24,7 @@ class CheckUpdateTask : public Task {
QString old_hash;
QString old_version;
QString new_version;
std::optional<ModPlatform::IndexedVersionType> new_version_type;
QString changelog;
ModPlatform::ResourceProvider provider;
shared_qobject_ptr<ResourceDownloadTask> download;
@ -32,14 +34,23 @@ class CheckUpdateTask : public Task {
QString old_h,
QString old_v,
QString new_v,
std::optional<ModPlatform::IndexedVersionType> new_v_type,
QString changelog,
ModPlatform::ResourceProvider p,
shared_qobject_ptr<ResourceDownloadTask> t)
: name(name), old_hash(old_h), old_version(old_v), new_version(new_v), changelog(changelog), provider(p), download(t)
: name(name)
, old_hash(old_h)
, old_version(old_v)
, new_version(new_v)
, new_version_type(new_v_type)
, changelog(changelog)
, provider(p)
, download(t)
{}
};
auto getUpdatable() -> std::vector<UpdatableMod>&& { return std::move(m_updatable); }
auto getDependencies() -> QList<std::shared_ptr<GetModDependenciesTask::PackDependency>>&& { return std::move(m_deps); }
public slots:
bool abort() override = 0;
@ -57,4 +68,5 @@ class CheckUpdateTask : public Task {
std::shared_ptr<ModFolderModel> m_mods_folder;
std::vector<UpdatableMod> m_updatable;
QList<std::shared_ptr<GetModDependenciesTask::PackDependency>> m_deps;
};

View File

@ -3,6 +3,7 @@
#include <MurmurHash2.h>
#include <QDebug>
#include "Application.h"
#include "Json.h"
#include "minecraft/mod/Mod.h"
@ -33,7 +34,7 @@ EnsureMetadataTask::EnsureMetadataTask(Mod* mod, QDir dir, ModPlatform::Resource
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.reset(new ConcurrentTask(this, "MakeHashesTask", 10));
m_hashing_task.reset(new ConcurrentTask(this, "MakeHashesTask", APPLICATION->settings()->get("NumberOfConcurrentTasks").toInt()));
for (auto* mod : mods) {
auto hash_task = createNewHash(mod);
if (!hash_task)

View File

@ -24,6 +24,40 @@
namespace ModPlatform {
static const QMap<QString, IndexedVersionType::VersionType> s_indexed_version_type_names = {
{ "release", IndexedVersionType::VersionType::Release },
{ "beta", IndexedVersionType::VersionType::Beta },
{ "alpha", IndexedVersionType::VersionType::Alpha }
};
IndexedVersionType::IndexedVersionType(const QString& type) : IndexedVersionType(enumFromString(type)) {}
IndexedVersionType::IndexedVersionType(const IndexedVersionType::VersionType& type)
{
m_type = type;
}
IndexedVersionType::IndexedVersionType(const IndexedVersionType& other)
{
m_type = other.m_type;
}
IndexedVersionType& IndexedVersionType::operator=(const IndexedVersionType& other)
{
m_type = other.m_type;
return *this;
}
const QString IndexedVersionType::toString(const IndexedVersionType::VersionType& type)
{
return s_indexed_version_type_names.key(type, "unknown");
}
IndexedVersionType::VersionType IndexedVersionType::enumFromString(const QString& type)
{
return s_indexed_version_type_names.value(type, IndexedVersionType::VersionType::Unknown);
}
auto ProviderCapabilities::name(ResourceProvider p) -> const char*
{
switch (p) {

View File

@ -25,6 +25,7 @@
#include <QVariant>
#include <QVector>
#include <memory>
#include <optional>
class QIODevice;
@ -58,6 +59,34 @@ struct DonationData {
QString url;
};
struct IndexedVersionType {
enum class VersionType { Release = 1, Beta, Alpha, Unknown };
IndexedVersionType(const QString& type);
IndexedVersionType(const IndexedVersionType::VersionType& type);
IndexedVersionType(const IndexedVersionType& type);
IndexedVersionType() : IndexedVersionType(IndexedVersionType::VersionType::Unknown) {}
static const QString toString(const IndexedVersionType::VersionType& type);
static IndexedVersionType::VersionType enumFromString(const QString& type);
bool isValid() const { return m_type != IndexedVersionType::VersionType::Unknown; }
IndexedVersionType& operator=(const IndexedVersionType& other);
bool operator==(const IndexedVersionType& other) const { return m_type == other.m_type; }
bool operator==(const IndexedVersionType::VersionType& type) const { return m_type == type; }
bool operator!=(const IndexedVersionType& other) const { return m_type != other.m_type; }
bool operator!=(const IndexedVersionType::VersionType& type) const { return m_type != type; }
bool operator<(const IndexedVersionType& other) const { return m_type < other.m_type; }
bool operator<(const IndexedVersionType::VersionType& type) const { return m_type < type; }
bool operator<=(const IndexedVersionType& other) const { return m_type <= other.m_type; }
bool operator<=(const IndexedVersionType::VersionType& type) const { return m_type <= type; }
bool operator>(const IndexedVersionType& other) const { return m_type > other.m_type; }
bool operator>(const IndexedVersionType::VersionType& type) const { return m_type > type; }
bool operator>=(const IndexedVersionType& other) const { return m_type >= other.m_type; }
bool operator>=(const IndexedVersionType::VersionType& type) const { return m_type >= type; }
QString toString() const { return toString(m_type); }
IndexedVersionType::VersionType m_type;
};
struct Dependency {
QVariant addonId;
DependencyType type;
@ -69,6 +98,7 @@ struct IndexedVersion {
QVariant fileId;
QString version;
QString version_number = {};
IndexedVersionType version_type;
QStringList mcVersion;
QString downloadUrl;
QString date;

View File

@ -10,6 +10,7 @@
#include "ResourceDownloadTask.h"
#include "minecraft/mod/ModFolderModel.h"
#include "minecraft/mod/tasks/GetModDependenciesTask.h"
#include "net/ApiDownload.h"
@ -154,18 +155,17 @@ void FlameCheckUpdate::executeTask()
continue;
}
// Fake pack with the necessary info to pass to the download task :)
auto pack = std::make_shared<ModPlatform::IndexedPack>();
pack->name = mod->name();
pack->slug = mod->metadata()->slug;
pack->addonId = mod->metadata()->project_id;
pack->websiteUrl = mod->homeurl();
for (auto& author : mod->authors())
pack->authors.append({ author });
pack->description = mod->description();
pack->provider = ModPlatform::ResourceProvider::FLAME;
if (!latest_ver.hash.isEmpty() && (mod->metadata()->hash != latest_ver.hash || mod->status() == ModStatus::NotInstalled)) {
// Fake pack with the necessary info to pass to the download task :)
auto pack = std::make_shared<ModPlatform::IndexedPack>();
pack->name = mod->name();
pack->slug = mod->metadata()->slug;
pack->addonId = mod->metadata()->project_id;
pack->websiteUrl = mod->homeurl();
for (auto& author : mod->authors())
pack->authors.append({ author });
pack->description = mod->description();
pack->provider = ModPlatform::ResourceProvider::FLAME;
auto old_version = mod->version();
if (old_version.isEmpty() && mod->status() != ModStatus::NotInstalled) {
auto current_ver = getFileInfo(latest_ver.addonId.toInt(), mod->metadata()->file_id.toInt());
@ -173,10 +173,11 @@ void FlameCheckUpdate::executeTask()
}
auto download_task = makeShared<ResourceDownloadTask>(pack, latest_ver, m_mods_folder);
m_updatable.emplace_back(pack->name, mod->metadata()->hash, old_version, latest_ver.version,
m_updatable.emplace_back(pack->name, mod->metadata()->hash, old_version, latest_ver.version, latest_ver.version_type,
api.getModFileChangelog(latest_ver.addonId.toInt(), latest_ver.fileId.toInt()),
ModPlatform::ResourceProvider::FLAME, download_task);
}
m_deps.append(std::make_shared<GetModDependenciesTask::PackDependency>(pack, latest_ver));
}
emitSucceeded();

View File

@ -139,6 +139,22 @@ auto FlameMod::loadIndexedPackVersion(QJsonObject& obj, bool load_changelog) ->
file.downloadUrl = Json::ensureString(obj, "downloadUrl");
file.fileName = Json::requireString(obj, "fileName");
ModPlatform::IndexedVersionType::VersionType ver_type;
switch (Json::requireInteger(obj, "releaseType")) {
case 1:
ver_type = ModPlatform::IndexedVersionType::VersionType::Release;
break;
case 2:
ver_type = ModPlatform::IndexedVersionType::VersionType::Beta;
break;
case 3:
ver_type = ModPlatform::IndexedVersionType::VersionType::Alpha;
break;
default:
ver_type = ModPlatform::IndexedVersionType::VersionType::Unknown;
}
file.version_type = ModPlatform::IndexedVersionType(ver_type);
auto hash_list = Json::ensureArray(obj, "hashes");
for (auto h : hash_list) {
auto hash_entry = Json::ensureObject(h);

View File

@ -28,6 +28,7 @@
#include <algorithm>
#include <iterator>
#include <memory>
#include "Application.h"
#include "Json.h"
#include "MMCZip.h"
#include "minecraft/PackProfile.h"
@ -102,7 +103,8 @@ void FlamePackExportTask::collectHashes()
setStatus(tr("Finding file hashes..."));
setProgress(1, 5);
auto allMods = mcInstance->loaderModList()->allMods();
ConcurrentTask::Ptr hashingTask(new ConcurrentTask(this, "MakeHashesTask", 10));
ConcurrentTask::Ptr hashingTask(
new ConcurrentTask(this, "MakeHashesTask", APPLICATION->settings()->get("NumberOfConcurrentTasks").toInt()));
task.reset(hashingTask);
for (const QFileInfo& file : files) {
const QString relative = gameRoot.relativeFilePath(file.absoluteFilePath());

View File

@ -89,6 +89,22 @@ void Flame::loadIndexedPackVersions(Flame::IndexedPack& pack, QJsonArray& arr)
// pick the latest version supported
file.mcVersion = versionArray[0].toString();
file.version = Json::requireString(version, "displayName");
ModPlatform::IndexedVersionType::VersionType ver_type;
switch (Json::requireInteger(version, "releaseType")) {
case 1:
ver_type = ModPlatform::IndexedVersionType::VersionType::Release;
break;
case 2:
ver_type = ModPlatform::IndexedVersionType::VersionType::Beta;
break;
case 3:
ver_type = ModPlatform::IndexedVersionType::VersionType::Alpha;
break;
default:
ver_type = ModPlatform::IndexedVersionType::VersionType::Unknown;
}
file.version_type = ModPlatform::IndexedVersionType(ver_type);
file.downloadUrl = Json::ensureString(version, "downloadUrl");
// only add if we have a download URL (third party distribution is enabled)

View File

@ -17,6 +17,7 @@ struct IndexedVersion {
int addonId;
int fileId;
QString version;
ModPlatform::IndexedVersionType version_type;
QString mcVersion;
QString downloadUrl;
};

View File

@ -38,7 +38,7 @@ void ModrinthCheckUpdate::executeTask()
QStringList hashes;
auto best_hash_type = ProviderCaps.hashType(ModPlatform::ResourceProvider::MODRINTH).first();
ConcurrentTask hashing_task(this, "MakeModrinthHashesTask", 10);
ConcurrentTask hashing_task(this, "MakeModrinthHashesTask", APPLICATION->settings()->get("NumberOfConcurrentTasks").toInt());
for (auto* mod : m_mods) {
if (!mod->enabled()) {
emit checkFailed(mod, tr("Disabled mods won't be updated, to prevent mod duplication issues!"));
@ -144,26 +144,27 @@ void ModrinthCheckUpdate::executeTask()
auto mod = *mod_iter;
auto key = project_ver.hash;
// Fake pack with the necessary info to pass to the download task :)
auto pack = std::make_shared<ModPlatform::IndexedPack>();
pack->name = mod->name();
pack->slug = mod->metadata()->slug;
pack->addonId = mod->metadata()->project_id;
pack->websiteUrl = mod->homeurl();
for (auto& author : mod->authors())
pack->authors.append({ author });
pack->description = mod->description();
pack->provider = ModPlatform::ResourceProvider::MODRINTH;
if ((key != hash && project_ver.is_preferred) || (mod->status() == ModStatus::NotInstalled)) {
if (mod->version() == project_ver.version_number)
continue;
// Fake pack with the necessary info to pass to the download task :)
auto pack = std::make_shared<ModPlatform::IndexedPack>();
pack->name = mod->name();
pack->slug = mod->metadata()->slug;
pack->addonId = mod->metadata()->project_id;
pack->websiteUrl = mod->homeurl();
for (auto& author : mod->authors())
pack->authors.append({ author });
pack->description = mod->description();
pack->provider = ModPlatform::ResourceProvider::MODRINTH;
auto download_task = makeShared<ResourceDownloadTask>(pack, project_ver, m_mods_folder);
m_updatable.emplace_back(pack->name, hash, mod->version(), project_ver.version_number, project_ver.changelog,
ModPlatform::ResourceProvider::MODRINTH, download_task);
m_updatable.emplace_back(pack->name, hash, mod->version(), project_ver.version_number, project_ver.version_type,
project_ver.changelog, ModPlatform::ResourceProvider::MODRINTH, download_task);
}
m_deps.append(std::make_shared<GetModDependenciesTask::PackDependency>(pack, project_ver));
}
} catch (Json::JsonException& e) {
failed(e.cause() + " : " + e.what());

View File

@ -149,6 +149,8 @@ auto Modrinth::loadIndexedPackVersion(QJsonObject& obj, QString preferred_hash_t
}
file.version = Json::requireString(obj, "name");
file.version_number = Json::requireString(obj, "version_number");
file.version_type = ModPlatform::IndexedVersionType(Json::requireString(obj, "version_type"));
file.changelog = Json::requireString(obj, "changelog");
auto dependencies = Json::ensureArray(obj, "dependencies");

View File

@ -111,8 +111,9 @@ void loadIndexedVersions(Modpack& pack, QJsonDocument& doc)
unsortedVersions.append(file);
}
auto orderSortPredicate = [](const ModpackVersion& a, const ModpackVersion& b) -> bool {
bool a_better_release = a.version_type <= b.version_type;
// dates are in RFC 3339 format
return a.date > b.date;
return a.date > b.date && a_better_release;
};
std::sort(unsortedVersions.begin(), unsortedVersions.end(), orderSortPredicate);
@ -128,6 +129,7 @@ auto loadIndexedVersion(QJsonObject& obj) -> ModpackVersion
file.name = Json::requireString(obj, "name");
file.version = Json::requireString(obj, "version_number");
file.version_type = ModPlatform::IndexedVersionType(Json::requireString(obj, "version_type"));
file.changelog = Json::ensureString(obj, "changelog");
file.id = Json::requireString(obj, "id");

View File

@ -45,6 +45,8 @@
#include <QUrl>
#include <QVector>
#include "modplatform/ModIndex.h"
class MinecraftInstance;
namespace Modrinth {
@ -79,6 +81,7 @@ struct ModpackExtra {
struct ModpackVersion {
QString name;
QString version;
ModPlatform::IndexedVersionType version_type;
QString changelog;
QString id;