Get rid of QNAM (now subclassed and less needy). Basic LWJGL download and extraction.
This commit is contained in:
@ -25,6 +25,7 @@
|
||||
|
||||
#include "libmmc_config.h"
|
||||
|
||||
class BaseUpdate;
|
||||
class MinecraftProcess;
|
||||
class OneSixUpdate;
|
||||
class InstanceList;
|
||||
@ -117,7 +118,7 @@ public:
|
||||
virtual SettingsObject &settings() const;
|
||||
|
||||
/// returns a valid update task if update is needed, NULL otherwise
|
||||
virtual OneSixUpdate* doUpdate() = 0;
|
||||
virtual BaseUpdate* doUpdate() = 0;
|
||||
|
||||
/// returns a valid minecraft process, ready for launch
|
||||
virtual MinecraftProcess* prepareForLaunch(QString user, QString session) = 0;
|
||||
|
18
backend/BaseUpdate.cpp
Normal file
18
backend/BaseUpdate.cpp
Normal file
@ -0,0 +1,18 @@
|
||||
#include "BaseUpdate.h"
|
||||
|
||||
BaseUpdate::BaseUpdate ( BaseInstance* inst, QObject* parent ) : Task ( parent )
|
||||
{
|
||||
m_inst = inst;
|
||||
}
|
||||
|
||||
void BaseUpdate::error ( const QString& msg )
|
||||
{
|
||||
emit gameUpdateError(msg);
|
||||
}
|
||||
|
||||
void BaseUpdate::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
|
||||
}
|
62
backend/BaseUpdate.h
Normal file
62
backend/BaseUpdate.h
Normal file
@ -0,0 +1,62 @@
|
||||
/* 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 <QObject>
|
||||
#include <QList>
|
||||
#include <QUrl>
|
||||
|
||||
#include "net/DownloadJob.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 BaseUpdate : public Task
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit BaseUpdate(BaseInstance *inst, QObject *parent = 0);
|
||||
|
||||
virtual void executeTask() = 0;
|
||||
|
||||
signals:
|
||||
/*!
|
||||
* \brief Signal emitted when the game update is complete.
|
||||
*/
|
||||
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);
|
||||
|
||||
protected slots:
|
||||
virtual void error(const QString &msg);
|
||||
void updateDownloadProgress(qint64 current, qint64 total);
|
||||
|
||||
protected:
|
||||
JobListQueue download_queue;
|
||||
BaseInstance *m_inst;
|
||||
};
|
||||
|
||||
|
@ -24,13 +24,20 @@ libmmc_config.h
|
||||
InstanceVersion.h
|
||||
MinecraftVersion.h
|
||||
InstanceFactory.h
|
||||
BaseUpdate.h
|
||||
BaseInstance.h
|
||||
BaseInstance_p.h
|
||||
MinecraftProcess.h
|
||||
|
||||
# network stuffs
|
||||
net/DownloadJob.h
|
||||
net/JobQueue.h
|
||||
net/NetWorker.h
|
||||
|
||||
# legacy instances
|
||||
LegacyInstance.h
|
||||
LegacyInstance_p.h
|
||||
LegacyUpdate.h
|
||||
|
||||
# 1.6 instances
|
||||
OneSixAssets.h
|
||||
@ -56,11 +63,17 @@ SET(LIBINST_SOURCES
|
||||
InstanceVersion.cpp
|
||||
MinecraftVersion.cpp
|
||||
InstanceFactory.cpp
|
||||
BaseUpdate.cpp
|
||||
BaseInstance.cpp
|
||||
MinecraftProcess.cpp
|
||||
|
||||
# network stuffs
|
||||
net/NetWorker.cpp
|
||||
net/DownloadJob.cpp
|
||||
|
||||
# legacy instances
|
||||
LegacyInstance.cpp
|
||||
LegacyUpdate.cpp
|
||||
|
||||
# 1.6 instances
|
||||
OneSixAssets.cpp
|
||||
@ -93,4 +106,3 @@ add_library(backend SHARED ${LIBINST_SOURCES} ${LIBINST_HEADERS})
|
||||
qt5_use_modules(backend Core Network Xml)
|
||||
target_link_libraries(backend libUtil libSettings quazip)
|
||||
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
#include "LegacyInstance.h"
|
||||
#include "LegacyInstance_p.h"
|
||||
#include "MinecraftProcess.h"
|
||||
#include "LegacyUpdate.h"
|
||||
#include <setting.h>
|
||||
#include <pathutils.h>
|
||||
#include <cmdutils.h>
|
||||
@ -16,7 +17,7 @@ LegacyInstance::LegacyInstance(const QString& rootDir, SettingsObject* settings,
|
||||
settings->registerSetting(new Setting("NeedsRebuild", true));
|
||||
settings->registerSetting(new Setting("ShouldUpdate", false));
|
||||
settings->registerSetting(new Setting("JarVersion", "Unknown"));
|
||||
settings->registerSetting(new Setting("LwjglVersion", "Mojang"));
|
||||
settings->registerSetting(new Setting("LwjglVersion", "2.9.0"));
|
||||
settings->registerSetting(new Setting("IntendedJarVersion", ""));
|
||||
}
|
||||
|
||||
@ -31,10 +32,9 @@ QString LegacyInstance::minecraftDir() const
|
||||
return mcDir.filePath();
|
||||
}
|
||||
|
||||
OneSixUpdate* LegacyInstance::doUpdate()
|
||||
BaseUpdate* LegacyInstance::doUpdate()
|
||||
{
|
||||
// legacy instances no longer update
|
||||
return nullptr;
|
||||
return new LegacyUpdate(this, this);
|
||||
}
|
||||
|
||||
MinecraftProcess* LegacyInstance::prepareForLaunch(QString user, QString session)
|
||||
@ -224,6 +224,6 @@ bool LegacyInstance::setIntendedVersionId ( QString version )
|
||||
}
|
||||
bool LegacyInstance::shouldUpdate() const
|
||||
{
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
void LegacyInstance::setShouldUpdate ( bool val ) {}
|
||||
|
@ -2,6 +2,8 @@
|
||||
|
||||
#include "BaseInstance.h"
|
||||
|
||||
class BaseUpdate;
|
||||
|
||||
class LIBMULTIMC_EXPORT LegacyInstance : public BaseInstance
|
||||
{
|
||||
Q_OBJECT
|
||||
@ -77,7 +79,7 @@ public:
|
||||
|
||||
virtual bool shouldUpdate() const;
|
||||
virtual void setShouldUpdate(bool val);
|
||||
virtual OneSixUpdate* doUpdate();
|
||||
virtual BaseUpdate* doUpdate();
|
||||
|
||||
virtual MinecraftProcess* prepareForLaunch( QString user, QString session );
|
||||
virtual void cleanupAfterRun();
|
||||
|
185
backend/LegacyUpdate.cpp
Normal file
185
backend/LegacyUpdate.cpp
Normal file
@ -0,0 +1,185 @@
|
||||
#include "LegacyUpdate.h"
|
||||
#include "lists/LwjglVersionList.h"
|
||||
#include "BaseInstance.h"
|
||||
#include "LegacyInstance.h"
|
||||
#include "net/NetWorker.h"
|
||||
#include <pathutils.h>
|
||||
#include <quazip.h>
|
||||
#include <quazipfile.h>
|
||||
|
||||
|
||||
LegacyUpdate::LegacyUpdate ( BaseInstance* inst, QObject* parent ) : BaseUpdate ( inst, parent ) {}
|
||||
|
||||
void LegacyUpdate::executeTask()
|
||||
{
|
||||
lwjglStart();
|
||||
}
|
||||
|
||||
void LegacyUpdate::lwjglStart()
|
||||
{
|
||||
LegacyInstance * inst = (LegacyInstance *) m_inst;
|
||||
auto &list = LWJGLVersionList::get();
|
||||
if(!list.isLoaded())
|
||||
{
|
||||
error("Too soon! Let the LWJGL list load :)");
|
||||
emitEnded();
|
||||
return;
|
||||
}
|
||||
QString lwjglVer = inst->lwjglVersion();
|
||||
auto version = list.getVersion(lwjglVer);
|
||||
if(!version)
|
||||
{
|
||||
error("Game update failed: the selected LWJGL version is invalid.");
|
||||
emitEnded();
|
||||
}
|
||||
lwjglVersion = version->name();
|
||||
QString url = version->url();
|
||||
|
||||
auto &worker = NetWorker::spawn();
|
||||
QNetworkRequest req(url);
|
||||
req.setRawHeader("Host", "sourceforge.net");
|
||||
req.setHeader(QNetworkRequest::UserAgentHeader, "Wget/1.14 (linux-gnu)");
|
||||
QNetworkReply * rep = worker.get ( req );
|
||||
|
||||
m_reply = QSharedPointer<QNetworkReply> (rep, &QObject::deleteLater);
|
||||
connect(rep, SIGNAL(downloadProgress(qint64,qint64)), SLOT(updateDownloadProgress(qint64,qint64)));
|
||||
connect(&worker, SIGNAL(finished(QNetworkReply*)), SLOT(lwjglFinished(QNetworkReply*)));
|
||||
//connect(rep, SIGNAL(error(QNetworkReply::NetworkError)), SLOT(downloadError(QNetworkReply::NetworkError)));
|
||||
}
|
||||
|
||||
void LegacyUpdate::lwjglFinished(QNetworkReply* reply)
|
||||
{
|
||||
if(m_reply != reply)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if(reply->error() != QNetworkReply::NoError)
|
||||
{
|
||||
error("Failed to download: " + reply->errorString() + "\nSometimes you have to wait a bit if you download many LWJGL versions in a row. YMMV");
|
||||
emitEnded();
|
||||
return;
|
||||
}
|
||||
auto &worker = NetWorker::spawn();
|
||||
//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)
|
||||
{
|
||||
//you must tell which cookie goes with which url
|
||||
worker.cookieJar()->setCookiesFromUrl(cookies, QUrl("sourceforge.net"));
|
||||
}
|
||||
|
||||
//here you can check for the 302 or whatever other header i need
|
||||
QVariant newLoc = reply->header(QNetworkRequest::LocationHeader);
|
||||
if(newLoc.isValid())
|
||||
{
|
||||
auto &worker = NetWorker::spawn();
|
||||
QString redirectedTo = reply->header(QNetworkRequest::LocationHeader).toString();
|
||||
QNetworkRequest req(redirectedTo);
|
||||
req.setRawHeader("Host", "sourceforge.net");
|
||||
req.setHeader(QNetworkRequest::UserAgentHeader, "Wget/1.14 (linux-gnu)");
|
||||
QNetworkReply * rep = worker.get(req);
|
||||
connect(rep, SIGNAL(downloadProgress(qint64,qint64)), SLOT(updateDownloadProgress(qint64,qint64)));
|
||||
m_reply = QSharedPointer<QNetworkReply> (rep, &QObject::deleteLater);
|
||||
return;
|
||||
}
|
||||
QFile saveMe("lwjgl.zip");
|
||||
saveMe.open(QIODevice::WriteOnly);
|
||||
saveMe.write(m_reply->readAll());
|
||||
saveMe.close();
|
||||
setStatus("Installing new LWJGL...");
|
||||
extractLwjgl();
|
||||
}
|
||||
void LegacyUpdate::extractLwjgl()
|
||||
{
|
||||
// make sure the directories are there
|
||||
QString lwjgl_base = PathCombine("lwjgl", lwjglVersion );
|
||||
QString nativesPath = PathCombine( lwjgl_base, "natives/");
|
||||
bool success = ensurePathExists(nativesPath);
|
||||
|
||||
if(!success)
|
||||
{
|
||||
error("Failed to extract the lwjgl libs - error when creating required folders.");
|
||||
emitEnded();
|
||||
return;
|
||||
}
|
||||
|
||||
QuaZip zip("lwjgl.zip");
|
||||
if(!zip.open(QuaZip::mdUnzip))
|
||||
{
|
||||
error("Failed to extract the lwjgl libs - not a valid archive.");
|
||||
emitEnded();
|
||||
return;
|
||||
}
|
||||
|
||||
// and now we are going to access files inside it
|
||||
QuaZipFile file(&zip);
|
||||
const QString jarNames[] = { "jinput.jar", "lwjgl_util.jar", "lwjgl.jar" };
|
||||
for(bool more=zip.goToFirstFile(); more; more=zip.goToNextFile())
|
||||
{
|
||||
if(!file.open(QIODevice::ReadOnly))
|
||||
{
|
||||
zip.close();
|
||||
error("Failed to extract the lwjgl libs - error while reading archive.");
|
||||
emitEnded();
|
||||
return;
|
||||
}
|
||||
QuaZipFileInfo info;
|
||||
QString name = file.getActualFileName();
|
||||
if(name.endsWith('/'))
|
||||
{
|
||||
file.close();
|
||||
continue;
|
||||
}
|
||||
QString destFileName;
|
||||
// Look for the jars
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
if (name.endsWith(jarNames[i]))
|
||||
{
|
||||
destFileName = PathCombine(lwjgl_base, jarNames[i]);
|
||||
}
|
||||
}
|
||||
// Not found? look for the natives
|
||||
if(destFileName.isEmpty())
|
||||
{
|
||||
#ifdef Q_OS_WIN32
|
||||
QString nativesDir = "windows";
|
||||
#elif Q_OS_MAC
|
||||
QString nativesDir = "macosx";
|
||||
#else
|
||||
QString nativesDir = "linux";
|
||||
#endif
|
||||
if (name.contains(nativesDir))
|
||||
{
|
||||
int lastSlash = name.lastIndexOf('/');
|
||||
int lastBackSlash = name.lastIndexOf('/');
|
||||
if(lastSlash != -1)
|
||||
name = name.mid(lastSlash+1);
|
||||
else if(lastBackSlash != -1)
|
||||
name = name.mid(lastBackSlash+1);
|
||||
destFileName = PathCombine(nativesPath, name);
|
||||
}
|
||||
}
|
||||
// Now if destFileName is still empty, go to the next file.
|
||||
if (!destFileName.isEmpty())
|
||||
{
|
||||
setStatus("Installing new LWJGL - Extracting " + name);
|
||||
QFile output(destFileName);
|
||||
output.open(QIODevice::WriteOnly);
|
||||
output.write(file.readAll()); // FIXME: wste of memory!?
|
||||
output.close();
|
||||
}
|
||||
file.close(); // do not forget to close!
|
||||
}
|
||||
zip.close();
|
||||
m_reply.clear();
|
||||
emit gameUpdateComplete();
|
||||
emitEnded();
|
||||
}
|
||||
|
||||
void LegacyUpdate::lwjglFailed()
|
||||
{
|
||||
error("Bad stuff happened while trying to get the lwjgl libs...");
|
||||
emitEnded();
|
||||
}
|
||||
|
52
backend/LegacyUpdate.h
Normal file
52
backend/LegacyUpdate.h
Normal file
@ -0,0 +1,52 @@
|
||||
/* 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 <QObject>
|
||||
#include <QList>
|
||||
#include <QUrl>
|
||||
|
||||
#include "net/DownloadJob.h"
|
||||
#include "tasks/Task.h"
|
||||
#include "libmmc_config.h"
|
||||
#include "BaseUpdate.h"
|
||||
|
||||
class MinecraftVersion;
|
||||
class BaseInstance;
|
||||
|
||||
class LIBMULTIMC_EXPORT LegacyUpdate : public BaseUpdate
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit LegacyUpdate(BaseInstance *inst, QObject *parent = 0);
|
||||
virtual void executeTask();
|
||||
|
||||
private slots:
|
||||
void lwjglStart();
|
||||
void lwjglFinished( QNetworkReply* );
|
||||
void lwjglFailed();
|
||||
void extractLwjgl();
|
||||
private:
|
||||
|
||||
QSharedPointer<QNetworkReply> m_reply;
|
||||
|
||||
// target version, determined during this task
|
||||
// MinecraftVersion *targetVersion;
|
||||
QString lwjglURL;
|
||||
QString lwjglVersion;
|
||||
};
|
||||
|
||||
|
@ -51,6 +51,9 @@ QString MinecraftVersion::typeName() const
|
||||
case Snapshot:
|
||||
return "Snapshot";
|
||||
|
||||
case Nostalgia:
|
||||
return "Nostalgia";
|
||||
|
||||
default:
|
||||
return QString("Unknown Type %1").arg(versionType());
|
||||
}
|
||||
|
@ -39,6 +39,7 @@ public:
|
||||
Stable,
|
||||
CurrentStable,
|
||||
Snapshot,
|
||||
Nostalgia
|
||||
};
|
||||
|
||||
virtual QString descriptor() const;
|
||||
|
@ -2,7 +2,7 @@
|
||||
#include <QDebug>
|
||||
#include <QtXml/QtXml>
|
||||
#include "OneSixAssets.h"
|
||||
#include "dlqueue.h"
|
||||
#include "net/DownloadJob.h"
|
||||
|
||||
inline QDomElement getDomElementByTagName(QDomElement parent, QString tagname)
|
||||
{
|
||||
@ -138,7 +138,7 @@ void OneSixAssets::fetchFinished()
|
||||
QString trimmedEtag = etagStr.remove ( '"' );
|
||||
nuke_whitelist.append ( keyStr );
|
||||
if(trimmedEtag != client_etag)
|
||||
job->add ( DownloadJob::create ( net_manager, QUrl ( prefix + keyStr ), filename ) );
|
||||
job->add ( DownloadJob::create ( QUrl ( prefix + keyStr ), filename ) );
|
||||
|
||||
}
|
||||
job->add ( JobPtr ( new NukeAndPaveJob ( fprefix, nuke_whitelist ) ) );
|
||||
|
@ -1,5 +1,5 @@
|
||||
#pragma once
|
||||
#include "dlqueue.h"
|
||||
#include "net/DownloadJob.h"
|
||||
|
||||
class Private;
|
||||
|
||||
@ -16,7 +16,6 @@ public slots:
|
||||
public:
|
||||
void start();
|
||||
private:
|
||||
QSharedPointer<QNetworkAccessManager> net_manager {new QNetworkAccessManager()};
|
||||
JobListQueue dl;
|
||||
JobListPtr index_job;
|
||||
JobListPtr files_job;
|
||||
|
@ -18,7 +18,7 @@ OneSixInstance::OneSixInstance ( const QString& rootDir, SettingsObject* setting
|
||||
reloadFullVersion();
|
||||
}
|
||||
|
||||
OneSixUpdate* OneSixInstance::doUpdate()
|
||||
BaseUpdate* OneSixInstance::doUpdate()
|
||||
{
|
||||
return new OneSixUpdate(this);
|
||||
}
|
||||
|
@ -3,13 +3,14 @@
|
||||
#include "BaseInstance.h"
|
||||
#include <QStringList>
|
||||
class FullVersion;
|
||||
class BaseUpdate;
|
||||
|
||||
class LIBMULTIMC_EXPORT OneSixInstance : public BaseInstance
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit OneSixInstance(const QString &rootDir, SettingsObject * settings, QObject *parent = 0);
|
||||
virtual OneSixUpdate* doUpdate();
|
||||
virtual BaseUpdate* doUpdate();
|
||||
virtual MinecraftProcess* prepareForLaunch ( QString user, QString session );
|
||||
virtual void cleanupAfterRun();
|
||||
|
||||
|
@ -33,11 +33,7 @@
|
||||
#include "pathutils.h"
|
||||
|
||||
|
||||
OneSixUpdate::OneSixUpdate(BaseInstance *inst, QObject *parent) :
|
||||
Task(parent)
|
||||
{
|
||||
m_inst = inst;
|
||||
}
|
||||
OneSixUpdate::OneSixUpdate(BaseInstance *inst, QObject *parent):BaseUpdate(inst, parent){}
|
||||
|
||||
void OneSixUpdate::executeTask()
|
||||
{
|
||||
@ -142,7 +138,7 @@ void OneSixUpdate::jarlibStart()
|
||||
{
|
||||
QString download_path = lib->downloadPath();
|
||||
QString storage_path = "libraries/" + lib->storagePath();
|
||||
jarlibDownloadJob->add(DownloadJob::create(net_manager, download_path, storage_path));
|
||||
jarlibDownloadJob->add(DownloadJob::create(download_path, storage_path));
|
||||
}
|
||||
connect(jarlibDownloadJob.data(), SIGNAL(finished()), SLOT(jarlibFinished()));
|
||||
connect(jarlibDownloadJob.data(), SIGNAL(failed()), SLOT(jarlibFailed()));
|
||||
@ -163,15 +159,3 @@ void OneSixUpdate::jarlibFailed()
|
||||
emitEnded();
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
|
@ -16,36 +16,25 @@
|
||||
#pragma once
|
||||
|
||||
#include <QObject>
|
||||
|
||||
#include <QList>
|
||||
|
||||
#include <QNetworkAccessManager>
|
||||
#include <QUrl>
|
||||
#include "dlqueue.h"
|
||||
#include "net/DownloadJob.h"
|
||||
|
||||
#include "tasks/Task.h"
|
||||
#include "libmmc_config.h"
|
||||
#include "BaseUpdate.h"
|
||||
|
||||
class MinecraftVersion;
|
||||
class BaseInstance;
|
||||
|
||||
/*!
|
||||
* The game update task is the task that handles downloading instances' files.
|
||||
*/
|
||||
class LIBMULTIMC_EXPORT OneSixUpdate : public Task
|
||||
class LIBMULTIMC_EXPORT OneSixUpdate : public BaseUpdate
|
||||
{
|
||||
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 versionFileStart();
|
||||
void versionFileFinished();
|
||||
void versionFileFailed();
|
||||
@ -54,25 +43,7 @@ private slots:
|
||||
void jarlibFinished();
|
||||
void jarlibFailed();
|
||||
|
||||
|
||||
signals:
|
||||
/*!
|
||||
* \brief Signal emitted when the game update is complete.
|
||||
*/
|
||||
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;
|
||||
|
||||
QSharedPointer<QNetworkAccessManager> net_manager {new QNetworkAccessManager()};
|
||||
JobListPtr legacyDownloadJob;
|
||||
JobListPtr specificVersionDownloadJob;
|
||||
JobListPtr jarlibDownloadJob;
|
||||
|
@ -13,23 +13,14 @@ enum OpSys
|
||||
|
||||
OpSys OpSys_fromString(QString);
|
||||
|
||||
#ifdef Q_OS_MAC
|
||||
#define currentSystem Os_OSX
|
||||
#endif
|
||||
|
||||
#ifdef Q_OS_LINUX
|
||||
#define currentSystem Os_Linux
|
||||
#endif
|
||||
|
||||
#ifdef Q_OS_WIN32
|
||||
#define currentSystem Os_Windows
|
||||
#elif Q_OS_MAC
|
||||
#define currentSystem Os_OSX
|
||||
#else
|
||||
#define currentSystem Os_Linux
|
||||
#endif
|
||||
|
||||
#ifndef currentSystem
|
||||
#define currentSystem Os_Other
|
||||
#endif
|
||||
|
||||
|
||||
enum RuleAction
|
||||
{
|
||||
Allow,
|
||||
|
@ -80,6 +80,16 @@ QSharedPointer<FullVersion> FullVersionFactory::parse4(QJsonObject root, QShared
|
||||
fullVersion->minecraftArguments = minecraftArgsValue.toString();
|
||||
}
|
||||
|
||||
auto minecraftTypeValue = root.value("type");
|
||||
if(minecraftTypeValue.isString())
|
||||
{
|
||||
QString copy = fullVersion->type = minecraftTypeValue.toString();
|
||||
if(copy == "old_aplha" || copy == "old_beta")
|
||||
{
|
||||
fullVersion->isLegacy = true;
|
||||
}
|
||||
}
|
||||
|
||||
fullVersion->releaseTime = root.value("releaseTime").toString();
|
||||
fullVersion->time = root.value("time").toString();
|
||||
|
||||
@ -107,7 +117,7 @@ QSharedPointer<FullVersion> FullVersionFactory::parse4(QJsonObject root, QShared
|
||||
auto urlVal = libObj.value("url");
|
||||
if(urlVal.isString())
|
||||
{
|
||||
library->setBaseUrl(urlVal.toString());
|
||||
library->setBaseUrl(nameVal.toString());
|
||||
}
|
||||
|
||||
// Extract excludes (if any)
|
||||
@ -175,19 +185,15 @@ QSharedPointer<FullVersion> FullVersionFactory::parse(QByteArray data)
|
||||
}
|
||||
QJsonObject root = jsonDoc.object();
|
||||
|
||||
readVersion->minimumLauncherVersion = root.value("minimumLauncherVersion").toDouble();
|
||||
switch(readVersion->minimumLauncherVersion)
|
||||
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
|
||||
{
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
case 4:
|
||||
return parse4(root, readVersion);
|
||||
// ADD MORE HERE :D
|
||||
default:
|
||||
error_string = "Version file was for an unrecognized launcher version. RIP";
|
||||
m_error = FullVersionFactory::UnsupportedVersion;
|
||||
return QSharedPointer<FullVersion>();
|
||||
error_string = "Version file was for an unrecognized launcher version. RIP";
|
||||
m_error = FullVersionFactory::UnsupportedVersion;
|
||||
return QSharedPointer<FullVersion>();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -14,6 +14,7 @@
|
||||
*/
|
||||
|
||||
#include "LwjglVersionList.h"
|
||||
#include <net/NetWorker.h>
|
||||
|
||||
#include <QtNetwork>
|
||||
|
||||
@ -53,7 +54,7 @@ QVariant LWJGLVersionList::data(const QModelIndex &index, int role) const
|
||||
return version->name();
|
||||
|
||||
case Qt::ToolTipRole:
|
||||
return version->url().toString();
|
||||
return version->url();
|
||||
|
||||
default:
|
||||
return QVariant();
|
||||
@ -90,7 +91,8 @@ void LWJGLVersionList::loadList()
|
||||
Q_ASSERT_X(!m_loading, "loadList", "list is already loading (m_loading is true)");
|
||||
|
||||
setLoading(true);
|
||||
reply = netMgr.get(QNetworkRequest(QUrl(RSS_URL)));
|
||||
auto & worker = NetWorker::spawn();
|
||||
reply = worker.get(QNetworkRequest(QUrl(RSS_URL)));
|
||||
connect(reply, SIGNAL(finished()), SLOT(netRequestComplete()));
|
||||
}
|
||||
|
||||
@ -144,9 +146,9 @@ void LWJGLVersionList::netRequestComplete()
|
||||
// Make sure it's a download link.
|
||||
if (link.endsWith("/download") && link.contains(lwjglRegex))
|
||||
{
|
||||
QString name = link.mid(lwjglRegex.indexIn(link));
|
||||
QString name = link.mid(lwjglRegex.indexIn(link) + 6);
|
||||
// Subtract 4 here to remove the .zip file extension.
|
||||
name = name.left(lwjglRegex.matchedLength() - 4);
|
||||
name = name.left(lwjglRegex.matchedLength() - 10);
|
||||
|
||||
QUrl url(link);
|
||||
if (!url.isValid())
|
||||
@ -179,7 +181,8 @@ const PtrLWJGLVersion LWJGLVersionList::getVersion(const QString &versionName)
|
||||
{
|
||||
for (int i = 0; i < count(); i++)
|
||||
{
|
||||
if (at(i)->name() == versionName)
|
||||
QString name = at(i)->name();
|
||||
if ( name == versionName)
|
||||
return at(i);
|
||||
}
|
||||
return PtrLWJGLVersion();
|
||||
|
@ -20,7 +20,6 @@
|
||||
#include <QSharedPointer>
|
||||
#include <QUrl>
|
||||
|
||||
#include <QNetworkAccessManager>
|
||||
#include <QNetworkReply>
|
||||
|
||||
#include "libmmc_config.h"
|
||||
@ -32,32 +31,22 @@ class LIBMULTIMC_EXPORT LWJGLVersion : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
/*!
|
||||
* The name of the LWJGL version.
|
||||
*/
|
||||
Q_PROPERTY(QString name READ name)
|
||||
|
||||
/*!
|
||||
* The URL for this version of LWJGL.
|
||||
*/
|
||||
Q_PROPERTY(QUrl url READ url)
|
||||
|
||||
LWJGLVersion(const QString &name, const QUrl &url, QObject *parent = 0) :
|
||||
LWJGLVersion(const QString &name, const QString &url, QObject *parent = 0) :
|
||||
QObject(parent), m_name(name), m_url(url) { }
|
||||
public:
|
||||
|
||||
static PtrLWJGLVersion Create(const QString &name, const QUrl &url, QObject *parent = 0)
|
||||
static PtrLWJGLVersion Create(const QString &name, const QString &url, QObject *parent = 0)
|
||||
{
|
||||
return PtrLWJGLVersion(new LWJGLVersion(name, url, parent));
|
||||
};
|
||||
|
||||
QString name() const { return m_name; }
|
||||
|
||||
QUrl url() const { return m_url; }
|
||||
QString url() const { return m_url; }
|
||||
|
||||
protected:
|
||||
QString m_name;
|
||||
QUrl m_url;
|
||||
QString m_url;
|
||||
};
|
||||
|
||||
class LIBMULTIMC_EXPORT LWJGLVersionList : public QAbstractListModel
|
||||
@ -112,8 +101,6 @@ private:
|
||||
QList<PtrLWJGLVersion> m_vlist;
|
||||
|
||||
QNetworkReply *m_netReply;
|
||||
|
||||
QNetworkAccessManager netMgr;
|
||||
QNetworkReply *reply;
|
||||
|
||||
bool m_loading;
|
||||
|
@ -14,6 +14,7 @@
|
||||
*/
|
||||
|
||||
#include "MinecraftVersionList.h"
|
||||
#include <net/NetWorker.h>
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
@ -29,8 +30,6 @@
|
||||
|
||||
#include <QtNetwork>
|
||||
|
||||
#include "netutils.h"
|
||||
|
||||
#define MCVLIST_URLBASE "http://s3.amazonaws.com/Minecraft.Download/versions/"
|
||||
#define ASSETS_URLBASE "http://assets.minecraft.net/"
|
||||
#define MCN_URLBASE "http://sonicrules.org/mcnweb.py"
|
||||
@ -160,21 +159,18 @@ MCVListLoadTask::MCVListLoadTask(MinecraftVersionList *vlist)
|
||||
{
|
||||
m_list = vlist;
|
||||
m_currentStable = NULL;
|
||||
netMgr = nullptr;
|
||||
vlistReply = nullptr;
|
||||
}
|
||||
|
||||
MCVListLoadTask::~MCVListLoadTask()
|
||||
{
|
||||
if(netMgr)
|
||||
netMgr->deleteLater();
|
||||
}
|
||||
|
||||
void MCVListLoadTask::executeTask()
|
||||
{
|
||||
setStatus("Loading instance version list...");
|
||||
netMgr = new QNetworkAccessManager();
|
||||
vlistReply = netMgr->get(QNetworkRequest(QUrl(QString(MCVLIST_URLBASE) + "versions.json")));
|
||||
auto & worker = NetWorker::spawn();
|
||||
vlistReply = worker.get(QNetworkRequest(QUrl(QString(MCVLIST_URLBASE) + "versions.json")));
|
||||
connect(vlistReply, SIGNAL(finished()), this, SLOT(list_downloaded()));
|
||||
}
|
||||
|
||||
@ -283,12 +279,18 @@ void MCVListLoadTask::list_downloaded()
|
||||
{
|
||||
versionType = MinecraftVersion::Snapshot;
|
||||
}
|
||||
else if(versionTypeStr == "old_beta" || versionTypeStr == "old_alpha")
|
||||
{
|
||||
versionType = MinecraftVersion::Nostalgia;
|
||||
}
|
||||
else
|
||||
{
|
||||
//FIXME: log this somewhere
|
||||
continue;
|
||||
}
|
||||
|
||||
//FIXME: detect if snapshots are old or not
|
||||
|
||||
// Get the download URL.
|
||||
QString dlUrl = QString(MCVLIST_URLBASE) + versionID + "/";
|
||||
|
||||
|
@ -24,7 +24,6 @@
|
||||
#include "libmmc_config.h"
|
||||
|
||||
class MCVListLoadTask;
|
||||
class QNetworkAccessManager;
|
||||
class QNetworkReply;
|
||||
|
||||
class LIBMULTIMC_EXPORT MinecraftVersionList : public InstVersionList
|
||||
@ -76,7 +75,6 @@ protected:
|
||||
//! Loads versions from Mojang's official version list.
|
||||
bool loadFromVList();
|
||||
|
||||
QNetworkAccessManager *netMgr;
|
||||
QNetworkReply *vlistReply;
|
||||
|
||||
MinecraftVersionList *m_list;
|
||||
|
138
backend/net/DownloadJob.cpp
Normal file
138
backend/net/DownloadJob.cpp
Normal file
@ -0,0 +1,138 @@
|
||||
#include "DownloadJob.h"
|
||||
#include "pathutils.h"
|
||||
#include "NetWorker.h"
|
||||
|
||||
DownloadJob::DownloadJob (QUrl url,
|
||||
QString target_path,
|
||||
QString expected_md5 )
|
||||
:Job()
|
||||
{
|
||||
m_url = url;
|
||||
m_target_path = target_path;
|
||||
m_expected_md5 = expected_md5;
|
||||
|
||||
m_check_md5 = m_expected_md5.size();
|
||||
m_save_to_file = m_target_path.size();
|
||||
m_status = Job_NotStarted;
|
||||
m_opened_for_saving = false;
|
||||
}
|
||||
|
||||
JobPtr DownloadJob::create (QUrl url,
|
||||
QString target_path,
|
||||
QString expected_md5 )
|
||||
{
|
||||
return JobPtr ( new DownloadJob ( url, target_path, expected_md5 ) );
|
||||
}
|
||||
|
||||
void DownloadJob::start()
|
||||
{
|
||||
if ( m_save_to_file )
|
||||
{
|
||||
QString filename = m_target_path;
|
||||
m_output_file.setFileName ( filename );
|
||||
// if there already is a file and md5 checking is in effect and it can be opened
|
||||
if ( m_output_file.exists() && m_output_file.open ( QIODevice::ReadOnly ) )
|
||||
{
|
||||
// check the md5 against the expected one
|
||||
QString hash = QCryptographicHash::hash ( m_output_file.readAll(), QCryptographicHash::Md5 ).toHex().constData();
|
||||
m_output_file.close();
|
||||
// skip this file if they match
|
||||
if ( m_check_md5 && hash == m_expected_md5 )
|
||||
{
|
||||
qDebug() << "Skipping " << m_url.toString() << ": md5 match.";
|
||||
emit finish();
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_expected_md5 = hash;
|
||||
}
|
||||
}
|
||||
if(!ensurePathExists(filename))
|
||||
{
|
||||
emit fail();
|
||||
return;
|
||||
}
|
||||
}
|
||||
qDebug() << "Downloading " << m_url.toString();
|
||||
QNetworkRequest request ( m_url );
|
||||
request.setRawHeader(QString("If-None-Match").toLatin1(), m_expected_md5.toLatin1());
|
||||
|
||||
auto &worker = NetWorker::spawn();
|
||||
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 DownloadJob::downloadProgress ( qint64 bytesReceived, qint64 bytesTotal )
|
||||
{
|
||||
emit progress ( bytesReceived, bytesTotal );
|
||||
}
|
||||
|
||||
void DownloadJob::downloadError ( QNetworkReply::NetworkError error )
|
||||
{
|
||||
// error happened during download.
|
||||
// TODO: log the reason why
|
||||
m_status = Job_Failed;
|
||||
}
|
||||
|
||||
void DownloadJob::downloadFinished()
|
||||
{
|
||||
// if the download succeeded
|
||||
if ( m_status != Job_Failed )
|
||||
{
|
||||
// nothing went wrong...
|
||||
m_status = Job_Finished;
|
||||
// save the data to the downloadable if we aren't saving to file
|
||||
if ( !m_save_to_file )
|
||||
{
|
||||
m_data = m_reply->readAll();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_output_file.close();
|
||||
}
|
||||
|
||||
//TODO: check md5 here!
|
||||
m_reply.clear();
|
||||
emit finish();
|
||||
return;
|
||||
}
|
||||
// else the download failed
|
||||
else
|
||||
{
|
||||
if ( m_save_to_file )
|
||||
{
|
||||
m_output_file.close();
|
||||
m_output_file.remove();
|
||||
}
|
||||
m_reply.clear();
|
||||
emit fail();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void DownloadJob::downloadReadyRead()
|
||||
{
|
||||
if( m_save_to_file )
|
||||
{
|
||||
if(!m_opened_for_saving)
|
||||
{
|
||||
if ( !m_output_file.open ( QIODevice::WriteOnly ) )
|
||||
{
|
||||
/*
|
||||
* Can't open the file... the job failed
|
||||
*/
|
||||
m_reply->abort();
|
||||
emit fail();
|
||||
return;
|
||||
}
|
||||
m_opened_for_saving = true;
|
||||
}
|
||||
m_output_file.write ( m_reply->readAll() );
|
||||
}
|
||||
}
|
51
backend/net/DownloadJob.h
Normal file
51
backend/net/DownloadJob.h
Normal file
@ -0,0 +1,51 @@
|
||||
#pragma once
|
||||
#include "JobQueue.h"
|
||||
#include <QtNetwork>
|
||||
|
||||
/**
|
||||
* A single file for the downloader/cache to process.
|
||||
*/
|
||||
class LIBUTIL_EXPORT DownloadJob : public Job
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
DownloadJob(QUrl url,
|
||||
QString rel_target_path = QString(),
|
||||
QString expected_md5 = QString()
|
||||
);
|
||||
static JobPtr create(QUrl url, QString rel_target_path = QString(), QString expected_md5 = QString());
|
||||
public slots:
|
||||
virtual void start();
|
||||
|
||||
private slots:
|
||||
void downloadProgress(qint64 bytesReceived, qint64 bytesTotal);;
|
||||
void downloadError(QNetworkReply::NetworkError error);
|
||||
void downloadFinished();
|
||||
void downloadReadyRead();
|
||||
|
||||
public:
|
||||
/// the network reply
|
||||
QSharedPointer<QNetworkReply> m_reply;
|
||||
/// source URL
|
||||
QUrl m_url;
|
||||
|
||||
/// if true, check the md5sum against a provided md5sum
|
||||
/// also, if a file exists, perform an md5sum first and don't download only if they don't match
|
||||
bool m_check_md5;
|
||||
/// the expected md5 checksum
|
||||
QString m_expected_md5;
|
||||
|
||||
/// save to file?
|
||||
bool m_save_to_file;
|
||||
/// is the saving file already open?
|
||||
bool m_opened_for_saving;
|
||||
/// if saving to file, use the one specified in this string
|
||||
QString m_target_path;
|
||||
/// this is the output file, if any
|
||||
QFile m_output_file;
|
||||
/// if not saving to file, downloaded data is placed here
|
||||
QByteArray m_data;
|
||||
|
||||
/// The file's status
|
||||
JobStatus m_status;
|
||||
};
|
180
backend/net/JobQueue.h
Normal file
180
backend/net/JobQueue.h
Normal file
@ -0,0 +1,180 @@
|
||||
#pragma once
|
||||
#include <QtCore>
|
||||
#include "libutil_config.h"
|
||||
|
||||
enum JobStatus
|
||||
{
|
||||
Job_NotStarted,
|
||||
Job_InProgress,
|
||||
Job_Finished,
|
||||
Job_Failed
|
||||
};
|
||||
|
||||
class JobList;
|
||||
|
||||
class LIBUTIL_EXPORT Job : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
protected:
|
||||
explicit Job(): QObject(0){};
|
||||
public:
|
||||
virtual ~Job() {};
|
||||
signals:
|
||||
void finish();
|
||||
void fail();
|
||||
void progress(qint64 current, qint64 total);
|
||||
public slots:
|
||||
virtual void start() = 0;
|
||||
};
|
||||
typedef QSharedPointer<Job> JobPtr;
|
||||
|
||||
/**
|
||||
* A list of jobs, to be processed one by one.
|
||||
*/
|
||||
class LIBUTIL_EXPORT JobList : public QObject
|
||||
{
|
||||
friend class JobListQueue;
|
||||
Q_OBJECT
|
||||
public:
|
||||
|
||||
JobList() : QObject(0)
|
||||
{
|
||||
m_status = Job_NotStarted;
|
||||
current_job_idx = 0;
|
||||
}
|
||||
JobStatus getStatus()
|
||||
{
|
||||
return m_status;
|
||||
}
|
||||
void add(JobPtr dlable)
|
||||
{
|
||||
if(m_status == Job_NotStarted)
|
||||
m_jobs.append(dlable);
|
||||
//else there's a bug. TODO: catch the bugs
|
||||
}
|
||||
JobPtr getFirstJob()
|
||||
{
|
||||
if(m_jobs.size())
|
||||
return m_jobs[0];
|
||||
else
|
||||
return JobPtr();
|
||||
}
|
||||
void start()
|
||||
{
|
||||
current_job_idx = 0;
|
||||
auto job = m_jobs[current_job_idx];
|
||||
|
||||
connect(job.data(), SIGNAL(progress(qint64,qint64)), SLOT(currentJobProgress(qint64,qint64)));
|
||||
connect(job.data(), SIGNAL(finish()), SLOT(currentJobFinished()));
|
||||
connect(job.data(), SIGNAL(fail()), SLOT(currentJobFailed()));
|
||||
job->start();
|
||||
emit started();
|
||||
}
|
||||
private slots:
|
||||
void currentJobFinished()
|
||||
{
|
||||
if(current_job_idx == m_jobs.size() - 1)
|
||||
{
|
||||
m_status = Job_Finished;
|
||||
emit finished();
|
||||
}
|
||||
else
|
||||
{
|
||||
current_job_idx++;
|
||||
auto job = m_jobs[current_job_idx];
|
||||
connect(job.data(), SIGNAL(progress(qint64,qint64)), SLOT(currentJobProgress(qint64,qint64)));
|
||||
connect(job.data(), SIGNAL(finish()), SLOT(currentJobFinished()));
|
||||
connect(job.data(), SIGNAL(fail()), SLOT(currentJobFailed()));
|
||||
job->start();
|
||||
}
|
||||
}
|
||||
void currentJobFailed()
|
||||
{
|
||||
m_status = Job_Failed;
|
||||
emit failed();
|
||||
}
|
||||
void currentJobProgress(qint64 current, qint64 total)
|
||||
{
|
||||
if(!total)
|
||||
return;
|
||||
|
||||
int total_jobs = m_jobs.size();
|
||||
|
||||
if(!total_jobs)
|
||||
return;
|
||||
|
||||
float job_chunk = 1000.0 / float(total_jobs);
|
||||
float cur = current;
|
||||
float tot = total;
|
||||
float last_chunk = (cur / tot) * job_chunk;
|
||||
|
||||
float list_total = job_chunk * current_job_idx + last_chunk;
|
||||
emit progress(qint64(list_total), 1000LL);
|
||||
}
|
||||
private:
|
||||
QVector<JobPtr> m_jobs;
|
||||
/// The overall status of this job list
|
||||
JobStatus m_status;
|
||||
int current_job_idx;
|
||||
signals:
|
||||
void progress(qint64 current, qint64 total);
|
||||
void started();
|
||||
void finished();
|
||||
void failed();
|
||||
};
|
||||
typedef QSharedPointer<JobList> JobListPtr;
|
||||
|
||||
|
||||
/**
|
||||
* A queue of job lists! The job lists fail or finish as units.
|
||||
*/
|
||||
class LIBUTIL_EXPORT JobListQueue : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
JobListQueue(QObject *p = 0):
|
||||
QObject(p),
|
||||
currentIndex(0),
|
||||
is_running(false){}
|
||||
|
||||
void enqueue(JobListPtr job)
|
||||
{
|
||||
jobs.enqueue(job);
|
||||
|
||||
// finish or fail, we should catch that and start the next one
|
||||
connect(job.data(),SIGNAL(finished()), SLOT(startNextJob()));
|
||||
connect(job.data(),SIGNAL(failed()), SLOT(startNextJob()));
|
||||
|
||||
if(!is_running)
|
||||
{
|
||||
QTimer::singleShot(0, this, SLOT(startNextJob()));
|
||||
}
|
||||
}
|
||||
|
||||
private slots:
|
||||
void startNextJob()
|
||||
{
|
||||
if (jobs.isEmpty())
|
||||
{
|
||||
currentJobList.clear();
|
||||
currentIndex = 0;
|
||||
is_running = false;
|
||||
emit finishedAllJobs();
|
||||
return;
|
||||
}
|
||||
|
||||
currentJobList = jobs.dequeue();
|
||||
is_running = true;
|
||||
currentIndex = 0;
|
||||
currentJobList->start();
|
||||
}
|
||||
|
||||
signals:
|
||||
void finishedAllJobs();
|
||||
|
||||
private:
|
||||
JobListPtr currentJobList;
|
||||
QQueue<JobListPtr> jobs;
|
||||
unsigned currentIndex;
|
||||
bool is_running;
|
||||
};
|
12
backend/net/NetWorker.cpp
Normal file
12
backend/net/NetWorker.cpp
Normal file
@ -0,0 +1,12 @@
|
||||
#include "NetWorker.h"
|
||||
#include <QThreadStorage>
|
||||
|
||||
NetWorker& NetWorker::spawn()
|
||||
{
|
||||
static QThreadStorage<NetWorker *> storage;
|
||||
if (!storage.hasLocalData())
|
||||
{
|
||||
storage.setLocalData(new NetWorker());
|
||||
}
|
||||
return *storage.localData();
|
||||
}
|
20
backend/net/NetWorker.h
Normal file
20
backend/net/NetWorker.h
Normal file
@ -0,0 +1,20 @@
|
||||
/*
|
||||
_.ooo-._
|
||||
.OOOP _ '.
|
||||
dOOOO (_) \
|
||||
OOOOOb |
|
||||
OOOOOOb. |
|
||||
OOOOOOOOb |
|
||||
YOO(_)OOO /
|
||||
'OOOOOY _.'
|
||||
'""""''
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <QNetworkAccessManager>
|
||||
class NetWorker : public QNetworkAccessManager
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
static NetWorker &spawn();
|
||||
};
|
@ -14,27 +14,23 @@
|
||||
*/
|
||||
|
||||
#include "LoginTask.h"
|
||||
#include <net/NetWorker.h>
|
||||
|
||||
#include <QStringList>
|
||||
|
||||
#include <QtNetwork/QNetworkAccessManager>
|
||||
#include <QtNetwork/QNetworkReply>
|
||||
#include <QtNetwork/QNetworkRequest>
|
||||
#include <QNetworkReply>
|
||||
#include <QNetworkRequest>
|
||||
|
||||
#include <QUrl>
|
||||
#include <QUrlQuery>
|
||||
|
||||
LoginTask::LoginTask( const UserInfo& uInfo, QObject* parent ) :
|
||||
Task(parent), uInfo(uInfo)
|
||||
{
|
||||
netMgr.reset(new QNetworkAccessManager());
|
||||
}
|
||||
LoginTask::LoginTask( const UserInfo& uInfo, QObject* parent ) : Task(parent), uInfo(uInfo){}
|
||||
|
||||
void LoginTask::executeTask()
|
||||
{
|
||||
setStatus("Logging in...");
|
||||
|
||||
connect(netMgr.data(), SIGNAL(finished(QNetworkReply*)), this, SLOT(processNetReply(QNetworkReply*)));
|
||||
auto & worker = NetWorker::spawn();
|
||||
connect(&worker, SIGNAL(finished(QNetworkReply*)), this, SLOT(processNetReply(QNetworkReply*)));
|
||||
|
||||
QUrl loginURL("https://login.minecraft.net/");
|
||||
QNetworkRequest netRequest(loginURL);
|
||||
@ -45,11 +41,13 @@ void LoginTask::executeTask()
|
||||
params.addQueryItem("password", uInfo.password);
|
||||
params.addQueryItem("version", "13");
|
||||
|
||||
netReply = netMgr->post(netRequest, params.query(QUrl::EncodeSpaces).toUtf8());
|
||||
netReply = worker.post(netRequest, params.query(QUrl::EncodeSpaces).toUtf8());
|
||||
}
|
||||
|
||||
void LoginTask::processNetReply(QNetworkReply *reply)
|
||||
{
|
||||
if(netReply != reply)
|
||||
return;
|
||||
// Check for errors.
|
||||
switch (reply->error())
|
||||
{
|
||||
|
@ -33,7 +33,6 @@ struct LoginResponse
|
||||
qint64 latestVersion;
|
||||
};
|
||||
|
||||
class QNetworkAccessManager;
|
||||
class QNetworkReply;
|
||||
|
||||
class LIBMULTIMC_EXPORT LoginTask : public Task
|
||||
@ -54,8 +53,6 @@ protected:
|
||||
|
||||
QNetworkReply* netReply;
|
||||
UserInfo uInfo;
|
||||
private:
|
||||
QSharedPointer<QNetworkAccessManager> netMgr;
|
||||
};
|
||||
|
||||
#endif // LOGINTASK_H
|
||||
|
Reference in New Issue
Block a user