aboutsummaryrefslogtreecommitdiff
path: root/launcher
diff options
context:
space:
mode:
Diffstat (limited to 'launcher')
-rw-r--r--launcher/Application.cpp1
-rw-r--r--launcher/CMakeLists.txt68
-rw-r--r--launcher/LaunchController.cpp219
-rw-r--r--launcher/minecraft/auth/AccountData.h15
-rw-r--r--launcher/minecraft/auth/AccountList.cpp138
-rw-r--r--launcher/minecraft/auth/AccountList.h28
-rw-r--r--launcher/minecraft/auth/AccountTask.cpp75
-rw-r--r--launcher/minecraft/auth/AccountTask.h72
-rw-r--r--launcher/minecraft/auth/AuthRequest.cpp (renamed from launcher/minecraft/auth/flows/AuthRequest.cpp)10
-rw-r--r--launcher/minecraft/auth/AuthRequest.h (renamed from launcher/minecraft/auth/flows/AuthRequest.h)8
-rw-r--r--launcher/minecraft/auth/AuthStep.cpp7
-rw-r--r--launcher/minecraft/auth/AuthStep.h33
-rw-r--r--launcher/minecraft/auth/MinecraftAccount.cpp259
-rw-r--r--launcher/minecraft/auth/MinecraftAccount.h37
-rw-r--r--launcher/minecraft/auth/Parsers.cpp (renamed from launcher/minecraft/auth/flows/Parsers.cpp)2
-rw-r--r--launcher/minecraft/auth/Parsers.h (renamed from launcher/minecraft/auth/flows/Parsers.h)4
-rw-r--r--launcher/minecraft/auth/Yggdrasil.cpp (renamed from launcher/minecraft/auth/flows/Yggdrasil.cpp)34
-rw-r--r--launcher/minecraft/auth/Yggdrasil.h (renamed from launcher/minecraft/auth/flows/Yggdrasil.h)22
-rw-r--r--launcher/minecraft/auth/flows/AuthContext.cpp671
-rw-r--r--launcher/minecraft/auth/flows/AuthContext.h110
-rw-r--r--launcher/minecraft/auth/flows/AuthFlow.cpp71
-rw-r--r--launcher/minecraft/auth/flows/AuthFlow.h45
-rw-r--r--launcher/minecraft/auth/flows/MSA.cpp37
-rw-r--r--launcher/minecraft/auth/flows/MSA.h22
-rw-r--r--launcher/minecraft/auth/flows/MSAInteractive.cpp22
-rw-r--r--launcher/minecraft/auth/flows/MSAInteractive.h13
-rw-r--r--launcher/minecraft/auth/flows/MSASilent.cpp16
-rw-r--r--launcher/minecraft/auth/flows/MSASilent.h13
-rw-r--r--launcher/minecraft/auth/flows/Mojang.cpp27
-rw-r--r--launcher/minecraft/auth/flows/Mojang.h26
-rw-r--r--launcher/minecraft/auth/flows/MojangLogin.cpp18
-rw-r--r--launcher/minecraft/auth/flows/MojangLogin.h17
-rw-r--r--launcher/minecraft/auth/flows/MojangRefresh.cpp17
-rw-r--r--launcher/minecraft/auth/flows/MojangRefresh.h10
-rw-r--r--launcher/minecraft/auth/steps/EntitlementsStep.cpp53
-rw-r--r--launcher/minecraft/auth/steps/EntitlementsStep.h25
-rw-r--r--launcher/minecraft/auth/steps/GetSkinStep.cpp43
-rw-r--r--launcher/minecraft/auth/steps/GetSkinStep.h22
-rw-r--r--launcher/minecraft/auth/steps/LauncherLoginStep.cpp78
-rw-r--r--launcher/minecraft/auth/steps/LauncherLoginStep.h22
-rw-r--r--launcher/minecraft/auth/steps/MSAStep.cpp111
-rw-r--r--launcher/minecraft/auth/steps/MSAStep.h32
-rw-r--r--launcher/minecraft/auth/steps/MigrationEligibilityStep.cpp45
-rw-r--r--launcher/minecraft/auth/steps/MigrationEligibilityStep.h22
-rw-r--r--launcher/minecraft/auth/steps/MinecraftProfileStep.cpp83
-rw-r--r--launcher/minecraft/auth/steps/MinecraftProfileStep.h22
-rw-r--r--launcher/minecraft/auth/steps/XboxAuthorizationStep.cpp158
-rw-r--r--launcher/minecraft/auth/steps/XboxAuthorizationStep.h34
-rw-r--r--launcher/minecraft/auth/steps/XboxProfileStep.cpp73
-rw-r--r--launcher/minecraft/auth/steps/XboxProfileStep.h22
-rw-r--r--launcher/minecraft/auth/steps/XboxUserStep.cpp68
-rw-r--r--launcher/minecraft/auth/steps/XboxUserStep.h22
-rw-r--r--launcher/minecraft/auth/steps/YggdrasilStep.cpp51
-rw-r--r--launcher/minecraft/auth/steps/YggdrasilStep.h28
-rw-r--r--launcher/minecraft/services/CapeChange.cpp8
-rw-r--r--launcher/minecraft/services/CapeChange.h5
-rw-r--r--launcher/minecraft/services/SkinDelete.cpp6
-rw-r--r--launcher/minecraft/services/SkinDelete.h6
-rw-r--r--launcher/minecraft/services/SkinUpload.cpp6
-rw-r--r--launcher/minecraft/services/SkinUpload.h5
-rw-r--r--launcher/ui/dialogs/LoginDialog.cpp2
-rw-r--r--launcher/ui/dialogs/MSALoginDialog.cpp2
-rw-r--r--launcher/ui/dialogs/ProfileSetupDialog.cpp10
-rw-r--r--launcher/ui/dialogs/SkinUploadDialog.cpp15
-rw-r--r--launcher/ui/pages/global/AccountListPage.cpp16
-rw-r--r--launcher/ui/widgets/ErrorFrame.cpp134
-rw-r--r--launcher/ui/widgets/ErrorFrame.h49
-rw-r--r--launcher/ui/widgets/ErrorFrame.ui92
68 files changed, 2098 insertions, 1439 deletions
diff --git a/launcher/Application.cpp b/launcher/Application.cpp
index 37724038..2d0c81bb 100644
--- a/launcher/Application.cpp
+++ b/launcher/Application.cpp
@@ -827,6 +827,7 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv)
qDebug() << "Loading accounts...";
m_accounts->setListFilePath("accounts.json", true);
m_accounts->loadList();
+ m_accounts->fillQueue();
qDebug() << "<> Accounts loaded.";
}
diff --git a/launcher/CMakeLists.txt b/launcher/CMakeLists.txt
index 08c878d1..2dfc78b5 100644
--- a/launcher/CMakeLists.txt
+++ b/launcher/CMakeLists.txt
@@ -196,36 +196,52 @@ set(ICONS_SOURCES
# Support for Minecraft instances and launch
set(MINECRAFT_SOURCES
# Minecraft support
- minecraft/auth/AccountData.h
minecraft/auth/AccountData.cpp
- minecraft/auth/AccountTask.h
+ minecraft/auth/AccountData.h
+ minecraft/auth/AccountList.cpp
+ minecraft/auth/AccountList.h
minecraft/auth/AccountTask.cpp
- minecraft/auth/AuthSession.h
+ minecraft/auth/AccountTask.h
+ minecraft/auth/AuthRequest.cpp
+ minecraft/auth/AuthRequest.h
minecraft/auth/AuthSession.cpp
- minecraft/auth/AccountList.h
- minecraft/auth/AccountList.cpp
- minecraft/auth/MinecraftAccount.h
+ minecraft/auth/AuthSession.h
+ minecraft/auth/AuthStep.cpp
+ minecraft/auth/AuthStep.h
minecraft/auth/MinecraftAccount.cpp
- minecraft/auth/flows/AuthContext.h
- minecraft/auth/flows/AuthContext.cpp
- minecraft/auth/flows/AuthRequest.h
- minecraft/auth/flows/AuthRequest.cpp
-
- minecraft/auth/flows/MSAInteractive.h
- minecraft/auth/flows/MSAInteractive.cpp
- minecraft/auth/flows/MSASilent.h
- minecraft/auth/flows/MSASilent.cpp
-
- minecraft/auth/flows/MojangLogin.h
- minecraft/auth/flows/MojangLogin.cpp
- minecraft/auth/flows/MojangRefresh.h
- minecraft/auth/flows/MojangRefresh.cpp
-
- minecraft/auth/flows/Yggdrasil.h
- minecraft/auth/flows/Yggdrasil.cpp
-
- minecraft/auth/flows/Parsers.h
- minecraft/auth/flows/Parsers.cpp
+ minecraft/auth/MinecraftAccount.h
+ minecraft/auth/Parsers.cpp
+ minecraft/auth/Parsers.h
+ minecraft/auth/Yggdrasil.cpp
+ minecraft/auth/Yggdrasil.h
+
+ minecraft/auth/flows/AuthFlow.cpp
+ minecraft/auth/flows/AuthFlow.h
+ minecraft/auth/flows/Mojang.cpp
+ minecraft/auth/flows/Mojang.h
+ minecraft/auth/flows/MSA.cpp
+ minecraft/auth/flows/MSA.h
+
+ minecraft/auth/steps/EntitlementsStep.cpp
+ minecraft/auth/steps/EntitlementsStep.h
+ minecraft/auth/steps/GetSkinStep.cpp
+ minecraft/auth/steps/GetSkinStep.h
+ minecraft/auth/steps/LauncherLoginStep.cpp
+ minecraft/auth/steps/LauncherLoginStep.h
+ minecraft/auth/steps/MigrationEligibilityStep.cpp
+ minecraft/auth/steps/MigrationEligibilityStep.h
+ minecraft/auth/steps/MinecraftProfileStep.cpp
+ minecraft/auth/steps/MinecraftProfileStep.h
+ minecraft/auth/steps/MSAStep.cpp
+ minecraft/auth/steps/MSAStep.h
+ minecraft/auth/steps/XboxAuthorizationStep.cpp
+ minecraft/auth/steps/XboxAuthorizationStep.h
+ minecraft/auth/steps/XboxProfileStep.cpp
+ minecraft/auth/steps/XboxProfileStep.h
+ minecraft/auth/steps/XboxUserStep.cpp
+ minecraft/auth/steps/XboxUserStep.h
+ minecraft/auth/steps/YggdrasilStep.cpp
+ minecraft/auth/steps/YggdrasilStep.h
minecraft/gameoptions/GameOptions.h
minecraft/gameoptions/GameOptions.cpp
diff --git a/launcher/LaunchController.cpp b/launcher/LaunchController.cpp
index 8bd5732f..39fec9e6 100644
--- a/launcher/LaunchController.cpp
+++ b/launcher/LaunchController.cpp
@@ -35,6 +35,8 @@ void LaunchController::executeTask()
return;
}
+ JavaCommon::checkJVMArgs(m_instance->settings()->get("JvmArgs").toString(), m_parentWidget);
+
login();
}
@@ -90,8 +92,6 @@ void LaunchController::decideAccount()
void LaunchController::login() {
- JavaCommon::checkJVMArgs(m_instance->settings()->get("JvmArgs").toString(), m_parentWidget);
-
decideAccount();
// if no account is selected, we bail
@@ -113,120 +113,107 @@ void LaunchController::login() {
{
m_session = std::make_shared<AuthSession>();
m_session->wants_online = m_online;
- shared_qobject_ptr<AccountTask> task;
- if(!password.isNull()) {
- task = m_accountToUse->login(m_session, password);
- }
- else {
- task = m_accountToUse->refresh(m_session);
- }
- if (task)
- {
- // We'll need to validate the access token to make sure the account
- // is still logged in.
- ProgressDialog progDialog(m_parentWidget);
- if (m_online)
- {
- progDialog.setSkipButton(true, tr("Play Offline"));
- }
- progDialog.execWithTask(task.get());
- if (!task->wasSuccessful())
- {
- auto failReasonNew = task->failReason();
- if(failReasonNew == "Invalid token." || failReasonNew == "Invalid Signature")
- {
- // account->invalidateClientToken();
- failReason = needLoginAgain;
- }
- else failReason = failReasonNew;
- }
- }
- switch (m_session->status)
- {
- case AuthSession::Undetermined: {
- qCritical() << "Received undetermined session status during login. Bye.";
- tryagain = false;
- emitFailed(tr("Received undetermined session status during login."));
- return;
- }
- case AuthSession::RequiresPassword: {
- // FIXME: this needs to understand MSA
- EditAccountDialog passDialog(failReason, m_parentWidget, EditAccountDialog::PasswordField);
- auto username = m_session->username;
- auto chopN = [](QString toChop, int N) -> QString
- {
- if(toChop.size() > N)
- {
- auto left = toChop.left(N);
- left += QString("\u25CF").repeated(toChop.size() - N);
- return left;
- }
- return toChop;
- };
+ m_accountToUse->fillSession(m_session);
- if(username.contains('@'))
- {
- auto parts = username.split('@');
- auto mailbox = chopN(parts[0],3);
- QString domain = chopN(parts[1], 3);
- username = mailbox + '@' + domain;
- }
- passDialog.setUsername(username);
- if (passDialog.exec() == QDialog::Accepted)
+ switch(m_accountToUse->accountState()) {
+ case AccountState::Offline: {
+ // we ask the user for a player name
+ bool ok = false;
+ QString usedname = m_session->player_name;
+ QString name = QInputDialog::getText(
+ m_parentWidget,
+ tr("Player name"),
+ tr("Choose your offline mode player name."),
+ QLineEdit::Normal,
+ m_session->player_name,
+ &ok
+ );
+ if (!ok)
{
- password = passDialog.password();
+ tryagain = false;
+ break;
}
- else
+ if (name.length())
{
- tryagain = false;
- emitFailed(tr("Received undetermined session status during login."));
+ usedname = name;
}
- break;
+ m_session->MakeOffline(usedname);
+ // offline flavored game from here :3
+ // NOTE: fallthrough is intentional
}
- case AuthSession::RequiresProfileSetup: {
- auto entitlement = m_accountToUse->accountData()->minecraftEntitlement;
- QString errorString;
- if(!entitlement.canPlayMinecraft) {
- errorString = tr("The account does not own Minecraft. You need to purchase the game first to play it.");
- QMessageBox::warning(
- nullptr,
- tr("Missing Minecraft profile"),
- errorString,
- QMessageBox::StandardButton::Ok,
- QMessageBox::StandardButton::Ok
- );
- tryagain = false;
- emitFailed(errorString);
- return;
+ case AccountState::Online: {
+ if(m_accountToUse->ownsMinecraft() && !m_accountToUse->hasProfile()) {
+ auto entitlement = m_accountToUse->accountData()->minecraftEntitlement;
+ QString errorString;
+ if(!entitlement.canPlayMinecraft) {
+ errorString = tr("The account does not own Minecraft. You need to purchase the game first to play it.");
+ QMessageBox::warning(
+ nullptr,
+ tr("Missing Minecraft profile"),
+ errorString,
+ QMessageBox::StandardButton::Ok,
+ QMessageBox::StandardButton::Ok
+ );
+ emitFailed(errorString);
+ return;
+ }
+ // Now handle setting up a profile name here...
+ ProfileSetupDialog dialog(m_accountToUse, m_parentWidget);
+ if (dialog.exec() == QDialog::Accepted)
+ {
+ tryagain = true;
+ continue;
+ }
+ else
+ {
+ emitFailed(tr("Received undetermined session status during login."));
+ return;
+ }
}
- // Now handle setting up a profile name here...
- ProfileSetupDialog dialog(m_accountToUse, m_parentWidget);
- if (dialog.exec() == QDialog::Accepted)
- {
- tryagain = true;
- continue;
+ else {
+ launchInstance();
}
- else
+ return;
+ }
+ case AccountState::Unchecked: {
+ m_accountToUse->refresh();
+ // NOTE: fallthrough intentional
+ }
+ case AccountState::Working: {
+ // refresh is in progress, we need to wait for it to finish to proceed.
+ ProgressDialog progDialog(m_parentWidget);
+ if (m_online)
{
- tryagain = false;
- emitFailed(tr("Received undetermined session status during login."));
- return;
+ progDialog.setSkipButton(true, tr("Play Offline"));
}
+ auto task = m_accountToUse->currentTask();
+ progDialog.execWithTask(task.get());
+ continue;
+ }
+ // FIXME: this is missing - the meaning is that the account is queued for refresh and we should wait for that
+ /*
+ case AccountState::Queued: {
+ return;
}
- case AuthSession::RequiresOAuth: {
- auto errorString = tr("Microsoft account has expired and needs to be logged into manually again.");
+ */
+ case AccountState::Errored: {
+ // This means some sort of soft error that we can fix with a refresh ... so let's refresh.
+ // TODO: implement
+ return;
+ }
+ case AccountState::Expired: {
+ auto errorString = tr("The account has expired and needs to be logged into manually again.");
QMessageBox::warning(
m_parentWidget,
- tr("Microsoft Account refresh failed"),
+ tr("Account refresh failed"),
errorString,
QMessageBox::StandardButton::Ok,
QMessageBox::StandardButton::Ok
);
- tryagain = false;
emitFailed(errorString);
return;
}
- case AuthSession::GoneOrMigrated: {
+ case AccountState::Gone: {
auto errorString = tr("The account no longer exists on the servers. It may have been migrated, in which case please add the new account you migrated this one to.");
QMessageBox::warning(
m_parentWidget,
@@ -235,40 +222,9 @@ void LaunchController::login() {
QMessageBox::StandardButton::Ok,
QMessageBox::StandardButton::Ok
);
- tryagain = false;
emitFailed(errorString);
return;
}
- case AuthSession::PlayableOffline: {
- // we ask the user for a player name
- bool ok = false;
- QString usedname = m_session->player_name;
- QString name = QInputDialog::getText(
- m_parentWidget,
- tr("Player name"),
- tr("Choose your offline mode player name."),
- QLineEdit::Normal,
- m_session->player_name,
- &ok
- );
- if (!ok)
- {
- tryagain = false;
- break;
- }
- if (name.length())
- {
- usedname = name;
- }
- m_session->MakeOffline(usedname);
- // offline flavored game from here :3
- }
- case AuthSession::PlayableOnline:
- {
- launchInstance();
- tryagain = false;
- return;
- }
}
}
emitFailed(tr("Failed to launch."));
@@ -334,14 +290,7 @@ void LaunchController::launchInstance()
online_mode = "offline";
}
- QString auth_server_status;
- if(m_session->auth_server_online) {
- auth_server_status = "online";
- } else {
- auth_server_status = "offline";
- }
-
- m_launcher->prependStep(new TextPrint(m_launcher.get(), "Launched instance in " + online_mode + " mode\nAuthentication server is " + auth_server_status + "\n", MessageLevel::Launcher));
+ m_launcher->prependStep(new TextPrint(m_launcher.get(), "Launched instance in " + online_mode + " mode\n", MessageLevel::Launcher));
// Prepend Version
m_launcher->prependStep(new TextPrint(m_launcher.get(), BuildConfig.LAUNCHER_NAME + " version: " + BuildConfig.printableVersionString() + "\n\n", MessageLevel::Launcher));
diff --git a/launcher/minecraft/auth/AccountData.h b/launcher/minecraft/auth/AccountData.h
index 09cd2c73..fa42747e 100644
--- a/launcher/minecraft/auth/AccountData.h
+++ b/launcher/minecraft/auth/AccountData.h
@@ -41,6 +41,16 @@ enum class AccountType {
Mojang
};
+enum class AccountState {
+ Unchecked,
+ Offline,
+ Working,
+ Online,
+ Errored,
+ Expired,
+ Gone
+};
+
struct AccountData {
QJsonObject saveState() const;
bool resumeStateFromV2(QJsonObject data);
@@ -77,4 +87,9 @@ struct AccountData {
MinecraftProfile minecraftProfile;
MinecraftEntitlement minecraftEntitlement;
Katabasis::Validity validity_ = Katabasis::Validity::None;
+
+ // runtime only information (not saved with the account)
+ QString internalId;
+ QString errorString;
+ AccountState accountState = AccountState::Unchecked;
};
diff --git a/launcher/minecraft/auth/AccountList.cpp b/launcher/minecraft/auth/AccountList.cpp
index d7537345..c44e3e89 100644
--- a/launcher/minecraft/auth/AccountList.cpp
+++ b/launcher/minecraft/auth/AccountList.cpp
@@ -15,6 +15,7 @@
#include "AccountList.h"
#include "AccountData.h"
+#include "AccountTask.h"
#include <QIODevice>
#include <QFile>
@@ -24,6 +25,7 @@
#include <QJsonObject>
#include <QJsonParseError>
#include <QDir>
+#include <QTimer>
#include <QDebug>
@@ -35,7 +37,14 @@ enum AccountListVersion {
MojangMSA = 3
};
-AccountList::AccountList(QObject *parent) : QAbstractListModel(parent) { }
+AccountList::AccountList(QObject *parent) : QAbstractListModel(parent) {
+ m_refreshTimer = new QTimer(this);
+ m_refreshTimer->setSingleShot(true);
+ connect(m_refreshTimer, &QTimer::timeout, this, &AccountList::fillQueue);
+ m_nextTimer = new QTimer(this);
+ m_nextTimer->setSingleShot(true);
+ connect(m_nextTimer, &QTimer::timeout, this, &AccountList::tryNext);
+}
AccountList::~AccountList() noexcept {}
@@ -244,13 +253,29 @@ QVariant AccountList::data(const QModelIndex &index, int role) const
}
case StatusColumn: {
- if(account->isActive()) {
- return tr("Working", "Account status");
- }
- if(account->isExpired()) {
- return tr("Expired", "Account status");
+ switch(account->accountState()) {
+ case AccountState::Unchecked: {
+ return tr("Unchecked", "Account status");
+ }
+ case AccountState::Offline: {
+ return tr("Offline", "Account status");
+ }
+ case AccountState