diff options
author | Jan Dalheimer <jan@dalheimer.de> | 2014-01-27 19:20:07 +0100 |
---|---|---|
committer | Jan Dalheimer <jan@dalheimer.de> | 2014-01-27 19:20:07 +0100 |
commit | f9ea3dbfdea0db5626a6afadcfd599a5f53d8abd (patch) | |
tree | e02cbc9b4f290a7ea4fe37cd2996f6a8f2595177 /logic/OneSixVersionBuilder.cpp | |
parent | 966f9d1206fee51641c9ae844323f85316a59b1d (diff) | |
download | MultiMC-f9ea3dbfdea0db5626a6afadcfd599a5f53d8abd.tar MultiMC-f9ea3dbfdea0db5626a6afadcfd599a5f53d8abd.tar.gz MultiMC-f9ea3dbfdea0db5626a6afadcfd599a5f53d8abd.tar.lz MultiMC-f9ea3dbfdea0db5626a6afadcfd599a5f53d8abd.tar.xz MultiMC-f9ea3dbfdea0db5626a6afadcfd599a5f53d8abd.zip |
Split parsing/applying. Better error logging. Fix crash.
Diffstat (limited to 'logic/OneSixVersionBuilder.cpp')
-rw-r--r-- | logic/OneSixVersionBuilder.cpp | 1002 |
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; } |