From 005a010ee6a67191ec24583780310fcf217ff30c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Mr=C3=A1zek?= Date: Sun, 4 Aug 2013 14:46:33 +0200 Subject: More code cleanups! --- backend/BaseInstance.h | 4 +- backend/CMakeLists.txt | 45 ++--- backend/LegacyInstance.cpp | 2 +- backend/LegacyInstance.h | 2 +- backend/OneSixInstance.cpp | 6 +- backend/OneSixInstance.h | 2 +- backend/OneSixUpdate.cpp | 140 ++++++++++++++++ backend/OneSixUpdate.h | 82 +++++++++ backend/lists/InstVersionList.h | 2 +- backend/lists/MinecraftVersionList.cpp | 292 +++++++++++++-------------------- backend/lists/MinecraftVersionList.h | 25 +-- backend/tasks/GameUpdateTask.cpp | 140 ---------------- backend/tasks/GameUpdateTask.h | 82 --------- backend/tasks/LoginTask.cpp | 7 +- backend/tasks/LoginTask.h | 7 +- backend/tasks/UserInfo.cpp | 49 ------ backend/tasks/UserInfo.h | 41 ----- gui/mainwindow.cpp | 6 +- main.cpp | 2 +- 19 files changed, 386 insertions(+), 550 deletions(-) create mode 100644 backend/OneSixUpdate.cpp create mode 100644 backend/OneSixUpdate.h delete mode 100644 backend/tasks/GameUpdateTask.cpp delete mode 100644 backend/tasks/GameUpdateTask.h delete mode 100644 backend/tasks/UserInfo.cpp delete mode 100644 backend/tasks/UserInfo.h diff --git a/backend/BaseInstance.h b/backend/BaseInstance.h index 1bb2ce17..eb13b92b 100644 --- a/backend/BaseInstance.h +++ b/backend/BaseInstance.h @@ -26,7 +26,7 @@ #include "libmmc_config.h" class MinecraftProcess; -class GameUpdateTask; +class OneSixUpdate; class InstanceList; class BaseInstancePrivate; @@ -102,7 +102,7 @@ public: virtual SettingsObject &settings() const; /// returns a valid update task if update is needed, NULL otherwise - virtual GameUpdateTask* doUpdate() = 0; + virtual OneSixUpdate* doUpdate() = 0; /// returns a valid minecraft process, ready for launch virtual MinecraftProcess* prepareForLaunch(QString user, QString session) = 0; diff --git a/backend/CMakeLists.txt b/backend/CMakeLists.txt index f79ef8ef..309dde97 100644 --- a/backend/CMakeLists.txt +++ b/backend/CMakeLists.txt @@ -20,17 +20,23 @@ include_directories(${CMAKE_SOURCE_DIR}/libsettings/include) SET(LIBINST_HEADERS libmmc_config.h -# Instance Stuff +# Base classes and infrastructure +InstanceVersion.h +MinecraftVersion.h +InstanceFactory.h BaseInstance.h +BaseInstance_p.h +MinecraftProcess.h + +# legacy instances LegacyInstance.h -OneSixInstance.h -InstanceFactory.h +LegacyInstance_p.h +# 1.6 instances OneSixAssets.h - -# Versions -InstanceVersion.h -MinecraftVersion.h +OneSixInstance.h +OneSixInstance_p.h +OneSixUpdate.h OneSixVersion.h VersionFactory.h @@ -43,25 +49,24 @@ lists/LwjglVersionList.h # Tasks tasks/Task.h tasks/LoginTask.h -tasks/GameUpdateTask.h -tasks/UserInfo.h - -MinecraftProcess.h ) SET(LIBINST_SOURCES -# Instance Stuff +# Base classes and infrastructure +InstanceVersion.cpp +MinecraftVersion.cpp +InstanceFactory.cpp BaseInstance.cpp +MinecraftProcess.cpp + +# legacy instances LegacyInstance.cpp -OneSixInstance.cpp -InstanceFactory.cpp +# 1.6 instances OneSixAssets.cpp - -# Versions -InstanceVersion.cpp -MinecraftVersion.cpp +OneSixInstance.cpp OneSixVersion.cpp +OneSixUpdate.cpp VersionFactory.cpp # Lists @@ -73,10 +78,6 @@ lists/LwjglVersionList.cpp # Tasks tasks/Task.cpp tasks/LoginTask.cpp -tasks/GameUpdateTask.cpp -tasks/UserInfo.cpp - -MinecraftProcess.cpp ) # Set the include dir path. diff --git a/backend/LegacyInstance.cpp b/backend/LegacyInstance.cpp index b4031eb1..aace2a22 100644 --- a/backend/LegacyInstance.cpp +++ b/backend/LegacyInstance.cpp @@ -31,7 +31,7 @@ QString LegacyInstance::minecraftDir() const return mcDir.filePath(); } -GameUpdateTask* LegacyInstance::doUpdate() +OneSixUpdate* LegacyInstance::doUpdate() { // legacy instances no longer update return nullptr; diff --git a/backend/LegacyInstance.h b/backend/LegacyInstance.h index 64b7b40a..dcc97448 100644 --- a/backend/LegacyInstance.h +++ b/backend/LegacyInstance.h @@ -96,7 +96,7 @@ public: void setShouldUpdate(bool val); /// return a valid GameUpdateTask if an update is needed, return NULL otherwise - virtual GameUpdateTask* doUpdate(); + virtual OneSixUpdate* doUpdate(); /// prepare the instance for launch and return a constructed MinecraftProcess instance virtual MinecraftProcess* prepareForLaunch( QString user, QString session ); diff --git a/backend/OneSixInstance.cpp b/backend/OneSixInstance.cpp index d81ed3b1..e64f9b03 100644 --- a/backend/OneSixInstance.cpp +++ b/backend/OneSixInstance.cpp @@ -1,6 +1,6 @@ #include "OneSixInstance.h" #include "OneSixInstance_p.h" -#include "tasks/GameUpdateTask.h" +#include "OneSixUpdate.h" #include "MinecraftProcess.h" #include @@ -11,9 +11,9 @@ OneSixInstance::OneSixInstance ( const QString& rootDir, SettingsObject* setting d->m_settings->registerSetting(new Setting("IntendedVersion", "")); } -GameUpdateTask* OneSixInstance::doUpdate() +OneSixUpdate* OneSixInstance::doUpdate() { - return new GameUpdateTask(this); + return new OneSixUpdate(this); } MinecraftProcess* OneSixInstance::prepareForLaunch ( QString user, QString session ) diff --git a/backend/OneSixInstance.h b/backend/OneSixInstance.h index 5b4b2d8f..89e3c9c3 100644 --- a/backend/OneSixInstance.h +++ b/backend/OneSixInstance.h @@ -6,7 +6,7 @@ class LIBMULTIMC_EXPORT OneSixInstance : public BaseInstance Q_OBJECT public: explicit OneSixInstance(const QString &rootDir, SettingsObject * settings, QObject *parent = 0); - virtual GameUpdateTask* doUpdate(); + virtual OneSixUpdate* doUpdate(); virtual MinecraftProcess* prepareForLaunch ( QString user, QString session ); virtual bool setIntendedVersionId ( QString version ); diff --git a/backend/OneSixUpdate.cpp b/backend/OneSixUpdate.cpp new file mode 100644 index 00000000..a344662c --- /dev/null +++ b/backend/OneSixUpdate.cpp @@ -0,0 +1,140 @@ +/* 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 "OneSixUpdate.h" + +#include + +#include +#include +#include +#include + +#include + +#include "BaseInstance.h" +#include "lists/MinecraftVersionList.h" +#include "VersionFactory.h" +#include "OneSixVersion.h" + +#include "pathutils.h" + + +OneSixUpdate::OneSixUpdate(BaseInstance *inst, QObject *parent) : + Task(parent) +{ + m_inst = inst; +} + +void OneSixUpdate::executeTask() +{ + // Get a pointer to the version object that corresponds to the instance's version. + targetVersion = (MinecraftVersion *)MinecraftVersionList::getMainList().findVersion(m_inst->intendedVersionId()); + if(targetVersion == NULL) + { + emit gameUpdateComplete(); + return; + } + + setStatus("Getting the version files from Mojang."); + + QString urlstr("http://s3.amazonaws.com/Minecraft.Download/versions/"); + urlstr += targetVersion->descriptor() + "/" + targetVersion->descriptor() + ".json"; + auto dljob = DownloadJob::create(QUrl(urlstr)); + specificVersionDownloadJob.reset(new JobList()); + specificVersionDownloadJob->add(dljob); + connect(specificVersionDownloadJob.data(), SIGNAL(finished()), SLOT(versionFileFinished())); + connect(specificVersionDownloadJob.data(), SIGNAL(failed()), SLOT(versionFileFailed())); + connect(specificVersionDownloadJob.data(), SIGNAL(progress(qint64,qint64)), SLOT(updateDownloadProgress(qint64,qint64))); + download_queue.enqueue(specificVersionDownloadJob); + + QEventLoop loop; + loop.exec(); +} + +void OneSixUpdate::versionFileFinished() +{ + JobPtr firstJob = specificVersionDownloadJob->getFirstJob(); + auto DlJob = firstJob.dynamicCast(); + FullVersionFactory parser; + auto version = parser.parse(DlJob->m_data); + + if(!version) + { + error(parser.error_string); + exit(0); + } + + // save the version file in $instanceId/version.json and versions/$version/$version.json + QString version_id = targetVersion->descriptor(); + QString inst_dir = m_inst->rootDir(); + QString version1 = PathCombine(inst_dir, "/version.json"); + QString version2 = QString("versions/") + version_id + "/" + version_id + ".json"; + DownloadJob::ensurePathExists(version1); + DownloadJob::ensurePathExists(version2); + QFile vfile1 (version1); + QFile vfile2 (version2); + vfile1.open(QIODevice::Truncate | QIODevice::WriteOnly ); + vfile2.open(QIODevice::Truncate | QIODevice::WriteOnly ); + vfile1.write(DlJob->m_data); + vfile2.write(DlJob->m_data); + vfile1.close(); + vfile2.close(); + + // download the right jar, save it in versions/$version/$version.jar + QString urlstr("http://s3.amazonaws.com/Minecraft.Download/versions/"); + urlstr += targetVersion->descriptor() + "/" + targetVersion->descriptor() + ".jar"; + QString targetstr ("versions/"); + targetstr += targetVersion->descriptor() + "/" + targetVersion->descriptor() + ".jar"; + auto dljob = DownloadJob::create(QUrl(urlstr), targetstr); + + jarlibDownloadJob.reset(new JobList()); + jarlibDownloadJob->add(dljob); + connect(jarlibDownloadJob.data(), SIGNAL(finished()), SLOT(jarlibFinished())); + connect(jarlibDownloadJob.data(), SIGNAL(failed()), SLOT(jarlibFailed())); + connect(jarlibDownloadJob.data(), SIGNAL(progress(qint64,qint64)), SLOT(updateDownloadProgress(qint64,qint64))); + // determine and download all the libraries, save them in libraries/whatever... + download_queue.enqueue(jarlibDownloadJob); +} + +void OneSixUpdate::jarlibFinished() +{ + exit(1); +} + +void OneSixUpdate::jarlibFailed() +{ + error("Failed to download the binary garbage. Try again. Maybe. IF YOU DARE"); + exit(0); +} + +void OneSixUpdate::versionFileFailed() +{ + error("Failed to download the version description. Try again."); + exit(0); +} + +void OneSixUpdate::error(const QString &msg) +{ + emit gameUpdateError(msg); +} + +void OneSixUpdate::updateDownloadProgress(qint64 current, qint64 total) +{ + // The progress on the current file is current / total + float currentDLProgress = (float) current / (float) total; + setProgress((int)(currentDLProgress * 100)); // convert to percentage +} + diff --git a/backend/OneSixUpdate.h b/backend/OneSixUpdate.h new file mode 100644 index 00000000..27a7bccd --- /dev/null +++ b/backend/OneSixUpdate.h @@ -0,0 +1,82 @@ +/* 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 "dlqueue.h" + +#include "tasks/Task.h" +#include "libmmc_config.h" + +class MinecraftVersion; +class BaseInstance; + +/*! + * The game update task is the task that handles downloading instances' files. + */ +class LIBMULTIMC_EXPORT OneSixUpdate : public Task +{ + Q_OBJECT +public: + explicit OneSixUpdate(BaseInstance *inst, QObject *parent = 0); + + virtual void executeTask(); + +public slots: + virtual void error(const QString &msg); + +private slots: + void updateDownloadProgress(qint64 current, qint64 total); + + void versionFileFinished(); + void versionFileFailed(); + + void jarlibFinished(); + void jarlibFailed(); + +signals: + /*! + * \brief Signal emitted when the game update is complete. + * \param response The login response received from login task. + */ + void gameUpdateComplete(); + + /*! + * \brief Signal emitted if an error occurrs during the update. + * \param errorMsg An error message to be displayed to the user. + */ + void gameUpdateError(const QString &errorMsg); + +private: + BaseInstance *m_inst; + + QString m_subStatusMsg; + + JobListPtr legacyDownloadJob; + JobListPtr specificVersionDownloadJob; + JobListPtr jarlibDownloadJob; + JobListQueue download_queue; + + // target version, determined during this task + MinecraftVersion *targetVersion; +}; + + diff --git a/backend/lists/InstVersionList.h b/backend/lists/InstVersionList.h index 97e00383..57965333 100644 --- a/backend/lists/InstVersionList.h +++ b/backend/lists/InstVersionList.h @@ -60,7 +60,7 @@ public: explicit InstVersionList(QObject *parent = 0); /*! - * \brief Gets a task that will reload the version islt. + * \brief Gets a task that will reload the version list. * Simply execute the task to load the list. * The task returned by this function should reset the model when it's done. * \return A pointer to a task that reloads the version list. diff --git a/backend/lists/MinecraftVersionList.cpp b/backend/lists/MinecraftVersionList.cpp index feb479a9..4abfbfb8 100644 --- a/backend/lists/MinecraftVersionList.cpp +++ b/backend/lists/MinecraftVersionList.cpp @@ -160,196 +160,141 @@ MCVListLoadTask::MCVListLoadTask(MinecraftVersionList *vlist) { m_list = vlist; m_currentStable = NULL; - processedAssetsReply = false; - processedMCNReply = false; - processedMCVListReply = false; + netMgr = nullptr; + vlistReply = nullptr; } MCVListLoadTask::~MCVListLoadTask() { -// delete netMgr; + if(netMgr) + netMgr->deleteLater(); } void MCVListLoadTask::executeTask() { - setSubStatus(); + // NOTE: this executes in the QThread + setStatus("Loading instance version list..."); + netMgr = new QNetworkAccessManager(); + vlistReply = netMgr->get(QNetworkRequest(QUrl(QString(MCVLIST_URLBASE) + "versions.json"))); + connect(vlistReply, SIGNAL(finished()), this, SLOT(list_downloaded())); + exec(); +} + + +void MCVListLoadTask::list_downloaded() +{ + // NOTE: this executes in the main thread + + if(vlistReply->error() != QNetworkReply::QNetworkReply::NoError) + { + qDebug() << "Failed to load Minecraft main version list" << vlistReply->errorString(); + vlistReply->deleteLater(); + exit(0); + } - QNetworkAccessManager networkMgr; - netMgr = &networkMgr; + QJsonParseError jsonError; + QJsonDocument jsonDoc = QJsonDocument::fromJson(vlistReply->readAll(), &jsonError); + vlistReply->deleteLater(); - if (!loadFromVList()) + if (jsonError.error != QJsonParseError::NoError) { - qDebug() << "Failed to load from Mojang version list."; + qDebug() << "Error parsing version list JSON:" << jsonError.errorString(); + exit(0); } - finalize(); -} - -void MCVListLoadTask::setSubStatus(const QString msg) -{ - if (msg.isEmpty()) - setStatus("Loading instance version list..."); - else - setStatus("Loading instance version list: " + msg); -} -// FIXME: we should have a local cache of the version list and a local cache of version data -bool MCVListLoadTask::loadFromVList() -{ - QNetworkReply *vlistReply = netMgr->get(QNetworkRequest(QUrl(QString(MCVLIST_URLBASE) + - "versions.json"))); - NetUtils::waitForNetRequest(vlistReply); + if(!jsonDoc.isObject()) + { + qDebug() << "Error parsing version list JSON: " << "jsonDoc is not an object"; + exit(0); + } + + QJsonObject root = jsonDoc.object(); + + // Get the ID of the latest release and the latest snapshot. + if(!root.value("latest").isObject()) + { + qDebug() << "Error parsing version list JSON: " << "version list is missing 'latest' object"; + exit(0); + } - switch (vlistReply->error()) + QJsonObject latest = root.value("latest").toObject(); + + QString latestReleaseID = latest.value("release").toString(""); + QString latestSnapshotID = latest.value("snapshot").toString(""); + if(latestReleaseID.isEmpty()) + { + qDebug() << "Error parsing version list JSON: " << "latest release field is missing"; + exit(0); + } + if(latestSnapshotID.isEmpty()) + { + qDebug() << "Error parsing version list JSON: " << "latest snapshot field is missing"; + exit(0); + } + + // Now, get the array of versions. + if(!root.value("versions").isArray()) { - case QNetworkReply::NoError: + qDebug() << "Error parsing version list JSON: " << "version list object is missing 'versions' array"; + exit(0); + } + QJsonArray versions = root.value("versions").toArray(); + + for (int i = 0; i < versions.count(); i++) { - QJsonParseError jsonError; - QJsonDocument jsonDoc = QJsonDocument::fromJson(vlistReply->readAll(), &jsonError); + // Load the version info. + if(!versions[i].isObject()) + { + //FIXME: log this somewhere + continue; + } + QJsonObject version = versions[i].toObject(); + QString versionID = version.value("id").toString(""); + QString versionTimeStr = version.value("releaseTime").toString(""); + QString versionTypeStr = version.value("type").toString(""); + if(versionID.isEmpty() || versionTimeStr.isEmpty() || versionTypeStr.isEmpty()) + { + //FIXME: log this somewhere + continue; + } + + // Parse the timestamp. + QDateTime versionTime = timeFromS3Time(versionTimeStr); + if(!versionTime.isValid()) + { + //FIXME: log this somewhere + continue; + } - if (jsonError.error == QJsonParseError::NoError) + // Parse the type. + MinecraftVersion::VersionType versionType; + if (versionTypeStr == "release") { - Q_ASSERT_X(jsonDoc.isObject(), "loadFromVList", "jsonDoc is not an object"); - - QJsonObject root = jsonDoc.object(); - - // Get the ID of the latest release and the latest snapshot. - Q_ASSERT_X(root.value("latest").isObject(), "loadFromVList", - "version list is missing 'latest' object"); - QJsonObject latest = root.value("latest").toObject(); - - QString latestReleaseID = latest.value("release").toString(""); - QString latestSnapshotID = latest.value("snapshot").toString(""); - Q_ASSERT_X(!latestReleaseID.isEmpty(), "loadFromVList", "latest release field is missing"); - Q_ASSERT_X(!latestSnapshotID.isEmpty(), "loadFromVList", "latest snapshot field is missing"); - - // Now, get the array of versions. - Q_ASSERT_X(root.value("versions").isArray(), "loadFromVList", - "version list object is missing 'versions' array"); - QJsonArray versions = root.value("versions").toArray(); - - for (int i = 0; i < versions.count(); i++) - { - // Load the version info. - Q_ASSERT_X(versions[i].isObject(), "loadFromVList", - QString("in versions array, index %1 is not an object"). - arg(i).toUtf8()); - QJsonObject version = versions[i].toObject(); - - QString versionID = version.value("id").toString(""); - QString versionTimeStr = version.value("releaseTime").toString(""); - QString versionTypeStr = version.value("type").toString(""); - - Q_ASSERT_X(!versionID.isEmpty(), "loadFromVList", - QString("in versions array, index %1's \"id\" field is not a valid string"). - arg(i).toUtf8()); - Q_ASSERT_X(!versionTimeStr.isEmpty(), "loadFromVList", - QString("in versions array, index %1's \"time\" field is not a valid string"). - arg(i).toUtf8()); - Q_ASSERT_X(!versionTypeStr.isEmpty(), "loadFromVList", - QString("in versions array, index %1's \"type\" field is not a valid string"). - arg(i).toUtf8()); - - - // Now, process that info and add the version to the list. - - // Parse the timestamp. - QDateTime versionTime = timeFromS3Time(versionTimeStr); - - Q_ASSERT_X(versionTime.isValid(), "loadFromVList", - QString("in versions array, index %1's timestamp failed to parse"). - arg(i).toUtf8()); - - // Parse the type. - MinecraftVersion::VersionType versionType; - if (versionTypeStr == "release") - { - // Check if this version is the current stable version. - if (versionID == latestReleaseID) - versionType = MinecraftVersion::CurrentStable; - else - versionType = MinecraftVersion::Stable; - } - else if(versionTypeStr == "snapshot") - { - versionType = MinecraftVersion::Snapshot; - } - else - { - // we don't know what to do with this... - continue; - } - - // Get the download URL. - QString dlUrl = QString(MCVLIST_URLBASE) + versionID + "/"; - - - // Now, we construct the version object and add it to the list. - MinecraftVersion *mcVersion = new MinecraftVersion( - versionID, versionID, versionTime.toMSecsSinceEpoch(), - dlUrl, ""); - mcVersion->setVersionType(versionType); - tempList.append(mcVersion); - } + // Check if this version is the current stable version. + if (versionID == latestReleaseID) + versionType = MinecraftVersion::CurrentStable; + else + versionType = MinecraftVersion::Stable; + } + else if(versionTypeStr == "snapshot") + { + versionType = MinecraftVersion::Snapshot; } else { - qDebug() << "Error parsing version list JSON:" << jsonError.errorString(); + //FIXME: log this somewhere + continue; } - break; - } + // Get the download URL. + QString dlUrl = QString(MCVLIST_URLBASE) + versionID + "/"; - default: - // TODO: Network error handling. - qDebug() << "Failed to load Minecraft main version list" << vlistReply->errorString(); - break; + // Now, we construct the version object and add it to the list. + MinecraftVersion *mcVersion = new MinecraftVersion(versionID, versionID, versionTime.toMSecsSinceEpoch(),dlUrl, ""); + mcVersion->setVersionType(versionType); + tempList.append(mcVersion); } - - return true; -} - -bool MCVListLoadTask::finalize() -{ - // First, we need to do some cleanup. We loaded assets versions into assetsList, - // MCNostalgia versions into mcnList and all the others into tempList. MCNostalgia - // provides some versions that are on assets.minecraft.net and we want to ignore - // those, so we remove and delete them from mcnList. assets.minecraft.net also provides - // versions that are on Mojang's version list and we want to ignore those as well. - - // To start, we get a list of the descriptors in tmpList. - QStringList tlistDescriptors; - for (int i = 0; i < tempList.count(); i++) - tlistDescriptors.append(tempList.at(i)->descriptor()); - - // Now, we go through our assets version list and remove anything with - // a descriptor that matches one we already have in tempList. - for (int i = 0; i < assetsList.count(); i++) - if (tlistDescriptors.contains(assetsList.at(i)->descriptor())) - delete assetsList.takeAt(i--); // We need to decrement here because we're removing an item. - - // We also need to rebuild the list of descriptors. - tlistDescriptors.clear(); - for (int i = 0; i < tempList.count(); i++) - tlistDescriptors.append(tempList.at(i)->descriptor()); - - // Next, we go through our MCNostalgia version list and do the same thing. - for (int i = 0; i < mcnList.count(); i++) - if (tlistDescriptors.contains(mcnList.at(i)->descriptor())) - delete mcnList.takeAt(i--); // We need to decrement here because we're removing an item. - - // Now that the duplicates are gone, we need to merge the lists. This is - // simple enough. - tempList.append(assetsList); - tempList.append(mcnList); - - // We're done with these lists now, but the items have been moved over to - // tempList, so we don't need to delete them yet. - - // Now, we invoke the updateListData slot on the GUI thread. This will copy all - // the versions we loaded and set their parents to the version list. - // Then, it will swap the new list with the old one and free the old list's memory. - QMetaObject::invokeMethod(m_list, "updateListData", Qt::BlockingQueuedConnection, - Q_ARG(QList, tempList)); + m_list->updateListData(tempList); // Once that's finished, we can delete the versions in our temp list. while (!tempList.isEmpty()) @@ -358,21 +303,10 @@ bool MCVListLoadTask::finalize() #ifdef PRINT_VERSIONS m_list->printToStdOut(); #endif - return true; + exit(1); } -void MCVListLoadTask::updateStuff() +// FIXME: we should have a local cache of the version list and a local cache of version data +bool MCVListLoadTask::loadFromVList() { - const int totalReqs = 1; - int reqsComplete = 0; - - if (processedMCVListReply) - reqsComplete++; - - calcProgress(reqsComplete, totalReqs); - - if (reqsComplete >= totalReqs) - { - quit(); - } } diff --git a/backend/lists/MinecraftVersionList.h b/backend/lists/MinecraftVersionList.h index 8da74112..078c7c66 100644 --- a/backend/lists/MinecraftVersionList.h +++ b/backend/lists/MinecraftVersionList.h @@ -16,20 +16,16 @@ #pragma once #include - -#include - #include #include "InstVersionList.h" - #include "tasks/Task.h" - #include "MinecraftVersion.h" - #include "libmmc_config.h" class MCVListLoadTask; +class QNetworkAccessManager; +class QNetworkReply; class LIBMULTIMC_EXPORT MinecraftVersionList : public InstVersionList { @@ -73,28 +69,19 @@ public: virtual void executeTask(); -protected: - void setSubStatus(const QString msg = ""); +protected slots: + void list_downloaded(); +protected: //! Loads versions from Mojang's official version list. bool loadFromVList(); - //! Finalizes loading by updating the version list. - bool finalize(); - - void updateStuff(); - QNetworkAccessManager *netMgr; + QNetworkReply *vlistReply; MinecraftVersionList *m_list; QList tempList; //! < List of loaded versions - QList assetsList; //! < List of versions loaded from assets.minecraft.net - QList mcnList; //! < List of loaded MCNostalgia versions MinecraftVersion *m_currentStable; - - bool processedMCVListReply; - bool processedAssetsReply; - bool processedMCNReply; }; diff --git a/backend/tasks/GameUpdateTask.cpp b/backend/tasks/GameUpdateTask.cpp deleted file mode 100644 index f49b551c..00000000 --- a/backend/tasks/GameUpdateTask.cpp +++ /dev/null @@ -1,140 +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 "GameUpdateTask.h" - -#include - -#include -#include -#include -#include - -#include - -#include "BaseInstance.h" -#include "lists/MinecraftVersionList.h" -#include "VersionFactory.h" -#include "OneSixVersion.h" - -#include "pathutils.h" - - -GameUpdateTask::GameUpdateTask(BaseInstance *inst, QObject *parent) : - Task(parent) -{ - m_inst = inst; -} - -void GameUpdateTask::executeTask() -{ - // Get a pointer to the version object that corresponds to the instance's version. - targetVersion = (MinecraftVersion *)MinecraftVersionList::getMainList().findVersion(m_inst->intendedVersionId()); - if(targetVersion == NULL) - { - emit gameUpdateComplete(); - return; - } - - setStatus("Getting the version files from Mojang."); - - QString urlstr("http://s3.amazonaws.com/Minecraft.Download/versions/"); - urlstr += targetVersion->descriptor() + "/" + targetVersion->descriptor() + ".json"; - auto dljob = DownloadJob::create(QUrl(urlstr)); - specificVersionDownloadJob.reset(new JobList()); - specificVersionDownloadJob->add(dljob); - connect(specificVersionDownloadJob.data(), SIGNAL(finished()), SLOT(versionFileFinished())); - connect(specificVersionDownloadJob.data(), SIGNAL(failed()), SLOT(versionFileFailed())); - connect(specificVersionDownloadJob.data(), SIGNAL(progress(qint64,qint64)), SLOT(updateDownloadProgress(qint64,qint64))); - download_queue.enqueue(specificVersionDownloadJob); - - QEventLoop loop; - loop.exec(); -} - -void GameUpdateTask::versionFileFinished() -{ - JobPtr firstJob = specificVersionDownloadJob->getFirstJob(); - auto DlJob = firstJob.dynamicCast(); - FullVersionFactory parser; - auto version = parser.parse(DlJob->m_data); - - if(!version) - { - error(parser.error_string); - exit(0); - } - - // save the version file in $instanceId/version.json and versions/$version/$version.json - QString version_id = targetVersion->descriptor(); - QString inst_dir = m_inst->rootDir(); - QString version1 = PathCombine(inst_dir, "/version.json"); - QString version2 = QString("versions/") + version_id + "/" + version_id + ".json"; - DownloadJob::ensurePathExists(version1); - DownloadJob::ensurePathExists(version2); - QFile vfile1 (version1); - QFile vfile2 (version2); - vfile1.open(QIODevice::Truncate | QIODevice::WriteOnly ); - vfile2.open(QIODevice::Truncate | QIODevice::WriteOnly ); - vfile1.write(DlJob->m_data); - vfile2.write(DlJob->m_data); - vfile1.close(); - vfile2.close(); - - // download the right jar, save it in versions/$version/$version.jar - QString urlstr("http://s3.amazonaws.com/Minecraft.Download/versions/"); - urlstr += targetVersion->descriptor() + "/" + targetVersion->descriptor() + ".jar"; - QString targetstr ("versions/"); - targetstr += targetVersion->descriptor() + "/" + targetVersion->descriptor() + ".jar"; - auto dljob = DownloadJob::create(QUrl(urlstr), targetstr); - - jarlibDownloadJob.reset(new JobList()); - jarlibDownloadJob->add(dljob); - connect(jarlibDownloadJob.data(), SIGNAL(finished()), SLOT(jarlibFinished())); - connect(jarlibDownloadJob.data(), SIGNAL(failed()), SLOT(jarlibFailed())); - connect(jarlibDownloadJob.data(), SIGNAL(progress(qint64,qint64)), SLOT(updateDownloadProgress(qint64,qint64))); - // determine and download all the libraries, save them in libraries/whatever... - download_queue.enqueue(jarlibDownloadJob); -} - -void GameUpdateTask::jarlibFinished() -{ - exit(1); -} - -void GameUpdateTask::jarlibFailed() -{ - error("Failed to download the binary garbage. Try again. Maybe. IF YOU DARE"); - exit(0); -} - -void GameUpdateTask::versionFileFailed() -{ - error("Failed to download the version description. Try again."); - exit(0); -} - -void GameUpdateTask::error(const QString &msg) -{ - emit gameUpdateError(msg); -} - -void GameUpdateTask::updateDownloadProgress(qint64 current, qint64 total) -{ - // The progress on the current file is current / total - float currentDLProgress = (float) current / (float) total; - setProgress((int)(currentDLProgress * 100)); // convert to percentage -} - diff --git a/backend/tasks/GameUpdateTask.h b/backend/tasks/GameUpdateTask.h deleted file mode 100644 index f13f42d1..00000000 --- a/backend/tasks/GameUpdateTask.h +++ /dev/null @@ -1,82 +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 "dlqueue.h" - -#include "Task.h" -#include "libmmc_config.h" - -class MinecraftVersion; -class BaseInstance; - -/*! - * The game update task is the task that handles downloading instances' files. - */ -class LIBMULTIMC_EXPORT GameUpdateTask : public Task -{ - Q_OBJECT -public: - explicit GameUpdateTask(BaseInstance *inst, QObject *parent = 0); - - virtual void executeTask(); - -public slots: - virtual void error(const QString &msg); - -private slots: - void updateDownloadProgress(qint64 current, qint64 total); - - void versionFileFinished(); - void versionFileFailed(); - - void jarlibFinished(); - void jarlibFailed(); - -signals: - /*! - * \brief Signal emitted when the game update is complete. - * \param response The login response received from login task. - */ - void gameUpdateComplete(); - - /*! - * \brief Signal emitted if an error occurrs during the update. - * \param errorMsg An error message to be displayed to the user. - */ - void gameUpdateError(const QString &errorMsg); - -private: - BaseInstance *m_inst; - - QString m_subStatusMsg; - - JobListPtr legacyDownloadJob; - JobListPtr specificVersionDownloadJob; - JobListPtr jarlibDownloadJob; - JobListQueue download_queue; - - // target version, determined during this task - MinecraftVersion *targetVersion; -}; - - diff --git a/backend/tasks/LoginTask.cpp b/backend/tasks/LoginTask.cpp index 999a718e..88cdbacc 100644 --- a/backend/tasks/LoginTask.cpp +++ b/backend/tasks/LoginTask.cpp @@ -40,12 +40,11 @@ void LoginTask::executeTask() QUrl loginURL("https://login.minecraft.net/"); QNetworkRequest netRequest(loginURL); - netRequest.setHeader(QNetworkRequest::ContentTypeHeader, - "application/x-www-form-urlencoded"); + netRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded"); QUrlQuery params; - params.addQueryItem("user", uInfo.username()); - params.addQueryItem("password", uInfo.password()); + params.addQueryItem("user", uInfo.username); + params.addQueryItem("password", uInfo.password); params.addQueryItem("version", "13"); netReply = netMgr.post(netRequest, params.query(QUrl::EncodeSpaces).toUtf8()); diff --git a/backend/tasks/LoginTask.h b/backend/tasks/LoginTask.h index cb606204..3f72bb0b 100644 --- a/backend/tasks/LoginTask.h +++ b/backend/tasks/LoginTask.h @@ -18,9 +18,14 @@ #include "Task.h" -#include "UserInfo.h" #include "libmmc_config.h" +struct UserInfo +{ + QString username; + QString password; +}; + struct LoginResponse { QString username; diff --git a/backend/tasks/UserInfo.cpp b/backend/tasks/UserInfo.cpp deleted file mode 100644 index 82225309..00000000 --- a/backend/tasks/UserInfo.cpp +++ /dev/null @@ -1,49 +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 "UserInfo.h" - -UserInfo::UserInfo(const QString &username, const QString &password, QObject *parent) : - QObject(parent) -{ - this->m_username = username; - this->m_password = password; -} - -UserInfo::UserInfo(const UserInfo &other) -{ - this->m_username = other.m_username; - this->m_password = other.m_password; -} - -QString UserInfo::username() const -{ - return m_username; -} - -void UserInfo::setUsername(const QString &username) -{ - this->m_username = username; -} - -QString UserInfo::password() const -{ - return m_password; -} - -void UserInfo::setPassword(const QString &password) -{ - this->m_password = password; -} diff --git a/backend/tasks/UserInfo.h b/backend/tasks/UserInfo.h deleted file mode 100644 index 280f98de..00000000 --- a/backend/tasks/UserInfo.h +++ /dev/null @@ -1,41 +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. - */ - -#ifndef USERINFO_H -#define USERINFO_H - -#include - -#include "libmmc_config.h" - -class LIBMULTIMC_EXPORT UserInfo : public QObject -{ - Q_OBJECT -public: - explicit UserInfo(const QString& username, const QString& password, QObject *parent = 0); - explicit UserInfo(const UserInfo& other); - - QString username() const; - void setUsername(const QString& username); - - QString password() const; - void setPassword(const QString& password); - -protected: - QString m_username; - QString m_password; -}; - -#endif // USERINFO_H diff --git a/gui/mainwindow.cpp b/gui/mainwindow.cpp index d3dee254..25949042 100644 --- a/gui/mainwindow.cpp +++ b/gui/mainwindow.cpp @@ -53,12 +53,12 @@ #include "AppVersion.h" #include "tasks/LoginTask.h" -#include "tasks/GameUpdateTask.h" #include "BaseInstance.h" #include "InstanceFactory.h" #include "MinecraftProcess.h" #include "OneSixAssets.h" +#include "OneSixUpdate.h" #include "instancemodel.h" #include "instancedelegate.h" @@ -393,7 +393,7 @@ void MainWindow::doLogin(const QString& errorMsg) LoginDialog* loginDlg = new LoginDialog(this, errorMsg); if (loginDlg->exec()) { - UserInfo uInfo(loginDlg->getUsername(), loginDlg->getPassword()); + UserInfo uInfo{loginDlg->getUsername(), loginDlg->getPassword()}; TaskDialog* tDialog = new TaskDialog(this); LoginTask* loginTask = new LoginTask(uInfo, tDialog); @@ -412,7 +412,7 @@ void MainWindow::onLoginComplete(LoginResponse response) return; m_activeLogin = LoginResponse(response); - GameUpdateTask *updateTask = m_activeInst->doUpdate(); + OneSixUpdate *updateTask = m_activeInst->doUpdate(); if(!updateTask) { launchInstance(m_activeInst, m_activeLogin); diff --git a/main.cpp b/main.cpp index 468cf438..50fed27f 100644 --- a/main.cpp +++ b/main.cpp @@ -83,7 +83,7 @@ private slots: LoginDialog* loginDlg = new LoginDialog(nullptr, errorMsg); if (loginDlg->exec()) { - UserInfo uInfo(loginDlg->getUsername(), loginDlg->getPassword()); + UserInfo uInfo{loginDlg->getUsername(), loginDlg->getPassword()}; TaskDialog* tDialog = new TaskDialog(nullptr); LoginTask* loginTask = new LoginTask(uInfo, tDialog); -- cgit v1.2.3