From 7dfd6aa051c582e26125e17e1d6eed5e675e1027 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Mr=C3=A1zek?= Date: Sat, 1 Mar 2014 18:18:51 +0100 Subject: Remove obsolete OneSixFTBInstanceForge --- logic/OneSixFTBInstance.cpp | 70 --------------------------------------------- 1 file changed, 70 deletions(-) (limited to 'logic') diff --git a/logic/OneSixFTBInstance.cpp b/logic/OneSixFTBInstance.cpp index 91efce8e..8b8465b9 100644 --- a/logic/OneSixFTBInstance.cpp +++ b/logic/OneSixFTBInstance.cpp @@ -10,76 +10,6 @@ #include "MultiMC.h" #include "pathutils.h" -class OneSixFTBInstanceForge : public Task -{ - Q_OBJECT -public: - explicit OneSixFTBInstanceForge(const QString &version, OneSixFTBInstance *inst, QObject *parent = 0) : - Task(parent), instance(inst), version("Forge " + version) - { - } - - void executeTask() - { - for (int i = 0; i < MMC->forgelist()->count(); ++i) - { - if (MMC->forgelist()->at(i)->name() == version) - { - forgeVersion = std::dynamic_pointer_cast(MMC->forgelist()->at(i)); - break; - } - } - if (!forgeVersion) - { - emitFailed(QString("Couldn't find forge version ") + version ); - return; - } - entry = MMC->metacache()->resolveEntry("minecraftforge", forgeVersion->filename); - if (entry->stale) - { - setStatus(tr("Downloading Forge...")); - fjob = new NetJob("Forge download"); - fjob->addNetAction(CacheDownload::make(forgeVersion->installer_url, entry)); - connect(fjob, &NetJob::failed, [this](){emitFailed(m_failReason);}); - connect(fjob, &NetJob::succeeded, this, &OneSixFTBInstanceForge::installForge); - connect(fjob, &NetJob::progress, [this](qint64 c, qint64 total){ setProgress(100 * c / total); }); - fjob->start(); - } - else - { - installForge(); - } - } - -private -slots: - void installForge() - { - setStatus(tr("Installing Forge...")); - QString forgePath = entry->getFullPath(); - ForgeInstaller forge(forgePath, forgeVersion->universal_url); - if (!instance->reloadVersion()) - { - emitFailed(tr("Couldn't load the version config")); - return; - } - auto version = instance->getFullVersion(); - if (!forge.add(instance)) - { - emitFailed(tr("Couldn't install Forge")); - return; - } - emitSucceeded(); - } - -private: - OneSixFTBInstance *instance; - QString version; - ForgeVersionPtr forgeVersion; - MetaEntryPtr entry; - NetJob *fjob; -}; - OneSixFTBInstance::OneSixFTBInstance(const QString &rootDir, SettingsObject *settings, QObject *parent) : OneSixInstance(rootDir, settings, parent) { -- cgit v1.2.3 From 7c24bcc83476dcbdd7f7acbe14ecef4398962689 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Mr=C3=A1zek?= Date: Sat, 1 Mar 2014 23:06:47 +0100 Subject: Reorganize the version-related code. --- logic/BaseInstaller.cpp | 2 +- logic/ForgeInstaller.cpp | 6 +- logic/ForgeInstaller.h | 4 +- logic/LiteLoaderInstaller.cpp | 2 +- logic/OneSixFTBInstance.cpp | 2 +- logic/OneSixInstance.cpp | 12 +- logic/OneSixInstance.h | 8 +- logic/OneSixInstance_p.h | 6 +- logic/OneSixUpdate.cpp | 8 +- logic/OneSixVersion.cpp | 221 ------------ logic/OneSixVersion.h | 137 ------- logic/OneSixVersionBuilder.cpp | 797 +---------------------------------------- logic/OneSixVersionBuilder.h | 15 +- logic/VersionFile.cpp | 702 ++++++++++++++++++++++++++++++++++++ logic/VersionFile.h | 90 +++++ logic/VersionFinal.cpp | 221 ++++++++++++ logic/VersionFinal.h | 137 +++++++ 17 files changed, 1197 insertions(+), 1173 deletions(-) delete mode 100644 logic/OneSixVersion.cpp delete mode 100644 logic/OneSixVersion.h create mode 100644 logic/VersionFile.cpp create mode 100644 logic/VersionFile.h create mode 100644 logic/VersionFinal.cpp create mode 100644 logic/VersionFinal.h (limited to 'logic') diff --git a/logic/BaseInstaller.cpp b/logic/BaseInstaller.cpp index 92aa0c92..669fd0ac 100644 --- a/logic/BaseInstaller.cpp +++ b/logic/BaseInstaller.cpp @@ -17,7 +17,7 @@ #include -#include "OneSixVersion.h" +#include "VersionFinal.h" #include "OneSixLibrary.h" #include "OneSixInstance.h" diff --git a/logic/ForgeInstaller.cpp b/logic/ForgeInstaller.cpp index 3e18d17f..6f238c21 100644 --- a/logic/ForgeInstaller.cpp +++ b/logic/ForgeInstaller.cpp @@ -14,7 +14,7 @@ */ #include "ForgeInstaller.h" -#include "OneSixVersion.h" +#include "VersionFinal.h" #include "OneSixLibrary.h" #include "net/HttpMetaCache.h" #include @@ -33,7 +33,7 @@ ForgeInstaller::ForgeInstaller(QString filename, QString universal_url) { - std::shared_ptr newVersion; + std::shared_ptr newVersion; m_universal_url = universal_url; QuaZip zip(filename); @@ -66,7 +66,7 @@ ForgeInstaller::ForgeInstaller(QString filename, QString universal_url) // read the forge version info { - newVersion = OneSixVersion::fromJson(versionInfoVal.toObject()); + newVersion = VersionFinal::fromJson(versionInfoVal.toObject()); if (!newVersion) return; } diff --git a/logic/ForgeInstaller.h b/logic/ForgeInstaller.h index c5052092..df029f38 100644 --- a/logic/ForgeInstaller.h +++ b/logic/ForgeInstaller.h @@ -20,7 +20,7 @@ #include #include -class OneSixVersion; +class VersionFinal; class ForgeInstaller : public BaseInstaller { @@ -33,7 +33,7 @@ public: private: // the version, read from the installer - std::shared_ptr m_forge_version; + std::shared_ptr m_forge_version; QString internalPath; QString finalPath; QString realVersionId; diff --git a/logic/LiteLoaderInstaller.cpp b/logic/LiteLoaderInstaller.cpp index 126027fb..44400e8a 100644 --- a/logic/LiteLoaderInstaller.cpp +++ b/logic/LiteLoaderInstaller.cpp @@ -20,7 +20,7 @@ #include "logger/QsLog.h" -#include "OneSixVersion.h" +#include "VersionFinal.h" #include "OneSixLibrary.h" #include "OneSixInstance.h" diff --git a/logic/OneSixFTBInstance.cpp b/logic/OneSixFTBInstance.cpp index 8b8465b9..cdb3f53e 100644 --- a/logic/OneSixFTBInstance.cpp +++ b/logic/OneSixFTBInstance.cpp @@ -1,6 +1,6 @@ #include "OneSixFTBInstance.h" -#include "OneSixVersion.h" +#include "VersionFinal.h" #include "OneSixLibrary.h" #include "tasks/SequentialTask.h" #include "ForgeInstaller.h" diff --git a/logic/OneSixInstance.cpp b/logic/OneSixInstance.cpp index 10411c56..bd5d559e 100644 --- a/logic/OneSixInstance.cpp +++ b/logic/OneSixInstance.cpp @@ -19,7 +19,7 @@ #include "OneSixInstance_p.h" #include "OneSixUpdate.h" -#include "OneSixVersion.h" +#include "VersionFinal.h" #include "pathutils.h" #include "logger/QsLog.h" #include "assets/AssetsUtils.h" @@ -34,8 +34,8 @@ OneSixInstance::OneSixInstance(const QString &rootDir, SettingsObject *settings, I_D(OneSixInstance); d->m_settings->registerSetting("IntendedVersion", ""); d->m_settings->registerSetting("ShouldUpdate", false); - d->version.reset(new OneSixVersion(this, this)); - d->vanillaVersion.reset(new OneSixVersion(this, this)); + d->version.reset(new VersionFinal(this, this)); + d->vanillaVersion.reset(new VersionFinal(this, this)); } void OneSixInstance::init() @@ -79,7 +79,7 @@ QString replaceTokensIn(QString text, QMap with) return result; } -QDir OneSixInstance::reconstructAssets(std::shared_ptr version) +QDir OneSixInstance::reconstructAssets(std::shared_ptr version) { QDir assetsDir = QDir("assets/"); QDir indexDir = QDir(PathCombine(assetsDir.path(), "indexes")); @@ -345,13 +345,13 @@ void OneSixInstance::clearVersion() emit versionReloaded(); } -std::shared_ptr OneSixInstance::getFullVersion() const +std::shared_ptr OneSixInstance::getFullVersion() const { I_D(const OneSixInstance); return d->version; } -std::shared_ptr OneSixInstance::getVanillaVersion() const +std::shared_ptr OneSixInstance::getVanillaVersion() const { I_D(const OneSixInstance); return d->vanillaVersion; diff --git a/logic/OneSixInstance.h b/logic/OneSixInstance.h index 06fd9de3..75edec1e 100644 --- a/logic/OneSixInstance.h +++ b/logic/OneSixInstance.h @@ -17,7 +17,7 @@ #include "BaseInstance.h" -#include "OneSixVersion.h" +#include "VersionFinal.h" #include "ModList.h" class OneSixInstance : public BaseInstance @@ -58,9 +58,9 @@ public: /// clears all version information in preparation for an update void clearVersion(); /// get the current full version info - std::shared_ptr getFullVersion() const; + std::shared_ptr getFullVersion() const; /// gets the current version info, but only for version.json - std::shared_ptr getVanillaVersion() const; + std::shared_ptr getVanillaVersion() const; /// is the current version original, or custom? virtual bool versionIsCustom() override; @@ -80,5 +80,5 @@ signals: private: QStringList processMinecraftArgs(AuthSessionPtr account); - QDir reconstructAssets(std::shared_ptr version); + QDir reconstructAssets(std::shared_ptr version); }; diff --git a/logic/OneSixInstance_p.h b/logic/OneSixInstance_p.h index 0cc46f33..2dffa62c 100644 --- a/logic/OneSixInstance_p.h +++ b/logic/OneSixInstance_p.h @@ -16,13 +16,13 @@ #pragma once #include "BaseInstance_p.h" -#include "OneSixVersion.h" +#include "VersionFinal.h" #include "ModList.h" struct OneSixInstancePrivate : public BaseInstancePrivate { - std::shared_ptr version; - std::shared_ptr vanillaVersion; + std::shared_ptr version; + std::shared_ptr vanillaVersion; std::shared_ptr loader_mod_list; std::shared_ptr resource_pack_list; }; diff --git a/logic/OneSixUpdate.cpp b/logic/OneSixUpdate.cpp index f87c65e7..750aeabb 100644 --- a/logic/OneSixUpdate.cpp +++ b/logic/OneSixUpdate.cpp @@ -25,7 +25,7 @@ #include "BaseInstance.h" #include "lists/MinecraftVersionList.h" -#include "OneSixVersion.h" +#include "VersionFinal.h" #include "OneSixLibrary.h" #include "OneSixInstance.h" #include "net/ForgeMirrors.h" @@ -150,7 +150,7 @@ void OneSixUpdate::assetIndexStart() { setStatus(tr("Updating assets index...")); OneSixInstance *inst = (OneSixInstance *)m_inst; - std::shared_ptr version = inst->getFullVersion(); + std::shared_ptr version = inst->getFullVersion(); QString assetName = version->assets; QUrl indexUrl = "http://" + URLConstants::AWS_DOWNLOAD_INDEXES + assetName + ".json"; QString localPath = assetName + ".json"; @@ -174,7 +174,7 @@ void OneSixUpdate::assetIndexFinished() AssetsIndex index; OneSixInstance *inst = (OneSixInstance *)m_inst; - std::shared_ptr version = inst->getFullVersion(); + std::shared_ptr version = inst->getFullVersion(); QString assetName = version->assets; QString asset_fname = "assets/indexes/" + assetName + ".json"; @@ -243,7 +243,7 @@ void OneSixUpdate::jarlibStart() } // Build a list of URLs that will need to be downloaded. - std::shared_ptr version = inst->getFullVersion(); + std::shared_ptr version = inst->getFullVersion(); // minecraft.jar for this version { QString version_id = version->id; diff --git a/logic/OneSixVersion.cpp b/logic/OneSixVersion.cpp deleted file mode 100644 index 06e748bd..00000000 --- a/logic/OneSixVersion.cpp +++ /dev/null @@ -1,221 +0,0 @@ -/* Copyright 2013 MultiMC Contributors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "OneSixVersion.h" - -#include -#include - -#include "OneSixVersionBuilder.h" - -OneSixVersion::OneSixVersion(OneSixInstance *instance, QObject *parent) - : QAbstractListModel(parent), m_instance(instance) -{ - clear(); -} - -bool OneSixVersion::reload(QWidget *widgetParent, const bool onlyVanilla, const QStringList &external) -{ - beginResetModel(); - bool ret = OneSixVersionBuilder::build(this, m_instance, widgetParent, onlyVanilla, external); - endResetModel(); - return ret; -} - -void OneSixVersion::clear() -{ - beginResetModel(); - id.clear(); - time.clear(); - releaseTime.clear(); - type.clear(); - assets.clear(); - processArguments.clear(); - minecraftArguments.clear(); - minimumLauncherVersion = 0xDEADBEAF; - mainClass.clear(); - libraries.clear(); - tweakers.clear(); - versionFiles.clear(); - endResetModel(); -} - -void OneSixVersion::dump() const -{ - qDebug().nospace() << "OneSixVersion(" - << "\n\tid=" << id - << "\n\ttime=" << time - << "\n\treleaseTime=" << releaseTime - << "\n\ttype=" << type - << "\n\tassets=" << assets - << "\n\tprocessArguments=" << processArguments - << "\n\tminecraftArguments=" << minecraftArguments - << "\n\tminimumLauncherVersion=" << minimumLauncherVersion - << "\n\tmainClass=" << mainClass - << "\n\tlibraries="; - for (auto lib : libraries) - { - qDebug().nospace() << "\n\t\t" << lib.get(); - } - qDebug().nospace() << "\n)"; -} - -bool OneSixVersion::canRemove(const int index) const -{ - if (index < versionFiles.size()) - { - return versionFiles.at(index).id != "org.multimc.version.json"; - } - return false; -} - -QString OneSixVersion::versionFileId(const int index) const -{ - if (index < 0 || index >= versionFiles.size()) - { - return QString(); - } - return versionFiles.at(index).id; -} - -bool OneSixVersion::remove(const int index) -{ - if (canRemove(index)) - { - return QFile::remove(versionFiles.at(index).filename); - } - return false; -} - -QList > OneSixVersion::getActiveNormalLibs() -{ - QList > output; - for (auto lib : libraries) - { - if (lib->isActive() && !lib->isNative()) - { - output.append(lib); - } - } - return output; -} - -QList > OneSixVersion::getActiveNativeLibs() -{ - QList > output; - for (auto lib : libraries) - { - if (lib->isActive() && lib->isNative()) - { - output.append(lib); - } - } - return output; -} - -std::shared_ptr OneSixVersion::fromJson(const QJsonObject &obj) -{ - std::shared_ptr version(new OneSixVersion(0)); - if (OneSixVersionBuilder::read(version.get(), obj)) - { - return version; - } - return 0; -} - -QVariant OneSixVersion::data(const QModelIndex &index, int role) const -{ - if (!index.isValid()) - return QVariant(); - - int row = index.row(); - int column = index.column(); - - if (row < 0 || row >= versionFiles.size()) - return QVariant(); - - if (role == Qt::DisplayRole) - { - switch (column) - { - case 0: - return versionFiles.at(row).name; - case 1: - return versionFiles.at(row).version; - default: - return QVariant(); - } - } - return QVariant(); -} - -QVariant OneSixVersion::headerData(int section, Qt::Orientation orientation, int role) const -{ - if (orientation == Qt::Horizontal) - { - if (role == Qt::DisplayRole) - { - switch (section) - { - case 0: - return tr("Name"); - case 1: - return tr("Version"); - default: - return QVariant(); - } - } - } - return QVariant(); -} - -Qt::ItemFlags OneSixVersion::flags(const QModelIndex &index) const -{ - if (!index.isValid()) - return Qt::NoItemFlags; - return Qt::ItemIsSelectable | Qt::ItemIsEnabled; -} - -int OneSixVersion::rowCount(const QModelIndex &parent) const -{ - return versionFiles.size(); -} - -int OneSixVersion::columnCount(const QModelIndex &parent) const -{ - return 2; -} - -QDebug operator<<(QDebug &dbg, const OneSixVersion *version) -{ - version->dump(); - return dbg.maybeSpace(); -} -QDebug operator<<(QDebug &dbg, const OneSixLibrary *library) -{ - dbg.nospace() << "OneSixLibrary(" - << "\n\t\t\trawName=" << library->rawName() - << "\n\t\t\tname=" << library->name() - << "\n\t\t\tversion=" << library->version() - << "\n\t\t\ttype=" << library->type() - << "\n\t\t\tisActive=" << library->isActive() - << "\n\t\t\tisNative=" << library->isNative() - << "\n\t\t\tdownloadUrl=" << library->downloadUrl() - << "\n\t\t\tstoragePath=" << library->storagePath() - << "\n\t\t\tabsolutePath=" << library->absoluteUrl() - << "\n\t\t\thint=" << library->hint(); - dbg.nospace() << "\n\t\t)"; - return dbg.maybeSpace(); -} diff --git a/logic/OneSixVersion.h b/logic/OneSixVersion.h deleted file mode 100644 index fee47fa3..00000000 --- a/logic/OneSixVersion.h +++ /dev/null @@ -1,137 +0,0 @@ -/* Copyright 2013 MultiMC Contributors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#pragma once - -#include - -#include -#include -#include - -#include "OneSixLibrary.h" - -class OneSixInstance; - -class OneSixVersion : public QAbstractListModel -{ - Q_OBJECT -public: - explicit OneSixVersion(OneSixInstance *instance, QObject *parent = 0); - - virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; - virtual QVariant headerData(int section, Qt::Orientation orientation, int role) const; - virtual int rowCount(const QModelIndex &parent = QModelIndex()) const; - virtual int columnCount(const QModelIndex &parent) const; - virtual Qt::ItemFlags flags(const QModelIndex &index) const; - - bool reload(QWidget *widgetParent, const bool onlyVanilla = false, const QStringList &external = QStringList()); - void clear(); - - void dump() const; - - bool canRemove(const int index) const; - - QString versionFileId(const int index) const; - -public -slots: - bool remove(const int index); - -public: - QList> getActiveNormalLibs(); - QList> getActiveNativeLibs(); - - static std::shared_ptr fromJson(const QJsonObject &obj); - - // 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 releaseTime; - /// Release type - "release" or "snapshot" - QString type; - /// Assets type - "legacy" or a version ID - QString assets; - /** - * DEPRECATED: Old versions of the new vanilla launcher used this - * ex: "username_session_version" - */ - QString processArguments; - /** - * arguments that should be used for launching minecraft - * - * ex: "--username ${auth_player_name} --session ${auth_session} - * --version ${version_name} --gameDir ${game_directory} --assetsDir ${game_assets}" - */ - QString minecraftArguments; - /** - * the minimum launcher version required by this version ... current is 4 (at point of - * writing) - */ - int minimumLauncherVersion = 0xDEADBEEF; - /** - * A list of all tweaker classes - */ - QStringList tweakers; - /** - * The main class to load first - */ - QString mainClass; - - /// the list of libs - both active and inactive, native and java - QList> libraries; - - /* - FIXME: add support for those rules here? Looks like a pile of quick hacks to me though. - - "rules": [ - { - "action": "allow" - }, - { - "action": "disallow", - "os": { - "name": "osx", - "version": "^10\\.5\\.\\d$" - } - } - ], - "incompatibilityReason": "There is a bug in LWJGL which makes it incompatible with OSX - 10.5.8. Please go to New Profile and use 1.5.2 for now. Sorry!" - } - */ - // QList rules; - - struct VersionFile - { - QString name; - QString id; - QString version; - QString mcVersion; - QString filename; - int order; - }; - QList versionFiles; - -private: - OneSixInstance *m_instance; -}; - -QDebug operator<<(QDebug &dbg, const OneSixVersion *version); -QDebug operator<<(QDebug &dbg, const OneSixLibrary *library); diff --git a/logic/OneSixVersionBuilder.cpp b/logic/OneSixVersionBuilder.cpp index f6917697..0d4d66a2 100644 --- a/logic/OneSixVersionBuilder.cpp +++ b/logic/OneSixVersionBuilder.cpp @@ -26,806 +26,37 @@ #include #include -#include "OneSixVersion.h" +#include "VersionFinal.h" #include "OneSixInstance.h" #include "OneSixRule.h" +#include "VersionFile.h" #include "modutils.h" #include "logger/QsLog.h" -#define CURRENT_MINIMUM_LAUNCHER_VERSION 14 - -struct VersionFile -{ - int order; - QString name; - QString fileId; - QString version; - // TODO use the mcVersion to determine if a version file should be removed on update - QString mcVersion; - QString filename; - // TODO requirements - // QMap requirements; - 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> natives; - bool applyRules = false; - QList> rules; - - // user for '+' libraries - enum InsertType - { - Apply, - Append, - Prepend, - Replace - }; - InsertType insertType = Append; - QString insertData; - enum DependType - { - Soft, - Hard - }; - DependType dependType = Soft; - }; - bool shouldOverwriteLibs = false; - QList overwriteLibs; - QList addLibs; - QList removeLibs; - - enum ApplyError - { - LauncherVersionError, - OtherError, - NoApplyError - }; - - static Library fromLibraryJson(const QJsonObject &libObj, const QString &filename, - bool &isError) - { - isError = true; - Library out; - if (!libObj.contains("name")) - { - QLOG_ERROR() << filename << "contains a library that doesn't have a 'name' field"; - return out; - } - out.name = libObj.value("name").toString(); - - 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(); - } - } - }; - - readString("url", out.url); - readString("MMC-hint", out.hint); - readString("MMC-absulute_url", out.absoluteUrl); - readString("MMC-absoluteUrl", out.absoluteUrl); - if (libObj.contains("extract")) - { - if (!libObj.value("extract").isObject()) - { - QLOG_ERROR() - << filename - << "contains a library with an 'extract' field that's not an object"; - return out; - } - QJsonObject extractObj = libObj.value("extract").toObject(); - if (!extractObj.contains("exclude") || !extractObj.value("exclude").isArray()) - { - QLOG_ERROR() << filename - << "contains a library with an invalid 'extract' field"; - return out; - } - out.applyExcludes = true; - QJsonArray excludeArray = extractObj.value("exclude").toArray(); - for (auto excludeVal : excludeArray) - { - 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()); - } - } - } - if (libObj.contains("natives")) - { - if (!libObj.value("natives").isObject()) - { - QLOG_ERROR() - << filename - << "contains a library with a 'natives' field that's not an object"; - return out; - } - out.applyNatives = true; - QJsonObject nativesObj = libObj.value("natives").toObject(); - for (auto it = nativesObj.begin(); it != nativesObj.end(); ++it) - { - 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; - } - static VersionFile fromJson(const QJsonDocument &doc, const QString &filename, - const bool requireOrder, bool &isError, const OneSixVersionBuilder::ParseFlags flags = OneSixVersionBuilder::NoFlags) - { - VersionFile out; - isError = true; - if (doc.isEmpty() || doc.isNull()) - { - QLOG_ERROR() << filename << "is empty or null"; - return out; - } - if (!doc.isObject()) - { - QLOG_ERROR() << "The root of" << filename << "is not an object"; - return out; - } - - QJsonObject root = doc.object(); - - if (requireOrder) - { - 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"; - } - } - - out.name = root.value("name").toString(); - out.fileId = root.value("fileId").toString(); - out.version = root.value("version").toString(); - out.mcVersion = root.value("mcVersion").toString(); - out.filename = filename; - - 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(); - } - } - }; - - if (!(flags & OneSixVersionBuilder::IsFTBPackJson)) - { - 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")) - { - QJsonValue val = root.value("minimumLauncherVersion"); - if (!val.isDouble()) - { - QLOG_WARN() << "minimumLauncherVersion is not an int in" << filename - << "(skipping)"; - } - else - { - out.minimumLauncherVersion = val.toDouble(); - } - } - - if (root.contains("tweakers")) - { - 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()); - } - } - if (root.contains("+tweakers")) - { - 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 (root.contains("-tweakers")) - { - 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()); - } - } - - if (root.contains("libraries")) - { - out.shouldOverwriteLibs = !(flags & OneSixVersionBuilder::IsFTBPackJson); - 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; - } - if (flags & OneSixVersionBuilder::IsFTBPackJson) - { - lib.hint = "local"; - lib.insertType = Library::Prepend; - out.addLibs.prepend(lib); - } - else - { - out.overwriteLibs.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(); - 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")) - { - 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 == "prepend") - { - lib.insertType = Library::Prepend; - } - else if (insertString == "append") - { - lib.insertType = Library::Prepend; - } - else if (insertString == "replace") - { - lib.insertType = Library::Replace; - } - else - { - QLOG_ERROR() << "A '+' library in" << filename - << "contains an invalid insert type"; - return out; - } - if (libObj.contains("MMC-depend") && libObj.value("MMC-depend").isString()) - { - const QString dependString = libObj.value("MMC-depend").toString(); - if (dependString == "hard") - { - lib.dependType = Library::Hard; - } - else if (dependString == "soft") - { - lib.dependType = Library::Soft; - } - else - { - QLOG_ERROR() << "A '+' library in" << filename - << "contains an invalid depend 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; - } - - static std::shared_ptr createLibrary(const Library &lib) - { - std::shared_ptr out(new OneSixLibrary(lib.name)); - if (!lib.url.isEmpty()) - { - out->setBaseUrl(lib.url); - } - out->setHint(lib.hint); - if (!lib.absoluteUrl.isEmpty()) - { - out->setAbsoluteUrl(lib.absoluteUrl); - } - out->setAbsoluteUrl(lib.absoluteUrl); - out->extract_excludes = lib.excludes; - for (auto native : lib.natives) - { - out->addNative(native.first, native.second); - } - out->setRules(lib.rules); - out->finalize(); - return out; - } - int findLibrary(QList> haystack, const QString &needle) - { - 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; - } - ApplyError applyTo(OneSixVersion *version) - { - if (minimumLauncherVersion != -1) - { - if (minimumLauncherVersion > CURRENT_MINIMUM_LAUNCHER_VERSION) - { - QLOG_ERROR() << filename << "is for a different launcher version (" - << minimumLauncherVersion << "), current supported is" - << CURRENT_MINIMUM_LAUNCHER_VERSION; - return LauncherVersionError; - } - } - - if (!version->id.isNull() && !mcVersion.isNull()) - { - if (QRegExp(mcVersion, Qt::CaseInsensitive, QRegExp::Wildcard) - .indexIn(version->id) == -1) - { - QLOG_ERROR() << filename << "is for a different version of Minecraft"; - return OtherError; - } - } - - if (!id.isNull()) - { - 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; - } - if (!removeMinecraftArguments.isNull()) - { - 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: - case Library::Prepend: - { - - const int startOfVersion = lib.name.lastIndexOf(':') + 1; - const int index = - findLibrary(version->libraries, - QString(lib.name).replace(startOfVersion, INT_MAX, '*')); - if (index < 0) - { - if (lib.insertType == Library::Append) - { - version->libraries.append(createLibrary(lib)); - } - else - { - version->libraries.prepend(createLibrary(lib)); - } - } - else - { - auto otherLib = version->libraries.at(index); - const Util::Version ourVersion = lib.name.mid(startOfVersion, INT_MAX); - const Util::Version otherVersion = otherLib->version(); - // if the existing version is a hard dependency we can either use it or - // fail, but we can't change it - if (otherLib->dependType == OneSixLibrary::Hard) - { - // we need a higher version, or we're hard to and the versions aren't - // equal - if (ourVersion > otherVersion || - (lib.dependType == Library::Hard && ourVersion != otherVersion)) - { - QLOG_ERROR() << "Error resolving library dependencies between" - << otherLib->rawName() << "and" << lib.name << "in" - << filename; - return OtherError; - } - else - { - // the library is already existing, so we don't have to do anything - } - } - else if (otherLib->dependType == OneSixLibrary::Soft) - { - // if we are higher it means we should update - if (ourVersion > otherVersion) - { - auto library = createLibrary(lib); - if (Util::Version(otherLib->minVersion) < ourVersion) - { - library->minVersion = ourVersion.toString(); - } - version->libraries.replace(index, library); - } - else - { - // our version is smaller than the existing version, but we require - // it: fail - if (lib.dependType == Library::Hard) - { - QLOG_ERROR() << "Error resolving library dependencies between" - << otherLib->rawName() << "and" << lib.name << "in" - << filename; - return OtherError; - } - } - } - } - 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)"; - } - } - - OneSixVersion::VersionFile versionFile; - versionFile.name = name; - versionFile.id = fileId; - versionFile.version = this->version; - versionFile.mcVersion = mcVersion; - versionFile.filename = filename; - versionFile.order = order; - version->versionFiles.append(versionFile); - - return NoApplyError; - } -}; - OneSixVersionBuilder::OneSixVersionBuilder() { } -bool OneSixVersionBuilder::build(OneSixVersion *version, OneSixInstance *instance, +bool OneSixVersionBuilder::build(VersionFinal *version, OneSixInstance *instance, QWidget *widgetParent, const bool onlyVanilla, const QStringList &external) { OneSixVersionBuilder builder; builder.m_version = version; builder.m_instance = instance; builder.m_widgetParent = widgetParent; - return builder.build(onlyVanilla, external); + return builder.buildInternal(onlyVanilla, external); } -bool OneSixVersionBuilder::read(OneSixVersion *version, const QJsonObject &obj) +bool OneSixVersionBuilder::readJsonAndApplyToVersion(VersionFinal *version, const QJsonObject &obj) { OneSixVersionBuilder builder; builder.m_version = version; builder.m_instance = 0; builder.m_widgetParent = 0; - return builder.read(obj); + return builder.readJsonAndApply(obj); } -bool OneSixVersionBuilder::build(const bool onlyVanilla, const QStringList &external) +bool OneSixVersionBuilder::buildInternal(const bool onlyVanilla, const QStringList &external) { m_version->clear(); @@ -837,8 +68,7 @@ bool OneSixVersionBuilder::build(const bool onlyVanilla, const QStringList &exte { QLOG_INFO() << "Reading" << fileName; VersionFile file; - ParseFlags flags = fileName.endsWith("pack.json") ? IsFTBPackJson : NoFlags; - if (!read(QFileInfo(fileName), false, &file, flags)) + if (!parseJsonFile(QFileInfo(fileName), false, &file, fileName.endsWith("pack.json") ? IsFTBPackJson : NoFlags)) { return false; } @@ -856,7 +86,7 @@ bool OneSixVersionBuilder::build(const bool onlyVanilla, const QStringList &exte { QLOG_INFO() << "Reading custom.json"; VersionFile file; - if (!read(QFileInfo(root.absoluteFilePath("custom.json")), false, &file)) + if (!parseJsonFile(QFileInfo(root.absoluteFilePath("custom.json")), false, &file)) { return false; } @@ -876,7 +106,7 @@ bool OneSixVersionBuilder::build(const bool onlyVanilla, const QStringList &exte // version.json QLOG_INFO() << "Reading version.json"; VersionFile file; - if (!read(QFileInfo(root.absoluteFilePath("version.json")), false, &file)) + if (!parseJsonFile(QFileInfo(root.absoluteFilePath("version.json")), false, &file)) { return false; } @@ -907,7 +137,7 @@ bool OneSixVersionBuilder::build(const bool onlyVanilla, const QStringList &exte { QLOG_INFO() << "Reading" << info.fileName(); VersionFile file; - if (!read(info, true, &file)) + if (!parseJsonFile(info, true, &file)) { return false; } @@ -968,7 +198,7 @@ bool OneSixVersionBuilder::build(const bool onlyVanilla, const QStringList &exte return true; } -bool OneSixVersionBuilder::read(const QJsonObject &obj) +bool OneSixVersionBuilder::readJsonAndApply(const QJsonObject &obj) { m_version->clear(); @@ -1000,7 +230,7 @@ bool OneSixVersionBuilder::read(const QJsonObject &obj) return true; } -bool OneSixVersionBuilder::read(const QFileInfo &fileInfo, const bool requireOrder, +bool OneSixVersionBuilder::parseJsonFile(const QFileInfo &fileInfo, const bool requireOrder, VersionFile *out, const ParseFlags flags) { QFile file(fileInfo.absoluteFilePath()); @@ -1072,6 +302,7 @@ QMap OneSixVersionBuilder::readOverrideOrders(OneSixInstance *inst } return out; } + bool OneSixVersionBuilder::writeOverrideOrders(const QMap &order, OneSixInstance *instance) { diff --git a/logic/OneSixVersionBuilder.h b/logic/OneSixVersionBuilder.h index 8cf6f32f..8ca2551a 100644 --- a/logic/OneSixVersionBuilder.h +++ b/logic/OneSixVersionBuilder.h @@ -18,7 +18,7 @@ #include #include -class OneSixVersion; +class VersionFinal; class OneSixInstance; class QWidget; class QJsonObject; @@ -29,8 +29,9 @@ class OneSixVersionBuilder { OneSixVersionBuilder(); public: - static bool build(OneSixVersion *version, OneSixInstance *instance, QWidget *widgetParent, const bool onlyVanilla, const QStringList &external); - static bool read(OneSixVersion *version, const QJsonObject &obj); + static bool build(VersionFinal *version, OneSixInstance *instance, QWidget *widgetParent, const bool onlyVanilla, const QStringList &external); + static bool readJsonAndApplyToVersion(VersionFinal *version, const QJsonObject &obj); + static QMap readOverrideOrders(OneSixInstance *instance); static bool writeOverrideOrders(const QMap &order, OneSixInstance *instance); @@ -42,14 +43,14 @@ public: Q_DECLARE_FLAGS(ParseFlags, ParseFlag) private: - OneSixVersion *m_version; + VersionFinal *m_version; OneSixInstance *m_instance; QWidget *m_widgetParent; - bool build(const bool onlyVanilla, const QStringList &external); - bool read(const QJsonObject &obj); + bool buildInternal(const bool onlyVanilla, const QStringList &external); + bool readJsonAndApply(const QJsonObject &obj); - bool read(const QFileInfo &fileInfo, const bool requireOrder, VersionFile *out, const ParseFlags flags = NoFlags); + bool parseJsonFile(const QFileInfo &fileInfo, const bool requireOrder, VersionFile *out, const ParseFlags flags = NoFlags); }; Q_DECLARE_OPERATORS_FOR_FLAGS(OneSixVersionBuilder::ParseFlags) diff --git a/logic/VersionFile.cpp b/logic/VersionFile.cpp new file mode 100644 index 00000000..76cf9279 --- /dev/null +++ b/logic/VersionFile.cpp @@ -0,0 +1,702 @@ +#include +#include + +#include + +#include "logger/QsLog.h" +#include "logic/VersionFile.h" +#include "logic/OneSixLibrary.h" +#include "logic/VersionFinal.h" + + +#define CURRENT_MINIMUM_LAUNCHER_VERSION 14 + +VersionFile::Library VersionFile::Library::fromJson(const QJsonObject &libObj, + const QString &filename, bool &isError) +{ + isError = true; + Library out; + if (!libObj.contains("name")) + { + QLOG_ERROR() << filename << "contains a library that doesn't have a 'name' field"; + return out; + } + out.name = libObj.value("name").toString(); + + 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(); + } + } + }; + + readString("url", out.url); + readString("MMC-hint", out.hint); + readString("MMC-absulute_url", out.absoluteUrl); + readString("MMC-absoluteUrl", out.absoluteUrl); + if (libObj.contains("extract")) + { + if (!libObj.value("extract").isObject()) + { + QLOG_ERROR() << filename + << "contains a library with an 'extract' field that's not an object"; + return out; + } + QJsonObject extractObj = libObj.value("extract").toObject(); + if (!extractObj.contains("exclude") || !extractObj.value("exclude").isArray()) + { + QLOG_ERROR() << filename << "contains a library with an invalid 'extract' field"; + return out; + } + out.applyExcludes = true; + QJsonArray excludeArray = extractObj.value("exclude").toArray(); + for (auto excludeVal : excludeArray) + { + 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()); + } + } + } + if (libObj.contains("natives")) + { + if (!libObj.value("natives").isObject()) + { + QLOG_ERROR() << filename + << "contains a library with a 'natives' field that's not an object"; + return out; + } + out.applyNatives = true; + QJsonObject nativesObj = libObj.value("natives").toObject(); + for (auto it = nativesObj.begin(); it != nativesObj.end(); ++it) + { + 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; +} + +VersionFile VersionFile::fromJson(const QJsonDocument &doc, const QString &filename, + const bool requireOrder, bool &isError, const bool isFTB) +{ + VersionFile out; + isError = true; + if (doc.isEmpty() || doc.isNull()) + { + QLOG_ERROR() << filename << "is empty or null"; + return out; + } + if (!doc.isObject()) + { + QLOG_ERROR() << "The root of" << filename << "is not an object"; + return out; + } + + QJsonObject root = doc.object(); + + if (requireOrder) + { + 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"; + } + } + + out.name = root.value("name").toString(); + out.fileId = root.value("fileId").toString(); + out.version = root.value("version").toString(); + out.mcVersion = root.value("mcVersion").toString(); + out.filename = filename; + + 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(); + } + } + }; + + // FTB id attribute is completely bogus. We ignore it. + if (!isFTB) + { + 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")) + { + QJsonValue val = root.value("minimumLauncherVersion"); + if (!val.isDouble()) + { + QLOG_WARN() << "minimumLauncherVersion is not an int in" << filename + << "(skipping)"; + } + else + { + out.minimumLauncherVersion = val.toDouble(); + } + } + + if (root.contains("tweakers")) + { + 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()); + } + } + if (root.contains("+tweakers")) + { + 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 (root.contains("-tweakers")) + { + 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()); + } + } + + if (root.contains("libraries")) + { + out.shouldOverwriteLibs = !isFTB; + 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 = Library::fromJson(libObj, filename, error); + if (error) + { + QLOG_ERROR() << "Error while reading a library entry in" << filename; + return out; + } + if (isFTB) + { + lib.hint = "local"; + lib.insertType = Library::Prepend; + out.addLibs.prepend(lib); + } + else + { + out.overwriteLibs.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(); + bool error; + Library lib = Library::fromJson(libObj, filename, error); + if (error) + { + QLOG_ERROR() << "Error while reading a library entry in" << filename; + return out; + } + if (!libObj.contains("insert")) + { + 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 == "prepend") + { + lib.insertType = Library::Prepend; + } + else if (insertString == "append") + { + lib.insertType = Library::Prepend; + } + else if (insertString == "replace") + { + lib.insertType = Library::Replace; + } + else + { + QLOG_ERROR() << "A '+' library in" << filename + << "contains an invalid insert type"; + return out; + } + if (libObj.contains("MMC-depend") && libObj.value("MMC-depend").isString()) + { + const QString dependString = libObj.value("MMC-depend").toString(); + if (dependString == "hard") + { + lib.dependType = Library::Hard; + } + else if (dependString == "soft") + { + lib.dependType = Library::Soft; + } + else + { + QLOG_ERROR() << "A '+' library in" << filename + << "contains an invalid depend 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; +} + +std::shared_ptr VersionFile::createLibrary(const VersionFile::Library &lib) +{ + std::shared_ptr out(new OneSixLibrary(lib.name)); + if (!lib.url.isEmpty()) + { + out->setBaseUrl(lib.url); + } + out->setHint(lib.hint); + if (!lib.absoluteUrl.isEmpty()) + { + out->setAbsoluteUrl(lib.absoluteUrl); + } + out->setAbsoluteUrl(lib.absoluteUrl); + out->extract_excludes = lib.excludes; + for (auto native : lib.natives) + { + out->addNative(native.first, native.second); + } + out->setRules(lib.rules); + out->finalize(); + return out; +} + +int VersionFile::findLibrary(QList> haystack, + const QString &needle) +{ + 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; +} + +VersionFile::ApplyError VersionFile::applyTo(VersionFinal *version) +{ + if (minimumLauncherVersion != -1) + { + if (minimumLauncherVersion > CURRENT_MINIMUM_LAUNCHER_VERSION) + { + QLOG_ERROR() << filename << "is for a different launcher version (" + << minimumLauncherVersion << "), current supported is" + << CURRENT_MINIMUM_LAUNCHER_VERSION; + return LauncherVersionError; + } + } + + if (!version->id.isNull() && !mcVersion.isNull()) + { + if (QRegExp(mcVersion, Qt::CaseInsensitive, QRegExp::Wildcard).indexIn(version->id) == + -1) + { + QLOG_ERROR() << filename << "is for a different version of Minecraft"; + return OtherError; + } + } + + if (!id.isNull()) + { + 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; + } + if (!removeMinecraftArguments.isNull()) + { + 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: + case Library::Prepend: + { + + const int startOfVersion = lib.name.lastIndexOf(':') + 1; + const int index = findLibrary( + version->libraries, QString(lib.name).replace(startOfVersion, INT_MAX, '*')); + if (index < 0) + { + if (lib.insertType == Library::Append) + { + version->libraries.append(createLibrary(lib)); + } + else + { + version->libraries.prepend(createLibrary(lib)); + } + } + else + { + auto otherLib = version->libraries.at(index); + const Util::Version ourVersion = lib.name.mid(startOfVersion, INT_MAX); + const Util::Version otherVersion = otherLib->version(); + // if the existing version is a hard dependency we can either use it or + // fail, but we can't change it + if (otherLib->dependType == OneSixLibrary::Hard) + { + // we need a higher version, or we're hard to and the versions aren't + // equal + if (ourVersion > otherVersion || + (lib.dependType == Library::Hard && ourVersion != otherVersion)) + { + QLOG_ERROR() << "Error resolving library dependencies between" + << otherLib->rawName() << "and" << lib.name << "in" + << filename; + return OtherError; + } + else + { + // the library is already existing, so we don't have to do anything + } + } + else if (otherLib->dependType == OneSixLibrary::Soft) + { + // if we are higher it means we should update + if (ourVersion > otherVersion) + { + auto library = createLibrary(lib); + if (Util::Version(otherLib->minVersion) < ourVersion) + { + library->minVersion = ourVersion.toString(); + } + version->libraries.replace(index, library); + } + else + { + // our version is smaller than the existing version, but we require + // it: fail + if (lib.dependType == Library::Hard) + { + QLOG_ERROR() << "Error resolving library dependencies between" + << otherLib->rawName() << "and" << lib.name << "in" + << filename; + return OtherError; + } + } + } + } + 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)"; + } + } + + VersionFinal::VersionFile versionFile; + versionFile.name = name; + versionFile.id = fileId; + versionFile.version = this->version; + versionFile.mcVersion = mcVersion; + versionFile.filename = filename; + versionFile.order = order; + version->versionFiles.append(versionFile); + + return NoApplyError; +} diff --git a/logic/VersionFile.h b/logic/VersionFile.h new file mode 100644 index 00000000..04694999 --- /dev/null +++ b/logic/VersionFile.h @@ -0,0 +1,90 @@ +#pragma once + +#include +#include +#include +#include "logic/OpSys.h" +#include "logic/OneSixRule.h" +class VersionFinal; + +struct VersionFile +{ + int order; + QString name; + QString fileId; + QString version; + // TODO use the mcVersion to determine if a version file should be removed on update + QString mcVersion; + QString filename; + // TODO requirements + // QMap requirements; + 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> natives; + bool applyRules = false; + QList> rules; + + // user for '+' libraries + enum InsertType + { + Apply, + Append, + Prepend, + Replace + }; + InsertType insertType = Append; + QString insertData; + enum DependType + { + Soft, + Hard + }; + DependType dependType = Soft; + + static Library fromJson(const QJsonObject &libObj, const QString &filename, + bool &isError); + }; + bool shouldOverwriteLibs = false; + QList overwriteLibs; + QList addLibs; + QList removeLibs; + + enum ApplyError + { + LauncherVersionError, + OtherError, + NoApplyError + }; + + static VersionFile fromJson(const QJsonDocument &doc, const QString &filename, + const bool requireOrder, bool &isError, + const bool isFTB = false); + + static std::shared_ptr createLibrary(const Library &lib); + int findLibrary(QList> haystack, const QString &needle); + ApplyError applyTo(VersionFinal *version); +}; \ No newline at end of file diff --git a/logic/VersionFinal.cpp b/logic/VersionFinal.cpp new file mode 100644 index 00000000..ce78e8e3 --- /dev/null +++ b/logic/VersionFinal.cpp @@ -0,0 +1,221 @@ +/* Copyright 2013 MultiMC Contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "VersionFinal.h" + +#include +#include + +#include "OneSixVersionBuilder.h" + +VersionFinal::VersionFinal(OneSixInstance *instance, QObject *parent) + : QAbstractListModel(parent), m_instance(instance) +{ + clear(); +} + +bool VersionFinal::reload(QWidget *widgetParent, const bool onlyVanilla, const QStringList &external) +{ + beginResetModel(); + bool ret = OneSixVersionBuilder::build(this, m_instance, widgetParent, onlyVanilla, external); + endResetModel(); + return ret; +} + +void VersionFinal::clear() +{ + beginResetModel(); + id.clear(); + time.clear(); + releaseTime.clear(); + type.clear(); + assets.clear(); + processArguments.clear(); + minecraftArguments.clear(); + minimumLauncherVersion = 0xDEADBEAF; + mainClass.clear(); + libraries.clear(); + tweakers.clear(); + versionFiles.clear(); + endResetModel(); +} + +void VersionFinal::dump() const +{ + qDebug().nospace() << "VersionFinal(" + << "\n\tid=" << id + << "\n\ttime=" << time + << "\n\treleaseTime=" << releaseTime + << "\n\ttype=" << type + << "\n\tassets=" << assets + << "\n\tprocessArguments=" << processArguments + << "\n\tminecraftArguments=" << minecraftArguments + << "\n\tminimumLauncherVersion=" << minimumLauncherVersion + << "\n\tmainClass=" << mainClass + << "\n\tlibraries="; + for (auto lib : libraries) + { + qDebug().nospace() << "\n\t\t" << lib.get(); + } + qDebug().nospace() << "\n)"; +} + +bool VersionFinal::canRemove(const int index) const +{ + if (index < versionFiles.size()) + { + return versionFiles.at(index).id != "org.multimc.version.json"; + } + return false; +} + +QString VersionFinal::versionFileId(const int index) const +{ + if (index < 0 || index >= versionFiles.size()) + { + return QString(); + } + return versionFiles.at(index).id; +} + +bool VersionFinal::remove(const int index) +{ + if (canRemove(index)) + { + return QFile::remove(versionFiles.at(index).filename); + } + return false; +} + +QList > VersionFinal::getActiveNormalLibs() +{ + QList > output; + for (auto lib : libraries) + { + if (lib->isActive() && !lib->isNative()) + { + output.append(lib); + } + } + return output; +} + +QList > VersionFinal::getActiveNativeLibs() +{ + QList > output; + for (auto lib : libraries) + { + if (lib->isActive() && lib->isNative()) + { + output.append(lib); + } + } + return output; +} + +std::shared_ptr VersionFinal::fromJson(const QJsonObject &obj) +{ + std::shared_ptr version(new VersionFinal(0)); + if (OneSixVersionBuilder::readJsonAndApplyToVersion(version.get(), obj)) + { + return version; + } + return 0; +} + +QVariant VersionFinal::data(const QModelIndex &index, int role) const +{ + if (!index.isValid()) + return QVariant(); + + int row = index.row(); + int column = index.column(); + + if (row < 0 || row >= versionFiles.size()) + return QVariant(); + + if (role == Qt::DisplayRole) + { + switch (column) + { + case 0: + return versionFiles.at(row).name; + case 1: + return versionFiles.at(row).version; + default: + return QVariant(); + } + } + return QVariant(); +} + +QVariant VersionFinal::headerData(int section, Qt::Orientation orientation, int role) const +{ + if (orientation == Qt::Horizontal) + { + if (role == Qt::DisplayRole) + { + switch (section) + { + case 0: + return tr("Name"); + case 1: + return tr("Version"); + default: + return QVariant(); + } + } + } + return QVariant(); +} + +Qt::ItemFlags VersionFinal::flags(const QModelIndex &index) const +{ + if (!index.isValid()) + return Qt::NoItemFlags; + return Qt::ItemIsSelectable | Qt::ItemIsEnabled; +} + +int VersionFinal::rowCount(const QModelIndex &parent) const +{ + return versionFiles.size(); +} + +int VersionFinal::columnCount(const QModelIndex &parent) const +{ + return 2; +} + +QDebug operator<<(QDebug &dbg, const VersionFinal *version) +{ + version->dump(); + return dbg.maybeSpace(); +} +QDebug operator<<(QDebug &dbg, const OneSixLibrary *library) +{ + dbg.nospace() << "OneSixLibrary(" + << "\n\t\t\trawName=" << library->rawName() + << "\n\t\t\tname=" << library->name() + << "\n\t\t\tversion=" << library->version() + << "\n\t\t\ttype=" << library->type() + << "\n\t\t\tisActive=" << library->isActive() + << "\n\t\t\tisNative=" << library->isNative() + << "\n\t\t\tdownloadUrl=" << library->downloadUrl() + << "\n\t\t\tstoragePath=" << library->storagePath() + << "\n\t\t\tabsolutePath=" << library->absoluteUrl() + << "\n\t\t\thint=" << library->hint(); + dbg.nospace() << "\n\t\t)"; + return dbg.maybeSpace(); +} diff --git a/logic/VersionFinal.h b/logic/VersionFinal.h new file mode 100644 index 00000000..c9a5f469 --- /dev/null +++ b/logic/VersionFinal.h @@ -0,0 +1,137 @@ +/* Copyright 2013 MultiMC Contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include + +#include +#include +#include + +#include "OneSixLibrary.h" + +class OneSixInstance; + +class VersionFinal : public QAbstractListModel +{ + Q_OBJECT +public: + explicit VersionFinal(OneSixInstance *instance, QObject *parent = 0); + + virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; + virtual QVariant headerData(int section, Qt::Orientation orientation, int role) const; + virtual int rowCount(const QModelIndex &parent = QModelIndex()) const; + virtual int columnCount(const QModelIndex &parent) const; + virtual Qt::ItemFlags flags(const QModelIndex &index) const; + + bool reload(QWidget *widgetParent, const bool onlyVanilla = false, const QStringList &external = QStringList()); + void clear(); + + void dump() const; + + bool canRemove(const int index) const; + + QString versionFileId(const int index) const; + +public +slots: + bool remove(const int index); + +public: + QList> getActiveNormalLibs(); + QList> getActiveNativeLibs(); + + static std::shared_ptr fromJson(const QJsonObject &obj); + + // 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 releaseTime; + /// Release type - "release" or "snapshot" + QString type; + /// Assets type - "legacy" or a version ID + QString assets; + /** + * DEPRECATED: Old versions of the new vanilla launcher used this + * ex: "username_session_version" + */ + QString processArguments; + /** + * arguments that should be used for launching minecraft + * + * ex: "--username ${auth_player_name} --session ${auth_session} + * --version ${version_name} --gameDir ${game_directory} --assetsDir ${game_assets}" + */ + QString minecraftArguments; + /** + * the minimum launcher version required by this version ... current is 4 (at point of + * writing) + */ + int minimumLauncherVersion = 0xDEADBEEF; + /** + * A list of all tweaker classes + */ + QStringList tweakers; + /** + * The main class to load first + */ + QString mainClass; + + /// the list of libs - both active and inactive, native and java + QList> libraries; + + /* + FIXME: add support for those rules here? Looks like a pile of quick hacks to me though. + + "rules": [ + { + "action": "allow" + }, + { + "action": "disallow", + "os": { + "name": "osx", + "version": "^10\\.5\\.\\d$" + } + } + ], + "incompatibilityReason": "There is a bug in LWJGL which makes it incompatible with OSX + 10.5.8. Please go to New Profile and use 1.5.2 for now. Sorry!" + } + */ + // QList rules; + + struct VersionFile + { + QString name; + QString id; + QString version; + QString mcVersion; + QString filename; + int order; + }; + QList versionFiles; + +private: + OneSixInstance *m_instance; +}; + +QDebug operator<<(QDebug &dbg, const VersionFinal *version); +QDebug operator<<(QDebug &dbg, const OneSixLibrary *library); -- cgit v1.2.3 From 053b938beb7bb47fc63ec1ec2df519573629e32b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Mr=C3=A1zek?= Date: Sun, 2 Mar 2014 01:51:40 +0100 Subject: Get rid of parse flags --- logic/OneSixVersionBuilder.cpp | 8 +++----- logic/OneSixVersionBuilder.h | 11 +---------- 2 files changed, 4 insertions(+), 15 deletions(-) (limited to 'logic') diff --git a/logic/OneSixVersionBuilder.cpp b/logic/OneSixVersionBuilder.cpp index 0d4d66a2..2b05e45a 100644 --- a/logic/OneSixVersionBuilder.cpp +++ b/logic/OneSixVersionBuilder.cpp @@ -68,7 +68,7 @@ bool OneSixVersionBuilder::buildInternal(const bool onlyVanilla, const QStringLi { QLOG_INFO() << "Reading" << fileName; VersionFile file; - if (!parseJsonFile(QFileInfo(fileName), false, &file, fileName.endsWith("pack.json") ? IsFTBPackJson : NoFlags)) + if (!parseJsonFile(QFileInfo(fileName), false, &file, fileName.endsWith("pack.json"))) { return false; } @@ -230,8 +230,7 @@ bool OneSixVersionBuilder::readJsonAndApply(const QJsonObject &obj) return true; } -bool OneSixVersionBuilder::parseJsonFile(const QFileInfo &fileInfo, const bool requireOrder, - VersionFile *out, const ParseFlags flags) +bool OneSixVersionBuilder::parseJsonFile(const QFileInfo& fileInfo, const bool requireOrder, VersionFile* out, bool isFTB) { QFile file(fileInfo.absoluteFilePath()); if (!file.open(QFile::ReadOnly)) @@ -252,14 +251,13 @@ bool OneSixVersionBuilder::parseJsonFile(const QFileInfo &fileInfo, const bool r return false; } bool isError = false; - *out = VersionFile::fromJson(doc, file.fileName(), requireOrder, isError, flags); + *out = VersionFile::fromJson(doc, file.fileName(), requireOrder, isError, isFTB); 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; } diff --git a/logic/OneSixVersionBuilder.h b/logic/OneSixVersionBuilder.h index 8ca2551a..fe77ed9d 100644 --- a/logic/OneSixVersionBuilder.h +++ b/logic/OneSixVersionBuilder.h @@ -35,13 +35,6 @@ public: static QMap readOverrideOrders(OneSixInstance *instance); static bool writeOverrideOrders(const QMap &order, OneSixInstance *instance); - enum ParseFlag - { - NoFlags = 0x0, - IsFTBPackJson = 0x1 - }; - Q_DECLARE_FLAGS(ParseFlags, ParseFlag) - private: VersionFinal *m_version; OneSixInstance *m_instance; @@ -50,7 +43,5 @@ private: bool buildInternal(const bool onlyVanilla, const QStringList &external); bool readJsonAndApply(const QJsonObject &obj); - bool parseJsonFile(const QFileInfo &fileInfo, const bool requireOrder, VersionFile *out, const ParseFlags flags = NoFlags); + bool parseJsonFile(const QFileInfo &fileInfo, const bool requireOrder, VersionFile *out, bool isFTB = false); }; - -Q_DECLARE_OPERATORS_FOR_FLAGS(OneSixVersionBuilder::ParseFlags) -- cgit v1.2.3 From 5a344a293323993eabbe2165d01cbb9a4220201c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Mr=C3=A1zek?= Date: Sun, 2 Mar 2014 02:08:01 +0100 Subject: Gather and store liteloader metadata. --- logic/LiteLoaderInstaller.cpp | 2 +- logic/lists/LiteLoaderVersionList.cpp | 55 ++++++++++++++++++++++++++++------- logic/lists/LiteLoaderVersionList.h | 11 ++++++- 3 files changed, 55 insertions(+), 13 deletions(-) (limited to 'logic') diff --git a/logic/LiteLoaderInstaller.cpp b/logic/LiteLoaderInstaller.cpp index 44400e8a..bb4b07ca 100644 --- a/logic/LiteLoaderInstaller.cpp +++ b/logic/LiteLoaderInstaller.cpp @@ -69,7 +69,7 @@ bool LiteLoaderInstaller::add(OneSixInstance *to) obj.insert("+libraries", libraries); obj.insert("name", QString("LiteLoader")); obj.insert("fileId", id()); - obj.insert("version", to->intendedVersionId()); + obj.insert("version", m_version->version); obj.insert("mcVersion", to->intendedVersionId()); QFile file(filename(to->instanceRoot())); diff --git a/logic/lists/LiteLoaderVersionList.cpp b/logic/lists/LiteLoaderVersionList.cpp index b8cea442..ef95eefd 100644 --- a/logic/lists/LiteLoaderVersionList.cpp +++ b/logic/lists/LiteLoaderVersionList.cpp @@ -92,7 +92,6 @@ void LiteLoaderVersionList::updateListData(QList versions) LLListLoadTask::LLListLoadTask(LiteLoaderVersionList *vlist) { m_list = vlist; - vlistReply = nullptr; } LLListLoadTask::~LLListLoadTask() @@ -102,23 +101,49 @@ LLListLoadTask::~LLListLoadTask() void LLListLoadTask::executeTask() { setStatus(tr("Loading LiteLoader version list...")); - auto worker = MMC->qnam(); - vlistReply = worker->get(QNetworkRequest(QUrl(URLConstants::LITELOADER_URL))); - connect(vlistReply, SIGNAL(finished()), this, SLOT(listDownloaded())); + auto job = new NetJob("Version index"); + // we do not care if the version is stale or not. + auto liteloaderEntry = MMC->metacache()->resolveEntry("liteloader", "versions.json"); + + // verify by poking the server. + liteloaderEntry->stale = true; + + job->addNetAction(listDownload = CacheDownload::make(QUrl(URLConstants::LITELOADER_URL), + liteloaderEntry)); + + connect(listDownload.get(), SIGNAL(failed(int)), SLOT(listFailed())); + + listJob.reset(job); + connect(listJob.get(), SIGNAL(succeeded()), SLOT(listDownloaded())); + connect(listJob.get(), SIGNAL(progress(qint64, qint64)), SIGNAL(progress(qint64, qint64))); + listJob->start(); +} + +void LLListLoadTask::listFailed() +{ + emitFailed("Failed to load LiteLoader version list."); + return; } void LLListLoadTask::listDownloaded() { - if (vlistReply->error() != QNetworkReply::NoError) + QByteArray data; { - vlistReply->deleteLater(); - emitFailed("Failed to load LiteLoader version list" + vlistReply->errorString()); - return; + auto dlJob = listDownload; + auto filename = std::dynamic_pointer_cast(dlJob)->getTargetFilepath(); + QFile listFile(filename); + if (!listFile.open(QIODevice::ReadOnly)) + { + emitFailed("Failed to open the LiteLoader version list."); + return; + } + data = listFile.readAll(); + listFile.close(); + dlJob.reset(); } QJsonParseError jsonError; - QJsonDocument jsonDoc = QJsonDocument::fromJson(vlistReply->readAll(), &jsonError); - vlistReply->deleteLater(); + QJsonDocument jsonDoc = QJsonDocument::fromJson(data, &jsonError); if (jsonError.error != QJsonParseError::NoError) { @@ -140,7 +165,12 @@ void LLListLoadTask::listDownloaded() emitFailed("Error parsing version list JSON: missing 'versions' object"); return; } - const QJsonObject versions = root.value("versions").toObject(); + + auto meta = root.value("meta").toObject(); + QString description = meta.value("description").toString(tr("This is a lightweight loader for mods that don't change game mechanics.")); + QString defaultUrl = meta.value("url").toString("http://dl.liteloader.com"); + QString authors = meta.value("authors").toString("Mumfrey"); + auto versions = root.value("versions").toObject(); QList tempList; for (auto vIt = versions.begin(); vIt != versions.end(); ++vIt) @@ -170,6 +200,9 @@ void LLListLoadTask::listDownloaded() version->md5 = artefact.value("md5").toString(); version->timestamp = artefact.value("timestamp").toDouble(); version->tweakClass = artefact.value("tweakClass").toString(); + version->authors = authors; + version->description = description; + version->defaultUrl = defaultUrl; const QJsonArray libs = artefact.value("libraries").toArray(); for (auto lIt = libs.begin(); lIt != libs.end(); ++lIt) { diff --git a/logic/lists/LiteLoaderVersionList.h b/logic/lists/LiteLoaderVersionList.h index 8f761caf..bfc913e5 100644 --- a/logic/lists/LiteLoaderVersionList.h +++ b/logic/lists/LiteLoaderVersionList.h @@ -22,6 +22,7 @@ #include "BaseVersionList.h" #include "logic/tasks/Task.h" #include "logic/BaseVersion.h" +#include class LLListLoadTask; class QNetworkReply; @@ -46,6 +47,7 @@ public: return version; } + // important info QString version; QString file; QString mcVersion; @@ -54,6 +56,11 @@ public: bool isLatest; QString tweakClass; QStringList libraries; + + // meta + QString defaultUrl; + QString description; + QString authors; }; typedef std::shared_ptr LiteLoaderVersionPtr; @@ -96,8 +103,10 @@ public: protected slots: void listDownloaded(); + void listFailed(); protected: - QNetworkReply *vlistReply; + NetJobPtr listJob; + CacheDownloadPtr listDownload; LiteLoaderVersionList *m_list; }; -- cgit v1.2.3 From 80d146866c8c5f00c6d790b476a774def71010bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Mr=C3=A1zek?= Date: Sun, 2 Mar 2014 02:17:55 +0100 Subject: Remove widgets from logic. --- logic/OneSixInstance.cpp | 6 +++--- logic/OneSixInstance.h | 2 +- logic/OneSixVersionBuilder.cpp | 21 +++++++++++++++++---- logic/OneSixVersionBuilder.h | 4 +--- logic/VersionFinal.cpp | 4 ++-- logic/VersionFinal.h | 2 +- 6 files changed, 25 insertions(+), 14 deletions(-) (limited to 'logic') diff --git a/logic/OneSixInstance.cpp b/logic/OneSixInstance.cpp index bd5d559e..0e0be4d8 100644 --- a/logic/OneSixInstance.cpp +++ b/logic/OneSixInstance.cpp @@ -316,14 +316,14 @@ QString OneSixInstance::currentVersionId() const return intendedVersionId(); } -bool OneSixInstance::reloadVersion(QWidget *widgetParent) +bool OneSixInstance::reloadVersion() { I_D(OneSixInstance); - bool ret = d->version->reload(widgetParent, false, externalPatches()); + bool ret = d->version->reload(false, externalPatches()); if (ret) { - ret = d->vanillaVersion->reload(widgetParent, true, externalPatches()); + ret = d->vanillaVersion->reload(true, externalPatches()); } if (ret) { diff --git a/logic/OneSixInstance.h b/logic/OneSixInstance.h index 75edec1e..c7ef2ee8 100644 --- a/logic/OneSixInstance.h +++ b/logic/OneSixInstance.h @@ -54,7 +54,7 @@ public: virtual QDialog *createModEditDialog(QWidget *parent) override; /// reload the full version json files. return true on success! - bool reloadVersion(QWidget *widgetParent = 0); + bool reloadVersion(); /// clears all version information in preparation for an update void clearVersion(); /// get the current full version info diff --git a/logic/OneSixVersionBuilder.cpp b/logic/OneSixVersionBuilder.cpp index 2b05e45a..98e4b54e 100644 --- a/logic/OneSixVersionBuilder.cpp +++ b/logic/OneSixVersionBuilder.cpp @@ -37,13 +37,11 @@ OneSixVersionBuilder::OneSixVersionBuilder() { } -bool OneSixVersionBuilder::build(VersionFinal *version, OneSixInstance *instance, - QWidget *widgetParent, const bool onlyVanilla, const QStringList &external) +bool OneSixVersionBuilder::build(VersionFinal *version, OneSixInstance *instance, const bool onlyVanilla, const QStringList &external) { OneSixVersionBuilder builder; builder.m_version = version; builder.m_instance = instance; - builder.m_widgetParent = widgetParent; return builder.buildInternal(onlyVanilla, external); } @@ -52,7 +50,6 @@ bool OneSixVersionBuilder::readJsonAndApplyToVersion(VersionFinal *version, cons OneSixVersionBuilder builder; builder.m_version = version; builder.m_instance = 0; - builder.m_widgetParent = 0; return builder.readJsonAndApply(obj); } @@ -117,11 +114,13 @@ bool OneSixVersionBuilder::buildInternal(const bool onlyVanilla, const QStringLi auto error = file.applyTo(m_version); if (error != VersionFile::NoApplyError) { + /* 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; } @@ -159,10 +158,12 @@ bool OneSixVersionBuilder::buildInternal(const bool onlyVanilla, const QStringLi auto error = filePair.second.applyTo(m_version); if (error != VersionFile::NoApplyError) { + /* 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; } } @@ -206,24 +207,30 @@ bool OneSixVersionBuilder::readJsonAndApply(const QJsonObject &obj) 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; } VersionFile::ApplyError error = file.applyTo(m_version); if (error == VersionFile::OtherError) { + /* QMessageBox::critical( m_widgetParent, QObject::tr("Error"), QObject::tr("Error while applying. Please check MultiMC-0.log for more info.")); + */ return false; } else if (error == VersionFile::LauncherVersionError) { + /* QMessageBox::critical( m_widgetParent, QObject::tr("Error"), QObject::tr("The version descriptors of this instance are not compatible with the current version of MultiMC")); + */ return false; } @@ -235,29 +242,35 @@ bool OneSixVersionBuilder::parseJsonFile(const QFileInfo& fileInfo, const bool r 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())); + */ 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)); + */ return false; } bool isError = false; *out = VersionFile::fromJson(doc, file.fileName(), requireOrder, isError, isFTB); 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; } diff --git a/logic/OneSixVersionBuilder.h b/logic/OneSixVersionBuilder.h index fe77ed9d..789fe3f1 100644 --- a/logic/OneSixVersionBuilder.h +++ b/logic/OneSixVersionBuilder.h @@ -20,7 +20,6 @@ class VersionFinal; class OneSixInstance; -class QWidget; class QJsonObject; class QFileInfo; class VersionFile; @@ -29,7 +28,7 @@ class OneSixVersionBuilder { OneSixVersionBuilder(); public: - static bool build(VersionFinal *version, OneSixInstance *instance, QWidget *widgetParent, const bool onlyVanilla, const QStringList &external); + static bool build(VersionFinal *version, OneSixInstance *instance, const bool onlyVanilla, const QStringList &external); static bool readJsonAndApplyToVersion(VersionFinal *version, const QJsonObject &obj); static QMap readOverrideOrders(OneSixInstance *instance); @@ -38,7 +37,6 @@ public: private: VersionFinal *m_version; OneSixInstance *m_instance; - QWidget *m_widgetParent; bool buildInternal(const bool onlyVanilla, const QStringList &external); bool readJsonAndApply(const QJsonObject &obj); diff --git a/logic/VersionFinal.cpp b/logic/VersionFinal.cpp index ce78e8e3..3aa95ed7 100644 --- a/logic/VersionFinal.cpp +++ b/logic/VersionFinal.cpp @@ -26,10 +26,10 @@ VersionFinal::VersionFinal(OneSixInstance *instance, QObject *parent) clear(); } -bool VersionFinal::reload(QWidget *widgetParent, const bool onlyVanilla, const QStringList &external) +bool VersionFinal::reload(const bool onlyVanilla, const QStringList &external) { beginResetModel(); - bool ret = OneSixVersionBuilder::build(this, m_instance, widgetParent, onlyVanilla, external); + bool ret = OneSixVersionBuilder::build(this, m_instance, onlyVanilla, external); endResetModel(); return ret; } diff --git a/logic/VersionFinal.h b/logic/VersionFinal.h index c9a5f469..e5a38423 100644 --- a/logic/VersionFinal.h +++ b/logic/VersionFinal.h @@ -37,7 +37,7 @@ public: virtual int columnCount(const QModelIndex &parent) const; virtual Qt::ItemFlags flags(const QModelIndex &index) const; - bool reload(QWidget *widgetParent, const bool onlyVanilla = false, const QStringList &external = QStringList()); + bool reload(const bool onlyVanilla = false, const QStringList &external = QStringList()); void clear(); void dump() const; -- cgit v1.2.3 From 28ad9befdcac246eb69a434be970abc29a80bc80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Mr=C3=A1zek?= Date: Sun, 2 Mar 2014 19:12:04 +0100 Subject: Remove a lot of error code and error handling madness. --- logic/MMCJson.cpp | 53 ++++++++ logic/MMCJson.h | 46 +++++++ logic/OneSixVersionBuilder.cpp | 90 ++----------- logic/VersionFile.cpp | 288 ++++++++++------------------------------- logic/VersionFile.h | 28 ++-- 5 files changed, 196 insertions(+), 309 deletions(-) create mode 100644 logic/MMCJson.cpp create mode 100644 logic/MMCJson.h (limited to 'logic') diff --git a/logic/MMCJson.cpp b/logic/MMCJson.cpp new file mode 100644 index 00000000..14cde0c1 --- /dev/null +++ b/logic/MMCJson.cpp @@ -0,0 +1,53 @@ +#include "MMCJson.h" +#include + +bool MMCJson::ensureBoolean(const QJsonValue val, const QString what) +{ + if (!val.isBool()) + throw JSONValidationError(what + " is not boolean"); + return val.isBool(); +} + +QJsonValue MMCJson::ensureExists(QJsonValue val, const QString what) +{ + if(val.isNull()) + throw JSONValidationError(what + " does not exist"); + return val; +} + +QJsonArray MMCJson::ensureArray(const QJsonValue val, const QString what) +{ + if (!val.isArray()) + throw JSONValidationError(what + " is not an array"); + return val.toArray(); +} + +double MMCJson::ensureDouble(const QJsonValue val, const QString what) +{ + if (!val.isDouble()) + throw JSONValidationError(what + " is not a number"); + double ret = val.toDouble(); +} + +int MMCJson::ensureInteger(const QJsonValue val, const QString what) +{ + double ret = ensureDouble(val, what); + if (fmod(ret, 1) != 0) + throw JSONValidationError(what + " is not an integer"); + return ret; +} + +QJsonObject MMCJson::ensureObject(const QJsonValue val, const QString what) +{ + if (!val.isObject()) + throw JSONValidationError(what + " is not an object"); + return val.toObject(); +} + +QString MMCJson::ensureString(const QJsonValue val, const QString what) +{ + if (!val.isString()) + throw JSONValidationError(what + " is not a string"); + return val.toString(); +} + diff --git a/logic/MMCJson.h b/logic/MMCJson.h new file mode 100644 index 00000000..3e7342b5 --- /dev/null +++ b/logic/MMCJson.h @@ -0,0 +1,46 @@ +/** + * Some de-bullshitting for Qt JSON failures. + * + * Simple exception-throwing + */ + +#pragma once +#include +#include +#include +#include "MMCError.h" + +class JSONValidationError : public MMCError +{ +public: + JSONValidationError(QString cause) : MMCError(cause) {}; + virtual QString errorName() + { + return "JSONValidationError"; + }; + virtual ~JSONValidationError() {}; +}; + +namespace MMCJson +{ +/// make sure the value exists. throw otherwise. +QJsonValue ensureExists(QJsonValue val, const QString what = "value"); + +/// make sure the value is converted into an object. throw otherwise. +QJsonObject ensureObject(const QJsonValue val, const QString what = "value"); + +/// make sure the value is converted into an array. throw otherwise. +QJsonArray ensureArray(const QJsonValue val, QString what = "value"); + +/// make sure the value is converted into a string. throw otherwise. +QString ensureString(const QJsonValue val, QString what = "value"); + +/// make sure the value is converted into a boolean. throw otherwise. +bool ensureBoolean(const QJsonValue val, QString what = "value"); + +/// make sure the value is converted into an integer. throw otherwise. +int ensureInteger(const QJsonValue val, QString what = "value"); + +/// make sure the value is converted into a double precision floating number. throw otherwise. +double ensureDouble(const QJsonValue val, QString what = "value"); +} diff --git a/logic/OneSixVersionBuilder.cpp b/logic/OneSixVersionBuilder.cpp index 98e4b54e..752f2d8f 100644 --- a/logic/OneSixVersionBuilder.cpp +++ b/logic/OneSixVersionBuilder.cpp @@ -73,10 +73,7 @@ bool OneSixVersionBuilder::buildInternal(const bool onlyVanilla, const QStringLi file.fileId = "org.multimc.external." + file.name; file.version = QString(); file.mcVersion = QString(); - bool isError = false; - auto errorcode = file.applyTo(m_version); - if(errorcode != VersionFile::NoApplyError) - return false; + file.applyTo(m_version); } // else, if there's custom json, we just do that. else if (QFile::exists(root.absoluteFilePath("custom.json"))) @@ -91,9 +88,7 @@ bool OneSixVersionBuilder::buildInternal(const bool onlyVanilla, const QStringLi file.filename = "custom.json"; file.fileId = "org.multimc.custom.json"; file.version = QString(); - auto errorcode = file.applyTo(m_version); - if(errorcode != VersionFile::NoApplyError) - return false; + file.applyTo(m_version); // 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.") } @@ -111,18 +106,8 @@ bool OneSixVersionBuilder::buildInternal(const bool onlyVanilla, const QStringLi file.fileId = "org.multimc.version.json"; file.version = m_instance->intendedVersionId(); file.mcVersion = m_instance->intendedVersionId(); - auto error = file.applyTo(m_version); - if (error != VersionFile::NoApplyError) - { - /* - 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; - } + file.applyTo(m_version); + // QObject::tr("Error while applying %1. Please check MultiMC-0.log for more info.").arg(root.absoluteFilePath("version.json"))); if (onlyVanilla) break; @@ -155,17 +140,8 @@ bool OneSixVersionBuilder::buildInternal(const bool onlyVanilla, const QStringLi { QLOG_DEBUG() << "Applying file with order" << order; auto filePair = files[order]; - auto error = filePair.second.applyTo(m_version); - if (error != VersionFile::NoApplyError) - { - /* - 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; - } + filePair.second.applyTo(m_version); + // QObject::tr("Error while applying %1. Please check MultiMC-0.log for more info.").arg(filePair.first)); } } while(0); @@ -203,37 +179,12 @@ bool OneSixVersionBuilder::readJsonAndApply(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; - } - VersionFile::ApplyError error = file.applyTo(m_version); - if (error == VersionFile::OtherError) - { - /* - QMessageBox::critical( - m_widgetParent, QObject::tr("Error"), - QObject::tr("Error while applying. Please check MultiMC-0.log for more info.")); - */ - return false; - } - else if (error == VersionFile::LauncherVersionError) - { - /* - QMessageBox::critical( - m_widgetParent, QObject::tr("Error"), - QObject::tr("The version descriptors of this instance are not compatible with the current version of MultiMC")); - */ - return false; - } + VersionFile file = VersionFile::fromJson(QJsonDocument(obj), QString(), false); + // QObject::tr("Error while reading. Please check MultiMC-0.log for more info.")); + file.applyTo(m_version); + // 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")); return true; } @@ -242,11 +193,7 @@ bool OneSixVersionBuilder::parseJsonFile(const QFileInfo& fileInfo, const bool r 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())); - */ + // QObject::tr("Unable to open %1: %2").arg(file.fileName(), file.errorString()); return false; } QJsonParseError error; @@ -261,17 +208,8 @@ bool OneSixVersionBuilder::parseJsonFile(const QFileInfo& fileInfo, const bool r */ return false; } - bool isError = false; - *out = VersionFile::fromJson(doc, file.fileName(), requireOrder, isError, isFTB); - 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())); - */ - } + *out = VersionFile::fromJson(doc, file.fileName(), requireOrder, isFTB); + // QObject::tr("Error while reading %1. Please check MultiMC-0.log for more info.").arg(file.fileName()); return true; } diff --git a/logic/VersionFile.cpp b/logic/VersionFile.cpp index 76cf9279..4423e733 100644 --- a/logic/VersionFile.cpp +++ b/logic/VersionFile.cpp @@ -7,19 +7,20 @@ #include "logic/VersionFile.h" #include "logic/OneSixLibrary.h" #include "logic/VersionFinal.h" +#include "MMCJson.h" +using namespace MMCJson; #define CURRENT_MINIMUM_LAUNCHER_VERSION 14 VersionFile::Library VersionFile::Library::fromJson(const QJsonObject &libObj, - const QString &filename, bool &isError) + const QString &filename) { - isError = true; Library out; if (!libObj.contains("name")) { - QLOG_ERROR() << filename << "contains a library that doesn't have a 'name' field"; - return out; + throw JSONValidationError(filename + + "contains a library that doesn't have a 'name' field"); } out.name = libObj.value("name").toString(); @@ -45,44 +46,17 @@ VersionFile::Library VersionFile::Library::fromJson(const QJsonObject &libObj, readString("MMC-absoluteUrl", out.absoluteUrl); if (libObj.contains("extract")) { - if (!libObj.value("extract").isObject()) - { - QLOG_ERROR() << filename - << "contains a library with an 'extract' field that's not an object"; - return out; - } - QJsonObject extractObj = libObj.value("extract").toObject(); - if (!extractObj.contains("exclude") || !extractObj.value("exclude").isArray()) - { - QLOG_ERROR() << filename << "contains a library with an invalid 'extract' field"; - return out; - } out.applyExcludes = true; - QJsonArray excludeArray = extractObj.value("exclude").toArray(); - for (auto excludeVal : excludeArray) + auto extractObj = ensureObject(libObj.value("extract")); + for (auto excludeVal : ensureArray(extractObj.value("exclude"))) { - 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()); - } + out.excludes.append(ensureString(excludeVal)); } } if (libObj.contains("natives")) { - if (!libObj.value("natives").isObject()) - { - QLOG_ERROR() << filename - << "contains a library with a 'natives' field that's not an object"; - return out; - } out.applyNatives = true; - QJsonObject nativesObj = libObj.value("natives").toObject(); + QJsonObject nativesObj = ensureObject(libObj.value("natives")); for (auto it = nativesObj.begin(); it != nativesObj.end(); ++it) { if (!it.value().isString()) @@ -101,24 +75,19 @@ VersionFile::Library VersionFile::Library::fromJson(const QJsonObject &libObj, out.applyRules = true; out.rules = rulesFromJsonV4(libObj); } - isError = false; return out; } -VersionFile VersionFile::fromJson(const QJsonDocument &doc, const QString &filename, - const bool requireOrder, bool &isError, const bool isFTB) +VersionFile VersionFile::fromJson(const QJsonDocument &doc, const QString &filename, const bool requireOrder, const bool isFTB) { VersionFile out; - isError = true; if (doc.isEmpty() || doc.isNull()) { - QLOG_ERROR() << filename << "is empty or null"; - return out; + throw JSONValidationError(filename + " is empty or null"); } if (!doc.isObject()) { - QLOG_ERROR() << "The root of" << filename << "is not an object"; - return out; + throw JSONValidationError("The root of " + filename + " is not an object"); } QJsonObject root = doc.object(); @@ -127,18 +96,11 @@ VersionFile VersionFile::fromJson(const QJsonDocument &doc, const QString &filen { 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; - } + out.order = ensureInteger(root.value("order")); } else { + // FIXME: evaluate if we don't want to throw exceptions here instead QLOG_ERROR() << filename << "doesn't contain an order field"; } } @@ -153,19 +115,11 @@ VersionFile VersionFile::fromJson(const QJsonDocument &doc, const QString &filen { 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(); - } + variable = ensureString(root.value(key)); } }; - // FTB id attribute is completely bogus. We ignore it. + // FIXME: This should be ignored when applying. if (!isFTB) { readString("id", out.id); @@ -180,108 +134,47 @@ VersionFile VersionFile::fromJson(const QJsonDocument &doc, const QString &filen readString("releaseTime", out.releaseTime); readString("time", out.time); readString("assets", out.assets); + if (root.contains("minimumLauncherVersion")) { - QJsonValue val = root.value("minimumLauncherVersion"); - if (!val.isDouble()) - { - QLOG_WARN() << "minimumLauncherVersion is not an int in" << filename - << "(skipping)"; - } - else - { - out.minimumLauncherVersion = val.toDouble(); - } + out.minimumLauncherVersion = ensureInteger(root.value("minimumLauncherVersion")); } if (root.contains("tweakers")) { - 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) + for (auto tweakerVal : ensureArray(root.value("tweakers"))) { - if (!tweakerVal.isString()) - { - QLOG_ERROR() << filename - << "contains a 'tweakers' field entry that's not a string"; - return out; - } - out.overwriteTweakers.append(tweakerVal.toString()); + out.overwriteTweakers.append(ensureString(tweakerVal)); } } + if (root.contains("+tweakers")) { - 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) + for (auto tweakerVal : ensureArray(root.value("+tweakers"))) { - if (!tweakerVal.isString()) - { - QLOG_ERROR() << filename - << "contains a '+tweakers' field entry that's not a string"; - return out; - } - out.addTweakers.append(tweakerVal.toString()); + out.addTweakers.append(ensureString(tweakerVal)); } } + if (root.contains("-tweakers")) { - 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) + for (auto tweakerVal : ensureArray(root.value("-tweakers"))) { - if (!tweakerVal.isString()) - { - QLOG_ERROR() << filename - << "contains a '-tweakers' field entry that's not a string"; - return out; - } - out.removeTweakers.append(tweakerVal.toString()); + out.removeTweakers.append(ensureString(tweakerVal)); } } if (root.contains("libraries")) { + // FIXME: This should be done when applying. out.shouldOverwriteLibs = !isFTB; - 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) + for (auto libVal : ensureArray(root.value("libraries"))) { - if (!libVal.isObject()) - { - QLOG_ERROR() << filename << "contains a library that's not an object"; - return out; - } - QJsonObject libObj = libVal.toObject(); - bool error; - Library lib = Library::fromJson(libObj, filename, error); - if (error) - { - QLOG_ERROR() << "Error while reading a library entry in" << filename; - return out; - } + auto libObj = ensureObject(libVal); + + Library lib = Library::fromJson(libObj, filename); + // FIXME: This should be done when applying. if (isFTB) { lib.hint = "local"; @@ -294,36 +187,18 @@ VersionFile VersionFile::fromJson(const QJsonDocument &doc, const QString &filen } } } + 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) + for (auto libVal : ensureArray(root.value("+libraries"))) { - if (!libVal.isObject()) - { - QLOG_ERROR() << filename << "contains a library that's not an object"; - return out; - } - QJsonObject libObj = libVal.toObject(); - bool error; - Library lib = Library::fromJson(libObj, filename, error); - if (error) - { - QLOG_ERROR() << "Error while reading a library entry in" << filename; - return out; - } - if (!libObj.contains("insert")) - { - QLOG_ERROR() << "Missing 'insert' field in '+libraries' field in" << filename; - return out; - } - QJsonValue insertVal = libObj.value("insert"); + QJsonObject libObj = ensureObject(libVal); + QJsonValue insertVal = ensureExists(libObj.value("insert")); + + // parse the library + Library lib = Library::fromJson(libObj, filename); + + // TODO: utility functions for handling this case. templates? QString insertString; { if (insertVal.isString()) @@ -335,8 +210,8 @@ VersionFile VersionFile::fromJson(const QJsonDocument &doc, const QString &filen QJsonObject insertObj = insertVal.toObject(); if (insertObj.isEmpty()) { - QLOG_ERROR() << "One library has an empty insert object in" << filename; - return out; + throw JSONValidationError("One library has an empty insert object in " + + filename); } insertString = insertObj.keys().first(); lib.insertData = insertObj.value(insertString).toString(); @@ -360,13 +235,12 @@ VersionFile VersionFile::fromJson(const QJsonDocument &doc, const QString &filen } else { - QLOG_ERROR() << "A '+' library in" << filename - << "contains an invalid insert type"; - return out; + throw JSONValidationError("A '+' library in " + filename + + " contains an invalid insert type"); } - if (libObj.contains("MMC-depend") && libObj.value("MMC-depend").isString()) + if (libObj.contains("MMC-depend")) { - const QString dependString = libObj.value("MMC-depend").toString(); + const QString dependString = ensureString(libObj.value("MMC-depend")); if (dependString == "hard") { lib.dependType = Library::Hard; @@ -377,9 +251,8 @@ VersionFile VersionFile::fromJson(const QJsonDocument &doc, const QString &filen } else { - QLOG_ERROR() << "A '+' library in" << filename - << "contains an invalid depend type"; - return out; + throw JSONValidationError("A '+' library in " + filename + + " contains an invalid depend type"); } } out.addLibs.append(lib); @@ -387,36 +260,12 @@ VersionFile VersionFile::fromJson(const QJsonDocument &doc, const QString &filen } 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) + for (auto libVal : ensureArray(root.value("-libraries"))) { - 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()); + auto libObj = ensureObject(libVal); + out.removeLibs.append(ensureString(libObj.value("name"))); } } - - isError = false; return out; } @@ -457,16 +306,15 @@ int VersionFile::findLibrary(QList> haystack, return -1; } -VersionFile::ApplyError VersionFile::applyTo(VersionFinal *version) +void VersionFile::applyTo(VersionFinal *version) { if (minimumLauncherVersion != -1) { if (minimumLauncherVersion > CURRENT_MINIMUM_LAUNCHER_VERSION) { - QLOG_ERROR() << filename << "is for a different launcher version (" - << minimumLauncherVersion << "), current supported is" - << CURRENT_MINIMUM_LAUNCHER_VERSION; - return LauncherVersionError; + throw VersionBuildError( + QString("%1 is for a different launcher version (%2), current supported is %3") + .arg(filename, minimumLauncherVersion, CURRENT_MINIMUM_LAUNCHER_VERSION)); } } @@ -475,8 +323,8 @@ VersionFile::ApplyError VersionFile::applyTo(VersionFinal *version) if (QRegExp(mcVersion, Qt::CaseInsensitive, QRegExp::Wildcard).indexIn(version->id) == -1) { - QLOG_ERROR() << filename << "is for a different version of Minecraft"; - return OtherError; + throw VersionBuildError( + QString("%1 is for a different version of Minecraft").arg(filename)); } } @@ -587,7 +435,7 @@ VersionFile::ApplyError VersionFile::applyTo(VersionFinal *version) } else { - QLOG_WARN() << "Couldn't find" << lib.insertData << "(skipping)"; + QLOG_WARN() << "Couldn't find" << lib.name << "(skipping)"; } break; } @@ -623,10 +471,10 @@ VersionFile::ApplyError VersionFile::applyTo(VersionFinal *version) if (ourVersion > otherVersion || (lib.dependType == Library::Hard && ourVersion != otherVersion)) { - QLOG_ERROR() << "Error resolving library dependencies between" - << otherLib->rawName() << "and" << lib.name << "in" - << filename; - return OtherError; + throw VersionBuildError( + QString( + "Error resolving library dependencies between %1 and %2 in %3.") + .arg(otherLib->rawName(), lib.name, filename)); } else { @@ -651,10 +499,10 @@ VersionFile::ApplyError VersionFile::applyTo(VersionFinal *version) // it: fail if (lib.dependType == Library::Hard) { - QLOG_ERROR() << "Error resolving library dependencies between" - << otherLib->rawName() << "and" << lib.name << "in" - << filename; - return OtherError; + throw VersionBuildError(QString( + "Error resolving library dependencies between %1 and %2 in %3.") + .arg(otherLib->rawName(), lib.name, + filename)); } } } @@ -697,6 +545,4 @@ VersionFile::ApplyError VersionFile::applyTo(VersionFinal *version) versionFile.filename = filename; versionFile.order = order; version->versionFiles.append(versionFile); - - return NoApplyError; } diff --git a/logic/VersionFile.h b/logic/VersionFile.h index 04694999..37c8c415 100644 --- a/logic/VersionFile.h +++ b/logic/VersionFile.h @@ -5,8 +5,21 @@ #include #include "logic/OpSys.h" #include "logic/OneSixRule.h" +#include "MMCError.h" + class VersionFinal; +class VersionBuildError : public MMCError +{ +public: + VersionBuildError(QString cause) : MMCError(cause) {}; + virtual QString errorName() + { + return "VersionBuildError"; + }; + virtual ~VersionBuildError() {}; +}; + struct VersionFile { int order; @@ -65,26 +78,17 @@ struct VersionFile }; DependType dependType = Soft; - static Library fromJson(const QJsonObject &libObj, const QString &filename, - bool &isError); + static Library fromJson(const QJsonObject &libObj, const QString &filename); }; bool shouldOverwriteLibs = false; QList overwriteLibs; QList addLibs; QList removeLibs; - enum ApplyError - { - LauncherVersionError, - OtherError, - NoApplyError - }; - static VersionFile fromJson(const QJsonDocument &doc, const QString &filename, - const bool requireOrder, bool &isError, - const bool isFTB = false); + const bool requireOrder, const bool isFTB = false); static std::shared_ptr createLibrary(const Library &lib); int findLibrary(QList> haystack, const QString &needle); - ApplyError applyTo(VersionFinal *version); + void applyTo(VersionFinal *version); }; \ No newline at end of file -- cgit v1.2.3 From 29cdc9364b0153d04a211adf3eab86076174c0a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Mr=C3=A1zek?= Date: Mon, 3 Mar 2014 01:23:10 +0100 Subject: More code butchery related to version files. No end in sight. --- logic/OneSixInstance.cpp | 19 ++++++---- logic/OneSixVersionBuilder.cpp | 59 +++++++++-------------------- logic/OneSixVersionBuilder.h | 13 ++++--- logic/VersionFile.cpp | 41 ++++++++++---------- logic/VersionFile.h | 85 ++++++++++++++++++++++-------------------- logic/VersionFinal.cpp | 14 ++++--- 6 files changed, 109 insertions(+), 122 deletions(-) (limited to 'logic') diff --git a/logic/OneSixInstance.cpp b/logic/OneSixInstance.cpp index 0e0be4d8..f6fe49f1 100644 --- a/logic/OneSixInstance.cpp +++ b/logic/OneSixInstance.cpp @@ -27,6 +27,7 @@ #include "icons/IconList.h" #include "MinecraftProcess.h" #include "gui/dialogs/OneSixModEditDialog.h" +#include OneSixInstance::OneSixInstance(const QString &rootDir, SettingsObject *settings, QObject *parent) : BaseInstance(new OneSixInstancePrivate(), rootDir, settings, parent) @@ -320,21 +321,23 @@ bool OneSixInstance::reloadVersion() { I_D(OneSixInstance); - bool ret = d->version->reload(false, externalPatches()); - if (ret) - { - ret = d->vanillaVersion->reload(true, externalPatches()); - } - if (ret) + try { + d->version->reload(false, externalPatches()); + d->vanillaVersion->reload(true, externalPatches()); setFlags(flags() & ~VersionBrokenFlag); emit versionReloaded(); + return true; } - else + catch(MMCError error) { + d->version->clear(); + d->vanillaVersion->clear(); setFlags(flags() | VersionBrokenFlag); + //TODO: rethrow to show some error message(s)? + emit versionReloaded(); + return false; } - return ret; } void OneSixInstance::clearVersion() diff --git a/logic/OneSixVersionBuilder.cpp b/logic/OneSixVersionBuilder.cpp index 752f2d8f..37467aef 100644 --- a/logic/OneSixVersionBuilder.cpp +++ b/logic/OneSixVersionBuilder.cpp @@ -30,6 +30,7 @@ #include "OneSixInstance.h" #include "OneSixRule.h" #include "VersionFile.h" +#include "MMCJson.h" #include "modutils.h" #include "logger/QsLog.h" @@ -37,23 +38,23 @@ OneSixVersionBuilder::OneSixVersionBuilder() { } -bool OneSixVersionBuilder::build(VersionFinal *version, OneSixInstance *instance, const bool onlyVanilla, const QStringList &external) +void OneSixVersionBuilder::build(VersionFinal *version, OneSixInstance *instance, const bool onlyVanilla, const QStringList &external) { OneSixVersionBuilder builder; builder.m_version = version; builder.m_instance = instance; - return builder.buildInternal(onlyVanilla, external); + builder.buildInternal(onlyVanilla, external); } -bool OneSixVersionBuilder::readJsonAndApplyToVersion(VersionFinal *version, const QJsonObject &obj) +void OneSixVersionBuilder::readJsonAndApplyToVersion(VersionFinal *version, const QJsonObject &obj) { OneSixVersionBuilder builder; builder.m_version = version; builder.m_instance = 0; - return builder.readJsonAndApply(obj); + builder.readJsonAndApply(obj); } -bool OneSixVersionBuilder::buildInternal(const bool onlyVanilla, const QStringList &external) +void OneSixVersionBuilder::buildInternal(const bool onlyVanilla, const QStringList &external) { m_version->clear(); @@ -64,11 +65,7 @@ bool OneSixVersionBuilder::buildInternal(const bool onlyVanilla, const QStringLi if(!external.isEmpty()) for (auto fileName : external) { QLOG_INFO() << "Reading" << fileName; - VersionFile file; - if (!parseJsonFile(QFileInfo(fileName), false, &file, fileName.endsWith("pack.json"))) - { - return false; - } + VersionFile file = parseJsonFile(QFileInfo(fileName), false, fileName.endsWith("pack.json")); file.name = QFileInfo(fileName).fileName(); file.fileId = "org.multimc.external." + file.name; file.version = QString(); @@ -79,11 +76,7 @@ bool OneSixVersionBuilder::buildInternal(const bool onlyVanilla, const QStringLi else if (QFile::exists(root.absoluteFilePath("custom.json"))) { QLOG_INFO() << "Reading custom.json"; - VersionFile file; - if (!parseJsonFile(QFileInfo(root.absoluteFilePath("custom.json")), false, &file)) - { - return false; - } + VersionFile file = parseJsonFile(QFileInfo(root.absoluteFilePath("custom.json")), false); file.name = "custom.json"; file.filename = "custom.json"; file.fileId = "org.multimc.custom.json"; @@ -98,11 +91,8 @@ bool OneSixVersionBuilder::buildInternal(const bool onlyVanilla, const QStringLi // version.json QLOG_INFO() << "Reading version.json"; VersionFile file; - if (!parseJsonFile(QFileInfo(root.absoluteFilePath("version.json")), false, &file)) - { - return false; - } - file.name = "version.json"; + parseJsonFile(QFileInfo(root.absoluteFilePath("version.json")), false, &file); + file.name = "Minecraft"; file.fileId = "org.multimc.version.json"; file.version = m_instance->intendedVersionId(); file.mcVersion = m_instance->intendedVersionId(); @@ -120,19 +110,14 @@ bool OneSixVersionBuilder::buildInternal(const bool onlyVanilla, const QStringLi for (auto info : patches.entryInfoList(QStringList() << "*.json", QDir::Files)) { QLOG_INFO() << "Reading" << info.fileName(); - VersionFile file; - if (!parseJsonFile(info, true, &file)) - { - return false; - } + VersionFile file = parseJsonFile(info, true); if (overrideOrder.contains(file.fileId)) { file.order = overrideOrder.value(file.fileId); } if (files.contains(file.order)) { - QLOG_ERROR() << file.fileId << "has the same order as" << files[file.order].second.fileId; - return false; + 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)); } @@ -141,7 +126,6 @@ bool OneSixVersionBuilder::buildInternal(const bool onlyVanilla, const QStringLi QLOG_DEBUG() << "Applying file with order" << order; auto filePair = files[order]; filePair.second.applyTo(m_version); - // QObject::tr("Error while applying %1. Please check MultiMC-0.log for more info.").arg(filePair.first)); } } while(0); @@ -171,11 +155,9 @@ bool OneSixVersionBuilder::buildInternal(const bool onlyVanilla, const QStringLi } } } - - return true; } -bool OneSixVersionBuilder::readJsonAndApply(const QJsonObject &obj) +void OneSixVersionBuilder::readJsonAndApply(const QJsonObject &obj) { m_version->clear(); @@ -185,32 +167,25 @@ bool OneSixVersionBuilder::readJsonAndApply(const QJsonObject &obj) file.applyTo(m_version); // 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")); - return true; } -bool OneSixVersionBuilder::parseJsonFile(const QFileInfo& fileInfo, const bool requireOrder, VersionFile* out, bool isFTB) +VersionFile OneSixVersionBuilder::parseJsonFile(const QFileInfo &fileInfo, const bool requireOrder, bool isFTB) { QFile file(fileInfo.absoluteFilePath()); if (!file.open(QFile::ReadOnly)) { - // QObject::tr("Unable to open %1: %2").arg(file.fileName(), file.errorString()); - return false; + throw JSONValidationError(QObject::tr("Unable to open %1: %2").arg(file.fileName(), file.errorString())); } 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") + throw JSONValidationError(QObject::tr("Unable to parse %1: %2 at %3") .arg(file.fileName(), error.errorString()) .arg(error.offset)); - */ - return false; } - *out = VersionFile::fromJson(doc, file.fileName(), requireOrder, isFTB); + return VersionFile::fromJson(doc, file.fileName(), requireOrder, isFTB); // QObject::tr("Error while reading %1. Please check MultiMC-0.log for more info.").arg(file.fileName()); - return true; } QMap OneSixVersionBuilder::readOverrideOrders(OneSixInstance *instance) diff --git a/logic/OneSixVersionBuilder.h b/logic/OneSixVersionBuilder.h index 789fe3f1..c5ef83f3 100644 --- a/logic/OneSixVersionBuilder.h +++ b/logic/OneSixVersionBuilder.h @@ -17,19 +17,20 @@ #include #include +#include "VersionFile.h" class VersionFinal; class OneSixInstance; class QJsonObject; class QFileInfo; -class VersionFile; class OneSixVersionBuilder { OneSixVersionBuilder(); public: - static bool build(VersionFinal *version, OneSixInstance *instance, const bool onlyVanilla, const QStringList &external); - static bool readJsonAndApplyToVersion(VersionFinal *version, const QJsonObject &obj); + static void build(VersionFinal *version, OneSixInstance *instance, const bool onlyVanilla, + const QStringList &external); + static void readJsonAndApplyToVersion(VersionFinal *version, const QJsonObject &obj); static QMap readOverrideOrders(OneSixInstance *instance); static bool writeOverrideOrders(const QMap &order, OneSixInstance *instance); @@ -38,8 +39,8 @@ private: VersionFinal *m_version; OneSixInstance *m_instance; - bool buildInternal(const bool onlyVanilla, const QStringList &external); - bool readJsonAndApply(const QJsonObject &obj); + void buildInternal(const bool onlyVanilla, const QStringList &external); + void readJsonAndApply(const QJsonObject &obj); - bool parseJsonFile(const QFileInfo &fileInfo, const bool requireOrder, VersionFile *out, bool isFTB = false); + VersionFile parseJsonFile(const QFileInfo &fileInfo, const bool requireOrder, bool isFTB = false); }; diff --git a/logic/VersionFile.cpp b/logic/VersionFile.cpp index 4423e733..b7695907 100644 --- a/logic/VersionFile.cpp +++ b/logic/VersionFile.cpp @@ -13,10 +13,10 @@ using namespace MMCJson; #define CURRENT_MINIMUM_LAUNCHER_VERSION 14 -VersionFile::Library VersionFile::Library::fromJson(const QJsonObject &libObj, +RawLibrary RawLibrary::fromJson(const QJsonObject &libObj, const QString &filename) { - Library out; + RawLibrary out; if (!libObj.contains("name")) { throw JSONValidationError(filename + @@ -78,7 +78,8 @@ VersionFile::Library VersionFile::Library::fromJson(const QJsonObject &libObj, return out; } -VersionFile VersionFile::fromJson(const QJsonDocument &doc, const QString &filename, const bool requireOrder, const bool isFTB) +VersionFile VersionFile::fromJson(const QJsonDocument &doc, const QString &filename, + const bool requireOrder, const bool isFTB) { VersionFile out; if (doc.isEmpty() || doc.isNull()) @@ -173,12 +174,12 @@ VersionFile VersionFile::fromJson(const QJsonDocument &doc, const QString &filen { auto libObj = ensureObject(libVal); - Library lib = Library::fromJson(libObj, filename); + RawLibrary lib = RawLibrary::fromJson(libObj, filename); // FIXME: This should be done when applying. if (isFTB) { lib.hint = "local"; - lib.insertType = Library::Prepend; + lib.insertType = RawLibrary::Prepend; out.addLibs.prepend(lib); } else @@ -196,7 +197,7 @@ VersionFile VersionFile::fromJson(const QJsonDocument &doc, const QString &filen QJsonValue insertVal = ensureExists(libObj.value("insert")); // parse the library - Library lib = Library::fromJson(libObj, filename); + RawLibrary lib = RawLibrary::fromJson(libObj, filename); // TODO: utility functions for handling this case. templates? QString insertString; @@ -219,19 +220,19 @@ VersionFile VersionFile::fromJson(const QJsonDocument &doc, const QString &filen } if (insertString == "apply") { - lib.insertType = Library::Apply; + lib.insertType = RawLibrary::Apply; } else if (insertString == "prepend") { - lib.insertType = Library::Prepend; + lib.insertType = RawLibrary::Prepend; } else if (insertString == "append") { - lib.insertType = Library::Prepend; + lib.insertType = RawLibrary::Prepend; } else if (insertString == "replace") { - lib.insertType = Library::Replace; + lib.insertType = RawLibrary::Replace; } else { @@ -243,11 +244,11 @@ VersionFile VersionFile::fromJson(const QJsonDocument &doc, const QString &filen const QString dependString = ensureString(libObj.value("MMC-depend")); if (dependString == "hard") { - lib.dependType = Library::Hard; + lib.dependType = RawLibrary::Hard; } else if (dependString == "soft") { - lib.dependType = Library::Soft; + lib.dependType = RawLibrary::Soft; } else { @@ -269,7 +270,7 @@ VersionFile VersionFile::fromJson(const QJsonDocument &doc, const QString &filen return out; } -std::shared_ptr VersionFile::createLibrary(const VersionFile::Library &lib) +std::shared_ptr VersionFile::createLibrary(const RawLibrary &lib) { std::shared_ptr out(new OneSixLibrary(lib.name)); if (!lib.url.isEmpty()) @@ -396,7 +397,7 @@ void VersionFile::applyTo(VersionFinal *version) { switch (lib.insertType) { - case Library::Apply: + case RawLibrary::Apply: { int index = findLibrary(version->libraries, lib.name); @@ -439,8 +440,8 @@ void VersionFile::applyTo(VersionFinal *version) } break; } - case Library::Append: - case Library::Prepend: + case RawLibrary::Append: + case RawLibrary::Prepend: { const int startOfVersion = lib.name.lastIndexOf(':') + 1; @@ -448,7 +449,7 @@ void VersionFile::applyTo(VersionFinal *version) version->libraries, QString(lib.name).replace(startOfVersion, INT_MAX, '*')); if (index < 0) { - if (lib.insertType == Library::Append) + if (lib.insertType == RawLibrary::Append) { version->libraries.append(createLibrary(lib)); } @@ -469,7 +470,7 @@ void VersionFile::applyTo(VersionFinal *version) // we need a higher version, or we're hard to and the versions aren't // equal if (ourVersion > otherVersion || - (lib.dependType == Library::Hard && ourVersion != otherVersion)) + (lib.dependType == RawLibrary::Hard && ourVersion != otherVersion)) { throw VersionBuildError( QString( @@ -497,7 +498,7 @@ void VersionFile::applyTo(VersionFinal *version) { // our version is smaller than the existing version, but we require // it: fail - if (lib.dependType == Library::Hard) + if (lib.dependType == RawLibrary::Hard) { throw VersionBuildError(QString( "Error resolving library dependencies between %1 and %2 in %3.") @@ -509,7 +510,7 @@ void VersionFile::applyTo(VersionFinal *version) } break; } - case Library::Replace: + case RawLibrary::Replace: { int index = findLibrary(version->libraries, lib.insertData); if (index >= 0) diff --git a/logic/VersionFile.h b/logic/VersionFile.h index 37c8c415..0f183ae8 100644 --- a/logic/VersionFile.h +++ b/logic/VersionFile.h @@ -20,8 +20,50 @@ public: virtual ~VersionBuildError() {}; }; +struct RawLibrary +{ + QString name; + QString url; + QString hint; + QString absoluteUrl; + bool applyExcludes = false; + QStringList excludes; + bool applyNatives = false; + QList> natives; + bool applyRules = false; + QList> rules; + + // user for '+' libraries + enum InsertType + { + Apply, + Append, + Prepend, + Replace + }; + InsertType insertType = Append; + QString insertData; + enum DependType + { + Soft, + Hard + }; + DependType dependType = Soft; + + static RawLibrary fromJson(const QJsonObject &libObj, const QString &filename); +}; + struct VersionFile { +public: /* methods */ + static VersionFile fromJson(const QJsonDocument &doc, const QString &filename, + const bool requireOrder, const bool isFTB = false); + + static std::shared_ptr createLibrary(const RawLibrary &lib); + int findLibrary(QList> haystack, const QString &needle); + void applyTo(VersionFinal *version); + +public: /* data */ int order; QString name; QString fileId; @@ -48,47 +90,8 @@ struct VersionFile QStringList addTweakers; QStringList removeTweakers; - struct Library - { - QString name; - QString url; - QString hint; - QString absoluteUrl; - bool applyExcludes = false; - QStringList excludes; - bool applyNatives = false; - QList> natives; - bool applyRules = false; - QList> rules; - - // user for '+' libraries - enum InsertType - { - Apply, - Append, - Prepend, - Replace - }; - InsertType insertType = Append; - QString insertData; - enum DependType - { - Soft, - Hard - }; - DependType dependType = Soft; - - static Library fromJson(const QJsonObject &libObj, const QString &filename); - }; bool shouldOverwriteLibs = false; - QList overwriteLibs; - QList addLibs; + QList overwriteLibs; + QList addLibs; QList removeLibs; - - static VersionFile fromJson(const QJsonDocument &doc, const QString &filename, - const bool requireOrder, const bool isFTB = false); - - static std::shared_ptr createLibrary(const Library &lib); - int findLibrary(QList> haystack, const QString &needle); - void applyTo(VersionFinal *version); }; \ No newline at end of file diff --git a/logic/VersionFinal.cpp b/logic/VersionFinal.cpp index 3aa95ed7..ec450eda 100644 --- a/logic/VersionFinal.cpp +++ b/logic/VersionFinal.cpp @@ -28,10 +28,10 @@ VersionFinal::VersionFinal(OneSixInstance *instance, QObject *parent) bool VersionFinal::reload(const bool onlyVanilla, const QStringList &external) { + //FIXME: source of epic failure. beginResetModel(); - bool ret = OneSixVersionBuilder::build(this, m_instance, onlyVanilla, external); + OneSixVersionBuilder::build(this, m_instance, onlyVanilla, external); endResetModel(); - return ret; } void VersionFinal::clear() @@ -128,11 +128,15 @@ QList > VersionFinal::getActiveNativeLibs() std::shared_ptr VersionFinal::fromJson(const QJsonObject &obj) { std::shared_ptr version(new VersionFinal(0)); - if (OneSixVersionBuilder::readJsonAndApplyToVersion(version.get(), obj)) + try { - return version; + OneSixVersionBuilder::readJsonAndApplyToVersion(version.get(), obj); } - return 0; + catch(MMCError err) + { + return 0; + } + return version; } QVariant VersionFinal::data(const QModelIndex &index, int role) const -- cgit v1.2.3 From d66f2500a6b4215a135f1e41802f7c7498375c62 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Mr=C3=A1zek?= Date: Mon, 3 Mar 2014 01:44:07 +0100 Subject: No end in sight :< --- logic/OneSixVersionBuilder.cpp | 41 ++++++++++++++++++++++------------------- logic/OneSixVersionBuilder.h | 1 + 2 files changed, 23 insertions(+), 19 deletions(-) (limited to 'logic') diff --git a/logic/OneSixVersionBuilder.cpp b/logic/OneSixVersionBuilder.cpp index 37467aef..879ff72e 100644 --- a/logic/OneSixVersionBuilder.cpp +++ b/logic/OneSixVersionBuilder.cpp @@ -130,29 +130,32 @@ void OneSixVersionBuilder::buildInternal(const bool onlyVanilla, const QStringLi } while(0); // some final touches + finalizeVersion(); +} + +void OneSixVersionBuilder::finalizeVersion() +{ + if (m_version->assets.isEmpty()) { - if (m_version->assets.isEmpty()) + m_version->assets = "legacy"; + } + if (m_version->minecraftArguments.isEmpty()) + { + QString toCompare = m_version->processArguments.toLower(); + if (toCompare == "legacy") { - m_version->assets = "legacy"; + m_version->minecraftArguments = " ${auth_player_name} ${auth_session}"; } - if (m_version->minecraftArguments.isEmpty()) + else if (toCompare == "username_session") { - QString toCompare = m_version->processArguments.toLower(); - if (toCompare == "legacy") - { - m_version->minecraftArguments = " ${auth_player_name} ${auth_session}"; - } - else if (toCompare == "username_session") - { - 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}"; - } + 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}"; } } } diff --git a/logic/OneSixVersionBuilder.h b/logic/OneSixVersionBuilder.h index c5ef83f3..c48e8ec5 100644 --- a/logic/OneSixVersionBuilder.h +++ b/logic/OneSixVersionBuilder.h @@ -41,6 +41,7 @@ private: void buildInternal(const bool onlyVanilla, const QStringList &external); void readJsonAndApply(const QJsonObject &obj); + void finalizeVersion(); VersionFile parseJsonFile(const QFileInfo &fileInfo, const bool requireOrder, bool isFTB = false); }; -- cgit v1.2.3 From 011ea8453015ff4d8fd1f9bed5bed36959c20269 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Mr=C3=A1zek?= Date: Mon, 3 Mar 2014 09:08:32 +0100 Subject: Fix missed version file assignment. --- logic/OneSixVersionBuilder.cpp | 5 ++--- logic/VersionFile.h | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) (limited to 'logic') diff --git a/logic/OneSixVersionBuilder.cpp b/logic/OneSixVersionBuilder.cpp index 879ff72e..0c63dc2a 100644 --- a/logic/OneSixVersionBuilder.cpp +++ b/logic/OneSixVersionBuilder.cpp @@ -90,8 +90,7 @@ void OneSixVersionBuilder::buildInternal(const bool onlyVanilla, const QStringLi { // version.json QLOG_INFO() << "Reading version.json"; - VersionFile file; - parseJsonFile(QFileInfo(root.absoluteFilePath("version.json")), false, &file); + VersionFile file = parseJsonFile(QFileInfo(root.absoluteFilePath("version.json")), false); file.name = "Minecraft"; file.fileId = "org.multimc.version.json"; file.version = m_instance->intendedVersionId(); @@ -124,7 +123,7 @@ void OneSixVersionBuilder::buildInternal(const bool onlyVanilla, const QStringLi for (auto order : files.keys()) { QLOG_DEBUG() << "Applying file with order" << order; - auto filePair = files[order]; + auto & filePair = files[order]; filePair.second.applyTo(m_version); } } while(0); diff --git a/logic/VersionFile.h b/logic/VersionFile.h index 0f183ae8..0475f927 100644 --- a/logic/VersionFile.h +++ b/logic/VersionFile.h @@ -64,7 +64,7 @@ public: /* methods */ void applyTo(VersionFinal *version); public: /* data */ - int order; + int order = 0; QString name; QString fileId; QString version; -- cgit v1.2.3 From 47bc7e5ee377dacfeb7cf3d13f07cfd24db906fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Mr=C3=A1zek?= Date: Wed, 5 Mar 2014 01:50:05 +0100 Subject: More refactor. --- logic/MMCJson.cpp | 7 ++ logic/MMCJson.h | 4 + logic/OneSixLibrary.h | 3 + logic/OneSixVersionBuilder.cpp | 123 +++++++++++++++------------ logic/OneSixVersionBuilder.h | 3 +- logic/VersionFile.cpp | 189 +++++++++++++++++++---------------------- logic/VersionFile.h | 16 ++-- logic/VersionFinal.cpp | 42 --------- logic/VersionFinal.h | 10 +-- 9 files changed, 183 insertions(+), 214 deletions(-) (limited to 'logic') diff --git a/logic/MMCJson.cpp b/logic/MMCJson.cpp index 14cde0c1..80d36204 100644 --- a/logic/MMCJson.cpp +++ b/logic/MMCJson.cpp @@ -44,6 +44,13 @@ QJsonObject MMCJson::ensureObject(const QJsonValue val, const QString what) return val.toObject(); } +QJsonObject MMCJson::ensureObject(const QJsonDocument val, const QString what) +{ + if (!val.isObject()) + throw JSONValidationError(what + " is not an object"); + return val.object(); +} + QString MMCJson::ensureString(const QJsonValue val, const QString what) { if (!val.isString()) diff --git a/logic/MMCJson.h b/logic/MMCJson.h index 3e7342b5..b0d898fc 100644 --- a/logic/MMCJson.h +++ b/logic/MMCJson.h @@ -7,6 +7,7 @@ #pragma once #include #include +#include #include #include "MMCError.h" @@ -29,6 +30,9 @@ QJsonValue ensureExists(QJsonValue val, const QString what = "value"); /// make sure the value is converted into an object. throw otherwise. QJsonObject ensureObject(const QJsonValue val, const QString what = "value"); +/// make sure the document is converted into an object. throw otherwise. +QJsonObject ensureObject(const QJsonDocument val, const QString what = "value"); + /// make sure the value is converted into an array. throw otherwise. QJsonArray ensureArray(const QJsonValue val, QString what = "value"); diff --git a/logic/OneSixLibrary.h b/logic/OneSixLibrary.h index 371ca6f4..3bd21c51 100644 --- a/logic/OneSixLibrary.h +++ b/logic/OneSixLibrary.h @@ -26,6 +26,9 @@ class Rule; +class OneSixLibrary; +typedef std::shared_ptr OneSixLibraryPtr; + class OneSixLibrary { private: diff --git a/logic/OneSixVersionBuilder.cpp b/logic/OneSixVersionBuilder.cpp index 0c63dc2a..a6bc5ec7 100644 --- a/logic/OneSixVersionBuilder.cpp +++ b/logic/OneSixVersionBuilder.cpp @@ -65,23 +65,23 @@ void OneSixVersionBuilder::buildInternal(const bool onlyVanilla, const QStringLi if(!external.isEmpty()) for (auto fileName : external) { QLOG_INFO() << "Reading" << fileName; - VersionFile file = parseJsonFile(QFileInfo(fileName), false, fileName.endsWith("pack.json")); - file.name = QFileInfo(fileName).fileName(); - file.fileId = "org.multimc.external." + file.name; - file.version = QString(); - file.mcVersion = QString(); - file.applyTo(m_version); + auto file = parseJsonFile(QFileInfo(fileName), false, fileName.endsWith("pack.json")); + file->name = QFileInfo(fileName).fileName(); + file->fileId = "org.multimc.external." + file->name; + file->version = QString(); + file->mcVersion = QString(); + file->applyTo(m_version); } // else, if there's custom json, we just do that. else if (QFile::exists(root.absoluteFilePath("custom.json"))) { QLOG_INFO() << "Reading custom.json"; - VersionFile file = parseJsonFile(QFileInfo(root.absoluteFilePath("custom.json")), false); - file.name = "custom.json"; - file.filename = "custom.json"; - file.fileId = "org.multimc.custom.json"; - file.version = QString(); - file.applyTo(m_version); + auto file = parseJsonFile(QFileInfo(root.absoluteFilePath("custom.json")), false); + file->name = "custom.json"; + file->filename = "custom.json"; + file->fileId = "org.multimc.custom.json"; + file->version = QString(); + file->applyTo(m_version); // 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.") } @@ -90,12 +90,12 @@ void OneSixVersionBuilder::buildInternal(const bool onlyVanilla, const QStringLi { // version.json QLOG_INFO() << "Reading version.json"; - VersionFile file = parseJsonFile(QFileInfo(root.absoluteFilePath("version.json")), false); - file.name = "Minecraft"; - file.fileId = "org.multimc.version.json"; - file.version = m_instance->intendedVersionId(); - file.mcVersion = m_instance->intendedVersionId(); - file.applyTo(m_version); + auto file = parseJsonFile(QFileInfo(root.absoluteFilePath("version.json")), false); + file->name = "Minecraft"; + file->fileId = "org.multimc.version.json"; + file->version = m_instance->intendedVersionId(); + file->mcVersion = m_instance->intendedVersionId(); + file->applyTo(m_version); // QObject::tr("Error while applying %1. Please check MultiMC-0.log for more info.").arg(root.absoluteFilePath("version.json"))); if (onlyVanilla) @@ -105,26 +105,26 @@ void OneSixVersionBuilder::buildInternal(const bool onlyVanilla, const QStringLi // load all, put into map for ordering, apply in the right order QMap overrideOrder = readOverrideOrders(m_instance); - QMap> files; + QMap> files; for (auto info : patches.entryInfoList(QStringList() << "*.json", QDir::Files)) { QLOG_INFO() << "Reading" << info.fileName(); - VersionFile file = parseJsonFile(info, true); - if (overrideOrder.contains(file.fileId)) + auto file = parseJsonFile(info, true); + if (overrideOrder.contains(file->fileId)) { - file.order = overrideOrder.value(file.fileId); + file->order = overrideOrder.value(file->fileId); } - if (files.contains(file.order)) + if (files.contains(file->order)) { - throw VersionBuildError(QObject::tr("%1 has the same order as %2").arg(file.fileId, files[file.order].second.fileId)); + 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)); + files.insert(file->order, qMakePair(info.fileName(), file)); } for (auto order : files.keys()) { QLOG_DEBUG() << "Applying file with order" << order; auto & filePair = files[order]; - filePair.second.applyTo(m_version); + filePair.second->applyTo(m_version); } } while(0); @@ -163,15 +163,15 @@ void OneSixVersionBuilder::readJsonAndApply(const QJsonObject &obj) { m_version->clear(); - VersionFile file = VersionFile::fromJson(QJsonDocument(obj), QString(), false); + auto file = VersionFile::fromJson(QJsonDocument(obj), QString(), false); // QObject::tr("Error while reading. Please check MultiMC-0.log for more info.")); - file.applyTo(m_version); + file->applyTo(m_version); // 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")); } -VersionFile OneSixVersionBuilder::parseJsonFile(const QFileInfo &fileInfo, const bool requireOrder, bool isFTB) +VersionFilePtr OneSixVersionBuilder::parseJsonFile(const QFileInfo &fileInfo, const bool requireOrder, bool isFTB) { QFile file(fileInfo.absoluteFilePath()); if (!file.open(QFile::ReadOnly)) @@ -193,39 +193,50 @@ VersionFile OneSixVersionBuilder::parseJsonFile(const QFileInfo &fileInfo, const QMap OneSixVersionBuilder::readOverrideOrders(OneSixInstance *instance) { QMap out; - if (QDir(instance->instanceRoot()).exists("order.json")) + + // make sure the order file exists + if (!QDir(instance->instanceRoot()).exists("order.json")) + return out; + + // and it can be opened + QFile orderFile(instance->instanceRoot() + "/order.json"); + if (!orderFile.open(QFile::ReadOnly)) { - QFile orderFile(instance->instanceRoot() + "/order.json"); - if (!orderFile.open(QFile::ReadOnly)) - { - QLOG_ERROR() << "Couldn't open" << orderFile.fileName() - << " for reading:" << orderFile.errorString(); - QLOG_WARN() << "Ignoring overriden order"; - } - else + QLOG_ERROR() << "Couldn't open" << orderFile.fileName() + << " for reading:" << orderFile.errorString(); + QLOG_WARN() << "Ignoring overriden order"; + return out; + } + + // and it's valid JSON + QJsonParseError error; + QJsonDocument doc = QJsonDocument::fromJson(orderFile.readAll(), &error); + if (error.error != QJsonParseError::NoError ) + { + QLOG_ERROR() << "Couldn't parse" << orderFile.fileName() << ":" << error.errorString(); + QLOG_WARN() << "Ignoring overriden order"; + return out; + } + + // and then read it and process it if all above is true. + try + { + auto obj = MMCJson::ensureObject(doc); + for (auto it = obj.begin(); it != obj.end(); ++it) { - QJsonParseError error; - QJsonDocument doc = QJsonDocument::fromJson(orderFile.readAll(), &error); - if (error.error != QJsonParseError::NoError || !doc.isObject()) + if (it.key().startsWith("org.multimc.")) { - QLOG_ERROR() << "Couldn't parse" << orderFile.fileName() << ":" - << error.errorString(); - QLOG_WARN() << "Ignoring overriden order"; - } - else - { - QJsonObject obj = doc.object(); - for (auto it = obj.begin(); it != obj.end(); ++it) - { - if (it.key().startsWith("org.multimc.")) - { - continue; - } - out.insert(it.key(), it.value().toDouble()); - } + continue; } + out.insert(it.key(), MMCJson::ensureInteger(it.value())); } } + catch (JSONValidationError err) + { + QLOG_ERROR() << "Couldn't parse" << orderFile.fileName() << ": bad file format"; + QLOG_WARN() << "Ignoring overriden order"; + return out; + } return out; } diff --git a/logic/OneSixVersionBuilder.h b/logic/OneSixVersionBuilder.h index c48e8ec5..8be3d9d3 100644 --- a/logic/OneSixVersionBuilder.h +++ b/logic/OneSixVersionBuilder.h @@ -43,5 +43,6 @@ private: void readJsonAndApply(const QJsonObject &obj); void finalizeVersion(); - VersionFile parseJsonFile(const QFileInfo &fileInfo, const bool requireOrder, bool isFTB = false); + VersionFilePtr parseJsonFile(const QFileInfo &fileInfo, const bool requireOrder, + bool isFTB = false); }; diff --git a/logic/VersionFile.cpp b/logic/VersionFile.cpp index b7695907..40dcb0c3 100644 --- a/logic/VersionFile.cpp +++ b/logic/VersionFile.cpp @@ -13,16 +13,15 @@ using namespace MMCJson; #define CURRENT_MINIMUM_LAUNCHER_VERSION 14 -RawLibrary RawLibrary::fromJson(const QJsonObject &libObj, - const QString &filename) +RawLibraryPtr RawLibrary::fromJson(const QJsonObject &libObj, const QString &filename) { - RawLibrary out; + RawLibraryPtr out(new RawLibrary()); if (!libObj.contains("name")) { throw JSONValidationError(filename + "contains a library that doesn't have a 'name' field"); } - out.name = libObj.value("name").toString(); + out->name = libObj.value("name").toString(); auto readString = [libObj, filename](const QString & key, QString & variable) { @@ -40,22 +39,22 @@ RawLibrary RawLibrary::fromJson(const QJsonObject &libObj, } }; - readString("url", out.url); - readString("MMC-hint", out.hint); - readString("MMC-absulute_url", out.absoluteUrl); - readString("MMC-absoluteUrl", out.absoluteUrl); + readString("url", out->url); + readString("MMC-hint", out->hint); + readString("MMC-absulute_url", out->absoluteUrl); + readString("MMC-absoluteUrl", out->absoluteUrl); if (libObj.contains("extract")) { - out.applyExcludes = true; + out->applyExcludes = true; auto extractObj = ensureObject(libObj.value("extract")); for (auto excludeVal : ensureArray(extractObj.value("exclude"))) { - out.excludes.append(ensureString(excludeVal)); + out->excludes.append(ensureString(excludeVal)); } } if (libObj.contains("natives")) { - out.applyNatives = true; + out->applyNatives = true; QJsonObject nativesObj = ensureObject(libObj.value("natives")); for (auto it = nativesObj.begin(); it != nativesObj.end(); ++it) { @@ -66,22 +65,22 @@ RawLibrary RawLibrary::fromJson(const QJsonObject &libObj, OpSys opSys = OpSys_fromString(it.key()); if (opSys != Os_Other) { - out.natives.append(qMakePair(opSys, it.value().toString())); + out->natives.append(qMakePair(opSys, it.value().toString())); } } } if (libObj.contains("rules")) { - out.applyRules = true; - out.rules = rulesFromJsonV4(libObj); + out->applyRules = true; + out->rules = rulesFromJsonV4(libObj); } return out; } -VersionFile VersionFile::fromJson(const QJsonDocument &doc, const QString &filename, +VersionFilePtr VersionFile::fromJson(const QJsonDocument &doc, const QString &filename, const bool requireOrder, const bool isFTB) { - VersionFile out; + VersionFilePtr out(new VersionFile()); if (doc.isEmpty() || doc.isNull()) { throw JSONValidationError(filename + " is empty or null"); @@ -97,7 +96,7 @@ VersionFile VersionFile::fromJson(const QJsonDocument &doc, const QString &filen { if (root.contains("order")) { - out.order = ensureInteger(root.value("order")); + out->order = ensureInteger(root.value("order")); } else { @@ -106,11 +105,11 @@ VersionFile VersionFile::fromJson(const QJsonDocument &doc, const QString &filen } } - out.name = root.value("name").toString(); - out.fileId = root.value("fileId").toString(); - out.version = root.value("version").toString(); - out.mcVersion = root.value("mcVersion").toString(); - out.filename = filename; + out->name = root.value("name").toString(); + out->fileId = root.value("fileId").toString(); + out->version = root.value("version").toString(); + out->mcVersion = root.value("mcVersion").toString(); + out->filename = filename; auto readString = [root, filename](const QString & key, QString & variable) { @@ -123,30 +122,30 @@ VersionFile VersionFile::fromJson(const QJsonDocument &doc, const QString &filen // FIXME: This should be ignored when applying. if (!isFTB) { - readString("id", out.id); + 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); + 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")) { - out.minimumLauncherVersion = ensureInteger(root.value("minimumLauncherVersion")); + out->minimumLauncherVersion = ensureInteger(root.value("minimumLauncherVersion")); } if (root.contains("tweakers")) { - out.shouldOverwriteTweakers = true; + out->shouldOverwriteTweakers = true; for (auto tweakerVal : ensureArray(root.value("tweakers"))) { - out.overwriteTweakers.append(ensureString(tweakerVal)); + out->overwriteTweakers.append(ensureString(tweakerVal)); } } @@ -154,7 +153,7 @@ VersionFile VersionFile::fromJson(const QJsonDocument &doc, const QString &filen { for (auto tweakerVal : ensureArray(root.value("+tweakers"))) { - out.addTweakers.append(ensureString(tweakerVal)); + out->addTweakers.append(ensureString(tweakerVal)); } } @@ -162,29 +161,29 @@ VersionFile VersionFile::fromJson(const QJsonDocument &doc, const QString &filen { for (auto tweakerVal : ensureArray(root.value("-tweakers"))) { - out.removeTweakers.append(ensureString(tweakerVal)); + out->removeTweakers.append(ensureString(tweakerVal)); } } if (root.contains("libraries")) { // FIXME: This should be done when applying. - out.shouldOverwriteLibs = !isFTB; + out->shouldOverwriteLibs = !isFTB; for (auto libVal : ensureArray(root.value("libraries"))) { auto libObj = ensureObject(libVal); - RawLibrary lib = RawLibrary::fromJson(libObj, filename); + auto lib = RawLibrary::fromJson(libObj, filename); // FIXME: This should be done when applying. if (isFTB) { - lib.hint = "local"; - lib.insertType = RawLibrary::Prepend; - out.addLibs.prepend(lib); + lib->hint = "local"; + lib->insertType = RawLibrary::Prepend; + out->addLibs.prepend(lib); } else { - out.overwriteLibs.append(lib); + out->overwriteLibs.append(lib); } } } @@ -197,7 +196,7 @@ VersionFile VersionFile::fromJson(const QJsonDocument &doc, const QString &filen QJsonValue insertVal = ensureExists(libObj.value("insert")); // parse the library - RawLibrary lib = RawLibrary::fromJson(libObj, filename); + auto lib = RawLibrary::fromJson(libObj, filename); // TODO: utility functions for handling this case. templates? QString insertString; @@ -215,24 +214,24 @@ VersionFile VersionFile::fromJson(const QJsonDocument &doc, const QString &filen filename); } insertString = insertObj.keys().first(); - lib.insertData = insertObj.value(insertString).toString(); + lib->insertData = insertObj.value(insertString).toString(); } } if (insertString == "apply") { - lib.insertType = RawLibrary::Apply; + lib->insertType = RawLibrary::Apply; } else if (insertString == "prepend") { - lib.insertType = RawLibrary::Prepend; + lib->insertType = RawLibrary::Prepend; } else if (insertString == "append") { - lib.insertType = RawLibrary::Prepend; + lib->insertType = RawLibrary::Prepend; } else if (insertString == "replace") { - lib.insertType = RawLibrary::Replace; + lib->insertType = RawLibrary::Replace; } else { @@ -244,11 +243,11 @@ VersionFile VersionFile::fromJson(const QJsonDocument &doc, const QString &filen const QString dependString = ensureString(libObj.value("MMC-depend")); if (dependString == "hard") { - lib.dependType = RawLibrary::Hard; + lib->dependType = RawLibrary::Hard; } else if (dependString == "soft") { - lib.dependType = RawLibrary::Soft; + lib->dependType = RawLibrary::Soft; } else { @@ -256,7 +255,7 @@ VersionFile VersionFile::fromJson(const QJsonDocument &doc, const QString &filen " contains an invalid depend type"); } } - out.addLibs.append(lib); + out->addLibs.append(lib); } } if (root.contains("-libraries")) @@ -264,37 +263,36 @@ VersionFile VersionFile::fromJson(const QJsonDocument &doc, const QString &filen for (auto libVal : ensureArray(root.value("-libraries"))) { auto libObj = ensureObject(libVal); - out.removeLibs.append(ensureString(libObj.value("name"))); + out->removeLibs.append(ensureString(libObj.value("name"))); } } return out; } -std::shared_ptr VersionFile::createLibrary(const RawLibrary &lib) +OneSixLibraryPtr VersionFile::createLibrary(RawLibraryPtr lib) { - std::shared_ptr out(new OneSixLibrary(lib.name)); - if (!lib.url.isEmpty()) + std::shared_ptr out(new OneSixLibrary(lib->name)); + if (!lib->url.isEmpty()) { - out->setBaseUrl(lib.url); + out->setBaseUrl(lib->url); } - out->setHint(lib.hint); - if (!lib.absoluteUrl.isEmpty()) + out->setHint(lib->hint); + if (!lib->absoluteUrl.isEmpty()) { - out->setAbsoluteUrl(lib.absoluteUrl); + out->setAbsoluteUrl(lib->absoluteUrl); } - out->setAbsoluteUrl(lib.absoluteUrl); - out->extract_excludes = lib.excludes; - for (auto native : lib.natives) + out->setAbsoluteUrl(lib->absoluteUrl); + out->extract_excludes = lib->excludes; + for (auto native : lib->natives) { out->addNative(native.first, native.second); } - out->setRules(lib.rules); + out->setRules(lib->rules); out->finalize(); return out; } -int VersionFile::findLibrary(QList> haystack, - const QString &needle) +int VersionFile::findLibrary(QList haystack, const QString &needle) { for (int i = 0; i < haystack.size(); ++i) { @@ -395,48 +393,48 @@ void VersionFile::applyTo(VersionFinal *version) } for (auto lib : addLibs) { - switch (lib.insertType) + switch (lib->insertType) { case RawLibrary::Apply: { - int index = findLibrary(version->libraries, lib.name); + int index = findLibrary(version->libraries, lib->name); if (index >= 0) { auto library = version->libraries[index]; - if (!lib.url.isNull()) + if (!lib->url.isNull()) { - library->setBaseUrl(lib.url); + library->setBaseUrl(lib->url); } - if (!lib.hint.isNull()) + if (!lib->hint.isNull()) { - library->setHint(lib.hint); + library->setHint(lib->hint); } - if (!lib.absoluteUrl.isNull()) + if (!lib->absoluteUrl.isNull()) { - library->setAbsoluteUrl(lib.absoluteUrl); + library->setAbsoluteUrl(lib->absoluteUrl); } - if (lib.applyExcludes) + if (lib->applyExcludes) { - library->extract_excludes = lib.excludes; + library->extract_excludes = lib->excludes; } - if (lib.applyNatives) + if (lib->applyNatives) { library->clearSuffixes(); - for (auto native : lib.natives) + for (auto native : lib->natives) { library->addNative(native.first, native.second); } } - if (lib.applyRules) + if (lib->applyRules) { - library->setRules(lib.rules); + library->setRules(lib->rules); } library->finalize(); } else { - QLOG_WARN() << "Couldn't find" << lib.name << "(skipping)"; + QLOG_WARN() << "Couldn't find" << lib->name << "(skipping)"; } break; } @@ -444,12 +442,12 @@ void VersionFile::applyTo(VersionFinal *version) case RawLibrary::Prepend: { - const int startOfVersion = lib.name.lastIndexOf(':') + 1; + const int startOfVersion = lib->name.lastIndexOf(':') + 1; const int index = findLibrary( - version->libraries, QString(lib.name).replace(startOfVersion, INT_MAX, '*')); + version->libraries, QString(lib->name).replace(startOfVersion, INT_MAX, '*')); if (index < 0) { - if (lib.insertType == RawLibrary::Append) + if (lib->insertType == RawLibrary::Append) { version->libraries.append(createLibrary(lib)); } @@ -461,7 +459,7 @@ void VersionFile::applyTo(VersionFinal *version) else { auto otherLib = version->libraries.at(index); - const Util::Version ourVersion = lib.name.mid(startOfVersion, INT_MAX); + const Util::Version ourVersion = lib->name.mid(startOfVersion, INT_MAX); const Util::Version otherVersion = otherLib->version(); // if the existing version is a hard dependency we can either use it or // fail, but we can't change it @@ -470,12 +468,12 @@ void VersionFile::applyTo(VersionFinal *version) // we need a higher version, or we're hard to and the versions aren't // equal if (ourVersion > otherVersion || - (lib.dependType == RawLibrary::Hard && ourVersion != otherVersion)) + (lib->dependType == RawLibrary::Hard && ourVersion != otherVersion)) { throw VersionBuildError( QString( "Error resolving library dependencies between %1 and %2 in %3.") - .arg(otherLib->rawName(), lib.name, filename)); + .arg(otherLib->rawName(), lib->name, filename)); } else { @@ -498,11 +496,11 @@ void VersionFile::applyTo(VersionFinal *version) { // our version is smaller than the existing version, but we require // it: fail - if (lib.dependType == RawLibrary::Hard) + if (lib->dependType == RawLibrary::Hard) { throw VersionBuildError(QString( "Error resolving library dependencies between %1 and %2 in %3.") - .arg(otherLib->rawName(), lib.name, + .arg(otherLib->rawName(), lib->name, filename)); } } @@ -512,14 +510,14 @@ void VersionFile::applyTo(VersionFinal *version) } case RawLibrary::Replace: { - int index = findLibrary(version->libraries, lib.insertData); + 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)"; + QLOG_WARN() << "Couldn't find" << lib->insertData << "(skipping)"; } break; } @@ -537,13 +535,4 @@ void VersionFile::applyTo(VersionFinal *version) QLOG_WARN() << "Couldn't find" << lib << "(skipping)"; } } - - VersionFinal::VersionFile versionFile; - versionFile.name = name; - versionFile.id = fileId; - versionFile.version = this->version; - versionFile.mcVersion = mcVersion; - versionFile.filename = filename; - versionFile.order = order; - version->versionFiles.append(versionFile); } diff --git a/logic/VersionFile.h b/logic/VersionFile.h index 0475f927..504fcbff 100644 --- a/logic/VersionFile.h +++ b/logic/VersionFile.h @@ -20,6 +20,8 @@ public: virtual ~VersionBuildError() {}; }; +struct RawLibrary; +typedef std::shared_ptr RawLibraryPtr; struct RawLibrary { QString name; @@ -50,17 +52,19 @@ struct RawLibrary }; DependType dependType = Soft; - static RawLibrary fromJson(const QJsonObject &libObj, const QString &filename); + static RawLibraryPtr fromJson(const QJsonObject &libObj, const QString &filename); }; +struct VersionFile; +typedef std::shared_ptr VersionFilePtr; struct VersionFile { public: /* methods */ - static VersionFile fromJson(const QJsonDocument &doc, const QString &filename, + static VersionFilePtr fromJson(const QJsonDocument &doc, const QString &filename, const bool requireOrder, const bool isFTB = false); - static std::shared_ptr createLibrary(const RawLibrary &lib); - int findLibrary(QList> haystack, const QString &needle); + static OneSixLibraryPtr createLibrary(RawLibraryPtr lib); + int findLibrary(QList haystack, const QString &needle); void applyTo(VersionFinal *version); public: /* data */ @@ -91,7 +95,7 @@ public: /* data */ QStringList removeTweakers; bool shouldOverwriteLibs = false; - QList overwriteLibs; - QList addLibs; + QList overwriteLibs; + QList addLibs; QList removeLibs; }; \ No newline at end of file diff --git a/logic/VersionFinal.cpp b/logic/VersionFinal.cpp index ec450eda..8d668014 100644 --- a/logic/VersionFinal.cpp +++ b/logic/VersionFinal.cpp @@ -52,26 +52,6 @@ void VersionFinal::clear() endResetModel(); } -void VersionFinal::dump() const -{ - qDebug().nospace() << "VersionFinal(" - << "\n\tid=" << id - << "\n\ttime=" << time - << "\n\treleaseTime=" << releaseTime - << "\n\ttype=" << type - << "\n\tassets=" << assets - << "\n\tprocessArguments=" << processArguments - << "\n\tminecraftArguments=" << minecraftArguments - << "\n\tminimumLauncherVersion=" << minimumLauncherVersion - << "\n\tmainClass=" << mainClass - << "\n\tlibraries="; - for (auto lib : libraries) - { - qDebug().nospace() << "\n\t\t" << lib.get(); - } - qDebug().nospace() << "\n)"; -} - bool VersionFinal::canRemove(const int index) const { if (index < versionFiles.size()) @@ -201,25 +181,3 @@ int VersionFinal::columnCount(const QModelIndex &parent) const { return 2; } - -QDebug operator<<(QDebug &dbg, const VersionFinal *version) -{ - version->dump(); - return dbg.maybeSpace(); -} -QDebug operator<<(QDebug &dbg, const OneSixLibrary *library) -{ - dbg.nospace() << "OneSixLibrary(" - << "\n\t\t\trawName=" << library->rawName() - << "\n\t\t\tname=" << library->name() - << "\n\t\t\tversion=" << library->version() - << "\n\t\t\ttype=" << library->type() - << "\n\t\t\tisActive=" << library->isActive() - << "\n\t\t\tisNative=" << library->isNative() - << "\n\t\t\tdownloadUrl=" << library->downloadUrl() - << "\n\t\t\tstoragePath=" << library->storagePath() - << "\n\t\t\tabsolutePath=" << library->absoluteUrl() - << "\n\t\t\thint=" << library->hint(); - dbg.nospace() << "\n\t\t)"; - return dbg.maybeSpace(); -} diff --git a/logic/VersionFinal.h b/logic/VersionFinal.h index e5a38423..b19cd6f9 100644 --- a/logic/VersionFinal.h +++ b/logic/VersionFinal.h @@ -22,6 +22,7 @@ #include #include "OneSixLibrary.h" +#include "VersionFile.h" class OneSixInstance; @@ -118,15 +119,6 @@ public: */ // QList rules; - struct VersionFile - { - QString name; - QString id; - QString version; - QString mcVersion; - QString filename; - int order; - }; QList versionFiles; private: -- cgit v1.2.3 From 0cc682c629a4e471495114584bb85be9c73b40ee Mon Sep 17 00:00:00 2001 From: Jan Dalheimer Date: Fri, 7 Mar 2014 16:15:38 +0100 Subject: Fix a few paste upload bugs Fixes https://www.pivotaltracker.com/story/show/66994990 --- logic/net/PasteUpload.cpp | 11 +++++------ logic/net/PasteUpload.h | 2 +- 2 files changed, 6 insertions(+), 7 deletions(-) (limited to 'logic') diff --git a/logic/net/PasteUpload.cpp b/logic/net/PasteUpload.cpp index fa54d084..402eb400 100644 --- a/logic/net/PasteUpload.cpp +++ b/logic/net/PasteUpload.cpp @@ -25,7 +25,7 @@ void PasteUpload::executeTask() m_reply = std::shared_ptr(rep); connect(rep, &QNetworkReply::downloadProgress, [&](qint64 value, qint64 max) - { setProgress(value / max * 100); }); + { setProgress(value / qMax((qint64)1, max) * 100); }); connect(rep, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(downloadError(QNetworkReply::NetworkError))); connect(rep, SIGNAL(finished()), this, SLOT(downloadFinished())); @@ -52,10 +52,9 @@ void PasteUpload::downloadFinished() emitFailed(jsonError.errorString()); return; } - QString error; - if (!parseResult(doc, &error)) + if (!parseResult(doc)) { - emitFailed(error); + emitFailed(tr("paste.ee returned an error. Please consult the logs for more information")); return; } } @@ -69,13 +68,13 @@ void PasteUpload::downloadFinished() emitSucceeded(); } -bool PasteUpload::parseResult(QJsonDocument doc, QString *parseError) +bool PasteUpload::parseResult(QJsonDocument doc) { auto object = doc.object(); auto status = object.value("status").toString("error"); if (status == "error") { - parseError = new QString(object.value("error").toString()); + QLOG_ERROR() << "paste.ee reported error:" << QString(object.value("error").toString()); return false; } // FIXME: not the place for GUI things. diff --git a/logic/net/PasteUpload.h b/logic/net/PasteUpload.h index 917a0016..83876c17 100644 --- a/logic/net/PasteUpload.h +++ b/logic/net/PasteUpload.h @@ -14,7 +14,7 @@ protected: virtual void executeTask(); private: - bool parseResult(QJsonDocument doc, QString *parseError); + bool parseResult(QJsonDocument doc); QString m_text; QString m_error; QWidget *m_window; -- cgit v1.2.3 From 91faaa5b591d7d4203591994718c2ed21d5b4d6e Mon Sep 17 00:00:00 2001 From: robotbrain Date: Fri, 7 Mar 2014 19:44:15 -0500 Subject: Fix logging when system language is not en_US. --- logic/MinecraftProcess.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'logic') diff --git a/logic/MinecraftProcess.cpp b/logic/MinecraftProcess.cpp index 89cd71ed..e26459ab 100644 --- a/logic/MinecraftProcess.cpp +++ b/logic/MinecraftProcess.cpp @@ -350,6 +350,7 @@ void MinecraftProcess::arm() args << QString("-Xms%1m").arg(settings.get("MinMemAlloc").toInt()); args << QString("-Xmx%1m").arg(settings.get("MaxMemAlloc").toInt()); args << QString("-XX:PermSize=%1m").arg(settings.get("PermGen").toInt()); + args << "-Duser.language=en"; if(!m_nativeFolder.isEmpty()) args << QString("-Djava.library.path=%1").arg(m_nativeFolder); args << "-jar" << PathCombine(MMC->bin(), "jars", "NewLaunch.jar"); -- cgit v1.2.3 From 44f21406e91c68b230d38441b950eb7c3d6a8ec5 Mon Sep 17 00:00:00 2001 From: Jan Dalheimer Date: Sun, 9 Mar 2014 08:18:50 +0100 Subject: Some pre/post related stuff Reload the onesix version config after the commands (addresses https://www.pivotaltracker.com/story/show/60360652) Add a few more variables and also substitute them in the command (fixes https://www.pivotaltracker.com/story/show/66994828) --- logic/BaseInstance.cpp | 6 ++ logic/BaseInstance.h | 2 + logic/MinecraftProcess.cpp | 198 ++++++++++++++++++++++++++++----------------- logic/MinecraftProcess.h | 7 ++ logic/OneSixInstance.cpp | 5 ++ logic/OneSixInstance.h | 2 + 6 files changed, 148 insertions(+), 72 deletions(-) (limited to 'logic') diff --git a/logic/BaseInstance.cpp b/logic/BaseInstance.cpp index d78f1ea0..aea91ef2 100644 --- a/logic/BaseInstance.cpp +++ b/logic/BaseInstance.cpp @@ -169,6 +169,12 @@ bool BaseInstance::canLaunch() const return !(flags() & VersionBrokenFlag); } +bool BaseInstance::reload() +{ + // TODO reload the instance settings + return true; +} + QString BaseInstance::baseJar() const { I_D(BaseInstance); diff --git a/logic/BaseInstance.h b/logic/BaseInstance.h index 27f939bc..195fd339 100644 --- a/logic/BaseInstance.h +++ b/logic/BaseInstance.h @@ -190,6 +190,8 @@ public: bool canLaunch() const; + virtual bool reload(); + signals: /*! * \brief Signal emitted when properties relevant to the instance view change diff --git a/logic/MinecraftProcess.cpp b/logic/MinecraftProcess.cpp index 89cd71ed..1001cee5 100644 --- a/logic/MinecraftProcess.cpp +++ b/logic/MinecraftProcess.cpp @@ -49,9 +49,11 @@ MinecraftProcess::MinecraftProcess(BaseInstance *inst) : m_instance(inst) #endif // export some infos - env.insert("INST_NAME", inst->name()); - env.insert("INST_ID", inst->id()); - env.insert("INST_DIR", QDir(inst->instanceRoot()).absolutePath()); + auto variables = getVariables(); + for (auto it = variables.begin(); it != variables.end(); ++it) + { + env.insert(it.key(), it.value()); + } this->setProcessEnvironment(env); m_prepostlaunchprocess.setProcessEnvironment(env); @@ -63,10 +65,10 @@ MinecraftProcess::MinecraftProcess(BaseInstance *inst) : m_instance(inst) // Log prepost launch command output (can be disabled.) if (m_instance->settings().get("LogPrePostOutput").toBool()) { - connect(&m_prepostlaunchprocess, &QProcess::readyReadStandardError, - this, &MinecraftProcess::on_prepost_stdErr); - connect(&m_prepostlaunchprocess, &QProcess::readyReadStandardOutput, - this, &MinecraftProcess::on_prepost_stdOut); + connect(&m_prepostlaunchprocess, &QProcess::readyReadStandardError, this, + &MinecraftProcess::on_prepost_stdErr); + connect(&m_prepostlaunchprocess, &QProcess::readyReadStandardOutput, this, + &MinecraftProcess::on_prepost_stdOut); } } @@ -79,10 +81,10 @@ void MinecraftProcess::setWorkdir(QString path) QString MinecraftProcess::censorPrivateInfo(QString in) { - if(!m_session) + if (!m_session) return in; - if(m_session->session != "-") + if (m_session->session != "-") in.replace(m_session->session, ""); in.replace(m_session->access_token, ""); in.replace(m_session->client_token, ""); @@ -113,7 +115,7 @@ MessageLevel::Enum MinecraftProcess::guessLevel(const QString &line, MessageLeve level = MessageLevel::Fatal; if (line.contains("[DEBUG]")) level = MessageLevel::Debug; - if(line.contains("overwriting existing")) + if (line.contains("overwriting existing")) level = MessageLevel::Fatal; return level; } @@ -139,17 +141,15 @@ MessageLevel::Enum MinecraftProcess::getLevel(const QString &levelName) return MessageLevel::Message; } -void MinecraftProcess::logOutput(const QStringList &lines, - MessageLevel::Enum defaultLevel, +void MinecraftProcess::logOutput(const QStringList &lines, MessageLevel::Enum defaultLevel, bool guessLevel, bool censor) { for (int i = 0; i < lines.size(); ++i) logOutput(lines[i], defaultLevel, guessLevel, censor); } -void MinecraftProcess::logOutput(QString line, - MessageLevel::Enum defaultLevel, - bool guessLevel, bool censor) +void MinecraftProcess::logOutput(QString line, MessageLevel::Enum defaultLevel, bool guessLevel, + bool censor) { MessageLevel::Enum level = defaultLevel; @@ -251,33 +251,7 @@ void MinecraftProcess::finish(int code, ExitStatus status) m_prepostlaunchprocess.processEnvironment().insert("INST_EXITCODE", QString(code)); // run post-exit - QString postlaunch_cmd = m_instance->settings().get("PostExitCommand").toString(); - if (!postlaunch_cmd.isEmpty()) - { - emit log(tr("Running Post-Launch command: %1").arg(postlaunch_cmd)); - m_prepostlaunchprocess.start(postlaunch_cmd); - m_prepostlaunchprocess.waitForFinished(); - // Flush console window - if (!m_err_leftover.isEmpty()) - { - logOutput(m_err_leftover, MessageLevel::PrePost); - m_err_leftover.clear(); - } - if (!m_out_leftover.isEmpty()) - { - logOutput(m_out_leftover, MessageLevel::PrePost); - m_out_leftover.clear(); - } - if (m_prepostlaunchprocess.exitStatus() != NormalExit) - { - emit log(tr("Post-Launch command failed with code %1.\n\n").arg(m_prepostlaunchprocess.exitCode()), - MessageLevel::Error); - emit postlaunch_failed(m_instance, m_prepostlaunchprocess.exitCode(), - m_prepostlaunchprocess.exitStatus()); - } - else - emit log(tr("Post-Launch command ran successfully.\n\n")); - } + postLaunch(); m_instance->cleanupAfterRun(); emit ended(m_instance, code, status); } @@ -288,14 +262,12 @@ void MinecraftProcess::killMinecraft() kill(); } -void MinecraftProcess::arm() +bool MinecraftProcess::preLaunch() { - emit log("MultiMC version: " + MMC->version().toString() + "\n\n"); - emit log("Minecraft folder is:\n" + workingDirectory() + "\n\n"); - QString prelaunch_cmd = m_instance->settings().get("PreLaunchCommand").toString(); if (!prelaunch_cmd.isEmpty()) { + prelaunch_cmd = substituteVariables(prelaunch_cmd); // Launch emit log(tr("Running Pre-Launch command: %1").arg(prelaunch_cmd)); m_prepostlaunchprocess.start(prelaunch_cmd); @@ -315,46 +287,128 @@ void MinecraftProcess::arm() // Process return values if (m_prepostlaunchprocess.exitStatus() != NormalExit) { - emit log(tr("Pre-Launch command failed with code %1.\n\n").arg(m_prepostlaunchprocess.exitCode()), + emit log(tr("Pre-Launch command failed with code %1.\n\n") + .arg(m_prepostlaunchprocess.exitCode()), MessageLevel::Fatal); m_instance->cleanupAfterRun(); emit prelaunch_failed(m_instance, m_prepostlaunchprocess.exitCode(), m_prepostlaunchprocess.exitStatus()); - return; + return false; } else emit log(tr("Pre-Launch command ran successfully.\n\n")); + + return m_instance->reload(); + } + return true; +} +bool MinecraftProcess::postLaunch() +{ + QString postlaunch_cmd = m_instance->settings().get("PostExitCommand").toString(); + if (!postlaunch_cmd.isEmpty()) + { + postlaunch_cmd = substituteVariables(postlaunch_cmd); + emit log(tr("Running Post-Launch command: %1").arg(postlaunch_cmd)); + m_prepostlaunchprocess.start(postlaunch_cmd); + m_prepostlaunchprocess.waitForFinished(); + // Flush console window + if (!m_err_leftover.isEmpty()) + { + logOutput(m_err_leftover, MessageLevel::PrePost); + m_err_leftover.clear(); + } + if (!m_out_leftover.isEmpty()) + { + logOutput(m_out_leftover, MessageLevel::PrePost); + m_out_leftover.clear(); + } + if (m_prepostlaunchprocess.exitStatus() != NormalExit) + { + emit log(tr("Post-Launch command failed with code %1.\n\n") + .arg(m_prepostlaunchprocess.exitCode()), + MessageLevel::Error); + emit postlaunch_failed(m_instance, m_prepostlaunchprocess.exitCode(), + m_prepostlaunchprocess.exitStatus()); + } + else + emit log(tr("Post-Launch command ran successfully.\n\n")); + + return m_instance->reload(); } + return true; +} - m_instance->setLastLaunch(); - auto &settings = m_instance->settings(); +QMap MinecraftProcess::getVariables() const +{ + QMap out; + out.insert("INST_NAME", m_instance->name()); + out.insert("INST_ID", m_instance->id()); + out.insert("INST_DIR", QDir(m_instance->instanceRoot()).absolutePath()); + out.insert("INST_MC_DIR", QDir(m_instance->minecraftRoot()).absolutePath()); + out.insert("INST_JAVA", m_instance->settings().get("JavaPath").toString()); + out.insert("INST_JAVA_ARGS", javaArguments().join(' ')); + return out; +} +QString MinecraftProcess::substituteVariables(const QString &cmd) const +{ + QString out = cmd; + auto variables = getVariables(); + for (auto it = variables.begin(); it != variables.end(); ++it) + { + out.replace("$" + it.key(), it.value()); + } + auto env = QProcessEnvironment::systemEnvironment(); + for (auto var : env.keys()) + { + out.replace("$" + var, env.value(var)); + } + return out; +} - //////////// java arguments //////////// +QStringList MinecraftProcess::javaArguments() const +{ QStringList args; + + // custom args go first. we want to override them if we have our own here. + args.append(m_instance->extraArguments()); + +// OSX dock icon and name +#ifdef OSX + args << "-Xdock:icon=icon.png"; + args << QString("-Xdock:name=\"%1\"").arg(m_instance->windowTitle()); +#endif + +// HACK: Stupid hack for Intel drivers. See: https://mojang.atlassian.net/browse/MCL-767 +#ifdef Q_OS_WIN32 + args << QString("-XX:HeapDumpPath=MojangTricksIntelDriversForPerformance_javaw.exe_" + "minecraft.exe.heapdump"); +#endif + + args << QString("-Xms%1m").arg(m_instance->settings().get("MinMemAlloc").toInt()); + args << QString("-Xmx%1m").arg(m_instance->settings().get("MaxMemAlloc").toInt()); + args << QString("-XX:PermSize=%1m").arg(m_instance->settings().get("PermGen").toInt()); + if (!m_nativeFolder.isEmpty()) + args << QString("-Djava.library.path=%1").arg(m_nativeFolder); + args << "-jar" << PathCombine(MMC->bin(), "jars", "NewLaunch.jar"); + + return args; +} + +void MinecraftProcess::arm() +{ + emit log("MultiMC version: " + MMC->version().toString() + "\n\n"); + emit log("Minecraft folder is:\n" + workingDirectory() + "\n\n"); + + if (!preLaunch()) { - // custom args go first. we want to override them if we have our own here. - args.append(m_instance->extraArguments()); - - // OSX dock icon and name - #ifdef OSX - args << "-Xdock:icon=icon.png"; - args << QString("-Xdock:name=\"%1\"").arg(m_instance->windowTitle()); - #endif - - // HACK: Stupid hack for Intel drivers. See: https://mojang.atlassian.net/browse/MCL-767 - #ifdef Q_OS_WIN32 - args << QString("-XX:HeapDumpPath=MojangTricksIntelDriversForPerformance_javaw.exe_" - "minecraft.exe.heapdump"); - #endif - - args << QString("-Xms%1m").arg(settings.get("MinMemAlloc").toInt()); - args << QString("-Xmx%1m").arg(settings.get("MaxMemAlloc").toInt()); - args << QString("-XX:PermSize=%1m").arg(settings.get("PermGen").toInt()); - if(!m_nativeFolder.isEmpty()) - args << QString("-Djava.library.path=%1").arg(m_nativeFolder); - args << "-jar" << PathCombine(MMC->bin(), "jars", "NewLaunch.jar"); + return; } + m_instance->setLastLaunch(); + auto &settings = m_instance->settings(); + + QStringList args = javaArguments(); + QString JavaPath = m_instance->settings().get("JavaPath").toString(); emit log("Java path is:\n" + JavaPath + "\n\n"); QString allArgs = args.join(", "); diff --git a/logic/MinecraftProcess.h b/logic/MinecraftProcess.h index 56340962..d91dad56 100644 --- a/logic/MinecraftProcess.h +++ b/logic/MinecraftProcess.h @@ -131,6 +131,13 @@ protected: QString launchScript; QString m_nativeFolder; + bool preLaunch(); + bool postLaunch(); + QMap getVariables() const; + QString substituteVariables(const QString &cmd) const; + + QStringList javaArguments() const; + protected slots: void finish(int, QProcess::ExitStatus status); diff --git a/logic/OneSixInstance.cpp b/logic/OneSixInstance.cpp index 10411c56..4f8fef5b 100644 --- a/logic/OneSixInstance.cpp +++ b/logic/OneSixInstance.cpp @@ -413,6 +413,11 @@ bool OneSixInstance::providesVersionFile() const return false; } +bool OneSixInstance::reload() +{ + return BaseInstance::reload() && reloadVersion(); +} + QString OneSixInstance::loaderModsDir() const { return PathCombine(minecraftRoot(), "mods"); diff --git a/logic/OneSixInstance.h b/logic/OneSixInstance.h index 06fd9de3..fafb34a0 100644 --- a/logic/OneSixInstance.h +++ b/logic/OneSixInstance.h @@ -75,6 +75,8 @@ public: virtual QStringList externalPatches() const; virtual bool providesVersionFile() const; + bool reload() override; + signals: void versionReloaded(); -- cgit v1.2.3 From f1dc4568020d222803d54fdcece324a14c9266c7 Mon Sep 17 00:00:00 2001 From: Jan Dalheimer Date: Sun, 9 Mar 2014 08:43:08 +0100 Subject: Also reload the instance cfg While this should work, there don't seem to be any places where the signals are listened for, so changes probably will only be available when calling Setting::get TODO: Fix that ^ --- logic/BaseInstance.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'logic') diff --git a/logic/BaseInstance.cpp b/logic/BaseInstance.cpp index aea91ef2..c565ab59 100644 --- a/logic/BaseInstance.cpp +++ b/logic/BaseInstance.cpp @@ -171,8 +171,7 @@ bool BaseInstance::canLaunch() const bool BaseInstance::reload() { - // TODO reload the instance settings - return true; + return settings().reload(); } QString BaseInstance::baseJar() const -- cgit v1.2.3 From ffff2cd3248a574d3d666731580ac7b8c33e1735 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Mr=C3=A1zek?= Date: Sun, 9 Mar 2014 17:38:42 +0100 Subject: Remove version patch reordering. Remove the main class display from onesix edit mods. --- logic/OneSixVersionBuilder.cpp | 10 +++++----- logic/VersionFinal.cpp | 10 +++++----- logic/VersionFinal.h | 5 +---- 3 files changed, 11 insertions(+), 14 deletions(-) (limited to 'logic') diff --git a/logic/OneSixVersionBuilder.cpp b/logic/OneSixVersionBuilder.cpp index a6bc5ec7..8abeb0d8 100644 --- a/logic/OneSixVersionBuilder.cpp +++ b/logic/OneSixVersionBuilder.cpp @@ -71,6 +71,7 @@ void OneSixVersionBuilder::buildInternal(const bool onlyVanilla, const QStringLi file->version = QString(); file->mcVersion = QString(); file->applyTo(m_version); + m_version->versionFiles.append(file); } // else, if there's custom json, we just do that. else if (QFile::exists(root.absoluteFilePath("custom.json"))) @@ -82,6 +83,7 @@ void OneSixVersionBuilder::buildInternal(const bool onlyVanilla, const QStringLi file->fileId = "org.multimc.custom.json"; file->version = QString(); file->applyTo(m_version); + 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.") } @@ -96,6 +98,7 @@ void OneSixVersionBuilder::buildInternal(const bool onlyVanilla, const QStringLi file->version = m_instance->intendedVersionId(); file->mcVersion = m_instance->intendedVersionId(); file->applyTo(m_version); + m_version->versionFiles.append(file); // QObject::tr("Error while applying %1. Please check MultiMC-0.log for more info.").arg(root.absoluteFilePath("version.json"))); if (onlyVanilla) @@ -103,17 +106,12 @@ void OneSixVersionBuilder::buildInternal(const bool onlyVanilla, const QStringLi // patches/ // load all, put into map for ordering, apply in the right order - QMap overrideOrder = readOverrideOrders(m_instance); QMap> files; for (auto info : patches.entryInfoList(QStringList() << "*.json", QDir::Files)) { QLOG_INFO() << "Reading" << info.fileName(); auto file = parseJsonFile(info, true); - if (overrideOrder.contains(file->fileId)) - { - file->order = overrideOrder.value(file->fileId); - } if (files.contains(file->order)) { throw VersionBuildError(QObject::tr("%1 has the same order as %2").arg(file->fileId, files[file->order].second->fileId)); @@ -125,6 +123,7 @@ void OneSixVersionBuilder::buildInternal(const bool onlyVanilla, const QStringLi QLOG_DEBUG() << "Applying file with order" << order; auto & filePair = files[order]; filePair.second->applyTo(m_version); + m_version->versionFiles.append(filePair.second); } } while(0); @@ -167,6 +166,7 @@ void OneSixVersionBuilder::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); // 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")); } diff --git a/logic/VersionFinal.cpp b/logic/VersionFinal.cpp index 8d668014..48601d57 100644 --- a/logic/VersionFinal.cpp +++ b/logic/VersionFinal.cpp @@ -56,7 +56,7 @@ bool VersionFinal::canRemove(const int index) const { if (index < versionFiles.size()) { - return versionFiles.at(index).id != "org.multimc.version.json"; + return versionFiles.at(index)->fileId != "org.multimc.version.json"; } return false; } @@ -67,14 +67,14 @@ QString VersionFinal::versionFileId(const int index) const { return QString(); } - return versionFiles.at(index).id; + return versionFiles.at(index)->fileId; } bool VersionFinal::remove(const int index) { if (canRemove(index)) { - return QFile::remove(versionFiles.at(index).filename); + return QFile::remove(versionFiles.at(index)->filename); } return false; } @@ -135,9 +135,9 @@ QVariant VersionFinal::data(const QModelIndex &index, int role) const switch (column) { case 0: - return versionFiles.at(row).name; + return versionFiles.at(row)->name; case 1: - return versionFiles.at(row).version; + return versionFiles.at(row)->version; default: return QVariant(); } diff --git a/logic/VersionFinal.h b/logic/VersionFinal.h index b19cd6f9..99fd5ff0 100644 --- a/logic/VersionFinal.h +++ b/logic/VersionFinal.h @@ -119,11 +119,8 @@ public: */ // QList rules; - QList versionFiles; + QList versionFiles; private: OneSixInstance *m_instance; }; - -QDebug operator<<(QDebug &dbg, const VersionFinal *version); -QDebug operator<<(QDebug &dbg, const OneSixLibrary *library); -- cgit v1.2.3 From b2c803a378695026f12aabc3729eb2139bee1b2c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Mr=C3=A1zek?= Date: Sun, 9 Mar 2014 23:42:25 +0100 Subject: Improve reporting of version file errors.x --- logic/MMCJson.h | 4 -- logic/OneSixFTBInstance.cpp | 9 ++- logic/OneSixInstance.cpp | 17 ++++-- logic/OneSixInstance.h | 8 ++- logic/OneSixUpdate.cpp | 40 +++++++------ logic/OneSixVersionBuilder.cpp | 129 ++++++++++++++++++++++------------------- logic/VersionFile.cpp | 11 ++-- logic/VersionFile.h | 36 ++++++++++-- logic/VersionFinal.cpp | 2 +- 9 files changed, 154 insertions(+), 102 deletions(-) (limited to 'logic') diff --git a/logic/MMCJson.h b/logic/MMCJson.h index b0d898fc..f2cc4b31 100644 --- a/logic/MMCJson.h +++ b/logic/MMCJson.h @@ -15,10 +15,6 @@ class JSONValidationError : public MMCError { public: JSONValidationError(QString cause) : MMCError(cause) {}; - virtual QString errorName() - { - return "JSONValidationError"; - }; virtual ~JSONValidationError() {}; }; diff --git a/logic/OneSixFTBInstance.cpp b/logic/OneSixFTBInstance.cpp index cdb3f53e..8f70ed08 100644 --- a/logic/OneSixFTBInstance.cpp +++ b/logic/OneSixFTBInstance.cpp @@ -17,7 +17,14 @@ OneSixFTBInstance::OneSixFTBInstance(const QString &rootDir, SettingsObject *set void OneSixFTBInstance::init() { - reloadVersion(); + try + { + reloadVersion(); + } + catch(MMCError & e) + { + // QLOG_ERROR() << "Caught exception on instance init: " << e.cause(); + } } void OneSixFTBInstance::copy(const QDir &newDir) diff --git a/logic/OneSixInstance.cpp b/logic/OneSixInstance.cpp index f6fe49f1..3c1f6545 100644 --- a/logic/OneSixInstance.cpp +++ b/logic/OneSixInstance.cpp @@ -41,9 +41,17 @@ OneSixInstance::OneSixInstance(const QString &rootDir, SettingsObject *settings, void OneSixInstance::init() { + // FIXME: why is this decided here? what does this even mean? if (QDir(instanceRoot()).exists("version.json")) { - reloadVersion(); + try + { + reloadVersion(); + } + catch(MMCError & e) + { + // QLOG_ERROR() << "Caught exception on instance init: " << e.cause(); + } } else { @@ -317,7 +325,7 @@ QString OneSixInstance::currentVersionId() const return intendedVersionId(); } -bool OneSixInstance::reloadVersion() +void OneSixInstance::reloadVersion() { I_D(OneSixInstance); @@ -327,16 +335,15 @@ bool OneSixInstance::reloadVersion() d->vanillaVersion->reload(true, externalPatches()); setFlags(flags() & ~VersionBrokenFlag); emit versionReloaded(); - return true; } - catch(MMCError error) + catch(MMCError & error) { d->version->clear(); d->vanillaVersion->clear(); setFlags(flags() | VersionBrokenFlag); //TODO: rethrow to show some error message(s)? emit versionReloaded(); - return false; + throw; } } diff --git a/logic/OneSixInstance.h b/logic/OneSixInstance.h index c7ef2ee8..d2bc9b01 100644 --- a/logic/OneSixInstance.h +++ b/logic/OneSixInstance.h @@ -53,8 +53,12 @@ public: virtual QDialog *createModEditDialog(QWidget *parent) override; - /// reload the full version json files. return true on success! - bool reloadVersion(); + /** + * reload the full version json files. return true on success! + * + * throws various exceptions :3 + */ + void reloadVersion(); /// clears all version information in preparation for an update void clearVersion(); /// get the current full version info diff --git a/logic/OneSixUpdate.cpp b/logic/OneSixUpdate.cpp index 750aeabb..65f30cda 100644 --- a/logic/OneSixUpdate.cpp +++ b/logic/OneSixUpdate.cpp @@ -48,7 +48,7 @@ void OneSixUpdate::executeTask() QDir mcDir(m_inst->minecraftRoot()); if (!mcDir.exists() && !mcDir.mkpath(".")) { - emitFailed("Failed to create bin folder."); + emitFailed(tr("Failed to create folder for minecraft binaries.")); return; } @@ -60,7 +60,7 @@ void OneSixUpdate::executeTask() if (targetVersion == nullptr) { // don't do anything if it was invalid - emitFailed("The specified Minecraft version is invalid. Choose a different one."); + emitFailed(tr("The specified Minecraft version is invalid. Choose a different one.")); return; } versionFileStart(); @@ -108,20 +108,19 @@ void OneSixUpdate::versionFileFinished() QSaveFile vfile1(version1); if (!vfile1.open(QIODevice::Truncate | QIODevice::WriteOnly)) { - emitFailed("Can't open " + version1 + " for writing."); + emitFailed(tr("Can't open %1 for writing.").arg(version1)); return; } auto data = std::dynamic_pointer_cast(DlJob)->m_data; qint64 actual = 0; if ((actual = vfile1.write(data)) != data.size()) { - emitFailed("Failed to write into " + version1 + ". Written " + actual + " out of " + - data.size() + '.'); + emitFailed(tr("Failed to write into %1. Written %2 out of %3.").arg(version1).arg(actual).arg(data.size())); return; } if (!vfile1.commit()) { - emitFailed("Can't commit changes to " + version1); + emitFailed(tr("Can't commit changes to %1").arg(version1)); return; } } @@ -136,14 +135,13 @@ void OneSixUpdate::versionFileFinished() { finfo.remove(); } - inst->reloadVersion(); - + // NOTE: Version is reloaded in jarlibStart jarlibStart(); } void OneSixUpdate::versionFileFailed() { - emitFailed("Failed to download the version description. Try again."); + emitFailed(tr("Failed to download the version description. Try again.")); } void OneSixUpdate::assetIndexStart() @@ -180,7 +178,7 @@ void OneSixUpdate::assetIndexFinished() QString asset_fname = "assets/indexes/" + assetName + ".json"; if (!AssetsUtils::loadAssetsIndexJson(asset_fname, &index)) { - emitFailed("Failed to read the assets index!"); + emitFailed(tr("Failed to read the assets index!")); } QList dls; @@ -216,7 +214,7 @@ void OneSixUpdate::assetIndexFinished() void OneSixUpdate::assetIndexFailed() { - emitFailed("Failed to download the assets index!"); + emitFailed(tr("Failed to download the assets index!")); } void OneSixUpdate::assetsFinished() @@ -226,7 +224,7 @@ void OneSixUpdate::assetsFinished() void OneSixUpdate::assetsFailed() { - emitFailed("Failed to download assets!"); + emitFailed(tr("Failed to download assets!")); } void OneSixUpdate::jarlibStart() @@ -234,11 +232,18 @@ void OneSixUpdate::jarlibStart() setStatus(tr("Getting the library files from Mojang...")); QLOG_INFO() << m_inst->name() << ": downloading libraries"; OneSixInstance *inst = (OneSixInstance *)m_inst; - bool successful = inst->reloadVersion(); - if (!successful) + try + { + inst->reloadVersion(); + } + catch(MMCError & e) + { + emitFailed(e.cause()); + return; + } + catch(...) { - emitFailed("Failed to load the version description file. It might be " - "corrupted, missing or simply too new."); + emitFailed(tr("Failed to load the version description file for reasons unknown.")); return; } @@ -326,6 +331,5 @@ void OneSixUpdate::jarlibFailed() { QStringList failed = jarlibDownloadJob->getFailedFiles(); QString failed_all = failed.join("\n"); - emitFailed("Failed to download the following files:\n" + failed_all + - "\n\nPlease try again."); + emitFailed(tr("Failed to download the following files:\n%1\n\nPlease try again.").arg(failed_all)); } diff --git a/logic/OneSixVersionBuilder.cpp b/logic/OneSixVersionBuilder.cpp index 8abeb0d8..8eacbce4 100644 --- a/logic/OneSixVersionBuilder.cpp +++ b/logic/OneSixVersionBuilder.cpp @@ -38,7 +38,8 @@ OneSixVersionBuilder::OneSixVersionBuilder() { } -void OneSixVersionBuilder::build(VersionFinal *version, OneSixInstance *instance, const bool onlyVanilla, const QStringList &external) +void OneSixVersionBuilder::build(VersionFinal *version, OneSixInstance *instance, + const bool onlyVanilla, const QStringList &external) { OneSixVersionBuilder builder; builder.m_version = version; @@ -46,7 +47,8 @@ void OneSixVersionBuilder::build(VersionFinal *version, OneSixInstance *instance builder.buildInternal(onlyVanilla, external); } -void OneSixVersionBuilder::readJsonAndApplyToVersion(VersionFinal *version, const QJsonObject &obj) +void OneSixVersionBuilder::readJsonAndApplyToVersion(VersionFinal *version, + const QJsonObject &obj) { OneSixVersionBuilder builder; builder.m_version = version; @@ -62,17 +64,19 @@ void OneSixVersionBuilder::buildInternal(const bool onlyVanilla, const QStringLi QDir patches(root.absoluteFilePath("patches/")); // if we do external files, do just those. - if(!external.isEmpty()) for (auto fileName : external) - { - 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->version = QString(); - file->mcVersion = QString(); - file->applyTo(m_version); - m_version->versionFiles.append(file); - } + if (!external.isEmpty()) + for (auto fileName : external) + { + 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->version = QString(); + file->mcVersion = QString(); + file->applyTo(m_version); + m_version->versionFiles.append(file); + } // else, if there's custom json, we just do that. else if (QFile::exists(root.absoluteFilePath("custom.json"))) { @@ -84,48 +88,52 @@ void OneSixVersionBuilder::buildInternal(const bool onlyVanilla, const QStringLi file->version = QString(); file->applyTo(m_version); m_version->versionFiles.append(file); - // QObject::tr("The version descriptors of this instance are not compatible with the current version of MultiMC")); + // 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.") } // 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->version = m_instance->intendedVersionId(); - file->mcVersion = m_instance->intendedVersionId(); - file->applyTo(m_version); - m_version->versionFiles.append(file); - // QObject::tr("Error while applying %1. Please check MultiMC-0.log for more info.").arg(root.absoluteFilePath("version.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->version = m_instance->intendedVersionId(); + file->mcVersion = m_instance->intendedVersionId(); + file->applyTo(m_version); + m_version->versionFiles.append(file); + // QObject::tr("Error while applying %1. Please check MultiMC-0.log for more + // info.").arg(root.absoluteFilePath("version.json"))); - if (onlyVanilla) - break; + if (onlyVanilla) + break; - // patches/ - // load all, put into map for ordering, apply in the right order + // patches/ + // load all, put into map for ordering, apply in the right order - QMap> 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)) + QMap> files; + for (auto info : patches.entryInfoList(QStringList() << "*.json", QDir::Files)) { - throw VersionBuildError(QObject::tr("%1 has the same order as %2").arg(file->fileId, files[file->order].second->fileId)); + 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)); } - files.insert(file->order, qMakePair(info.fileName(), file)); - } - for (auto order : files.keys()) - { - QLOG_DEBUG() << "Applying file with order" << order; - auto & filePair = files[order]; - filePair.second->applyTo(m_version); - m_version->versionFiles.append(filePair.second); - } - } while(0); + for (auto order : files.keys()) + { + QLOG_DEBUG() << "Applying file with order" << order; + auto &filePair = files[order]; + filePair.second->applyTo(m_version); + m_version->versionFiles.append(filePair.second); + } + } while (0); // some final touches finalizeVersion(); @@ -168,26 +176,30 @@ void OneSixVersionBuilder::readJsonAndApply(const QJsonObject &obj) file->applyTo(m_version); m_version->versionFiles.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")); + // QObject::tr("The version descriptors of this instance are not compatible with the current + // version of MultiMC")); } -VersionFilePtr OneSixVersionBuilder::parseJsonFile(const QFileInfo &fileInfo, const bool requireOrder, bool isFTB) +VersionFilePtr OneSixVersionBuilder::parseJsonFile(const QFileInfo &fileInfo, + const bool requireOrder, bool isFTB) { QFile file(fileInfo.absoluteFilePath()); if (!file.open(QFile::ReadOnly)) { - throw JSONValidationError(QObject::tr("Unable to open %1: %2").arg(file.fileName(), file.errorString())); + throw JSONValidationError(QObject::tr("Unable to open the version file %1: %2.") + .arg(fileInfo.fileName(), file.errorString())); } QJsonParseError error; QJsonDocument doc = QJsonDocument::fromJson(file.readAll(), &error); if (error.error != QJsonParseError::NoError) { - throw JSONValidationError(QObject::tr("Unable to parse %1: %2 at %3") - .arg(file.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 info.").arg(file.fileName()); + // QObject::tr("Error while reading %1. Please check MultiMC-0.log for more + // info.").arg(file.fileName()); } QMap OneSixVersionBuilder::readOverrideOrders(OneSixInstance *instance) @@ -203,7 +215,7 @@ QMap OneSixVersionBuilder::readOverrideOrders(OneSixInstance *inst if (!orderFile.open(QFile::ReadOnly)) { QLOG_ERROR() << "Couldn't open" << orderFile.fileName() - << " for reading:" << orderFile.errorString(); + << " for reading:" << orderFile.errorString(); QLOG_WARN() << "Ignoring overriden order"; return out; } @@ -211,9 +223,9 @@ QMap OneSixVersionBuilder::readOverrideOrders(OneSixInstance *inst // and it's valid JSON QJsonParseError error; QJsonDocument doc = QJsonDocument::fromJson(orderFile.readAll(), &error); - if (error.error != QJsonParseError::NoError ) + if (error.error != QJsonParseError::NoError) { - QLOG_ERROR() << "Couldn't parse" << orderFile.fileName() << ":" << error.errorString(); + QLOG_ERROR() << "Couldn't parse" << orderFile.fileName() << ":" << error.errorString(); QLOG_WARN() << "Ignoring overriden order"; return out; } @@ -231,7 +243,7 @@ QMap OneSixVersionBuilder::readOverrideOrders(OneSixInstance *inst out.insert(it.key(), MMCJson::ensureInteger(it.value())); } } - catch (JSONValidationError err) + catch (JSONValidationError &err) { QLOG_ERROR() << "Couldn't parse" << orderFile.fileName() << ": bad file format"; QLOG_WARN() << "Ignoring overriden order"; @@ -262,4 +274,3 @@ bool OneSixVersionBuilder::writeOverrideOrders(const QMap &order, orderFile.write(QJsonDocument(obj).toJson(QJsonDocument::Indented)); return true; } - diff --git a/logic/VersionFile.cpp b/logic/VersionFile.cpp index 40dcb0c3..831b086e 100644 --- a/logic/VersionFile.cpp +++ b/logic/VersionFile.cpp @@ -311,9 +311,7 @@ void VersionFile::applyTo(VersionFinal *version) { if (minimumLauncherVersion > CURRENT_MINIMUM_LAUNCHER_VERSION) { - throw VersionBuildError( - QString("%1 is for a different launcher version (%2), current supported is %3") - .arg(filename, minimumLauncherVersion, CURRENT_MINIMUM_LAUNCHER_VERSION)); + throw LauncherVersionError(minimumLauncherVersion, CURRENT_MINIMUM_LAUNCHER_VERSION); } } @@ -322,8 +320,7 @@ void VersionFile::applyTo(VersionFinal *version) if (QRegExp(mcVersion, Qt::CaseInsensitive, QRegExp::Wildcard).indexIn(version->id) == -1) { - throw VersionBuildError( - QString("%1 is for a different version of Minecraft").arg(filename)); + throw MinecraftVersionMismatch(fileId, mcVersion, version->id); } } @@ -471,7 +468,7 @@ void VersionFile::applyTo(VersionFinal *version) (lib->dependType == RawLibrary::Hard && ourVersion != otherVersion)) { throw VersionBuildError( - QString( + QObject::tr( "Error resolving library dependencies between %1 and %2 in %3.") .arg(otherLib->rawName(), lib->name, filename)); } @@ -498,7 +495,7 @@ void VersionFile::applyTo(VersionFinal *version) // it: fail if (lib->dependType == RawLibrary::Hard) { - throw VersionBuildError(QString( + throw VersionBuildError(QObject::tr( "Error resolving library dependencies between %1 and %2 in %3.") .arg(otherLib->rawName(), lib->name, filename)); diff --git a/logic/VersionFile.h b/logic/VersionFile.h index 504fcbff..67d22b23 100644 --- a/logic/VersionFile.h +++ b/logic/VersionFile.h @@ -13,13 +13,39 @@ class VersionBuildError : public MMCError { public: VersionBuildError(QString cause) : MMCError(cause) {}; - virtual QString errorName() - { - return "VersionBuildError"; - }; virtual ~VersionBuildError() {}; }; +/** + * 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() {}; +}; + +/** + * 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() {}; +}; + struct RawLibrary; typedef std::shared_ptr RawLibraryPtr; struct RawLibrary @@ -61,7 +87,7 @@ struct VersionFile { public: /* methods */ static VersionFilePtr fromJson(const QJsonDocument &doc, const QString &filename, - const bool requireOrder, const bool isFTB = false); + const bool requireOrder, const bool isFTB = false); static OneSixLibraryPtr createLibrary(RawLibraryPtr lib); int findLibrary(QList haystack, const QString &needle); diff --git a/logic/VersionFinal.cpp b/logic/VersionFinal.cpp index 48601d57..a057ecdd 100644 --- a/logic/VersionFinal.cpp +++ b/logic/VersionFinal.cpp @@ -112,7 +112,7 @@ std::shared_ptr VersionFinal::fromJson(const QJsonObject &obj) { OneSixVersionBuilder::readJsonAndApplyToVersion(version.get(), obj); } - catch(MMCError err) + catch(MMCError & err) { return 0; } -- cgit v1.2.3 From 5328cc7bbee5044b41355ff702af9c62971acc20 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Mr=C3=A1zek?= Date: Mon, 10 Mar 2014 00:14:30 +0100 Subject: Add missing include for math.h --- logic/MMCJson.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'logic') diff --git a/logic/MMCJson.cpp b/logic/MMCJson.cpp index 80d36204..25cc2de3 100644 --- a/logic/MMCJson.cpp +++ b/logic/MMCJson.cpp @@ -1,5 +1,6 @@ #include "MMCJson.h" #include +#include bool MMCJson::ensureBoolean(const QJsonValue val, const QString what) { -- cgit v1.2.3 From d11f10ea1ed54336254838ff068258d2d42e0774 Mon Sep 17 00:00:00 2001 From: Jan Dalheimer Date: Mon, 10 Mar 2014 18:55:54 +0100 Subject: Fix a compiling error by adding noexcept --- logic/MMCJson.h | 2 +- logic/VersionFile.h | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'logic') diff --git a/logic/MMCJson.h b/logic/MMCJson.h index f2cc4b31..71ded435 100644 --- a/logic/MMCJson.h +++ b/logic/MMCJson.h @@ -15,7 +15,7 @@ class JSONValidationError : public MMCError { public: JSONValidationError(QString cause) : MMCError(cause) {}; - virtual ~JSONValidationError() {}; + virtual ~JSONValidationError() noexcept {} }; namespace MMCJson diff --git a/logic/VersionFile.h b/logic/VersionFile.h index 67d22b23..169a2066 100644 --- a/logic/VersionFile.h +++ b/logic/VersionFile.h @@ -13,7 +13,7 @@ class VersionBuildError : public MMCError { public: VersionBuildError(QString cause) : MMCError(cause) {}; - virtual ~VersionBuildError() {}; + virtual ~VersionBuildError() noexcept {} }; /** @@ -28,7 +28,7 @@ public: "version of the vanilla launcher than this version of MultiMC supports (%2).") .arg(actual) .arg(supported)) {}; - virtual ~LauncherVersionError() {}; + virtual ~LauncherVersionError() noexcept {} }; /** @@ -43,7 +43,7 @@ public: .arg(fileId) .arg(mcVersion) .arg(parentMcVersion)) {}; - virtual ~MinecraftVersionMismatch() {}; + virtual ~MinecraftVersionMismatch() noexcept {} }; struct RawLibrary; @@ -124,4 +124,4 @@ public: /* data */ QList overwriteLibs; QList addLibs; QList removeLibs; -}; \ No newline at end of file +}; -- cgit v1.2.3