diff options
author | Petr Mrázek <peterix@gmail.com> | 2013-09-22 14:03:05 +0200 |
---|---|---|
committer | Petr Mrázek <peterix@gmail.com> | 2013-09-22 14:03:05 +0200 |
commit | 1bed5e4023f503cb95a914c1e6886e045b7f34e2 (patch) | |
tree | 6c2a2eb34b93bdd24e7db1f9378b231084c0b27a /logic | |
parent | 930b07afd4229e952d0cd47ca62cd94235499a0c (diff) | |
parent | 9d03a9c1e3b9c24a4146adedb2971591d23b037a (diff) | |
download | MultiMC-1bed5e4023f503cb95a914c1e6886e045b7f34e2.tar MultiMC-1bed5e4023f503cb95a914c1e6886e045b7f34e2.tar.gz MultiMC-1bed5e4023f503cb95a914c1e6886e045b7f34e2.tar.lz MultiMC-1bed5e4023f503cb95a914c1e6886e045b7f34e2.tar.xz MultiMC-1bed5e4023f503cb95a914c1e6886e045b7f34e2.zip |
Merge branch 'feature_onesix_forge' into develop
Diffstat (limited to 'logic')
-rw-r--r-- | logic/BaseInstance.cpp | 2 | ||||
-rw-r--r-- | logic/BaseInstance.h | 2 | ||||
-rw-r--r-- | logic/ForgeInstaller.cpp | 135 | ||||
-rw-r--r-- | logic/ForgeInstaller.h | 25 | ||||
-rw-r--r-- | logic/LegacyUpdate.cpp | 4 | ||||
-rw-r--r-- | logic/ModList.h | 3 | ||||
-rw-r--r-- | logic/NostalgiaInstance.h | 1 | ||||
-rw-r--r-- | logic/OneSixInstance.cpp | 129 | ||||
-rw-r--r-- | logic/OneSixInstance.h | 4 | ||||
-rw-r--r-- | logic/OneSixLibrary.cpp | 98 | ||||
-rw-r--r-- | logic/OneSixLibrary.h | 26 | ||||
-rw-r--r-- | logic/OneSixRule.cpp | 66 | ||||
-rw-r--r-- | logic/OneSixRule.h | 6 | ||||
-rw-r--r-- | logic/OneSixUpdate.cpp | 85 | ||||
-rw-r--r-- | logic/OneSixVersion.cpp | 261 | ||||
-rw-r--r-- | logic/OneSixVersion.h | 60 | ||||
-rw-r--r-- | logic/OpSys.cpp | 11 | ||||
-rw-r--r-- | logic/OpSys.h | 1 | ||||
-rw-r--r-- | logic/VersionFactory.cpp | 196 | ||||
-rw-r--r-- | logic/VersionFactory.h | 24 | ||||
-rw-r--r-- | logic/lists/ForgeVersionList.cpp | 118 | ||||
-rw-r--r-- | logic/lists/ForgeVersionList.h | 52 | ||||
-rw-r--r-- | logic/net/CacheDownload.cpp | 63 | ||||
-rw-r--r-- | logic/net/HttpMetaCache.h | 19 | ||||
-rw-r--r-- | logic/tasks/LoginTask.cpp | 2 |
25 files changed, 873 insertions, 520 deletions
diff --git a/logic/BaseInstance.cpp b/logic/BaseInstance.cpp index 10bb4573..ec86596a 100644 --- a/logic/BaseInstance.cpp +++ b/logic/BaseInstance.cpp @@ -132,7 +132,7 @@ InstanceList *BaseInstance::instList() const return NULL; } -BaseVersionList *BaseInstance::versionList() const +QSharedPointer<BaseVersionList> BaseInstance::versionList() const { return MMC->minecraftlist(); } diff --git a/logic/BaseInstance.h b/logic/BaseInstance.h index fa317ba1..374d1437 100644 --- a/logic/BaseInstance.h +++ b/logic/BaseInstance.h @@ -134,7 +134,7 @@ public: * \brief Gets a pointer to this instance's version list. * \return A pointer to the available version list for this instance. */ - virtual BaseVersionList *versionList() const; + virtual QSharedPointer<BaseVersionList> versionList() const; /*! * \brief Gets this instance's settings object. diff --git a/logic/ForgeInstaller.cpp b/logic/ForgeInstaller.cpp new file mode 100644 index 00000000..bcba00e9 --- /dev/null +++ b/logic/ForgeInstaller.cpp @@ -0,0 +1,135 @@ +#include "ForgeInstaller.h" +#include "OneSixVersion.h" +#include "OneSixLibrary.h" +#include "net/HttpMetaCache.h" +#include <quazip.h> +#include <quazipfile.h> +#include <pathutils.h> +#include <QStringList> +#include "MultiMC.h" + +ForgeInstaller::ForgeInstaller(QString filename, QString universal_url) +{ + QSharedPointer<OneSixVersion> newVersion; + m_universal_url = universal_url; + + QuaZip zip(filename); + if (!zip.open(QuaZip::mdUnzip)) + return; + + QuaZipFile file(&zip); + + // read the install profile + if (!zip.setCurrentFile("install_profile.json")) + return; + + QJsonParseError jsonError; + if (!file.open(QIODevice::ReadOnly)) + return; + QJsonDocument jsonDoc = QJsonDocument::fromJson(file.readAll(), &jsonError); + file.close(); + if (jsonError.error != QJsonParseError::NoError) + return; + + if (!jsonDoc.isObject()) + return; + + QJsonObject root = jsonDoc.object(); + + auto installVal = root.value("install"); + auto versionInfoVal = root.value("versionInfo"); + if (!installVal.isObject() || !versionInfoVal.isObject()) + return; + + // read the forge version info + { + newVersion = OneSixVersion::fromJson(versionInfoVal.toObject()); + if (!newVersion) + return; + } + + QJsonObject installObj = installVal.toObject(); + QString libraryName = installObj.value("path").toString(); + internalPath = installObj.value("filePath").toString(); + + // where do we put the library? decode the mojang path + OneSixLibrary lib(libraryName); + lib.finalize(); + + auto cacheentry = MMC->metacache()->resolveEntry("libraries", lib.storagePath()); + finalPath = "libraries/" + lib.storagePath(); + if (!ensureFilePathExists(finalPath)) + return; + + if (!zip.setCurrentFile(internalPath)) + return; + if (!file.open(QIODevice::ReadOnly)) + return; + { + QByteArray data = file.readAll(); + // extract file + QSaveFile extraction(finalPath); + if (!extraction.open(QIODevice::WriteOnly)) + return; + if (extraction.write(data) != data.size()) + return; + if (!extraction.commit()) + return; + QCryptographicHash md5sum(QCryptographicHash::Md5); + md5sum.addData(data); + + cacheentry->stale = false; + cacheentry->md5sum = md5sum.result().toHex().constData(); + MMC->metacache()->updateEntry(cacheentry); + } + file.close(); + + m_forge_version = newVersion; + realVersionId = m_forge_version->id = installObj.value("minecraft").toString(); +} + +bool ForgeInstaller::apply(QSharedPointer<OneSixVersion> to) +{ + if (!m_forge_version) + return false; + to->externalUpdateStart(); + int sliding_insert_window = 0; + { + // for each library in the version we are adding (except for the blacklisted) + QSet<QString> blacklist{"lwjgl", "lwjgl_util", "lwjgl-platform"}; + for (auto lib : m_forge_version->libraries) + { + QString libName = lib->name(); + // if this is the actual forge lib, set an absolute url for the download + if (libName.contains("minecraftforge")) + { + lib->setAbsoluteUrl(m_universal_url); + } + if (blacklist.contains(libName)) + continue; + + // find an entry that matches this one + bool found = false; + for (auto tolib : to->libraries) + { + if (tolib->name() != libName) + continue; + found = true; + // replace lib + tolib = lib; + break; + } + if (!found) + { + // add lib + to->libraries.insert(sliding_insert_window, lib); + sliding_insert_window++; + } + } + to->mainClass = m_forge_version->mainClass; + to->minecraftArguments = m_forge_version->minecraftArguments; + to->processArguments = m_forge_version->processArguments; + } + to->externalUpdateFinish(); + return to->toOriginalFile(); +} diff --git a/logic/ForgeInstaller.h b/logic/ForgeInstaller.h new file mode 100644 index 00000000..f4ceaaef --- /dev/null +++ b/logic/ForgeInstaller.h @@ -0,0 +1,25 @@ +#pragma once +#include <QString> +#include <QSharedPointer> + +class OneSixVersion; + +class ForgeInstaller +{ +public: + ForgeInstaller(QString filename, QString universal_url); + + bool apply(QSharedPointer<OneSixVersion> to); + +private: + // the version, read from the installer + QSharedPointer<OneSixVersion> m_forge_version; + QString internalPath; + QString finalPath; + QString realVersionId; + QString m_universal_url; +}; + + + + diff --git a/logic/LegacyUpdate.cpp b/logic/LegacyUpdate.cpp index 0f58e3e3..84d3d830 100644 --- a/logic/LegacyUpdate.cpp +++ b/logic/LegacyUpdate.cpp @@ -60,7 +60,7 @@ void LegacyUpdate::lwjglStart() m_reply = QSharedPointer<QNetworkReply> (rep, &QObject::deleteLater); connect(rep, SIGNAL(downloadProgress(qint64,qint64)), SIGNAL(progress(qint64,qint64))); - connect(worker, SIGNAL(finished(QNetworkReply*)), SLOT(lwjglFinished(QNetworkReply*))); + connect(worker.data(), SIGNAL(finished(QNetworkReply*)), SLOT(lwjglFinished(QNetworkReply*))); //connect(rep, SIGNAL(error(QNetworkReply::NetworkError)), SLOT(downloadError(QNetworkReply::NetworkError))); } @@ -77,7 +77,7 @@ void LegacyUpdate::lwjglFinished(QNetworkReply* reply) "\nSometimes you have to wait a bit if you download many LWJGL versions in a row. YMMV"); return; } - auto *worker = MMC->qnam(); + auto worker = MMC->qnam(); //Here i check if there is a cookie for me in the reply and extract it QList<QNetworkCookie> cookies = qvariant_cast<QList<QNetworkCookie>>(reply->header(QNetworkRequest::SetCookieHeader)); if(cookies.count() != 0) diff --git a/logic/ModList.h b/logic/ModList.h index 5395e9ae..e99b6c82 100644 --- a/logic/ModList.h +++ b/logic/ModList.h @@ -112,3 +112,6 @@ protected: QString m_list_id; QList<Mod> mods; }; + + + diff --git a/logic/NostalgiaInstance.h b/logic/NostalgiaInstance.h index f2df1828..1436e48d 100644 --- a/logic/NostalgiaInstance.h +++ b/logic/NostalgiaInstance.h @@ -9,3 +9,4 @@ public: explicit NostalgiaInstance(const QString &rootDir, SettingsObject * settings, QObject *parent = 0); virtual QString getStatusbarDescription(); }; + diff --git a/logic/OneSixInstance.cpp b/logic/OneSixInstance.cpp index 7b038c46..e22a8890 100644 --- a/logic/OneSixInstance.cpp +++ b/logic/OneSixInstance.cpp @@ -2,7 +2,7 @@ #include "OneSixInstance_p.h" #include "OneSixUpdate.h" #include "MinecraftProcess.h" -#include "VersionFactory.h" +#include "OneSixVersion.h" #include <setting.h> #include <pathutils.h> @@ -10,8 +10,9 @@ #include <JlCompress.h> #include <gui/OneSixModEditDialog.h> -OneSixInstance::OneSixInstance ( const QString& rootDir, SettingsObject* setting_obj, QObject* parent ) -: BaseInstance ( new OneSixInstancePrivate(), rootDir, setting_obj, parent ) +OneSixInstance::OneSixInstance(const QString &rootDir, SettingsObject *setting_obj, + QObject *parent) + : BaseInstance(new OneSixInstancePrivate(), rootDir, setting_obj, parent) { I_D(OneSixInstance); d->m_settings->registerSetting(new Setting("IntendedVersion", "")); @@ -19,7 +20,7 @@ OneSixInstance::OneSixInstance ( const QString& rootDir, SettingsObject* setting reloadFullVersion(); } -BaseUpdate* OneSixInstance::doUpdate() +BaseUpdate *OneSixInstance::doUpdate() { return new OneSixUpdate(this); } @@ -34,10 +35,10 @@ QString replaceTokensIn(QString text, QMap<QString, QString> with) int head = 0; while ((head = token_regexp.indexIn(text, head)) != -1) { - result.append(text.mid(tail, head-tail)); + result.append(text.mid(tail, head - tail)); QString key = token_regexp.cap(1); auto iter = with.find(key); - if(iter != with.end()) + if (iter != with.end()) { result.append(*iter); } @@ -48,26 +49,26 @@ QString replaceTokensIn(QString text, QMap<QString, QString> with) return result; } -QStringList OneSixInstance::processMinecraftArgs( QString user, QString session ) +QStringList OneSixInstance::processMinecraftArgs(QString user, QString session) { I_D(OneSixInstance); auto version = d->version; QString args_pattern = version->minecraftArguments; - + QMap<QString, QString> token_mapping; token_mapping["auth_username"] = user; token_mapping["auth_session"] = session; - //FIXME: user and player name are DIFFERENT! + // FIXME: user and player name are DIFFERENT! token_mapping["auth_player_name"] = user; - //FIXME: WTF is this. I just plugged in a random UUID here. + // FIXME: WTF is this. I just plugged in a random UUID here. token_mapping["auth_uuid"] = "7d4bacf0-fd62-11e2-b778-0800200c9a66"; // obviously fake. - + // this is for offline: /* map["auth_player_name"] = "Player"; map["auth_player_name"] = "00000000-0000-0000-0000-000000000000"; */ - + token_mapping["profile_name"] = name(); token_mapping["version_name"] = version->id; @@ -75,8 +76,8 @@ QStringList OneSixInstance::processMinecraftArgs( QString user, QString session token_mapping["game_directory"] = absRootDir; QString absAssetsDir = QDir("assets/").absolutePath(); token_mapping["game_assets"] = absAssetsDir; - - QStringList parts = args_pattern.split(' ',QString::SkipEmptyParts); + + QStringList parts = args_pattern.split(' ', QString::SkipEmptyParts); for (int i = 0; i < parts.length(); i++) { parts[i] = replaceTokensIn(parts[i], token_mapping); @@ -84,27 +85,28 @@ QStringList OneSixInstance::processMinecraftArgs( QString user, QString session return parts; } -MinecraftProcess* OneSixInstance::prepareForLaunch ( QString user, QString session ) +MinecraftProcess *OneSixInstance::prepareForLaunch(QString user, QString session) { I_D(OneSixInstance); cleanupAfterRun(); auto version = d->version; - if(!version) + if (!version) return nullptr; auto libs_to_extract = version->getActiveNativeLibs(); QString natives_dir_raw = PathCombine(instanceRoot(), "natives/"); bool success = ensureFolderPathExists(natives_dir_raw); - if(!success) + if (!success) { // FIXME: handle errors return nullptr; } - - for(auto lib: libs_to_extract) + + for (auto lib : libs_to_extract) { QString path = "libraries/" + lib->storagePath(); qDebug() << "Will extract " << path.toLocal8Bit(); - if(JlCompress::extractWithExceptions(path, natives_dir_raw, lib->extract_excludes).isEmpty()) + if (JlCompress::extractWithExceptions(path, natives_dir_raw, lib->extract_excludes) + .isEmpty()) { return nullptr; } @@ -116,11 +118,11 @@ MinecraftProcess* OneSixInstance::prepareForLaunch ( QString user, QString sessi args << QString("-Xmx%1m").arg(settings().get("MaxMemAlloc").toInt()); args << QString("-XX:PermSize=%1m").arg(settings().get("PermGen").toInt()); QDir natives_dir(natives_dir_raw); - args << QString("-Djava.library.path=%1").arg( natives_dir.absolutePath() ); + args << QString("-Djava.library.path=%1").arg(natives_dir.absolutePath()); QString classPath; { auto libs = version->getActiveNormalLibs(); - for (auto lib: libs) + for (auto lib : libs) { QFileInfo fi(QString("libraries/") + lib->storagePath()); classPath.append(fi.absoluteFilePath()); @@ -134,16 +136,16 @@ MinecraftProcess* OneSixInstance::prepareForLaunch ( QString user, QString sessi QFileInfo fi(targetstr); classPath.append(fi.absoluteFilePath()); } - if(classPath.size()) + if (classPath.size()) { args << "-cp"; args << classPath; } args << version->mainClass; args.append(processMinecraftArgs(user, session)); - + // create the process and set its parameters - MinecraftProcess * proc = new MinecraftProcess(this); + MinecraftProcess *proc = new MinecraftProcess(this); proc->setMinecraftArguments(args); proc->setMinecraftWorkdir(minecraftRoot()); return proc; @@ -156,10 +158,10 @@ void OneSixInstance::cleanupAfterRun() dir.removeRecursively(); } -QSharedPointer< ModList > OneSixInstance::loaderModList() +QSharedPointer<ModList> OneSixInstance::loaderModList() { I_D(OneSixInstance); - if(!d->loader_mod_list) + if (!d->loader_mod_list) { d->loader_mod_list.reset(new ModList(loaderModsDir())); } @@ -168,10 +170,10 @@ QSharedPointer< ModList > OneSixInstance::loaderModList() return d->loader_mod_list; } -QSharedPointer< ModList > OneSixInstance::resourcePackList() +QSharedPointer<ModList> OneSixInstance::resourcePackList() { I_D(OneSixInstance); - if(!d->resource_pack_list) + if (!d->resource_pack_list) { d->resource_pack_list.reset(new ModList(resourcePacksDir())); } @@ -180,13 +182,12 @@ QSharedPointer< ModList > OneSixInstance::resourcePackList() return d->resource_pack_list; } - -QDialog * OneSixInstance::createModEditDialog ( QWidget* parent ) +QDialog *OneSixInstance::createModEditDialog(QWidget *parent) { return new OneSixModEditDialog(this, parent); } -bool OneSixInstance::setIntendedVersionId ( QString version ) +bool OneSixInstance::setIntendedVersionId(QString version) { settings().set("IntendedVersion", version); setShouldUpdate(true); @@ -198,16 +199,16 @@ QString OneSixInstance::intendedVersionId() const return settings().get("IntendedVersion").toString(); } -void OneSixInstance::setShouldUpdate ( bool val ) +void OneSixInstance::setShouldUpdate(bool val) { - settings().set ( "ShouldUpdate", val ); + settings().set("ShouldUpdate", val); } bool OneSixInstance::shouldUpdate() const { I_D(OneSixInstance); - QVariant var = settings().get ( "ShouldUpdate" ); - if ( !var.isValid() || var.toBool() == false ) + QVariant var = settings().get("ShouldUpdate"); + if (!var.isValid() || var.toBool() == false) { return intendedVersionId() != currentVersionId(); } @@ -226,34 +227,53 @@ QString OneSixInstance::currentVersionId() const return intendedVersionId(); } +bool OneSixInstance::customizeVersion() +{ + if (!versionIsCustom()) + { + auto pathCustom = PathCombine(instanceRoot(), "custom.json"); + auto pathOrig = PathCombine(instanceRoot(), "version.json"); + QFile::copy(pathOrig, pathCustom); + return reloadFullVersion(); + } + else + return true; +} + +bool OneSixInstance::revertCustomVersion() +{ + if (versionIsCustom()) + { + auto path = PathCombine(instanceRoot(), "custom.json"); + QFile::remove(path); + return reloadFullVersion(); + } + else + return true; +} + bool OneSixInstance::reloadFullVersion() { I_D(OneSixInstance); - + QString verpath = PathCombine(instanceRoot(), "version.json"); { QString verpath_custom = PathCombine(instanceRoot(), "custom.json"); QFile versionfile(verpath_custom); - if(versionfile.exists()) + if (versionfile.exists()) verpath = verpath_custom; } - - QFile versionfile(verpath); - if(versionfile.exists() && versionfile.open(QIODevice::ReadOnly)) + + auto version = OneSixVersion::fromFile(verpath); + if (version) { - FullVersionFactory fvf; - auto version = fvf.parse(versionfile.readAll()); - versionfile.close(); - if(version) - { - d->version = version; - return true; - } - }; + d->version = version; + return true; + } return false; } -QSharedPointer< OneSixVersion > OneSixInstance::getFullVersion() +QSharedPointer<OneSixVersion> OneSixInstance::getFullVersion() { I_D(OneSixInstance); return d->version; @@ -269,9 +289,9 @@ QString OneSixInstance::defaultCustomBaseJar() const return PathCombine(instanceRoot(), "custom.jar"); } -bool OneSixInstance::menuActionEnabled ( QString action_name ) const +bool OneSixInstance::menuActionEnabled(QString action_name) const { - if(action_name == "actionChangeInstLWJGLVersion") + if (action_name == "actionChangeInstLWJGLVersion") return false; return true; } @@ -279,7 +299,7 @@ bool OneSixInstance::menuActionEnabled ( QString action_name ) const QString OneSixInstance::getStatusbarDescription() { QString descr = "One Six : " + intendedVersionId(); - if(versionIsCustom()) + if (versionIsCustom()) { descr + " (custom)"; } @@ -300,3 +320,4 @@ QString OneSixInstance::instanceConfigFolder() const { return PathCombine(minecraftRoot(), "config"); } + diff --git a/logic/OneSixInstance.h b/logic/OneSixInstance.h index 72bde630..0139b645 100644 --- a/logic/OneSixInstance.h +++ b/logic/OneSixInstance.h @@ -41,6 +41,10 @@ public: bool reloadFullVersion(); /// get the current full version info QSharedPointer<OneSixVersion> getFullVersion(); + /// revert the current custom version back to base + bool revertCustomVersion(); + /// customize the current base version + bool customizeVersion(); /// is the current version original, or custom? bool versionIsCustom(); diff --git a/logic/OneSixLibrary.cpp b/logic/OneSixLibrary.cpp index a45a4aec..8da1fde7 100644 --- a/logic/OneSixLibrary.cpp +++ b/logic/OneSixLibrary.cpp @@ -1,18 +1,19 @@ #include "OneSixLibrary.h" #include "OneSixRule.h" #include "OpSys.h" +#include <QJsonArray> void OneSixLibrary::finalize() { - QStringList parts = m_name.split ( ':' ); + QStringList parts = m_name.split(':'); QString relative = parts[0]; - relative.replace ( '.','/' ); + relative.replace('.', '/'); relative += '/' + parts[1] + '/' + parts[2] + '/' + parts[1] + '-' + parts[2]; - - if ( !m_is_native ) + + if (!m_is_native) relative += ".jar"; else { - if ( m_native_suffixes.contains ( currentSystem ) ) + if (m_native_suffixes.contains(currentSystem)) { relative += "-" + m_native_suffixes[currentSystem] + ".jar"; } @@ -22,30 +23,30 @@ void OneSixLibrary::finalize() relative += ".jar"; } } - + m_decentname = parts[1]; m_decentversion = parts[2]; m_storage_path = relative; - m_download_path = m_base_url + relative; - - if ( m_rules.empty() ) + m_download_url = m_base_url + relative; + + if (m_rules.empty()) { m_is_active = true; } else { RuleAction result = Disallow; - for ( auto rule: m_rules ) + for (auto rule : m_rules) { - RuleAction temp = rule->apply ( this ); - if ( temp != Defer ) + RuleAction temp = rule->apply(this); + if (temp != Defer) result = temp; } - m_is_active = ( result == Allow ); + m_is_active = (result == Allow); } - if ( m_is_native ) + if (m_is_native) { - m_is_active = m_is_active && m_native_suffixes.contains ( currentSystem ); + m_is_active = m_is_active && m_native_suffixes.contains(currentSystem); m_decenttype = "Native"; } else @@ -54,11 +55,11 @@ void OneSixLibrary::finalize() } } -void OneSixLibrary::setName ( QString name ) +void OneSixLibrary::setName(QString name) { m_name = name; } -void OneSixLibrary::setBaseUrl ( QString base_url ) +void OneSixLibrary::setBaseUrl(QString base_url) { m_base_url = base_url; } @@ -66,12 +67,12 @@ void OneSixLibrary::setIsNative() { m_is_native = true; } -void OneSixLibrary::addNative ( OpSys os, QString suffix ) +void OneSixLibrary::addNative(OpSys os, QString suffix) { m_is_native = true; m_native_suffixes[os] = suffix; } -void OneSixLibrary::setRules ( QList< QSharedPointer< Rule > > rules ) +void OneSixLibrary::setRules(QList<QSharedPointer<Rule>> rules) { m_rules = rules; } @@ -83,11 +84,66 @@ bool OneSixLibrary::isNative() { return m_is_native; } -QString OneSixLibrary::downloadPath() +QString OneSixLibrary::downloadUrl() { - return m_download_path; + if(m_absolute_url.size()) + return m_absolute_url; + return m_download_url; } QString OneSixLibrary::storagePath() { return m_storage_path; } + +void OneSixLibrary::setAbsoluteUrl(QString absolute_url) +{ + m_absolute_url = absolute_url; +} + +QString OneSixLibrary::absoluteUrl() +{ + return m_absolute_url; +} + +QJsonObject OneSixLibrary::toJson() +{ + QJsonObject libRoot; + libRoot.insert("name", m_name); + if(m_absolute_url.size()) + libRoot.insert("MMC-absulute_url", m_absolute_url); + if(m_base_url != "https://s3.amazonaws.com/Minecraft.Download/libraries/") + libRoot.insert("url", m_base_url); + if (isNative() && m_native_suffixes.size()) + { + QJsonObject nativeList; + auto iter = m_native_suffixes.begin(); + while (iter != m_native_suffixes.end()) + { + nativeList.insert(OpSys_toString(iter.key()), iter.value()); + iter++; + } + libRoot.insert("natives", nativeList); + } + if (isNative() && extract_excludes.size()) + { + QJsonArray excludes; + QJsonObject extract; + for (auto exclude : extract_excludes) + { + excludes.append(exclude); + } + extract.insert("exclude", excludes); + libRoot.insert("extract", extract); + } + if (m_rules.size()) + { + QJsonArray allRules; + for (auto &rule : m_rules) + { + QJsonObject ruleObj = rule->toJson(); + allRules.append(ruleObj); + } + libRoot.insert("rules", allRules); + } + return libRoot; +} diff --git a/logic/OneSixLibrary.h b/logic/OneSixLibrary.h index ac16d3d3..f3106483 100644 --- a/logic/OneSixLibrary.h +++ b/logic/OneSixLibrary.h @@ -3,6 +3,7 @@ #include <QStringList> #include <QMap> #include <QSharedPointer> +#include <QJsonObject> #include "OpSys.h" class Rule; @@ -12,9 +13,13 @@ class OneSixLibrary private: // basic values used internally (so far) QString m_name; - QString m_base_url; + QString m_base_url = "https://s3.amazonaws.com/Minecraft.Download/libraries/"; QList<QSharedPointer<Rule> > m_rules; - + + // custom values + /// absolute URL. takes precedence over m_download_path, if defined + QString m_absolute_url; + // derived values used for real things /// a decent name fit for display QString m_decentname; @@ -25,11 +30,11 @@ private: /// where to store the lib locally QString m_storage_path; /// where to download the lib from - QString m_download_path; + QString m_download_url; /// is this lib actually active on the current OS? - bool m_is_active; + bool m_is_active = false; /// is the library a native? - bool m_is_native; + bool m_is_native = false; /// native suffixes per OS QMap<OpSys, QString> m_native_suffixes; public: @@ -39,12 +44,11 @@ public: /// Constructor OneSixLibrary(QString name) { - m_is_native = false; - m_is_active = false; m_name = name; - m_base_url = "https://s3.amazonaws.com/Minecraft.Download/libraries/"; } + QJsonObject toJson(); + /** * finalize the library, processing the input values into derived values and state * @@ -84,7 +88,11 @@ public: /// Returns true if the library is native bool isNative(); /// Get the URL to download the library from - QString downloadPath(); + QString downloadUrl(); /// Get the relative path where the library should be saved QString storagePath(); + + /// set an absolute URL for the library. This is an MMC extension. + void setAbsoluteUrl(QString absolute_url); + QString absoluteUrl(); }; diff --git a/logic/OneSixRule.cpp b/logic/OneSixRule.cpp index 85f7d434..545cd641 100644 --- a/logic/OneSixRule.cpp +++ b/logic/OneSixRule.cpp @@ -1,10 +1,72 @@ #include "OneSixRule.h" +#include <QJsonObject> +#include <QJsonArray> + +QList<QSharedPointer<Rule>> rulesFromJsonV4(QJsonObject &objectWithRules) +{ + QList<QSharedPointer<Rule>> rules; + auto rulesVal = objectWithRules.value("rules"); + if (!rulesVal.isArray()) + return rules; + + QJsonArray ruleList = rulesVal.toArray(); + for (auto ruleVal : ruleList) + { + QSharedPointer<Rule> rule; + if (!ruleVal.isObject()) + continue; + auto ruleObj = ruleVal.toObject(); + auto actionVal = ruleObj.value("action"); + if (!actionVal.isString()) + continue; + auto action = RuleAction_fromString(actionVal.toString()); + if (action == Defer) + continue; + + auto osVal = ruleObj.value("os"); + if (!osVal.isObject()) + { + // add a new implicit action rule + rules.append(ImplicitRule::create(action)); + continue; + } + + auto osObj = osVal.toObject(); + auto osNameVal = osObj.value("name"); + if (!osNameVal.isString()) + continue; + OpSys requiredOs = OpSys_fromString(osNameVal.toString()); + QString versionRegex = osObj.value("version").toString(); + // add a new OS rule + rules.append(OsRule::create(action, requiredOs, versionRegex)); + } +} + +QJsonObject ImplicitRule::toJson() +{ + QJsonObject ruleObj; + ruleObj.insert("action", m_result == Allow ? QString("allow") : QString("disallow")); + return ruleObj; +} + +QJsonObject OsRule::toJson() +{ + QJsonObject ruleObj; + ruleObj.insert("action", m_result == Allow ? QString("allow") : QString("disallow")); + QJsonObject osObj; + { + osObj.insert("name", OpSys_toString(m_system)); + osObj.insert("version", m_version_regexp); + } + ruleObj.insert("os", osObj); + return ruleObj; +} RuleAction RuleAction_fromString(QString name) { - if(name == "allow") + if (name == "allow") return Allow; - if(name == "disallow") + if (name == "disallow") return Disallow; return Defer; }
\ No newline at end of file diff --git a/logic/OneSixRule.h b/logic/OneSixRule.h index 465c963f..23d20ff4 100644 --- a/logic/OneSixRule.h +++ b/logic/OneSixRule.h @@ -1,8 +1,6 @@ #pragma once #include <QString> #include <QSharedPointer> - -class OneSixLibrary; #include "OneSixLibrary.h" enum RuleAction @@ -13,6 +11,7 @@ enum RuleAction }; RuleAction RuleAction_fromString(QString); +QList<QSharedPointer<Rule>> rulesFromJsonV4(QJsonObject &objectWithRules); class Rule { @@ -23,6 +22,7 @@ public: Rule(RuleAction result) :m_result(result) {} virtual ~Rule(){}; + virtual QJsonObject toJson() = 0; RuleAction apply(OneSixLibrary * parent) { if(applies(parent)) @@ -47,6 +47,7 @@ protected: OsRule(RuleAction result, OpSys system, QString version_regexp) : Rule(result), m_system(system), m_version_regexp(version_regexp) {} public: + virtual QJsonObject toJson(); static QSharedPointer<OsRule> create(RuleAction result, OpSys system, QString version_regexp) { return QSharedPointer<OsRule> (new OsRule(result, system, version_regexp)); @@ -63,6 +64,7 @@ protected: ImplicitRule(RuleAction result) : Rule(result) {} public: + virtual QJsonObject toJson(); static QSharedPointer<ImplicitRule> create(RuleAction result) { return QSharedPointer<ImplicitRule> (new ImplicitRule(result)); diff --git a/logic/OneSixUpdate.cpp b/logic/OneSixUpdate.cpp index 298ad28a..d0af8b93 100644 --- a/logic/OneSixUpdate.cpp +++ b/logic/OneSixUpdate.cpp @@ -3,7 +3,7 @@ * 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 @@ -26,20 +26,20 @@ #include "BaseInstance.h" #include "lists/MinecraftVersionList.h" -#include "VersionFactory.h" #include "OneSixVersion.h" #include "OneSixLibrary.h" #include "OneSixInstance.h" #include "pathutils.h" - -OneSixUpdate::OneSixUpdate(BaseInstance *inst, QObject *parent):BaseUpdate(inst, parent){} +OneSixUpdate::OneSixUpdate(BaseInstance *inst, QObject *parent) : BaseUpdate(inst, parent) +{ +} void OneSixUpdate::executeTask() { QString intendedVersion = m_inst->intendedVersionId(); - + // Make directories QDir mcDir(m_inst->minecraftRoot()); if (!mcDir.exists() && !mcDir.mkpath(".")) @@ -47,17 +47,18 @@ void OneSixUpdate::executeTask() emitFailed("Failed to create bin folder."); return; } - + // Get a pointer to the version object that corresponds to the instance's version. - targetVersion = MMC->minecraftlist()->findVersion(intendedVersion).dynamicCast<MinecraftVersion>(); - if(targetVersion == nullptr) + targetVersion = + MMC->minecraftlist()->findVersion(intendedVersion).dynamicCast<MinecraftVersion>(); + if (targetVersion == nullptr) { // don't do anything if it was invalid emitSucceeded(); return; } - - if(m_inst->shouldUpdate()) + + if (m_inst->shouldUpdate()) { versionFileStart(); } @@ -70,62 +71,65 @@ void OneSixUpdate::executeTask() void OneSixUpdate::versionFileStart() { setStatus("Getting the version files from Mojang."); - + QString urlstr("http://s3.amazonaws.com/Minecraft.Download/versions/"); urlstr += targetVersion->descriptor() + "/" + targetVersion->descriptor() + ".json"; auto job = new DownloadJob("Version index"); job->add(QUrl(urlstr)); specificVersionDownloadJob.reset(job); - connect(specificVersionDownloadJob.data(), SIGNAL(succeeded()), SLOT(versionFileFinished())); + connect(specificVersionDownloadJob.data(), SIGNAL(succeeded()), + SLOT(versionFileFinished())); connect(specificVersionDownloadJob.data(), SIGNAL(failed()), SLOT(versionFileFailed())); - connect(specificVersionDownloadJob.data(), SIGNAL(progress(qint64,qint64)), SIGNAL(progress(qint64,qint64))); + connect(specificVersionDownloadJob.data(), SIGNAL(progress(qint64, qint64)), + SIGNAL(progress(qint64, qint64))); specificVersionDownloadJob->start(); } void OneSixUpdate::versionFileFinished() { DownloadPtr DlJob = specificVersionDownloadJob->first(); - OneSixInstance * inst = (OneSixInstance *) m_inst; - + OneSixInstance *inst = (OneSixInstance *)m_inst; + QString version_id = targetVersion->descriptor(); QString inst_dir = m_inst->instanceRoot(); // save the version file in $instanceId/version.json { - QString version1 = PathCombine(inst_dir, "/version.json"); + QString version1 = PathCombine(inst_dir, "/version.json"); ensureFilePathExists(version1); // FIXME: detect errors here, download to a temp file, swap - QSaveFile vfile1 (version1); - if(!vfile1.open(QIODevice::Truncate | QIODevice::WriteOnly )) + QSaveFile vfile1(version1); + if (!vfile1.open(QIODevice::Truncate | QIODevice::WriteOnly)) { emitFailed("Can't open " + version1 + " for writing."); return; } auto data = DlJob.dynamicCast<ByteArrayDownload>()->m_data; qint64 actual = 0; - if((actual = vfile1.write(data)) != data.size()) + if ((actual = vfile1.write(data)) != data.size()) { - emitFailed("Failed to write into " + version1 + ". Written " + actual + " out of " + data.size() + '.'); + emitFailed("Failed to write into " + version1 + ". Written " + actual + " out of " + + data.size() + '.'); return; } - if(!vfile1.commit()) + if (!vfile1.commit()) { emitFailed("Can't commit changes to " + version1); return; } } - + // the version is downloaded safely. update is 'done' at this point m_inst->setShouldUpdate(false); - + // delete any custom version inside the instance (it's no longer relevant, we did an update) - QString custom = PathCombine(inst_dir, "/custom.json"); + QString custom = PathCombine(inst_dir, "/custom.json"); QFile finfo(custom); - if(finfo.exists()) + if (finfo.exists()) { finfo.remove(); } inst->reloadFullVersion(); - + jarlibStart(); } @@ -136,42 +140,44 @@ void OneSixUpdate::versionFileFailed() void OneSixUpdate::jarlibStart() { - OneSixInstance * inst = (OneSixInstance *) m_inst; + OneSixInstance *inst = (OneSixInstance *)m_inst; bool successful = inst->reloadFullVersion(); - if(!successful) + if (!successful) { - emitFailed("Failed to load the version description file (version.json). It might be corrupted, missing or simply too new."); + emitFailed("Failed to load the version description file (version.json). It might be " + "corrupted, missing or simply too new."); return; } - + QSharedPointer<OneSixVersion> version = inst->getFullVersion(); - + // download the right jar, save it in versions/$version/$version.jar QString urlstr("http://s3.amazonaws.com/Minecraft.Download/versions/"); urlstr += version->id + "/" + version->id + ".jar"; - QString targetstr ("versions/"); + QString targetstr("versions/"); targetstr += version->id + "/" + version->id + ".jar"; - + auto job = new DownloadJob("Libraries for instance " + inst->name()); job->add(QUrl(urlstr), targetstr); jarlibDownloadJob.reset(job); - + auto libs = version->getActiveNativeLibs(); libs.append(version->getActiveNormalLibs()); - + auto metacache = MMC->metacache(); - for(auto lib: libs) + for (auto lib : libs) { - QString download_path = lib->downloadPath(); + QString download_path = lib->downloadUrl(); auto entry = metacache->resolveEntry("libraries", lib->storagePath()); - if(entry->stale) + if (entry->stale) { jarlibDownloadJob->add(download_path, entry); } } connect(jarlibDownloadJob.data(), SIGNAL(succeeded()), SLOT(jarlibFinished())); connect(jarlibDownloadJob.data(), SIGNAL(failed()), SLOT(jarlibFailed())); - connect(jarlibDownloadJob.data(), SIGNAL(progress(qint64,qint64)), SIGNAL(progress(qint64,qint64))); + connect(jarlibDownloadJob.data(), SIGNAL(progress(qint64, qint64)), + SIGNAL(progress(qint64, qint64))); jarlibDownloadJob->start(); } @@ -185,4 +191,3 @@ void OneSixUpdate::jarlibFailed() { emitFailed("Failed to download the binary garbage. Try again. Maybe. IF YOU DARE"); } - diff --git a/logic/OneSixVersion.cpp b/logic/OneSixVersion.cpp index dc1b5d6f..663d903a 100644 --- a/logic/OneSixVersion.cpp +++ b/logic/OneSixVersion.cpp @@ -1,10 +1,201 @@ #include "OneSixVersion.h" #include "OneSixLibrary.h" +#include "OneSixRule.h" -QList<QSharedPointer<OneSixLibrary> > OneSixVersion::getActiveNormalLibs() +QSharedPointer<OneSixVersion> fromJsonV4(QJsonObject root, + QSharedPointer<OneSixVersion> fullVersion) { - QList<QSharedPointer<OneSixLibrary> > output; - for ( auto lib: libraries ) + fullVersion->id = root.value("id").toString(); + + fullVersion->mainClass = root.value("mainClass").toString(); + auto procArgsValue = root.value("processArguments"); + if (procArgsValue.isString()) + { + fullVersion->processArguments = procArgsValue.toString(); + QString toCompare = fullVersion->processArguments.toLower(); + if (toCompare == "legacy") + { + fullVersion->minecraftArguments = " ${auth_player_name} ${auth_session}"; + } + else if (toCompare == "username_session") + { + fullVersion->minecraftArguments = + "--username ${auth_player_name} --session ${auth_session}"; + } + else if (toCompare == "username_session_version") + { + fullVersion->minecraftArguments = "--username ${auth_player_name} " + "--session ${auth_session} " + "--version ${profile_name}"; + } + } + + auto minecraftArgsValue = root.value("minecraftArguments"); + if (minecraftArgsValue.isString()) + { + fullVersion->minecraftArguments = minecraftArgsValue.toString(); + } + + auto minecraftTypeValue = root.value("type"); + if (minecraftTypeValue.isString()) + { + fullVersion->type = minecraftTypeValue.toString(); + } + + fullVersion->releaseTime = root.value("releaseTime").toString(); + fullVersion->time = root.value("time").toString(); + + // Iterate through the list, if it's a list. + auto librariesValue = root.value("libraries"); + if (!librariesValue.isArray()) + return fullVersion; + + QJsonArray libList = root.value("libraries").toArray(); + for (auto libVal : libList) + { + if (!libVal.isObject()) + { + continue; + } + + QJsonObject libObj = libVal.toObject(); + + // Library name + auto nameVal = libObj.value("name"); + if (!nameVal.isString()) + continue; + QSharedPointer<OneSixLibrary> library(new OneSixLibrary(nameVal.toString())); + + auto urlVal = libObj.value("url"); + if (urlVal.isString()) + { + library->setBaseUrl(urlVal.toString()); + } + auto urlAbsVal = libObj.value("MMC-absulute_url"); + if (urlAbsVal.isString()) + { + library->setAbsoluteUrl(urlAbsVal.toString()); + } + // Extract excludes (if any) + auto extractVal = libObj.value("extract"); + if (extractVal.isObject()) + { + QStringList excludes; + auto extractObj = extractVal.toObject(); + auto excludesVal = extractObj.value("exclude"); + if (excludesVal.isArray()) + { + auto excludesList = excludesVal.toArray(); + for (auto excludeVal : excludesList) + { + if (excludeVal.isString()) + excludes.append(excludeVal.toString()); + } + library->extract_excludes = excludes; + } + } + + auto nativesVal = libObj.value("natives"); + if (nativesVal.isObject()) + { + library->setIsNative(); + auto nativesObj = nativesVal.toObject(); + auto iter = nativesObj.begin(); + while (iter != nativesObj.end()) + { + auto osType = OpSys_fromString(iter.key()); + if (osType == Os_Other) + continue; + if (!iter.value().isString()) + continue; + library->addNative(osType, iter.value().toString()); + iter++; + } + } + library->setRules(rulesFromJsonV4(libObj)); + library->finalize(); + fullVersion->libraries.append(library); + } + return fullVersion; +} + +QSharedPointer<OneSixVersion> OneSixVersion::fromJson(QJsonObject root) +{ + QSharedPointer<OneSixVersion> readVersion(new OneSixVersion()); + int launcher_ver = readVersion->minimumLauncherVersion = + root.value("minimumLauncherVersion").toDouble(); + + // ADD MORE HERE :D + if (launcher_ver > 0 && launcher_ver <= 7) + return fromJsonV4(root, readVersion); + else + { + return QSharedPointer<OneSixVersion>(); + } +} + +QSharedPointer<OneSixVersion> OneSixVersion::fromFile(QString filepath) +{ + QFile file(filepath); + if (!file.open(QIODevice::ReadOnly)) + { + return QSharedPointer<OneSixVersion>(); + } + + auto data = file.readAll(); + QJsonParseError jsonError; + QJsonDocument jsonDoc = QJsonDocument::fromJson(data, &jsonError); + + if (jsonError.error != QJsonParseError::NoError) + { + return QSharedPointer<OneSixVersion>(); + } + + if (!jsonDoc.isObject()) + { + return QSharedPointer<OneSixVersion>(); + } + QJsonObject root = jsonDoc.object(); + auto version = fromJson(root); + version->original_file = filepath; + return version; +} + +bool OneSixVersion::toOriginalFile() +{ + if (original_file.isEmpty()) + return false; + QSaveFile file(original_file); + if (!file.open(QIODevice::WriteOnly)) + { + return false; + } + // serialize base attributes (those we care about anyway) + QJsonObject root; + root.insert("minecraftArguments", minecraftArguments); + root.insert("mainClass", mainClass); + root.insert("minimumLauncherVersion", minimumLauncherVersion); + root.insert("time", time); + root.insert("id", id); + root.insert("type", type); + // screw processArguments + root.insert("releaseTime", releaseTime); + QJsonArray libarray; + for(const auto & lib: libraries) + { + libarray.append(lib->toJson()); + } + if(libarray.count()) + root.insert("libraries", libarray); + QJsonDocument doc(root); + file.write(doc.toJson()); + return file.commit(); +} + +QList<QSharedPointer<OneSixLibrary>> OneSixVersion::getActiveNormalLibs() +{ + QList<QSharedPointer<OneSixLibrary>> output; + for (auto lib : libraries) { if (lib->isActive() && !lib->isNative()) { @@ -14,10 +205,10 @@ QList<QSharedPointer<OneSixLibrary> > OneSixVersion::getActiveNormalLibs() return output; } -QList<QSharedPointer<OneSixLibrary> > OneSixVersion::getActiveNativeLibs() +QList<QSharedPointer<OneSixLibrary>> OneSixVersion::getActiveNativeLibs() { - QList<QSharedPointer<OneSixLibrary> > output; - for ( auto lib: libraries ) + QList<QSharedPointer<OneSixLibrary>> output; + for (auto lib : libraries) { if (lib->isActive() && lib->isNative()) { @@ -27,41 +218,50 @@ QList<QSharedPointer<OneSixLibrary> > OneSixVersion::getActiveNativeLibs() return output; } +void OneSixVersion::externalUpdateStart() +{ + beginResetModel(); +} + +void OneSixVersion::externalUpdateFinish() +{ + endResetModel(); +} -QVariant OneSixVersion::data(const QModelIndex& index, int role) const +QVariant OneSixVersion::data(const QModelIndex &index, int role) const { - if(!index.isValid()) + if (!index.isValid()) return QVariant(); - + int row = index.row(); int column = index.column(); - - if(row < 0 || row >= libraries.size()) + + if (row < 0 || row >= libraries.size()) return QVariant(); - - if(role == Qt::DisplayRole) + + if (role == Qt::DisplayRole) { - switch(column) + switch (column) { - case 0: - return libraries[row]->name(); - case 1: - return libraries[row]->type(); - case 2: - return libraries[row]->version(); - default: - return QVariant(); + case 0: + return libraries[row]->name(); + case 1: + return libraries[row]->type(); + case 2: + return libraries[row]->version(); + default: + return QVariant(); } } return QVariant(); } -Qt::ItemFlags OneSixVersion::flags(const QModelIndex& index) const +Qt::ItemFlags OneSixVersion::flags(const QModelIndex &index) const { - if(!index.isValid()) + if (!index.isValid()) return Qt::NoItemFlags; int row = index.row(); - if(libraries[row]->isActive()) + if (libraries[row]->isActive()) { return Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemNeverHasChildren; } @@ -69,11 +269,10 @@ Qt::ItemFlags OneSixVersion::flags(const QModelIndex& index) const { return Qt::ItemNeverHasChildren; } - //return QAbstractListModel::flags(index); + // return QAbstractListModel::flags(index); } - -QVariant OneSixVersion::headerData ( int section, Qt::Orientation orientation, int role ) const +QVariant OneSixVersion::headerData(int section, Qt::Orientation orientation, int role) const { if (role != Qt::DisplayRole || orientation != Qt::Horizontal) return QVariant(); @@ -90,12 +289,12 @@ QVariant OneSixVersion::headerData ( int section, Qt::Orientation orientation, i } } -int OneSixVersion::rowCount(const QModelIndex& parent) const +int OneSixVersion::rowCount(const QModelIndex &parent) const { return libraries.size(); } -int OneSixVersion::columnCount(const QModelIndex& parent) const +int OneSixVersion::columnCount(const QModelIndex &parent) const { - return 3; + return 3; } diff --git a/logic/OneSixVersion.h b/logic/OneSixVersion.h index 6a6a5b4b..69268ecf 100644 --- a/logic/OneSixVersion.h +++ b/logic/OneSixVersion.h @@ -4,13 +4,33 @@ class OneSixLibrary; class OneSixVersion : public QAbstractListModel { + // Things required to implement the Qt list model public: - virtual QVariant data ( const QModelIndex& index, int role = Qt::DisplayRole ) const; - virtual int rowCount ( const QModelIndex& parent = QModelIndex() ) const; - virtual QVariant headerData ( int section, Qt::Orientation orientation, int role = Qt::DisplayRole ) const; - virtual int columnCount ( const QModelIndex& parent ) const; - virtual Qt::ItemFlags flags(const QModelIndex& index) const; + virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; + virtual int rowCount(const QModelIndex &parent = QModelIndex()) const; + virtual QVariant headerData(int section, Qt::Orientation orientation, + int role = Qt::DisplayRole) const; + virtual int columnCount(const QModelIndex &parent) const; + virtual Qt::ItemFlags flags(const QModelIndex &index) const; + + // serialization/deserialization +public: + bool toOriginalFile(); + static QSharedPointer<OneSixVersion> fromJson(QJsonObject root); + static QSharedPointer<OneSixVersion> fromFile(QString filepath); + public: + QList<QSharedPointer<OneSixLibrary>> getActiveNormalLibs(); + QList<QSharedPointer<OneSixLibrary>> getActiveNativeLibs(); + // called when something starts/stops messing with the object + // FIXME: these are ugly in every possible way. + void externalUpdateStart(); + void externalUpdateFinish(); + + // data members +public: + /// file this was read from. blank, if none + QString original_file; /// the ID - determines which jar to use! ACTUALLY IMPORTANT! QString id; /// Last updated time - as a string @@ -23,26 +43,27 @@ public: * DEPRECATED: Old versions of the new vanilla launcher used this * ex: "username_session_version" */ - QString processArguments; + 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) + * the minimum launcher version required by this version ... current is 4 (at point of + * writing) */ - int minimumLauncherVersion; + int minimumLauncherVersion = 0xDEADBEEF; /** * The main class to load first */ QString mainClass; - + /// the list of libs - both active and inactive, native and java - QList<QSharedPointer<OneSixLibrary> > libraries; - + QList<QSharedPointer<OneSixLibrary>> libraries; + /* FIXME: add support for those rules here? Looks like a pile of quick hacks to me though. @@ -58,18 +79,11 @@ public: } } ], - "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!" + "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<Rule> rules; - -public: - - OneSixVersion() - { - minimumLauncherVersion = 0xDEADBEEF; - } - - QList<QSharedPointer<OneSixLibrary> > getActiveNormalLibs(); - QList<QSharedPointer<OneSixLibrary> > getActiveNativeLibs(); + + }; diff --git a/logic/OpSys.cpp b/logic/OpSys.cpp index 559479fd..f101fd08 100644 --- a/logic/OpSys.cpp +++ b/logic/OpSys.cpp @@ -9,4 +9,15 @@ OpSys OpSys_fromString(QString name) if(name == "osx") return Os_OSX; return Os_Other; +} + +QString OpSys_toString(OpSys name) +{ + switch(name) + { + case Os_Linux: return "linux"; + case Os_OSX: return "osx"; + case Os_Windows: return "windows"; + default: return "other"; + } }
\ No newline at end of file diff --git a/logic/OpSys.h b/logic/OpSys.h index c68c437a..aaa2eb65 100644 --- a/logic/OpSys.h +++ b/logic/OpSys.h @@ -9,6 +9,7 @@ enum OpSys }; OpSys OpSys_fromString(QString); +QString OpSys_toString(OpSys); #ifdef Q_OS_WIN32 #define currentSystem Os_Windows diff --git a/logic/VersionFactory.cpp b/logic/VersionFactory.cpp deleted file mode 100644 index 4fa5ad3f..00000000 --- a/logic/VersionFactory.cpp +++ /dev/null @@ -1,196 +0,0 @@ -#include "VersionFactory.h" -#include "OneSixVersion.h" -#include "OneSixRule.h" - -// Library rules (if any) -QList<QSharedPointer<Rule> > FullVersionFactory::parse4rules(QJsonObject & baseObj) -{ - QList<QSharedPointer<Rule> > rules; - auto rulesVal = baseObj.value("rules"); - if(rulesVal.isArray()) - { - QJsonArray ruleList = rulesVal.toArray(); - for(auto ruleVal : ruleList) - { - QSharedPointer<Rule> rule; - if(!ruleVal.isObject()) - continue; - auto ruleObj = ruleVal.toObject(); - auto actionVal = ruleObj.value("action"); - if(!actionVal.isString()) - continue; - auto action = RuleAction_fromString(actionVal.toString()); - if(action == Defer) - continue; - - auto osVal = ruleObj.value("os"); - if(!osVal.isObject()) - { - // add a new implicit action rule - rules.append(ImplicitRule::create(action)); - } - else - { - auto osObj = osVal.toObject(); - auto osNameVal = osObj.value("name"); - if(!osNameVal.isString()) - continue; - OpSys requiredOs = OpSys_fromString(osNameVal.toString()); - QString versionRegex = osObj.value("version").toString(); - // add a new OS rule - rules.append(OsRule::create(action, requiredOs, versionRegex)); - } - } - } - return rules; -} - - -QSharedPointer<OneSixVersion> FullVersionFactory::parse4(QJsonObject root, QSharedPointer<OneSixVersion> fullVersion) -{ - fullVersion->id = root.value("id").toString(); - - fullVersion->mainClass = root.value("mainClass").toString(); - auto procArgsValue = root.value("processArguments"); - if(procArgsValue.isString()) - { - fullVersion->processArguments = procArgsValue.toString(); - QString toCompare = fullVersion->processArguments.toLower(); - if(toCompare == "legacy") - { - fullVersion->minecraftArguments = " ${auth_player_name} ${auth_session}"; - } - else if(toCompare == "username_session") - { - fullVersion->minecraftArguments = "--username ${auth_player_name} --session ${auth_session}"; - } - else if(toCompare == "username_session_version") - { - fullVersion->minecraftArguments = "--username ${auth_player_name} --session ${auth_session} --version ${profile_name}"; - } - } - - auto minecraftArgsValue = root.value("minecraftArguments"); - if(minecraftArgsValue.isString()) - { - fullVersion->minecraftArguments = minecraftArgsValue.toString(); - } - - auto minecraftTypeValue = root.value("type"); - if(minecraftTypeValue.isString()) - { - fullVersion->type = minecraftTypeValue.toString(); - } - - fullVersion->releaseTime = root.value("releaseTime").toString(); - fullVersion->time = root.value("time").toString(); - - // Iterate through the list, if it's a list. - auto librariesValue = root.value("libraries"); - if(!librariesValue.isArray()) - return fullVersion; - - QJsonArray libList = root.value("libraries").toArray(); - for (auto libVal : libList) - { - if (!libVal.isObject()) - { - continue; - } - - QJsonObject libObj = libVal.toObject(); - - // Library name - auto nameVal = libObj.value("name"); - if(!nameVal.isString()) - continue; - QSharedPointer<OneSixLibrary> library(new OneSixLibrary(nameVal.toString())); - - auto urlVal = libObj.value("url"); - if(urlVal.isString()) - { - library->setBaseUrl(urlVal.toString()); - } - - // Extract excludes (if any) - auto extractVal = libObj.value("extract"); - if(extractVal.isObject()) - { - QStringList excludes; - auto extractObj = extractVal.toObject(); - auto excludesVal = extractObj.value("exclude"); - if(!excludesVal.isArray()) - goto SKIP_EXTRACTS; - auto excludesList = excludesVal.toArray(); - for(auto excludeVal : excludesList) - { - if(excludeVal.isString()) - excludes.append(excludeVal.toString()); - } - library->extract_excludes = excludes; - } - SKIP_EXTRACTS: - - auto nativesVal = libObj.value("natives"); - if(nativesVal.isObject()) - { - library->setIsNative(); - auto nativesObj = nativesVal.toObject(); - auto iter = nativesObj.begin(); - while(iter != nativesObj.end()) - { - auto osType = OpSys_fromString(iter.key()); - if(osType == Os_Other) - continue; - if(!iter.value().isString()) - continue; - library->addNative(osType, iter.value().toString()); - iter++; - } - } - library->setRules(parse4rules(libObj)); - library->finalize(); - fullVersion->libraries.append(library); - } - return fullVersion; -} - -QSharedPointer<OneSixVersion> FullVersionFactory::parse(QByteArray data) -{ - QSharedPointer<OneSixVersion> readVersion(new OneSixVersion()); - - QJsonParseError jsonError; - QJsonDocument jsonDoc = QJsonDocument::fromJson(data, &jsonError); - - if (jsonError.error != QJsonParseError::NoError) - { - error_string = QString( "Error reading version file :") + " " + jsonError.errorString(); - m_error = FullVersionFactory::ParseError; - return QSharedPointer<OneSixVersion>(); - } - - if(!jsonDoc.isObject()) - { - error_string = "Error reading version file."; - m_error = FullVersionFactory::ParseError; - return QSharedPointer<OneSixVersion>(); - } - QJsonObject root = jsonDoc.object(); - - int launcher_ver = readVersion->minimumLauncherVersion = root.value("minimumLauncherVersion").toDouble(); - // ADD MORE HERE :D - if(launcher_ver > 0 && launcher_ver <= 7) - return parse4(root, readVersion); - else - { - error_string = "Version file was for an unrecognized launcher version. RIP"; - m_error = FullVersionFactory::UnsupportedVersion; - return QSharedPointer<OneSixVersion>(); - } -} - - -FullVersionFactory::FullVersionFactory() -{ - m_error = FullVersionFactory::AllOK; -} diff --git a/logic/VersionFactory.h b/logic/VersionFactory.h deleted file mode 100644 index 0c0ee2d4..00000000 --- a/logic/VersionFactory.h +++ /dev/null @@ -1,24 +0,0 @@ -#pragma once -#include <QtCore> - -struct OneSixVersion; -class Rule; - -class FullVersionFactory -{ -public: - enum Error - { - AllOK, // all parsed OK - ParseError, // the file was corrupted somehow - UnsupportedVersion // the file was meant for a launcher version we don't support (yet) - } m_error; - QString error_string; - -public: - FullVersionFactory(); - QSharedPointer<OneSixVersion> parse(QByteArray data); -private: - QSharedPointer<OneSixVersion> parse4(QJsonObject root, QSharedPointer<OneSixVersion> product); - QList<QSharedPointer<Rule> > parse4rules(QJsonObject & baseObj); -};
\ No newline at end of file diff --git a/logic/lists/ForgeVersionList.cpp b/logic/lists/ForgeVersionList.cpp index 412c04fe..721f2c0a 100644 --- a/logic/lists/ForgeVersionList.cpp +++ b/logic/lists/ForgeVersionList.cpp @@ -3,7 +3,7 @@ * 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 @@ -25,10 +25,8 @@ #define JSON_URL "http://files.minecraftforge.net/minecraftforge/json" - -ForgeVersionList::ForgeVersionList(QObject* parent): BaseVersionList(parent) +ForgeVersionList::ForgeVersionList(QObject *parent) : BaseVersionList(parent) { - } Task *ForgeVersionList::getLoadTask() @@ -51,19 +49,19 @@ int ForgeVersionList::count() const return m_vlist.count(); } -int ForgeVersionList::columnCount(const QModelIndex& parent) const +int ForgeVersionList::columnCount(const QModelIndex &parent) const { - return 3; + return 3; } QVariant ForgeVersionList::data(const QModelIndex &index, int role) const { if (!index.isValid()) return QVariant(); - + if (index.row() > count()) return QVariant(); - + auto version = m_vlist[index.row()].dynamicCast<ForgeVersion>(); switch (role) { @@ -72,22 +70,22 @@ QVariant ForgeVersionList::data(const QModelIndex &index, int role) const { case 0: return version->name(); - + case 1: return version->mcver; - + case 2: return version->typeString(); default: return QVariant(); } - + case Qt::ToolTipRole: return version->descriptor(); - + case VersionPointerRole: return qVariantFromValue(m_vlist[index.row()]); - + default: return QVariant(); } @@ -102,33 +100,33 @@ QVariant ForgeVersionList::headerData(int section, Qt::Orientation orientation, { case 0: return "Version"; - + case 1: return "Minecraft"; - + case 2: return "Type"; - + default: return QVariant(); } - + case Qt::ToolTipRole: switch (section) { case 0: return "The name of the version."; - + case 1: return "Minecraft version"; - + case 2: return "The version's type."; - + default: return QVariant(); } - + default: return QVariant(); } @@ -139,7 +137,7 @@ BaseVersionPtr ForgeVersionList::getLatestStable() const return BaseVersionPtr(); } -void ForgeVersionList::updateListData(QList<BaseVersionPtr > versions) +void ForgeVersionList::updateListData(QList<BaseVersionPtr> versions) { beginResetModel(); m_vlist = versions; @@ -154,101 +152,112 @@ void ForgeVersionList::sort() // NO-OP for now } - -ForgeListLoadTask::ForgeListLoadTask(ForgeVersionList* vlist): Task() +ForgeListLoadTask::ForgeListLoadTask(ForgeVersionList *vlist) : Task() { m_list = vlist; } - void ForgeListLoadTask::executeTask() { auto job = new DownloadJob("Version index"); - job->add(QUrl(JSON_URL)); + // we do not care if the version is stale or not. + auto forgeListEntry = MMC->metacache()->resolveEntry("minecraftforge", "list.json"); + job->add(QUrl(JSON_URL), forgeListEntry); listJob.reset(job); connect(listJob.data(), SIGNAL(succeeded()), SLOT(list_downloaded())); connect(listJob.data(), SIGNAL(failed()), SLOT(versionFileFailed())); - connect(listJob.data(), SIGNAL(progress(qint64,qint64)), SIGNAL(progress(qint64,qint64))); + connect(listJob.data(), SIGNAL(progress(qint64, qint64)), SIGNAL(progress(qint64, qint64))); listJob->start(); } void ForgeListLoadTask::list_downloaded() { - auto DlJob = listJob->first(); - auto data = DlJob.dynamicCast<ByteArrayDownload>()->m_data; - - + QByteArray data; + { + auto DlJob = listJob->first(); + auto filename = DlJob.dynamicCast<CacheDownload>()->m_target_path; + QFile listFile(filename); + if(!listFile.open(QIODevice::ReadOnly)) + return; + data = listFile.readAll(); + DlJob.reset(); + } + QJsonParseError jsonError; QJsonDocument jsonDoc = QJsonDocument::fromJson(data, &jsonError); - DlJob.reset(); - + + if (jsonError.error != QJsonParseError::NoError) { emitFailed("Error parsing version list JSON:" + jsonError.errorString()); return; } - if(!jsonDoc.isObject()) + if (!jsonDoc.isObject()) { emitFailed("Error parsing version list JSON: jsonDoc is not an object"); return; } - + QJsonObject root = jsonDoc.object(); - + // Now, get the array of versions. - if(!root.value("builds").isArray()) + if (!root.value("builds").isArray()) { - emitFailed("Error parsing version list JSON: version list object is missing 'builds' array"); + emitFailed( + "Error parsing version list JSON: version list object is missing 'builds' array"); return; } QJsonArray builds = root.value("builds").toArray(); - - QList<BaseVersionPtr > tempList; + + QList<BaseVersionPtr> tempList; for (int i = 0; i < builds.count(); i++) { // Load the version info. - if(!builds[i].isObject()) + if (!builds[i].isObject()) { - //FIXME: log this somewhere + // FIXME: log this somewhere continue; } QJsonObject obj = builds[i].toObject(); int build_nr = obj.value("build").toDouble(0); - if(!build_nr) + if (!build_nr) continue; QJsonArray files = obj.value("files").toArray(); QString url, jobbuildver, mcver, buildtype, filename; QString changelog_url, installer_url; + QString installer_filename; bool valid = false; - for(int j = 0; j < files.count(); j++) + for (int j = 0; j < files.count(); j++) { - if(!files[j].isObject()) + if (!files[j].isObject()) continue; QJsonObject file = files[j].toObject(); buildtype = file.value("buildtype").toString(); - if((buildtype == "client" || buildtype == "universal") && !valid) + if ((buildtype == "client" || buildtype == "universal") && !valid) { mcver = file.value("mcver").toString(); url = file.value("url").toString(); jobbuildver = file.value("jobbuildver").toString(); int lastSlash = url.lastIndexOf('/'); - filename = url.mid(lastSlash+1); + filename = url.mid(lastSlash + 1); valid = true; } - else if(buildtype == "changelog") + else if (buildtype == "changelog") { QString ext = file.value("ext").toString(); - if(ext.isEmpty()) + if (ext.isEmpty()) continue; changelog_url = file.value("url").toString(); } - else if(buildtype == "installer") + else if (buildtype == "installer") { installer_url = file.value("url").toString(); + int lastSlash = installer_url.lastIndexOf('/'); + installer_filename = installer_url.mid(lastSlash + 1); } } - if(valid) + if (valid) { // Now, we construct the version object and add it to the list. QSharedPointer<ForgeVersion> fVersion(new ForgeVersion()); @@ -257,13 +266,16 @@ void ForgeListLoadTask::list_downloaded() fVersion->installer_url = installer_url; fVersion->jobbuildver = jobbuildver; fVersion->mcver = mcver; - fVersion->filename = filename; + if (installer_filename.isEmpty()) + fVersion->filename = filename; + else + fVersion->filename = installer_filename; fVersion->m_buildnr = build_nr; tempList.append(fVersion); } } m_list->updateListData(tempList); - + emitSucceeded(); return; } diff --git a/logic/lists/ForgeVersionList.h b/logic/lists/ForgeVersionList.h index ca6b27bc..613de8a6 100644 --- a/logic/lists/ForgeVersionList.h +++ b/logic/lists/ForgeVersionList.h @@ -3,7 +3,7 @@ * 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 @@ -33,19 +33,22 @@ struct ForgeVersion : public BaseVersion virtual QString descriptor() { return filename; - }; + } + ; virtual QString name() { return "Forge " + jobbuildver; - }; + } + ; virtual QString typeString() const { - if(installer_url.isEmpty()) + if (installer_url.isEmpty()) return "Universal"; else return "Installer"; - }; - + } + ; + int m_buildnr = 0; QString universal_url; QString changelog_url; @@ -60,42 +63,45 @@ class ForgeVersionList : public BaseVersionList Q_OBJECT public: friend class ForgeListLoadTask; - + explicit ForgeVersionList(QObject *parent = 0); - + virtual Task *getLoadTask(); virtual bool isLoaded(); virtual const BaseVersionPtr at(int i) const; virtual int count() const; virtual void sort(); - + virtual BaseVersionPtr getLatestStable() const; - - virtual QVariant data(const QModelIndex& index, int role) const; - virtual QVariant headerData(int section, Qt::Orientation orientation, int role) const; - virtual int columnCount(const QModelIndex& parent) const; - + + virtual QVariant data(const QModelIndex &index, int role) const; + virtual QVariant headerData(int section, Qt::Orientation orientation, + int role) const; + virtual int columnCount(const QModelIndex &parent) const; + protected: QList<BaseVersionPtr> m_vlist; - + bool m_loaded; - -protected slots: - virtual void updateListData(QList<BaseVersionPtr > versions); + +protected +slots: + virtual void updateListData(QList<BaseVersionPtr> versions); }; class ForgeListLoadTask : public Task { Q_OBJECT - + public: explicit ForgeListLoadTask(ForgeVersionList *vlist); - + virtual void executeTask(); - -protected slots: + +protected +slots: void list_downloaded(); - + protected: DownloadJobPtr listJob; ForgeVersionList *m_list; diff --git a/logic/net/CacheDownload.cpp b/logic/net/CacheDownload.cpp index c0074574..dc2e0448 100644 --- a/logic/net/CacheDownload.cpp +++ b/logic/net/CacheDownload.cpp @@ -7,8 +7,8 @@ #include <QDateTime> #include <QDebug> -CacheDownload::CacheDownload (QUrl url, MetaEntryPtr entry ) - :Download(), md5sum(QCryptographicHash::Md5) +CacheDownload::CacheDownload(QUrl url, MetaEntryPtr entry) + : Download(), md5sum(QCryptographicHash::Md5) { m_url = url; m_entry = entry; @@ -19,38 +19,40 @@ CacheDownload::CacheDownload (QUrl url, MetaEntryPtr entry ) void CacheDownload::start() { - if(!m_entry->stale) + if (!m_entry->stale) { emit succeeded(index_within_job); return; } m_output_file.setFileName(m_target_path); // if there already is a file and md5 checking is in effect and it can be opened - if(!ensureFilePathExists(m_target_path)) + if (!ensureFilePathExists(m_target_path)) { emit failed(index_within_job); return; } qDebug() << "Downloading " << m_url.toString(); - QNetworkRequest request ( m_url ); - request.setRawHeader(QString("If-None-Match").toLatin1(), m_entry->etag.toLatin1()); - + QNetworkRequest request(m_url); + request.setRawHeader(QString("If-None-Match").toLatin1(), m_entry->etag.toLatin1()); + auto worker = MMC->qnam(); - QNetworkReply * rep = worker->get ( request ); - - m_reply = QSharedPointer<QNetworkReply> ( rep, &QObject::deleteLater ); - connect ( rep, SIGNAL ( downloadProgress ( qint64,qint64 ) ), SLOT ( downloadProgress ( qint64,qint64 ) ) ); - connect ( rep, SIGNAL ( finished() ), SLOT ( downloadFinished() ) ); - connect ( rep, SIGNAL ( error ( QNetworkReply::NetworkError ) ), SLOT ( downloadError ( QNetworkReply::NetworkError ) ) ); - connect ( rep, SIGNAL ( readyRead() ), SLOT ( downloadReadyRead() ) ); + QNetworkReply *rep = worker->get(request); + + m_reply = QSharedPointer<QNetworkReply>(rep, &QObject::deleteLater); + connect(rep, SIGNAL(downloadProgress(qint64, qint64)), + SLOT(downloadProgress(qint64, qint64))); + connect(rep, SIGNAL(finished()), SLOT(downloadFinished())); + connect(rep, SIGNAL(error(QNetworkReply::NetworkError)), + SLOT(downloadError(QNetworkReply::NetworkError))); + connect(rep, SIGNAL(readyRead()), SLOT(downloadReadyRead())); } -void CacheDownload::downloadProgress ( qint64 bytesReceived, qint64 bytesTotal ) +void CacheDownload::downloadProgress(qint64 bytesReceived, qint64 bytesTotal) { - emit progress (index_within_job, bytesReceived, bytesTotal ); + emit progress(index_within_job, bytesReceived, bytesTotal); } -void CacheDownload::downloadError ( QNetworkReply::NetworkError error ) +void CacheDownload::downloadError(QNetworkReply::NetworkError error) { // error happened during download. // TODO: log the reason why @@ -59,12 +61,12 @@ void CacheDownload::downloadError ( QNetworkReply::NetworkError error ) void CacheDownload::downloadFinished() { // if the download succeeded - if ( m_status != Job_Failed ) + if (m_status != Job_Failed) { - + // nothing went wrong... m_status = Job_Finished; - if(m_opened_for_saving) + if (m_opened_for_saving) { // save the data to the downloadable if we aren't saving to file m_output_file.close(); @@ -72,20 +74,23 @@ void CacheDownload::downloadFinished() } else { - if ( m_output_file.open ( QIODevice::ReadOnly ) ) + if (m_output_file.open(QIODevice::ReadOnly)) { - m_entry->md5sum = QCryptographicHash::hash ( m_output_file.readAll(), QCryptographicHash::Md5 ).toHex().constData(); + m_entry->md5sum = + QCryptographicHash::hash(m_output_file.readAll(), QCryptographicHash::Md5) + .toHex() + .constData(); m_output_file.close(); } } QFileInfo output_file_info(m_target_path); - - + m_entry->etag = m_reply->rawHeader("ETag").constData(); - m_entry->last_changed_timestamp = output_file_info.lastModified().toUTC().toMSecsSinceEpoch(); + m_entry->last_changed_timestamp = + output_file_info.lastModified().toUTC().toMSecsSinceEpoch(); m_entry->stale = false; MMC->metacache()->updateEntry(m_entry); - + m_reply.clear(); emit succeeded(index_within_job); return; @@ -103,9 +108,9 @@ void CacheDownload::downloadFinished() void CacheDownload::downloadReadyRead() { - if(!m_opened_for_saving) + if (!m_opened_for_saving) { - if ( !m_output_file.open ( QIODevice::WriteOnly ) ) + if (!m_output_file.open(QIODevice::WriteOnly)) { /* * Can't open the file... the job failed @@ -118,5 +123,5 @@ void CacheDownload::downloadReadyRead() } QByteArray ba = m_reply->readAll(); md5sum.addData(ba); - m_output_file.write ( ba ); + m_output_file.write(ba); } diff --git a/logic/net/HttpMetaCache.h b/logic/net/HttpMetaCache.h index fac6bec3..daf6c43f 100644 --- a/logic/net/HttpMetaCache.h +++ b/logic/net/HttpMetaCache.h @@ -24,25 +24,28 @@ public: // supply path to the cache index file HttpMetaCache(QString path); ~HttpMetaCache(); - + // get the entry solely from the cache // you probably don't want this, unless you have some specific caching needs. MetaEntryPtr getEntry(QString base, QString resource_path); - + // get the entry from cache and verify that it isn't stale (within reason) - MetaEntryPtr resolveEntry(QString base, QString resource_path, QString expected_etag = QString()); - + MetaEntryPtr resolveEntry(QString base, QString resource_path, + QString expected_etag = QString()); + // add a previously resolved stale entry bool updateEntry(MetaEntryPtr stale_entry); - + void addBase(QString base, QString base_root); - + // (re)start a timer that calls SaveNow later. void SaveEventually(); void Load(); - QString getBasePath ( QString base ); -public slots: + QString getBasePath(QString base); +public +slots: void SaveNow(); + private: // create a new stale entry, given the parameters MetaEntryPtr staleEntry(QString base, QString resource_path); diff --git a/logic/tasks/LoginTask.cpp b/logic/tasks/LoginTask.cpp index 859827bc..222af618 100644 --- a/logic/tasks/LoginTask.cpp +++ b/logic/tasks/LoginTask.cpp @@ -30,7 +30,7 @@ void LoginTask::executeTask() { setStatus(tr("Logging in...")); auto worker = MMC->qnam(); - connect(worker, SIGNAL(finished(QNetworkReply*)), this, SLOT(processNetReply(QNetworkReply*))); + connect(worker.data(), SIGNAL(finished(QNetworkReply*)), this, SLOT(processNetReply(QNetworkReply*))); QUrl loginURL("https://login.minecraft.net/"); QNetworkRequest netRequest(loginURL); |