aboutsummaryrefslogtreecommitdiff
path: root/logic
diff options
context:
space:
mode:
Diffstat (limited to 'logic')
-rw-r--r--logic/BaseInstance.h2
-rw-r--r--logic/LegacyInstance.cpp6
-rw-r--r--logic/LegacyInstance.h2
-rw-r--r--logic/LegacyUpdate.cpp22
-rw-r--r--logic/LegacyUpdate.h4
-rw-r--r--logic/MinecraftProcess.cpp22
-rw-r--r--logic/OneSixInstance.cpp8
-rw-r--r--logic/OneSixInstance.h2
-rw-r--r--logic/OneSixUpdate.cpp54
-rw-r--r--logic/OneSixUpdate.h8
-rw-r--r--logic/auth/MojangAccount.cpp202
-rw-r--r--logic/auth/MojangAccount.h199
-rw-r--r--logic/auth/YggdrasilTask.cpp168
-rw-r--r--logic/auth/YggdrasilTask.h62
-rw-r--r--logic/auth/flows/AuthenticateTask.cpp23
-rw-r--r--logic/auth/flows/AuthenticateTask.h2
-rw-r--r--logic/auth/flows/InvalidateTask.cpp0
-rw-r--r--logic/auth/flows/InvalidateTask.h0
-rw-r--r--logic/auth/flows/RefreshTask.cpp22
-rw-r--r--logic/auth/flows/RefreshTask.h2
-rw-r--r--logic/auth/flows/ValidateTask.cpp4
-rw-r--r--logic/auth/flows/ValidateTask.h6
-rw-r--r--logic/lists/MojangAccountList.cpp24
-rw-r--r--logic/lists/MojangAccountList.h5
-rw-r--r--logic/net/NetJob.h2
-rw-r--r--logic/net/PasteUpload.cpp84
-rw-r--r--logic/net/PasteUpload.h26
-rw-r--r--logic/tasks/ProgressProvider.h1
-rw-r--r--logic/tasks/Task.h1
29 files changed, 537 insertions, 426 deletions
diff --git a/logic/BaseInstance.h b/logic/BaseInstance.h
index 2d7537d6..93e57414 100644
--- a/logic/BaseInstance.h
+++ b/logic/BaseInstance.h
@@ -150,7 +150,7 @@ public:
virtual SettingsObject &settings() const;
/// returns a valid update task if update is needed, NULL otherwise
- virtual Task *doUpdate(bool prepare_for_launch) = 0;
+ virtual std::shared_ptr<Task> doUpdate(bool only_prepare) = 0;
/// returns a valid minecraft process, ready for launch with the given account.
virtual MinecraftProcess *prepareForLaunch(MojangAccountPtr account) = 0;
diff --git a/logic/LegacyInstance.cpp b/logic/LegacyInstance.cpp
index 72b6c51a..fef27bcd 100644
--- a/logic/LegacyInstance.cpp
+++ b/logic/LegacyInstance.cpp
@@ -44,12 +44,12 @@ LegacyInstance::LegacyInstance(const QString &rootDir, SettingsObject *settings,
settings->registerSetting(new Setting("IntendedJarVersion", ""));
}
-Task *LegacyInstance::doUpdate(bool prepare_for_launch)
+std::shared_ptr<Task> LegacyInstance::doUpdate(bool only_prepare)
{
// make sure the jar mods list is initialized by asking for it.
auto list = jarModList();
// create an update task
- return new LegacyUpdate(this, prepare_for_launch , this);
+ return std::shared_ptr<Task> (new LegacyUpdate(this, only_prepare , this));
}
MinecraftProcess *LegacyInstance::prepareForLaunch(MojangAccountPtr account)
@@ -105,7 +105,7 @@ MinecraftProcess *LegacyInstance::prepareForLaunch(MojangAccountPtr account)
#endif
args << "-jar" << LAUNCHER_FILE;
- args << account->currentProfile()->name();
+ args << account->currentProfile()->name;
args << account->sessionId();
args << windowTitle;
args << windowSize;
diff --git a/logic/LegacyInstance.h b/logic/LegacyInstance.h
index a17ef281..1e7d9eb6 100644
--- a/logic/LegacyInstance.h
+++ b/logic/LegacyInstance.h
@@ -76,7 +76,7 @@ public:
virtual bool shouldUpdate() const override;
virtual void setShouldUpdate(bool val) override;
- virtual Task *doUpdate(bool prepare_for_launch) override;
+ virtual std::shared_ptr<Task> doUpdate(bool only_prepare) override;
virtual MinecraftProcess *prepareForLaunch(MojangAccountPtr account) override;
virtual void cleanupAfterRun() override;
diff --git a/logic/LegacyUpdate.cpp b/logic/LegacyUpdate.cpp
index 3fc17351..6125101b 100644
--- a/logic/LegacyUpdate.cpp
+++ b/logic/LegacyUpdate.cpp
@@ -26,14 +26,30 @@
#include <JlCompress.h>
#include "logger/QsLog.h"
-LegacyUpdate::LegacyUpdate(BaseInstance *inst, bool prepare_for_launch, QObject *parent)
- : Task(parent), m_inst(inst), m_prepare_for_launch(prepare_for_launch)
+LegacyUpdate::LegacyUpdate(BaseInstance *inst, bool only_prepare, QObject *parent)
+ : Task(parent), m_inst(inst), m_only_prepare(only_prepare)
{
}
void LegacyUpdate::executeTask()
{
- lwjglStart();
+ if(m_only_prepare)
+ {
+ // FIXME: think this through some more.
+ LegacyInstance *inst = (LegacyInstance *)m_inst;
+ if (!inst->shouldUpdate() || inst->shouldUseCustomBaseJar())
+ {
+ ModTheJar();
+ }
+ else
+ {
+ emitSucceeded();
+ }
+ }
+ else
+ {
+ lwjglStart();
+ }
}
void LegacyUpdate::lwjglStart()
diff --git a/logic/LegacyUpdate.h b/logic/LegacyUpdate.h
index d753197f..0b573ca5 100644
--- a/logic/LegacyUpdate.h
+++ b/logic/LegacyUpdate.h
@@ -31,7 +31,7 @@ class LegacyUpdate : public Task
{
Q_OBJECT
public:
- explicit LegacyUpdate(BaseInstance *inst, bool prepare_for_launch, QObject *parent = 0);
+ explicit LegacyUpdate(BaseInstance *inst, bool only_prepare, QObject *parent = 0);
virtual void executeTask();
private
@@ -72,5 +72,5 @@ private:
private:
NetJobPtr legacyDownloadJob;
BaseInstance *m_inst = nullptr;
- bool m_prepare_for_launch = false;
+ bool m_only_prepare = false;
};
diff --git a/logic/MinecraftProcess.cpp b/logic/MinecraftProcess.cpp
index 5d99bfae..209929b7 100644
--- a/logic/MinecraftProcess.cpp
+++ b/logic/MinecraftProcess.cpp
@@ -75,20 +75,22 @@ QString MinecraftProcess::censorPrivateInfo(QString in)
{
if(!m_account)
return in;
- else
+
+ QString sessionId = m_account->sessionId();
+ QString accessToken = m_account->accessToken();
+ QString clientToken = m_account->clientToken();
+ in.replace(sessionId, "<SESSION ID>");
+ in.replace(accessToken, "<ACCESS TOKEN>");
+ in.replace(clientToken, "<CLIENT TOKEN>");
+ auto profile = m_account->currentProfile();
+ if(profile)
{
- QString sessionId = m_account->sessionId();
- QString accessToken = m_account->accessToken();
- QString clientToken = m_account->clientToken();
- QString profileId = m_account->currentProfile()->id();
- QString profileName = m_account->currentProfile()->name();
- in.replace(sessionId, "<SESSION ID>");
- in.replace(accessToken, "<ACCESS TOKEN>");
- in.replace(clientToken, "<CLIENT TOKEN>");
+ QString profileId = profile->id;
+ QString profileName = profile->name;
in.replace(profileId, "<PROFILE ID>");
in.replace(profileName, "<PROFILE NAME>");
- return in;
}
+ return in;
}
// console window
diff --git a/logic/OneSixInstance.cpp b/logic/OneSixInstance.cpp
index a6b439a1..e804de11 100644
--- a/logic/OneSixInstance.cpp
+++ b/logic/OneSixInstance.cpp
@@ -39,9 +39,9 @@ OneSixInstance::OneSixInstance(const QString &rootDir, SettingsObject *setting_o
reloadFullVersion();
}
-Task *OneSixInstance::doUpdate(bool prepare_for_launch)
+std::shared_ptr<Task> OneSixInstance::doUpdate(bool only_prepare)
{
- return new OneSixUpdate(this, prepare_for_launch);
+ return std::shared_ptr<Task> (new OneSixUpdate(this, only_prepare));
}
QString replaceTokensIn(QString text, QMap<QString, QString> with)
@@ -136,8 +136,8 @@ QStringList OneSixInstance::processMinecraftArgs(MojangAccountPtr account)
token_mapping["auth_username"] = account->username();
token_mapping["auth_session"] = account->sessionId();
token_mapping["auth_access_token"] = account->accessToken();
- token_mapping["auth_player_name"] = account->currentProfile()->name();
- token_mapping["auth_uuid"] = account->currentProfile()->id();
+ token_mapping["auth_player_name"] = account->currentProfile()->name;
+ token_mapping["auth_uuid"] = account->currentProfile()->id;
// this is for offline?:
/*
diff --git a/logic/OneSixInstance.h b/logic/OneSixInstance.h
index cc98d822..f869e345 100644
--- a/logic/OneSixInstance.h
+++ b/logic/OneSixInstance.h
@@ -40,7 +40,7 @@ public:
QString loaderModsDir() const;
virtual QString instanceConfigFolder() const override;
- virtual Task *doUpdate(bool prepare_for_launch) override;
+ virtual std::shared_ptr<Task> doUpdate(bool only_prepare) override;
virtual MinecraftProcess *prepareForLaunch(MojangAccountPtr account) override;
virtual void cleanupAfterRun() override;
diff --git a/logic/OneSixUpdate.cpp b/logic/OneSixUpdate.cpp
index 25e16328..7be0c056 100644
--- a/logic/OneSixUpdate.cpp
+++ b/logic/OneSixUpdate.cpp
@@ -33,8 +33,8 @@
#include "pathutils.h"
#include <JlCompress.h>
-OneSixUpdate::OneSixUpdate(BaseInstance *inst, bool prepare_for_launch, QObject *parent)
- : Task(parent), m_inst(inst), m_prepare_for_launch(prepare_for_launch)
+OneSixUpdate::OneSixUpdate(BaseInstance *inst, bool only_prepare, QObject *parent)
+ : Task(parent), m_inst(inst), m_only_prepare(only_prepare)
{
}
@@ -50,6 +50,23 @@ void OneSixUpdate::executeTask()
return;
}
+ if(m_only_prepare)
+ {
+ if (m_inst->shouldUpdate())
+ {
+ emitFailed("Unable to update instance in offline mode.");
+ return;
+ }
+ setStatus("Testing the Java installation.");
+ QString java_path = m_inst->settings().get("JavaPath").toString();
+
+ checker.reset(new JavaChecker());
+ connect(checker.get(), SIGNAL(checkFinished(JavaCheckResult)), this,
+ SLOT(checkFinishedOffline(JavaCheckResult)));
+ checker->performCheck(java_path);
+ return;
+ }
+
if (m_inst->shouldUpdate())
{
// Get a pointer to the version object that corresponds to the instance's version.
@@ -65,35 +82,43 @@ void OneSixUpdate::executeTask()
}
else
{
- checkJava();
+ checkJavaOnline();
}
}
-void OneSixUpdate::checkJava()
+void OneSixUpdate::checkJavaOnline()
{
- QLOG_INFO() << m_inst->name() << ": checking java binary";
setStatus("Testing the Java installation.");
- // TODO: cache this so we don't have to run an extra java process every time.
QString java_path = m_inst->settings().get("JavaPath").toString();
checker.reset(new JavaChecker());
connect(checker.get(), SIGNAL(checkFinished(JavaCheckResult)), this,
- SLOT(checkFinished(JavaCheckResult)));
+ SLOT(checkFinishedOnline(JavaCheckResult)));
checker->performCheck(java_path);
}
-void OneSixUpdate::checkFinished(JavaCheckResult result)
+void OneSixUpdate::checkFinishedOnline(JavaCheckResult result)
{
if (result.valid)
{
- QLOG_INFO() << m_inst->name() << ": java is "
- << (result.is_64bit ? "64 bit" : "32 bit");
java_is_64bit = result.is_64bit;
jarlibStart();
}
else
{
- QLOG_INFO() << m_inst->name() << ": java isn't valid";
+ emitFailed("The java binary doesn't work. Check the settings and correct the problem");
+ }
+}
+
+void OneSixUpdate::checkFinishedOffline(JavaCheckResult result)
+{
+ if (result.valid)
+ {
+ java_is_64bit = result.is_64bit;
+ prepareForLaunch();
+ }
+ else
+ {
emitFailed("The java binary doesn't work. Check the settings and correct the problem");
}
}
@@ -160,7 +185,7 @@ void OneSixUpdate::versionFileFinished()
}
inst->reloadFullVersion();
- checkJava();
+ checkJavaOnline();
}
void OneSixUpdate::versionFileFailed()
@@ -240,10 +265,7 @@ void OneSixUpdate::jarlibStart()
void OneSixUpdate::jarlibFinished()
{
- if (m_prepare_for_launch)
- prepareForLaunch();
- else
- emitSucceeded();
+ prepareForLaunch();
}
void OneSixUpdate::jarlibFailed()
diff --git a/logic/OneSixUpdate.h b/logic/OneSixUpdate.h
index b86c205f..7ff9d881 100644
--- a/logic/OneSixUpdate.h
+++ b/logic/OneSixUpdate.h
@@ -43,11 +43,13 @@ slots:
void jarlibFinished();
void jarlibFailed();
- void checkJava();
- void checkFinished(JavaCheckResult result);
+ void checkJavaOnline();
+ void checkFinishedOnline(JavaCheckResult result);
+ void checkFinishedOffline(JavaCheckResult result);
// extract the appropriate libraries
void prepareForLaunch();
+
private:
NetJobPtr specificVersionDownloadJob;
NetJobPtr jarlibDownloadJob;
@@ -55,7 +57,7 @@ private:
// target version, determined during this task
std::shared_ptr<MinecraftVersion> targetVersion;
BaseInstance *m_inst = nullptr;
- bool m_prepare_for_launch = false;
+ bool m_only_prepare = false;
std::shared_ptr<JavaChecker> checker;
bool java_is_64bit = false;
diff --git a/logic/auth/MojangAccount.cpp b/logic/auth/MojangAccount.cpp
index 4a61cf19..b1acfb25 100644
--- a/logic/auth/MojangAccount.cpp
+++ b/logic/auth/MojangAccount.cpp
@@ -16,113 +16,16 @@
*/
#include "MojangAccount.h"
+#include "flows/RefreshTask.h"
+#include "flows/AuthenticateTask.h"
#include <QUuid>
#include <QJsonObject>
#include <QJsonArray>
+#include <QRegExp>
#include <logger/QsLog.h>
-MojangAccount::MojangAccount(const QString &username, QObject *parent) : QObject(parent)
-{
- // Generate a client token.
- m_clientToken = QUuid::createUuid().toString();
-
- m_username = username;
-
- m_currentProfile = -1;
-}
-
-MojangAccount::MojangAccount(const QString &username, const QString &clientToken,
- const QString &accessToken, QObject *parent)
- : QObject(parent)
-{
- m_username = username;
- m_clientToken = clientToken;
- m_accessToken = accessToken;
-
- m_currentProfile = -1;
-}
-
-MojangAccount::MojangAccount(const MojangAccount &other, QObject *parent)
-{
- m_username = other.username();
- m_clientToken = other.clientToken();
- m_accessToken = other.accessToken();
-
- m_profiles = other.m_profiles;
- m_currentProfile = other.m_currentProfile;
-}
-
-QString MojangAccount::username() const
-{
- return m_username;
-}
-
-QString MojangAccount::clientToken() const
-{
- return m_clientToken;
-}
-
-void MojangAccount::setClientToken(const QString &clientToken)
-{
- m_clientToken = clientToken;
-}
-
-QString MojangAccount::accessToken() const
-{
- return m_accessToken;
-}
-
-void MojangAccount::setAccessToken(const QString &accessToken)
-{
- m_accessToken = accessToken;
-}
-
-QString MojangAccount::sessionId() const
-{
- return "token:" + m_accessToken + ":" + currentProfile()->id();
-}
-
-const QList<AccountProfile> MojangAccount::profiles() const
-{
- return m_profiles;
-}
-
-const AccountProfile *MojangAccount::currentProfile() const
-{
- if (m_currentProfile < 0)
- {
- if (m_profiles.length() > 0)
- return &m_profiles.at(0);
- else
- return nullptr;
- }
- else
- return &m_profiles.at(m_currentProfile);
-}
-
-bool MojangAccount::setProfile(const QString &profileId)
-{
- const QList<AccountProfile> &profiles = this->profiles();
- for (int i = 0; i < profiles.length(); i++)
- {
- if (profiles.at(i).id() == profileId)
- {
- m_currentProfile = i;
- return true;
- }
- }
- return false;
-}
-
-void MojangAccount::loadProfiles(const ProfileList &profiles)
-{
- m_profiles.clear();
- for (auto profile : profiles)
- m_profiles.append(profile);
-}
-
MojangAccountPtr MojangAccount::loadFromJson(const QJsonObject &object)
{
// The JSON object must at least have a username for it to be valid.
@@ -143,7 +46,7 @@ MojangAccountPtr MojangAccount::loadFromJson(const QJsonObject &object)
return nullptr;
}
- ProfileList profiles;
+ QList<AccountProfile> profiles;
for (QJsonValue profileVal : profileArray)
{
QJsonObject profileObject = profileVal.toObject();
@@ -154,67 +57,116 @@ MojangAccountPtr MojangAccount::loadFromJson(const QJsonObject &object)
QLOG_WARN() << "Unable to load a profile because it was missing an ID or a name.";
continue;
}
- profiles.append(AccountProfile(id, name));
+ profiles.append({id, name});
}
- MojangAccountPtr account(new MojangAccount(username, clientToken, accessToken));
- account->loadProfiles(profiles);
+ MojangAccountPtr account(new MojangAccount());
+ account->m_username = username;
+ account->m_clientToken = clientToken;
+ account->m_accessToken = accessToken;
+ account->m_profiles = profiles;
// Get the currently selected profile.
QString currentProfile = object.value("activeProfile").toString("");
if (!currentProfile.isEmpty())
- account->setProfile(currentProfile);
+ account->setCurrentProfile(currentProfile);
return account;
}
-QJsonObject MojangAccount::saveToJson()
+MojangAccountPtr MojangAccount::createFromUsername(const QString& username)
+{
+ MojangAccountPtr account(new MojangAccount());
+ account->m_clientToken = QUuid::createUuid().toString().remove(QRegExp("[{}-]"));
+ account->m_username = username;
+ return account;
+}
+
+QJsonObject MojangAccount::saveToJson() const
{
QJsonObject json;
- json.insert("username", username());
- json.insert("clientToken", clientToken());
- json.insert("accessToken", accessToken());
+ json.insert("username", m_username);
+ json.insert("clientToken", m_clientToken);
+ json.insert("accessToken", m_accessToken);
QJsonArray profileArray;
for (AccountProfile profile : m_profiles)
{
QJsonObject profileObj;
- profileObj.insert("id", profile.id());
- profileObj.insert("name", profile.name());
+ profileObj.insert("id", profile.id);
+ profileObj.insert("name", profile.name);
profileArray.append(profileObj);
}
json.insert("profiles", profileArray);
- if (currentProfile() != nullptr)
- json.insert("activeProfile", currentProfile()->id());
+ if (m_currentProfile != -1)
+ json.insert("activeProfile", currentProfile()->id);
return json;
}
-
-AccountProfile::AccountProfile(const QString& id, const QString& name)
+bool MojangAccount::setCurrentProfile(const QString &profileId)
{
- m_id = id;
- m_name = name;
+ for (int i = 0; i < m_profiles.length(); i++)
+ {
+ if (m_profiles[i].id == profileId)
+ {
+ m_currentProfile = i;
+ return true;
+ }
+ }
+ return false;
}
-AccountProfile::AccountProfile(const AccountProfile &other)
+const AccountProfile* MojangAccount::currentProfile() const
{
- m_id = other.m_id;
- m_name = other.m_name;
+ if(m_currentProfile == -1)
+ return nullptr;
+ return &m_profiles[m_currentProfile];
}
-QString AccountProfile::id() const
+AccountStatus MojangAccount::accountStatus() const
{
- return m_id;
+ if(m_accessToken.isEmpty())
+ return NotVerified;
+ if(!m_online)
+ return Verified;
+ return Online;
}
-QString AccountProfile::name() const
+std::shared_ptr<Task> MojangAccount::login(QString password)
{
- return m_name;
+ if(m_currentTask)
+ return m_currentTask;
+ if(password.isEmpty())
+ {
+ m_currentTask.reset(new RefreshTask(this));
+ }
+ else
+ {
+ m_currentTask.reset(new AuthenticateTask(this, password));
+ }
+ connect(m_currentTask.get(), SIGNAL(succeeded()), SLOT(authSucceeded()));
+ connect(m_currentTask.get(), SIGNAL(failed(QString)), SLOT(authFailed(QString)));
+ return m_currentTask;
}
-void MojangAccount::propagateChange()
+void MojangAccount::authSucceeded()
{
+ m_online = true;
+ m_currentTask.reset();
emit changed();
}
+
+void MojangAccount::authFailed(QString reason)
+{
+ // This is emitted when the yggdrasil tasks time out or are cancelled.
+ // -> we treat the error as no-op
+ if(reason != "Yggdrasil task cancelled.")
+ {
+ m_online = false;
+ m_accessToken = QString();
+ emit changed();
+ }
+ m_currentTask.reset();
+}
diff --git a/logic/auth/MojangAccount.h b/logic/auth/MojangAccount.h
index 25a85790..95f777ce 100644
--- a/logic/auth/MojangAccount.h
+++ b/logic/auth/MojangAccount.h
@@ -23,34 +23,26 @@
#include <memory>
+class Task;
+class YggdrasilTask;
class MojangAccount;
typedef std::shared_ptr<MojangAccount> MojangAccountPtr;
Q_DECLARE_METATYPE(MojangAccountPtr)
/**
- * Class that represents a profile within someone's Mojang account.
+ * A profile within someone's Mojang account.
*
* Currently, the profile system has not been implemented by Mojang yet,
* but we might as well add some things for it in MultiMC right now so
* we don't have to rip the code to pieces to add it later.
*/
-class AccountProfile
+struct AccountProfile
{
-public:
- AccountProfile(const QString &id, const QString &name);
- AccountProfile(const AccountProfile &other);
-
- QString id() const;
- QString name() const;
-
-protected:
- QString m_id;
- QString m_name;
+ QString id;
+ QString name;
};
-typedef QList<AccountProfile> ProfileList;
-
struct User
{
QString id;
@@ -59,6 +51,13 @@ struct User
QList<QPair<QString, QString>> properties;
};
+enum AccountStatus
+{
+ NotVerified,
+ Verified,
+ Online
+};
+
/**
* Object that stores information about a certain Mojang account.
*
@@ -68,106 +67,116 @@ struct User
class MojangAccount : public QObject
{
Q_OBJECT
-public:
- /**
- * Constructs a new MojangAccount with the given username.
- * The client token will be generated automatically and the access token will be blank.
- */
- explicit MojangAccount(const QString &username, QObject *parent = 0);
+public: /* construction */
+ //! Do not copy accounts. ever.
+ explicit MojangAccount(const MojangAccount &other, QObject *parent) = delete;
- /**
- * Constructs a new MojangAccount with the given username, client token, and access token.
- */
- explicit MojangAccount(const QString &username, const QString &clientToken,
- const QString &accessToken, QObject *parent = 0);
+ //! Default constructor
+ explicit MojangAccount(QObject *parent = 0) : QObject(parent) {};
- /**
- * Constructs a new MojangAccount matching the given account.
- */
- MojangAccount(const MojangAccount &other, QObject *parent);
+ //! Creates an empty account for the specified user name.
+ static MojangAccountPtr createFromUsername(const QString &username);
- /**
- * Loads a MojangAccount from the given JSON object.
- */
+ //! Loads a MojangAccount from the given JSON object.
static MojangAccountPtr loadFromJson(const QJsonObject &json);
- /**
- * Saves a MojangAccount to a JSON object and returns it.
- */
- QJsonObject saveToJson();
+ //! Saves a MojangAccount to a JSON object and returns it.
+ QJsonObject saveToJson() const;
+public: /* manipulation */
/**
- * Update the account on disk and lists (it changed, for whatever reason)
- * This is called by various Yggdrasil tasks.
- */
- void propagateChange();
+ * Sets the currently selected profile to the profile with the given ID string.
+ * If profileId is not in the list of available profiles, the function will simply return
+ * false.
+ */
+ bool setCurrentProfile(const QString &profileId);
+
+ /**
+ * 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<Task> login(QString password = QString());
+
+ void downgrade()
+ {
+ m_online = false;
+ }
+public: /* queries */
+ const QString &username() const
+ {
+ return m_username;
+ }
+
+ const QString &clientToken() const
+ {
+ return m_clientToken;
+ }
+
+ const QString &accessToken() const
+ {
+ return m_accessToken;
+ }
+
+ const QList<AccountProfile> &profiles() const
+ {
+ return m_profiles;
+ }
+
+ //! Get the session ID required for legacy Minecraft versions
+ QString sessionId() const
+ {
+ if (m_currentProfile != -1 && !m_accessToken.isEmpty())
+ return "token:" + m_accessToken + ":" + m_profiles[m_currentProfile].id;
+ return "-";
+ }
+
+ //! Returns the currently selected profile (if none, returns nullptr)
+ const AccountProfile *currentProfile() const;
- /**
- * This MojangAccount's username. May be an email address if the account is migrated.
- */
- QString username() const;
+ //! Returns whether the account is NotVerified, Verified or Online
+ AccountStatus accountStatus() const;
+signals:
/**
- * This MojangAccount's client token. This is a UUID used by Mojang's auth servers to identify this client.
- * This is unique for each MojangAccount.
+ * This signal is emitted when the account changes
*/
- QString clientToken() const;
+ void changed();
- /**
- * Sets the MojangAccount's client token to the given value.
- */
- void setClientToken(const QString &token);
+ // TODO: better signalling for the various possible state changes - especially errors
- /**
- * This MojangAccount's access token.
- * If the user has not chosen to stay logged in, this will be an empty string.
- */
- QString accessToken() const;
+protected: /* variables */
+ QString m_username;
- /**
- * Changes this MojangAccount's access token to the given value.
- */
- void setAccessToken(const QString &token);
+ // Used to identify the client - the user can have multiple clients for the same account
+ // Think: different launchers, all connecting to the same account/profile
+ QString m_clientToken;
- /**
- * Get full session ID
- */
- QString sessionId() const;
+ // Blank if not logged in.
+ QString m_accessToken;
- /**
- * Returns a list of the available account profiles.
- */
- const ProfileList profiles() const;
+ // Index of the selected profile within the list of available
+ // profiles. -1 if nothing is selected.
+ int m_currentProfile = -1;
- /**
- * Returns a pointer to the currently selected profile.
- * If no profile is selected, returns the first profile in the profile list or nullptr if there are none.
- */
- const AccountProfile *currentProfile() const;
+ // List of available profiles.
+ QList<AccountProfile> m_profiles;
- /**
- * Sets the currently selected profile to the profile with the given ID string.
- * If profileId is not in the list of available profiles, the function will simply return false.
- */
- bool setProfile(const QString &profileId);
+ // the user structure, whatever it is.
+ User m_user;
- /**
- * Clears the current account profile list and replaces it with the given profile list.
- */
- void loadProfiles(const ProfileList &profiles);
+ // true when the account is verified
+ bool m_online = false;
-signals:
- /**
- * This isgnal is emitted whrn the account changes
- */
- void changed();
+ // current task we are executing here
+ std::shared_ptr<YggdrasilTask> m_currentTask;
-protected:
- QString m_username;
- QString m_clientToken;
- QString m_accessToken; // Blank if not logged in.
- int m_currentProfile; // Index of the selected profile within the list of available
- // profiles. -1 if nothing is selected.
- ProfileList m_profiles; // List of available profiles.
- User m_user; // the user structure, whatever it is.
+private slots:
+ void authSucceeded();
+ void authFailed(QString reason);
+
+public:
+ friend class YggdrasilTask;
+ friend class AuthenticateTask;
+ friend class ValidateTask;
+ friend class RefreshTask;
};
diff --git a/logic/auth/YggdrasilTask.cpp b/logic/auth/YggdrasilTask.cpp
index 797e84cd..45155058 100644
--- a/