aboutsummaryrefslogtreecommitdiff
path: root/api/logic
diff options
context:
space:
mode:
authorPetr Mrázek <peterix@gmail.com>2017-11-11 01:38:31 +0100
committerPetr Mrázek <peterix@gmail.com>2017-12-03 01:22:34 +0100
commit85ae710d407eb31527183d5f8bec0399eb209f33 (patch)
tree23647a83506ad3bd052720fb40068240e9768481 /api/logic
parent17c8f31a09da6bdfc4aa7f67b2ca86b791f2ba96 (diff)
downloadPrismLauncher-85ae710d407eb31527183d5f8bec0399eb209f33.tar.gz
PrismLauncher-85ae710d407eb31527183d5f8bec0399eb209f33.tar.bz2
PrismLauncher-85ae710d407eb31527183d5f8bec0399eb209f33.zip
GH-2026 implement changes necessary to support 1.13 snapshots
Diffstat (limited to 'api/logic')
-rw-r--r--api/logic/BaseInstance.cpp2
-rw-r--r--api/logic/BaseInstance.h6
-rw-r--r--api/logic/CMakeLists.txt8
-rw-r--r--api/logic/InstanceCreationTask.cpp13
-rw-r--r--api/logic/InstanceImportTask.cpp6
-rw-r--r--api/logic/NullInstance.h2
-rw-r--r--api/logic/ProblemProvider.h6
-rw-r--r--api/logic/launch/steps/Update.cpp2
-rw-r--r--api/logic/launch/steps/Update.h4
-rw-r--r--api/logic/meta/BaseEntity.cpp4
-rw-r--r--api/logic/meta/BaseEntity.h3
-rw-r--r--api/logic/meta/JsonFormat.cpp66
-rw-r--r--api/logic/meta/JsonFormat.h33
-rw-r--r--api/logic/meta/Version.cpp19
-rw-r--r--api/logic/meta/Version.h15
-rw-r--r--api/logic/meta/VersionList.cpp31
-rw-r--r--api/logic/minecraft/Component.cpp408
-rw-r--r--api/logic/minecraft/Component.h104
-rw-r--r--api/logic/minecraft/ComponentList.cpp1140
-rw-r--r--api/logic/minecraft/ComponentList.h93
-rw-r--r--api/logic/minecraft/ComponentList_p.h42
-rw-r--r--api/logic/minecraft/ComponentUpdateTask.cpp688
-rw-r--r--api/logic/minecraft/ComponentUpdateTask.h37
-rw-r--r--api/logic/minecraft/ComponentUpdateTask_p.h32
-rw-r--r--api/logic/minecraft/MinecraftInstance.cpp127
-rw-r--r--api/logic/minecraft/MinecraftInstance.h12
-rw-r--r--api/logic/minecraft/MinecraftLoadAndCheck.cpp45
-rw-r--r--api/logic/minecraft/MinecraftLoadAndCheck.h47
-rw-r--r--api/logic/minecraft/MinecraftUpdate.cpp41
-rw-r--r--api/logic/minecraft/OneSixVersionFormat.cpp31
-rw-r--r--api/logic/minecraft/OneSixVersionFormat.h2
-rw-r--r--api/logic/minecraft/ProfilePatch.cpp188
-rw-r--r--api/logic/minecraft/ProfilePatch.h71
-rw-r--r--api/logic/minecraft/ProfileUtils.cpp51
-rw-r--r--api/logic/minecraft/ProfileUtils.h3
-rw-r--r--api/logic/minecraft/VersionFile.h21
-rw-r--r--api/logic/minecraft/launch/ModMinecraftJar.cpp5
-rw-r--r--api/logic/minecraft/legacy/LegacyInstance.cpp2
-rw-r--r--api/logic/minecraft/legacy/LegacyInstance.h2
-rw-r--r--api/logic/minecraft/legacy/LegacyUpgradeTask.cpp101
-rw-r--r--api/logic/minecraft/update/FMLLibrariesTask.cpp7
-rw-r--r--api/logic/minecraft/update/LibrariesTask.cpp6
-rw-r--r--api/logic/net/Mode.h10
43 files changed, 2544 insertions, 992 deletions
diff --git a/api/logic/BaseInstance.cpp b/api/logic/BaseInstance.cpp
index f52b2812..027b8f78 100644
--- a/api/logic/BaseInstance.cpp
+++ b/api/logic/BaseInstance.cpp
@@ -197,7 +197,7 @@ bool BaseInstance::canLaunch() const
return (!hasVersionBroken() && !isRunning());
}
-bool BaseInstance::reload()
+bool BaseInstance::reloadSettings()
{
return m_settings->reload();
}
diff --git a/api/logic/BaseInstance.h b/api/logic/BaseInstance.h
index 26d4bc35..d0909031 100644
--- a/api/logic/BaseInstance.h
+++ b/api/logic/BaseInstance.h
@@ -30,6 +30,8 @@
#include "MessageLevel.h"
#include "pathmatcher/IPathMatcher.h"
+#include "net/Mode.h"
+
#include "multimc_logic_export.h"
class QDir;
@@ -148,7 +150,7 @@ public:
virtual SettingsObjectPtr settings() const;
/// returns a valid update task
- virtual shared_qobject_ptr<Task> createUpdateTask() = 0;
+ virtual shared_qobject_ptr<Task> createUpdateTask(Net::Mode mode) = 0;
/// returns a valid launcher (task container)
virtual std::shared_ptr<LaunchTask> createLaunchTask(AuthSessionPtr account) = 0;
@@ -224,7 +226,7 @@ public:
virtual bool canEdit() const = 0;
virtual bool canExport() const = 0;
- virtual bool reload();
+ bool reloadSettings();
/**
* 'print' a verbose desription of the instance into a QStringList
diff --git a/api/logic/CMakeLists.txt b/api/logic/CMakeLists.txt
index 42bea98c..8a8ef495 100644
--- a/api/logic/CMakeLists.txt
+++ b/api/logic/CMakeLists.txt
@@ -239,8 +239,14 @@ set(MINECRAFT_SOURCES
minecraft/MinecraftInstance.h
minecraft/LaunchProfile.cpp
minecraft/LaunchProfile.h
+ minecraft/Component.cpp
+ minecraft/Component.h
minecraft/ComponentList.cpp
minecraft/ComponentList.h
+ minecraft/ComponentUpdateTask.cpp
+ minecraft/ComponentUpdateTask.h
+ minecraft/MinecraftLoadAndCheck.h
+ minecraft/MinecraftLoadAndCheck.cpp
minecraft/MinecraftUpdate.h
minecraft/MinecraftUpdate.cpp
minecraft/MojangVersionFormat.cpp
@@ -260,8 +266,6 @@ set(MINECRAFT_SOURCES
minecraft/MojangDownloadInfo.h
minecraft/VersionFile.cpp
minecraft/VersionFile.h
- minecraft/ProfilePatch.cpp
- minecraft/ProfilePatch.h
minecraft/VersionFilterData.h
minecraft/VersionFilterData.cpp
minecraft/Mod.h
diff --git a/api/logic/InstanceCreationTask.cpp b/api/logic/InstanceCreationTask.cpp
index 21892f82..8a68815a 100644
--- a/api/logic/InstanceCreationTask.cpp
+++ b/api/logic/InstanceCreationTask.cpp
@@ -5,6 +5,7 @@
//FIXME: remove this
#include "minecraft/MinecraftInstance.h"
+#include "minecraft/ComponentList.h"
InstanceCreationTask::InstanceCreationTask(SettingsObjectPtr settings, const QString & stagingPath, BaseVersionPtr version,
const QString& instName, const QString& instIcon, const QString& instGroup)
@@ -25,11 +26,13 @@ void InstanceCreationTask::executeTask()
instanceSettings->suspendSave();
instanceSettings->registerSetting("InstanceType", "Legacy");
instanceSettings->set("InstanceType", "OneSix");
- auto inst = new MinecraftInstance(m_globalSettings, instanceSettings, m_stagingPath);
- inst->setComponentVersion("net.minecraft", m_version->descriptor());
- inst->setName(m_instName);
- inst->setIconKey(m_instIcon);
- inst->init();
+ MinecraftInstance inst(m_globalSettings, instanceSettings, m_stagingPath);
+ auto components = inst.getComponentList();
+ components->buildingFromScratch();
+ components->setComponentVersion("net.minecraft", m_version->descriptor(), true);
+ inst.setName(m_instName);
+ inst.setIconKey(m_instIcon);
+ inst.init();
instanceSettings->resumeSave();
}
emitSucceeded();
diff --git a/api/logic/InstanceImportTask.cpp b/api/logic/InstanceImportTask.cpp
index e2782cd8..80f68458 100644
--- a/api/logic/InstanceImportTask.cpp
+++ b/api/logic/InstanceImportTask.cpp
@@ -242,7 +242,9 @@ void InstanceImportTask::processFlame()
mcVersion.remove(QRegExp("[.]+$"));
qWarning() << "Mysterious trailing dots removed from Minecraft version while importing pack.";
}
- instance.setComponentVersion("net.minecraft", mcVersion);
+ auto components = instance.getComponentList();
+ components->buildingFromScratch();
+ components->setComponentVersion("net.minecraft", mcVersion, true);
if(!forgeVersion.isEmpty())
{
// FIXME: dirty, nasty, hack. Proper solution requires dependency resolution and knowledge of the metadata.
@@ -257,7 +259,7 @@ void InstanceImportTask::processFlame()
qWarning() << "Could not map recommended forge version for" << mcVersion;
}
}
- instance.setComponentVersion("net.minecraftforge", forgeVersion);
+ components->setComponentVersion("net.minecraftforge", forgeVersion);
}
if (m_instIcon != "default")
{
diff --git a/api/logic/NullInstance.h b/api/logic/NullInstance.h
index f689c5ab..27a8a251 100644
--- a/api/logic/NullInstance.h
+++ b/api/logic/NullInstance.h
@@ -29,7 +29,7 @@ public:
{
return nullptr;
}
- virtual shared_qobject_ptr< Task > createUpdateTask() override
+ virtual shared_qobject_ptr< Task > createUpdateTask(Net::Mode mode) override
{
return nullptr;
}
diff --git a/api/logic/ProblemProvider.h b/api/logic/ProblemProvider.h
index 4040f4fa..978710f0 100644
--- a/api/logic/ProblemProvider.h
+++ b/api/logic/ProblemProvider.h
@@ -1,5 +1,7 @@
#pragma once
+#include "multimc_logic_export.h"
+
enum class ProblemSeverity
{
None,
@@ -13,7 +15,7 @@ struct PatchProblem
QString m_description;
};
-class ProblemProvider
+class MULTIMC_LOGIC_EXPORT ProblemProvider
{
public:
virtual ~ProblemProvider() {};
@@ -21,7 +23,7 @@ public:
virtual ProblemSeverity getProblemSeverity() const = 0;
};
-class ProblemContainer : public ProblemProvider
+class MULTIMC_LOGIC_EXPORT ProblemContainer : public ProblemProvider
{
public:
const QList<PatchProblem> getProblems() const override
diff --git a/api/logic/launch/steps/Update.cpp b/api/logic/launch/steps/Update.cpp
index f06c39eb..42ca3c67 100644
--- a/api/logic/launch/steps/Update.cpp
+++ b/api/logic/launch/steps/Update.cpp
@@ -23,7 +23,7 @@ void Update::executeTask()
emitFailed(tr("Task aborted."));
return;
}
- m_updateTask.reset(m_parent->instance()->createUpdateTask());
+ m_updateTask.reset(m_parent->instance()->createUpdateTask(m_mode));
if(m_updateTask)
{
connect(m_updateTask.get(), SIGNAL(finished()), this, SLOT(updateFinished()));
diff --git a/api/logic/launch/steps/Update.h b/api/logic/launch/steps/Update.h
index d855a1db..e9573bcd 100644
--- a/api/logic/launch/steps/Update.h
+++ b/api/logic/launch/steps/Update.h
@@ -19,13 +19,14 @@
#include <QObjectPtr.h>
#include <LoggedProcess.h>
#include <java/JavaChecker.h>
+#include <net/Mode.h>
// FIXME: stupid. should be defined by the instance type? or even completely abstracted away...
class Update: public LaunchStep
{
Q_OBJECT
public:
- explicit Update(LaunchTask *parent):LaunchStep(parent) {};
+ explicit Update(LaunchTask *parent, Net::Mode mode):LaunchStep(parent), m_mode(mode) {};
virtual ~Update() {};
void executeTask() override;
@@ -40,4 +41,5 @@ private slots:
private:
shared_qobject_ptr<Task> m_updateTask;
bool m_aborted = false;
+ Net::Mode m_mode = Net::Mode::Offline;
};
diff --git a/api/logic/meta/BaseEntity.cpp b/api/logic/meta/BaseEntity.cpp
index 6bac71ee..7cf327be 100644
--- a/api/logic/meta/BaseEntity.cpp
+++ b/api/logic/meta/BaseEntity.cpp
@@ -99,7 +99,7 @@ bool Meta::BaseEntity::loadLocalFile()
}
}
-void Meta::BaseEntity::load()
+void Meta::BaseEntity::load(Net::Mode loadType)
{
// load local file if nothing is loaded yet
if(!isLoaded())
@@ -110,7 +110,7 @@ void Meta::BaseEntity::load()
}
}
// if we need remote update, run the update task
- if(!shouldStartRemoteUpdate())
+ if(loadType == Net::Mode::Offline || !shouldStartRemoteUpdate())
{
return;
}
diff --git a/api/logic/meta/BaseEntity.h b/api/logic/meta/BaseEntity.h
index 4483beab..4c74b1a7 100644
--- a/api/logic/meta/BaseEntity.h
+++ b/api/logic/meta/BaseEntity.h
@@ -20,6 +20,7 @@
#include "QObjectPtr.h"
#include "multimc_logic_export.h"
+#include "net/Mode.h"
class Task;
namespace Meta
@@ -54,7 +55,7 @@ public:
bool isLoaded() const;
bool shouldStartRemoteUpdate() const;
- void load();
+ void load(Net::Mode loadType);
shared_qobject_ptr<Task> getCurrentTask();
protected: /* methods */
diff --git a/api/logic/meta/JsonFormat.cpp b/api/logic/meta/JsonFormat.cpp
index d13c89df..2c313478 100644
--- a/api/logic/meta/JsonFormat.cpp
+++ b/api/logic/meta/JsonFormat.cpp
@@ -51,18 +51,11 @@ static VersionPtr parseCommonVersion(const QString &uid, const QJsonObject &obj)
version->setType(ensureString(obj, "type", QString()));
version->setParentUid(ensureString(obj, "parentUid", QString()));
version->setRecommended(ensureBoolean(obj, QString("recommended"), false));
- if(obj.contains("requires"))
- {
- QHash<QString, QString> requires;
- auto reqobj = requireObject(obj, "requires");
- auto iter = reqobj.begin();
- while(iter != reqobj.end())
- {
- requires[iter.key()] = requireString(iter.value());
- iter++;
- }
- version->setRequires(requires);
- }
+ version->setVolatile(ensureBoolean(obj, QString("volatile"), false));
+ RequireSet requires, conflicts;
+ parseRequires(obj, &requires, "requires");
+ parseRequires(obj, &conflicts, "conflicts");
+ version->setRequires(requires, conflicts);
return version;
}
@@ -145,4 +138,53 @@ void parseVersion(const QJsonObject &obj, Version *ptr)
throw ParseException(QObject::tr("Unknown formatVersion: %1").arg(version));
}
}
+
+/*
+[
+{"uid":"foo", "equals":"version"}
+]
+*/
+void parseRequires(const QJsonObject& obj, RequireSet* ptr, const char * keyName)
+{
+ if(obj.contains(keyName))
+ {
+ QSet<QString> requires;
+ auto reqArray = requireArray(obj, keyName);
+ auto iter = reqArray.begin();
+ while(iter != reqArray.end())
+ {
+ auto reqObject = requireObject(*iter);
+ auto uid = requireString(reqObject, "uid");
+ auto equals = ensureString(reqObject, "equals", QString());
+ auto suggests = ensureString(reqObject, "suggests", QString());
+ ptr->insert({uid, equals, suggests});
+ iter++;
+ }
+ }
}
+void serializeRequires(QJsonObject& obj, RequireSet* ptr, const char * keyName)
+{
+ if(!ptr || ptr->empty())
+ {
+ return;
+ }
+ QJsonArray arrOut;
+ for(auto &iter: *ptr)
+ {
+ QJsonObject reqOut;
+ reqOut.insert("uid", iter.uid);
+ if(!iter.equalsVersion.isEmpty())
+ {
+ reqOut.insert("equals", iter.equalsVersion);
+ }
+ if(!iter.suggests.isEmpty())
+ {
+ reqOut.insert("suggests", iter.suggests);
+ }
+ arrOut.append(reqOut);
+ }
+ obj.insert(keyName, arrOut);
+}
+
+}
+
diff --git a/api/logic/meta/JsonFormat.h b/api/logic/meta/JsonFormat.h
index aaed07fc..9b9dcd91 100644
--- a/api/logic/meta/JsonFormat.h
+++ b/api/logic/meta/JsonFormat.h
@@ -20,6 +20,7 @@
#include "Exception.h"
#include "meta/BaseEntity.h"
+#include <set>
namespace Meta
{
@@ -32,9 +33,41 @@ class ParseException : public Exception
public:
using Exception::Exception;
};
+struct Require
+{
+ bool operator==(const Require & rhs) const
+ {
+ return uid == rhs.uid;
+ }
+ bool operator<(const Require & rhs) const
+ {
+ return uid < rhs.uid;
+ }
+ bool deepEquals(const Require & rhs) const
+ {
+ return uid == rhs.uid
+ && equalsVersion == rhs.equalsVersion
+ && suggests == rhs.suggests;
+ }
+ QString uid;
+ QString equalsVersion;
+ QString suggests;
+};
+
+inline Q_DECL_PURE_FUNCTION uint qHash(const Require &key, uint seed = 0) Q_DECL_NOTHROW
+{
+ return qHash(key.uid, seed);
+}
+
+using RequireSet = std::set<Require>;
void parseIndex(const QJsonObject &obj, Index *ptr);
void parseVersion(const QJsonObject &obj, Version *ptr);
void parseVersionList(const QJsonObject &obj, VersionList *ptr);
+// FIXME: this has a different shape than the others...FIX IT!?
+void parseRequires(const QJsonObject &obj, RequireSet * ptr, const char * keyName = "requires");
+void serializeRequires(QJsonObject & objOut, RequireSet* ptr, const char * keyName = "requires");
}
+
+Q_DECLARE_METATYPE(std::set<Meta::Require>); \ No newline at end of file
diff --git a/api/logic/meta/Version.cpp b/api/logic/meta/Version.cpp
index bf739157..d82878a1 100644
--- a/api/logic/meta/Version.cpp
+++ b/api/logic/meta/Version.cpp
@@ -74,12 +74,20 @@ void Meta::Version::merge(const std::shared_ptr<BaseEntity> &other)
}
if (m_requires != version->m_requires)
{
- setRequires(version->m_requires);
+ m_requires = version->m_requires;
+ }
+ if (m_conflicts != version->m_conflicts)
+ {
+ m_conflicts = version->m_conflicts;
}
if (m_parentUid != version->m_parentUid)
{
setParentUid(version->m_parentUid);
}
+ if(m_volatile != version->m_volatile)
+ {
+ setVolatile(version->m_volatile);
+ }
if(version->m_data)
{
setData(version->m_data);
@@ -109,12 +117,19 @@ void Meta::Version::setTime(const qint64 time)
emit timeChanged();
}
-void Meta::Version::setRequires(const QHash<QString, QString> &requires)
+void Meta::Version::setRequires(const Meta::RequireSet &requires, const Meta::RequireSet &conflicts)
{
m_requires = requires;
+ m_conflicts = conflicts;
emit requiresChanged();
}
+void Meta::Version::setVolatile(bool volatile_)
+{
+ m_volatile = volatile_;
+}
+
+
void Meta::Version::setData(const VersionFilePtr &data)
{
m_data = data;
diff --git a/api/logic/meta/Version.h b/api/logic/meta/Version.h
index 2f92ee9f..61f253c6 100644
--- a/api/logic/meta/Version.h
+++ b/api/logic/meta/Version.h
@@ -28,6 +28,8 @@
#include "multimc_logic_export.h"
+#include "JsonFormat.h"
+
namespace Meta
{
using VersionPtr = std::shared_ptr<class Version>;
@@ -65,7 +67,7 @@ public: /* con/des */
{
return m_time;
}
- const QHash<QString, QString> &requires() const
+ const Meta::RequireSet &requires() const
{
return m_requires;
}
@@ -77,6 +79,10 @@ public: /* con/des */
{
return m_recommended;
}
+ bool isLoaded() const
+ {
+ return m_data != nullptr;
+ }
void merge(const std::shared_ptr<BaseEntity> &other) override;
void parse(const QJsonObject &obj) override;
@@ -87,7 +93,8 @@ public: // for usage by format parsers only
void setParentUid(const QString &parentUid);
void setType(const QString &type);
void setTime(const qint64 time);
- void setRequires(const QHash<QString, QString> &requires);
+ void setRequires(const Meta::RequireSet &requires, const Meta::RequireSet &conflicts);
+ void setVolatile(bool volatile_);
void setRecommended(bool recommended);
void setProvidesRecommendations();
void setData(const VersionFilePtr &data);
@@ -106,7 +113,9 @@ private:
QString m_version;
QString m_type;
qint64 m_time = 0;
- QHash<QString, QString> m_requires;
+ Meta::RequireSet m_requires;
+ Meta::RequireSet m_conflicts;
+ bool m_volatile = false;
VersionFilePtr m_data;
};
}
diff --git a/api/logic/meta/VersionList.cpp b/api/logic/meta/VersionList.cpp
index 4da0fb76..8910c4d7 100644
--- a/api/logic/meta/VersionList.cpp
+++ b/api/logic/meta/VersionList.cpp
@@ -30,7 +30,7 @@ VersionList::VersionList(const QString &uid, QObject *parent)
shared_qobject_ptr<Task> VersionList::getLoadTask()
{
- load();
+ load(Net::Mode::Online);
return getCurrentTask();
}
@@ -81,10 +81,13 @@ QVariant VersionList::data(const QModelIndex &index, int role) const
return QVariant();
}
auto & reqs = version->requires();
- auto iter = reqs.find(parentUid);
+ auto iter = std::find_if(reqs.begin(), reqs.end(), [&parentUid](const Require & req)
+ {
+ return req.uid == parentUid;
+ });
if (iter != reqs.end())
{
- return iter.value();
+ return (*iter).equalsVersion;
}
}
case TypeRole: return version->type();
@@ -159,6 +162,7 @@ void VersionList::setVersions(const QVector<VersionPtr> &versions)
setupAddedVersion(i, m_versions.at(i));
}
+ // FIXME: this is dumb, we have 'recommended' as part of the metadata already...
auto recommendedIt = std::find_if(m_versions.constBegin(), m_versions.constEnd(), [](const VersionPtr &ptr) { return ptr->type() == "release"; });
m_recommended = recommendedIt == m_versions.constEnd() ? nullptr : *recommendedIt;
endResetModel();
@@ -169,6 +173,22 @@ void VersionList::parse(const QJsonObject& obj)
parseVersionList(obj, this);
}
+// FIXME: this is dumb, we have 'recommended' as part of the metadata already...
+static const Meta::VersionPtr &getBetterVersion(const Meta::VersionPtr &a, const Meta::VersionPtr &b)
+{
+ if(!a)
+ return b;
+ if(!b)
+ return a;
+ if(a->type() == b->type())
+ {
+ // newer of same type wins
+ return (a->rawTime() > b->rawTime() ? a : b);
+ }
+ // 'release' type wins
+ return (a->type() == "release" ? a : b);
+}
+
void VersionList::merge(const BaseEntity::Ptr &other)
{
const VersionListPtr list = std::dynamic_pointer_cast<VersionList>(other);
@@ -199,10 +219,7 @@ void VersionList::merge(const BaseEntity::Ptr &other)
// connect it.
setupAddedVersion(m_versions.size(), version);
m_versions.append(version);
- if (!m_recommended || (version->type() == "release" && version->rawTime() > m_recommended->rawTime()))
- {
- m_recommended = version;
- }
+ m_recommended = getBetterVersion(m_recommended, version);
}
endResetModel();
}
diff --git a/api/logic/minecraft/Component.cpp b/api/logic/minecraft/Component.cpp
new file mode 100644
index 00000000..db523142
--- /dev/null
+++ b/api/logic/minecraft/Component.cpp
@@ -0,0 +1,408 @@
+#include <meta/VersionList.h>
+#include <meta/Index.h>
+#include <Env.h>
+#include "Component.h"
+
+#include "meta/Version.h"
+#include "VersionFile.h"
+#include "minecraft/ComponentList.h"
+#include <FileSystem.h>
+#include <QSaveFile>
+#include "OneSixVersionFormat.h"
+#include <assert.h>
+
+Component::Component(ComponentList * parent, const QString& uid)
+{
+ assert(parent);
+ m_parent = parent;
+
+ m_uid = uid;
+}
+
+Component::Component(ComponentList * parent, std::shared_ptr<Meta::Version> version)
+{
+ assert(parent);
+ m_parent = parent;
+
+ m_metaVersion = version;
+ m_uid = version->uid();
+ m_version = m_cachedVersion = version->version();
+ m_cachedName = version->name();
+ m_loaded = version->isLoaded();
+}
+
+Component::Component(ComponentList * parent, const QString& uid, std::shared_ptr<VersionFile> file)
+{
+ assert(parent);
+ m_parent = parent;
+
+ m_file = file;
+ m_uid = uid;
+ m_cachedVersion = m_file->version;
+ m_cachedName = m_file->name;
+ m_loaded = true;
+}
+
+std::shared_ptr<Meta::Version> Component::getMeta()
+{
+ return m_metaVersion;
+}
+
+void Component::applyTo(LaunchProfile* profile)
+{
+ auto vfile = getVersionFile();
+ if(vfile)
+ {
+ vfile->applyTo(profile);
+ }
+ else
+ {
+ profile->applyProblemSeverity(getProblemSeverity());
+ }
+}
+
+std::shared_ptr<class VersionFile> Component::getVersionFile() const
+{
+ if(m_metaVersion)
+ {
+ if(!m_metaVersion->isLoaded())
+ {
+ m_metaVersion->load(Net::Mode::Online);
+ }
+ return m_metaVersion->data();
+ }
+ else
+ {
+ return m_file;
+ }
+}
+
+std::shared_ptr<class Meta::VersionList> Component::getVersionList() const
+{
+ // FIXME: what if the metadata index isn't loaded yet?
+ if(ENV.metadataIndex()->hasUid(m_uid))
+ {
+ return ENV.metadataIndex()->get(m_uid);
+ }
+ return nullptr;
+}
+
+int Component::getOrder()
+{
+ if(m_orderOverride)
+ return m_order;
+
+ auto vfile = getVersionFile();
+ if(vfile)
+ {
+ return vfile->order;
+ }
+ return 0;
+}
+void Component::setOrder(int order)
+{
+ m_orderOverride = true;
+ m_order = order;
+}
+QString Component::getID()
+{
+ return m_uid;
+}
+QString Component::getName()
+{
+ if (!m_cachedName.isEmpty())
+ return m_cachedName;
+ return m_uid;
+}
+QString Component::getVersion()
+{
+ return m_cachedVersion;
+}
+QString Component::getFilename()
+{
+ return m_parent->patchFilePathForUid(m_uid);
+}
+QDateTime Component::getReleaseDateTime()
+{
+ if(m_metaVersion)
+ {
+ return m_metaVersion->time();
+ }
+ auto vfile = getVersionFile();
+ if(vfile)
+ {
+ return vfile->releaseTime;
+ }
+ // FIXME: fake
+ return QDateTime::currentDateTime();
+}
+
+bool Component::isCustom()
+{
+ return m_file != nullptr;
+};
+
+bool Component::isCustomizable()
+{
+ if(m_metaVersion)
+ {
+ if(getVersionFile())
+ {
+ return true;
+ }