diff options
-rw-r--r-- | gui/MainWindow.cpp | 134 | ||||
-rw-r--r-- | gui/MainWindow.h | 12 | ||||
-rw-r--r-- | logic/BaseInstance.h | 6 | ||||
-rw-r--r-- | logic/InstanceLauncher.cpp | 3 | ||||
-rw-r--r-- | logic/LegacyInstance.cpp | 6 | ||||
-rw-r--r-- | logic/LegacyInstance.h | 4 | ||||
-rw-r--r-- | logic/OneSixInstance.cpp | 16 | ||||
-rw-r--r-- | logic/OneSixInstance.h | 6 | ||||
-rw-r--r-- | logic/auth/MojangAccount.cpp | 55 | ||||
-rw-r--r-- | logic/auth/MojangAccount.h | 2 | ||||
-rw-r--r-- | logic/lists/MojangAccountList.cpp | 14 |
11 files changed, 144 insertions, 114 deletions
diff --git a/gui/MainWindow.cpp b/gui/MainWindow.cpp index 3bf248f9..734ed3b4 100644 --- a/gui/MainWindow.cpp +++ b/gui/MainWindow.cpp @@ -544,11 +544,7 @@ void MainWindow::instanceActivated(QModelIndex index) NagUtils::checkJVMArgs(inst->settings().get("JvmArgs").toString(), this); - bool autoLogin = inst->settings().get("AutoLogin").toBool(); - if (autoLogin) - doAutoLogin(); - else - doLogin(); + doLogin(); } void MainWindow::on_actionLaunchInstance_triggered() @@ -560,56 +556,34 @@ void MainWindow::on_actionLaunchInstance_triggered() } } -void MainWindow::doAutoLogin() +void MainWindow::doLogin(const QString &errorMsg) { if (!m_selectedInstance) return; - Keyring *k = Keyring::instance(); - QStringList accounts = k->getStoredAccounts("minecraft"); - - if (!accounts.isEmpty()) + // Find an account to use. + std::shared_ptr<MojangAccountList> accounts = MMC->accounts(); + MojangAccountPtr account; + if (accounts->count() <= 0) { - QString username = accounts[0]; - QString password = k->getPassword("minecraft", username); - - if (!password.isEmpty()) - { - QLOG_INFO() << "Automatically logging in with stored account: " << username; - m_activeInst = m_selectedInstance; - doLogin(username, password); - } - else - { - QLOG_ERROR() << "Auto login set for account, but no password was found: " - << username; - doLogin(tr("Auto login attempted, but no password is stored.")); - } + // Tell the user they need to log in at least one account in order to play. + CustomMessageBox::selectable(this, tr("No Accounts"), + tr("In order to play Minecraft, you must have at least one Mojang or Minecraft account logged in to MultiMC. Please add an account."), + QMessageBox::Warning)->show(); } else { - QLOG_ERROR() << "Auto login set but no accounts were stored."; - doLogin(tr("Auto login attempted, but no accounts are stored.")); + // TODO: Allow user to select different accounts. + // For now, we'll just use the first one in the list until I get arround to implementing that. + account = accounts->at(0); } -} - -void MainWindow::doLogin(QString username, QString password) -{ - UserInfo uInfo{username, password}; - - ProgressDialog *tDialog = new ProgressDialog(this); - LoginTask *loginTask = new LoginTask(uInfo, tDialog); - connect(loginTask, SIGNAL(succeeded()), SLOT(onLoginComplete()), Qt::QueuedConnection); - connect(loginTask, SIGNAL(failed(QString)), SLOT(doLogin(QString)), Qt::QueuedConnection); - - tDialog->exec(loginTask); -} -void MainWindow::doLogin(const QString &errorMsg) -{ - if (!m_selectedInstance) - return; + // We'll need to validate the access token to make sure the account is still logged in. + // TODO: Do that ^ + + launchInstance(m_selectedInstance, account); + /* LoginDialog *loginDlg = new LoginDialog(this, errorMsg); if (!m_selectedInstance->lastLaunch()) loginDlg->forceOnline(); @@ -632,6 +606,41 @@ void MainWindow::doLogin(const QString &errorMsg) launchInstance(m_activeInst, m_activeLogin); } } + */ +} + +void MainWindow::launchInstance(BaseInstance *instance, MojangAccountPtr account) +{ + Q_ASSERT_X(instance != NULL, "launchInstance", "instance is NULL"); + + proc = instance->prepareForLaunch(account); + if (!proc) + return; + + // Prepare GUI: If it shall stay open disable the required parts + if (MMC->settings()->get("NoHide").toBool()) + { + ui->actionLaunchInstance->setEnabled(false); + } + else + { + this->hide(); + } + + console = new ConsoleWindow(proc); + + connect(proc, SIGNAL(log(QString, MessageLevel::Enum)), console, + SLOT(write(QString, MessageLevel::Enum))); + connect(proc, SIGNAL(ended(BaseInstance *)), this, SLOT(instanceEnded(BaseInstance *))); + + if (instance->settings().get("ShowConsole").toBool()) + { + console->show(); + } + + // I think this will work... + proc->setLogin(account->username(), account->accessToken()); + proc->launch(); } void MainWindow::onLoginComplete() @@ -644,7 +653,7 @@ void MainWindow::onLoginComplete() BaseUpdate *updateTask = m_activeInst->doUpdate(); if (!updateTask) { - launchInstance(m_activeInst, m_activeLogin); + //launchInstance(m_activeInst, m_activeLogin); } else { @@ -701,7 +710,7 @@ void MainWindow::onLoginComplete() void MainWindow::onGameUpdateComplete() { - launchInstance(m_activeInst, m_activeLogin); + //launchInstance(m_activeInst, m_activeLogin); } void MainWindow::onGameUpdateError(QString error) @@ -710,39 +719,6 @@ void MainWindow::onGameUpdateError(QString error) QMessageBox::Warning)->show(); } -void MainWindow::launchInstance(BaseInstance *instance, LoginResponse response) -{ - Q_ASSERT_X(instance != NULL, "launchInstance", "instance is NULL"); - - proc = instance->prepareForLaunch(response); - if (!proc) - return; - - // Prepare GUI: If it shall stay open disable the required parts - if (MMC->settings()->get("NoHide").toBool()) - { - ui->actionLaunchInstance->setEnabled(false); - } - else - { - this->hide(); - } - - console = new ConsoleWindow(proc); - - connect(proc, SIGNAL(log(QString, MessageLevel::Enum)), console, - SLOT(write(QString, MessageLevel::Enum))); - connect(proc, SIGNAL(ended(BaseInstance *)), this, SLOT(instanceEnded(BaseInstance *))); - - if (instance->settings().get("ShowConsole").toBool()) - { - console->show(); - } - - proc->setLogin(response.username, response.session_id); - proc->launch(); -} - void MainWindow::taskStart() { // Nothing to do here yet. diff --git a/gui/MainWindow.h b/gui/MainWindow.h index b89aab7c..c0fcc385 100644 --- a/gui/MainWindow.h +++ b/gui/MainWindow.h @@ -21,6 +21,8 @@ #include "logic/net/LoginTask.h" #include "logic/BaseInstance.h" +#include "logic/auth/MojangAccount.h" + class QToolButton; class LabeledToolButton; class QLabel; @@ -104,8 +106,12 @@ slots: void on_actionEditInstNotes_triggered(); void doLogin(const QString &errorMsg = ""); - void doLogin(QString username, QString password); - void doAutoLogin(); + + /*! + * Launches the given instance with the given account. + * This function assumes that the given account has a valid, usable access token. + */ + void launchInstance(BaseInstance* instance, MojangAccountPtr account); void onLoginComplete(); @@ -137,8 +143,6 @@ slots: void startTask(Task *task); - void launchInstance(BaseInstance *inst, LoginResponse response); - protected: bool eventFilter(QObject *obj, QEvent *ev); void setCatBackground(bool enabled); diff --git a/logic/BaseInstance.h b/logic/BaseInstance.h index b083c24a..b92d50cc 100644 --- a/logic/BaseInstance.h +++ b/logic/BaseInstance.h @@ -22,7 +22,7 @@ #include "inifile.h" #include "lists/BaseVersionList.h" -#include "net/LoginTask.h" +#include "logic/auth/MojangAccount.h" class QDialog; class BaseUpdate; @@ -153,8 +153,8 @@ public: /// returns a valid update task if update is needed, NULL otherwise virtual BaseUpdate *doUpdate() = 0; - /// returns a valid minecraft process, ready for launch - virtual MinecraftProcess *prepareForLaunch(LoginResponse response) = 0; + /// returns a valid minecraft process, ready for launch with the given account. + virtual MinecraftProcess *prepareForLaunch(MojangAccountPtr account) = 0; /// do any necessary cleanups after the instance finishes. also runs before /// 'prepareForLaunch' diff --git a/logic/InstanceLauncher.cpp b/logic/InstanceLauncher.cpp index 9f78e55b..c4df8220 100644 --- a/logic/InstanceLauncher.cpp +++ b/logic/InstanceLauncher.cpp @@ -38,6 +38,8 @@ void InstanceLauncher::onTerminated() void InstanceLauncher::onLoginComplete() { + // TODO: Fix this. + /* LoginTask *task = (LoginTask *)QObject::sender(); auto result = task->getResult(); auto instance = MMC->instances()->getInstanceById(instId); @@ -55,6 +57,7 @@ void InstanceLauncher::onLoginComplete() SLOT(write(QString, MessageLevel::Enum))); proc->launch(); + */ } void InstanceLauncher::doLogin(const QString &errorMsg) diff --git a/logic/LegacyInstance.cpp b/logic/LegacyInstance.cpp index 9a91b839..3a337140 100644 --- a/logic/LegacyInstance.cpp +++ b/logic/LegacyInstance.cpp @@ -50,7 +50,7 @@ BaseUpdate *LegacyInstance::doUpdate() return new LegacyUpdate(this, this); } -MinecraftProcess *LegacyInstance::prepareForLaunch(LoginResponse response) +MinecraftProcess *LegacyInstance::prepareForLaunch(MojangAccountPtr account) { MinecraftProcess *proc = new MinecraftProcess(this); @@ -103,8 +103,8 @@ MinecraftProcess *LegacyInstance::prepareForLaunch(LoginResponse response) #endif args << "-jar" << LAUNCHER_FILE; - args << response.player_name; - args << response.session_id; + args << account->currentProfile()->name(); + args << account->accessToken(); args << windowTitle; args << windowSize; args << lwjgl; diff --git a/logic/LegacyInstance.h b/logic/LegacyInstance.h index 8a8d4b91..e78bfd73 100644 --- a/logic/LegacyInstance.h +++ b/logic/LegacyInstance.h @@ -80,7 +80,7 @@ public: virtual void setShouldUpdate(bool val); virtual BaseUpdate *doUpdate(); - virtual MinecraftProcess *prepareForLaunch(LoginResponse response); + virtual MinecraftProcess *prepareForLaunch(MojangAccountPtr account); virtual void cleanupAfterRun(); virtual QDialog *createModEditDialog(QWidget *parent); @@ -93,4 +93,4 @@ public: protected slots: virtual void jarModsChanged(); -};
\ No newline at end of file +}; diff --git a/logic/OneSixInstance.cpp b/logic/OneSixInstance.cpp index 5c93236b..5a83bafc 100644 --- a/logic/OneSixInstance.cpp +++ b/logic/OneSixInstance.cpp @@ -65,7 +65,7 @@ QString replaceTokensIn(QString text, QMap<QString, QString> with) return result; } -QStringList OneSixInstance::processMinecraftArgs(LoginResponse response) +QStringList OneSixInstance::processMinecraftArgs(MojangAccountPtr account) { I_D(OneSixInstance); auto version = d->version; @@ -73,11 +73,11 @@ QStringList OneSixInstance::processMinecraftArgs(LoginResponse response) QMap<QString, QString> token_mapping; // yggdrasil! - token_mapping["auth_username"] = response.username; - token_mapping["auth_session"] = response.session_id; - token_mapping["auth_access_token"] = response.access_token; - token_mapping["auth_player_name"] = response.player_name; - token_mapping["auth_uuid"] = response.player_id; + token_mapping["auth_username"] = account->username(); + //token_mapping["auth_session"] = response.session_id; + token_mapping["auth_access_token"] = account->accessToken(); + token_mapping["auth_player_name"] = account->currentProfile()->name(); + token_mapping["auth_uuid"] = account->currentProfile()->id(); // this is for offline?: /* @@ -102,7 +102,7 @@ QStringList OneSixInstance::processMinecraftArgs(LoginResponse response) return parts; } -MinecraftProcess *OneSixInstance::prepareForLaunch(LoginResponse response) +MinecraftProcess *OneSixInstance::prepareForLaunch(MojangAccountPtr account) { I_D(OneSixInstance); cleanupAfterRun(); @@ -169,7 +169,7 @@ MinecraftProcess *OneSixInstance::prepareForLaunch(LoginResponse response) args << classPath; } args << version->mainClass; - args.append(processMinecraftArgs(response)); + args.append(processMinecraftArgs(account)); // Set the width and height for 1.6 instances bool maximize = settings().get("LaunchMaximized").toBool(); diff --git a/logic/OneSixInstance.h b/logic/OneSixInstance.h index 2d02b605..c1c742a8 100644 --- a/logic/OneSixInstance.h +++ b/logic/OneSixInstance.h @@ -40,7 +40,7 @@ public: virtual QString instanceConfigFolder() const; virtual BaseUpdate *doUpdate(); - virtual MinecraftProcess *prepareForLaunch(LoginResponse response); + virtual MinecraftProcess *prepareForLaunch(MojangAccountPtr account); virtual void cleanupAfterRun(); virtual QString intendedVersionId() const; @@ -72,5 +72,5 @@ public: virtual QString getStatusbarDescription(); private: - QStringList processMinecraftArgs(LoginResponse response); -};
\ No newline at end of file + QStringList processMinecraftArgs(MojangAccountPtr account); +}; diff --git a/logic/auth/MojangAccount.cpp b/logic/auth/MojangAccount.cpp index 80b88082..4875e5f7 100644 --- a/logic/auth/MojangAccount.cpp +++ b/logic/auth/MojangAccount.cpp @@ -18,6 +18,8 @@ #include "MojangAccount.h" #include <QUuid> +#include <QJsonObject> +#include <QJsonArray> #include <logger/QsLog.h> @@ -89,7 +91,12 @@ const QList<AccountProfile> MojangAccount::profiles() const const AccountProfile* MojangAccount::currentProfile() const { if (m_currentProfile < 0) - return nullptr; + { + if (m_profiles.length() > 0) + return &m_profiles.at(0); + else + return nullptr; + } else return &m_profiles.at(m_currentProfile); } @@ -128,9 +135,36 @@ MojangAccountPtr MojangAccount::loadFromJson(const QJsonObject& object) QString clientToken = object.value("clientToken").toString(""); QString accessToken = object.value("accessToken").toString(""); - // TODO: Load profiles? + QJsonArray profileArray = object.value("profiles").toArray(); + if (profileArray.size() < 1) + { + QLOG_ERROR() << "Can't load Mojang account with username \"" << username << "\". No profiles found."; + return nullptr; + } + + ProfileList profiles; + for (QJsonValue profileVal : profileArray) + { + QJsonObject profileObject = profileVal.toObject(); + QString id = profileObject.value("id").toString(""); + QString name = profileObject.value("name").toString(""); + if (id.isEmpty() || name.isEmpty()) + { + QLOG_WARN() << "Unable to load a profile because it was missing an ID or a name."; + continue; + } + profiles.append(AccountProfile(id, name)); + } + + MojangAccountPtr account(new MojangAccount(username, clientToken, accessToken)); + account->loadProfiles(profiles); - return MojangAccountPtr(new MojangAccount(username, clientToken, accessToken)); + // Get the currently selected profile. + QString currentProfile = object.value("activeProfile").toString(""); + if (!currentProfile.isEmpty()) + account->setProfile(currentProfile); + + return account; } QJsonObject MojangAccount::saveToJson() @@ -139,7 +173,20 @@ QJsonObject MojangAccount::saveToJson() json.insert("username", username()); json.insert("clientToken", clientToken()); json.insert("accessToken", accessToken()); - // TODO: Save profiles? + + QJsonArray profileArray; + for (AccountProfile profile : m_profiles) + { + QJsonObject profileObj; + 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()); + return json; } diff --git a/logic/auth/MojangAccount.h b/logic/auth/MojangAccount.h index 35261d65..e5684b77 100644 --- a/logic/auth/MojangAccount.h +++ b/logic/auth/MojangAccount.h @@ -123,7 +123,7 @@ public: /** * Returns a pointer to the currently selected profile. - * If no profile is selected, returns nullptr. + * If no profile is selected, returns the first profile in the profile list or nullptr if there are none. */ const AccountProfile* currentProfile() const; diff --git a/logic/lists/MojangAccountList.cpp b/logic/lists/MojangAccountList.cpp index 68a4da18..32317f84 100644 --- a/logic/lists/MojangAccountList.cpp +++ b/logic/lists/MojangAccountList.cpp @@ -185,7 +185,7 @@ bool MojangAccountList::loadList(const QString& filePath) // TODO: We should probably report this error to the user. if (!file.open(QIODevice::ReadOnly)) { - QLOG_ERROR() << "Failed to read the account list file (" << path << ")."; + QLOG_ERROR() << QString("Failed to read the account list file (%1).").arg(path).toUtf8(); return false; } @@ -217,9 +217,9 @@ bool MojangAccountList::loadList(const QString& filePath) // Make sure the format version matches. if (root.value("formatVersion").toVariant().toInt() != ACCOUNT_LIST_FORMAT_VERSION) { - QString newName = "accountlist-old.json"; - QLOG_WARN() << "Format version mismatch when loading account list. Existing one will be renamed to \"" - << newName << "\"."; + QString newName = "accounts-old.json"; + QLOG_WARN() << "Format version mismatch when loading account list. Existing one will be renamed to" + << newName; // Attempt to rename the old version. file.rename(newName); @@ -257,7 +257,7 @@ bool MojangAccountList::saveList(const QString& filePath) return false; } - QLOG_INFO() << "Writing account list to \"" << path << "\"..."; + QLOG_INFO() << "Writing account list to" << path; QLOG_DEBUG() << "Building JSON data structure."; // Build the JSON document to write to the list file. @@ -289,7 +289,7 @@ bool MojangAccountList::saveList(const QString& filePath) // TODO: We should probably report this error to the user. if (!file.open(QIODevice::WriteOnly)) { - QLOG_ERROR() << "Failed to read the account list file (" << path << ")."; + QLOG_ERROR() << QString("Failed to read the account list file (%1).").arg(path).toUtf8(); return false; } @@ -297,7 +297,7 @@ bool MojangAccountList::saveList(const QString& filePath) file.write(doc.toJson()); file.close(); - QLOG_INFO() << "Saved account list to \"" << path << "\"."; + QLOG_INFO() << "Saved account list to" << path; return true; } |