NOISSUE Some happy little refactors
This commit is contained in:
@ -85,9 +85,9 @@ std::shared_ptr<class VersionFile> Component::getVersionFile() const
|
||||
std::shared_ptr<class Meta::VersionList> Component::getVersionList() const
|
||||
{
|
||||
// FIXME: what if the metadata index isn't loaded yet?
|
||||
if(ENV.metadataIndex()->hasUid(m_uid))
|
||||
if(ENV->metadataIndex()->hasUid(m_uid))
|
||||
{
|
||||
return ENV.metadataIndex()->get(m_uid);
|
||||
return ENV->metadataIndex()->get(m_uid);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
@ -192,7 +192,7 @@ bool Component::isRevertible()
|
||||
{
|
||||
if (isCustom())
|
||||
{
|
||||
if(ENV.metadataIndex()->hasUid(m_uid))
|
||||
if(ENV->metadataIndex()->hasUid(m_uid))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@ -266,7 +266,7 @@ void Component::setVersion(const QString& version)
|
||||
// we don't have a file, therefore we are loaded with metadata
|
||||
m_cachedVersion = version;
|
||||
// see if the meta version is loaded
|
||||
auto metaVersion = ENV.metadataIndex()->get(m_uid, version);
|
||||
auto metaVersion = ENV->metadataIndex()->get(m_uid, version);
|
||||
if(metaVersion->isLoaded())
|
||||
{
|
||||
// if yes, we can continue with that.
|
||||
@ -350,7 +350,7 @@ bool Component::revert()
|
||||
m_file.reset();
|
||||
|
||||
// check local cache for metadata...
|
||||
auto version = ENV.metadataIndex()->get(m_uid, m_version);
|
||||
auto version = ENV->metadataIndex()->get(m_uid, m_version);
|
||||
if(version->isLoaded())
|
||||
{
|
||||
m_metaVersion = version;
|
||||
|
@ -102,7 +102,7 @@ static LoadResult loadComponent(ComponentPtr component, shared_qobject_ptr<Task>
|
||||
}
|
||||
else
|
||||
{
|
||||
auto metaVersion = ENV.metadataIndex()->get(component->m_uid, component->m_version);
|
||||
auto metaVersion = ENV->metadataIndex()->get(component->m_uid, component->m_version);
|
||||
component->m_metaVersion = metaVersion;
|
||||
if(metaVersion->isLoaded())
|
||||
{
|
||||
@ -135,7 +135,7 @@ static LoadResult loadPackProfile(ComponentPtr component, shared_qobject_ptr<Tas
|
||||
}
|
||||
|
||||
LoadResult result = LoadResult::Failed;
|
||||
auto metaList = ENV.metadataIndex()->get(component->m_uid);
|
||||
auto metaList = ENV->metadataIndex()->get(component->m_uid);
|
||||
if(metaList->isLoaded())
|
||||
{
|
||||
component->m_loaded = true;
|
||||
@ -154,13 +154,13 @@ static LoadResult loadPackProfile(ComponentPtr component, shared_qobject_ptr<Tas
|
||||
static LoadResult loadIndex(shared_qobject_ptr<Task>& loadTask, Net::Mode netmode)
|
||||
{
|
||||
// FIXME: DECIDE. do we want to run the update task anyway?
|
||||
if(ENV.metadataIndex()->isLoaded())
|
||||
if(ENV->metadataIndex()->isLoaded())
|
||||
{
|
||||
qDebug() << "Index is already loaded";
|
||||
return LoadResult::LoadedLocal;
|
||||
}
|
||||
ENV.metadataIndex()->load(netmode);
|
||||
loadTask = ENV.metadataIndex()->getCurrentTask();
|
||||
ENV->metadataIndex()->load(netmode);
|
||||
loadTask = ENV->metadataIndex()->getCurrentTask();
|
||||
if(loadTask)
|
||||
{
|
||||
return LoadResult::RequiresRemote;
|
||||
|
@ -816,7 +816,7 @@ shared_qobject_ptr<LaunchTask> MinecraftInstance::createLaunchTask(AuthSessionPt
|
||||
auto process = LaunchTask::create(std::dynamic_pointer_cast<MinecraftInstance>(shared_from_this()));
|
||||
auto pptr = process.get();
|
||||
|
||||
ENV.icons()->saveIcon(iconKey(), FS::PathCombine(gameRoot(), "icon.png"), "PNG");
|
||||
ENV->icons()->saveIcon(iconKey(), FS::PathCombine(gameRoot(), "icon.png"), "PNG");
|
||||
|
||||
// print a header
|
||||
{
|
||||
|
@ -481,7 +481,7 @@ bool PackProfile::migratePreComponentConfig()
|
||||
}
|
||||
else if(!intendedVersion.isEmpty())
|
||||
{
|
||||
auto metaVersion = ENV.metadataIndex()->get(uid, intendedVersion);
|
||||
auto metaVersion = ENV->metadataIndex()->get(uid, intendedVersion);
|
||||
component = new Component(this, metaVersion);
|
||||
}
|
||||
else
|
||||
@ -546,7 +546,7 @@ bool PackProfile::migratePreComponentConfig()
|
||||
auto patchVersion = d->getOldConfigVersion(uid);
|
||||
if(!patchVersion.isEmpty() && !loadedComponents.contains(uid))
|
||||
{
|
||||
auto patch = new Component(this, ENV.metadataIndex()->get(uid, patchVersion));
|
||||
auto patch = new Component(this, ENV->metadataIndex()->get(uid, patchVersion));
|
||||
patch->setOrder(order);
|
||||
loadedComponents[uid] = patch;
|
||||
}
|
||||
|
@ -37,6 +37,8 @@ enum AccountListVersion {
|
||||
|
||||
AccountList::AccountList(QObject *parent) : QAbstractListModel(parent) { }
|
||||
|
||||
AccountList::~AccountList() noexcept {}
|
||||
|
||||
int AccountList::findAccountByProfileId(const QString& profileId) const {
|
||||
for (int i = 0; i < count(); i++) {
|
||||
MinecraftAccountPtr account = at(i);
|
||||
@ -62,6 +64,18 @@ const MinecraftAccountPtr AccountList::at(int i) const
|
||||
return MinecraftAccountPtr(m_accounts.at(i));
|
||||
}
|
||||
|
||||
QStringList AccountList::profileNames() const {
|
||||
QStringList out;
|
||||
for(auto & account: m_accounts) {
|
||||
auto profileName = account->profileName();
|
||||
if(profileName.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
out.append(profileName);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
void AccountList::addAccount(const MinecraftAccountPtr account)
|
||||
{
|
||||
auto profileId = account->profileId();
|
||||
@ -71,8 +85,8 @@ void AccountList::addAccount(const MinecraftAccountPtr account)
|
||||
if(existingAccount != -1) {
|
||||
MinecraftAccountPtr existingAccountPtr = m_accounts[existingAccount];
|
||||
m_accounts[existingAccount] = account;
|
||||
if(m_activeAccount == existingAccountPtr) {
|
||||
m_activeAccount = account;
|
||||
if(m_defaultAccount == existingAccountPtr) {
|
||||
m_defaultAccount = account;
|
||||
}
|
||||
emit dataChanged(index(existingAccount), index(existingAccount, columnCount(QModelIndex()) - 1));
|
||||
onListChanged();
|
||||
@ -80,10 +94,11 @@ void AccountList::addAccount(const MinecraftAccountPtr account)
|
||||
}
|
||||
}
|
||||
|
||||
// if we don't have this porfileId yet, add the account to the end
|
||||
// if we don't have this profileId yet, add the account to the end
|
||||
int row = m_accounts.count();
|
||||
beginInsertRows(QModelIndex(), row, row);
|
||||
connect(account.get(), SIGNAL(changed()), SLOT(accountChanged()));
|
||||
connect(account.get(), &MinecraftAccount::changed, this, &AccountList::accountChanged);
|
||||
connect(account.get(), &MinecraftAccount::activityChanged, this, &AccountList::accountActivityChanged);
|
||||
m_accounts.append(account);
|
||||
endInsertRows();
|
||||
onListChanged();
|
||||
@ -95,10 +110,10 @@ void AccountList::removeAccount(QModelIndex index)
|
||||
if(index.isValid() && row >= 0 && row < m_accounts.size())
|
||||
{
|
||||
auto & account = m_accounts[row];
|
||||
if(account == m_activeAccount)
|
||||
if(account == m_defaultAccount)
|
||||
{
|
||||
m_activeAccount = nullptr;
|
||||
onActiveChanged();
|
||||
m_defaultAccount = nullptr;
|
||||
onDefaultAccountChanged();
|
||||
}
|
||||
beginRemoveRows(QModelIndex(), row, row);
|
||||
m_accounts.removeAt(index.row());
|
||||
@ -107,54 +122,54 @@ void AccountList::removeAccount(QModelIndex index)
|
||||
}
|
||||
}
|
||||
|
||||
MinecraftAccountPtr AccountList::activeAccount() const
|
||||
MinecraftAccountPtr AccountList::defaultAccount() const
|
||||
{
|
||||
return m_activeAccount;
|
||||
return m_defaultAccount;
|
||||
}
|
||||
|
||||
void AccountList::setActiveAccount(MinecraftAccountPtr newAccount)
|
||||
void AccountList::setDefaultAccount(MinecraftAccountPtr newAccount)
|
||||
{
|
||||
if (!newAccount && m_activeAccount)
|
||||
if (!newAccount && m_defaultAccount)
|
||||
{
|
||||
int idx = 0;
|
||||
auto prevActiveAcc = m_activeAccount;
|
||||
m_activeAccount = nullptr;
|
||||
auto previousDefaultAccount = m_defaultAccount;
|
||||
m_defaultAccount = nullptr;
|
||||
for (MinecraftAccountPtr account : m_accounts)
|
||||
{
|
||||
if (account == prevActiveAcc)
|
||||
if (account == previousDefaultAccount)
|
||||
{
|
||||
emit dataChanged(index(idx), index(idx));
|
||||
emit dataChanged(index(idx), index(idx, columnCount(QModelIndex()) - 1));
|
||||
}
|
||||
idx ++;
|
||||
}
|
||||
onActiveChanged();
|
||||
onDefaultAccountChanged();
|
||||
}
|
||||
else
|
||||
{
|
||||
auto currentActiveAccount = m_activeAccount;
|
||||
int currentActiveAccountIdx = -1;
|
||||
auto newActiveAccount = m_activeAccount;
|
||||
int newActiveAccountIdx = -1;
|
||||
auto currentDefaultAccount = m_defaultAccount;
|
||||
int currentDefaultAccountIdx = -1;
|
||||
auto newDefaultAccount = m_defaultAccount;
|
||||
int newDefaultAccountIdx = -1;
|
||||
int idx = 0;
|
||||
for (MinecraftAccountPtr account : m_accounts)
|
||||
{
|
||||
if (account == newAccount)
|
||||
{
|
||||
newActiveAccount = account;
|
||||
newActiveAccountIdx = idx;
|
||||
newDefaultAccount = account;
|
||||
newDefaultAccountIdx = idx;
|
||||
}
|
||||
if(currentActiveAccount == account)
|
||||
if(currentDefaultAccount == account)
|
||||
{
|
||||
currentActiveAccountIdx = idx;
|
||||
currentDefaultAccountIdx = idx;
|
||||
}
|
||||
idx++;
|
||||
}
|
||||
if(currentActiveAccount != newActiveAccount)
|
||||
if(currentDefaultAccount != newDefaultAccount)
|
||||
{
|
||||
emit dataChanged(index(currentActiveAccountIdx), index(currentActiveAccountIdx));
|
||||
emit dataChanged(index(newActiveAccountIdx), index(newActiveAccountIdx));
|
||||
m_activeAccount = newActiveAccount;
|
||||
onActiveChanged();
|
||||
emit dataChanged(index(currentDefaultAccountIdx), index(currentDefaultAccountIdx, columnCount(QModelIndex()) - 1));
|
||||
emit dataChanged(index(newDefaultAccountIdx), index(newDefaultAccountIdx, columnCount(QModelIndex()) - 1));
|
||||
m_defaultAccount = newDefaultAccount;
|
||||
onDefaultAccountChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -165,6 +180,23 @@ void AccountList::accountChanged()
|
||||
onListChanged();
|
||||
}
|
||||
|
||||
void AccountList::accountActivityChanged(bool active)
|
||||
{
|
||||
MinecraftAccount *account = qobject_cast<MinecraftAccount *>(sender());
|
||||
bool found = false;
|
||||
for (int i = 0; i < count(); i++) {
|
||||
if (at(i).get() == account) {
|
||||
emit dataChanged(index(i), index(i, columnCount(QModelIndex()) - 1));
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(found) {
|
||||
emit listActivityChanged();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void AccountList::onListChanged()
|
||||
{
|
||||
if (m_autosave)
|
||||
@ -174,12 +206,12 @@ void AccountList::onListChanged()
|
||||
emit listChanged();
|
||||
}
|
||||
|
||||
void AccountList::onActiveChanged()
|
||||
void AccountList::onDefaultAccountChanged()
|
||||
{
|
||||
if (m_autosave)
|
||||
saveList();
|
||||
|
||||
emit activeAccountChanged();
|
||||
emit defaultAccountChanged();
|
||||
}
|
||||
|
||||
int AccountList::count() const
|
||||
@ -211,6 +243,11 @@ QVariant AccountList::data(const QModelIndex &index, int role) const
|
||||
return typeStr;
|
||||
}
|
||||
|
||||
case StatusColumn: {
|
||||
auto isActive = account->isActive();
|
||||
return isActive ? "Working" : "Ready";
|
||||
}
|
||||
|
||||
case ProfileNameColumn: {
|
||||
return account->profileName();
|
||||
}
|
||||
@ -235,13 +272,13 @@ QVariant AccountList::data(const QModelIndex &index, int role) const
|
||||
return account->accountDisplayString();
|
||||
|
||||
case PointerRole:
|
||||
return qVariantFromValue(account);
|
||||
return QVariant::fromValue(account);
|
||||
|
||||
case Qt::CheckStateRole:
|
||||
switch (index.column())
|
||||
{
|
||||
case NameColumn:
|
||||
return account == m_activeAccount ? Qt::Checked : Qt::Unchecked;
|
||||
return account == m_defaultAccount ? Qt::Checked : Qt::Unchecked;
|
||||
}
|
||||
|
||||
default:
|
||||
@ -260,6 +297,8 @@ QVariant AccountList::headerData(int section, Qt::Orientation orientation, int r
|
||||
return tr("Account");
|
||||
case TypeColumn:
|
||||
return tr("Type");
|
||||
case StatusColumn:
|
||||
return tr("Status");
|
||||
case MigrationColumn:
|
||||
return tr("Can Migrate?");
|
||||
case ProfileNameColumn:
|
||||
@ -275,6 +314,8 @@ QVariant AccountList::headerData(int section, Qt::Orientation orientation, int r
|
||||
return tr("User name of the account.");
|
||||
case TypeColumn:
|
||||
return tr("Type of the account - Mojang or MSA.");
|
||||
case StatusColumn:
|
||||
return tr("Current status of the account.");
|
||||
case MigrationColumn:
|
||||
return tr("Can this account migrate to Microsoft account?");
|
||||
case ProfileNameColumn:
|
||||
@ -309,9 +350,9 @@ Qt::ItemFlags AccountList::flags(const QModelIndex &index) const
|
||||
return Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsSelectable;
|
||||
}
|
||||
|
||||
bool AccountList::setData(const QModelIndex &index, const QVariant &value, int role)
|
||||
bool AccountList::setData(const QModelIndex &idx, const QVariant &value, int role)
|
||||
{
|
||||
if (index.row() < 0 || index.row() >= rowCount(index) || !index.isValid())
|
||||
if (idx.row() < 0 || idx.row() >= rowCount(idx) || !idx.isValid())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@ -320,12 +361,12 @@ bool AccountList::setData(const QModelIndex &index, const QVariant &value, int r
|
||||
{
|
||||
if(value == Qt::Checked)
|
||||
{
|
||||
MinecraftAccountPtr account = at(index.row());
|
||||
setActiveAccount(account);
|
||||
MinecraftAccountPtr account = at(idx.row());
|
||||
setDefaultAccount(account);
|
||||
}
|
||||
}
|
||||
|
||||
emit dataChanged(index, index);
|
||||
emit dataChanged(idx, index(idx.row(), columnCount(QModelIndex()) - 1));
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -395,7 +436,7 @@ bool AccountList::loadList()
|
||||
|
||||
bool AccountList::loadV2(QJsonObject& root) {
|
||||
beginResetModel();
|
||||
auto activeUserName = root.value("activeAccount").toString("");
|
||||
auto defaultUserName = root.value("activeAccount").toString("");
|
||||
QJsonArray accounts = root.value("accounts").toArray();
|
||||
for (QJsonValue accountVal : accounts)
|
||||
{
|
||||
@ -411,9 +452,10 @@ bool AccountList::loadV2(QJsonObject& root) {
|
||||
continue;
|
||||
}
|
||||
connect(account.get(), &MinecraftAccount::changed, this, &AccountList::accountChanged);
|
||||
connect(account.get(), &MinecraftAccount::activityChanged, this, &AccountList::accountActivityChanged);
|
||||
m_accounts.append(account);
|
||||
if (activeUserName.size() && account->mojangUserName() == activeUserName) {
|
||||
m_activeAccount = account;
|
||||
if (defaultUserName.size() && account->mojangUserName() == defaultUserName) {
|
||||
m_defaultAccount = account;
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -441,9 +483,10 @@ bool AccountList::loadV3(QJsonObject& root) {
|
||||
}
|
||||
}
|
||||
connect(account.get(), &MinecraftAccount::changed, this, &AccountList::accountChanged);
|
||||
connect(account.get(), &MinecraftAccount::activityChanged, this, &AccountList::accountActivityChanged);
|
||||
m_accounts.append(account);
|
||||
if(accountObj.value("active").toBool(false)) {
|
||||
m_activeAccount = account;
|
||||
m_defaultAccount = account;
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -490,7 +533,7 @@ bool AccountList::saveList()
|
||||
for (MinecraftAccountPtr account : m_accounts)
|
||||
{
|
||||
QJsonObject accountObj = account->saveToJson();
|
||||
if(m_activeAccount == account) {
|
||||
if(m_defaultAccount == account) {
|
||||
accountObj["active"] = true;
|
||||
}
|
||||
accounts.append(accountObj);
|
||||
|
@ -42,11 +42,13 @@ public:
|
||||
ProfileNameColumn,
|
||||
MigrationColumn,
|
||||
TypeColumn,
|
||||
StatusColumn,
|
||||
|
||||
NUM_COLUMNS
|
||||
};
|
||||
|
||||
explicit AccountList(QObject *parent = 0);
|
||||
virtual ~AccountList() noexcept;
|
||||
|
||||
const MinecraftAccountPtr at(int i) const;
|
||||
int count() const;
|
||||
@ -63,6 +65,7 @@ public:
|
||||
void removeAccount(QModelIndex index);
|
||||
int findAccountByProfileId(const QString &profileId) const;
|
||||
MinecraftAccountPtr getAccountByProfileName(const QString &profileName) const;
|
||||
QStringList profileNames() const;
|
||||
|
||||
/*!
|
||||
* Sets the path to load/save the list file from/to.
|
||||
@ -78,13 +81,14 @@ public:
|
||||
bool loadV3(QJsonObject &root);
|
||||
bool saveList();
|
||||
|
||||
MinecraftAccountPtr activeAccount() const;
|
||||
void setActiveAccount(MinecraftAccountPtr profileId);
|
||||
MinecraftAccountPtr defaultAccount() const;
|
||||
void setDefaultAccount(MinecraftAccountPtr profileId);
|
||||
bool anyAccountIsValid();
|
||||
|
||||
signals:
|
||||
void listChanged();
|
||||
void activeAccountChanged();
|
||||
void listActivityChanged();
|
||||
void defaultAccountChanged();
|
||||
|
||||
public slots:
|
||||
/**
|
||||
@ -92,6 +96,11 @@ public slots:
|
||||
*/
|
||||
void accountChanged();
|
||||
|
||||
/**
|
||||
* This is called when a (refresh/login) task involving the account starts or ends
|
||||
*/
|
||||
void accountActivityChanged(bool active);
|
||||
|
||||
protected:
|
||||
/*!
|
||||
* Called whenever the list changes.
|
||||
@ -101,13 +110,13 @@ protected:
|
||||
|
||||
/*!
|
||||
* Called whenever the active account changes.
|
||||
* Emits the activeAccountChanged() signal and autosaves the list if enabled.
|
||||
* Emits the defaultAccountChanged() signal and autosaves the list if enabled.
|
||||
*/
|
||||
void onActiveChanged();
|
||||
void onDefaultAccountChanged();
|
||||
|
||||
QList<MinecraftAccountPtr> m_accounts;
|
||||
|
||||
MinecraftAccountPtr m_activeAccount;
|
||||
MinecraftAccountPtr m_defaultAccount;
|
||||
|
||||
//! Path to the account list file. Empty string if there isn't one.
|
||||
QString m_listFilePath;
|
||||
|
@ -23,10 +23,6 @@
|
||||
#include <QNetworkReply>
|
||||
#include <QByteArray>
|
||||
|
||||
#include <Env.h>
|
||||
|
||||
#include <BuildConfig.h>
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
AccountTask::AccountTask(AccountData *data, QObject *parent)
|
||||
|
@ -3,8 +3,10 @@
|
||||
#include <QString>
|
||||
#include <QMultiMap>
|
||||
#include <memory>
|
||||
#include "QObjectPtr.h"
|
||||
|
||||
class MinecraftAccount;
|
||||
class QNetworkAccessManager;
|
||||
|
||||
struct AuthSession
|
||||
{
|
||||
@ -41,7 +43,6 @@ struct AuthSession
|
||||
bool auth_server_online = false;
|
||||
// Did the user request online mode?
|
||||
bool wants_online = true;
|
||||
std::shared_ptr<MinecraftAccount> m_accountPtr;
|
||||
};
|
||||
|
||||
typedef std::shared_ptr<AuthSession> AuthSessionPtr;
|
||||
|
@ -28,11 +28,11 @@
|
||||
#include <QDebug>
|
||||
|
||||
#include <QPainter>
|
||||
#include <minecraft/auth/flows/MSASilent.h>
|
||||
#include <minecraft/auth/flows/MSAInteractive.h>
|
||||
#include "flows/MSASilent.h"
|
||||
#include "flows/MSAInteractive.h"
|
||||
|
||||
#include <minecraft/auth/flows/MojangRefresh.h>
|
||||
#include <minecraft/auth/flows/MojangLogin.h>
|
||||
#include "flows/MojangRefresh.h"
|
||||
#include "flows/MojangLogin.h"
|
||||
|
||||
MinecraftAccountPtr MinecraftAccount::loadFromJsonV2(const QJsonObject& json) {
|
||||
MinecraftAccountPtr account(new MinecraftAccount());
|
||||
@ -104,7 +104,7 @@ QPixmap MinecraftAccount::getFace() const {
|
||||
}
|
||||
|
||||
|
||||
std::shared_ptr<AccountTask> MinecraftAccount::login(AuthSessionPtr session, QString password)
|
||||
shared_qobject_ptr<AccountTask> MinecraftAccount::login(AuthSessionPtr session, QString password)
|
||||
{
|
||||
Q_ASSERT(m_currentTask.get() == nullptr);
|
||||
|
||||
@ -140,11 +140,12 @@ std::shared_ptr<AccountTask> MinecraftAccount::login(AuthSessionPtr session, QSt
|
||||
|
||||
connect(m_currentTask.get(), SIGNAL(succeeded()), SLOT(authSucceeded()));
|
||||
connect(m_currentTask.get(), SIGNAL(failed(QString)), SLOT(authFailed(QString)));
|
||||
emit activityChanged(true);
|
||||
}
|
||||
return m_currentTask;
|
||||
}
|
||||
|
||||
std::shared_ptr<AccountTask> MinecraftAccount::loginMSA(AuthSessionPtr session) {
|
||||
shared_qobject_ptr<AccountTask> MinecraftAccount::loginMSA(AuthSessionPtr session) {
|
||||
Q_ASSERT(m_currentTask.get() == nullptr);
|
||||
|
||||
if(accountStatus() == Verified && !session->wants_online)
|
||||
@ -161,11 +162,12 @@ std::shared_ptr<AccountTask> MinecraftAccount::loginMSA(AuthSessionPtr session)
|
||||
|
||||
connect(m_currentTask.get(), SIGNAL(succeeded()), SLOT(authSucceeded()));
|
||||
connect(m_currentTask.get(), SIGNAL(failed(QString)), SLOT(authFailed(QString)));
|
||||
emit activityChanged(true);
|
||||
}
|
||||
return m_currentTask;
|
||||
}
|
||||
|
||||
std::shared_ptr<AccountTask> MinecraftAccount::refresh(AuthSessionPtr session) {
|
||||
shared_qobject_ptr<AccountTask> MinecraftAccount::refresh(AuthSessionPtr session) {
|
||||
Q_ASSERT(m_currentTask.get() == nullptr);
|
||||
|
||||
// take care of the true offline status
|
||||
@ -203,6 +205,7 @@ std::shared_ptr<AccountTask> MinecraftAccount::refresh(AuthSessionPtr session) {
|
||||
|
||||
connect(m_currentTask.get(), SIGNAL(succeeded()), SLOT(authSucceeded()));
|
||||
connect(m_currentTask.get(), SIGNAL(failed(QString)), SLOT(authFailed(QString)));
|
||||
emit activityChanged(true);
|
||||
}
|
||||
return m_currentTask;
|
||||
}
|
||||
@ -233,6 +236,7 @@ void MinecraftAccount::authSucceeded()
|
||||
}
|
||||
m_currentTask.reset();
|
||||
emit changed();
|
||||
emit activityChanged(false);
|
||||
}
|
||||
|
||||
void MinecraftAccount::authFailed(QString reason)
|
||||
@ -297,6 +301,45 @@ void MinecraftAccount::authFailed(QString reason)
|
||||
}
|
||||
}
|
||||
m_currentTask.reset();
|
||||
emit activityChanged(false);
|
||||
}
|
||||
|
||||
bool MinecraftAccount::isActive() const {
|
||||
return m_currentTask;
|
||||
}
|
||||
|
||||
bool MinecraftAccount::shouldRefresh() const {
|
||||
/*
|
||||
* Never refresh accounts that are being used by the game, it breaks the game session.
|
||||
* Always refresh accounts that have not been refreshed yet during this session.
|
||||
* Don't refresh broken accounts.
|
||||
* Refresh accounts that would expire in the next 12 hours (fresh token validity is 24 hours).
|
||||
*/
|
||||
if(isInUse()) {
|
||||
return false;
|
||||
}
|
||||
switch(data.validity_) {
|
||||
case Katabasis::Validity::Certain: {
|
||||
break;
|
||||
}
|
||||
case Katabasis::Validity::None: {
|
||||
return false;
|
||||
}
|
||||
case Katabasis::Validity::Assumed: {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
auto now = QDateTime::currentDateTimeUtc();
|
||||
auto issuedTimestamp = data.yggdrasilToken.issueInstant;
|
||||
auto expiresTimestamp = data.yggdrasilToken.notAfter;
|
||||
|
||||
if(!expiresTimestamp.isValid()) {
|
||||
expiresTimestamp = issuedTimestamp.addSecs(24 * 3600);
|
||||
}
|
||||
if (now.secsTo(expiresTimestamp) < 12 * 3600) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void MinecraftAccount::fillSession(AuthSessionPtr session)
|
||||
@ -322,7 +365,6 @@ void MinecraftAccount::fillSession(AuthSessionPtr session)
|
||||
{
|
||||
session->session = "-";
|
||||
}
|
||||
session->m_accountPtr = shared_from_this();
|
||||
}
|
||||
|
||||
void MinecraftAccount::decrementUses()
|
||||
|
@ -27,12 +27,13 @@
|
||||
#include "AuthSession.h"
|
||||
#include "Usable.h"
|
||||
#include "AccountData.h"
|
||||
#include "QObjectPtr.h"
|
||||
|
||||
class Task;
|
||||
class AccountTask;
|
||||
class MinecraftAccount;
|
||||
|
||||
typedef std::shared_ptr<MinecraftAccount> MinecraftAccountPtr;
|
||||
typedef shared_qobject_ptr<MinecraftAccount> MinecraftAccountPtr;
|
||||
Q_DECLARE_METATYPE(MinecraftAccountPtr)
|
||||
|
||||
/**
|
||||
@ -63,8 +64,7 @@ enum AccountStatus
|
||||
*/
|
||||
class MinecraftAccount :
|
||||
public QObject,
|
||||
public Usable,
|
||||
public std::enable_shared_from_this<MinecraftAccount>
|
||||
public Usable
|
||||
{
|
||||
Q_OBJECT
|
||||
public: /* construction */
|
||||
@ -90,11 +90,11 @@ public: /* manipulation */
|
||||
* Attempt to login. Empty password means we use the token.
|
||||
* If the attempt fails because we already are performing some task, it returns false.
|
||||
*/
|
||||
std::shared_ptr<AccountTask> login(AuthSessionPtr session, QString password = QString());
|
||||
shared_qobject_ptr<AccountTask> login(AuthSessionPtr session, QString password);
|
||||
|
||||
std::shared_ptr<AccountTask> loginMSA(AuthSessionPtr session);
|
||||
shared_qobject_ptr<AccountTask> loginMSA(AuthSessionPtr session);
|
||||
|
||||
std::shared_ptr<AccountTask> refresh(AuthSessionPtr session);
|
||||
shared_qobject_ptr<AccountTask> refresh(AuthSessionPtr session);
|
||||
|
||||
public: /* queries */
|
||||
QString accountDisplayString() const {
|
||||
@ -117,6 +117,8 @@ public: /* queries */
|
||||
return data.profileName();
|
||||
}
|
||||
|
||||
bool isActive() const;
|
||||
|
||||
bool canMigrate() const {
|
||||
return data.canMigrateToMSA;
|
||||
}
|
||||
@ -153,19 +155,23 @@ public: /* queries */
|
||||
return &data;
|
||||
}
|
||||
|
||||
bool shouldRefresh() const;
|
||||
|
||||
signals:
|
||||
/**
|
||||
* This signal is emitted when the account changes
|
||||
*/
|
||||
void changed();
|
||||
|
||||
void activityChanged(bool active);
|
||||
|
||||
// TODO: better signalling for the various possible state changes - especially errors
|
||||
|
||||
protected: /* variables */
|
||||
AccountData data;
|
||||
|
||||
// current task we are executing here
|
||||
std::shared_ptr<AccountTask> m_currentTask;
|
||||
shared_qobject_ptr<AccountTask> m_currentTask;
|
||||
|
||||
protected: /* methods */
|
||||
|
||||
|
@ -4,28 +4,21 @@
|
||||
#include <QDesktopServices>
|
||||
#include <QMetaEnum>
|
||||
#include <QDebug>
|
||||
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonObject>
|
||||
#include <QJsonArray>
|
||||
|
||||
#include <QUuid>
|
||||
|
||||
#include <QUrlQuery>
|
||||
|
||||
#include <QPixmap>
|
||||
#include <QPainter>
|
||||
|
||||
#include "AuthContext.h"
|
||||
#include "katabasis/Globals.h"
|
||||
#include "AuthRequest.h"
|
||||
|
||||
#include "Secrets.h"
|
||||
|
||||
#include "Env.h"
|
||||
|
||||
#include "Parsers.h"
|
||||
|
||||
#include <Application.h>
|
||||
#include <Env.h>
|
||||
|
||||
using OAuth2 = Katabasis::OAuth2;
|
||||
using Activity = Katabasis::Activity;
|
||||
|
||||
@ -58,19 +51,14 @@ void AuthContext::initMSA() {
|
||||
return;
|
||||
}
|
||||
|
||||
auto clientId = Secrets::getMSAClientID('-');
|
||||
if(clientId.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
Katabasis::OAuth2::Options opts;
|
||||
opts.scope = "XboxLive.signin offline_access";
|
||||
opts.clientIdentifier = clientId;
|
||||
opts.clientIdentifier = APPLICATION->msaClientId();
|
||||
opts.authorizationUrl = "https://login.microsoftonline.com/consumers/oauth2/v2.0/devicecode";
|
||||
opts.accessTokenUrl = "https://login.microsoftonline.com/consumers/oauth2/v2.0/token";
|
||||
opts.listenerPorts = {28562, 28563, 28564, 28565, 28566};
|
||||
|
||||
m_oauth2 = new OAuth2(opts, m_data->msaToken, this, &ENV.network());
|
||||
m_oauth2 = new OAuth2(opts, m_data->msaToken, this, &ENV->network());
|
||||
m_oauth2->setGrantFlow(Katabasis::OAuth2::GrantFlowDevice);
|
||||
|
||||
connect(m_oauth2, &OAuth2::linkingFailed, this, &AuthContext::onOAuthLinkingFailed);
|
||||
|
@ -7,7 +7,8 @@
|
||||
|
||||
#include "AuthRequest.h"
|
||||
#include "katabasis/Globals.h"
|
||||
#include "Env.h"
|
||||
|
||||
#include <Env.h>
|
||||
|
||||
AuthRequest::AuthRequest(QObject *parent): QObject(parent) {
|
||||
}
|
||||
@ -17,7 +18,7 @@ AuthRequest::~AuthRequest() {
|
||||
|
||||
void AuthRequest::get(const QNetworkRequest &req, int timeout/* = 60*1000*/) {
|
||||
setup(req, QNetworkAccessManager::GetOperation);
|
||||
reply_ = ENV.network().get(request_);
|
||||
reply_ = ENV->network().get(request_);
|
||||
status_ = Requesting;
|
||||
timedReplies_.add(new Katabasis::Reply(reply_, timeout));
|
||||
connect(reply_, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(onRequestError(QNetworkReply::NetworkError)));
|
||||
@ -29,7 +30,7 @@ void AuthRequest::post(const QNetworkRequest &req, const QByteArray &data, int t
|
||||
setup(req, QNetworkAccessManager::PostOperation);
|
||||
data_ = data;
|
||||
status_ = Requesting;
|
||||
reply_ = ENV.network().post(request_, data_);
|
||||
reply_ = ENV->network().post(request_, data_);
|
||||
timedReplies_.add(new Katabasis::Reply(reply_, timeout));
|
||||
connect(reply_, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(onRequestError(QNetworkReply::NetworkError)));
|
||||
connect(reply_, SIGNAL(finished()), this, SLOT(onRequestFinished()));
|
||||
@ -89,7 +90,7 @@ void AuthRequest::onUploadProgress(qint64 uploaded, qint64 total) {
|
||||
emit uploadProgress(uploaded, total);
|
||||
}
|
||||
|
||||
void AuthRequest::setup(const QNetworkRequest &req, QNetworkAccessManager::Operation operation) {
|
||||
void AuthRequest::setup(const QNetworkRequest &req, QNetworkAccessManager::Operation operation, const QByteArray &verb) {
|
||||
request_ = req;
|
||||
operation_ = operation;
|
||||
url_ = req.url();
|
||||
@ -97,6 +98,10 @@ void AuthRequest::setup(const QNetworkRequest &req, QNetworkAccessManager::Opera
|
||||
QUrl url = url_;
|
||||
request_.setUrl(url);
|
||||
|
||||
if (!verb.isEmpty()) {
|
||||
request_.setRawHeader(Katabasis::HTTP_HTTP_HEADER, verb);
|
||||
}
|
||||
|
||||
status_ = Requesting;
|
||||
error_ = QNetworkReply::NoError;
|
||||
}
|
||||
|
@ -5,7 +5,6 @@
|
||||
#include <QNetworkAccessManager>
|
||||
#include <QUrl>
|
||||
#include <QByteArray>
|
||||
#include <QHttpMultiPart>
|
||||
|
||||
#include "katabasis/Reply.h"
|
||||
|
||||
@ -48,7 +47,7 @@ protected slots:
|
||||
void onUploadProgress(qint64 uploaded, qint64 total);
|
||||
|
||||
protected:
|
||||
void setup(const QNetworkRequest &request, QNetworkAccessManager::Operation operation);
|
||||
void setup(const QNetworkRequest &request, QNetworkAccessManager::Operation operation, const QByteArray &verb = QByteArray());
|
||||
|
||||
enum Status {
|
||||
Idle, Requesting, ReRequesting
|
||||
|
@ -1,6 +1,9 @@
|
||||
#include "MSAInteractive.h"
|
||||
|
||||
MSAInteractive::MSAInteractive(AccountData* data, QObject* parent) : AuthContext(data, parent) {}
|
||||
MSAInteractive::MSAInteractive(
|
||||
AccountData* data,
|
||||
QObject* parent
|
||||
) : AuthContext(data, parent) {}
|
||||
|
||||
void MSAInteractive::executeTask() {
|
||||
m_requestsDone = 0;
|
||||
|
@ -5,6 +5,9 @@ class MSAInteractive : public AuthContext
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit MSAInteractive(AccountData * data, QObject *parent = 0);
|
||||
explicit MSAInteractive(
|
||||
AccountData *data,
|
||||
QObject *parent = 0
|
||||
);
|
||||
void executeTask() override;
|
||||
};
|
||||
|
@ -5,6 +5,9 @@ class MSASilent : public AuthContext
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit MSASilent(AccountData * data, QObject *parent = 0);
|
||||
explicit MSASilent(
|
||||
AccountData * data,
|
||||
QObject *parent = 0
|
||||
);
|
||||
void executeTask() override;
|
||||
};
|
||||
|
@ -1,6 +1,10 @@
|
||||
#include "MojangLogin.h"
|
||||
|
||||
MojangLogin::MojangLogin(AccountData* data, QString password, QObject* parent) : AuthContext(data, parent), m_password(password) {}
|
||||
MojangLogin::MojangLogin(
|
||||
AccountData *data,
|
||||
QString password,
|
||||
QObject *parent
|
||||
): AuthContext(data, parent), m_password(password) {}
|
||||
|
||||
void MojangLogin::executeTask() {
|
||||
m_requestsDone = 0;
|
||||
|
@ -5,7 +5,11 @@ class MojangLogin : public AuthContext
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit MojangLogin(AccountData * data, QString password, QObject *parent = 0);
|
||||
explicit MojangLogin(
|
||||
AccountData *data,
|
||||
QString password,
|
||||
QObject *parent = 0
|
||||
);
|
||||
void executeTask() override;
|
||||
|
||||
private:
|
||||
|
@ -1,6 +1,9 @@
|
||||
#include "MojangRefresh.h"
|
||||
|
||||
MojangRefresh::MojangRefresh(AccountData* data, QObject* parent) : AuthContext(data, parent) {}
|
||||
MojangRefresh::MojangRefresh(
|
||||
AccountData *data,
|
||||
QObject *parent
|
||||
) : AuthContext(data, parent) {}
|
||||
|
||||
void MojangRefresh::executeTask() {
|
||||
m_requestsDone = 0;
|
||||
|
@ -5,6 +5,6 @@ class MojangRefresh : public AuthContext
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit MojangRefresh(AccountData * data, QObject *parent = 0);
|
||||
explicit MojangRefresh(AccountData *data, QObject *parent = 0);
|
||||
void executeTask() override;
|
||||
};
|
||||
|
@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "minecraft/auth/AccountData.h"
|
||||
#include "../AccountData.h"
|
||||
|
||||
namespace Parsers
|
||||
{
|
||||
|
@ -23,12 +23,10 @@
|
||||
#include <QNetworkReply>
|
||||
#include <QByteArray>
|
||||
|
||||
#include <Env.h>
|
||||
|
||||
#include <BuildConfig.h>
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
#include <Env.h>
|
||||
|
||||
Yggdrasil::Yggdrasil(AccountData *data, QObject *parent)
|
||||
: AccountTask(data, parent)
|
||||
{
|
||||
@ -40,7 +38,7 @@ void Yggdrasil::sendRequest(QUrl endpoint, QByteArray content) {
|
||||
|
||||
QNetworkRequest netRequest(endpoint);
|
||||
netRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
|
||||
m_netReply = ENV.network().post(netRequest, content);
|
||||
m_netReply = ENV->network().post(netRequest, content);
|
||||
connect(m_netReply, &QNetworkReply::finished, this, &Yggdrasil::processReply);
|
||||
connect(m_netReply, &QNetworkReply::uploadProgress, this, &Yggdrasil::refreshTimers);
|
||||
connect(m_netReply, &QNetworkReply::downloadProgress, this, &Yggdrasil::refreshTimers);
|
||||
@ -86,7 +84,7 @@ void Yggdrasil::refresh() {
|
||||
req.insert("requestUser", false);
|
||||
QJsonDocument doc(req);
|
||||
|
||||
QUrl reqUrl(BuildConfig.AUTH_BASE + "refresh");
|
||||
QUrl reqUrl("https://authserver.mojang.com/refresh");
|
||||
QByteArray requestData = doc.toJson();
|
||||
|
||||
sendRequest(reqUrl, requestData);
|
||||
@ -131,7 +129,7 @@ void Yggdrasil::login(QString password) {
|
||||
|
||||
QJsonDocument doc(req);
|
||||
|
||||
QUrl reqUrl(BuildConfig.AUTH_BASE + "authenticate");
|
||||
QUrl reqUrl("https://authserver.mojang.com/authenticate");
|
||||
QNetworkRequest netRequest(reqUrl);
|
||||
QByteArray requestData = doc.toJson();
|
||||
|
||||
@ -140,20 +138,18 @@ void Yggdrasil::login(QString password) {
|
||||
|
||||
|
||||
|
||||
void Yggdrasil::refreshTimers(qint64, qint64)
|
||||
{
|
||||
void Yggdrasil::refreshTimers(qint64, qint64) {
|
||||
timeout_keeper.stop();
|
||||
timeout_keeper.start(timeout_max);
|
||||
progress(count = 0, timeout_max);
|
||||
}
|
||||
void Yggdrasil::heartbeat()
|
||||
{
|
||||
|
||||
void Yggdrasil::heartbeat() {
|
||||
count += time_step;
|
||||
progress(count, timeout_max);
|
||||
}
|
||||
|
||||
bool Yggdrasil::abort()
|
||||
{
|
||||
bool Yggdrasil::abort() {
|
||||
progress(timeout_max, timeout_max);
|
||||
// TODO: actually use this in a meaningful way
|
||||
m_aborted = Yggdrasil::BY_USER;
|
||||
@ -161,19 +157,16 @@ bool Yggdrasil::abort()
|
||||
return true;
|
||||
}
|
||||
|
||||
void Yggdrasil::abortByTimeout()
|
||||
{
|
||||
void Yggdrasil::abortByTimeout() {
|
||||
progress(timeout_max, timeout_max);
|
||||
// TODO: actually use this in a meaningful way
|
||||
m_aborted = Yggdrasil::BY_TIMEOUT;
|
||||
m_netReply->abort();
|
||||
}
|
||||
|
||||
void Yggdrasil::sslErrors(QList<QSslError> errors)
|
||||
{
|
||||
void Yggdrasil::sslErrors(QList<QSslError> errors) {
|
||||
int i = 1;
|
||||
for (auto error : errors)
|
||||
{
|
||||
for (auto error : errors) {
|
||||
qCritical() << "LOGIN SSL Error #" << i << " : " << error.errorString();
|
||||
auto cert = error.certificate();
|
||||
qCritical() << "Certificate in question:\n" << cert.toText();
|
||||
@ -181,8 +174,7 @@ void Yggdrasil::sslErrors(QList<QSslError> errors)
|
||||
}
|
||||
}
|
||||
|
||||
void Yggdrasil::processResponse(QJsonObject responseData)
|
||||
{
|
||||
void Yggdrasil::processResponse(QJsonObject responseData) {
|
||||
// Read the response data. We need to get the client token, access token, and the selected
|
||||
// profile.
|
||||
qDebug() << "Processing authentication response.";
|
||||
@ -191,8 +183,7 @@ void Yggdrasil::processResponse(QJsonObject responseData)
|
||||
// If we already have a client token, make sure the one the server gave us matches our
|
||||
// existing one.
|
||||
QString clientToken = responseData.value("clientToken").toString("");
|
||||
if (clientToken.isEmpty())
|
||||
{
|
||||
if (clientToken.isEmpty()) {
|
||||
// Fail if the server gave us an empty client token
|
||||
changeState(STATE_FAILED_HARD, tr("Authentication server didn't send a client token."));
|
||||
return;
|
||||
@ -208,8 +199,7 @@ void Yggdrasil::processResponse(QJsonObject responseData)
|
||||
// Now, we set the access token.
|
||||
qDebug() << "Getting access token.";
|
||||
QString accessToken = responseData.value("accessToken").toString("");
|
||||
if (accessToken.isEmpty())
|
||||
{
|
||||
if (accessToken.isEmpty()) {
|
||||
// Fail if the server didn't give us an access token.
|
||||
changeState(STATE_FAILED_HARD, tr("Authentication server didn't send an access token."));
|
||||
return;
|
||||
@ -217,6 +207,7 @@ void Yggdrasil::processResponse(QJsonObject responseData)
|
||||
// Set the access token.
|
||||
m_data->yggdrasilToken.token = accessToken;
|
||||
m_data->yggdrasilToken.validity = Katabasis::Validity::Certain;
|
||||
m_data->yggdrasilToken.issueInstant = QDateTime::currentDateTimeUtc();
|
||||
|
||||
// We've made it through the minefield of possible errors. Return true to indicate that
|
||||
// we've succeeded.
|
||||
@ -224,8 +215,7 @@ void Yggdrasil::processResponse(QJsonObject responseData)
|
||||
changeState(STATE_SUCCEEDED);
|
||||
}
|
||||
|
||||
void Yggdrasil::processReply()
|
||||
{
|
||||
void Yggdrasil::processReply() {
|
||||
changeState(STATE_WORKING);
|
||||
|
||||
switch (m_netReply->error())
|
||||
@ -247,9 +237,9 @@ void Yggdrasil::processReply()
|
||||
"<li>You use Windows and need to update your root certificates, please install any outstanding updates.</li>"
|
||||
"<li>Some device on your network is interfering with SSL traffic. In that case, "
|
||||
"you have bigger worries than Minecraft not starting.</li>"
|
||||
"<li>Possibly something else. Check the %1 log file for details</li>"
|
||||
"<li>Possibly something else. Check the log file for details</li>"
|
||||
"</ul>"
|
||||
).arg(BuildConfig.LAUNCHER_NAME)
|
||||
)
|
||||
);
|
||||
return;
|
||||
// used for invalid credentials and similar errors. Fall through.
|
||||
@ -278,19 +268,16 @@ void Yggdrasil::processReply()
|
||||
// Check the response code.
|
||||
int responseCode = m_netReply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
|
||||
|
||||
if (responseCode == 200)
|
||||
{
|
||||
if (responseCode == 200) {
|
||||
// If the response code was 200, then there shouldn't be an error. Make sure
|
||||
// anyways.
|
||||
// Also, sometimes an empty reply indicates success. If there was no data received,
|
||||
// pass an empty json object to the processResponse function.
|
||||
if (jsonError.error == QJsonParseError::NoError || replyData.size() == 0)
|
||||
{
|
||||
if (jsonError.error == QJsonParseError::NoError || replyData.size() == 0) {
|
||||
processResponse(replyData.size() > 0 ? doc.object() : QJsonObject());
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
changeState(
|
||||
STATE_FAILED_SOFT,
|
||||
tr("Failed to parse authentication server response JSON response: %1 at offset %2.").arg(jsonError.errorString()).arg(jsonError.offset)
|
||||
@ -304,16 +291,14 @@ void Yggdrasil::processReply()
|
||||
// about the error.
|
||||
// If we can parse the response, then get information from it. Otherwise just say
|
||||
// there was an unknown error.
|
||||
if (jsonError.error == QJsonParseError::NoError)
|
||||
{
|
||||
if (jsonError.error == QJsonParseError::NoError) {
|
||||
// We were able to parse the server's response. Woo!
|
||||
// Call processError. If a subclass has overridden it then they'll handle their
|
||||
// stuff there.
|
||||
qDebug() << "The request failed, but the server gave us an error message. Processing error.";
|
||||
processError(doc.object());
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
// The server didn't say anything regarding the error. Give the user an unknown
|
||||
// error.
|
||||
qDebug() << "The request failed and the server gave no error message. Unknown error.";
|
||||
@ -324,14 +309,12 @@ void Yggdrasil::processReply()
|
||||
}
|
||||
}
|
||||
|
||||
void Yggdrasil::processError(QJsonObject responseData)
|
||||
{
|
||||
void Yggdrasil::processError(QJsonObject responseData) {
|
||||
QJsonValue errorVal = responseData.value("error");
|
||||
QJsonValue errorMessageValue = responseData.value("errorMessage");
|
||||
QJsonValue causeVal = responseData.value("cause");
|
||||
|
||||
if (errorVal.isString() && errorMessageValue.isString())
|
||||
{
|
||||
if (errorVal.isString() && errorMessageValue.isString()) {
|
||||
m_error = std::shared_ptr<Error>(
|
||||
new Error {
|
||||
errorVal.toString(""),
|
||||
@ -341,8 +324,7 @@ void Yggdrasil::processError(QJsonObject responseData)
|
||||
);
|
||||
changeState(STATE_FAILED_HARD, m_error->m_errorMessageVerbose);
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
// Error is not in standard format. Don't set m_error and return unknown error.
|
||||
changeState(STATE_FAILED_HARD, tr("An unknown Yggdrasil error occurred."));
|
||||
}
|
||||
|
@ -24,6 +24,7 @@
|
||||
|
||||
#include "../MinecraftAccount.h"
|
||||
|
||||
class QNetworkAccessManager;
|
||||
class QNetworkReply;
|
||||
|
||||
/**
|
||||
@ -33,7 +34,10 @@ class Yggdrasil : public AccountTask
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit Yggdrasil(AccountData * data, QObject *parent = 0);
|
||||
explicit Yggdrasil(
|
||||
AccountData *data,
|
||||
QObject *parent = 0
|
||||
);
|
||||
virtual ~Yggdrasil() {};
|
||||
|
||||
void refresh();
|
||||
|
@ -1,11 +1,15 @@
|
||||
#include "ClaimAccount.h"
|
||||
#include <launch/LaunchTask.h>
|
||||
|
||||
#include "Application.h"
|
||||
#include "minecraft/auth/AccountList.h"
|
||||
|
||||
ClaimAccount::ClaimAccount(LaunchTask* parent, AuthSessionPtr session): LaunchStep(parent)
|
||||
{
|
||||
if(session->status == AuthSession::Status::PlayableOnline)
|
||||
{
|
||||
m_account = session->m_accountPtr;
|
||||
auto accounts = APPLICATION->accounts();
|
||||
m_account = accounts->getAccountByProfileName(session->player_name);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -72,7 +72,7 @@ void LauncherPartLaunch::executeTask()
|
||||
m_process.setDetachable(true);
|
||||
|
||||
auto classPath = minecraftInstance->getClassPath();
|
||||
classPath.prepend(FS::PathCombine(ENV.getJarsPath(), "NewLaunch.jar"));
|
||||
classPath.prepend(FS::PathCombine(ENV->getJarsPath(), "NewLaunch.jar"));
|
||||
|
||||
auto natPath = minecraftInstance->getNativePath();
|
||||
#ifdef Q_OS_WIN
|
||||
|
@ -12,7 +12,7 @@ void CapeChange::setCape(QString& cape) {
|
||||
QNetworkRequest request(QUrl("https://api.minecraftservices.com/minecraft/profile/capes/active"));
|
||||
auto requestString = QString("{\"capeId\":\"%1\"}").arg(m_capeId);
|
||||
request.setRawHeader("Authorization", QString("Bearer %1").arg(m_session->access_token).toLocal8Bit());
|
||||
QNetworkReply *rep = ENV.network().put(request, requestString.toUtf8());
|
||||
QNetworkReply *rep = ENV->network().put(request, requestString.toUtf8());
|
||||
|
||||
setStatus(tr("Equipping cape"));
|
||||
|
||||
@ -26,7 +26,7 @@ void CapeChange::clearCape() {
|
||||
QNetworkRequest request(QUrl("https://api.minecraftservices.com/minecraft/profile/capes/active"));
|
||||
auto requestString = QString("{\"capeId\":\"%1\"}").arg(m_capeId);
|
||||
request.setRawHeader("Authorization", QString("Bearer %1").arg(m_session->access_token).toLocal8Bit());
|
||||
QNetworkReply *rep = ENV.network().deleteResource(request);
|
||||
QNetworkReply *rep = ENV->network().deleteResource(request);
|
||||
|
||||
setStatus(tr("Removing cape"));
|
||||
|
||||
|
@ -12,7 +12,7 @@ void SkinDelete::executeTask()
|
||||
{
|
||||
QNetworkRequest request(QUrl("https://api.minecraftservices.com/minecraft/profile/skins/active"));
|
||||
request.setRawHeader("Authorization", QString("Bearer %1").arg(m_session->access_token).toLocal8Bit());
|
||||
QNetworkReply *rep = ENV.network().deleteResource(request);
|
||||
QNetworkReply *rep = ENV->network().deleteResource(request);
|
||||
m_reply = std::shared_ptr<QNetworkReply>(rep);
|
||||
|
||||
setStatus(tr("Deleting skin"));
|
||||
|
@ -37,7 +37,7 @@ void SkinUpload::executeTask()
|
||||
multiPart->append(skin);
|
||||
multiPart->append(model);
|
||||
|
||||
QNetworkReply *rep = ENV.network().post(request, multiPart);
|
||||
QNetworkReply *rep = ENV->network().post(request, multiPart);
|
||||
m_reply = std::shared_ptr<QNetworkReply>(rep);
|
||||
|
||||
setStatus(tr("Uploading skin"));
|
||||
|
@ -24,7 +24,7 @@ void AssetUpdateTask::executeTask()
|
||||
QString localPath = assets->id + ".json";
|
||||
auto job = new NetJob(tr("Asset index for %1").arg(m_inst->name()));
|
||||
|
||||
auto metacache = ENV.metacache();
|
||||
auto metacache = ENV->metacache();
|
||||
auto entry = metacache->resolveEntry("asset_indexes", localPath);
|
||||
entry->setStale(true);
|
||||
auto hexSha1 = assets->sha1.toLatin1();
|
||||
@ -62,7 +62,7 @@ void AssetUpdateTask::assetIndexFinished()
|
||||
// FIXME: this looks like a job for a generic validator based on json schema?
|
||||
if (!AssetsUtils::loadAssetsIndexJson(assets->id, asset_fname, index))
|
||||
{
|
||||
auto metacache = ENV.metacache();
|
||||
auto metacache = ENV->metacache();
|
||||
auto entry = metacache->resolveEntry("asset_indexes", assets->id + ".json");
|
||||
metacache->evictEntry(entry);
|
||||
emitFailed(tr("Failed to read the assets index!"));
|
||||
|
@ -60,7 +60,7 @@ void FMLLibrariesTask::executeTask()
|
||||
// download missing libs to our place
|
||||
setStatus(tr("Downloading FML libraries..."));
|
||||
auto dljob = new NetJob("FML libraries");
|
||||
auto metacache = ENV.metacache();
|
||||
auto metacache = ENV->metacache();
|
||||
for (auto &lib : fmlLibsToProcess)
|
||||
{
|
||||
auto entry = metacache->resolveEntry("fmllibs", lib.filename);
|
||||
@ -87,7 +87,7 @@ void FMLLibrariesTask::fmllibsFinished()
|
||||
{
|
||||
setStatus(tr("Copying FML libraries into the instance..."));
|
||||
MinecraftInstance *inst = (MinecraftInstance *)m_inst;
|
||||
auto metacache = ENV.metacache();
|
||||
auto metacache = ENV->metacache();
|
||||
int index = 0;
|
||||
for (auto &lib : fmlLibsToProcess)
|
||||
{
|
||||
|
@ -21,7 +21,7 @@ void LibrariesTask::executeTask()
|
||||
auto job = new NetJob(tr("Libraries for instance %1").arg(inst->name()));
|
||||
downloadJob.reset(job);
|
||||
|
||||
auto metacache = ENV.metacache();
|
||||
auto metacache = ENV->metacache();
|
||||
|
||||
auto processArtifactPool = [&](const QList<LibraryPtr> & pool, QStringList & errors, const QString & localPath)
|
||||
{
|
||||
|
Reference in New Issue
Block a user