summaryrefslogtreecommitdiffstats
path: root/logic/OneSixVersionBuilder.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'logic/OneSixVersionBuilder.cpp')
-rw-r--r--logic/OneSixVersionBuilder.cpp1002
1 files changed, 715 insertions, 287 deletions
diff --git a/logic/OneSixVersionBuilder.cpp b/logic/OneSixVersionBuilder.cpp
index 85f55a52..c031a94a 100644
--- a/logic/OneSixVersionBuilder.cpp
+++ b/logic/OneSixVersionBuilder.cpp
@@ -31,416 +31,844 @@
#include "OneSixRule.h"
#include "logger/QsLog.h"
-OneSixVersionBuilder::OneSixVersionBuilder()
-{
-
-}
-
-bool OneSixVersionBuilder::build(OneSixVersion *version, OneSixInstance *instance, QWidget *widgetParent)
+struct VersionFile
{
- OneSixVersionBuilder builder;
- builder.m_version = version;
- builder.m_instance = instance;
- builder.m_widgetParent = widgetParent;
- return builder.build();
-}
-
-bool OneSixVersionBuilder::read(OneSixVersion *version, const QJsonObject &obj)
-{
- OneSixVersionBuilder builder;
- builder.m_version = version;
- builder.m_instance = 0;
- builder.m_widgetParent = 0;
- return builder.read(obj);
-}
-
-bool OneSixVersionBuilder::build()
-{
- m_version->clear();
-
- QDir root(m_instance->instanceRoot());
- QDir patches(root.absoluteFilePath("patches/"));
-
- // version.json -> patches/*.json -> custom.json
+ int order;
+ QString id;
+ QString mainClass;
+ QString overwriteMinecraftArguments;
+ QString addMinecraftArguments;
+ QString removeMinecraftArguments;
+ QString processArguments;
+ QString type;
+ QString releaseTime;
+ QString time;
+ QString assets;
+ int minimumLauncherVersion = -1;
+
+ bool shouldOverwriteTweakers = false;
+ QStringList overwriteTweakers;
+ QStringList addTweakers;
+ QStringList removeTweakers;
+
+ struct Library
+ {
+ QString name;
+ QString url;
+ QString hint;
+ QString absoluteUrl;
+ bool applyExcludes = false;
+ QStringList excludes;
+ bool applyNatives = false;
+ QList<QPair<OpSys, QString>> natives;
+ bool applyRules = false;
+ QList<std::shared_ptr<Rule>> rules;
- // version.json
+ // user for '+' libraries
+ enum InsertType
+ {
+ Apply,
+ Append,
+ Prepend,
+ InsertBefore,
+ InsertAfter,
+ Replace
+ };
+ InsertType insertType;
+ QString insertData;
+ };
+ bool shouldOverwriteLibs = false;
+ QList<Library> overwriteLibs;
+ QList<Library> addLibs;
+ QList<QString> removeLibs;
+
+ static Library fromLibraryJson(const QJsonObject &libObj, const QString &filename,
+ bool &isError)
{
- QLOG_INFO() << "Reading version.json";
- QJsonObject obj;
- if (!read(QFileInfo(root.absoluteFilePath("version.json")), &obj))
+ isError = true;
+ Library out;
+ if (!libObj.contains("name"))
{
- return false;
+ QLOG_ERROR() << filename << "contains a library that doesn't have a 'name' field";
+ return out;
}
- if (!apply(obj))
- {
- return false;
- }
- }
+ out.name = libObj.value("name").toString();
- // patches/
- {
- // load all, put into map for ordering, apply in the right order
+ auto readString = [libObj, filename](const QString &key, QString &variable)
+ {
+ if (libObj.contains(key))
+ {
+ QJsonValue val = libObj.value(key);
+ if (!val.isString())
+ {
+ QLOG_WARN() << key << "is not a string in" << filename << "(skipping)";
+ }
+ else
+ {
+ variable = val.toString();
+ }
+ }
+ };
- QMap<int, QJsonObject> objects;
- for (auto info : patches.entryInfoList(QStringList() << "*.json", QDir::Files))
+ readString("url", out.url);
+ readString("MMC-hint", out.hint);
+ readString("MMC-absulute_url", out.absoluteUrl);
+ readString("MMC-absoluteUrl", out.absoluteUrl);
+ if (libObj.contains("extract"))
{
- QLOG_INFO() << "Reading" << info.fileName();
- QJsonObject obj;
- if (!read(info, &obj))
+ if (!libObj.value("extract").isObject())
{
- return false;
+ QLOG_ERROR()
+ << filename
+ << "contains a library with an 'extract' field that's not an object";
+ return out;
}
- if (!obj.contains("order") || !obj.value("order").isDouble())
+ QJsonObject extractObj = libObj.value("extract").toObject();
+ if (!extractObj.contains("exclude") || !extractObj.value("exclude").isArray())
{
- QMessageBox::critical(m_widgetParent, QObject::tr("Error"), QObject::tr("Missing or invalid 'order' in %1").arg(info.absoluteFilePath()));
- return false;
+ QLOG_ERROR() << filename
+ << "contains a library with an invalid 'extract' field";
+ return out;
}
- objects.insert(obj.value("order").toDouble(), obj);
- }
- for (auto object : objects.values())
- {
- qDebug() << "Applying object with order" << objects.key(object);
- if (!apply(object))
+ out.applyExcludes = true;
+ QJsonArray excludeArray = extractObj.value("exclude").toArray();
+ for (auto excludeVal : excludeArray)
{
- return false;
+ if (!excludeVal.isString())
+ {
+ QLOG_WARN() << filename << "contains a library that contains an 'extract' "
+ "field that contains an invalid 'exclude' entry "
+ "(skipping)";
+ }
+ else
+ {
+ out.excludes.append(excludeVal.toString());
+ }
}
}
- }
-
- // custom.json
- {
- if (QFile::exists(root.absoluteFilePath("custom.json")))
+ if (libObj.contains("natives"))
{
- QLOG_INFO() << "Reading custom.json";
- QJsonObject obj;
- if (!read(QFileInfo(root.absoluteFilePath("custom.json")), &obj))
+ if (!libObj.value("natives").isObject())
{
- return false;
+ QLOG_ERROR()
+ << filename
+ << "contains a library with a 'natives' field that's not an object";
+ return out;
}
- if (!apply(obj))
+ out.applyNatives = true;
+ QJsonObject nativesObj = libObj.value("natives").toObject();
+ for (auto it = nativesObj.begin(); it != nativesObj.end(); ++it)
{
- return false;
+ if (!it.value().isString())
+ {
+ QLOG_WARN() << filename << "contains an invalid native (skipping)";
+ }
+ OpSys opSys = OpSys_fromString(it.key());
+ if (opSys != Os_Other)
+ {
+ out.natives.append(qMakePair(opSys, it.value().toString()));
+ }
}
}
+ if (libObj.contains("rules"))
+ {
+ out.applyRules = true;
+ out.rules = rulesFromJsonV4(libObj);
+ }
+ isError = false;
+ return out;
}
-
- return true;
-}
-
-bool OneSixVersionBuilder::read(const QJsonObject &obj)
-{
- m_version->clear();
-
- return apply(obj);
-}
-
-void applyString(const QJsonObject &obj, const QString &key, QString &out, const bool onlyOverride = true)
-{
- if (obj.contains(key) && obj.value(key).isString())
- {
- out = obj.value(key).toString();
- }
- else if (!onlyOverride)
+ static VersionFile fromJson(const QJsonDocument &doc, const QString &filename,
+ const bool requireOrder, bool &isError)
{
- if (obj.contains("+" + key) && obj.value("+" + key).isString())
+ VersionFile out;
+ isError = true;
+ if (doc.isEmpty() || doc.isNull())
{
- out += obj.value("+" + key).toString();
+ QLOG_ERROR() << filename << "is empty or null";
+ return out;
}
- else if (obj.contains("-" + key) && obj.value("-" + key).isString())
+ if (!doc.isObject())
{
- out.remove(obj.value("-" + key).toString());
+ QLOG_ERROR() << "The root of" << filename << "is not an object";
+ return out;
}
- }
-}
-void applyString(const QJsonObject &obj, const QString &key, std::shared_ptr<OneSixLibrary> lib, void(OneSixLibrary::*func)(const QString &val))
-{
- if (obj.contains(key) && obj.value(key).isString())
- {
- (lib.get()->*func)(obj.value(key).toString());
- }
-}
-bool OneSixVersionBuilder::apply(const QJsonObject &object)
-{
- applyString(object, "id", m_version->id);
- applyString(object, "mainClass", m_version->mainClass);
- applyString(object, "minecraftArguments", m_version->minecraftArguments, false);
- applyString(object, "processArguments", m_version->processArguments, false);
- if (m_version->minecraftArguments.isEmpty())
- {
- const QString toCompare = m_version->processArguments.toLower();
- if (toCompare == "legacy")
+
+ QJsonObject root = doc.object();
+
+ if (requireOrder)
{
- m_version->minecraftArguments = " ${auth_player_name} ${auth_session}";
+ if (root.contains("order"))
+ {
+ if (root.value("order").isDouble())
+ {
+ out.order = root.value("order").toDouble();
+ }
+ else
+ {
+ QLOG_ERROR() << "'order' field contains an invalid value in" << filename;
+ return out;
+ }
+ }
+ else
+ {
+ QLOG_ERROR() << filename << "doesn't contain an order field";
+ }
}
- else if (toCompare == "username_session")
+
+ auto readString = [root, filename](const QString &key, QString &variable)
+ {
+ if (root.contains(key))
+ {
+ QJsonValue val = root.value(key);
+ if (!val.isString())
+ {
+ QLOG_WARN() << key << "is not a string in" << filename << "(skipping)";
+ }
+ else
+ {
+ variable = val.toString();
+ }
+ }
+ };
+
+ readString("id", out.id);
+ readString("mainClass", out.mainClass);
+ readString("processArguments", out.processArguments);
+ readString("minecraftArguments", out.overwriteMinecraftArguments);
+ readString("+minecraftArguments", out.addMinecraftArguments);
+ readString("-minecraftArguments", out.removeMinecraftArguments);
+ readString("type", out.type);
+ readString("releaseTime", out.releaseTime);
+ readString("time", out.time);
+ readString("assets", out.assets);
+ if (root.contains("minimumLauncherVersion"))
{
- m_version->minecraftArguments = "--username ${auth_player_name} --session ${auth_session}";
+ QJsonValue val = root.value("minimumLauncherVersion");
+ if (!val.isDouble())
+ {
+ QLOG_WARN() << "minimumLauncherVersion is not an int in" << filename
+ << "(skipping)";
+ }
+ else
+ {
+ out.minimumLauncherVersion = val.toDouble();
+ }
}
- else if (toCompare == "username_session_version")
+
+ if (root.contains("tweakers"))
{
- m_version->minecraftArguments = "--username ${auth_player_name} --session ${auth_session} --version ${profile_name}";
+ QJsonValue tweakersVal = root.value("tweakers");
+ if (!tweakersVal.isArray())
+ {
+ QLOG_ERROR() << filename << "contains a 'tweakers' field, but it's not an array";
+ return out;
+ }
+ out.shouldOverwriteTweakers = true;
+ QJsonArray tweakers = root.value("tweakers").toArray();
+ for (auto tweakerVal : tweakers)
+ {
+ if (!tweakerVal.isString())
+ {
+ QLOG_ERROR() << filename << "contains a 'tweakers' field entry that's not a string";
+ return out;
+ }
+ out.overwriteTweakers.append(tweakerVal.toString());
+ }
}
- }
- applyString(object, "type", m_version->type);
- applyString(object, "releaseTime", m_version->releaseTime);
- applyString(object, "time", m_version->time);
- applyString(object, "assets", m_version->assets);
- {
- if (m_version->assets.isEmpty())
+ if (root.contains("+tweakers"))
{
- m_version->assets = "legacy";
+ QJsonValue tweakersVal = root.value("+tweakers");
+ if (!tweakersVal.isArray())
+ {
+ QLOG_ERROR() << filename << "contains a '+tweakers' field, but it's not an array";
+ return out;
+ }
+ QJsonArray tweakers = root.value("+tweakers").toArray();
+ for (auto tweakerVal : tweakers)
+ {
+ if (!tweakerVal.isString())
+ {
+ QLOG_ERROR() << filename << "contains a '+tweakers' field entry that's not a string";
+ return out;
+ }
+ out.addTweakers.append(tweakerVal.toString());
+ }
}
- }
- if (object.contains("minimumLauncherVersion"))
- {
- auto minLauncherVersionVal = object.value("minimumLauncherVersion");
- if (minLauncherVersionVal.isDouble())
+ if (root.contains("-tweakers"))
{
- m_version->minimumLauncherVersion = minLauncherVersionVal.toDouble();
+ QJsonValue tweakersVal = root.value("-tweakers");
+ if (!tweakersVal.isArray())
+ {
+ QLOG_ERROR() << filename << "contains a '-tweakers' field, but it's not an array";
+ return out;
+ }
+ out.shouldOverwriteTweakers = true;
+ QJsonArray tweakers = root.value("-tweakers").toArray();
+ for (auto tweakerVal : tweakers)
+ {
+ if (!tweakerVal.isString())
+ {
+ QLOG_ERROR() << filename << "contains a '-tweakers' field entry that's not a string";
+ return out;
+ }
+ out.removeTweakers.append(tweakerVal.toString());
+ }
}
- }
- // libraries
- if (object.contains("libraries"))
- {
- m_version->libraries.clear();
- auto librariesValue = object.value("libraries");
- if (!librariesValue.isArray())
+ if (root.contains("libraries"))
{
- QMessageBox::critical(m_widgetParent, QObject::tr("Error"), QObject::tr("One json files contains a libraries field, but it's not an array"));
- return false;
+ out.shouldOverwriteLibs = true;
+ QJsonValue librariesVal = root.value("libraries");
+ if (!librariesVal.isArray())
+ {
+ QLOG_ERROR() << filename
+ << "contains a 'libraries' field, but its not an array";
+ return out;
+ }
+ QJsonArray librariesArray = librariesVal.toArray();
+ for (auto libVal : librariesArray)
+ {
+ if (!libVal.isObject())
+ {
+ QLOG_ERROR() << filename << "contains a library that's not an object";
+ return out;
+ }
+ QJsonObject libObj = libVal.toObject();
+ bool error;
+ Library lib = fromLibraryJson(libObj, filename, error);
+ if (error)
+ {
+ QLOG_ERROR() << "Error while reading a library entry in" << filename;
+ return out;
+ }
+ out.overwriteLibs.append(lib);
+ }
}
- auto array = librariesValue.toArray();
- for (auto libVal : array)
+ if (root.contains("+libraries"))
{
- if (libVal.isObject())
+ QJsonValue librariesVal = root.value("+libraries");
+ if (!librariesVal.isArray())
{
- if (!applyLibrary(libVal.toObject(), Override))
+ QLOG_ERROR() << filename
+ << "contains a '+libraries' field, but its not an array";
+ return out;
+ }
+ QJsonArray librariesArray = librariesVal.toArray();
+ for (auto libVal : librariesArray)
+ {
+ if (!libVal.isObject())
+ {
+ QLOG_ERROR() << filename << "contains a library that's not an object";
+ return out;
+ }
+ QJsonObject libObj = libVal.toObject();
+ bool error;
+ Library lib = fromLibraryJson(libObj, filename, error);
+ if (error)
+ {
+ QLOG_ERROR() << "Error while reading a library entry in" << filename;
+ return out;
+ }
+ if (!libObj.contains("insert"))
{
- return false;
+ QLOG_ERROR() << "Missing 'insert' field in '+libraries' field in"
+ << filename;
+ return out;
}
+ QJsonValue insertVal = libObj.value("insert");
+ QString insertString;
+ {
+ if (insertVal.isString())
+ {
+ insertString = insertVal.toString();
+ }
+ else if (insertVal.isObject())
+ {
+ QJsonObject insertObj = insertVal.toObject();
+ if (insertObj.isEmpty())
+ {
+ QLOG_ERROR() << "One library has an empty insert object in"
+ << filename;
+ return out;
+ }
+ insertString = insertObj.keys().first();
+ lib.insertData = insertObj.value(insertString).toString();
+ }
+ }
+ if (insertString == "apply")
+ {
+ lib.insertType = Library::Apply;
+ }
+ else if (insertString == "append")
+ {
+ lib.insertType = Library::Append;
+ }
+ else if (insertString == "prepend")
+ {
+ lib.insertType = Library::Prepend;
+ }
+ else if (insertString == "before")
+ {
+ lib.insertType = Library::InsertBefore;
+ }
+ else if (insertString == "after")
+ {
+ lib.insertType = Library::InsertAfter;
+ }
+ else if (insertString == "replace")
+ {
+ lib.insertType = Library::Replace;
+ }
+ else
+ {
+ QLOG_ERROR() << "A '+' library in" << filename
+ << "contains an invalid insert type";
+ return out;
+ }
+ out.addLibs.append(lib);
}
-
}
+ if (root.contains("-libraries"))
+ {
+ QJsonValue librariesVal = root.value("-libraries");
+ if (!librariesVal.isArray())
+ {
+ QLOG_ERROR() << filename
+ << "contains a '-libraries' field, but its not an array";
+ return out;
+ }
+ QJsonArray librariesArray = librariesVal.toArray();
+ for (auto libVal : librariesArray)
+ {
+ if (!libVal.isObject())
+ {
+ QLOG_ERROR() << filename << "contains a library that's not an object";
+ return out;
+ }
+ QJsonObject libObj = libVal.toObject();
+ if (!libObj.contains("name"))
+ {
+ QLOG_ERROR() << filename << "contains a library without a name";
+ return out;
+ }
+ if (!libObj.value("name").isString())
+ {
+ QLOG_ERROR() << filename
+ << "contains a library without a valid 'name' field";
+ return out;
+ }
+ out.removeLibs.append(libObj.value("name").toString());
+ }
+ }
+
+ isError = false;
+ return out;
}
- // +libraries
- if (object.contains("+libraries"))
+ static std::shared_ptr<OneSixLibrary> createLibrary(const Library &lib)
{
- auto librariesValue = object.value("+libraries");
- if (!librariesValue.isArray())
+ std::shared_ptr<OneSixLibrary> out(new OneSixLibrary(lib.name));
+ out->setBaseUrl(lib.url);
+ out->setHint(lib.hint);
+ out->setAbsoluteUrl(lib.absoluteUrl);
+ out->extract_excludes = lib.excludes;
+ for (auto native : lib.natives)
{
- QMessageBox::critical(m_widgetParent, QObject::tr("Error"), QObject::tr("One json files contains a libraries field, but it's not an array"));
- return false;
+ out->addNative(native.first, native.second);
}
- for (auto libVal : librariesValue.toArray())
+ out->setRules(lib.rules);
+ out->finalize();
+ return out;
+ }
+ int findLibrary(QList<std::shared_ptr<OneSixLibrary>> haystack, const QString &needle)
+ {
+ for (int i = 0; i < haystack.size(); ++i)
{
- if (libVal.isObject())
+ if (QRegExp(needle, Qt::CaseSensitive, QRegExp::WildcardUnix)
+ .indexIn(haystack.at(i)->rawName()) != -1)
{
- applyLibrary(libVal.toObject(), Add);
+ return i;
}
-
}
+ return -1;
}
-
- // -libraries
- if (object.contains("-libraries"))
+ void applyTo(OneSixVersion *version, bool &isError)
{
- auto librariesValue = object.value("-libraries");
- if (!librariesValue.isArray())
+ isError = true;
+ if (!id.isNull())
{
- QMessageBox::critical(m_widgetParent, QObject::tr("Error"), QObject::tr("One json files contains a libraries field, but it's not an array"));
- return false;
+ version->id = id;
+ }
+ if (!mainClass.isNull())
+ {
+ version->mainClass = mainClass;
+ }
+ if (!processArguments.isNull())
+ {
+ version->processArguments = processArguments;
+ }
+ if (!type.isNull())
+ {
+ version->type = type;
+ }
+ if (!releaseTime.isNull())
+ {
+ version->releaseTime = releaseTime;
+ }
+ if (!time.isNull())
+ {
+ version->time = time;
+ }
+ if (!assets.isNull())
+ {
+ version->assets = assets;
+ }
+ if (minimumLauncherVersion >= 0)
+ {
+ version->minimumLauncherVersion = minimumLauncherVersion;
+ }
+ if (!overwriteMinecraftArguments.isNull())
+ {
+ version->minecraftArguments = overwriteMinecraftArguments;
+ }
+ if (!addMinecraftArguments.isNull())
+ {
+ version->minecraftArguments += addMinecraftArguments;
}
- for (auto libVal : librariesValue.toArray())
+ if (!removeMinecraftArguments.isNull())
{
- if (libVal.isObject())
+ version->minecraftArguments.remove(removeMinecraftArguments);
+ }
+ if (shouldOverwriteTweakers)
+ {
+ version->tweakers = overwriteTweakers;
+ }
+ for (auto tweaker : addTweakers)
+ {
+ version->tweakers += tweaker;
+ }
+ for (auto tweaker : removeTweakers)
+ {
+ version->tweakers.removeAll(tweaker);
+ }
+ if (shouldOverwriteLibs)
+ {
+ version->libraries.clear();
+ for (auto lib : overwriteLibs)
+ {
+ version->libraries.append(createLibrary(lib));
+ }
+ }
+ for (auto lib : addLibs)
+ {
+ switch (lib.insertType)
+ {
+ case Library::Apply:
+ {
+
+ int index = findLibrary(version->libraries, lib.name);
+ if (index >= 0)
+ {
+ auto library = version->libraries[index];
+ if (!lib.url.isNull())
+ {
+ library->setBaseUrl(lib.url);
+ }
+ if (!lib.hint.isNull())
+ {
+ library->setHint(lib.hint);
+ }
+ if (!lib.absoluteUrl.isNull())
+ {
+ library->setAbsoluteUrl(lib.absoluteUrl);
+ }
+ if (lib.applyExcludes)
+ {
+ library->extract_excludes = lib.excludes;
+ }
+ if (lib.applyNatives)
+ {
+ library->clearSuffixes();
+ for (auto native : lib.natives)
+ {
+ library->addNative(native.first, native.second);
+ }
+ }
+ if (lib.applyRules)
+ {
+ library->setRules(lib.rules);
+ }
+ library->finalize();
+ }
+ else
+ {
+ QLOG_WARN() << "Couldn't find" << lib.insertData << "(skipping)";
+ }
+ break;
+ }
+ case Library::Append:
+ version->libraries.append(createLibrary(lib));
+ break;
+ case Library::Prepend:
+ version->libraries.prepend(createLibrary(lib));
+ break;
+ case Library::InsertBefore:
{
- applyLibrary(libVal.toObject(), Remove);
+
+ int index = findLibrary(version->libraries, lib.insertData);
+ if (index >= 0)
+ {
+ version->libraries.insert(index, createLibrary(lib));
+ }
+ else
+ {
+ QLOG_WARN() << "Couldn't find" << lib.insertData << "(skipping)";
+ }
+ break;
}
+ case Library::InsertAfter:
+ {
+ int index = findLibrary(version->libraries, lib.insertData);
+ if (index >= 0)
+ {
+ version->libraries.insert(index + 1, createLibrary(lib));
+ }
+ else
+ {
+ QLOG_WARN() << "Couldn't find" << lib.insertData << "(skipping)";
+ }
+ break;
+ }
+ case Library::Replace:
+ {
+ int index = findLibrary(version->libraries, lib.insertData);
+ if (index >= 0)
+ {
+ version->libraries.replace(index, createLibrary(lib));
+ }
+ else
+ {
+ QLOG_WARN() << "Couldn't find" << lib.insertData << "(skipping)";
+ }
+ break;
+ }
+ }
+ }
+ for (auto lib : removeLibs)
+ {
+ int index = findLibrary(version->libraries, lib);
+ if (index >= 0)
+ {
+ version->libraries.removeAt(index);
+ }
+ else
+ {
+ QLOG_WARN() << "Couldn't find" << lib << "(skipping)";
+ }
}
+
+ isError = false;
}
+};
- return true;
+OneSixVersionBuilder::OneSixVersionBuilder()
+{
}
-int findLibrary(QList<std::shared_ptr<OneSixLibrary> > haystack, const QString &needle)
+bool OneSixVersionBuilder::build(OneSixVersion *version, OneSixInstance *instance,
+ QWidget *widgetParent, const bool excludeCustom)
{
- for (int i = 0; i < haystack.size(); ++i)
- {
- if (QRegExp(needle, Qt::CaseSensitive, QRegExp::WildcardUnix).indexIn(haystack.at(i)->rawName()) != -1)
- {
- return i;
- }
- }
- return -1;
+ OneSixVersionBuilder builder;
+ builder.m_version = version;
+ builder.m_instance = instance;
+ builder.m_widgetParent = widgetParent;
+ return builder.build(excludeCustom);
}
-bool OneSixVersionBuilder::applyLibrary(const QJsonObject &lib, const OneSixVersionBuilder::Type type)
+bool OneSixVersionBuilder::read(OneSixVersion *version, const QJsonObject &obj)
{
- // Library name
- auto nameVal = lib.value("name");
- if (!nameVal.isString())
- {
- return false;
- }
- auto name = nameVal.toString();
+ OneSixVersionBuilder builder;
+ builder.m_version = version;
+ builder.m_instance = 0;
+ builder.m_widgetParent = 0;
+ return builder.read(obj);
+}
- if (type == Remove)
+bool OneSixVersionBuilder::build(const bool excludeCustom)
+{
+ m_version->clear();
+
+ QDir root(m_instance->instanceRoot());
+ QDir patches(root.absoluteFilePath("patches/"));
+
+ // version.json -> patches/*.json -> custom.json
+
+ // version.json
{
- int index = findLibrary(m_version->libraries, name);
- if (index >= 0)
+ QLOG_INFO() << "Reading version.json";
+ VersionFile file;
+ if (!read(QFileInfo(root.absoluteFilePath("version.json")), false, &file))
+ {
+ return false;
+ }
+ bool isError = false;
+ file.applyTo(m_version, isError);
+ if (isError)
{
- m_version->libraries.removeAt(index);
+ QMessageBox::critical(
+ m_widgetParent, QObject::tr("Error"),
+ QObject::tr(
+ "Error while applying %1. Please check MultiMC-0.log for more info.")
+ .arg(root.absoluteFilePath("version.json")));
+ return false;
}
- return true;
}
- if (type == Add && !lib.contains("insert"))
+ // patches/
{
- return false;
- }
-
- std::shared_ptr<OneSixLibrary> library;
+ // load all, put into map for ordering, apply in the right order
- if (lib.value("insert").toString() != "apply" && type == Add)
- {
- QMutableListIterator<std::shared_ptr<OneSixLibrary> > it(m_version->libraries);
- while (it.hasNext())
+ QMap<int, QPair<QString, VersionFile>> files;
+ for (auto info : patches.entryInfoList(QStringList() << "*.json", QDir::Files))
{
- if (it.next()->rawName() == name)
+ QLOG_INFO() << "Reading" << info.fileName();
+ VersionFile file;
+ if (!read(info, true, &file))
{
- it.remove();
+ return false;
}
+ files.insert(file.order, qMakePair(info.fileName(), file));
}
- }
-
- if (lib.value("insert").toString() == "apply" && type == Add)
- {
- library = m_version->libraries[findLibrary(m_version->libraries, name)];
- }
- else
- {
- library.reset(new OneSixLibrary(nameVal.toString()));
- }
-
- applyString(lib, "url", library, &OneSixLibrary::setBaseUrl);
- applyString(lib, "MMC-hint", library, &OneSixLibrary::setHint);
- applyString(lib, "MMC-absulute_url", library, &OneSixLibrary::setAbsoluteUrl);
- applyString(lib, "MMC-absoluteUrl", library, &OneSixLibrary::setAbsoluteUrl);
-
- auto extractVal = lib.value("extract");
- if (extractVal.isObject())
- {
- QStringList excludes;
- auto extractObj = extractVal.toObject();
- auto excludesVal = extractObj.value("exclude");
- if (excludesVal.isArray())
+ for (auto order : files.keys())
{
- auto excludesList = excludesVal.toArray();
- for (auto excludeVal : excludesList)
+ QLOG_DEBUG() << "Applying file with order" << order;
+ auto filePair = files[order];
+ bool isError = false;
+ filePair.second.applyTo(m_version, isError);
+ if (isError)
{
- if (excludeVal.isString())
- {
- excludes.append(excludeVal.toString());
- }
+ QMessageBox::critical(
+ m_widgetParent, QObject::tr("Error"),
+ QObject::tr(
+ "Error while applying %1. Please check MultiMC-0.log for more info.")
+ .arg(filePair.first));
+ return false;
}
- library->extract_excludes = excludes;
}
}
- auto nativesVal = lib.value("natives");
- if (nativesVal.isObject())
+ // custom.json
+ if (!excludeCustom)
{
- library->setIsNative();
- auto nativesObj = nativesVal.toObject();
- for (auto it = nativesObj.begin(); it != nativesObj.end(); ++it)
+ if (QFile::exists(root.absoluteFilePath("custom.json")))
{
- auto osType = OpSys_fromString(it.key());
- if (osType == Os_Other)
+ QLOG_INFO() << "Reading custom.json";
+ VersionFile file;
+ if (!read(QFileInfo(root.absoluteFilePath("custom.json")), false, &file))
{
- continue;
+ return false;
}
- if (!it.value().isString())
+ bool isError = false;
+ file.applyTo(m_version, isError);
+ if (isError)
{
- continue;
+ QMessageBox::critical(
+ m_widgetParent, QObject::tr("Error"),
+ QObject::tr(
+ "Error while applying %1. Please check MultiMC-0.log for more info.")
+ .arg(root.absoluteFilePath("custom.json")));
+ return false;
}
- library->addNative(osType, it.value().toString());
}
}
- if (lib.contains("rules"))
+ // some final touches
{
- library->setRules(rulesFromJsonV4(lib));
- }
- library->finalize();
- if (type == Override)
- {
- m_version->libraries.append(library);
- }
- else if (lib.value("insert").toString() != "apply")
- {
- if (lib.value("insert").toString() == "append")
- {
- m_version->libraries.append(library);
- }
- else if (lib.value("insert").toString() == "prepend")
+ if (m_version->assets.isEmpty())
{
- m_version->libraries.prepend(library);
+ m_version->assets = "legacy";
}
- else if (lib.value("insert").isObject())
+ if (m_version->minecraftArguments.isEmpty())
{
- QJsonObject insertObj = lib.value("insert").toObject();
- if (insertObj.isEmpty())
+ QString toCompare = m_version->processArguments.toLower();
+ if (toCompare == "legacy")
{
- QMessageBox::critical(m_widgetParent, QObject::tr("Error"), QObject::tr("'insert' object empty"));
- return false;
+ m_version->minecraftArguments = " ${auth_player_name} ${auth_session}";
}
- const QString key = insertObj.keys().first();
- const QString value = insertObj.value(key).toString();
- const int index = findLibrary(m_version->libraries, value);
- if (index >= 0)
+ else if (toCompare == "username_session")
{
- if (key == "before")
- {
- m_version->libraries.insert(index, library);
- }
- else if (key == "after")
- {
- m_version->libraries.insert(index + 1, library);
- }
- else
- {
- QMessageBox::critical(m_widgetParent, QObject::tr("Error"), QObject::tr("Invalid value for 'insert': %1").arg(lib.value("insert").toString()));
- return false;
- }
+ m_version->minecraftArguments =
+ "--username ${auth_player_name} --session ${auth_session}";
+ }
+ else if (toCompare == "username_session_version")
+ {
+ m_version->minecraftArguments = "--username ${auth_player_name} "
+ "--session ${auth_session} "
+ "--version ${profile_name}";
}
}
- else
- {
- QMessageBox::critical(m_widgetParent, QObject::tr("Error"), QObject::tr("Invalid value for 'insert': %1").arg(lib.value("insert").toString()));
- return false;
- }
}
+
+ return true;
+}
+
+bool OneSixVersionBuilder::read(const QJsonObject &obj)
+{
+ m_version->clear();
+
+ bool isError = false;
+ VersionFile file = VersionFile::fromJson(QJsonDocument(obj), QString(), false, isError);
+ if (isError)
+ {
+ QMessageBox::critical(
+ m_widgetParent, QObject::tr("Error"),
+ QObject::tr("Error while reading. Please check MultiMC-0.log for more info."));
+ return false;
+ }
+ file.applyTo(m_version, isError);
+ if (isError)
+ {
+ QMessageBox::critical(
+ m_widgetParent, QObject::tr("Error"),
+ QObject::tr("Error while applying. Please check MultiMC-0.log for more info."));
+ return false;
+ }
+
return true;
}
-bool OneSixVersionBuilder::read(const QFileInfo &fileInfo, QJsonObject *out)
+bool OneSixVersionBuilder::read(const QFileInfo &fileInfo, const bool requireOrder,
+ VersionFile *out)
{
QFile file(fileInfo.absoluteFilePath());
if (!file.open(QFile::ReadOnly))
{
- QMessageBox::critical(m_widgetParent, QObject::tr("Error"), QObject::tr("Unable to open %1: %2").arg(file.fileName(), file.errorString()));
+ QMessageBox::critical(
+ m_widgetParent, QObject::tr("Error"),
+ QObject::tr("Unable to open %1: %2").arg(file.fileName(), file.errorString()));
return false;
}
QJsonParseError error;
QJsonDocument doc = QJsonDocument::fromJson(file.readAll(), &error);
if (error.error != QJsonParseError::NoError)
{
- QMessageBox::critical(m_widgetParent, QObject::tr("Error"), QObject::tr("Unable to parse %1: %2 at %3").arg(file.fileName(), error.errorString()).arg(error.offset));
+ QMessageBox::critical(m_widgetParent, QObject::tr("Error"),
+ QObject::tr("Unable to parse %1: %2 at %3")
+ .arg(file.fileName(), error.errorString())
+ .arg(error.offset));
return false;
}
- *out = doc.object();
+ bool isError = false;
+ *out = VersionFile::fromJson(doc, file.fileName(), requireOrder, isError);
+ if (isError)
+ {
+ QMessageBox::critical(
+ m_widgetParent, QObject::tr("Error"),
+ QObject::tr("Error while reading %1. Please check MultiMC-0.log for more info.")
+ .arg(file.fileName()));
+ ;
+ }
return true;
}