NOISSUE Rough refactor of ProfilePatch and VersionFile internals.

They are now distinct classes with distinct responsibilities.

* ProfilePatch is an entry in MinecraftProfile and can hold VersionFile or Meta::Version.
* VersionFile is the basic element that holds version information loaded from JSON.
* Meta::Version is the loader class for VersionFile(s) from a server.
This commit is contained in:
Petr Mrázek 2017-03-27 03:34:39 +02:00
parent 6f2a87167a
commit 5fabb4f254
22 changed files with 431 additions and 374 deletions

View File

@ -93,7 +93,7 @@ QHash<int, QByteArray> BaseVersionList::roleNames() const
QHash<int, QByteArray> roles = QAbstractListModel::roleNames(); QHash<int, QByteArray> roles = QAbstractListModel::roleNames();
roles.insert(VersionRole, "version"); roles.insert(VersionRole, "version");
roles.insert(VersionIdRole, "versionId"); roles.insert(VersionIdRole, "versionId");
roles.insert(ParentGameVersionRole, "parentGameVersion"); roles.insert(ParentVersionRole, "parentGameVersion");
roles.insert(RecommendedRole, "recommended"); roles.insert(RecommendedRole, "recommended");
roles.insert(LatestRole, "latest"); roles.insert(LatestRole, "latest");
roles.insert(TypeRole, "type"); roles.insert(TypeRole, "type");

View File

@ -45,7 +45,7 @@ public:
VersionPointerRole = Qt::UserRole, VersionPointerRole = Qt::UserRole,
VersionRole, VersionRole,
VersionIdRole, VersionIdRole,
ParentGameVersionRole, ParentVersionRole,
RecommendedRole, RecommendedRole,
LatestRole, LatestRole,
TypeRole, TypeRole,

View File

@ -267,6 +267,7 @@ set(MINECRAFT_SOURCES
minecraft/VersionBuildError.h minecraft/VersionBuildError.h
minecraft/VersionFile.cpp minecraft/VersionFile.cpp
minecraft/VersionFile.h minecraft/VersionFile.h
minecraft/ProfilePatch.cpp
minecraft/ProfilePatch.h minecraft/ProfilePatch.h
minecraft/VersionFilterData.h minecraft/VersionFilterData.h
minecraft/VersionFilterData.cpp minecraft/VersionFilterData.cpp

View File

@ -0,0 +1,54 @@
#pragma once
enum class ProblemSeverity
{
None,
Warning,
Error
};
class PatchProblem
{
public:
PatchProblem(ProblemSeverity severity, const QString & description)
{
m_severity = severity;
m_description = description;
}
const QString & getDescription() const
{
return m_description;
}
const ProblemSeverity getSeverity() const
{
return m_severity;
}
private:
ProblemSeverity m_severity;
QString m_description;
};
class ProblemProvider
{
public:
virtual const QList<PatchProblem>& getProblems()
{
return m_problems;
}
virtual void addProblem(ProblemSeverity severity, const QString &description)
{
if(severity > m_problemSeverity)
{
m_problemSeverity = severity;
}
m_problems.append(PatchProblem(severity, description));
}
virtual ProblemSeverity getProblemSeverity()
{
return m_problemSeverity;
}
private:
QList<PatchProblem> m_problems;
ProblemSeverity m_problemSeverity = ProblemSeverity::None;
};

View File

@ -32,7 +32,7 @@ QString Meta::Version::descriptor()
QString Meta::Version::name() QString Meta::Version::name()
{ {
if(m_data) if(m_data)
return m_data->getName(); return m_data->name;
return m_uid; return m_uid;
} }
QString Meta::Version::typeString() const QString Meta::Version::typeString() const

View File

@ -73,7 +73,7 @@ QVariant VersionList::data(const QModelIndex &index, int role) const
case VersionRole: case VersionRole:
case VersionIdRole: case VersionIdRole:
return version->version(); return version->version();
case ParentGameVersionRole: case ParentVersionRole:
{ {
auto parentUid = this->parentUid(); auto parentUid = this->parentUid();
if(parentUid.isEmpty()) if(parentUid.isEmpty())
@ -102,7 +102,7 @@ QVariant VersionList::data(const QModelIndex &index, int role) const
BaseVersionList::RoleList VersionList::providesRoles() const BaseVersionList::RoleList VersionList::providesRoles() const
{ {
return {VersionPointerRole, VersionRole, VersionIdRole, ParentGameVersionRole, return {VersionPointerRole, VersionRole, VersionIdRole, ParentVersionRole,
TypeRole, UidRole, TimeRole, RequiresRole, SortRole, TypeRole, UidRole, TimeRole, RequiresRole, SortRole,
RecommendedRole, LatestRole, VersionPtrRole}; RecommendedRole, LatestRole, VersionPtrRole};
} }

View File

@ -80,7 +80,7 @@ void MinecraftProfile::clear()
m_traits.clear(); m_traits.clear();
m_jarMods.clear(); m_jarMods.clear();
mojangDownloads.clear(); mojangDownloads.clear();
m_problemSeverity = ProblemSeverity::PROBLEM_NONE; m_problemSeverity = ProblemSeverity::None;
} }
void MinecraftProfile::clearPatches() void MinecraftProfile::clearPatches()
@ -273,9 +273,9 @@ QVariant MinecraftProfile::data(const QModelIndex &index, int role) const
auto severity = patch->getProblemSeverity(); auto severity = patch->getProblemSeverity();
switch (severity) switch (severity)
{ {
case PROBLEM_WARNING: case ProblemSeverity::Warning:
return "warning"; return "warning";
case PROBLEM_ERROR: case ProblemSeverity::Error:
return "error"; return "error";
default: default:
return QVariant(); return QVariant();

View File

@ -22,7 +22,7 @@
#include <memory> #include <memory>
#include "Library.h" #include "Library.h"
#include "VersionFile.h" #include "ProfilePatch.h"
#include "JarMod.h" #include "JarMod.h"
#include "BaseVersion.h" #include "BaseVersion.h"
#include "MojangDownloadInfo.h" #include "MojangDownloadInfo.h"
@ -175,7 +175,7 @@ private: /* data */
/// A list of jar mods. version files can add those. /// A list of jar mods. version files can add those.
QList<JarmodPtr> m_jarMods; QList<JarmodPtr> m_jarMods;
ProblemSeverity m_problemSeverity = PROBLEM_NONE; ProblemSeverity m_problemSeverity = ProblemSeverity::None;
/* /*
FIXME: add support for those rules here? Looks like a pile of quick hacks to me though. FIXME: add support for those rules here? Looks like a pile of quick hacks to me though.

View File

@ -151,7 +151,7 @@ void MojangVersionFormat::readVersionProperties(const QJsonObject &in, VersionFi
} }
else if (!toCompare.isEmpty()) else if (!toCompare.isEmpty())
{ {
out->addProblem(PROBLEM_ERROR, QObject::tr("processArguments is set to unknown value '%1'").arg(processArguments)); out->addProblem(ProblemSeverity::Error, QObject::tr("processArguments is set to unknown value '%1'").arg(processArguments));
} }
} }
Bits::readString(in, "type", out->type); Bits::readString(in, "type", out->type);
@ -166,8 +166,8 @@ void MojangVersionFormat::readVersionProperties(const QJsonObject &in, VersionFi
out->mojangAssetIndex = std::make_shared<MojangAssetIndexInfo>(out->assets); out->mojangAssetIndex = std::make_shared<MojangAssetIndexInfo>(out->assets);
} }
out->m_releaseTime = timeFromS3Time(in.value("releaseTime").toString("")); out->releaseTime = timeFromS3Time(in.value("releaseTime").toString(""));
out->m_updateTime = timeFromS3Time(in.value("time").toString("")); out->updateTime = timeFromS3Time(in.value("time").toString(""));
if (in.contains("minimumLauncherVersion")) if (in.contains("minimumLauncherVersion"))
{ {
@ -175,7 +175,7 @@ void MojangVersionFormat::readVersionProperties(const QJsonObject &in, VersionFi
if (out->minimumLauncherVersion > CURRENT_MINIMUM_LAUNCHER_VERSION) if (out->minimumLauncherVersion > CURRENT_MINIMUM_LAUNCHER_VERSION)
{ {
out->addProblem( out->addProblem(
PROBLEM_WARNING, ProblemSeverity::Warning,
QObject::tr("The 'minimumLauncherVersion' value of this version (%1) is higher than supported by MultiMC (%2). It might not work properly!") QObject::tr("The 'minimumLauncherVersion' value of this version (%1) is higher than supported by MultiMC (%2). It might not work properly!")
.arg(out->minimumLauncherVersion) .arg(out->minimumLauncherVersion)
.arg(CURRENT_MINIMUM_LAUNCHER_VERSION)); .arg(CURRENT_MINIMUM_LAUNCHER_VERSION));
@ -212,7 +212,7 @@ VersionFilePtr MojangVersionFormat::versionFileFromJson(const QJsonDocument &doc
out->name = "Minecraft"; out->name = "Minecraft";
out->uid = "net.minecraft"; out->uid = "net.minecraft";
out->version = out->minecraftVersion; out->version = out->minecraftVersion;
out->filename = filename; // out->filename = filename;
if (root.contains("libraries")) if (root.contains("libraries"))
@ -234,13 +234,13 @@ void MojangVersionFormat::writeVersionProperties(const VersionFile* in, QJsonObj
writeString(out, "mainClass", in->mainClass); writeString(out, "mainClass", in->mainClass);
writeString(out, "minecraftArguments", in->minecraftArguments); writeString(out, "minecraftArguments", in->minecraftArguments);
writeString(out, "type", in->type); writeString(out, "type", in->type);
if(!in->m_releaseTime.isNull()) if(!in->releaseTime.isNull())
{ {
writeString(out, "releaseTime", timeToS3Time(in->m_releaseTime)); writeString(out, "releaseTime", timeToS3Time(in->releaseTime));
} }
if(!in->m_updateTime.isNull()) if(!in->updateTime.isNull())
{ {
writeString(out, "time", timeToS3Time(in->m_updateTime)); writeString(out, "time", timeToS3Time(in->updateTime));
} }
if(in->minimumLauncherVersion != -1) if(in->minimumLauncherVersion != -1)
{ {

View File

@ -0,0 +1,214 @@
#include "ProfilePatch.h"
#include "meta/Version.h"
#include "VersionFile.h"
ProfilePatch::ProfilePatch(std::shared_ptr<Meta::Version> version)
:m_metaVersion(version)
{
}
ProfilePatch::ProfilePatch(std::shared_ptr<VersionFile> file, const QString& filename)
:m_file(file), m_filename(filename)
{
}
void ProfilePatch::applyTo(MinecraftProfile* profile)
{
auto vfile = getVersionFile();
if(vfile)
{
vfile->applyTo(profile);
}
}
std::shared_ptr<class VersionFile> ProfilePatch::getVersionFile()
{
if(m_metaVersion)
{
if(!m_metaVersion->isLoaded())
{
m_metaVersion->load();
}
return m_metaVersion->data();
}
return m_file;
}
int ProfilePatch::getOrder()
{
if(m_orderOverride)
return m_order;
auto vfile = getVersionFile();
if(vfile)
{
return vfile->order;
}
return 0;
}
void ProfilePatch::setOrder(int order)
{
m_orderOverride = true;
m_order = order;
}
QString ProfilePatch::getID()
{
if(m_metaVersion)
return m_metaVersion->uid();
return getVersionFile()->uid;
}
QString ProfilePatch::getName()
{
if(m_metaVersion)
return m_metaVersion->name();
return getVersionFile()->name;
}
QString ProfilePatch::getVersion()
{
if(m_metaVersion)
return m_metaVersion->version();
return getVersionFile()->version;
}
QString ProfilePatch::getFilename()
{
return m_filename;
}
QDateTime ProfilePatch::getReleaseDateTime()
{
if(m_metaVersion)
{
return m_metaVersion->time();
}
return getVersionFile()->releaseTime;
}
bool ProfilePatch::isCustom()
{
return !m_isVanilla;
};
bool ProfilePatch::isCustomizable()
{
if(m_metaVersion)
{
if(getVersionFile())
{
return true;
}
}
return false;
}
bool ProfilePatch::isRemovable()
{
return m_isRemovable;
}
bool ProfilePatch::isRevertible()
{
return m_isRevertible;
}
bool ProfilePatch::isMoveable()
{
return m_isMovable;
}
bool ProfilePatch::isVersionChangeable()
{
return false;
}
void ProfilePatch::setVanilla (bool state)
{
m_isVanilla = state;
}
void ProfilePatch::setRemovable (bool state)
{
m_isRemovable = state;
}
void ProfilePatch::setRevertible (bool state)
{
m_isRevertible = state;
}
void ProfilePatch::setMovable (bool state)
{
m_isMovable = state;
}
/*
class MetaPatchProvider : public ProfilePatch
{
public:
MetaPatchProvider(std::shared_ptr<Meta::Version> data)
:m_version(data)
{
}
public:
QString getFilename() override
{
return QString();
}
QString getID() override
{
return m_version->uid();
}
QString getName() override
{
auto vfile = getFile();
if(vfile)
{
return vfile->name;
}
return m_version->name();
}
QDateTime getReleaseDateTime() override
{
return m_version->time();
}
QString getVersion() override
{
return m_version->version();
}
std::shared_ptr<class VersionFile> getVersionFile() override
{
return m_version->data();
}
void setOrder(int) override
{
}
int getOrder() override
{
return 0;
}
bool isVersionChangeable() override
{
return true;
}
bool isRevertible() override
{
return false;
}
bool isRemovable() override
{
return true;
}
bool isCustom() override
{
return false;
}
bool isCustomizable() override
{
return true;
}
bool isMoveable() override
{
return true;
}
private:
VersionFilePtr getFile()
{
}
private:
std::shared_ptr<Meta::Version> m_version;
};
*/

View File

@ -5,85 +5,63 @@
#include <QJsonDocument> #include <QJsonDocument>
#include <QDateTime> #include <QDateTime>
#include "JarMod.h" #include "JarMod.h"
#include "ProblemProvider.h"
class MinecraftProfile; class MinecraftProfile;
namespace Meta
enum ProblemSeverity
{ {
PROBLEM_NONE, class Version;
PROBLEM_WARNING, }
PROBLEM_ERROR class VersionFile;
};
class PatchProblem class ProfilePatch : public ProblemProvider
{ {
public: public:
PatchProblem(ProblemSeverity severity, const QString & description) ProfilePatch(std::shared_ptr<Meta::Version> version);
{ ProfilePatch(std::shared_ptr<VersionFile> file, const QString &filename = QString());
m_severity = severity;
m_description = description;
}
const QString & getDescription() const
{
return m_description;
}
const ProblemSeverity getSeverity() const
{
return m_severity;
}
private:
ProblemSeverity m_severity;
QString m_description;
};
class ProfilePatch : public std::enable_shared_from_this<ProfilePatch>
{
public:
virtual ~ProfilePatch(){}; virtual ~ProfilePatch(){};
virtual void applyTo(MinecraftProfile *profile) = 0; virtual void applyTo(MinecraftProfile *profile);
virtual bool isMinecraftVersion() = 0; virtual bool isMoveable();
virtual bool isCustomizable();
virtual bool isRevertible();
virtual bool isRemovable();
virtual bool isCustom();
virtual bool isVersionChangeable();
virtual bool isMoveable() = 0; virtual void setOrder(int order);
virtual bool isCustomizable() = 0; virtual int getOrder();
virtual bool isRevertible() = 0;
virtual bool isRemovable() = 0;
virtual bool isCustom() = 0;
virtual bool isEditable() = 0;
virtual bool isVersionChangeable() = 0;
virtual void setOrder(int order) = 0; virtual QString getID();
virtual int getOrder() = 0; virtual QString getName();
virtual QString getVersion();
virtual QDateTime getReleaseDateTime();
virtual QString getID() = 0; virtual QString getFilename();
virtual QString getName() = 0;
virtual QString getVersion() = 0;
virtual QDateTime getReleaseDateTime() = 0;
virtual QString getFilename() = 0; virtual std::shared_ptr<class VersionFile> getVersionFile();
virtual std::shared_ptr<class VersionFile> getVersionFile() = 0; void setVanilla (bool state);
void setRemovable (bool state);
virtual const QList<PatchProblem>& getProblems() void setRevertible (bool state);
{ void setCustomizable (bool state);
return m_problems; void setMovable (bool state);
}
virtual void addProblem(ProblemSeverity severity, const QString &description)
{
if(severity > m_problemSeverity)
{
m_problemSeverity = severity;
}
m_problems.append(PatchProblem(severity, description));
}
virtual ProblemSeverity getProblemSeverity()
{
return m_problemSeverity;
}
protected: protected:
QList<PatchProblem> m_problems; // Properties for UI and version manipulation from UI in general
ProblemSeverity m_problemSeverity = PROBLEM_NONE; bool m_isMovable = false;
bool m_isCustomizable = false;
bool m_isRevertible = false;
bool m_isRemovable = false;
bool m_isVanilla = false;
bool m_orderOverride = false;
int m_order = 0;
std::shared_ptr<Meta::Version> m_metaVersion;
std::shared_ptr<VersionFile> m_file;
QString m_filename;
}; };
typedef std::shared_ptr<ProfilePatch> ProfilePatchPtr; typedef std::shared_ptr<ProfilePatch> ProfilePatchPtr;

View File

@ -1,6 +1,7 @@
#pragma once #pragma once
#include "ProfileUtils.h" #include "ProfileUtils.h"
#include "ProfilePatch.h"
class MinecraftProfile; class MinecraftProfile;

View File

@ -103,8 +103,8 @@ static VersionFilePtr createErrorVersionFile(QString fileId, QString filepath, Q
{ {
auto outError = std::make_shared<VersionFile>(); auto outError = std::make_shared<VersionFile>();
outError->uid = outError->name = fileId; outError->uid = outError->name = fileId;
outError->filename = filepath; // outError->filename = filepath;
outError->addProblem(PROBLEM_ERROR, error); outError->addProblem(ProblemSeverity::Error, error);
return outError; return outError;
} }

View File

@ -26,23 +26,6 @@ public:
} }
}; };
/**
* some patch was intended for a different version of minecraft
*/
class MinecraftVersionMismatch : public VersionBuildError
{
public:
MinecraftVersionMismatch(QString fileId, QString mcVersion, QString parentMcVersion)
: VersionBuildError(QObject::tr("The patch %1 is for a different version of Minecraft "
"(%2) than that of the instance (%3).")
.arg(fileId)
.arg(mcVersion)
.arg(parentMcVersion)) {};
virtual ~MinecraftVersionMismatch() noexcept
{
}
};
/** /**
* files required for the version are not (yet?) present * files required for the version are not (yet?) present
*/ */

View File

@ -12,32 +12,28 @@
#include "VersionBuildError.h" #include "VersionBuildError.h"
#include <Version.h> #include <Version.h>
bool VersionFile::isMinecraftVersion() static bool isMinecraftVersion(const QString &uid)
{ {
return uid == "net.minecraft"; return uid == "net.minecraft";
} }
void VersionFile::applyTo(MinecraftProfile *profile) void VersionFile::applyTo(MinecraftProfile *profile)
{ {
auto theirVersion = profile->getMinecraftVersion(); // Only real Minecraft can set those. Don't let anything override them.
if (!theirVersion.isNull() && !dependsOnMinecraftVersion.isNull()) if (isMinecraftVersion(uid))
{ {
if (QRegExp(dependsOnMinecraftVersion, Qt::CaseInsensitive, QRegExp::Wildcard).indexIn(theirVersion) == -1) profile->applyMinecraftVersion(minecraftVersion);
{ profile->applyMinecraftVersionType(type);
throw MinecraftVersionMismatch(uid, dependsOnMinecraftVersion, theirVersion); // HACK: ignore assets from other version files than Minecraft
} // workaround for stupid assets issue caused by amazon:
// https://www.theregister.co.uk/2017/02/28/aws_is_awol_as_s3_goes_haywire/
profile->applyMinecraftAssets(mojangAssetIndex);
} }
profile->applyMinecraftVersion(minecraftVersion);
profile->applyMainClass(mainClass); profile->applyMainClass(mainClass);
profile->applyAppletClass(appletClass); profile->applyAppletClass(appletClass);
profile->applyMinecraftArguments(minecraftArguments); profile->applyMinecraftArguments(minecraftArguments);
if (isMinecraftVersion())
{
profile->applyMinecraftVersionType(type);
}
profile->applyMinecraftAssets(mojangAssetIndex);
profile->applyTweakers(addTweakers); profile->applyTweakers(addTweakers);
profile->applyJarMods(jarMods); profile->applyJarMods(jarMods);
profile->applyTraits(traits); profile->applyTraits(traits);
@ -53,3 +49,14 @@ void VersionFile::applyTo(MinecraftProfile *profile)
iter++; iter++;
} }
} }
/*
auto theirVersion = profile->getMinecraftVersion();
if (!theirVersion.isNull() && !dependsOnMinecraftVersion.isNull())
{
if (QRegExp(dependsOnMinecraftVersion, Qt::CaseInsensitive, QRegExp::Wildcard).indexIn(theirVersion) == -1)
{
throw MinecraftVersionMismatch(uid, dependsOnMinecraftVersion, theirVersion);
}
}
*/

View File

@ -8,7 +8,7 @@
#include <memory> #include <memory>
#include "minecraft/OpSys.h" #include "minecraft/OpSys.h"
#include "minecraft/Rule.h" #include "minecraft/Rule.h"
#include "ProfilePatch.h" #include "ProblemProvider.h"
#include "Library.h" #include "Library.h"
#include "JarMod.h" #include "JarMod.h"
@ -18,111 +18,19 @@ struct MojangDownloadInfo;
struct MojangAssetIndexInfo; struct MojangAssetIndexInfo;
typedef std::shared_ptr<VersionFile> VersionFilePtr; typedef std::shared_ptr<VersionFile> VersionFilePtr;
class VersionFile : public ProfilePatch class VersionFile : public ProblemProvider
{ {
friend class MojangVersionFormat; friend class MojangVersionFormat;
friend class OneSixVersionFormat; friend class OneSixVersionFormat;
public: /* methods */ public: /* methods */
virtual void applyTo(MinecraftProfile *profile) override; void applyTo(MinecraftProfile *profile);
virtual bool isMinecraftVersion() override;
virtual int getOrder() override
{
return order;
}
virtual void setOrder(int order) override
{
this->order = order;
}
virtual QString getID() override
{
return uid;
}
virtual QString getName() override
{
return name;
}
virtual QString getVersion() override
{
return version;
}
virtual QString getFilename() override
{
return filename;
}
virtual QDateTime getReleaseDateTime() override
{
return m_releaseTime;
}
std::shared_ptr<class VersionFile> getVersionFile() override
{
return std::dynamic_pointer_cast<VersionFile>(shared_from_this());
}
virtual bool isCustom() override
{
return !m_isVanilla;
};
virtual bool isCustomizable() override
{
return m_isCustomizable;
}
virtual bool isRemovable() override
{
return m_isRemovable;
}
virtual bool isRevertible() override
{
return m_isRevertible;
}
virtual bool isMoveable() override
{
return m_isMovable;
}
virtual bool isEditable() override
{
return isCustom();
}
virtual bool isVersionChangeable() override
{
return false;
}
void setVanilla (bool state)
{
m_isVanilla = state;
}
void setRemovable (bool state)
{
m_isRemovable = state;
}
void setRevertible (bool state)
{
m_isRevertible = state;
}
void setCustomizable (bool state)
{
m_isCustomizable = state;
}
void setMovable (bool state)
{
m_isMovable = state;
}
public: /* data */ public: /* data */
// Flags for UI and version file manipulation in general
bool m_isVanilla = false;
bool m_isRemovable = false;
bool m_isRevertible = false;
bool m_isCustomizable = false;
bool m_isMovable = false;
/// MultiMC: order hint for this version file if no explicit order is set /// MultiMC: order hint for this version file if no explicit order is set
int order = 0; int order = 0;
/// MultiMC: filename of the file this was loaded from /// MultiMC: filename of the file this was loaded from
QString filename; // QString filename;
/// MultiMC: human readable name of this package /// MultiMC: human readable name of this package
QString name; QString name;
@ -139,13 +47,13 @@ public: /* data */
/// Mojang: used to version the Mojang version format /// Mojang: used to version the Mojang version format
int minimumLauncherVersion = -1; int minimumLauncherVersion = -1;
/// Mojang: version of Minecraft this is /// Mojang: DEPRECATED version of Minecraft this is
QString minecraftVersion; QString minecraftVersion;
/// Mojang: class to launch Minecraft with /// Mojang: class to launch Minecraft with
QString mainClass; QString mainClass;
/// MultiMC: DEPRECATED class to launch legacy Minecraft with (ambed in a custom window) /// MultiMC: class to launch legacy Minecraft with (embed in a custom window)
QString appletClass; QString appletClass;
/// Mojang: Minecraft launch arguments (may contain placeholders for variable substitution) /// Mojang: Minecraft launch arguments (may contain placeholders for variable substitution)
@ -155,10 +63,10 @@ public: /* data */
QString type; QString type;
/// Mojang: the time this version was actually released by Mojang /// Mojang: the time this version was actually released by Mojang
QDateTime m_releaseTime; QDateTime releaseTime;
/// Mojang: the time this version was last updated by Mojang /// Mojang: the time this version was last updated by Mojang
QDateTime m_updateTime; QDateTime updateTime;
/// Mojang: DEPRECATED asset group to be used with Minecraft /// Mojang: DEPRECATED asset group to be used with Minecraft
QString assets; QString assets;

View File

@ -29,7 +29,6 @@ void FTBProfileStrategy::loadDefaultBuiltinPatches()
auto file = ProfileUtils::parseJsonFile(QFileInfo(mcJson), false); auto file = ProfileUtils::parseJsonFile(QFileInfo(mcJson), false);
file->uid = "net.minecraft"; file->uid = "net.minecraft";
file->name = QObject::tr("Minecraft (tracked)"); file->name = QObject::tr("Minecraft (tracked)");
file->setVanilla(true);
if(file->version.isEmpty()) if(file->version.isEmpty())
{ {
file->version = mcVersion; file->version = mcVersion;
@ -39,7 +38,8 @@ void FTBProfileStrategy::loadDefaultBuiltinPatches()
addLib->setHint("local"); addLib->setHint("local");
addLib->setStoragePrefix(nativeInstance->librariesPath().absolutePath()); addLib->setStoragePrefix(nativeInstance->librariesPath().absolutePath());
} }
minecraftPatch = std::dynamic_pointer_cast<ProfilePatch>(file); minecraftPatch = std::make_shared<ProfilePatch>(file);
minecraftPatch->setVanilla(true);
} }
else else
{ {
@ -65,7 +65,6 @@ void FTBProfileStrategy::loadDefaultBuiltinPatches()
addLib->setStoragePrefix(nativeInstance->librariesPath().absolutePath()); addLib->setStoragePrefix(nativeInstance->librariesPath().absolutePath());
} }
file->uid = "org.multimc.ftb.pack"; file->uid = "org.multimc.ftb.pack";
file->setVanilla(true);
file->name = QObject::tr("%1 (FTB pack)").arg(m_instance->name()); file->name = QObject::tr("%1 (FTB pack)").arg(m_instance->name());
if(file->version.isEmpty()) if(file->version.isEmpty())
{ {
@ -81,7 +80,8 @@ void FTBProfileStrategy::loadDefaultBuiltinPatches()
} }
} }
} }
packPatch = std::dynamic_pointer_cast<ProfilePatch>(file); packPatch = std::make_shared<ProfilePatch>(file);
packPatch->setVanilla(true);
} }
else else
{ {

View File

@ -523,7 +523,7 @@ QString OneSixInstance::currentVersionId() const
void OneSixInstance::reloadProfile() void OneSixInstance::reloadProfile()
{ {
m_profile->reload(); m_profile->reload();
setVersionBroken(m_profile->getProblemSeverity() == ProblemSeverity::PROBLEM_ERROR); setVersionBroken(m_profile->getProblemSeverity() == ProblemSeverity::Error);
emit versionReloaded(); emit versionReloaded();
} }

View File

@ -15,6 +15,8 @@
#include <meta/Index.h> #include <meta/Index.h>
#include <meta/Version.h> #include <meta/Version.h>
#include <tuple>
OneSixProfileStrategy::OneSixProfileStrategy(OneSixInstance* instance) OneSixProfileStrategy::OneSixProfileStrategy(OneSixInstance* instance)
{ {
m_instance = instance; m_instance = instance;
@ -81,103 +83,6 @@ void OneSixProfileStrategy::upgradeDeprecatedFiles()
} }
} }
class MetaPatchProvider : public ProfilePatch
{
public: /* con/des */
MetaPatchProvider(std::shared_ptr<Meta::Version> data)
:m_version(data)
{
}
public:
QString getFilename() override
{
return QString();
}
QString getID() override
{
return m_version->uid();
}
QString getName() override
{
auto vfile = getFile();
if(vfile)
{
return vfile->getName();
}
return m_version->name();
}
QDateTime getReleaseDateTime() override
{
return m_version->time();
}
QString getVersion() override
{
return m_version->version();
}
std::shared_ptr<class VersionFile> getVersionFile() override
{
return m_version->data();
}
void setOrder(int) override
{
}
int getOrder() override
{
return 0;
}
bool isVersionChangeable() override
{
return true;
}
bool isRevertible() override
{
return false;
}
bool isRemovable() override
{
return true;
}
bool isCustom() override
{
return false;
}
bool isCustomizable() override
{
return true;
}
bool isMoveable() override
{
return true;
}
bool isEditable() override
{
return false;
}
bool isMinecraftVersion() override
{
return getID() == "net.minecraft";
}
void applyTo(MinecraftProfile * profile) override
{
auto vfile = getFile();
if(vfile)
{
vfile->applyTo(profile);
}
}
private:
VersionFilePtr getFile()
{
if(!m_version->isLoaded())
{
m_version->load();
}
return m_version->data();
}
private:
std::shared_ptr<Meta::Version> m_version;
};
void OneSixProfileStrategy::loadDefaultBuiltinPatches() void OneSixProfileStrategy::loadDefaultBuiltinPatches()
{ {
{ {
@ -191,14 +96,15 @@ void OneSixProfileStrategy::loadDefaultBuiltinPatches()
{ {
file->version = m_instance->intendedVersionId(); file->version = m_instance->intendedVersionId();
} }
file->setVanilla(false); minecraftPatch = std::make_shared<ProfilePatch>(file, mcJson);
file->setRevertible(true); minecraftPatch->setVanilla(false);
minecraftPatch = std::dynamic_pointer_cast<ProfilePatch>(file); minecraftPatch->setRevertible(true);
} }
else else
{ {
auto mcversion = ENV.metadataIndex()->get("net.minecraft", m_instance->intendedVersionId()); auto mcversion = ENV.metadataIndex()->get("net.minecraft", m_instance->intendedVersionId());
minecraftPatch = std::make_shared<MetaPatchProvider>(mcversion); minecraftPatch = std::make_shared<ProfilePatch>(mcversion);
minecraftPatch->setVanilla(true);
} }
if (!minecraftPatch) if (!minecraftPatch)
{ {
@ -214,14 +120,15 @@ void OneSixProfileStrategy::loadDefaultBuiltinPatches()
if(QFile::exists(lwjglJson)) if(QFile::exists(lwjglJson))
{ {
auto file = ProfileUtils::parseJsonFile(QFileInfo(lwjglJson), false); auto file = ProfileUtils::parseJsonFile(QFileInfo(lwjglJson), false);
file->setVanilla(false); lwjglPatch = std::make_shared<ProfilePatch>(file, lwjglJson);
file->setRevertible(true); lwjglPatch->setVanilla(false);
lwjglPatch = std::dynamic_pointer_cast<ProfilePatch>(file); lwjglPatch->setRevertible(true);
} }
else else
{ {
auto lwjglversion = ENV.metadataIndex()->get("org.lwjgl", "2.9.1"); auto lwjglversion = ENV.metadataIndex()->get("org.lwjgl", "2.9.1");
lwjglPatch = std::make_shared<MetaPatchProvider>(lwjglversion); lwjglPatch = std::make_shared<ProfilePatch>(lwjglversion);
lwjglPatch->setVanilla(true);
} }
if (!lwjglPatch) if (!lwjglPatch)
{ {
@ -261,21 +168,17 @@ void OneSixProfileStrategy::loadUserPatches()
// sanity check. prevent tampering with files. // sanity check. prevent tampering with files.
if (file->uid != id) if (file->uid != id)
{ {
file->addProblem(PROBLEM_WARNING, QObject::tr("load id %1 does not match internal id %2").arg(id, file->uid)); file->addProblem(ProblemSeverity::Warning, QObject::tr("load id %1 does not match internal id %2").arg(id, file->uid));
seen_extra.insert(file->uid); seen_extra.insert(file->uid);
} }
file->setRemovable(true); auto patchEntry = std::make_shared<ProfilePatch>(file, filename);
file->setMovable(true); patchEntry->setRemovable(true);
// HACK: ignore assets from other version files than Minecraft patchEntry->setMovable(true);
// workaround for stupid assets issue caused by amazon: profile->appendPatch(patchEntry);
// https://www.theregister.co.uk/2017/02/28/aws_is_awol_as_s3_goes_haywire/
file->assets = QString();
file->mojangAssetIndex.reset();
// HACK
profile->appendPatch(file);
} }
// now load the rest by internal preference. // now load the rest by internal preference.
QMultiMap<int, VersionFilePtr> files; using FileEntry = std::tuple<VersionFilePtr, QString>;
QMultiMap<int, FileEntry> files;
for (auto info : patches.entryInfoList(QStringList() << "*.json", QDir::Files)) for (auto info : patches.entryInfoList(QStringList() << "*.json", QDir::Files))
{ {
// parse the file // parse the file
@ -292,16 +195,18 @@ void OneSixProfileStrategy::loadUserPatches()
// do not load what we already loaded in the first pass // do not load what we already loaded in the first pass
if (userOrder.contains(file->uid)) if (userOrder.contains(file->uid))
continue; continue;
file->setRemovable(true); files.insert(file->order, std::make_tuple(file, info.filePath()));
file->setMovable(true);
// HACK: ignore assets from other version files than Minecraft
// workaround for stupid assets issue caused by amazon:
// https://www.theregister.co.uk/2017/02/28/aws_is_awol_as_s3_goes_haywire/
file->assets = QString();
file->mojangAssetIndex.reset();
// HACK
files.insert(file->getOrder(), file);
} }
auto appendFilePatch = [&](FileEntry tuple)
{
VersionFilePtr file;
QString filename;
std::tie(file, filename) = tuple;
auto patchEntry = std::make_shared<ProfilePatch>(file, filename);
patchEntry->setRemovable(true);
patchEntry->setMovable(true);
profile->appendPatch(patchEntry);
};
QSet<int> seen; QSet<int> seen;
for (auto order : files.keys()) for (auto order : files.keys())
{ {
@ -311,7 +216,7 @@ void OneSixProfileStrategy::loadUserPatches()
const auto &values = files.values(order); const auto &values = files.values(order);
if(values.size() == 1) if(values.size() == 1)
{ {
profile->appendPatch(values[0]); appendFilePatch(values[0]);
continue; continue;
} }
for(auto &file: values) for(auto &file: values)
@ -320,10 +225,13 @@ void OneSixProfileStrategy::loadUserPatches()
for(auto &file2: values) for(auto &file2: values)
{ {
if(file != file2) if(file != file2)
list.append(file2->name); {
list.append(std::get<0>(file2)->name);
}
} }
file->addProblem(PROBLEM_WARNING, QObject::tr("%1 has the same order as the following components:\n%2").arg(file->name, list.join(", "))); auto vfileptr = std::get<0>(file);
profile->appendPatch(file); vfileptr->addProblem(ProblemSeverity::Warning, QObject::tr("%1 has the same order as the following components:\n%2").arg(vfileptr->name, list.join(", ")));
appendFilePatch(file);
} }
} }
} }
@ -503,11 +411,9 @@ bool OneSixProfileStrategy::installJarMods(QStringList filepaths)
f->jarMods.append(jarMod); f->jarMods.append(jarMod);
f->name = target_name; f->name = target_name;
f->uid = target_id; f->uid = target_id;
f->setOrder(profile->getFreeOrderNumber()); f->order = profile->getFreeOrderNumber();
QString patchFileName = FS::PathCombine(patchDir, target_id + ".json"); QString patchFileName = FS::PathCombine(patchDir, target_id + ".json");
f->filename = patchFileName; // f->filename = patchFileName;
f->setMovable(true);
f->setRemovable(true);
QFile file(patchFileName); QFile file(patchFileName);
if (!file.open(QFile::WriteOnly)) if (!file.open(QFile::WriteOnly))
@ -518,7 +424,11 @@ bool OneSixProfileStrategy::installJarMods(QStringList filepaths)
} }
file.write(OneSixVersionFormat::versionFileToJson(f, true).toJson()); file.write(OneSixVersionFormat::versionFileToJson(f, true).toJson());
file.close(); file.close();
profile->appendPatch(f);
auto patch = std::make_shared<ProfilePatch>(f);
patch->setMovable(true);
patch->setRemovable(true);
profile->appendPatch(patch);
} }
profile->saveCurrentOrder(); profile->saveCurrentOrder();
profile->reapplyPatches(); profile->reapplyPatches();

View File

@ -51,7 +51,7 @@ VersionFilePtr OneSixVersionFormat::versionFileFromJson(const QJsonDocument &doc
{ {
if (root.contains("order")) if (root.contains("order"))
{ {
out->setOrder(requireInteger(root.value("order"))); out->order = requireInteger(root.value("order"));
} }
else else
{ {
@ -73,7 +73,7 @@ VersionFilePtr OneSixVersionFormat::versionFileFromJson(const QJsonDocument &doc
out->version = root.value("version").toString(); out->version = root.value("version").toString();
out->dependsOnMinecraftVersion = root.value("mcVersion").toString(); out->dependsOnMinecraftVersion = root.value("mcVersion").toString();
out->filename = filename; // out->filename = filename;
MojangVersionFormat::readVersionProperties(root, out.get()); MojangVersionFormat::readVersionProperties(root, out.get());
@ -128,7 +128,8 @@ VersionFilePtr OneSixVersionFormat::versionFileFromJson(const QJsonDocument &doc
bool hasLibs = root.contains("libraries"); bool hasLibs = root.contains("libraries");
if (hasPlusLibs && hasLibs) if (hasPlusLibs && hasLibs)
{ {
out->addProblem(PROBLEM_WARNING, QObject::tr("Version file has both '+libraries' and 'libraries'. This is no longer supported.")); out->addProblem(ProblemSeverity::Warning,
QObject::tr("Version file has both '+libraries' and 'libraries'. This is no longer supported."));
readLibs("libraries"); readLibs("libraries");
readLibs("+libraries"); readLibs("+libraries");
} }
@ -144,23 +145,23 @@ VersionFilePtr OneSixVersionFormat::versionFileFromJson(const QJsonDocument &doc
/* removed features that shouldn't be used */ /* removed features that shouldn't be used */
if (root.contains("tweakers")) if (root.contains("tweakers"))
{ {
out->addProblem(PROBLEM_ERROR, QObject::tr("Version file contains unsupported element 'tweakers'")); out->addProblem(ProblemSeverity::Error, QObject::tr("Version file contains unsupported element 'tweakers'"));
} }
if (root.contains("-libraries")) if (root.contains("-libraries"))
{ {
out->addProblem(PROBLEM_ERROR, QObject::tr("Version file contains unsupported element '-libraries'")); out->addProblem(ProblemSeverity::Error, QObject::tr("Version file contains unsupported element '-libraries'"));
} }
if (root.contains("-tweakers")) if (root.contains("-tweakers"))
{ {
out->addProblem(PROBLEM_ERROR, QObject::tr("Version file contains unsupported element '-tweakers'")); out->addProblem(ProblemSeverity::Error, QObject::tr("Version file contains unsupported element '-tweakers'"));
} }
if (root.contains("-minecraftArguments")) if (root.contains("-minecraftArguments"))
{ {
out->addProblem(PROBLEM_ERROR, QObject::tr("Version file contains unsupported element '-minecraftArguments'")); out->addProblem(ProblemSeverity::Error, QObject::tr("Version file contains unsupported element '-minecraftArguments'"));
} }
if (root.contains("+minecraftArguments")) if (root.contains("+minecraftArguments"))
{ {
out->addProblem(PROBLEM_ERROR, QObject::tr("Version file contains unsupported element '+minecraftArguments'")); out->addProblem(ProblemSeverity::Error, QObject::tr("Version file contains unsupported element '+minecraftArguments'"));
} }
return out; return out;
} }
@ -170,7 +171,7 @@ QJsonDocument OneSixVersionFormat::versionFileToJson(const VersionFilePtr &patch
QJsonObject root; QJsonObject root;
if (saveOrder) if (saveOrder)
{ {
root.insert("order", patch->getOrder()); root.insert("order", patch->order);
} }
writeString(root, "name", patch->name); writeString(root, "name", patch->name);

View File

@ -26,7 +26,7 @@ public:
switch(role) switch(role)
{ {
case BaseVersionList::ParentGameVersionRole: case BaseVersionList::ParentVersionRole:
case BaseVersionList::VersionIdRole: case BaseVersionList::VersionIdRole:
{ {
auto versionString = data.toString(); auto versionString = data.toString();
@ -146,7 +146,7 @@ QVariant VersionProxyModel::data(const QModelIndex &index, int role) const
case Name: case Name:
return sourceModel()->data(parentIndex, BaseVersionList::VersionRole); return sourceModel()->data(parentIndex, BaseVersionList::VersionRole);
case ParentVersion: case ParentVersion:
return sourceModel()->data(parentIndex, BaseVersionList::ParentGameVersionRole); return sourceModel()->data(parentIndex, BaseVersionList::ParentVersionRole);
case Branch: case Branch:
return sourceModel()->data(parentIndex, BaseVersionList::BranchRole); return sourceModel()->data(parentIndex, BaseVersionList::BranchRole);
case Type: case Type:
@ -327,7 +327,7 @@ void VersionProxyModel::setSourceModel(QAbstractItemModel *replacingRaw)
m_columns.push_back(Name); m_columns.push_back(Name);
} }
/* /*
if(roles.contains(BaseVersionList::ParentGameVersionRole)) if(roles.contains(BaseVersionList::ParentVersionRole))
{ {
m_columns.push_back(ParentVersion); m_columns.push_back(ParentVersion);
} }

View File

@ -152,14 +152,14 @@ void VersionPage::packageCurrent(const QModelIndex &current, const QModelIndex &
auto severity = patch->getProblemSeverity(); auto severity = patch->getProblemSeverity();
switch(severity) switch(severity)
{ {
case PROBLEM_WARNING: case ProblemSeverity::Warning:
ui->frame->setModText(tr("%1 possibly has issues.").arg(patch->getName())); ui->frame->setModText(tr("%1 possibly has issues.").arg(patch->getName()));
break; break;
case PROBLEM_ERROR: case ProblemSeverity::Error:
ui->frame->setModText(tr("%1 has issues!").arg(patch->getName())); ui->frame->setModText(tr("%1 has issues!").arg(patch->getName()));
break; break;
default: default:
case PROBLEM_NONE: case ProblemSeverity::None:
ui->frame->clear(); ui->frame->clear();
return; return;
} }
@ -168,11 +168,11 @@ void VersionPage::packageCurrent(const QModelIndex &current, const QModelIndex &
QString problemOut; QString problemOut;
for (auto &problem: problems) for (auto &problem: problems)
{ {
if(problem.getSeverity() == PROBLEM_ERROR) if(problem.getSeverity() == ProblemSeverity::Error)
{ {
problemOut += tr("Error: "); problemOut += tr("Error: ");
} }
else if(problem.getSeverity() == PROBLEM_WARNING) else if(problem.getSeverity() == ProblemSeverity::Warning)
{ {
problemOut += tr("Warning: "); problemOut += tr("Warning: ");
} }
@ -381,7 +381,7 @@ void VersionPage::on_forgeBtn_clicked()
return; return;
} }
VersionSelectDialog vselect(vlist.get(), tr("Select Forge version"), this); VersionSelectDialog vselect(vlist.get(), tr("Select Forge version"), this);
vselect.setExactFilter(BaseVersionList::ParentGameVersionRole, m_inst->currentVersionId()); vselect.setExactFilter(BaseVersionList::ParentVersionRole, m_inst->currentVersionId());
vselect.setEmptyString(tr("No Forge versions are currently available for Minecraft ") + m_inst->currentVersionId()); vselect.setEmptyString(tr("No Forge versions are currently available for Minecraft ") + m_inst->currentVersionId());
vselect.setEmptyErrorString(tr("Couldn't load or download the Forge version lists!")); vselect.setEmptyErrorString(tr("Couldn't load or download the Forge version lists!"));
if (vselect.exec() && vselect.selectedVersion()) if (vselect.exec() && vselect.selectedVersion())
@ -400,7 +400,7 @@ void VersionPage::on_liteloaderBtn_clicked()
return; return;
} }
VersionSelectDialog vselect(vlist.get(), tr("Select LiteLoader version"), this); VersionSelectDialog vselect(vlist.get(), tr("Select LiteLoader version"), this);
vselect.setExactFilter(BaseVersionList::ParentGameVersionRole, m_inst->currentVersionId()); vselect.setExactFilter(BaseVersionList::ParentVersionRole, m_inst->currentVersionId());
vselect.setEmptyString(tr("No LiteLoader versions are currently available for Minecraft ") + m_inst->currentVersionId()); vselect.setEmptyString(tr("No LiteLoader versions are currently available for Minecraft ") + m_inst->currentVersionId());
vselect.setEmptyErrorString(tr("Couldn't load or download the LiteLoader version lists!")); vselect.setEmptyErrorString(tr("Couldn't load or download the LiteLoader version lists!"));
if (vselect.exec() && vselect.selectedVersion()) if (vselect.exec() && vselect.selectedVersion())
@ -457,7 +457,7 @@ void VersionPage::updateButtons(int row)
ui->moveDownBtn->setEnabled(patch->isMoveable()); ui->moveDownBtn->setEnabled(patch->isMoveable());
ui->moveUpBtn->setEnabled(patch->isMoveable()); ui->moveUpBtn->setEnabled(patch->isMoveable());
ui->changeVersionBtn->setEnabled(patch->isVersionChangeable()); ui->changeVersionBtn->setEnabled(patch->isVersionChangeable());
ui->editBtn->setEnabled(patch->isEditable()); ui->editBtn->setEnabled(patch->isCustom());
ui->customizeBtn->setEnabled(patch->isCustomizable()); ui->customizeBtn->setEnabled(patch->isCustomizable());
ui->revertBtn->setEnabled(patch->isRevertible()); ui->revertBtn->setEnabled(patch->isRevertible());
} }