From 167b6bd40550a7c9459f59976893e6a3d37b2173 Mon Sep 17 00:00:00 2001 From: Max Date: Mon, 14 Jun 2021 12:51:25 +0300 Subject: [PATCH] Dehardcode account providers (#38) * Dehardcode account providers * Fix crash on creation * Add dynamic 'add account dialog' provider selector * Fix typo and add newlines * Rename loginType to provider * Rename MojangAccount to Account and MojangAccountList to AccountList * Fix json save error --- api/logic/BaseInstance.h | 2 +- api/logic/CMakeLists.txt | 14 +++- api/logic/minecraft/MinecraftInstance.cpp | 7 +- .../auth/{MojangAccount.cpp => Account.cpp} | 74 +++++++------------ .../auth/{MojangAccount.h => Account.h} | 45 +++++------ ...{MojangAccountList.cpp => AccountList.cpp} | 68 ++++++++--------- .../{MojangAccountList.h => AccountList.h} | 22 +++--- api/logic/minecraft/auth/AccountProfile.h | 9 +++ api/logic/minecraft/auth/AuthProviders.cpp | 37 ++++++++++ api/logic/minecraft/auth/AuthProviders.h | 22 ++++++ api/logic/minecraft/auth/AuthSession.h | 4 +- api/logic/minecraft/auth/YggdrasilTask.cpp | 9 +-- api/logic/minecraft/auth/YggdrasilTask.h | 6 +- .../minecraft/auth/flows/AuthenticateTask.cpp | 6 +- .../minecraft/auth/flows/AuthenticateTask.h | 6 +- .../minecraft/auth/flows/RefreshTask.cpp | 4 +- api/logic/minecraft/auth/flows/RefreshTask.h | 4 +- .../minecraft/auth/flows/ValidateTask.cpp | 4 +- api/logic/minecraft/auth/flows/ValidateTask.h | 4 +- .../auth/providers/BaseAuthProvider.h | 52 +++++++++++++ .../auth/providers/DummyAuthProvider.h | 25 +++++++ .../auth/providers/ElybyAuthProvider.h | 26 +++++++ .../auth/providers/MojangAuthProvider.h | 25 +++++++ api/logic/minecraft/launch/ClaimAccount.h | 4 +- application/LaunchController.cpp | 6 +- application/MainWindow.cpp | 34 ++++----- application/MainWindow.h | 2 +- application/MultiMC.cpp | 10 ++- application/MultiMC.h | 6 +- application/dialogs/LoginDialog.cpp | 27 ++++--- application/dialogs/LoginDialog.h | 8 +- application/dialogs/LoginDialog.ui | 34 +-------- application/dialogs/ProfileSelectDialog.cpp | 10 +-- application/dialogs/ProfileSelectDialog.h | 8 +- application/dialogs/SkinUploadDialog.cpp | 2 +- application/dialogs/SkinUploadDialog.h | 6 +- application/pages/global/AccountListPage.cpp | 21 ++---- application/pages/global/AccountListPage.h | 4 +- application/pages/instance/VersionPage.cpp | 2 +- 39 files changed, 398 insertions(+), 261 deletions(-) rename api/logic/minecraft/auth/{MojangAccount.cpp => Account.cpp} (84%) rename api/logic/minecraft/auth/{MojangAccount.h => Account.h} (79%) rename api/logic/minecraft/auth/{MojangAccountList.cpp => AccountList.cpp} (83%) rename api/logic/minecraft/auth/{MojangAccountList.h => AccountList.h} (90%) create mode 100644 api/logic/minecraft/auth/AccountProfile.h create mode 100644 api/logic/minecraft/auth/AuthProviders.cpp create mode 100644 api/logic/minecraft/auth/AuthProviders.h create mode 100644 api/logic/minecraft/auth/providers/BaseAuthProvider.h create mode 100644 api/logic/minecraft/auth/providers/DummyAuthProvider.h create mode 100644 api/logic/minecraft/auth/providers/ElybyAuthProvider.h create mode 100644 api/logic/minecraft/auth/providers/MojangAuthProvider.h diff --git a/api/logic/BaseInstance.h b/api/logic/BaseInstance.h index 7f54e3db..8716953c 100644 --- a/api/logic/BaseInstance.h +++ b/api/logic/BaseInstance.h @@ -26,7 +26,7 @@ #include "settings/INIFile.h" #include "BaseVersionList.h" -#include "minecraft/auth/MojangAccount.h" +#include "minecraft/auth/Account.h" #include "MessageLevel.h" #include "pathmatcher/IPathMatcher.h" diff --git a/api/logic/CMakeLists.txt b/api/logic/CMakeLists.txt index b682a6a8..1084b825 100644 --- a/api/logic/CMakeLists.txt +++ b/api/logic/CMakeLists.txt @@ -201,12 +201,14 @@ set(STATUS_SOURCES # Support for Minecraft instances and launch set(MINECRAFT_SOURCES # Minecraft support + minecraft/auth/AuthProviders.h + minecraft/auth/AuthProviders.cpp minecraft/auth/AuthSession.h minecraft/auth/AuthSession.cpp - minecraft/auth/MojangAccountList.h - minecraft/auth/MojangAccountList.cpp - minecraft/auth/MojangAccount.h - minecraft/auth/MojangAccount.cpp + minecraft/auth/AccountList.h + minecraft/auth/AccountList.cpp + minecraft/auth/Account.h + minecraft/auth/Account.cpp minecraft/auth/YggdrasilTask.h minecraft/auth/YggdrasilTask.cpp minecraft/auth/flows/AuthenticateTask.h @@ -215,6 +217,10 @@ set(MINECRAFT_SOURCES minecraft/auth/flows/RefreshTask.cpp minecraft/auth/flows/ValidateTask.h minecraft/auth/flows/ValidateTask.cpp + minecraft/auth/providers/BaseAuthProvider.h + minecraft/auth/providers/DummyAuthProvider.h + minecraft/auth/providers/ElybyAuthProvider.h + minecraft/auth/providers/MojangAuthProvider.h minecraft/gameoptions/GameOptions.h minecraft/gameoptions/GameOptions.cpp diff --git a/api/logic/minecraft/MinecraftInstance.cpp b/api/logic/minecraft/MinecraftInstance.cpp index 80ea0cad..affaaf60 100644 --- a/api/logic/minecraft/MinecraftInstance.cpp +++ b/api/logic/minecraft/MinecraftInstance.cpp @@ -918,13 +918,10 @@ shared_qobject_ptr MinecraftInstance::createLaunchTask(AuthSessionPt } // authlib patch - if (session->m_accountPtr->loginType() != "mojang") + if (session->m_accountPtr->provider()->injectorEndpoint() != "") { auto step = new InjectAuthlib(pptr, &m_injector); - if(session->m_accountPtr->loginType() == "dummy") - step->setAuthServer(((QString)"http://localhost:%1").arg(localAuthServerPort)); - else if(session->m_accountPtr->loginType() == "elyby") - step->setAuthServer(((QString) "ely.by").arg(localAuthServerPort)); + step->setAuthServer(session->m_accountPtr->provider()->injectorEndpoint().arg(localAuthServerPort)); process->appendStep(step); } diff --git a/api/logic/minecraft/auth/MojangAccount.cpp b/api/logic/minecraft/auth/Account.cpp similarity index 84% rename from api/logic/minecraft/auth/MojangAccount.cpp rename to api/logic/minecraft/auth/Account.cpp index dd77d323..0f5e8c49 100644 --- a/api/logic/minecraft/auth/MojangAccount.cpp +++ b/api/logic/minecraft/auth/Account.cpp @@ -15,7 +15,8 @@ * limitations under the License. */ -#include "MojangAccount.h" +#include "Account.h" +#include "AuthProviders.h" #include "flows/RefreshTask.h" #include "flows/AuthenticateTask.h" @@ -30,7 +31,7 @@ #include -MojangAccountPtr MojangAccount::loadFromJson(const QJsonObject &object) +AccountPtr Account::loadFromJson(const QJsonObject &object) { // The JSON object must at least have a username for it to be valid. if (!object.value("username").isString()) @@ -40,7 +41,7 @@ MojangAccountPtr MojangAccount::loadFromJson(const QJsonObject &object) return nullptr; } - QString loginType = object.value("loginType").toString("mojang"); + QString provider = object.value("loginType").toString("dummy"); QString username = object.value("username").toString(""); QString clientToken = object.value("clientToken").toString(""); QString accessToken = object.value("accessToken").toString(""); @@ -68,7 +69,7 @@ MojangAccountPtr MojangAccount::loadFromJson(const QJsonObject &object) profiles.append({id, name, legacy}); } - MojangAccountPtr account(new MojangAccount()); + AccountPtr account(new Account()); if (object.value("user").isObject()) { User u; @@ -85,7 +86,7 @@ MojangAccountPtr MojangAccount::loadFromJson(const QJsonObject &object) */ account->m_user = u; } - account->m_loginType = loginType; + account->m_provider = AuthProviders::lookup(provider); account->m_username = username; account->m_clientToken = clientToken; account->m_accessToken = accessToken; @@ -99,18 +100,18 @@ MojangAccountPtr MojangAccount::loadFromJson(const QJsonObject &object) return account; } -MojangAccountPtr MojangAccount::createFromUsername(const QString &username) +AccountPtr Account::createFromUsername(const QString &username) { - MojangAccountPtr account(new MojangAccount()); + AccountPtr account(new Account()); account->m_clientToken = QUuid::createUuid().toString().remove(QRegExp("[{}-]")); account->m_username = username; return account; } -QJsonObject MojangAccount::saveToJson() const +QJsonObject Account::saveToJson() const { QJsonObject json; - json.insert("loginType", m_loginType); + json.insert("loginType", m_provider->id()); json.insert("username", m_username); json.insert("clientToken", m_clientToken); json.insert("accessToken", m_accessToken); @@ -147,18 +148,15 @@ QJsonObject MojangAccount::saveToJson() const return json; } -bool MojangAccount::setLoginType(const QString &loginType) +bool Account::setProvider(AuthProviderPtr provider) { - // TODO: Implement a cleaner validity check - if (loginType == "mojang" || loginType == "dummy" || loginType == "elyby") - { - m_loginType = loginType; - return true; - } - return false; + if (provider == nullptr) + return false; + m_provider = provider; + return true; } -bool MojangAccount::setCurrentProfile(const QString &profileId) +bool Account::setCurrentProfile(const QString &profileId) { for (int i = 0; i < m_profiles.length(); i++) { @@ -171,14 +169,14 @@ bool MojangAccount::setCurrentProfile(const QString &profileId) return false; } -const AccountProfile *MojangAccount::currentProfile() const +const AccountProfile *Account::currentProfile() const { if (m_currentProfile == -1) return nullptr; return &m_profiles[m_currentProfile]; } -AccountStatus MojangAccount::accountStatus() const +AccountStatus Account::accountStatus() const { if (m_accessToken.isEmpty()) return NotVerified; @@ -186,32 +184,12 @@ AccountStatus MojangAccount::accountStatus() const return Verified; } -QString MojangAccount::authEndpoint() const -{ - if(m_loginType == "elyby") - return BuildConfig.AUTH_BASE_ELYBY; - - return BuildConfig.AUTH_BASE_MOJANG; -} - -QString MojangAccount::displayLoginType() const -{ - if(m_loginType == "mojang") - return "Mojang"; - if(m_loginType == "dummy") - return "Local"; - if(m_loginType == "elyby") - return "Ely.by"; - - return "Unknown"; -} - -std::shared_ptr MojangAccount::login(AuthSessionPtr session, QString password) +std::shared_ptr Account::login(AuthSessionPtr session, QString password) { Q_ASSERT(m_currentTask.get() == nullptr); // Handling alternative account types - if (m_loginType == "dummy") + if (m_provider->dummyAuth()) { if (session) { @@ -267,7 +245,7 @@ std::shared_ptr MojangAccount::login(AuthSessionPtr session, QStr return m_currentTask; } -void MojangAccount::authSucceeded() +void Account::authSucceeded() { auto session = m_currentTask->getAssignedSession(); if (session) @@ -281,7 +259,7 @@ void MojangAccount::authSucceeded() emit changed(); } -void MojangAccount::authFailed(QString reason) +void Account::authFailed(QString reason) { auto session = m_currentTask->getAssignedSession(); // This is emitted when the yggdrasil tasks time out or are cancelled. @@ -310,7 +288,7 @@ void MojangAccount::authFailed(QString reason) m_currentTask.reset(); } -void MojangAccount::fillSession(AuthSessionPtr session) +void Account::fillSession(AuthSessionPtr session) { // the user name. you have to have an user name session->username = m_username; @@ -344,7 +322,7 @@ void MojangAccount::fillSession(AuthSessionPtr session) session->m_accountPtr = shared_from_this(); } -void MojangAccount::decrementUses() +void Account::decrementUses() { Usable::decrementUses(); if(!isInUse()) @@ -354,7 +332,7 @@ void MojangAccount::decrementUses() } } -void MojangAccount::incrementUses() +void Account::incrementUses() { bool wasInUse = isInUse(); Usable::incrementUses(); @@ -365,7 +343,7 @@ void MojangAccount::incrementUses() } } -void MojangAccount::invalidateClientToken() +void Account::invalidateClientToken() { m_clientToken = QUuid::createUuid().toString().remove(QRegExp("[{}-]")); emit changed(); diff --git a/api/logic/minecraft/auth/MojangAccount.h b/api/logic/minecraft/auth/Account.h similarity index 79% rename from api/logic/minecraft/auth/MojangAccount.h rename to api/logic/minecraft/auth/Account.h index 09498f8b..ec258be7 100644 --- a/api/logic/minecraft/auth/MojangAccount.h +++ b/api/logic/minecraft/auth/Account.h @@ -24,16 +24,18 @@ #include #include "AuthSession.h" +#include "AccountProfile.h" #include "Usable.h" +#include "providers/BaseAuthProvider.h" #include "multimc_logic_export.h" class Task; class YggdrasilTask; -class MojangAccount; +class Account; -typedef std::shared_ptr MojangAccountPtr; -Q_DECLARE_METATYPE(MojangAccountPtr) +typedef std::shared_ptr AccountPtr; +Q_DECLARE_METATYPE(AccountPtr) /** * A profile within someone's Mojang account. @@ -42,12 +44,6 @@ Q_DECLARE_METATYPE(MojangAccountPtr) * 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. */ -struct AccountProfile -{ - QString id; - QString name; - bool legacy; -}; enum AccountStatus { @@ -61,34 +57,33 @@ enum AccountStatus * Said information may include things such as that account's username, client token, and access * token if the user chose to stay logged in. */ -class MULTIMC_LOGIC_EXPORT MojangAccount : +class MULTIMC_LOGIC_EXPORT Account : public QObject, public Usable, - public std::enable_shared_from_this + public std::enable_shared_from_this { Q_OBJECT public: /* construction */ //! Do not copy accounts. ever. - explicit MojangAccount(const MojangAccount &other, QObject *parent) = delete; + explicit Account(const Account &other, QObject *parent) = delete; //! Default constructor - explicit MojangAccount(QObject *parent = 0) : QObject(parent) {}; + explicit Account(QObject *parent = 0) : QObject(parent) {}; //! Creates an empty account for the specified user name. - static MojangAccountPtr createFromUsername(const QString &username); + static AccountPtr createFromUsername(const QString &username); - //! Loads a MojangAccount from the given JSON object. - static MojangAccountPtr loadFromJson(const QJsonObject &json); + //! Loads a Account from the given JSON object. + static AccountPtr loadFromJson(const QJsonObject &json); - //! Saves a MojangAccount to a JSON object and returns it. + //! Saves a Account to a JSON object and returns it. QJsonObject saveToJson() const; public: /* manipulation */ /** * Overrides the login type on the account. - * Accepts "mojang" and "dummy". Returns false if other. */ - bool setLoginType(const QString &loginType); + bool setProvider(AuthProviderPtr provider); /** * Sets the currently selected profile to the profile with the given ID string. @@ -105,9 +100,9 @@ public: /* manipulation */ void invalidateClientToken(); public: /* queries */ - const QString &loginType() const + const AuthProviderPtr provider() const { - return m_loginType; + return m_provider; } const QString &username() const @@ -141,12 +136,6 @@ public: /* queries */ //! Returns whether the account is NotVerified, Verified or Online AccountStatus accountStatus() const; - //! Returns endpoint for authentication - QString authEndpoint() const; - - // ! Returns login type to display in account list or account chooser - QString displayLoginType() const; - signals: /** * This signal is emitted when the account changes @@ -158,7 +147,7 @@ signals: protected: /* variables */ // Authentication system used. // Usable values: "mojang", "dummy", "elyby" - QString m_loginType; + AuthProviderPtr m_provider; // Username taken by account. QString m_username; diff --git a/api/logic/minecraft/auth/MojangAccountList.cpp b/api/logic/minecraft/auth/AccountList.cpp similarity index 83% rename from api/logic/minecraft/auth/MojangAccountList.cpp rename to api/logic/minecraft/auth/AccountList.cpp index 9db87232..a0bfc6f3 100644 --- a/api/logic/minecraft/auth/MojangAccountList.cpp +++ b/api/logic/minecraft/auth/AccountList.cpp @@ -13,8 +13,8 @@ * limitations under the License. */ -#include "MojangAccountList.h" -#include "MojangAccount.h" +#include "AccountList.h" +#include "Account.h" #include #include @@ -31,27 +31,27 @@ #define ACCOUNT_LIST_FORMAT_VERSION 2 -MojangAccountList::MojangAccountList(QObject *parent) : QAbstractListModel(parent) +AccountList::AccountList(QObject *parent) : QAbstractListModel(parent) { } -MojangAccountPtr MojangAccountList::findAccount(const QString &username) const +AccountPtr AccountList::findAccount(const QString &username) const { for (int i = 0; i < count(); i++) { - MojangAccountPtr account = at(i); + AccountPtr account = at(i); if (account->username() == username) return account; } return nullptr; } -const MojangAccountPtr MojangAccountList::at(int i) const +const AccountPtr AccountList::at(int i) const { - return MojangAccountPtr(m_accounts.at(i)); + return AccountPtr(m_accounts.at(i)); } -void MojangAccountList::addAccount(const MojangAccountPtr account) +void AccountList::addAccount(const AccountPtr account) { int row = m_accounts.count(); beginInsertRows(QModelIndex(), row, row); @@ -61,7 +61,7 @@ void MojangAccountList::addAccount(const MojangAccountPtr account) onListChanged(); } -void MojangAccountList::removeAccount(const QString &username) +void AccountList::removeAccount(const QString &username) { int idx = 0; for (auto account : m_accounts) @@ -78,7 +78,7 @@ void MojangAccountList::removeAccount(const QString &username) onListChanged(); } -void MojangAccountList::removeAccount(QModelIndex index) +void AccountList::removeAccount(QModelIndex index) { int row = index.row(); if(index.isValid() && row >= 0 && row < m_accounts.size()) @@ -96,19 +96,19 @@ void MojangAccountList::removeAccount(QModelIndex index) } } -MojangAccountPtr MojangAccountList::activeAccount() const +AccountPtr AccountList::activeAccount() const { return m_activeAccount; } -void MojangAccountList::setActiveAccount(const QString &username) +void AccountList::setActiveAccount(const QString &username) { if (username.isEmpty() && m_activeAccount) { int idx = 0; auto prevActiveAcc = m_activeAccount; m_activeAccount = nullptr; - for (MojangAccountPtr account : m_accounts) + for (AccountPtr account : m_accounts) { if (account == prevActiveAcc) { @@ -125,7 +125,7 @@ void MojangAccountList::setActiveAccount(const QString &username) auto newActiveAccount = m_activeAccount; int newActiveAccountIdx = -1; int idx = 0; - for (MojangAccountPtr account : m_accounts) + for (AccountPtr account : m_accounts) { if (account->username() == username) { @@ -148,13 +148,13 @@ void MojangAccountList::setActiveAccount(const QString &username) } } -void MojangAccountList::accountChanged() +void AccountList::accountChanged() { // the list changed. there is no doubt. onListChanged(); } -void MojangAccountList::onListChanged() +void AccountList::onListChanged() { if (m_autosave) // TODO: Alert the user if this fails. @@ -163,7 +163,7 @@ void MojangAccountList::onListChanged() emit listChanged(); } -void MojangAccountList::onActiveChanged() +void AccountList::onActiveChanged() { if (m_autosave) saveList(); @@ -171,12 +171,12 @@ void MojangAccountList::onActiveChanged() emit activeAccountChanged(); } -int MojangAccountList::count() const +int AccountList::count() const { return m_accounts.count(); } -QVariant MojangAccountList::data(const QModelIndex &index, int role) const +QVariant AccountList::data(const QModelIndex &index, int role) const { if (!index.isValid()) return QVariant(); @@ -184,7 +184,7 @@ QVariant MojangAccountList::data(const QModelIndex &index, int role) const if (index.row() > count()) return QVariant(); - MojangAccountPtr account = at(index.row()); + AccountPtr account = at(index.row()); switch (role) { @@ -195,7 +195,7 @@ QVariant MojangAccountList::data(const QModelIndex &index, int role) const return account->username(); case TypeColumn: - return account->displayLoginType(); + return account->provider()->displayName(); default: return QVariant(); @@ -219,7 +219,7 @@ QVariant MojangAccountList::data(const QModelIndex &index, int role) const } } -QVariant MojangAccountList::headerData(int section, Qt::Orientation orientation, int role) const +QVariant AccountList::headerData(int section, Qt::Orientation orientation, int role) const { switch (role) { @@ -254,18 +254,18 @@ QVariant MojangAccountList::headerData(int section, Qt::Orientation orientation, } } -int MojangAccountList::rowCount(const QModelIndex &) const +int AccountList::rowCount(const QModelIndex &) const { // Return count return count(); } -int MojangAccountList::columnCount(const QModelIndex &) const +int AccountList::columnCount(const QModelIndex &) const { return 3; } -Qt::ItemFlags MojangAccountList::flags(const QModelIndex &index) const +Qt::ItemFlags AccountList::flags(const QModelIndex &index) const { if (index.row() < 0 || index.row() >= rowCount(index) || !index.isValid()) { @@ -275,7 +275,7 @@ Qt::ItemFlags MojangAccountList::flags(const QModelIndex &index) const return Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsSelectable; } -bool MojangAccountList::setData(const QModelIndex &index, const QVariant &value, int role) +bool AccountList::setData(const QModelIndex &index, const QVariant &value, int role) { if (index.row() < 0 || index.row() >= rowCount(index) || !index.isValid()) { @@ -286,7 +286,7 @@ bool MojangAccountList::setData(const QModelIndex &index, const QVariant &value, { if(value == Qt::Checked) { - MojangAccountPtr account = this->at(index.row()); + AccountPtr account = this->at(index.row()); this->setActiveAccount(account->username()); } } @@ -295,14 +295,14 @@ bool MojangAccountList::setData(const QModelIndex &index, const QVariant &value, return true; } -void MojangAccountList::updateListData(QList versions) +void AccountList::updateListData(QList versions) { beginResetModel(); m_accounts = versions; endResetModel(); } -bool MojangAccountList::loadList(const QString &filePath) +bool AccountList::loadList(const QString &filePath) { QString path = filePath; if (path.isEmpty()) @@ -366,7 +366,7 @@ bool MojangAccountList::loadList(const QString &filePath) for (QJsonValue accountVal : accounts) { QJsonObject accountObj = accountVal.toObject(); - MojangAccountPtr account = MojangAccount::loadFromJson(accountObj); + AccountPtr account = Account::loadFromJson(accountObj); if (account.get() != nullptr) { connect(account.get(), SIGNAL(changed()), SLOT(accountChanged())); @@ -383,7 +383,7 @@ bool MojangAccountList::loadList(const QString &filePath) return true; } -bool MojangAccountList::saveList(const QString &filePath) +bool AccountList::saveList(const QString &filePath) { QString path(filePath); if (path.isEmpty()) @@ -417,7 +417,7 @@ bool MojangAccountList::saveList(const QString &filePath) // Build a list of accounts. qDebug() << "Building account array."; QJsonArray accounts; - for (MojangAccountPtr account : m_accounts) + for (AccountPtr account : m_accounts) { QJsonObject accountObj = account->saveToJson(); accounts.append(accountObj); @@ -457,13 +457,13 @@ bool MojangAccountList::saveList(const QString &filePath) return true; } -void MojangAccountList::setListFilePath(QString path, bool autosave) +void AccountList::setListFilePath(QString path, bool autosave) { m_listFilePath = path; m_autosave = autosave; } -bool MojangAccountList::anyAccountIsValid() +bool AccountList::anyAccountIsValid() { for(auto account:m_accounts) { diff --git a/api/logic/minecraft/auth/MojangAccountList.h b/api/logic/minecraft/auth/AccountList.h similarity index 90% rename from api/logic/minecraft/auth/MojangAccountList.h rename to api/logic/minecraft/auth/AccountList.h index ab4da1d3..d02c183a 100644 --- a/api/logic/minecraft/auth/MojangAccountList.h +++ b/api/logic/minecraft/auth/AccountList.h @@ -15,7 +15,7 @@ #pragma once -#include "MojangAccount.h" +#include "Account.h" #include #include @@ -33,7 +33,7 @@ * all have a default implementation, but they can be overridden by subclasses to * change the behavior of the list. */ -class MULTIMC_LOGIC_EXPORT MojangAccountList : public QAbstractListModel +class MULTIMC_LOGIC_EXPORT AccountList : public QAbstractListModel { Q_OBJECT public: @@ -56,10 +56,10 @@ public: TypeColumn, }; - explicit MojangAccountList(QObject *parent = 0); + explicit AccountList(QObject *parent = 0); //! Gets the account at the given index. - virtual const MojangAccountPtr at(int i) const; + virtual const AccountPtr at(int i) const; //! Returns the number of accounts in the list. virtual int count() const; @@ -75,7 +75,7 @@ public: /*! * Adds a the given Mojang account to the account list. */ - virtual void addAccount(const MojangAccountPtr account); + virtual void addAccount(const AccountPtr account); /*! * Removes the mojang account with the given username from the account list. @@ -93,7 +93,7 @@ public: * \return A const pointer to the account with the given username. NULL if * one doesn't exist. */ - virtual MojangAccountPtr findAccount(const QString &username) const; + virtual AccountPtr findAccount(const QString &username) const; /*! * Sets the default path to save the list file to. @@ -122,9 +122,9 @@ public: * \brief Gets a pointer to the account that the user has selected as their "active" account. * Which account is active can be overridden on a per-instance basis, but this will return the one that * is set as active globally. - * \return The currently active MojangAccount. If there isn't an active account, returns a null pointer. + * \return The currently active Account. If there isn't an active account, returns a null pointer. */ - virtual MojangAccountPtr activeAccount() const; + virtual AccountPtr activeAccount() const; /*! * Sets the given account as the current active account. @@ -170,12 +170,12 @@ protected: */ void onActiveChanged(); - QList m_accounts; + QList m_accounts; /*! * Account that is currently active. */ - MojangAccountPtr m_activeAccount; + AccountPtr m_activeAccount; //! Path to the account list file. Empty string if there isn't one. QString m_listFilePath; @@ -200,5 +200,5 @@ slots: * then copies the accounts and sets their parents correctly. * \param accounts List of accounts whose parents should be set. */ - virtual void updateListData(QList versions); + virtual void updateListData(QList versions); }; diff --git a/api/logic/minecraft/auth/AccountProfile.h b/api/logic/minecraft/auth/AccountProfile.h new file mode 100644 index 00000000..6cc4b839 --- /dev/null +++ b/api/logic/minecraft/auth/AccountProfile.h @@ -0,0 +1,9 @@ +#pragma once +#include + +struct AccountProfile +{ + QString id; + QString name; + bool legacy; +}; diff --git a/api/logic/minecraft/auth/AuthProviders.cpp b/api/logic/minecraft/auth/AuthProviders.cpp new file mode 100644 index 00000000..546d0fe5 --- /dev/null +++ b/api/logic/minecraft/auth/AuthProviders.cpp @@ -0,0 +1,37 @@ +#include "AuthProviders.h" +#include "providers/ElybyAuthProvider.h" +#include "providers/DummyAuthProvider.h" +#include "providers/MojangAuthProvider.h" + +#define REGISTER_AUTH_PROVIDER(Provider) \ + { \ + AuthProviderPtr provider(new Provider()); \ + m_providers.insert(provider->id(), provider); \ + } + +namespace AuthProviders +{ + + QMap m_providers; + + void load() + { + REGISTER_AUTH_PROVIDER(ElybyAuthProvider); + REGISTER_AUTH_PROVIDER(DummyAuthProvider); + REGISTER_AUTH_PROVIDER(MojangAuthProvider); + } + + AuthProviderPtr lookup(QString id) + { + qDebug() << "LOOKUP AUTH_PROVIDER" << id; + if (m_providers.contains(id)) + return m_providers.value(id); + + qDebug() << "Lookup failed"; + return nullptr; + } + + QList getAll() { + return m_providers.values(); + } +} diff --git a/api/logic/minecraft/auth/AuthProviders.h b/api/logic/minecraft/auth/AuthProviders.h new file mode 100644 index 00000000..5d9bef28 --- /dev/null +++ b/api/logic/minecraft/auth/AuthProviders.h @@ -0,0 +1,22 @@ +#pragma once + +#include +#include "QObjectPtr.h" +#include +#include +#include +#include + +#include "providers/BaseAuthProvider.h" +#include "multimc_logic_export.h" + +/*! + * \brief Namespace for auth providers. + * This class main putpose is to handle registration and lookup of auth providers + */ +namespace AuthProviders +{ + MULTIMC_LOGIC_EXPORT void load(); + MULTIMC_LOGIC_EXPORT AuthProviderPtr lookup(QString id); + MULTIMC_LOGIC_EXPORT QList getAll(); +} diff --git a/api/logic/minecraft/auth/AuthSession.h b/api/logic/minecraft/auth/AuthSession.h index b397d9a1..8700d0dd 100644 --- a/api/logic/minecraft/auth/AuthSession.h +++ b/api/logic/minecraft/auth/AuthSession.h @@ -6,7 +6,7 @@ #include "multimc_logic_export.h" -class MojangAccount; +class Account; struct User { @@ -48,7 +48,7 @@ struct MULTIMC_LOGIC_EXPORT AuthSession bool auth_server_online = false; // Did the user request online mode? bool wants_online = true; - std::shared_ptr m_accountPtr; + std::shared_ptr m_accountPtr; }; typedef std::shared_ptr AuthSessionPtr; diff --git a/api/logic/minecraft/auth/YggdrasilTask.cpp b/api/logic/minecraft/auth/YggdrasilTask.cpp index 5b6f4919..dea3ec76 100644 --- a/api/logic/minecraft/auth/YggdrasilTask.cpp +++ b/api/logic/minecraft/auth/YggdrasilTask.cpp @@ -14,7 +14,7 @@ */ #include "YggdrasilTask.h" -#include "MojangAccount.h" +#include "Account.h" #include #include @@ -27,7 +27,7 @@ #include -YggdrasilTask::YggdrasilTask(MojangAccount *account, QObject *parent) +YggdrasilTask::YggdrasilTask(Account *account, QObject *parent) : Task(parent), m_account(account) { changeState(STATE_CREATED); @@ -40,9 +40,8 @@ void YggdrasilTask::executeTask() // Get the content of the request we're going to send to the server. QJsonDocument doc(getRequestContent()); - QUrl reqUrl(m_account->authEndpoint() + getEndpoint()); - qDebug() << m_account->authEndpoint() + getEndpoint(); - QNetworkRequest netRequest(reqUrl); + QUrl reqUrl(m_account->provider()->authEndpoint() + getEndpoint()); + QNetworkRequest netRequest(reqUrl); netRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); QByteArray requestData = doc.toJson(); diff --git a/api/logic/minecraft/auth/YggdrasilTask.h b/api/logic/minecraft/auth/YggdrasilTask.h index 8af2e132..4234116b 100644 --- a/api/logic/minecraft/auth/YggdrasilTask.h +++ b/api/logic/minecraft/auth/YggdrasilTask.h @@ -22,7 +22,7 @@ #include #include -#include "MojangAccount.h" +#include "Account.h" class QNetworkReply; @@ -33,7 +33,7 @@ class YggdrasilTask : public Task { Q_OBJECT public: - explicit YggdrasilTask(MojangAccount * account, QObject *parent = 0); + explicit YggdrasilTask(Account * account, QObject *parent = 0); virtual ~YggdrasilTask() {}; /** @@ -137,7 +137,7 @@ slots: State state(); protected: // FIXME: segfault disaster waiting to happen - MojangAccount *m_account = nullptr; + Account *m_account = nullptr; QNetworkReply *m_netReply = nullptr; std::shared_ptr m_error; QTimer timeout_keeper; diff --git a/api/logic/minecraft/auth/flows/AuthenticateTask.cpp b/api/logic/minecraft/auth/flows/AuthenticateTask.cpp index 2e8dc859..76622962 100644 --- a/api/logic/minecraft/auth/flows/AuthenticateTask.cpp +++ b/api/logic/minecraft/auth/flows/AuthenticateTask.cpp @@ -15,7 +15,7 @@ */ #include "AuthenticateTask.h" -#include "../MojangAccount.h" +#include "../Account.h" #include #include @@ -25,7 +25,7 @@ #include #include -AuthenticateTask::AuthenticateTask(MojangAccount * account, const QString &password, +AuthenticateTask::AuthenticateTask(Account * account, const QString &password, QObject *parent) : YggdrasilTask(account, parent), m_password(password) { @@ -139,7 +139,7 @@ void AuthenticateTask::processResponse(QJsonObject responseData) // Now, add a new AccountProfile entry to the list. loadedProfiles.append({id, name, legacy}); } - // Put the list of profiles we loaded into the MojangAccount object. + // Put the list of profiles we loaded into the Account object. m_account->m_profiles = loadedProfiles; // Finally, we set the current profile to the correct value. This is pretty simple. diff --git a/api/logic/minecraft/auth/flows/AuthenticateTask.h b/api/logic/minecraft/auth/flows/AuthenticateTask.h index 4c14eec7..2a6f0793 100644 --- a/api/logic/minecraft/auth/flows/AuthenticateTask.h +++ b/api/logic/minecraft/auth/flows/AuthenticateTask.h @@ -22,15 +22,15 @@ #include /** - * The authenticate task takes a MojangAccount with no access token and password and attempts to + * The authenticate task takes a Account with no access token and password and attempts to * authenticate with Mojang's servers. - * If successful, it will set the MojangAccount's access token. + * If successful, it will set the Account's access token. */ class AuthenticateTask : public YggdrasilTask { Q_OBJECT public: - AuthenticateTask(MojangAccount *account, const QString &password, QObject *parent = 0); + AuthenticateTask(Account *account, const QString &password, QObject *parent = 0); protected: virtual QJsonObject getRequestContent() const override; diff --git a/api/logic/minecraft/auth/flows/RefreshTask.cpp b/api/logic/minecraft/auth/flows/RefreshTask.cpp index ecba178d..6a9e3326 100644 --- a/api/logic/minecraft/auth/flows/RefreshTask.cpp +++ b/api/logic/minecraft/auth/flows/RefreshTask.cpp @@ -14,7 +14,7 @@ */ #include "RefreshTask.h" -#include "../MojangAccount.h" +#include "../Account.h" #include #include @@ -23,7 +23,7 @@ #include -RefreshTask::RefreshTask(MojangAccount *account) : YggdrasilTask(account) +RefreshTask::RefreshTask(Account *account) : YggdrasilTask(account) { } diff --git a/api/logic/minecraft/auth/flows/RefreshTask.h b/api/logic/minecraft/auth/flows/RefreshTask.h index f0840dda..364c38c8 100644 --- a/api/logic/minecraft/auth/flows/RefreshTask.h +++ b/api/logic/minecraft/auth/flows/RefreshTask.h @@ -22,7 +22,7 @@ #include /** - * The authenticate task takes a MojangAccount with a possibly timed-out access token + * The authenticate task takes a Account with a possibly timed-out access token * and attempts to authenticate with Mojang's servers. * If successful, it will set the new access token. The token is considered validated. */ @@ -30,7 +30,7 @@ class RefreshTask : public YggdrasilTask { Q_OBJECT public: - RefreshTask(MojangAccount * account); + RefreshTask(Account * account); protected: virtual QJsonObject getRequestContent() const override; diff --git a/api/logic/minecraft/auth/flows/ValidateTask.cpp b/api/logic/minecraft/auth/flows/ValidateTask.cpp index 6b3f0a65..1aeb067a 100644 --- a/api/logic/minecraft/auth/flows/ValidateTask.cpp +++ b/api/logic/minecraft/auth/flows/ValidateTask.cpp @@ -15,7 +15,7 @@ */ #include "ValidateTask.h" -#include "../MojangAccount.h" +#include "../Account.h" #include #include @@ -24,7 +24,7 @@ #include -ValidateTask::ValidateTask(MojangAccount * account, QObject *parent) +ValidateTask::ValidateTask(Account * account, QObject *parent) : YggdrasilTask(account, parent) { } diff --git a/api/logic/minecraft/auth/flows/ValidateTask.h b/api/logic/minecraft/auth/flows/ValidateTask.h index 986c2e9f..5d3722e6 100644 --- a/api/logic/minecraft/auth/flows/ValidateTask.h +++ b/api/logic/minecraft/auth/flows/ValidateTask.h @@ -26,13 +26,13 @@ #include /** - * The validate task takes a MojangAccount and checks to make sure its access token is valid. + * The validate task takes a Account and checks to make sure its access token is valid. */ class ValidateTask : public YggdrasilTask { Q_OBJECT public: - ValidateTask(MojangAccount *account, QObject *parent = 0); + ValidateTask(Account *account, QObject *parent = 0); protected: virtual QJsonObject getRequestContent() const override; diff --git a/api/logic/minecraft/auth/providers/BaseAuthProvider.h b/api/logic/minecraft/auth/providers/BaseAuthProvider.h new file mode 100644 index 00000000..6caf6860 --- /dev/null +++ b/api/logic/minecraft/auth/providers/BaseAuthProvider.h @@ -0,0 +1,52 @@ +#pragma once + +#include +#include "QObjectPtr.h" +#include +#include +#include +#include + + +#include "multimc_logic_export.h" +#include "minecraft/auth/AccountProfile.h" + +class BaseAuthProvider; +typedef std::shared_ptr AuthProviderPtr; + +/*! + * \brief Base class for auth provider. + * This class implements many functions that are common between providers and + * provides a standard interface for all providers. + * + * To create a new provider, create a new class inheriting from this class, + * implement the pure virtual functions, and + */ +class MULTIMC_LOGIC_EXPORT BaseAuthProvider : public QObject //, public std::enable_shared_from_this +{ + Q_OBJECT + +public: + virtual ~BaseAuthProvider(){}; + + // Unique id for provider + virtual QString id() { return "base"; }; + + // Name of provider that displayed in account selector and list + virtual QString displayName() { return "Base"; }; + + // Use dummy auth on login instead of calling endpoint + virtual bool dummyAuth() { return false; }; + + // Endpoint for authlib injector (use empty if authlib injector isn't required) + virtual QString injectorEndpoint() { return ""; }; + + // Endpoint for authentication + virtual QString authEndpoint() { return ""; }; + + // Function to get url of skin to display in launcher + virtual QUrl resolveSkinUrl(AccountProfile profile) { return QUrl(((QString) "https://crafatar.com/skins/%1.png").arg(profile.id)); }; + + // Can change skin (currently only mojang support) + virtual bool canChangeSkin() { return false; } +}; diff --git a/api/logic/minecraft/auth/providers/DummyAuthProvider.h b/api/logic/minecraft/auth/providers/DummyAuthProvider.h new file mode 100644 index 00000000..69810b05 --- /dev/null +++ b/api/logic/minecraft/auth/providers/DummyAuthProvider.h @@ -0,0 +1,25 @@ +#pragma once + +#include +#include "QObjectPtr.h" +#include +#include +#include +#include + +#include "BaseAuthProvider.h" + +class DummyAuthProvider : public BaseAuthProvider +{ + Q_OBJECT + +public: + QString id() + { + return "dummy"; + } + + QString displayName() { return "Local"; } + bool dummyAuth() { return true; } + QString injectorEndpoint() { return "http://localhost:%1"; }; +}; diff --git a/api/logic/minecraft/auth/providers/ElybyAuthProvider.h b/api/logic/minecraft/auth/providers/ElybyAuthProvider.h new file mode 100644 index 00000000..9057712d --- /dev/null +++ b/api/logic/minecraft/auth/providers/ElybyAuthProvider.h @@ -0,0 +1,26 @@ +#pragma once + +#include +#include "QObjectPtr.h" +#include +#include +#include +#include + +#include "BaseAuthProvider.h" + +class ElybyAuthProvider : public BaseAuthProvider +{ + Q_OBJECT + +public: + QString id() + { + return "elyby"; + } + + QString displayName() { return "Ely.by"; }; + QString injectorEndpoint() { return "ely.by"; }; + QString authEndpoint() { return "https://authserver.ely.by/auth/"; }; + QUrl resolveSkinUrl(AccountProfile profile) { return QUrl(((QString) "http://skinsystem.ely.by/skins/%1.png").arg(profile.name)); } +}; diff --git a/api/logic/minecraft/auth/providers/MojangAuthProvider.h b/api/logic/minecraft/auth/providers/MojangAuthProvider.h new file mode 100644 index 00000000..3a580613 --- /dev/null +++ b/api/logic/minecraft/auth/providers/MojangAuthProvider.h @@ -0,0 +1,25 @@ +#pragma once + +#include +#include "QObjectPtr.h" +#include +#include +#include +#include + +#include "BaseAuthProvider.h" + +class MojangAuthProvider : public BaseAuthProvider +{ + Q_OBJECT + +public: + QString id() + { + return "mojang"; + } + + QString displayName() { return "Mojang"; }; + QString authEndpoint() { return "https://authserver.mojang.com/"; }; + bool canChangeSkin() { return true; }; +}; diff --git a/api/logic/minecraft/launch/ClaimAccount.h b/api/logic/minecraft/launch/ClaimAccount.h index c5bd75f3..7dd2fdaa 100644 --- a/api/logic/minecraft/launch/ClaimAccount.h +++ b/api/logic/minecraft/launch/ClaimAccount.h @@ -16,7 +16,7 @@ #pragma once #include -#include +#include class ClaimAccount: public LaunchStep { @@ -33,5 +33,5 @@ public: } private: std::unique_ptr lock; - MojangAccountPtr m_account; + AccountPtr m_account; }; diff --git a/application/LaunchController.cpp b/application/LaunchController.cpp index cd4dde75..387cc2b2 100644 --- a/application/LaunchController.cpp +++ b/application/LaunchController.cpp @@ -1,6 +1,6 @@ #include "LaunchController.h" #include "MainWindow.h" -#include +#include #include "MultiMC.h" #include "dialogs/CustomMessageBox.h" #include "dialogs/ProfileSelectDialog.h" @@ -37,8 +37,8 @@ void LaunchController::login() JavaCommon::checkJVMArgs(m_instance->settings()->get("JvmArgs").toString(), m_parentWidget); // Find an account to use. - std::shared_ptr accounts = MMC->accounts(); - MojangAccountPtr account = accounts->activeAccount(); + std::shared_ptr accounts = MMC->accounts(); + AccountPtr account = accounts->activeAccount(); if (accounts->count() <= 0) { // Tell the user they need to log in at least one account in order to play. diff --git a/application/MainWindow.cpp b/application/MainWindow.cpp index 3e730ab8..d97be1a6 100644 --- a/application/MainWindow.cpp +++ b/application/MainWindow.cpp @@ -54,7 +54,7 @@ #include #include #include -#include +#include #include #include #include @@ -746,11 +746,11 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new MainWindow // Update the menu when the active account changes. // Shouldn't have to use lambdas here like this, but if I don't, the compiler throws a fit. // Template hell sucks... - connect(MMC->accounts().get(), &MojangAccountList::activeAccountChanged, [this] + connect(MMC->accounts().get(), &AccountList::activeAccountChanged, [this] { activeAccountChanged(); }); - connect(MMC->accounts().get(), &MojangAccountList::listChanged, [this] + connect(MMC->accounts().get(), &AccountList::listChanged, [this] { repopulateAccountsMenu(); }); @@ -771,15 +771,8 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new MainWindow } for (auto profile : account->profiles()) { - auto skinsBase = BuildConfig.SKINS_BASE_MOJANG; - auto skinsArg = profile.id; - if (account->loginType() == "elyby") - { - skinsBase = BuildConfig.SKINS_BASE_ELYBY; - skinsArg = profile.name; - } auto meta = Env::getInstance().metacache()->resolveEntry("skins", profile.id + ".png"); - auto action = Net::Download::makeCached(QUrl(skinsBase + skinsArg + ".png"), meta); + auto action = Net::Download::makeCached(account->provider()->resolveSkinUrl(profile), meta); skin_dls.append(action); meta->setStale(true); } @@ -1003,9 +996,9 @@ void MainWindow::updateToolsMenu() ui->actionLaunchInstanceOffline->setMenu(launchOfflineMenu); } -QString formatProfile(const QString & profileName, const QString & loginType, bool used) +QString formatProfile(const QString & profileName, const QString & provider, bool used) { - QString textInBrackets = loginType; + QString textInBrackets = provider; if(used) { textInBrackets += ", in use"; @@ -1018,8 +1011,8 @@ void MainWindow::repopulateAccountsMenu() { accountMenu->clear(); - std::shared_ptr accounts = MMC->accounts(); - MojangAccountPtr active_account = accounts->activeAccount(); + std::shared_ptr accounts = MMC->accounts(); + AccountPtr active_account = accounts->activeAccount(); QString active_username = ""; if (active_account != nullptr) @@ -1029,7 +1022,7 @@ void MainWindow::repopulateAccountsMenu() // this can be called before accountMenuButton exists if (profile != nullptr && accountMenuButton) { - auto profileLabel = formatProfile(profile->name, active_account->displayLoginType(), active_account->isInUse()); + auto profileLabel = formatProfile(profile->name, active_account->provider()->displayName(), active_account->isInUse()); accountMenuButton->setText(profileLabel); } } @@ -1045,11 +1038,10 @@ void MainWindow::repopulateAccountsMenu() // TODO: Nicer way to iterate? for (int i = 0; i < accounts->count(); i++) { - MojangAccountPtr account = accounts->at(i); + AccountPtr account = accounts->at(i); for (auto profile : account->profiles()) { - auto profileLabel = formatProfile(profile.name, account->displayLoginType(), account->isInUse()); - qDebug() << "AAA" << profileLabel; + auto profileLabel = formatProfile(profile.name, account->provider()->displayName(), account->isInUse()); QAction *action = new QAction(profileLabel, this); action->setData(account->username()); action->setCheckable(true); @@ -1119,14 +1111,14 @@ void MainWindow::activeAccountChanged() { repopulateAccountsMenu(); - MojangAccountPtr account = MMC->accounts()->activeAccount(); + AccountPtr account = MMC->accounts()->activeAccount(); if (account != nullptr && account->username() != "") { const AccountProfile *profile = account->currentProfile(); if (profile != nullptr) { - auto profileLabel = formatProfile(profile->name, account->displayLoginType(), account->isInUse()); + auto profileLabel = formatProfile(profile->name, account->provider()->displayName(), account->isInUse()); accountMenuButton->setIcon(SkinUtils::getFaceFromCache(profile->id)); accountMenuButton->setText(profileLabel); return; diff --git a/application/MainWindow.h b/application/MainWindow.h index 3d4114de..f8f8fc03 100644 --- a/application/MainWindow.h +++ b/application/MainWindow.h @@ -22,7 +22,7 @@ #include #include "BaseInstance.h" -#include "minecraft/auth/MojangAccount.h" +#include "minecraft/auth/Account.h" #include "net/NetJob.h" #include "updater/GoUpdate.h" diff --git a/application/MultiMC.cpp b/application/MultiMC.cpp index 90cf7622..7c737c43 100644 --- a/application/MultiMC.cpp +++ b/application/MultiMC.cpp @@ -42,7 +42,8 @@ #include "dialogs/CustomMessageBox.h" #include "InstanceList.h" -#include +#include +#include #include "icons/IconList.h" #include "net/HttpMetaCache.h" #include "Env.h" @@ -683,9 +684,14 @@ MultiMC::MultiMC(int &argc, char **argv) : QApplication(argc, argv) qDebug() << "<> Instances loaded."; } + // load auth providers + { + AuthProviders::load(); + } + // and accounts { - m_accounts.reset(new MojangAccountList(this)); + m_accounts.reset(new AccountList(this)); qDebug() << "Loading accounts..."; m_accounts->setListFilePath("accounts.json", true); m_accounts->loadList(); diff --git a/application/MultiMC.h b/application/MultiMC.h index 1f9e35c1..01f763ab 100644 --- a/application/MultiMC.h +++ b/application/MultiMC.h @@ -24,7 +24,7 @@ class QFile; class HttpMetaCache; class SettingsObject; class InstanceList; -class MojangAccountList; +class AccountList; class IconList; class QNetworkAccessManager; class JavaInstallList; @@ -112,7 +112,7 @@ public: return m_mcedit.get(); } - std::shared_ptr accounts() const + std::shared_ptr accounts() const { return m_accounts; } @@ -189,7 +189,7 @@ private: FolderInstanceProvider * m_instanceFolder = nullptr; std::shared_ptr m_icons; std::shared_ptr m_updateChecker; - std::shared_ptr m_accounts; + std::shared_ptr m_accounts; std::shared_ptr m_javalist; std::shared_ptr m_translations; std::shared_ptr m_globalSettingsProvider; diff --git a/application/dialogs/LoginDialog.cpp b/application/dialogs/LoginDialog.cpp index 365c807d..a2ad6428 100644 --- a/application/dialogs/LoginDialog.cpp +++ b/application/dialogs/LoginDialog.cpp @@ -15,7 +15,7 @@ #include "LoginDialog.h" #include "ui_LoginDialog.h" - +#include "minecraft/auth/AuthProviders.h" #include "minecraft/auth/YggdrasilTask.h" #include @@ -26,6 +26,14 @@ LoginDialog::LoginDialog(QWidget *parent) : QDialog(parent), ui(new Ui::LoginDia ui->progressBar->setVisible(false); ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false); + for(auto provider: AuthProviders::getAll()) { + QRadioButton *button = new QRadioButton(provider->displayName()); + m_radioButtons[provider->id()] = button; + ui->radioLayout->addWidget(button); + } + m_radioButtons["dummy"]->setChecked(true); + adjustSize(); + connect(ui->buttonBox, &QDialogButtonBox::accepted, this, &QDialog::accept); connect(ui->buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject); } @@ -41,14 +49,15 @@ void LoginDialog::accept() setUserInputsEnabled(false); ui->progressBar->setVisible(true); + m_account = Account::createFromUsername(ui->userTextBox->text()); + for(auto providerId: m_radioButtons.keys()){ + if(m_radioButtons[providerId]->isChecked()) { + m_account->setProvider(AuthProviders::lookup(providerId)); + break; + } + } + // Setup the login task and start it - m_account = MojangAccount::createFromUsername(ui->userTextBox->text()); - if (ui->radioMojang->isChecked()) - m_account->setLoginType("mojang"); - else if (ui->radioDummy->isChecked()) - m_account->setLoginType("dummy"); - else if (ui->radioElyby->isChecked()) - m_account->setLoginType("elyby"); m_loginTask = m_account->login(nullptr, ui->passTextBox->text()); connect(m_loginTask.get(), &Task::failed, this, &LoginDialog::onTaskFailed); connect(m_loginTask.get(), &Task::succeeded, this, @@ -109,7 +118,7 @@ void LoginDialog::onTaskProgress(qint64 current, qint64 total) } // Public interface -MojangAccountPtr LoginDialog::newAccount(QWidget *parent, QString msg) +AccountPtr LoginDialog::newAccount(QWidget *parent, QString msg) { LoginDialog dlg(parent); dlg.ui->label->setText(msg); diff --git a/application/dialogs/LoginDialog.h b/application/dialogs/LoginDialog.h index 16bdddfb..50be0f2d 100644 --- a/application/dialogs/LoginDialog.h +++ b/application/dialogs/LoginDialog.h @@ -16,9 +16,10 @@ #pragma once #include +#include #include -#include "minecraft/auth/MojangAccount.h" +#include "minecraft/auth/Account.h" namespace Ui { @@ -32,7 +33,7 @@ class LoginDialog : public QDialog public: ~LoginDialog(); - static MojangAccountPtr newAccount(QWidget *parent, QString message); + static AccountPtr newAccount(QWidget *parent, QString message); private: explicit LoginDialog(QWidget *parent = 0); @@ -53,6 +54,7 @@ slots: private: Ui::LoginDialog *ui; - MojangAccountPtr m_account; + AccountPtr m_account; + QMap m_radioButtons; std::shared_ptr m_loginTask; }; diff --git a/application/dialogs/LoginDialog.ui b/application/dialogs/LoginDialog.ui index b45ddf2b..95287e72 100644 --- a/application/dialogs/LoginDialog.ui +++ b/application/dialogs/LoginDialog.ui @@ -7,7 +7,7 @@ 0 0 400 - 219 + 150 @@ -61,37 +61,7 @@ - - - - - Mojang / Minecraft - - - true - - - - - - - Local (cracked) - - - false - - - - - - Ely.by - - - false - - - - + diff --git a/application/dialogs/ProfileSelectDialog.cpp b/application/dialogs/ProfileSelectDialog.cpp index ae34709f..fce59738 100644 --- a/application/dialogs/ProfileSelectDialog.cpp +++ b/application/dialogs/ProfileSelectDialog.cpp @@ -33,7 +33,7 @@ ProfileSelectDialog::ProfileSelectDialog(const QString &message, int flags, QWid m_accounts = MMC->accounts(); auto view = ui->listView; //view->setModel(m_accounts.get()); - //view->hideColumn(MojangAccountList::ActiveColumn); + //view->hideColumn(AccountList::ActiveColumn); view->setColumnCount(1); view->setRootIsDecorated(false); if(QTreeWidgetItem* header = view->headerItem()) @@ -47,7 +47,7 @@ ProfileSelectDialog::ProfileSelectDialog(const QString &message, int flags, QWid QList items; for (int i = 0; i < m_accounts->count(); i++) { - MojangAccountPtr account = m_accounts->at(i); + AccountPtr account = m_accounts->at(i); for (auto profile : account->profiles()) { auto profileLabel = profile.name; @@ -58,7 +58,7 @@ ProfileSelectDialog::ProfileSelectDialog(const QString &message, int flags, QWid auto item = new QTreeWidgetItem(view); item->setText(0, profileLabel); item->setIcon(0, SkinUtils::getFaceFromCache(profile.id)); - item->setData(0, MojangAccountList::PointerRole, QVariant::fromValue(account)); + item->setData(0, AccountList::PointerRole, QVariant::fromValue(account)); items.append(item); } } @@ -84,7 +84,7 @@ ProfileSelectDialog::~ProfileSelectDialog() delete ui; } -MojangAccountPtr ProfileSelectDialog::selectedAccount() const +AccountPtr ProfileSelectDialog::selectedAccount() const { return m_selected; } @@ -105,7 +105,7 @@ void ProfileSelectDialog::on_buttonBox_accepted() if (selection.size() > 0) { QModelIndex selected = selection.first(); - m_selected = selected.data(MojangAccountList::PointerRole).value(); + m_selected = selected.data(AccountList::PointerRole).value(); } close(); } diff --git a/application/dialogs/ProfileSelectDialog.h b/application/dialogs/ProfileSelectDialog.h index 9f95830c..1147494f 100644 --- a/application/dialogs/ProfileSelectDialog.h +++ b/application/dialogs/ProfileSelectDialog.h @@ -19,7 +19,7 @@ #include -#include "minecraft/auth/MojangAccountList.h" +#include "minecraft/auth/AccountList.h" namespace Ui { @@ -59,7 +59,7 @@ public: * Gets a pointer to the account that the user selected. * This is null if the user clicked cancel or hasn't clicked OK yet. */ - MojangAccountPtr selectedAccount() const; + AccountPtr selectedAccount() const; /*! * Returns true if the user checked the "use as global default" checkbox. @@ -80,10 +80,10 @@ slots: void on_buttonBox_rejected(); protected: - std::shared_ptr m_accounts; + std::shared_ptr m_accounts; //! The account that was selected when the user clicked OK. - MojangAccountPtr m_selected; + AccountPtr m_selected; private: Ui::ProfileSelectDialog *ui; diff --git a/application/dialogs/SkinUploadDialog.cpp b/application/dialogs/SkinUploadDialog.cpp index 56133529..0664fc27 100644 --- a/application/dialogs/SkinUploadDialog.cpp +++ b/application/dialogs/SkinUploadDialog.cpp @@ -107,7 +107,7 @@ void SkinUploadDialog::on_skinBrowseBtn_clicked() ui->skinPathTextBox->setText(cooked_path); } -SkinUploadDialog::SkinUploadDialog(MojangAccountPtr acct, QWidget *parent) +SkinUploadDialog::SkinUploadDialog(AccountPtr acct, QWidget *parent) :QDialog(parent), m_acct(acct), ui(new Ui::SkinUploadDialog) { ui->setupUi(this); diff --git a/application/dialogs/SkinUploadDialog.h b/application/dialogs/SkinUploadDialog.h index deb44eac..38bde275 100644 --- a/application/dialogs/SkinUploadDialog.h +++ b/application/dialogs/SkinUploadDialog.h @@ -1,7 +1,7 @@ #pragma once #include -#include +#include namespace Ui { @@ -11,7 +11,7 @@ namespace Ui class SkinUploadDialog : public QDialog { Q_OBJECT public: - explicit SkinUploadDialog(MojangAccountPtr acct, QWidget *parent = 0); + explicit SkinUploadDialog(AccountPtr acct, QWidget *parent = 0); virtual ~SkinUploadDialog() {}; public slots: @@ -22,7 +22,7 @@ public slots: void on_skinBrowseBtn_clicked(); protected: - MojangAccountPtr m_acct; + AccountPtr m_acct; private: Ui::SkinUploadDialog *ui; diff --git a/application/pages/global/AccountListPage.cpp b/application/pages/global/AccountListPage.cpp index 7e318499..0ce62f65 100644 --- a/application/pages/global/AccountListPage.cpp +++ b/application/pages/global/AccountListPage.cpp @@ -125,8 +125,8 @@ void AccountListPage::on_actionSetDefault_triggered() if (selection.size() > 0) { QModelIndex selected = selection.first(); - MojangAccountPtr account = - selected.data(MojangAccountList::PointerRole).value(); + AccountPtr account = + selected.data(AccountList::PointerRole).value(); m_accounts->setActiveAccount(account->username()); } } @@ -144,7 +144,7 @@ void AccountListPage::updateButtonStates() ui->actionRemove->setEnabled(selection.size() > 0); ui->actionSetDefault->setEnabled(selection.size() > 0); - bool enableSkins = selection.size() > 0 && selection.first().data(MojangAccountList::PointerRole).value()->loginType() == "mojang"; + bool enableSkins = selection.size() > 0 && selection.first().data(AccountList::PointerRole).value()->provider()->canChangeSkin(); ui->actionUploadSkin->setEnabled(enableSkins); ui->actionDeleteSkin->setEnabled(enableSkins); @@ -162,7 +162,7 @@ void AccountListPage::updateButtonStates() void AccountListPage::addAccount(const QString &errMsg) { // TODO: The login dialog isn't quite done yet - MojangAccountPtr account = LoginDialog::newAccount(this, errMsg); + AccountPtr account = LoginDialog::newAccount(this, errMsg); if (account != nullptr) { @@ -175,15 +175,8 @@ void AccountListPage::addAccount(const QString &errMsg) for (AccountProfile profile : account->profiles()) { - auto skinsBase = BuildConfig.SKINS_BASE_MOJANG; - auto skinsArg = profile.id; - if (account->loginType() == "elyby") - { - skinsBase = BuildConfig.SKINS_BASE_ELYBY; - skinsArg = profile.name; - } auto meta = Env::getInstance().metacache()->resolveEntry("skins", profile.id + ".png"); - auto action = Net::Download::makeCached(QUrl(skinsBase + skinsArg + ".png"), meta); + auto action = Net::Download::makeCached(account->provider()->resolveSkinUrl(profile), meta); job->addNetAction(action); meta->setStale(true); } @@ -198,7 +191,7 @@ void AccountListPage::on_actionUploadSkin_triggered() if (selection.size() > 0) { QModelIndex selected = selection.first(); - MojangAccountPtr account = selected.data(MojangAccountList::PointerRole).value(); + AccountPtr account = selected.data(AccountList::PointerRole).value(); SkinUploadDialog dialog(account, this); dialog.exec(); } @@ -212,7 +205,7 @@ void AccountListPage::on_actionDeleteSkin_triggered() QModelIndex selected = selection.first(); AuthSessionPtr session = std::make_shared(); - MojangAccountPtr account = selected.data(MojangAccountList::PointerRole).value(); + AccountPtr account = selected.data(AccountList::PointerRole).value(); auto login = account->login(session); ProgressDialog prog(this); if (prog.execWithTask((Task*)login.get()) != QDialog::Accepted) { diff --git a/application/pages/global/AccountListPage.h b/application/pages/global/AccountListPage.h index fba1833f..acc0e324 100644 --- a/application/pages/global/AccountListPage.h +++ b/application/pages/global/AccountListPage.h @@ -20,7 +20,7 @@ #include "pages/BasePage.h" -#include "minecraft/auth/MojangAccountList.h" +#include "minecraft/auth/AccountList.h" #include "MultiMC.h" namespace Ui @@ -79,6 +79,6 @@ protected slots: private: void changeEvent(QEvent * event) override; QMenu * createPopupMenu() override; - std::shared_ptr m_accounts; + std::shared_ptr m_accounts; Ui::AccountListPage *ui; }; diff --git a/application/pages/instance/VersionPage.cpp b/application/pages/instance/VersionPage.cpp index 7f7ba860..e47d0f9a 100644 --- a/application/pages/instance/VersionPage.cpp +++ b/application/pages/instance/VersionPage.cpp @@ -38,7 +38,7 @@ #include #include "minecraft/PackProfile.h" -#include "minecraft/auth/MojangAccountList.h" +#include "minecraft/auth/AccountList.h" #include "minecraft/mod/Mod.h" #include "icons/IconList.h" #include "Exception.h"