summaryrefslogtreecommitdiffstats
path: root/logic/minecraft
diff options
context:
space:
mode:
Diffstat (limited to 'logic/minecraft')
-rw-r--r--logic/minecraft/MinecraftVersion.cpp93
-rw-r--r--logic/minecraft/MinecraftVersion.h102
-rw-r--r--logic/minecraft/MinecraftVersionList.cpp167
-rw-r--r--logic/minecraft/ParseUtils.cpp23
-rw-r--r--logic/minecraft/ParseUtils.h14
-rw-r--r--logic/minecraft/VersionBuildError.h58
-rw-r--r--logic/minecraft/VersionBuilder.cpp220
-rw-r--r--logic/minecraft/VersionBuilder.h13
-rw-r--r--logic/minecraft/VersionFile.cpp69
-rw-r--r--logic/minecraft/VersionFile.h83
-rw-r--r--logic/minecraft/VersionFinal.cpp99
-rw-r--r--logic/minecraft/VersionFinal.h20
-rw-r--r--logic/minecraft/VersionPatch.h16
13 files changed, 646 insertions, 331 deletions
diff --git a/logic/minecraft/MinecraftVersion.cpp b/logic/minecraft/MinecraftVersion.cpp
index a2e5a50a..2191e8af 100644
--- a/logic/minecraft/MinecraftVersion.cpp
+++ b/logic/minecraft/MinecraftVersion.cpp
@@ -1,2 +1,95 @@
#include "MinecraftVersion.h"
+#include "VersionFinal.h"
+bool MinecraftVersion::usesLegacyLauncher()
+{
+ return m_traits.contains("legacyLaunch") || m_traits.contains("aplhaLaunch");
+}
+QString MinecraftVersion::descriptor()
+{
+ return m_descriptor;
+}
+QString MinecraftVersion::name()
+{
+ return m_name;
+}
+QString MinecraftVersion::typeString() const
+{
+ if (is_latest && is_snapshot)
+ {
+ return QObject::tr("Latest snapshot");
+ }
+ else if (is_latest)
+ {
+ return QObject::tr("Latest release");
+ }
+ else if (is_snapshot)
+ {
+ return QObject::tr("Snapshot");
+ }
+ else
+ {
+ return QObject::tr("Regular release");
+ }
+}
+bool MinecraftVersion::hasJarMods()
+{
+ return false;
+}
+bool MinecraftVersion::isVanilla()
+{
+ return true;
+}
+
+void MinecraftVersion::applyTo(VersionFinal *version)
+{
+ // FIXME: make this work.
+ if(m_versionSource != Builtin)
+ {
+ return;
+ }
+ if (!m_descriptor.isNull())
+ {
+ version->id = m_descriptor;
+ }
+ if (!m_mainClass.isNull())
+ {
+ version->mainClass = m_mainClass;
+ }
+ if (!m_appletClass.isNull())
+ {
+ version->appletClass = m_appletClass;
+ }
+ if (!m_processArguments.isNull())
+ {
+ version->vanillaProcessArguments = m_processArguments;
+ version->processArguments = m_processArguments;
+ }
+ if (!m_type.isNull())
+ {
+ version->type = m_type;
+ }
+ if (!m_releaseTimeString.isNull())
+ {
+ version->m_releaseTimeString = m_releaseTimeString;
+ version->m_releaseTime = m_releaseTime;
+ }
+ if (!m_updateTimeString.isNull())
+ {
+ version->m_updateTimeString = m_updateTimeString;
+ version->m_updateTime = m_updateTime;
+ }
+ version->traits.unite(m_traits);
+}
+int MinecraftVersion::getOrder()
+{
+ return order;
+}
+void MinecraftVersion::setOrder(int order)
+{
+ this->order = order;
+}
+QList<JarmodPtr> MinecraftVersion::getJarMods()
+{
+ return QList<JarmodPtr>();
+}
diff --git a/logic/minecraft/MinecraftVersion.h b/logic/minecraft/MinecraftVersion.h
index dab08bb1..6a1c54cb 100644
--- a/logic/minecraft/MinecraftVersion.h
+++ b/logic/minecraft/MinecraftVersion.h
@@ -15,16 +15,18 @@
#pragma once
-#include "logic/BaseVersion.h"
-#include "VersionPatch.h"
#include <QStringList>
#include <QSet>
+#include <QDateTime>
+
+#include "logic/BaseVersion.h"
+#include "VersionPatch.h"
+#include "VersionFile.h"
+
+class VersionFinal;
struct MinecraftVersion : public BaseVersion, public VersionPatch
{
- /// The version's timestamp - this is primarily used for sorting versions in a list.
- qint64 timestamp;
-
/// The URL that this version will be downloaded from. maybe.
QString download_url;
@@ -34,16 +36,20 @@ struct MinecraftVersion : public BaseVersion, public VersionPatch
/// is this a snapshot?
bool is_snapshot = false;
- /// is this a built-in version that comes with MultiMC?
- bool is_builtin = false;
-
+ /// where is this from?
+ enum VersionSource
+ {
+ Builtin,
+ Mojang
+ } m_versionSource = Builtin;
+
/// the human readable version name
QString m_name;
/// the version ID.
QString m_descriptor;
- /// version traits. generally launcher business...
+ /// version traits. added by MultiMC
QSet<QString> m_traits;
/// The main class this version uses (if any, can be empty).
@@ -52,57 +58,47 @@ struct MinecraftVersion : public BaseVersion, public VersionPatch
/// The applet class this version uses (if any, can be empty).
QString m_appletClass;
- bool usesLegacyLauncher()
- {
- return m_traits.contains("legacyLaunch") || m_traits.contains("aplhaLaunch");
- }
-
- virtual QString descriptor() override
- {
- return m_descriptor;
- }
+ /// The process arguments used by this version
+ QString m_processArguments;
- virtual QString name() override
- {
- return m_name;
- }
+ /// The type of this release
+ QString m_type;
- virtual QString typeString() const override
+ /// the time this version was actually released by Mojang, as string and as QDateTime
+ QString m_releaseTimeString;
+ QDateTime m_releaseTime;
+
+ /// the time this version was last updated by Mojang, as string and as QDateTime
+ QString m_updateTimeString;
+ QDateTime m_updateTime;
+
+ /// order of this file... default = -2
+ int order = -2;
+
+ bool usesLegacyLauncher();
+ virtual QString descriptor() override;
+ virtual QString name() override;
+ virtual QString typeString() const override;
+ virtual bool hasJarMods() override;
+ virtual bool isVanilla() override;
+ virtual void applyTo(VersionFinal *version) override;
+ virtual int getOrder();
+ virtual void setOrder(int order);
+ virtual QList<JarmodPtr> getJarMods() override;
+ virtual QString getPatchID()
{
- if (is_latest && is_snapshot)
- {
- return QObject::tr("Latest snapshot");
- }
- else if(is_latest)
- {
- return QObject::tr("Latest release");
- }
- else if(is_snapshot)
- {
- return QObject::tr("Snapshot");
- }
- else if(is_builtin)
- {
- return QObject::tr("Museum piece");
- }
- else
- {
- return QObject::tr("Regular release");
- }
+ return "net.minecraft";
}
-
- virtual bool hasJarMods() override
+ virtual QString getPatchVersion()
{
- return false;
+ return m_descriptor;
}
-
- virtual bool isVanilla() override
+ virtual QString getPatchName()
{
- return true;
+ return "Minecraft";
}
-
- virtual void applyTo(VersionFinal *version)
+ virtual QString getPatchFilename()
{
- // umm... what now?
- }
+ return QString();
+ };
};
diff --git a/logic/minecraft/MinecraftVersionList.cpp b/logic/minecraft/MinecraftVersionList.cpp
index cdf5fa77..1aa220e8 100644
--- a/logic/minecraft/MinecraftVersionList.cpp
+++ b/logic/minecraft/MinecraftVersionList.cpp
@@ -16,7 +16,8 @@
#include "MinecraftVersionList.h"
#include "MultiMC.h"
#include "logic/net/URLConstants.h"
-#include <logic/MMCJson.h>
+#include "logic/MMCJson.h"
+#include "ParseUtils.h"
#include <QtXml>
@@ -30,11 +31,6 @@
#include <QtNetwork>
-inline QDateTime timeFromS3Time(QString str)
-{
- return QDateTime::fromString(str, Qt::ISODate);
-}
-
MinecraftVersionList::MinecraftVersionList(QObject *parent) : BaseVersionList(parent)
{
loadBuiltinList();
@@ -64,7 +60,7 @@ static bool cmpVersions(BaseVersionPtr first, BaseVersionPtr second)
{
auto left = std::dynamic_pointer_cast<MinecraftVersion>(first);
auto right = std::dynamic_pointer_cast<MinecraftVersion>(second);
- return left->timestamp > right->timestamp;
+ return left->m_releaseTime > right->m_releaseTime;
}
void MinecraftVersionList::sortInternal()
@@ -79,55 +75,55 @@ void MinecraftVersionList::loadBuiltinList()
QFile filez(versionList.absoluteFilePath());
filez.open(QIODevice::ReadOnly);
auto data = filez.readAll();
-
+
// parse the data as json
QJsonParseError jsonError;
QJsonDocument jsonDoc = QJsonDocument::fromJson(data, &jsonError);
QJsonObject root = jsonDoc.object();
-
+
// parse all the versions
for (const auto version : MMCJson::ensureArray(root.value("versions")))
{
QJsonObject versionObj = version.toObject();
QString versionID = versionObj.value("id").toString("");
- QString versionTimeStr = versionObj.value("releaseTime").toString("");
QString versionTypeStr = versionObj.value("type").toString("");
- QSet<QString> traits;
- if (versionObj.contains("+traits"))
+ if (versionID.isEmpty() || versionTypeStr.isEmpty())
{
- for (auto traitVal : MMCJson::ensureArray(versionObj.value("+traits")))
- {
- traits.insert(MMCJson::ensureString(traitVal));
- }
- }
- if (versionID.isEmpty() || versionTimeStr.isEmpty() || versionTypeStr.isEmpty())
- {
- // FIXME: log this somewhere
+ QLOG_ERROR() << "Parsed version is missing ID or type";
continue;
}
+
+ // Now, we construct the version object and add it to the list.
+ std::shared_ptr<MinecraftVersion> mcVersion(new MinecraftVersion());
+ mcVersion->m_name = mcVersion->m_descriptor = versionID;
+
// Parse the timestamp.
- QDateTime versionTime = timeFromS3Time(versionTimeStr);
- if (!versionTime.isValid())
+ try
+ {
+ parse_timestamp(versionObj.value("releaseTime").toString(""),
+ mcVersion->m_releaseTimeString, mcVersion->m_releaseTime);
+ }
+ catch (MMCError &e)
{
- // FIXME: log this somewhere
+ QLOG_ERROR() << "Error while parsing version" << versionID << ":" << e.cause();
continue;
}
- // Get the download URL.
- QString dlUrl = "http://" + URLConstants::AWS_DOWNLOAD_VERSIONS + versionID + "/";
- // main class and applet class
- QString mainClass = versionObj.value("type").toString("");
- QString appletClass = versionObj.value("type").toString("");
+ // Get the download URL.
+ mcVersion->download_url =
+ "http://" + URLConstants::AWS_DOWNLOAD_VERSIONS + versionID + "/";
- // Now, we construct the version object and add it to the list.
- std::shared_ptr<MinecraftVersion> mcVersion(new MinecraftVersion());
- mcVersion->m_name = mcVersion->m_descriptor = versionID;
- mcVersion->timestamp = versionTime.toMSecsSinceEpoch();
- mcVersion->download_url = dlUrl;
- mcVersion->is_builtin = true;
- mcVersion->m_appletClass = appletClass;
- mcVersion->m_mainClass = mainClass;
- mcVersion->m_traits = traits;
+ mcVersion->m_versionSource = MinecraftVersion::Builtin;
+ mcVersion->m_appletClass = versionObj.value("appletClass").toString("");
+ mcVersion->m_mainClass = versionObj.value("mainClass").toString("");
+ mcVersion->m_processArguments = versionObj.value("processArguments").toString("legacy");
+ if (versionObj.contains("+traits"))
+ {
+ for (auto traitVal : MMCJson::ensureArray(versionObj.value("+traits")))
+ {
+ mcVersion->m_traits.insert(MMCJson::ensureString(traitVal));
+ }
+ }
m_vlist.append(mcVersion);
}
}
@@ -265,62 +261,77 @@ void MCVListLoadTask::list_downloaded()
// Load the version info.
if (!version.isObject())
{
- // FIXME: log this somewhere
+ QLOG_ERROR() << "Error while parsing version list : invalid JSON structure";
continue;
}
QJsonObject versionObj = version.toObject();
QString versionID = versionObj.value("id").toString("");
- QString versionTimeStr = versionObj.value("releaseTime").toString("");
- QString versionTypeStr = versionObj.value("type").toString("");
- if (versionID.isEmpty() || versionTimeStr.isEmpty() || versionTypeStr.isEmpty())
+ if (versionID.isEmpty())
{
- // FIXME: log this somewhere
+ QLOG_ERROR() << "Error while parsing version : version ID is missing";
continue;
}
+ // Get the download URL.
+ QString dlUrl = "http://" + URLConstants::AWS_DOWNLOAD_VERSIONS + versionID + "/";
- // Parse the timestamp.
- QDateTime versionTime = timeFromS3Time(versionTimeStr);
- if (!versionTime.isValid())
- {
- // FIXME: log this somewhere
- continue;
- }
- // OneSix or Legacy. use filter to determine type
- if (versionTypeStr == "release")
- {
- is_latest = (versionID == latestReleaseID);
- is_snapshot = false;
- }
- else if (versionTypeStr == "snapshot") // It's a snapshot... yay
- {
- is_latest = (versionID == latestSnapshotID);
- is_snapshot = true;
- }
- else if (versionTypeStr == "old_alpha")
- {
- is_latest = false;
- is_snapshot = false;
- }
- else if (versionTypeStr == "old_beta")
+ // Now, we construct the version object and add it to the list.
+ std::shared_ptr<MinecraftVersion> mcVersion(new MinecraftVersion());
+ mcVersion->m_name = mcVersion->m_descriptor = versionID;
+
+ try
{
- is_latest = false;
- is_snapshot = false;
+ // Parse the timestamps.
+ parse_timestamp(versionObj.value("releaseTime").toString(""),
+ mcVersion->m_releaseTimeString, mcVersion->m_releaseTime);
+
+ parse_timestamp(versionObj.value("time").toString(""),
+ mcVersion->m_updateTimeString, mcVersion->m_updateTime);
}
- else
+ catch (MMCError &e)
{
- // FIXME: log this somewhere
+ QLOG_ERROR() << "Error while parsing version" << versionID << ":" << e.cause();
continue;
}
- // Get the download URL.
- QString dlUrl = "http://" + URLConstants::AWS_DOWNLOAD_VERSIONS + versionID + "/";
- // Now, we construct the version object and add it to the list.
- std::shared_ptr<MinecraftVersion> mcVersion(new MinecraftVersion());
- mcVersion->m_name = mcVersion->m_descriptor = versionID;
- mcVersion->timestamp = versionTime.toMSecsSinceEpoch();
+ mcVersion->m_versionSource = MinecraftVersion::Builtin;
mcVersion->download_url = dlUrl;
- mcVersion->is_latest = is_latest;
- mcVersion->is_snapshot = is_snapshot;
+ {
+ QString versionTypeStr = versionObj.value("type").toString("");
+ if (versionTypeStr.isEmpty())
+ {
+ // FIXME: log this somewhere
+ continue;
+ }
+ // OneSix or Legacy. use filter to determine type
+ if (versionTypeStr == "release")
+ {
+ is_latest = (versionID == latestReleaseID);
+ is_snapshot = false;
+ }
+ else if (versionTypeStr == "snapshot") // It's a snapshot... yay
+ {
+ is_latest = (versionID == latestSnapshotID);
+ is_snapshot = true;
+ }
+ else if (versionTypeStr == "old_alpha")
+ {
+ is_latest = false;
+ is_snapshot = false;
+ }
+ else if (versionTypeStr == "old_beta")
+ {
+ is_latest = false;
+ is_snapshot = false;
+ }
+ else
+ {
+ // FIXME: log this somewhere
+ continue;
+ }
+ mcVersion->m_type = versionTypeStr;
+ mcVersion->is_latest = is_latest;
+ mcVersion->is_snapshot = is_snapshot;
+ }
tempList.append(mcVersion);
}
m_list->updateListData(tempList);
diff --git a/logic/minecraft/ParseUtils.cpp b/logic/minecraft/ParseUtils.cpp
new file mode 100644
index 00000000..67460ca4
--- /dev/null
+++ b/logic/minecraft/ParseUtils.cpp
@@ -0,0 +1,23 @@
+#include <QDateTime>
+#include <QString>
+#include "ParseUtils.h"
+#include <logic/MMCJson.h>
+
+QDateTime timeFromS3Time(QString str)
+{
+ return QDateTime::fromString(str, Qt::ISODate);
+}
+
+void parse_timestamp (const QString & raw, QString & save_here, QDateTime & parse_here)
+{
+ save_here = raw;
+ if (save_here.isEmpty())
+ {
+ throw JSONValidationError("The timestamp is empty!");
+ }
+ parse_here = timeFromS3Time(save_here);
+ if (!parse_here.isValid())
+ {
+ throw JSONValidationError("The timestamp not a valid timestamp!");
+ }
+}
diff --git a/logic/minecraft/ParseUtils.h b/logic/minecraft/ParseUtils.h
new file mode 100644
index 00000000..73cf526a
--- /dev/null
+++ b/logic/minecraft/ParseUtils.h
@@ -0,0 +1,14 @@
+#pragma once
+#include <QString>
+#include <QDateTime>
+
+/**
+ * parse the S3 timestamp in 'raw' and fill the forwarded variables.
+ * return true/false for success/failure
+ */
+void parse_timestamp (const QString &raw, QString &save_here, QDateTime &parse_here);
+
+/**
+ * take the timestamp used by S3 and turn it into QDateTime
+ */
+QDateTime timeFromS3Time(QString str);
diff --git a/logic/minecraft/VersionBuildError.h b/logic/minecraft/VersionBuildError.h
new file mode 100644
index 00000000..ae479851
--- /dev/null
+++ b/logic/minecraft/VersionBuildError.h
@@ -0,0 +1,58 @@
+#include "MMCError.h"
+
+class VersionBuildError : public MMCError
+{
+public:
+ VersionBuildError(QString cause) : MMCError(cause) {};
+ virtual ~VersionBuildError() noexcept
+ {
+ }
+};
+
+/**
+ * the base version file was meant for a newer version of the vanilla launcher than we support
+ */
+class LauncherVersionError : public VersionBuildError
+{
+public:
+ LauncherVersionError(int actual, int supported)
+ : VersionBuildError(QObject::tr(
+ "The base version file of this instance was meant for a newer (%1) "
+ "version of the vanilla launcher than this version of MultiMC supports (%2).")
+ .arg(actual)
+ .arg(supported)) {};
+ virtual ~LauncherVersionError() noexcept
+ {
+ }
+};
+
+/**
+ * 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
+ */
+class VersionIncomplete : public VersionBuildError
+{
+public:
+ VersionIncomplete(QString missingPatch)
+ : VersionBuildError(QObject::tr("Version is incomplete: missing %1.")
+ .arg(missingPatch)) {};
+ virtual ~VersionIncomplete() noexcept
+ {
+ }
+}; \ No newline at end of file
diff --git a/logic/minecraft/VersionBuilder.cpp b/logic/minecraft/VersionBuilder.cpp
index 56eef424..d19c2877 100644
--- a/logic/minecraft/VersionBuilder.cpp
+++ b/logic/minecraft/VersionBuilder.cpp
@@ -23,12 +23,17 @@
#include <QObject>
#include <QDir>
#include <QDebug>
+#include <qresource.h>
#include <modutils.h>
+#include "MultiMC.h"
#include "logic/minecraft/VersionBuilder.h"
#include "logic/minecraft/VersionFinal.h"
#include "logic/minecraft/OneSixRule.h"
+#include "logic/minecraft/VersionPatch.h"
#include "logic/minecraft/VersionFile.h"
+#include "VersionBuildError.h"
+#include "MinecraftVersionList.h"
#include "logic/OneSixInstance.h"
#include "logic/MMCJson.h"
@@ -39,16 +44,17 @@ VersionBuilder::VersionBuilder()
{
}
-void VersionBuilder::build(VersionFinal *version, OneSixInstance *instance, const QStringList &external)
+void VersionBuilder::build(VersionFinal *version, OneSixInstance *instance,
+ const QStringList &external)
{
VersionBuilder builder;
builder.m_version = version;
builder.m_instance = instance;
- builder.buildInternal(external);
+ builder.external_patches = external;
+ builder.buildInternal();
}
-void VersionBuilder::readJsonAndApplyToVersion(VersionFinal *version,
- const QJsonObject &obj)
+void VersionBuilder::readJsonAndApplyToVersion(VersionFinal *version, const QJsonObject &obj)
{
VersionBuilder builder;
builder.m_version = version;
@@ -56,88 +62,143 @@ void VersionBuilder::readJsonAndApplyToVersion(VersionFinal *version,
builder.readJsonAndApply(obj);
}
-void VersionBuilder::buildInternal(const QStringList &external)
+void VersionBuilder::buildFromCustomJson()
{
- m_version->versionFiles.clear();
+ QLOG_INFO() << "Building version from custom.json within the instance.";
+ QLOG_INFO() << "Reading custom.json";
+ auto file = parseJsonFile(QFileInfo(instance_root.absoluteFilePath("custom.json")), false);
+ file->name = "custom.json";
+ file->filename = "custom.json";
+ file->fileId = "org.multimc.custom.json";
+ file->order = -1;
+ file->version = QString();
+ m_version->VersionPatches.append(file);
+ // QObject::tr("The version descriptors of this instance are not compatible with the
+ // current version of MultiMC"));
+ // QObject::tr("Error while applying %1. Please check MultiMC-0.log for more info.")
+ // some final touches
+ m_version->finalize();
+ return;
+}
- QDir root(m_instance->instanceRoot());
- QDir patches(root.absoluteFilePath("patches/"));
+void VersionBuilder::buildFromVersionJson()
+{
+ QLOG_INFO() << "Building version from version.json and patches within the instance.";
+ QLOG_INFO() << "Reading version.json";
+ auto file = parseJsonFile(QFileInfo(instance_root.absoluteFilePath("version.json")), false);
+ file->name = "Minecraft";
+ file->fileId = "org.multimc.version.json";
+ file->order = -1;
+ file->version = m_instance->intendedVersionId();
+ file->mcVersion = m_instance->intendedVersionId();
+ m_version->VersionPatches.append(file);
- // if we do external files, do just those.
- if (!external.isEmpty())
+ // load all patches, put into map for ordering, apply in the right order
+ readInstancePatches();
+
+ // some final touches
+ m_version->finalize();
+}
+
+void VersionBuilder::readInstancePatches()
+{
+ QDir patches(instance_root.absoluteFilePath("patches/"));
+ QMap<int, QPair<QString, VersionFilePtr>> files;
+ for (auto info : patches.entryInfoList(QStringList() << "*.json", QDir::Files))
{
- int externalOrder = -1;
- for (auto fileName : external)
+ QLOG_INFO() << "Reading" << info.fileName();
+ auto file = parseJsonFile(info, true);
+ if(file->fileId == "net.minecraft")
+ continue;
+ if(file->fileId == "org.lwjgl")
+ continue;
+ if (files.contains(file->order))
{
- QLOG_INFO() << "Reading" << fileName;
- auto file =
- parseJsonFile(QFileInfo(fileName), false, fileName.endsWith("pack.json"));
- file->name = QFileInfo(fileName).fileName();
- file->fileId = "org.multimc.external." + file->name;
- file->order = (externalOrder += 1);
- file->version = QString();
- file->mcVersion = QString();
- m_version->versionFiles.append(file);
+ throw VersionBuildError(QObject::tr("%1 has the same order as %2")
+ .arg(file->fileId, files[file->order].second->fileId));
}
+ files.insert(file->order, qMakePair(info.fileName(), file));
}
- // else, if there's custom json, we just do that.
- else if (QFile::exists(root.absoluteFilePath("custom.json")))
- {
- QLOG_INFO() << "Reading custom.json";
- auto file = parseJsonFile(QFileInfo(root.absoluteFilePath("custom.json")), false);
- file->name = "custom.json";
- file->filename = "custom.json";
- file->fileId = "org.multimc.custom.json";
- file->order = -1;
- file->version = QString();
- m_version->versionFiles.append(file);
- // QObject::tr("The version descriptors of this instance are not compatible with the
- // current version of MultiMC"));
- // QObject::tr("Error while applying %1. Please check MultiMC-0.log for more info.")
+ for (auto order : files.keys())
+ {
+ auto &filePair = files[order];
+ m_version->VersionPatches.append(filePair.second);
}
- // version.json -> patches/*.json -> user.json
- else
- do
- {
- // version.json
- QLOG_INFO() << "Reading version.json";
- auto file = parseJsonFile(QFileInfo(root.absoluteFilePath("version.json")), false);
- file->name = "Minecraft";
- file->fileId = "org.multimc.version.json";
- file->order = -1;
- file->version = m_instance->intendedVersionId();
- file->mcVersion = m_instance->intendedVersionId();
- m_version->versionFiles.append(file);
- // QObject::tr("Error while applying %1. Please check MultiMC-0.log for more
- // info.").arg(root.absoluteFilePath("version.json")));
-
- // patches/
- // load all, put into map for ordering, apply in the right order
-
- QMap<int, QPair<QString, VersionFilePtr>> files;
- for (auto info : patches.entryInfoList(QStringList() << "*.json", QDir::Files))
- {
- QLOG_INFO() << "Reading" << info.fileName();
- auto file = parseJsonFile(info, true);
- if (files.contains(file->order))
- {
- throw VersionBuildError(QObject::tr("%1 has the same order as %2").arg(
- file->fileId, files[file->order].second->fileId));
- }
- files.insert(file->order, qMakePair(info.fileName(), file));
- }
- for (auto order : files.keys())
- {
- auto &filePair = files[order];
- m_version->versionFiles.append(filePair.second);
- }
- } while (0);
+}
+void VersionBuilder::buildFromExternalPatches()
+{
+ QLOG_INFO() << "Building version from external files.";
+ int externalOrder = -1;
+ for (auto fileName : external_patches)
+ {
+ QLOG_INFO() << "Reading" << fileName;
+ auto file = parseJsonFile(QFileInfo(fileName), false, fileName.endsWith("pack.json"));
+ file->name = QFileInfo(fileName).fileName();
+ file->fileId = "org.multimc.external." + file->name;
+ file->order = (externalOrder += 1);
+ file->version = QString();
+ file->mcVersion = QString();
+ m_version->VersionPatches.append(file);
+ }
// some final touches
m_version->finalize();
}
+void VersionBuilder::buildFromMultilayer()
+{
+ QLOG_INFO() << "Building version from multilayered sources.";
+ // just the builtin stuff for now
+ auto minecraftList = MMC->minecraftlist();
+ auto mcversion = minecraftList->findVersion(m_instance->intendedVersionId());
+ auto minecraftPatch = std::dynamic_pointer_cast<VersionPatch>(mcversion);
+ if(!minecraftPatch)
+ {
+ throw VersionIncomplete("net.minecraft");
+ }
+ minecraftPatch->setOrder(-2);
+ m_version->VersionPatches.append(minecraftPatch);
+ QResource LWJGL(":/versions/LWJGL/2.9.1.json");
+ auto lwjgl = parseJsonFile(LWJGL.absoluteFilePath(), false, false);
+ auto lwjglPatch = std::dynamic_pointer_cast<VersionPatch>(lwjgl);
+ if(!lwjglPatch)
+ {
+ throw VersionIncomplete("org.lwjgl");
+ }
+ lwjglPatch->setOrder(-1);
+ m_version->VersionPatches.append(lwjglPatch);
+
+ // load all patches, put into map for ordering, apply in the right order
+ readInstancePatches();
+
+ m_version->finalize();
+}
+
+void VersionBuilder::buildInternal()
+{
+ m_version->VersionPatches.clear();
+ instance_root = QDir(m_instance->instanceRoot());
+ // if we do external files, do just those.
+ if (!external_patches.isEmpty())
+ {
+ buildFromExternalPatches();
+ }
+ // else, if there's custom json, we just do that.
+ else if (QFile::exists(instance_root.absoluteFilePath("custom.json")))
+ {
+ buildFromCustomJson();
+ }
+ // version.json -> patches/*.json
+ else if (QFile::exists(instance_root.absoluteFilePath("version.json")))
+ {
+ buildFromVersionJson();
+ }
+ else
+ {
+ buildFromMultilayer();
+ }
+}
void VersionBuilder::readJsonAndApply(const QJsonObject &obj)
{
@@ -147,14 +208,14 @@ void VersionBuilder::readJsonAndApply(const QJsonObject &obj)
// QObject::tr("Error while reading. Please check MultiMC-0.log for more info."));
file->applyTo(m_version);
- m_version->versionFiles.append(file);
+ m_version->VersionPatches.append(file);
// QObject::tr("Error while applying. Please check MultiMC-0.log for more info."));
// QObject::tr("The version descriptors of this instance are not compatible with the current
// version of MultiMC"));
}
-VersionFilePtr VersionBuilder::parseJsonFile(const QFileInfo &fileInfo,
- const bool requireOrder, bool isFTB)
+VersionFilePtr VersionBuilder::parseJsonFile(const QFileInfo &fileInfo, const bool requireOrder,
+ bool isFTB)
{
QFile file(fileInfo.absoluteFilePath());
if (!file.open(QFile::ReadOnly))
@@ -166,9 +227,10 @@ VersionFilePtr VersionBuilder::parseJsonFile(const QFileInfo &fileInfo,
QJsonDocument doc = QJsonDocument::fromJson(file.readAll(), &error);
if (error.error != QJsonParseError::NoError)
{
- throw JSONValidationError(QObject::tr("Unable to process the version file %1: %2 at %3.")
- .arg(fileInfo.fileName(), error.errorString())
- .arg(error.offset));
+ throw JSONValidationError(
+ QObject::tr("Unable to process the version file %1: %2 at %3.")
+ .arg(fileInfo.fileName(), error.errorString())
+ .arg(error.offset));
}
return VersionFile::fromJson(doc, file.fileName(), requireOrder, isFTB);
// QObject::tr("Error while reading %1. Please check MultiMC-0.log for more
@@ -226,7 +288,7 @@ QMap<QString, int> VersionBuilder::readOverrideOrders(OneSixInstance *instance)
}
bool VersionBuilder::writeOverrideOrders(const QMap<QString, int> &order,
- OneSixInstance *instance)
+ OneSixInstance *instance)
{
QJsonObject obj;
for (auto it = order.cbegin(); it != order.cend(); ++it)
diff --git a/logic/minecraft/VersionBuilder.h b/logic/minecraft/VersionBuilder.h
index ac93ef11..c56e6c18 100644
--- a/logic/minecraft/VersionBuilder.h
+++ b/logic/minecraft/VersionBuilder.h
@@ -37,8 +37,17 @@ public:
private:
VersionFinal *m_version;
OneSixInstance *m_instance;
-
- void buildInternal(const QStringList& external);
+ QStringList external_patches;
+ QDir instance_root;
+
+ void buildInternal();
+ void buildFromExternalPatches();
+ void buildFromCustomJson();
+ void buildFromVersionJson();
+ void buildFromMultilayer();
+
+ void readInstancePatches();
+
void readJsonAndApply(const QJsonObject &obj);
VersionFilePtr parseJsonFile(const QFileInfo &fileInfo, const bool requireOrder,
diff --git a/logic/minecraft/VersionFile.cpp b/logic/minecraft/VersionFile.cpp
index e1b03e6c..bc9c42c1 100644
--- a/logic/minecraft/VersionFile.cpp
+++ b/logic/minecraft/VersionFile.cpp
@@ -8,10 +8,13 @@
#include "logic/minecraft/OneSixLibrary.h"
#include "logic/minecraft/VersionFinal.h"
#include "logic/minecraft/JarMod.h"
+#include "ParseUtils.h"
#include "logic/MMCJson.h"
using namespace MMCJson;
+#include "VersionBuildError.h"
+
#define CURRENT_MINIMUM_LAUNCHER_VERSION 14
int findLibrary(QList<OneSixLibraryPtr> haystack, const QString &needle)
@@ -23,7 +26,7 @@ int findLibrary(QList<OneSixLibraryPtr> haystack, const QString &needle)
if (QRegExp(needle, Qt::CaseSensitive, QRegExp::WildcardUnix).indexIn(chunk) != -1)
{
// only one is allowed.
- if(retval != -1)
+ if (retval != -1)
return -1;
retval = i;
}
@@ -32,7 +35,7 @@ int findLibrary(QList<OneSixLibraryPtr> haystack, const QString &needle)
}
VersionFilePtr VersionFile::fromJson(const QJsonDocument &doc, const QString &filename,
- const bool requireOrder, const bool isFTB)
+ const bool requireOrder, const bool isFTB)
{
VersionFilePtr out(new VersionFile());
if (doc.isEmpty() || doc.isNull())
@@ -41,7 +44,6 @@ VersionFilePtr VersionFile::fromJson(const QJsonDocument &doc, const QString &fi
}
if (!doc.isObject())
{
- throw JSONValidationError("The root of " + filename + " is not an object");
}
QJsonObject root = doc.object();
@@ -65,7 +67,7 @@ VersionFilePtr VersionFile::fromJson(const QJsonDocument &doc, const QString &fi
out->mcVersion = root.value("mcVersion").toString();
out->filename = filename;
- auto readString = [root, filename](const QString & key, QString & variable)
+ auto readString = [root](const QString & key, QString & variable)
{
if (root.contains(key))
{
@@ -73,6 +75,16 @@ VersionFilePtr VersionFile::fromJson(const QJsonDocument &doc, const QString &fi
}
};
+ auto readStringRet = [root](const QString & key)->QString
+ {
+ if (root.contains(key))
+ {
+ return ensureString(root.value(key));
+ }
+ return QString();
+ }
+ ;
+
// FIXME: This should be ignored when applying.
if (!isFTB)
{
@@ -86,8 +98,14 @@ VersionFilePtr VersionFile::fromJson(const QJsonDocument &doc, const QString &fi
readString("+minecraftArguments", out->addMinecraftArguments);
readString("-minecraftArguments", out->removeMinecraftArguments);
readString("type", out->type);
- readString("releaseTime", out->versionReleaseTime);
- readString("time", out->versionFileUpdateTime);
+ if (out->isVanilla())
+ {
+ parse_timestamp(readStringRet("releaseTime"), out->m_releaseTimeString,
+ out->m_releaseTime);
+ parse_timestamp(readStringRet("time"), out->m_updateTimeString, out->m_updateTime);
+ }
+
+ readStringRet("time");
readString("assets", out->assets);
if (root.contains("minimumLauncherVersion"))
@@ -284,7 +302,8 @@ void VersionFile::applyTo(VersionFinal *version)
{
if (minimumLauncherVersion > CURRENT_MINIMUM_LAUNCHER_VERSION)
{
- throw LauncherVersionError(minimumLauncherVersion, CURRENT_MINIMUM_LAUNCHER_VERSION);
+ throw LauncherVersionError(minimumLauncherVersion,
+ CURRENT_MINIMUM_LAUNCHER_VERSION);
}
}
@@ -311,23 +330,28 @@ void VersionFile::applyTo(VersionFinal *version)
}
if (!processArguments.isNull())
{
- if(isVanilla())
+ if (isVanilla())
{
version->vanillaProcessArguments = processArguments;
}
version->processArguments = processArguments;
}
- if (!type.isNull())
+ if(isVanilla())
{
- version->type = type;
- }
- if (!versionReleaseTime.isNull())
- {
- version->versionReleaseTime = versionReleaseTime;
- }
- if (!versionFileUpdateTime.isNull())
- {
- version->time = versionFileUpdateTime;
+ if (!type.isNull())
+ {
+ version->type = type;
+ }
+ if (!m_releaseTimeString.isNull())
+ {
+ version->m_releaseTimeString = m_releaseTimeString;
+ version->m_releaseTime = m_releaseTime;
+ }
+ if (!m_updateTimeString.isNull())
+ {
+ version->m_updateTimeString = m_updateTimeString;
+ version->m_updateTime = m_updateTime;
+ }
}
if (!assets.isNull())
{
@@ -335,11 +359,12 @@ void VersionFile::applyTo(VersionFinal *version)
}
if (minimumLauncherVersion >= 0)
{
- version->minimumLauncherVersion = minimumLauncherVersion;
+ if(version->minimumLauncherVersion < minimumLauncherVersion)
+ version->minimumLauncherVersion = minimumLauncherVersion;
}
if (!overwriteMinecraftArguments.isNull())
{
- if(isVanilla())
+ if (isVanilla())
{
version->vanillaMinecraftArguments = overwriteMinecraftArguments;
}
@@ -374,7 +399,7 @@ void VersionFile::applyTo(VersionFinal *version)
{
libs.append(createLibrary(lib));
}
- if(isVanilla())
+ if (isVanilla())
version->vanillaLibraries = libs;
version->libraries = libs;
}
@@ -498,7 +523,7 @@ void VersionFile::applyTo(VersionFinal *version)
case RawLibrary::Replace:
{
QString toReplace;
- if(lib->insertData.isEmpty())
+ if (lib->insertData.isEmpty())
{
const int startOfVersion = lib->name.lastIndexOf(':') + 1;
toReplace = QString(lib->name).replace(startOfVersion, INT_MAX, '*');
diff --git a/logic/minecraft/VersionFile.h b/logic/minecraft/VersionFile.h
index 82b16913..9c632d6f 100644
--- a/logic/minecraft/VersionFile.h
+++ b/logic/minecraft/VersionFile.h
@@ -2,6 +2,7 @@
#include <QString>
#include <QStringList>
+#include <QDateTime>
#include <memory>
#include "logic/minecraft/OpSys.h"
#include "logic/minecraft/OneSixRule.h"
@@ -11,46 +12,8 @@
#include "JarMod.h"
class VersionFinal;
-
-
-class VersionBuildError : public MMCError
-{
-public:
- VersionBuildError(QString cause) : MMCError(cause) {};
- virtual ~VersionBuildError() noexcept {}
-};
-
-/**
- * the base version file was meant for a newer version of the vanilla launcher than we support
- */
-class LauncherVersionError : public VersionBuildError
-{
-public:
- LauncherVersionError(int actual, int supported)
- : VersionBuildError(QObject::tr(
- "The base version file of this instance was meant for a newer (%1) "
- "version of the vanilla launcher than this version of MultiMC supports (%2).")
- .arg(actual)
- .arg(supported)) {};
- virtual ~LauncherVersionError() noexcept {}
-};
-
-/**
- * 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 {}
-};
-
struct VersionFile;
+
typedef std::shared_ptr<VersionFile> VersionFilePtr;
class VersionFile : public VersionPatch
{
@@ -62,7 +25,35 @@ public: /* methods */
virtual void applyTo(VersionFinal *version) override;
virtual bool isVanilla() override;
virtual bool hasJarMods() override;
-
+ virtual int getOrder() override
+ {
+ return order;
+ }
+ virtual void setOrder(int order) override
+ {
+ this->order = order;
+ }
+ virtual QList<JarmodPtr> getJarMods() override
+ {
+ return jarMods;
+ }
+ virtual QString getPatchID() override
+ {
+ return fileId;
+ }
+ virtual QString getPatchName() override
+ {
+ return name;
+ }
+ virtual QString getPatchVersion() override
+ {
+ return version;
+ }
+ virtual QString getPatchFilename() override
+ {
+ return filename;
+ }
+
public: /* data */
int order = 0;
QString name;
@@ -81,8 +72,16 @@ public: /* data */
QString removeMinecraftArguments;
QString processArguments;
QString type;
- QString versionReleaseTime;
- QString versionFileUpdateTime;
+
+ /// the time this version was actually released by Mojang, as string and as QDateTime
+ QString m_releaseTimeString;
+ QDateTime m_releaseTime;
+
+ /// the time this version was last updated by Mojang, as string and as QDateTime
+ QString m_updateTimeString;
+ QDateTime m_updateTime;
+
+ /// asset group used by this ... thing.
QString assets;
int minimumLauncherVersion = -1;
diff --git a/logic/minecraft/VersionFinal.cpp b/logic/minecraft/VersionFinal.cpp
index 07f58778..cc61da71 100644
--- a/logic/minecraft/VersionFinal.cpp
+++ b/logic/minecraft/VersionFinal.cpp
@@ -39,8 +39,10 @@ void VersionFinal::reload(const QStringList &external)
void VersionFinal::clear()
{
id.clear();
- time.clear();
- versionReleaseTime.clear();
+ m_updateTimeString.clear();
+ m_updateTime = QDateTime();
+ m_releaseTimeString.clear();
+ m_releaseTime = QDateTime();
type.clear();
assets.clear();
processArguments.clear();
@@ -56,17 +58,13 @@ void VersionFinal::clear()
bool VersionFinal::canRemove(const int index) const
{
- if (index < versionFiles.size())
- {
- return versionFiles.at(index)->fileId != "org.multimc.version.json";
- }
- return false;
+ return VersionPatches.at(index)->isMoveable();
}
-bool VersionFinal::preremove(VersionFilePtr versionfile)
+bool VersionFinal::preremove(VersionPatchPtr patch)
{
bool ok = true;
- for(auto & jarmod: versionfile->jarMods)
+ for(auto & jarmod: patch->getJarMods())
{
QString fullpath =PathCombine(m_instance->jarModsDir(), jarmod->name);
QFileInfo finfo (fullpath);
@@ -80,14 +78,14 @@ bool VersionFinal::remove(const int index)
{
if (!canRemove(index))
return false;
- if(!preremove(versionFiles[index]))
+ if(!preremove(VersionPatches[index]))
{
return false;
}
- if(!QFile::remove(versionFiles.at(index)->filename))
+ if(!QFile::remove(VersionPatches.at(index)->getPatchFilename()))
return false;
beginResetModel();
- versionFiles.removeAt(index);
+ VersionPatches.removeAt(index);
reapply(true);
endResetModel();
return true;
@@ -96,9 +94,9 @@ bool VersionFinal::remove(const int index)
bool VersionFinal::remove(const QString id)
{
int i = 0;
- for (auto file : versionFiles)
+ for (auto patch : VersionPatches)
{
- if (file->fileId == id)
+ if (patch->getPatchID() == id)
{
return remove(i);
}
@@ -109,18 +107,18 @@ bool VersionFinal::remove(const QString id)
QString VersionFinal::versionFileId(const int index) const
{
- if (index < 0 || index >= versionFiles.size())
+ if (index < 0 || index >= VersionPatches.size())
{
return QString();
}
- return versionFiles.at(index)->fileId;
+ return VersionPatches.at(index)->getPatchID();
}
-VersionFilePtr VersionFinal::versionPatch(const QString &id)
+VersionPatchPtr VersionFinal::versionPatch(const QString &id)
{
- for (auto file : versionFiles)
+ for (auto file : VersionPatches)
{
- if (file->fileId == id)
+ if (file->getPatchID() == id)
{
return file;
}
@@ -128,6 +126,14 @@ VersionFilePtr VersionFinal::versionPatch(const QString &id)
return 0;
}
+VersionPatchPtr VersionFinal::versionPatch(int index)
+{
+ if(index < 0 || index >= VersionPatches.size())
+ return 0;
+ return VersionPatches[index];
+}
+
+
bool VersionFinal::hasJarMods()
{
return !jarMods.isEmpty();
@@ -146,7 +152,7 @@ bool VersionFinal::removeFtbPack()
bool VersionFinal::isVanilla()
{
QDir patches(PathCombine(m_instance->instanceRoot(), "patches/"));
- if(versionFiles.size() > 1)
+ if(VersionPatches.size() > 1)
return false;
if(QFile::exists(PathCombine(m_instance->instanceRoot(), "custom.json")))
return false;
@@ -156,22 +162,22 @@ bool VersionFinal::isVanilla()
bool VersionFinal::revertToVanilla()
{
beginResetModel();
- auto it = versionFiles.begin();
- while (it != versionFiles.end())
+ auto it = VersionPatches.begin();
+ while (it != VersionPatches.end())
{
- if ((*it)->fileId != "org.multimc.version.json")
+ if ((*it)->isMoveable())
{
if(!preremove(*it))
{
endResetModel();
return false;
}
- if(!QFile::remove((*it)->filename))
+ if(!QFile::remove((*it)->getPatchFilename()))
{
endResetModel();
return false;
}
- it = versionFiles.erase(it);
+ it = VersionPatches.erase(it);
}
else
it++;
@@ -233,7 +239,7 @@ QVariant VersionFinal::data(const QModelIndex &index, int role) const
int row = index.row();
int column = index.column();
- if (row < 0 || row >= versionFiles.size())
+ if (row < 0 || row >= VersionPatches.size())
return QVariant();
if (role == Qt::DisplayRole)
@@ -241,9 +247,9 @@ QVariant VersionFinal::data(const QModelIndex &index, int role) const
switch (column)
{
case 0:
- return versionFiles.at(row)->name;
+ return VersionPatches.at(row)->getPatchName();
case 1:
- return versionFiles.at(row)->version;
+ return VersionPatches.at(row)->getPatchVersion();
default:
return QVariant();
}
@@ -278,7 +284,7 @@ Qt::ItemFlags VersionFinal::flags(const QModelIndex &index) const
int VersionFinal::rowCount(const QModelIndex &parent) const
{
- return versionFiles.size();
+ return VersionPatches.size();
}
int VersionFinal::columnCount(const QModelIndex &parent) const
@@ -288,13 +294,12 @@ int VersionFinal::columnCount(const QModelIndex &parent) const
QMap<QString, int> VersionFinal::getExistingOrder() const
{
-
QMap<QString, int> order;
// default
{
- for (auto file : versionFiles)
+ for (auto file : VersionPatches)
{
- order.insert(file->fileId, file->order);
+ order.insert(file->getPatchID(), file->getOrder());
}
}
// overriden
@@ -314,39 +319,37 @@ QMap<QString, int> VersionFinal::getExistingOrder() const
void VersionFinal::move(const int index, const MoveDirection direction)
{
int theirIndex;
+ int theirIndex_qt;
if (direction == MoveUp)
{
- theirIndex = index - 1;
+ theirIndex_qt = theirIndex = index - 1;
}
else
{
theirIndex = index + 1;
+ theirIndex_qt = index + 2;
}
- if (theirIndex < 0 || theirIndex >= versionFiles.size())
- {
- return;
- }
- const QString ourId = versionFileId(index);
- const QString theirId = versionFileId(theirIndex);
- if (ourId.isNull() || ourId.startsWith("org.multimc.") ||
- theirId.isNull() || theirId.startsWith("org.multimc."))
+ auto from = versionPatch(index);
+ auto to = versionPatch(theirIndex);
+
+ if (!from || !to || !from->isMoveable() || !from->isMoveable())
{
return;
}
if(direction == MoveDown)
{
- beginMoveRows(QModelIndex(), index, index, QModelIndex(), theirIndex+1);
+ beginMoveRows(QModelIndex(), index, index, QModelIndex(), theirIndex_qt);
}
else
{
- beginMoveRows(QModelIndex(), index, index, QModelIndex(), theirIndex);
+ beginMoveRows(QModelIndex(), index, index, QModelIndex(), theirIndex_qt);
}
- versionFiles.swap(index, theirIndex);
+ VersionPatches.swap(index, theirIndex);
endMoveRows();
auto order = getExistingOrder();
- order[ourId] = theirIndex;
- order[theirId] = index;
+ order[from->getPatchID()] = theirIndex;
+ order[to->getPatchID()] = index;
if (!VersionBuilder::writeOverrideOrders(order, m_instance))
{
@@ -375,14 +378,14 @@ void VersionFinal::reapply(const bool alreadyReseting)
auto existingOrders = getExistingOrder();
QList<int> orders = existingOrders.values();
std::sort(orders.begin(), orders.end());
- QList<VersionFilePtr> newVersionFiles;
+ QList<VersionPatchPtr> newVersionFiles;
for (auto order : orders)
{
auto file = versionPatch(existingOrders.key(order));
newVersionFiles.append(file);
file->applyTo(this);
}
- versionFiles.swap(newVersionFiles);
+ VersionPatches.swap(newVersionFiles);
finalize();
if (!alreadyReseting)
{
diff --git a/logic/minecraft/VersionFinal.h b/logic/minecraft/VersionFinal.h
index 7be981ed..83a88263 100644
--- a/logic/minecraft/VersionFinal.h
+++ b/logic/minecraft/VersionFinal.h
@@ -83,16 +83,21 @@ public:
static std::shared_ptr<VersionFinal> fromJson(const QJsonObject &obj);
private:
- bool preremove(VersionFilePtr);
+ bool preremove(VersionPatchPtr patch);
// data members
public:
/// the ID - determines which jar to use! ACTUALLY IMPORTANT!
QString id;
- /// Last updated time - as a string
- QString time;
- /// Release time - as a string
- QString versionReleaseTime;
+
+ /// the time this version was actually released by Mojang, as string and as QDateTime
+ QString m_releaseTimeString;
+ QDateTime m_releaseTime;
+
+ /// the time this version was last updated by Mojang, as string and as QDateTime
+ QString m_updateTimeString;
+ QDateTime m_updateTime;
+
/// Release type - "release" or "snapshot"
QString type;
/// Assets type - "legacy" or a version ID
@@ -164,8 +169,9 @@ public:
*/
// QList<Rule> rules;
- QList<VersionFilePtr> versionFiles;
- VersionFilePtr versionPatch(const QString &id);
+ QList<VersionPatchPtr> VersionPatches;
+ VersionPatchPtr versionPatch(const QString &id);
+ VersionPatchPtr versionPatch(int index);
private:
OneSixInstance *m_instance;
diff --git a/logic/minecraft/VersionPatch.h b/logic/minecraft/VersionPatch.h
index c2258787..cdb80199 100644
--- a/logic/minecraft/VersionPatch.h
+++ b/logic/minecraft/VersionPatch.h
@@ -1,6 +1,8 @@
#pragma once
#include <memory>
+#include <QList>
+#include "JarMod.h"
class VersionFinal;
class VersionPatch
@@ -8,8 +10,22 @@ class VersionPatch
public:
virtual ~VersionPatch(){};
virtual void applyTo(VersionFinal *version) = 0;
+
virtual bool isVanilla() = 0;
virtual bool hasJarMods() = 0;
+ virtual QList<JarmodPtr> getJarMods() = 0;
+
+ virtual bool isMoveable()
+ {
+ return getOrder() >= 0;
+ }
+ virtual void setOrder(int order) = 0;
+ virtual int getOrder() = 0;
+
+ virtual QString getPatchID() = 0;
+ virtual QString getPatchName() = 0;
+ virtual QString getPatchVersion() = 0;
+ virtual QString getPatchFilename() = 0;
};
typedef std::shared_ptr<VersionPatch> VersionPatchPtr;