Skip to content

Commit

Permalink
Merge pull request PrismLauncher#2547 from Ryex/fix/component-version…
Browse files Browse the repository at this point in the history
…-resolusion

Component version resolusion on Minecraft version change
  • Loading branch information
TheKodeToad authored Sep 8, 2024
2 parents 42eedd1 + c2a2e95 commit 01015a7
Show file tree
Hide file tree
Showing 13 changed files with 592 additions and 84 deletions.
27 changes: 24 additions & 3 deletions launcher/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,11 @@ set(ICONS_SOURCES

# Support for Minecraft instances and launch
set(MINECRAFT_SOURCES

# Logging
minecraft/Logging.h
minecraft/Logging.cpp

# Minecraft support
minecraft/auth/AccountData.cpp
minecraft/auth/AccountData.h
Expand Down Expand Up @@ -663,6 +668,22 @@ ecm_qt_declare_logging_category(CORE_SOURCES
EXPORT "${Launcher_Name}"
)

ecm_qt_export_logging_category(
IDENTIFIER instanceProfileC
CATEGORY_NAME "launcher.instance.profile"
DEFAULT_SEVERITY Debug
DESCRIPTION "Profile actions"
EXPORT "${Launcher_Name}"
)

ecm_qt_export_logging_category(
IDENTIFIER instanceProfileResolveC
CATEGORY_NAME "launcher.instance.profile.resolve"
DEFAULT_SEVERITY Debug
DESCRIPTION "Profile component resolusion actions"
EXPORT "${Launcher_Name}"
)

ecm_qt_export_logging_category(
IDENTIFIER taskLogC
CATEGORY_NAME "launcher.task"
Expand All @@ -675,22 +696,22 @@ ecm_qt_export_logging_category(
IDENTIFIER taskNetLogC
CATEGORY_NAME "launcher.task.net"
DEFAULT_SEVERITY Debug
DESCRIPTION "task network action"
DESCRIPTION "Task network action"
EXPORT "${Launcher_Name}"
)

ecm_qt_export_logging_category(
IDENTIFIER taskDownloadLogC
CATEGORY_NAME "launcher.task.net.download"
DEFAULT_SEVERITY Debug
DESCRIPTION "task network download actions"
DESCRIPTION "Task network download actions"
EXPORT "${Launcher_Name}"
)
ecm_qt_export_logging_category(
IDENTIFIER taskUploadLogC
CATEGORY_NAME "launcher.task.net.upload"
DEFAULT_SEVERITY Debug
DESCRIPTION "task network upload actions"
DESCRIPTION "Task network upload actions"
EXPORT "${Launcher_Name}"
)

Expand Down
44 changes: 43 additions & 1 deletion launcher/meta/VersionList.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include "VersionList.h"

#include <QDateTime>
#include <algorithm>

#include "Application.h"
#include "Index.h"
Expand Down Expand Up @@ -99,7 +100,7 @@ QVariant VersionList::data(const QModelIndex& index, int role) const
case VersionPtrRole:
return QVariant::fromValue(version);
case RecommendedRole:
return version->isRecommended();
return version->isRecommended() || m_externalRecommendsVersions.contains(version->version());
case JavaMajorRole: {
auto major = version->version();
if (major.startsWith("java")) {
Expand Down Expand Up @@ -192,6 +193,16 @@ void VersionList::parse(const QJsonObject& obj)
parseVersionList(obj, this);
}

void VersionList::addExternalRecommends(const QStringList& recommends)
{
m_externalRecommendsVersions.append(recommends);
}

void VersionList::clearExternalRecommends()
{
m_externalRecommendsVersions.clear();
}

// FIXME: this is dumb, we have 'recommended' as part of the metadata already...
static const Meta::Version::Ptr& getBetterVersion(const Meta::Version::Ptr& a, const Meta::Version::Ptr& b)
{
Expand Down Expand Up @@ -276,4 +287,35 @@ void VersionList::waitToLoad()
task->start();
ev.exec();
}

Version::Ptr VersionList::getRecommendedForParent(const QString& uid, const QString& version)
{
auto foundExplicit = std::find_if(m_versions.begin(), m_versions.end(), [uid, version](Version::Ptr ver) -> bool {
auto& reqs = ver->requiredSet();
auto parentReq = std::find_if(reqs.begin(), reqs.end(), [uid, version](const Require& req) -> bool {
return req.uid == uid && req.equalsVersion == version;
});
return parentReq != reqs.end() && ver->isRecommended();
});
if (foundExplicit != m_versions.end()) {
return *foundExplicit;
}
return nullptr;
}

Version::Ptr VersionList::getLatestForParent(const QString& uid, const QString& version)
{
Version::Ptr latestCompat = nullptr;
for (auto ver : m_versions) {
auto& reqs = ver->requiredSet();
auto parentReq = std::find_if(reqs.begin(), reqs.end(), [uid, version](const Require& req) -> bool {
return req.uid == uid && req.equalsVersion == version;
});
if (parentReq != reqs.end()) {
latestCompat = getBetterVersion(latestCompat, ver);
}
}
return latestCompat;
}

} // namespace Meta
5 changes: 5 additions & 0 deletions launcher/meta/VersionList.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ class VersionList : public BaseVersionList, public BaseEntity {
void sortVersions() override;

BaseVersion::Ptr getRecommended() const override;
Version::Ptr getRecommendedForParent(const QString& uid, const QString& version);
Version::Ptr getLatestForParent(const QString& uid, const QString& version);

QVariant data(const QModelIndex& index, int role) const override;
RoleList providesRoles() const override;
Expand Down Expand Up @@ -70,6 +72,8 @@ class VersionList : public BaseVersionList, public BaseEntity {
void merge(const VersionList::Ptr& other);
void mergeFromIndex(const VersionList::Ptr& other);
void parse(const QJsonObject& obj) override;
void addExternalRecommends(const QStringList& recommends);
void clearExternalRecommends();

signals:
void nameChanged(const QString& name);
Expand All @@ -79,6 +83,7 @@ class VersionList : public BaseVersionList, public BaseEntity {

private:
QVector<Version::Ptr> m_versions;
QStringList m_externalRecommendsVersions;
QHash<QString, Version::Ptr> m_lookup;
QString m_uid;
QString m_name;
Expand Down
83 changes: 81 additions & 2 deletions launcher/minecraft/Component.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,19 @@
#include "OneSixVersionFormat.h"
#include "VersionFile.h"
#include "meta/Version.h"
#include "minecraft/Component.h"
#include "minecraft/PackProfile.h"

#include <assert.h>

const QMap<QString, ModloaderMapEntry> Component::KNOWN_MODLOADERS = {
{ "net.neoforged", { ModPlatform::NeoForge, { "net.minecraftforge", "net.fabricmc.fabric-loader", "org.quiltmc.quilt-loader" } } },
{ "net.minecraftforge", { ModPlatform::Forge, { "net.neoforged", "net.fabricmc.fabric-loader", "org.quiltmc.quilt-loader" } } },
{ "net.fabricmc.fabric-loader", { ModPlatform::Fabric, { "net.minecraftforge", "net.neoforged", "org.quiltmc.quilt-loader" } } },
{ "org.quiltmc.quilt-loader", { ModPlatform::Quilt, { "net.minecraftforge", "net.neoforged", "net.fabricmc.fabric-loader" } } },
{ "com.mumfrey.liteloader", { ModPlatform::LiteLoader, {} } }
};

Component::Component(PackProfile* parent, const QString& uid)
{
assert(parent);
Expand Down Expand Up @@ -223,6 +232,22 @@ bool Component::isVersionChangeable()
return false;
}

bool Component::isKnownModloader()
{
auto iter = KNOWN_MODLOADERS.find(m_uid);
return iter != KNOWN_MODLOADERS.cend();
}

QStringList Component::knownConflictingComponents()
{
auto iter = KNOWN_MODLOADERS.find(m_uid);
if (iter != KNOWN_MODLOADERS.cend()) {
return (*iter).knownConflictingComponents;
} else {
return {};
}
}

void Component::setImportant(bool state)
{
if (m_important != state) {
Expand All @@ -235,7 +260,8 @@ ProblemSeverity Component::getProblemSeverity() const
{
auto file = getVersionFile();
if (file) {
return file->getProblemSeverity();
auto severity = file->getProblemSeverity();
return m_componentProblemSeverity > severity ? m_componentProblemSeverity : severity;
}
return ProblemSeverity::Error;
}
Expand All @@ -244,11 +270,31 @@ const QList<PatchProblem> Component::getProblems() const
{
auto file = getVersionFile();
if (file) {
return file->getProblems();
auto problems = file->getProblems();
problems.append(m_componentProblems);
return problems;
}
return { { ProblemSeverity::Error, QObject::tr("Patch is not loaded yet.") } };
}

void Component::addComponentProblem(ProblemSeverity severity, const QString& description)
{
if (severity > m_componentProblemSeverity) {
m_componentProblemSeverity = severity;
}
m_componentProblems.append({ severity, description });

emit dataChanged();
}

void Component::resetComponentProblems()
{
m_componentProblems.clear();
m_componentProblemSeverity = ProblemSeverity::None;

emit dataChanged();
}

void Component::setVersion(const QString& version)
{
if (version == m_version) {
Expand Down Expand Up @@ -402,3 +448,36 @@ void Component::updateCachedData()
emit dataChanged();
}
}

void Component::waitLoadMeta()
{
if (!m_loaded) {
if (!m_metaVersion || !m_metaVersion->isLoaded()) {
// wait for the loaded version from meta
m_metaVersion = APPLICATION->metadataIndex()->getLoadedVersion(m_uid, m_version);
}
m_loaded = true;
updateCachedData();
}
}

void Component::setUpdateAction(UpdateAction action)
{
m_updateAction = action;
}

UpdateAction Component::getUpdateAction()
{
return m_updateAction;
}

void Component::clearUpdateAction()
{
m_updateAction = UpdateAction{ UpdateActionNone{} };
}

QDebug operator<<(QDebug d, const Component& comp)
{
d << "Component(" << comp.m_uid << " : " << comp.m_cachedVersion << ")";
return d;
}
50 changes: 50 additions & 0 deletions launcher/minecraft/Component.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,12 @@
#include <QJsonDocument>
#include <QList>
#include <memory>
#include <optional>
#include <variant>
#include "ProblemProvider.h"
#include "QObjectPtr.h"
#include "meta/JsonFormat.h"
#include "modplatform/ModIndex.h"

class PackProfile;
class LaunchProfile;
Expand All @@ -16,6 +19,36 @@ class VersionList;
} // namespace Meta
class VersionFile;

struct UpdateActionChangeVersion {
/// version to change to
QString targetVersion;
};
struct UpdateActionLatestRecommendedCompatible {
/// Parent uid
QString parentUid;
QString parentName;
/// Parent version
QString version;
///
};
struct UpdateActionRemove {};
struct UpdateActionImportantChanged {
QString oldVersion;
};

using UpdateActionNone = std::monostate;

using UpdateAction = std::variant<UpdateActionNone,
UpdateActionChangeVersion,
UpdateActionLatestRecommendedCompatible,
UpdateActionRemove,
UpdateActionImportantChanged>;

struct ModloaderMapEntry {
ModPlatform::ModLoaderType type;
QStringList knownConflictingComponents;
};

class Component : public QObject, public ProblemProvider {
Q_OBJECT
public:
Expand All @@ -26,6 +59,8 @@ class Component : public QObject, public ProblemProvider {

virtual ~Component() {}

static const QMap<QString, ModloaderMapEntry> KNOWN_MODLOADERS;

void applyTo(LaunchProfile* profile);

bool isEnabled();
Expand All @@ -38,6 +73,8 @@ class Component : public QObject, public ProblemProvider {
bool isRemovable();
bool isCustom();
bool isVersionChangeable();
bool isKnownModloader();
QStringList knownConflictingComponents();

// DEPRECATED: explicit numeric order values, used for loading old non-component config. TODO: refactor and move to migration code
void setOrder(int order);
Expand All @@ -58,13 +95,21 @@ class Component : public QObject, public ProblemProvider {

const QList<PatchProblem> getProblems() const override;
ProblemSeverity getProblemSeverity() const override;
void addComponentProblem(ProblemSeverity severity, const QString& description);
void resetComponentProblems();

void setVersion(const QString& version);
bool customize();
bool revert();

void updateCachedData();

void waitLoadMeta();

void setUpdateAction(UpdateAction action);
void clearUpdateAction();
UpdateAction getUpdateAction();

signals:
void dataChanged();

Expand Down Expand Up @@ -102,6 +147,11 @@ class Component : public QObject, public ProblemProvider {
std::shared_ptr<Meta::Version> m_metaVersion;
std::shared_ptr<VersionFile> m_file;
bool m_loaded = false;

private:
QList<PatchProblem> m_componentProblems;
ProblemSeverity m_componentProblemSeverity = ProblemSeverity::None;
UpdateAction m_updateAction = UpdateAction{ UpdateActionNone{} };
};

using ComponentPtr = shared_qobject_ptr<Component>;
Loading

0 comments on commit 01015a7

Please sign in to comment.